Object.cpp 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/String.h>
  8. #include <LibJS/Interpreter.h>
  9. #include <LibJS/Runtime/AbstractOperations.h>
  10. #include <LibJS/Runtime/Accessor.h>
  11. #include <LibJS/Runtime/Array.h>
  12. #include <LibJS/Runtime/ECMAScriptFunctionObject.h>
  13. #include <LibJS/Runtime/Error.h>
  14. #include <LibJS/Runtime/GlobalObject.h>
  15. #include <LibJS/Runtime/NativeFunction.h>
  16. #include <LibJS/Runtime/Object.h>
  17. #include <LibJS/Runtime/PropertyDescriptor.h>
  18. #include <LibJS/Runtime/ProxyObject.h>
  19. #include <LibJS/Runtime/Shape.h>
  20. #include <LibJS/Runtime/Value.h>
  21. namespace JS {
  22. // 10.1.12 OrdinaryObjectCreate ( proto [ , additionalInternalSlotsList ] ), https://tc39.es/ecma262/#sec-ordinaryobjectcreate
  23. Object* Object::create(GlobalObject& global_object, Object* prototype)
  24. {
  25. if (!prototype)
  26. return global_object.heap().allocate<Object>(global_object, *global_object.empty_object_shape());
  27. else if (prototype == global_object.object_prototype())
  28. return global_object.heap().allocate<Object>(global_object, *global_object.new_object_shape());
  29. else
  30. return global_object.heap().allocate<Object>(global_object, *prototype);
  31. }
  32. Object::Object(GlobalObjectTag)
  33. {
  34. // This is the global object
  35. m_shape = heap().allocate_without_global_object<Shape>(*this);
  36. }
  37. Object::Object(ConstructWithoutPrototypeTag, GlobalObject& global_object)
  38. {
  39. m_shape = heap().allocate_without_global_object<Shape>(global_object);
  40. }
  41. Object::Object(GlobalObject& global_object, Object* prototype)
  42. {
  43. m_shape = global_object.empty_object_shape();
  44. if (prototype != nullptr)
  45. set_prototype(prototype);
  46. }
  47. Object::Object(Object& prototype)
  48. {
  49. m_shape = prototype.global_object().empty_object_shape();
  50. set_prototype(&prototype);
  51. }
  52. Object::Object(Shape& shape)
  53. : m_shape(&shape)
  54. {
  55. m_storage.resize(shape.property_count());
  56. }
  57. void Object::initialize(GlobalObject&)
  58. {
  59. }
  60. Object::~Object()
  61. {
  62. }
  63. // 7.2 Testing and Comparison Operations, https://tc39.es/ecma262/#sec-testing-and-comparison-operations
  64. // 7.2.5 IsExtensible ( O ), https://tc39.es/ecma262/#sec-isextensible-o
  65. ThrowCompletionOr<bool> Object::is_extensible() const
  66. {
  67. // 1. Return ? O.[[IsExtensible]]().
  68. return internal_is_extensible();
  69. }
  70. // 7.3 Operations on Objects, https://tc39.es/ecma262/#sec-operations-on-objects
  71. // 7.3.2 Get ( O, P ), https://tc39.es/ecma262/#sec-get-o-p
  72. ThrowCompletionOr<Value> Object::get(PropertyKey const& property_key) const
  73. {
  74. // 1. Assert: Type(O) is Object.
  75. // 2. Assert: IsPropertyKey(P) is true.
  76. VERIFY(property_key.is_valid());
  77. // 3. Return ? O.[[Get]](P, O).
  78. return TRY(internal_get(property_key, this));
  79. }
  80. // NOTE: 7.3.3 GetV ( V, P ) is implemented as Value::get().
  81. // 7.3.4 Set ( O, P, V, Throw ), https://tc39.es/ecma262/#sec-set-o-p-v-throw
  82. ThrowCompletionOr<bool> Object::set(PropertyKey const& property_key, Value value, ShouldThrowExceptions throw_exceptions)
  83. {
  84. VERIFY(!value.is_empty());
  85. auto& vm = this->vm();
  86. // 1. Assert: Type(O) is Object.
  87. // 2. Assert: IsPropertyKey(P) is true.
  88. VERIFY(property_key.is_valid());
  89. // 3. Assert: Type(Throw) is Boolean.
  90. // 4. Let success be ? O.[[Set]](P, V, O).
  91. auto success = TRY(internal_set(property_key, value, this));
  92. // 5. If success is false and Throw is true, throw a TypeError exception.
  93. if (!success && throw_exceptions == ShouldThrowExceptions::Yes) {
  94. // FIXME: Improve/contextualize error message
  95. return vm.throw_completion<TypeError>(global_object(), ErrorType::ObjectSetReturnedFalse);
  96. }
  97. // 6. Return success.
  98. return success;
  99. }
  100. // 7.3.5 CreateDataProperty ( O, P, V ), https://tc39.es/ecma262/#sec-createdataproperty
  101. ThrowCompletionOr<bool> Object::create_data_property(PropertyKey const& property_key, Value value)
  102. {
  103. // 1. Assert: Type(O) is Object.
  104. // 2. Assert: IsPropertyKey(P) is true.
  105. VERIFY(property_key.is_valid());
  106. // 3. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }.
  107. auto new_descriptor = PropertyDescriptor {
  108. .value = value,
  109. .writable = true,
  110. .enumerable = true,
  111. .configurable = true,
  112. };
  113. // 4. Return ? O.[[DefineOwnProperty]](P, newDesc).
  114. return internal_define_own_property(property_key, new_descriptor);
  115. }
  116. // 7.3.6 CreateMethodProperty ( O, P, V ), https://tc39.es/ecma262/#sec-createmethodproperty
  117. ThrowCompletionOr<bool> Object::create_method_property(PropertyKey const& property_key, Value value)
  118. {
  119. VERIFY(!value.is_empty());
  120. // 1. Assert: Type(O) is Object.
  121. // 2. Assert: IsPropertyKey(P) is true.
  122. VERIFY(property_key.is_valid());
  123. // 3. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
  124. auto new_descriptor = PropertyDescriptor {
  125. .value = value,
  126. .writable = true,
  127. .enumerable = false,
  128. .configurable = true,
  129. };
  130. // 4. Return ? O.[[DefineOwnProperty]](P, newDesc).
  131. return internal_define_own_property(property_key, new_descriptor);
  132. }
  133. // 7.3.7 CreateDataPropertyOrThrow ( O, P, V ), https://tc39.es/ecma262/#sec-createdatapropertyorthrow
  134. ThrowCompletionOr<bool> Object::create_data_property_or_throw(PropertyKey const& property_key, Value value)
  135. {
  136. VERIFY(!value.is_empty());
  137. auto& vm = this->vm();
  138. // 1. Assert: Type(O) is Object.
  139. // 2. Assert: IsPropertyKey(P) is true.
  140. VERIFY(property_key.is_valid());
  141. // 3. Let success be ? CreateDataProperty(O, P, V).
  142. auto success = TRY(create_data_property(property_key, value));
  143. // 4. If success is false, throw a TypeError exception.
  144. if (!success) {
  145. // FIXME: Improve/contextualize error message
  146. return vm.throw_completion<TypeError>(global_object(), ErrorType::ObjectDefineOwnPropertyReturnedFalse);
  147. }
  148. // 5. Return success.
  149. return success;
  150. }
  151. // 7.3.8 CreateNonEnumerableDataPropertyOrThrow ( O, P, V ), https://tc39.es/ecma262/#sec-createnonenumerabledatapropertyorthrow
  152. ThrowCompletionOr<bool> Object::create_non_enumerable_data_property_or_throw(PropertyKey const& property_key, Value value)
  153. {
  154. VERIFY(!value.is_empty());
  155. VERIFY(property_key.is_valid());
  156. // 1. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
  157. auto new_description = PropertyDescriptor { .value = value, .writable = true, .enumerable = false, .configurable = true };
  158. // 2. Return ? DefinePropertyOrThrow(O, P, newDesc).
  159. return define_property_or_throw(property_key, new_description);
  160. }
  161. // 7.3.9 DefinePropertyOrThrow ( O, P, desc ), https://tc39.es/ecma262/#sec-definepropertyorthrow
  162. ThrowCompletionOr<bool> Object::define_property_or_throw(PropertyKey const& property_key, PropertyDescriptor const& property_descriptor)
  163. {
  164. auto& vm = this->vm();
  165. // 1. Assert: Type(O) is Object.
  166. // 2. Assert: IsPropertyKey(P) is true.
  167. VERIFY(property_key.is_valid());
  168. // 3. Let success be ? O.[[DefineOwnProperty]](P, desc).
  169. auto success = TRY(internal_define_own_property(property_key, property_descriptor));
  170. // 4. If success is false, throw a TypeError exception.
  171. if (!success) {
  172. // FIXME: Improve/contextualize error message
  173. return vm.throw_completion<TypeError>(global_object(), ErrorType::ObjectDefineOwnPropertyReturnedFalse);
  174. }
  175. // 5. Return success.
  176. return success;
  177. }
  178. // 7.3.10 DeletePropertyOrThrow ( O, P ), https://tc39.es/ecma262/#sec-deletepropertyorthrow
  179. ThrowCompletionOr<bool> Object::delete_property_or_throw(PropertyKey const& property_key)
  180. {
  181. auto& vm = this->vm();
  182. // 1. Assert: Type(O) is Object.
  183. // 2. Assert: IsPropertyKey(P) is true.
  184. VERIFY(property_key.is_valid());
  185. // 3. Let success be ? O.[[Delete]](P).
  186. auto success = TRY(internal_delete(property_key));
  187. // 4. If success is false, throw a TypeError exception.
  188. if (!success) {
  189. // FIXME: Improve/contextualize error message
  190. return vm.throw_completion<TypeError>(global_object(), ErrorType::ObjectDeleteReturnedFalse);
  191. }
  192. // 5. Return success.
  193. return success;
  194. }
  195. // 7.3.12 HasProperty ( O, P ), https://tc39.es/ecma262/#sec-hasproperty
  196. ThrowCompletionOr<bool> Object::has_property(PropertyKey const& property_key) const
  197. {
  198. // 1. Assert: Type(O) is Object.
  199. // 2. Assert: IsPropertyKey(P) is true.
  200. VERIFY(property_key.is_valid());
  201. // 3. Return ? O.[[HasProperty]](P).
  202. return internal_has_property(property_key);
  203. }
  204. // 7.3.13 HasOwnProperty ( O, P ), https://tc39.es/ecma262/#sec-hasownproperty
  205. ThrowCompletionOr<bool> Object::has_own_property(PropertyKey const& property_key) const
  206. {
  207. // 1. Assert: Type(O) is Object.
  208. // 2. Assert: IsPropertyKey(P) is true.
  209. VERIFY(property_key.is_valid());
  210. // 3. Let desc be ? O.[[GetOwnProperty]](P).
  211. auto descriptor = TRY(internal_get_own_property(property_key));
  212. // 4. If desc is undefined, return false.
  213. if (!descriptor.has_value())
  214. return false;
  215. // 5. Return true.
  216. return true;
  217. }
  218. // 7.3.16 SetIntegrityLevel ( O, level ), https://tc39.es/ecma262/#sec-setintegritylevel
  219. ThrowCompletionOr<bool> Object::set_integrity_level(IntegrityLevel level)
  220. {
  221. auto& global_object = this->global_object();
  222. // 1. Assert: Type(O) is Object.
  223. // 2. Assert: level is either sealed or frozen.
  224. VERIFY(level == IntegrityLevel::Sealed || level == IntegrityLevel::Frozen);
  225. // 3. Let status be ? O.[[PreventExtensions]]().
  226. auto status = TRY(internal_prevent_extensions());
  227. // 4. If status is false, return false.
  228. if (!status)
  229. return false;
  230. // 5. Let keys be ? O.[[OwnPropertyKeys]]().
  231. auto keys = TRY(internal_own_property_keys());
  232. // 6. If level is sealed, then
  233. if (level == IntegrityLevel::Sealed) {
  234. // a. For each element k of keys, do
  235. for (auto& key : keys) {
  236. auto property_key = MUST(PropertyKey::from_value(global_object, key));
  237. // i. Perform ? DefinePropertyOrThrow(O, k, PropertyDescriptor { [[Configurable]]: false }).
  238. TRY(define_property_or_throw(property_key, { .configurable = false }));
  239. }
  240. }
  241. // 7. Else,
  242. else {
  243. // a. Assert: level is frozen.
  244. // b. For each element k of keys, do
  245. for (auto& key : keys) {
  246. auto property_key = MUST(PropertyKey::from_value(global_object, key));
  247. // i. Let currentDesc be ? O.[[GetOwnProperty]](k).
  248. auto current_descriptor = TRY(internal_get_own_property(property_key));
  249. // ii. If currentDesc is not undefined, then
  250. if (!current_descriptor.has_value())
  251. continue;
  252. PropertyDescriptor descriptor;
  253. // 1. If IsAccessorDescriptor(currentDesc) is true, then
  254. if (current_descriptor->is_accessor_descriptor()) {
  255. // a. Let desc be the PropertyDescriptor { [[Configurable]]: false }.
  256. descriptor = { .configurable = false };
  257. }
  258. // 2. Else,
  259. else {
  260. // a. Let desc be the PropertyDescriptor { [[Configurable]]: false, [[Writable]]: false }.
  261. descriptor = { .writable = false, .configurable = false };
  262. }
  263. // 3. Perform ? DefinePropertyOrThrow(O, k, desc).
  264. TRY(define_property_or_throw(property_key, descriptor));
  265. }
  266. }
  267. // 8. Return true.
  268. return true;
  269. }
  270. // 7.3.17 TestIntegrityLevel ( O, level ), https://tc39.es/ecma262/#sec-testintegritylevel
  271. ThrowCompletionOr<bool> Object::test_integrity_level(IntegrityLevel level) const
  272. {
  273. // 1. Assert: Type(O) is Object.
  274. // 2. Assert: level is either sealed or frozen.
  275. VERIFY(level == IntegrityLevel::Sealed || level == IntegrityLevel::Frozen);
  276. // 3. Let extensible be ? IsExtensible(O).
  277. auto extensible = TRY(is_extensible());
  278. // 4. If extensible is true, return false.
  279. // 5. NOTE: If the object is extensible, none of its properties are examined.
  280. if (extensible)
  281. return false;
  282. // 6. Let keys be ? O.[[OwnPropertyKeys]]().
  283. auto keys = TRY(internal_own_property_keys());
  284. // 7. For each element k of keys, do
  285. for (auto& key : keys) {
  286. auto property_key = MUST(PropertyKey::from_value(global_object(), key));
  287. // a. Let currentDesc be ? O.[[GetOwnProperty]](k).
  288. auto current_descriptor = TRY(internal_get_own_property(property_key));
  289. // b. If currentDesc is not undefined, then
  290. if (!current_descriptor.has_value())
  291. continue;
  292. // i. If currentDesc.[[Configurable]] is true, return false.
  293. if (*current_descriptor->configurable)
  294. return false;
  295. // ii. If level is frozen and IsDataDescriptor(currentDesc) is true, then
  296. if (level == IntegrityLevel::Frozen && current_descriptor->is_data_descriptor()) {
  297. // 1. If currentDesc.[[Writable]] is true, return false.
  298. if (*current_descriptor->writable)
  299. return false;
  300. }
  301. }
  302. // 8. Return true.
  303. return true;
  304. }
  305. // 7.3.24 EnumerableOwnPropertyNames ( O, kind ), https://tc39.es/ecma262/#sec-enumerableownpropertynames
  306. ThrowCompletionOr<MarkedVector<Value>> Object::enumerable_own_property_names(PropertyKind kind) const
  307. {
  308. // NOTE: This has been flattened for readability, so some `else` branches in the
  309. // spec text have been replaced with `continue`s in the loop below.
  310. auto& global_object = this->global_object();
  311. // 1. Assert: Type(O) is Object.
  312. // 2. Let ownKeys be ? O.[[OwnPropertyKeys]]().
  313. auto own_keys = TRY(internal_own_property_keys());
  314. // 3. Let properties be a new empty List.
  315. auto properties = MarkedVector<Value> { heap() };
  316. // 4. For each element key of ownKeys, do
  317. for (auto& key : own_keys) {
  318. // a. If Type(key) is String, then
  319. if (!key.is_string())
  320. continue;
  321. auto property_key = MUST(PropertyKey::from_value(global_object, key));
  322. // i. Let desc be ? O.[[GetOwnProperty]](key).
  323. auto descriptor = TRY(internal_get_own_property(property_key));
  324. // ii. If desc is not undefined and desc.[[Enumerable]] is true, then
  325. if (descriptor.has_value() && *descriptor->enumerable) {
  326. // 1. If kind is key, append key to properties.
  327. if (kind == PropertyKind::Key) {
  328. properties.append(key);
  329. continue;
  330. }
  331. // 2. Else,
  332. // a. Let value be ? Get(O, key).
  333. auto value = TRY(get(property_key));
  334. // b. If kind is value, append value to properties.
  335. if (kind == PropertyKind::Value) {
  336. properties.append(value);
  337. continue;
  338. }
  339. // c. Else,
  340. // i. Assert: kind is key+value.
  341. VERIFY(kind == PropertyKind::KeyAndValue);
  342. // ii. Let entry be ! CreateArrayFromList(« key, value »).
  343. auto entry = Array::create_from(global_object, { key, value });
  344. // iii. Append entry to properties.
  345. properties.append(entry);
  346. }
  347. }
  348. // 5. Return properties.
  349. return { move(properties) };
  350. }
  351. // 7.3.26 CopyDataProperties ( target, source, excludedItems ), https://tc39.es/ecma262/#sec-copydataproperties
  352. ThrowCompletionOr<Object*> Object::copy_data_properties(Value source, HashTable<PropertyKey> const& seen_names, GlobalObject& global_object)
  353. {
  354. if (source.is_nullish())
  355. return this;
  356. auto* from_object = MUST(source.to_object(global_object));
  357. for (auto& next_key_value : TRY(from_object->internal_own_property_keys())) {
  358. auto next_key = MUST(PropertyKey::from_value(global_object, next_key_value));
  359. if (seen_names.contains(next_key))
  360. continue;
  361. auto desc = TRY(from_object->internal_get_own_property(next_key));
  362. if (desc.has_value() && desc->attributes().is_enumerable()) {
  363. auto prop_value = TRY(from_object->get(next_key));
  364. TRY(create_data_property_or_throw(next_key, prop_value));
  365. }
  366. }
  367. return this;
  368. }
  369. // 7.3.27 PrivateElementFind ( O, P ), https://tc39.es/ecma262/#sec-privateelementfind
  370. PrivateElement* Object::private_element_find(PrivateName const& name)
  371. {
  372. if (!m_private_elements)
  373. return nullptr;
  374. auto element = m_private_elements->find_if([&](auto const& element) {
  375. return element.key == name;
  376. });
  377. if (element.is_end())
  378. return nullptr;
  379. return &(*element);
  380. }
  381. // 7.3.28 PrivateFieldAdd ( O, P, value ), https://tc39.es/ecma262/#sec-privatefieldadd
  382. ThrowCompletionOr<void> Object::private_field_add(PrivateName const& name, Value value)
  383. {
  384. if (auto* entry = private_element_find(name); entry)
  385. return vm().throw_completion<TypeError>(global_object(), ErrorType::PrivateFieldAlreadyDeclared, name.description);
  386. if (!m_private_elements)
  387. m_private_elements = make<Vector<PrivateElement>>();
  388. m_private_elements->empend(name, PrivateElement::Kind::Field, value);
  389. return {};
  390. }
  391. // 7.3.29 PrivateMethodOrAccessorAdd ( O, method ), https://tc39.es/ecma262/#sec-privatemethodoraccessoradd
  392. ThrowCompletionOr<void> Object::private_method_or_accessor_add(PrivateElement element)
  393. {
  394. VERIFY(element.kind == PrivateElement::Kind::Method || element.kind == PrivateElement::Kind::Accessor);
  395. if (auto* entry = private_element_find(element.key); entry)
  396. return vm().throw_completion<TypeError>(global_object(), ErrorType::PrivateFieldAlreadyDeclared, element.key.description);
  397. if (!m_private_elements)
  398. m_private_elements = make<Vector<PrivateElement>>();
  399. m_private_elements->append(move(element));
  400. return {};
  401. }
  402. // 7.3.30 PrivateGet ( O, P ), https://tc39.es/ecma262/#sec-privateget
  403. ThrowCompletionOr<Value> Object::private_get(PrivateName const& name)
  404. {
  405. auto* entry = private_element_find(name);
  406. if (!entry)
  407. return vm().throw_completion<TypeError>(global_object(), ErrorType::PrivateFieldDoesNotExistOnObject, name.description);
  408. auto& value = entry->value;
  409. if (entry->kind != PrivateElement::Kind::Accessor)
  410. return value;
  411. VERIFY(value.is_accessor());
  412. auto* getter = value.as_accessor().getter();
  413. if (!getter)
  414. return vm().throw_completion<TypeError>(global_object(), ErrorType::PrivateFieldGetAccessorWithoutGetter, name.description);
  415. // 8. Return ? Call(getter, Receiver).
  416. return TRY(call(global_object(), *getter, this));
  417. }
  418. // 7.3.31 PrivateSet ( O, P, value ), https://tc39.es/ecma262/#sec-privateset
  419. ThrowCompletionOr<void> Object::private_set(PrivateName const& name, Value value)
  420. {
  421. auto* entry = private_element_find(name);
  422. if (!entry)
  423. return vm().throw_completion<TypeError>(global_object(), ErrorType::PrivateFieldDoesNotExistOnObject, name.description);
  424. if (entry->kind == PrivateElement::Kind::Field) {
  425. entry->value = value;
  426. return {};
  427. } else if (entry->kind == PrivateElement::Kind::Method) {
  428. return vm().throw_completion<TypeError>(global_object(), ErrorType::PrivateFieldSetMethod, name.description);
  429. }
  430. VERIFY(entry->kind == PrivateElement::Kind::Accessor);
  431. auto& accessor = entry->value;
  432. VERIFY(accessor.is_accessor());
  433. auto* setter = accessor.as_accessor().setter();
  434. if (!setter)
  435. return vm().throw_completion<TypeError>(global_object(), ErrorType::PrivateFieldSetAccessorWithoutSetter, name.description);
  436. TRY(call(global_object(), *setter, this, value));
  437. return {};
  438. }
  439. // 7.3.32 DefineField ( receiver, fieldRecord ), https://tc39.es/ecma262/#sec-definefield
  440. ThrowCompletionOr<void> Object::define_field(Variant<PropertyKey, PrivateName> name, ECMAScriptFunctionObject* initializer)
  441. {
  442. Value init_value = js_undefined();
  443. if (initializer)
  444. init_value = TRY(call(global_object(), *initializer, this));
  445. if (auto* property_key_ptr = name.get_pointer<PropertyKey>())
  446. TRY(create_data_property_or_throw(*property_key_ptr, init_value));
  447. else
  448. TRY(private_field_add(name.get<PrivateName>(), init_value));
  449. return {};
  450. }
  451. // 10.1 Ordinary Object Internal Methods and Internal Slots, https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots
  452. // 10.1.1 [[GetPrototypeOf]] ( ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getprototypeof
  453. ThrowCompletionOr<Object*> Object::internal_get_prototype_of() const
  454. {
  455. // 1. Return O.[[Prototype]].
  456. return const_cast<Object*>(prototype());
  457. }
  458. // 10.1.2 [[SetPrototypeOf]] ( V ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-setprototypeof-v
  459. ThrowCompletionOr<bool> Object::internal_set_prototype_of(Object* new_prototype)
  460. {
  461. // 1. Assert: Either Type(V) is Object or Type(V) is Null.
  462. // 2. Let current be O.[[Prototype]].
  463. // 3. If SameValue(V, current) is true, return true.
  464. if (prototype() == new_prototype)
  465. return true;
  466. // 4. Let extensible be O.[[Extensible]].
  467. // 5. If extensible is false, return false.
  468. if (!m_is_extensible)
  469. return false;
  470. // 6. Let p be V.
  471. auto* prototype = new_prototype;
  472. // 7. Let done be false.
  473. // 8. Repeat, while done is false,
  474. while (prototype) {
  475. // a. If p is null, set done to true.
  476. // b. Else if SameValue(p, O) is true, return false.
  477. if (prototype == this)
  478. return false;
  479. // c. Else,
  480. // i. If p.[[GetPrototypeOf]] is not the ordinary object internal method defined in 10.1.1, set done to true.
  481. // NOTE: This is a best-effort implementation; we don't have a good way of detecting whether certain virtual
  482. // Object methods have been overridden by a given object, but as ProxyObject is the only one doing that for
  483. // [[SetPrototypeOf]], this check does the trick.
  484. if (is<ProxyObject>(prototype))
  485. break;
  486. // ii. Else, set p to p.[[Prototype]].
  487. prototype = prototype->prototype();
  488. }
  489. // 9. Set O.[[Prototype]] to V.
  490. set_prototype(new_prototype);
  491. // 10. Return true.
  492. return true;
  493. }
  494. // 10.1.3 [[IsExtensible]] ( ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-isextensible
  495. ThrowCompletionOr<bool> Object::internal_is_extensible() const
  496. {
  497. // 1. Return O.[[Extensible]].
  498. return m_is_extensible;
  499. }
  500. // 10.1.4 [[PreventExtensions]] ( ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-preventextensions
  501. ThrowCompletionOr<bool> Object::internal_prevent_extensions()
  502. {
  503. // 1. Set O.[[Extensible]] to false.
  504. m_is_extensible = false;
  505. // 2. Return true.
  506. return true;
  507. }
  508. // 10.1.5 [[GetOwnProperty]] ( P ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getownproperty-p
  509. ThrowCompletionOr<Optional<PropertyDescriptor>> Object::internal_get_own_property(PropertyKey const& property_key) const
  510. {
  511. // 1. Assert: IsPropertyKey(P) is true.
  512. VERIFY(property_key.is_valid());
  513. // 2. If O does not have an own property with key P, return undefined.
  514. auto maybe_storage_entry = storage_get(property_key);
  515. if (!maybe_storage_entry.has_value())
  516. return Optional<PropertyDescriptor> {};
  517. // 3. Let D be a newly created Property Descriptor with no fields.
  518. PropertyDescriptor descriptor;
  519. // 4. Let X be O's own property whose key is P.
  520. auto [value, attributes] = *maybe_storage_entry;
  521. // 5. If X is a data property, then
  522. if (!value.is_accessor()) {
  523. // a. Set D.[[Value]] to the value of X's [[Value]] attribute.
  524. descriptor.value = value.value_or(js_undefined());
  525. // b. Set D.[[Writable]] to the value of X's [[Writable]] attribute.
  526. descriptor.writable = attributes.is_writable();
  527. }
  528. // 6. Else,
  529. else {
  530. // a. Assert: X is an accessor property.
  531. // b. Set D.[[Get]] to the value of X's [[Get]] attribute.
  532. descriptor.get = value.as_accessor().getter();
  533. // c. Set D.[[Set]] to the value of X's [[Set]] attribute.
  534. descriptor.set = value.as_accessor().setter();
  535. }
  536. // 7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute.
  537. descriptor.enumerable = attributes.is_enumerable();
  538. // 8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute.
  539. descriptor.configurable = attributes.is_configurable();
  540. // 9. Return D.
  541. return descriptor;
  542. }
  543. // 10.1.6 [[DefineOwnProperty]] ( P, Desc ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-defineownproperty-p-desc
  544. ThrowCompletionOr<bool> Object::internal_define_own_property(PropertyKey const& property_key, PropertyDescriptor const& property_descriptor)
  545. {
  546. VERIFY(property_key.is_valid());
  547. // 1. Let current be ? O.[[GetOwnProperty]](P).
  548. auto current = TRY(internal_get_own_property(property_key));
  549. // 2. Let extensible be ? IsExtensible(O).
  550. auto extensible = TRY(is_extensible());
  551. // 3. Return ValidateAndApplyPropertyDescriptor(O, P, extensible, Desc, current).
  552. return validate_and_apply_property_descriptor(this, property_key, extensible, property_descriptor, current);
  553. }
  554. // 10.1.7 [[HasProperty]] ( P ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-hasproperty-p
  555. ThrowCompletionOr<bool> Object::internal_has_property(PropertyKey const& property_key) const
  556. {
  557. // 1. Assert: IsPropertyKey(P) is true.
  558. VERIFY(property_key.is_valid());
  559. // 2. Let hasOwn be ? O.[[GetOwnProperty]](P).
  560. auto has_own = TRY(internal_get_own_property(property_key));
  561. // 3. If hasOwn is not undefined, return true.
  562. if (has_own.has_value())
  563. return true;
  564. // 4. Let parent be ? O.[[GetPrototypeOf]]().
  565. auto* parent = TRY(internal_get_prototype_of());
  566. // 5. If parent is not null, then
  567. if (parent) {
  568. // a. Return ? parent.[[HasProperty]](P).
  569. return parent->internal_has_property(property_key);
  570. }
  571. // 6. Return false.
  572. return false;
  573. }
  574. // 10.1.8 [[Get]] ( P, Receiver ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-get-p-receiver
  575. ThrowCompletionOr<Value> Object::internal_get(PropertyKey const& property_key, Value receiver) const
  576. {
  577. VERIFY(!receiver.is_empty());
  578. // 1. Assert: IsPropertyKey(P) is true.
  579. VERIFY(property_key.is_valid());
  580. // 2. Let desc be ? O.[[GetOwnProperty]](P).
  581. auto descriptor = TRY(internal_get_own_property(property_key));
  582. // 3. If desc is undefined, then
  583. if (!descriptor.has_value()) {
  584. // a. Let parent be ? O.[[GetPrototypeOf]]().
  585. auto* parent = TRY(internal_get_prototype_of());
  586. // b. If parent is null, return undefined.
  587. if (!parent)
  588. return js_undefined();
  589. // c. Return ? parent.[[Get]](P, Receiver).
  590. return parent->internal_get(property_key, receiver);
  591. }
  592. // 4. If IsDataDescriptor(desc) is true, return desc.[[Value]].
  593. if (descriptor->is_data_descriptor())
  594. return *descriptor->value;
  595. // 5. Assert: IsAccessorDescriptor(desc) is true.
  596. VERIFY(descriptor->is_accessor_descriptor());
  597. // 6. Let getter be desc.[[Get]].
  598. auto* getter = *descriptor->get;
  599. // 7. If getter is undefined, return undefined.
  600. if (!getter)
  601. return js_undefined();
  602. // 8. Return ? Call(getter, Receiver).
  603. return TRY(call(global_object(), *getter, receiver));
  604. }
  605. // 10.1.9 [[Set]] ( P, V, Receiver ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-set-p-v-receiver
  606. ThrowCompletionOr<bool> Object::internal_set(PropertyKey const& property_key, Value value, Value receiver)
  607. {
  608. VERIFY(!value.is_empty());
  609. VERIFY(!receiver.is_empty());
  610. // 1. Assert: IsPropertyKey(P) is true.
  611. VERIFY(property_key.is_valid());
  612. // 2. Let ownDesc be ? O.[[GetOwnProperty]](P).
  613. auto own_descriptor = TRY(internal_get_own_property(property_key));
  614. // 3. Return OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc).
  615. return ordinary_set_with_own_descriptor(property_key, value, receiver, own_descriptor);
  616. }
  617. // 10.1.9.2 OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ), https://tc39.es/ecma262/#sec-ordinarysetwithowndescriptor
  618. ThrowCompletionOr<bool> Object::ordinary_set_with_own_descriptor(PropertyKey const& property_key, Value value, Value receiver, Optional<PropertyDescriptor> own_descriptor)
  619. {
  620. // 1. Assert: IsPropertyKey(P) is true.
  621. VERIFY(property_key.is_valid());
  622. // 2. If ownDesc is undefined, then
  623. if (!own_descriptor.has_value()) {
  624. // a. Let parent be ? O.[[GetPrototypeOf]]().
  625. auto* parent = TRY(internal_get_prototype_of());
  626. // b. If parent is not null, then
  627. if (parent) {
  628. // i. Return ? parent.[[Set]](P, V, Receiver).
  629. return TRY(parent->internal_set(property_key, value, receiver));
  630. }
  631. // c. Else,
  632. else {
  633. // i. Set ownDesc to the PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }.
  634. own_descriptor = PropertyDescriptor {
  635. .value = js_undefined(),
  636. .writable = true,
  637. .enumerable = true,
  638. .configurable = true,
  639. };
  640. }
  641. }
  642. // 3. If IsDataDescriptor(ownDesc) is true, then
  643. if (own_descriptor->is_data_descriptor()) {
  644. // a. If ownDesc.[[Writable]] is false, return false.
  645. if (!*own_descriptor->writable)
  646. return false;
  647. // b. If Type(Receiver) is not Object, return false.
  648. if (!receiver.is_object())
  649. return false;
  650. // c. Let existingDescriptor be ? Receiver.[[GetOwnProperty]](P).
  651. auto existing_descriptor = TRY(receiver.as_object().internal_get_own_property(property_key));
  652. // d. If existingDescriptor is not undefined, then
  653. if (existing_descriptor.has_value()) {
  654. // i. If IsAccessorDescriptor(existingDescriptor) is true, return false.
  655. if (existing_descriptor->is_accessor_descriptor())
  656. return false;
  657. // ii. If existingDescriptor.[[Writable]] is false, return false.
  658. if (!*existing_descriptor->writable)
  659. return false;
  660. // iii. Let valueDesc be the PropertyDescriptor { [[Value]]: V }.
  661. auto value_descriptor = PropertyDescriptor { .value = value };
  662. // iv. Return ? Receiver.[[DefineOwnProperty]](P, valueDesc).
  663. return TRY(receiver.as_object().internal_define_own_property(property_key, value_descriptor));
  664. }
  665. // e. Else,
  666. else {
  667. // i. Assert: Receiver does not currently have a property P.
  668. VERIFY(!receiver.as_object().storage_has(property_key));
  669. // ii. Return ? CreateDataProperty(Receiver, P, V).
  670. return TRY(receiver.as_object().create_data_property(property_key, value));
  671. }
  672. }
  673. // 4. Assert: IsAccessorDescriptor(ownDesc) is true.
  674. VERIFY(own_descriptor->is_accessor_descriptor());
  675. // 5. Let setter be ownDesc.[[Set]].
  676. auto* setter = *own_descriptor->set;
  677. // 6. If setter is undefined, return false.
  678. if (!setter)
  679. return false;
  680. // 7. Perform ? Call(setter, Receiver, « V »).
  681. (void)TRY(call(global_object(), *setter, receiver, value));
  682. // 8. Return true.
  683. return true;
  684. }
  685. // 10.1.10 [[Delete]] ( P ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-delete-p
  686. ThrowCompletionOr<bool> Object::internal_delete(PropertyKey const& property_key)
  687. {
  688. // 1. Assert: IsPropertyKey(P) is true.
  689. VERIFY(property_key.is_valid());
  690. // 2. Let desc be ? O.[[GetOwnProperty]](P).
  691. auto descriptor = TRY(internal_get_own_property(property_key));
  692. // 3. If desc is undefined, return true.
  693. if (!descriptor.has_value())
  694. return true;
  695. // 4. If desc.[[Configurable]] is true, then
  696. if (*descriptor->configurable) {
  697. // a. Remove the own property with name P from O.
  698. storage_delete(property_key);
  699. // b. Return true.
  700. return true;
  701. }
  702. // 5. Return false.
  703. return false;
  704. }
  705. // 10.1.11 [[OwnPropertyKeys]] ( ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys
  706. ThrowCompletionOr<MarkedVector<Value>> Object::internal_own_property_keys() const
  707. {
  708. auto& vm = this->vm();
  709. // 1. Let keys be a new empty List.
  710. MarkedVector<Value> keys { heap() };
  711. // 2. For each own property key P of O such that P is an array index, in ascending numeric index order, do
  712. for (auto& entry : m_indexed_properties) {
  713. // a. Add P as the last element of keys.
  714. keys.append(js_string(vm, String::number(entry.index())));
  715. }
  716. // 3. For each own property key P of O such that Type(P) is String and P is not an array index, in ascending chronological order of property creation, do
  717. for (auto& it : shape().property_table_ordered()) {
  718. if (it.key.is_string()) {
  719. // a. Add P as the last element of keys.
  720. keys.append(it.key.to_value(vm));
  721. }
  722. }
  723. // 4. For each own property key P of O such that Type(P) is Symbol, in ascending chronological order of property creation, do
  724. for (auto& it : shape().property_table_ordered()) {
  725. if (it.key.is_symbol()) {
  726. // a. Add P as the last element of keys.
  727. keys.append(it.key.to_value(vm));
  728. }
  729. }
  730. // 5. Return keys.
  731. return { move(keys) };
  732. }
  733. // 10.4.7.2 SetImmutablePrototype ( O, V ), https://tc39.es/ecma262/#sec-set-immutable-prototype
  734. ThrowCompletionOr<bool> Object::set_immutable_prototype(Object* prototype)
  735. {
  736. // 1. Assert: Either Type(V) is Object or Type(V) is Null.
  737. // 2. Let current be ? O.[[GetPrototypeOf]]().
  738. auto* current = TRY(internal_get_prototype_of());
  739. // 3. If SameValue(V, current) is true, return true.
  740. if (prototype == current)
  741. return true;
  742. // 4. Return false.
  743. return false;
  744. }
  745. Optional<ValueAndAttributes> Object::storage_get(PropertyKey const& property_key) const
  746. {
  747. VERIFY(property_key.is_valid());
  748. Value value;
  749. PropertyAttributes attributes;
  750. if (property_key.is_number()) {
  751. auto value_and_attributes = m_indexed_properties.get(property_key.as_number());
  752. if (!value_and_attributes.has_value())
  753. return {};
  754. value = value_and_attributes->value;
  755. attributes = value_and_attributes->attributes;
  756. } else {
  757. auto metadata = shape().lookup(property_key.to_string_or_symbol());
  758. if (!metadata.has_value())
  759. return {};
  760. value = m_storage[metadata->offset];
  761. attributes = metadata->attributes;
  762. }
  763. return ValueAndAttributes { .value = value, .attributes = attributes };
  764. }
  765. bool Object::storage_has(PropertyKey const& property_key) const
  766. {
  767. VERIFY(property_key.is_valid());
  768. if (property_key.is_number())
  769. return m_indexed_properties.has_index(property_key.as_number());
  770. return shape().lookup(property_key.to_string_or_symbol()).has_value();
  771. }
  772. void Object::storage_set(PropertyKey const& property_key, ValueAndAttributes const& value_and_attributes)
  773. {
  774. VERIFY(property_key.is_valid());
  775. auto [value, attributes] = value_and_attributes;
  776. if (property_key.is_number()) {
  777. auto index = property_key.as_number();
  778. m_indexed_properties.put(index, value, attributes);
  779. return;
  780. }
  781. auto property_key_string_or_symbol = property_key.to_string_or_symbol();
  782. auto metadata = shape().lookup(property_key_string_or_symbol);
  783. if (!metadata.has_value()) {
  784. if (!m_shape->is_unique() && shape().property_count() > 100) {
  785. // If you add more than 100 properties to an object, let's stop doing
  786. // transitions to avoid filling up the heap with shapes.
  787. ensure_shape_is_unique();
  788. }
  789. if (m_shape->is_unique())
  790. m_shape->add_property_to_unique_shape(property_key_string_or_symbol, attributes);
  791. else
  792. set_shape(*m_shape->create_put_transition(property_key_string_or_symbol, attributes));
  793. m_storage.append(value);
  794. return;
  795. }
  796. if (attributes != metadata->attributes) {
  797. if (m_shape->is_unique())
  798. m_shape->reconfigure_property_in_unique_shape(property_key_string_or_symbol, attributes);
  799. else
  800. set_shape(*m_shape->create_configure_transition(property_key_string_or_symbol, attributes));
  801. }
  802. m_storage[metadata->offset] = value;
  803. }
  804. void Object::storage_delete(PropertyKey const& property_key)
  805. {
  806. VERIFY(property_key.is_valid());
  807. VERIFY(storage_has(property_key));
  808. if (property_key.is_number())
  809. return m_indexed_properties.remove(property_key.as_number());
  810. auto metadata = shape().lookup(property_key.to_string_or_symbol());
  811. VERIFY(metadata.has_value());
  812. ensure_shape_is_unique();
  813. shape().remove_property_from_unique_shape(property_key.to_string_or_symbol(), metadata->offset);
  814. m_storage.remove(metadata->offset);
  815. }
  816. void Object::set_prototype(Object* new_prototype)
  817. {
  818. if (prototype() == new_prototype)
  819. return;
  820. auto& shape = this->shape();
  821. if (shape.is_unique())
  822. shape.set_prototype_without_transition(new_prototype);
  823. else
  824. m_shape = shape.create_prototype_transition(new_prototype);
  825. }
  826. void Object::define_native_accessor(PropertyKey const& property_key, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> getter, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> setter, PropertyAttributes attribute)
  827. {
  828. FunctionObject* getter_function = nullptr;
  829. if (getter)
  830. getter_function = NativeFunction::create(global_object(), move(getter), 0, property_key, {}, {}, "get"sv);
  831. FunctionObject* setter_function = nullptr;
  832. if (setter)
  833. setter_function = NativeFunction::create(global_object(), move(setter), 1, property_key, {}, {}, "set"sv);
  834. return define_direct_accessor(property_key, getter_function, setter_function, attribute);
  835. }
  836. void Object::define_direct_accessor(PropertyKey const& property_key, FunctionObject* getter, FunctionObject* setter, PropertyAttributes attributes)
  837. {
  838. VERIFY(property_key.is_valid());
  839. auto existing_property = storage_get(property_key).value_or({}).value;
  840. auto* accessor = existing_property.is_accessor() ? &existing_property.as_accessor() : nullptr;
  841. if (!accessor) {
  842. accessor = Accessor::create(vm(), getter, setter);
  843. define_direct_property(property_key, accessor, attributes);
  844. } else {
  845. if (getter)
  846. accessor->set_getter(getter);
  847. if (setter)
  848. accessor->set_setter(setter);
  849. }
  850. }
  851. void Object::ensure_shape_is_unique()
  852. {
  853. if (shape().is_unique())
  854. return;
  855. m_shape = m_shape->create_unique_clone();
  856. }
  857. // Simple side-effect free property lookup, following the prototype chain. Non-standard.
  858. Value Object::get_without_side_effects(const PropertyKey& property_key) const
  859. {
  860. auto* object = this;
  861. while (object) {
  862. auto value_and_attributes = object->storage_get(property_key);
  863. if (value_and_attributes.has_value())
  864. return value_and_attributes->value;
  865. object = object->prototype();
  866. }
  867. return {};
  868. }
  869. void Object::define_native_function(PropertyKey const& property_key, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> native_function, i32 length, PropertyAttributes attribute)
  870. {
  871. auto* function = NativeFunction::create(global_object(), move(native_function), length, property_key);
  872. define_direct_property(property_key, function, attribute);
  873. }
  874. // 20.1.2.3.1 ObjectDefineProperties ( O, Properties ), https://tc39.es/ecma262/#sec-objectdefineproperties
  875. ThrowCompletionOr<Object*> Object::define_properties(Value properties)
  876. {
  877. auto& global_object = this->global_object();
  878. // 1. Assert: Type(O) is Object.
  879. // 2. Let props be ? ToObject(Properties).
  880. auto* props = TRY(properties.to_object(global_object));
  881. // 3. Let keys be ? props.[[OwnPropertyKeys]]().
  882. auto keys = TRY(props->internal_own_property_keys());
  883. struct NameAndDescriptor {
  884. PropertyKey name;
  885. PropertyDescriptor descriptor;
  886. };
  887. // 4. Let descriptors be a new empty List.
  888. Vector<NameAndDescriptor> descriptors;
  889. // 5. For each element nextKey of keys, do
  890. for (auto& next_key : keys) {
  891. auto property_key = MUST(PropertyKey::from_value(global_object, next_key));
  892. // a. Let propDesc be ? props.[[GetOwnProperty]](nextKey).
  893. auto property_descriptor = TRY(props->internal_get_own_property(property_key));
  894. // b. If propDesc is not undefined and propDesc.[[Enumerable]] is true, then
  895. if (property_descriptor.has_value() && *property_descriptor->enumerable) {
  896. // i. Let descObj be ? Get(props, nextKey).
  897. auto descriptor_object = TRY(props->get(property_key));
  898. // ii. Let desc be ? ToPropertyDescriptor(descObj).
  899. auto descriptor = TRY(to_property_descriptor(global_object, descriptor_object));
  900. // iii. Append the pair (a two element List) consisting of nextKey and desc to the end of descriptors.
  901. descriptors.append({ property_key, descriptor });
  902. }
  903. }
  904. // 6. For each element pair of descriptors, do
  905. for (auto& [name, descriptor] : descriptors) {
  906. // a. Let P be the first element of pair.
  907. // b. Let desc be the second element of pair.
  908. // c. Perform ? DefinePropertyOrThrow(O, P, desc).
  909. TRY(define_property_or_throw(name, descriptor));
  910. }
  911. // 7. Return O.
  912. return this;
  913. }
  914. void Object::visit_edges(Cell::Visitor& visitor)
  915. {
  916. Cell::visit_edges(visitor);
  917. visitor.visit(m_shape);
  918. for (auto& value : m_storage)
  919. visitor.visit(value);
  920. m_indexed_properties.for_each_value([&visitor](auto& value) {
  921. visitor.visit(value);
  922. });
  923. if (m_private_elements) {
  924. for (auto& private_element : *m_private_elements)
  925. visitor.visit(private_element.value);
  926. }
  927. }
  928. // 7.1.1.1 OrdinaryToPrimitive ( O, hint ), https://tc39.es/ecma262/#sec-ordinarytoprimitive
  929. ThrowCompletionOr<Value> Object::ordinary_to_primitive(Value::PreferredType preferred_type) const
  930. {
  931. VERIFY(preferred_type == Value::PreferredType::String || preferred_type == Value::PreferredType::Number);
  932. auto& vm = this->vm();
  933. AK::Array<PropertyKey, 2> method_names;
  934. // 1. If hint is string, then
  935. if (preferred_type == Value::PreferredType::String) {
  936. // a. Let methodNames be « "toString", "valueOf" ».
  937. method_names = { vm.names.toString, vm.names.valueOf };
  938. } else {
  939. // a. Let methodNames be « "valueOf", "toString" ».
  940. method_names = { vm.names.valueOf, vm.names.toString };
  941. }
  942. // 3. For each element name of methodNames, do
  943. for (auto& method_name : method_names) {
  944. // a. Let method be ? Get(O, name).
  945. auto method = TRY(get(method_name));
  946. // b. If IsCallable(method) is true, then
  947. if (method.is_function()) {
  948. // i. Let result be ? Call(method, O).
  949. auto result = TRY(call(global_object(), method.as_function(), const_cast<Object*>(this)));
  950. // ii. If Type(result) is not Object, return result.
  951. if (!result.is_object())
  952. return result;
  953. }
  954. }
  955. // 4. Throw a TypeError exception.
  956. return vm.throw_completion<TypeError>(global_object(), ErrorType::Convert, "object", preferred_type == Value::PreferredType::String ? "string" : "number");
  957. }
  958. }