ObjectConstructor.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/Function.h>
  8. #include <LibJS/Runtime/Array.h>
  9. #include <LibJS/Runtime/Error.h>
  10. #include <LibJS/Runtime/GlobalObject.h>
  11. #include <LibJS/Runtime/ObjectConstructor.h>
  12. #include <LibJS/Runtime/ProxyObject.h>
  13. #include <LibJS/Runtime/Shape.h>
  14. namespace JS {
  15. ObjectConstructor::ObjectConstructor(GlobalObject& global_object)
  16. : NativeFunction(vm().names.Object, *global_object.function_prototype())
  17. {
  18. }
  19. void ObjectConstructor::initialize(GlobalObject& global_object)
  20. {
  21. auto& vm = this->vm();
  22. NativeFunction::initialize(global_object);
  23. // 20.1.2.19 Object.prototype, https://tc39.es/ecma262/#sec-object.prototype
  24. define_property(vm.names.prototype, global_object.object_prototype(), 0);
  25. define_property(vm.names.length, Value(1), Attribute::Configurable);
  26. u8 attr = Attribute::Writable | Attribute::Configurable;
  27. define_native_function(vm.names.defineProperty, define_property_, 3, attr);
  28. define_native_function(vm.names.defineProperties, define_properties, 2, attr);
  29. define_native_function(vm.names.is, is, 2, attr);
  30. define_native_function(vm.names.getOwnPropertyDescriptor, get_own_property_descriptor, 2, attr);
  31. define_native_function(vm.names.getOwnPropertyNames, get_own_property_names, 1, attr);
  32. define_native_function(vm.names.getOwnPropertySymbols, get_own_property_symbols, 1, attr);
  33. define_native_function(vm.names.getPrototypeOf, get_prototype_of, 1, attr);
  34. define_native_function(vm.names.setPrototypeOf, set_prototype_of, 2, attr);
  35. define_native_function(vm.names.isExtensible, is_extensible, 1, attr);
  36. define_native_function(vm.names.isFrozen, is_frozen, 1, attr);
  37. define_native_function(vm.names.isSealed, is_sealed, 1, attr);
  38. define_native_function(vm.names.preventExtensions, prevent_extensions, 1, attr);
  39. define_native_function(vm.names.freeze, freeze, 1, attr);
  40. define_native_function(vm.names.seal, seal, 1, attr);
  41. define_native_function(vm.names.keys, keys, 1, attr);
  42. define_native_function(vm.names.values, values, 1, attr);
  43. define_native_function(vm.names.entries, entries, 1, attr);
  44. define_native_function(vm.names.create, create, 2, attr);
  45. define_native_function(vm.names.hasOwn, has_own, 2, attr);
  46. define_native_function(vm.names.assign, assign, 2, attr);
  47. }
  48. ObjectConstructor::~ObjectConstructor()
  49. {
  50. }
  51. // 20.1.1.1 Object ( [ value ] ), https://tc39.es/ecma262/#sec-object-value
  52. Value ObjectConstructor::call()
  53. {
  54. auto value = vm().argument(0);
  55. if (value.is_nullish())
  56. return Object::create_empty(global_object());
  57. return value.to_object(global_object());
  58. }
  59. // 20.1.1.1 Object ( [ value ] ), https://tc39.es/ecma262/#sec-object-value
  60. Value ObjectConstructor::construct(Function&)
  61. {
  62. return call();
  63. }
  64. // 20.1.2.10 Object.getOwnPropertyNames ( O ), https://tc39.es/ecma262/#sec-object.getownpropertynames
  65. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_names)
  66. {
  67. auto* object = vm.argument(0).to_object(global_object);
  68. if (vm.exception())
  69. return {};
  70. return Array::create_from(global_object, object->get_own_properties(PropertyKind::Key, false, GetOwnPropertyReturnType::StringOnly));
  71. }
  72. // 20.1.2.11 Object.getOwnPropertySymbols ( O ), https://tc39.es/ecma262/#sec-object.getownpropertysymbols
  73. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_symbols)
  74. {
  75. auto* object = vm.argument(0).to_object(global_object);
  76. if (vm.exception())
  77. return {};
  78. return Array::create_from(global_object, object->get_own_properties(PropertyKind::Key, false, GetOwnPropertyReturnType::SymbolOnly));
  79. }
  80. // 20.1.2.12 Object.getPrototypeOf ( O ), https://tc39.es/ecma262/#sec-object.getprototypeof
  81. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_prototype_of)
  82. {
  83. auto* object = vm.argument(0).to_object(global_object);
  84. if (vm.exception())
  85. return {};
  86. return object->prototype();
  87. }
  88. // 20.1.2.21 Object.setPrototypeOf ( O, proto ), https://tc39.es/ecma262/#sec-object.setprototypeof
  89. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::set_prototype_of)
  90. {
  91. auto* object = vm.argument(0).to_object(global_object);
  92. if (vm.exception())
  93. return {};
  94. auto prototype_value = vm.argument(1);
  95. Object* prototype;
  96. if (prototype_value.is_null()) {
  97. prototype = nullptr;
  98. } else if (prototype_value.is_object()) {
  99. prototype = &prototype_value.as_object();
  100. } else {
  101. vm.throw_exception<TypeError>(global_object, ErrorType::ObjectPrototypeWrongType);
  102. return {};
  103. }
  104. if (!object->set_prototype(prototype)) {
  105. if (!vm.exception())
  106. vm.throw_exception<TypeError>(global_object, ErrorType::ObjectSetPrototypeOfReturnedFalse);
  107. return {};
  108. }
  109. return object;
  110. }
  111. // 20.1.2.14 Object.isExtensible ( O ), https://tc39.es/ecma262/#sec-object.isextensible
  112. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::is_extensible)
  113. {
  114. auto argument = vm.argument(0);
  115. if (!argument.is_object())
  116. return Value(false);
  117. return Value(argument.as_object().is_extensible());
  118. }
  119. // 20.1.2.15 Object.isFrozen ( O ), https://tc39.es/ecma262/#sec-object.isfrozen
  120. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::is_frozen)
  121. {
  122. auto argument = vm.argument(0);
  123. if (!argument.is_object())
  124. return Value(true);
  125. return Value(argument.as_object().test_integrity_level(Object::IntegrityLevel::Frozen));
  126. }
  127. // 20.1.2.16 Object.isSealed ( O ), https://tc39.es/ecma262/#sec-object.issealed
  128. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::is_sealed)
  129. {
  130. auto argument = vm.argument(0);
  131. if (!argument.is_object())
  132. return Value(true);
  133. return Value(argument.as_object().test_integrity_level(Object::IntegrityLevel::Sealed));
  134. }
  135. // 20.1.2.18 Object.preventExtensions ( O ), https://tc39.es/ecma262/#sec-object.preventextensions
  136. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::prevent_extensions)
  137. {
  138. auto argument = vm.argument(0);
  139. if (!argument.is_object())
  140. return argument;
  141. auto status = argument.as_object().prevent_extensions();
  142. if (vm.exception())
  143. return {};
  144. if (!status) {
  145. vm.throw_exception<TypeError>(global_object, ErrorType::ObjectPreventExtensionsReturnedFalse);
  146. return {};
  147. }
  148. return argument;
  149. }
  150. // 20.1.2.6 Object.freeze ( O ), https://tc39.es/ecma262/#sec-object.freeze
  151. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::freeze)
  152. {
  153. auto argument = vm.argument(0);
  154. if (!argument.is_object())
  155. return argument;
  156. auto status = argument.as_object().set_integrity_level(Object::IntegrityLevel::Frozen);
  157. if (vm.exception())
  158. return {};
  159. if (!status) {
  160. vm.throw_exception<TypeError>(global_object, ErrorType::ObjectFreezeFailed);
  161. return {};
  162. }
  163. return argument;
  164. }
  165. // 20.1.2.20 Object.seal ( O ), https://tc39.es/ecma262/#sec-object.seal
  166. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::seal)
  167. {
  168. auto argument = vm.argument(0);
  169. if (!argument.is_object())
  170. return argument;
  171. auto status = argument.as_object().set_integrity_level(Object::IntegrityLevel::Sealed);
  172. if (vm.exception())
  173. return {};
  174. if (!status) {
  175. vm.throw_exception<TypeError>(global_object, ErrorType::ObjectSealFailed);
  176. return {};
  177. }
  178. return argument;
  179. }
  180. // 20.1.2.8 Object.getOwnPropertyDescriptor ( O, P ), https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
  181. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_descriptor)
  182. {
  183. auto* object = vm.argument(0).to_object(global_object);
  184. if (vm.exception())
  185. return {};
  186. auto property_key = vm.argument(1).to_property_key(global_object);
  187. if (vm.exception())
  188. return {};
  189. return object->get_own_property_descriptor_object(property_key);
  190. }
  191. // 20.1.2.4 Object.defineProperty ( O, P, Attributes ), https://tc39.es/ecma262/#sec-object.defineproperty
  192. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::define_property_)
  193. {
  194. if (!vm.argument(0).is_object()) {
  195. vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, "Object argument");
  196. return {};
  197. }
  198. auto property_key = vm.argument(1).to_property_key(global_object);
  199. if (vm.exception())
  200. return {};
  201. if (!vm.argument(2).is_object()) {
  202. vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, "Descriptor argument");
  203. return {};
  204. }
  205. auto& object = vm.argument(0).as_object();
  206. auto& descriptor = vm.argument(2).as_object();
  207. if (!object.define_property(property_key, descriptor)) {
  208. if (!vm.exception()) {
  209. if (AK::is<ProxyObject>(object)) {
  210. vm.throw_exception<TypeError>(global_object, ErrorType::ObjectDefinePropertyReturnedFalse);
  211. } else {
  212. vm.throw_exception<TypeError>(global_object, ErrorType::NonExtensibleDefine, property_key.to_display_string());
  213. }
  214. }
  215. return {};
  216. }
  217. return &object;
  218. }
  219. // 20.1.2.3 Object.defineProperties ( O, Properties ), https://tc39.es/ecma262/#sec-object.defineproperties
  220. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::define_properties)
  221. {
  222. if (!vm.argument(0).is_object()) {
  223. vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, "Object argument");
  224. return {};
  225. }
  226. auto& object = vm.argument(0).as_object();
  227. auto properties = vm.argument(1);
  228. object.define_properties(properties);
  229. if (vm.exception())
  230. return {};
  231. return &object;
  232. }
  233. // 20.1.2.13 Object.is ( value1, value2 ), https://tc39.es/ecma262/#sec-object.is
  234. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::is)
  235. {
  236. return Value(same_value(vm.argument(0), vm.argument(1)));
  237. }
  238. // 20.1.2.17 Object.keys ( O ), https://tc39.es/ecma262/#sec-object.keys
  239. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::keys)
  240. {
  241. auto* obj_arg = vm.argument(0).to_object(global_object);
  242. if (vm.exception())
  243. return {};
  244. return Array::create_from(global_object, obj_arg->get_enumerable_own_property_names(PropertyKind::Key));
  245. }
  246. // 20.1.2.22 Object.values ( O ), https://tc39.es/ecma262/#sec-object.values
  247. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::values)
  248. {
  249. auto* obj_arg = vm.argument(0).to_object(global_object);
  250. if (vm.exception())
  251. return {};
  252. return Array::create_from(global_object, obj_arg->get_enumerable_own_property_names(PropertyKind::Value));
  253. }
  254. // 20.1.2.5 Object.entries ( O ), https://tc39.es/ecma262/#sec-object.entries
  255. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::entries)
  256. {
  257. auto* obj_arg = vm.argument(0).to_object(global_object);
  258. if (vm.exception())
  259. return {};
  260. return Array::create_from(global_object, obj_arg->get_enumerable_own_property_names(PropertyKind::KeyAndValue));
  261. }
  262. // 20.1.2.2 Object.create ( O, Properties ), https://tc39.es/ecma262/#sec-object.create
  263. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::create)
  264. {
  265. auto prototype_value = vm.argument(0);
  266. auto properties = vm.argument(1);
  267. Object* prototype;
  268. if (prototype_value.is_null()) {
  269. prototype = nullptr;
  270. } else if (prototype_value.is_object()) {
  271. prototype = &prototype_value.as_object();
  272. } else {
  273. vm.throw_exception<TypeError>(global_object, ErrorType::ObjectPrototypeWrongType);
  274. return {};
  275. }
  276. auto* object = Object::create_empty(global_object);
  277. object->set_prototype(prototype);
  278. if (!properties.is_undefined()) {
  279. object->define_properties(properties);
  280. if (vm.exception())
  281. return {};
  282. }
  283. return object;
  284. }
  285. // 1 Object.hasOwn ( O, P ), https://tc39.es/proposal-accessible-object-hasownproperty/#sec-object.hasown
  286. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::has_own)
  287. {
  288. auto* object = vm.argument(0).to_object(global_object);
  289. if (vm.exception())
  290. return {};
  291. auto property_key = vm.argument(1).to_property_key(global_object);
  292. if (vm.exception())
  293. return {};
  294. return Value(object->has_own_property(property_key));
  295. }
  296. // 20.1.2.1 Object.assign ( target, ...sources ), https://tc39.es/ecma262/#sec-object.assign
  297. JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::assign)
  298. {
  299. auto* to = vm.argument(0).to_object(global_object);
  300. if (vm.exception())
  301. return {};
  302. if (vm.argument_count() == 1)
  303. return to;
  304. for (size_t i = 1; i < vm.argument_count(); ++i) {
  305. auto next_source = vm.argument(i);
  306. if (next_source.is_nullish())
  307. continue;
  308. auto from = next_source.to_object(global_object);
  309. VERIFY(!vm.exception());
  310. auto keys = from->get_own_properties(PropertyKind::Key);
  311. if (vm.exception())
  312. return {};
  313. for (auto& key : keys) {
  314. auto property_name = PropertyName::from_value(global_object, key);
  315. auto property_descriptor = from->get_own_property_descriptor(property_name);
  316. if (!property_descriptor.has_value() || !property_descriptor->attributes.is_enumerable())
  317. continue;
  318. auto value = from->get(property_name);
  319. if (vm.exception())
  320. return {};
  321. to->put(property_name, value);
  322. if (vm.exception())
  323. return {};
  324. }
  325. }
  326. return to;
  327. }
  328. }