Object.cpp 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491
  1. /*
  2. * Copyright (c) 2020-2024, Andreas Kling <andreas@ladybird.org>
  3. * Copyright (c) 2020-2023, Linus Groh <linusg@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/ByteString.h>
  8. #include <AK/TypeCasts.h>
  9. #include <LibJS/Runtime/AbstractOperations.h>
  10. #include <LibJS/Runtime/Accessor.h>
  11. #include <LibJS/Runtime/Array.h>
  12. #include <LibJS/Runtime/ClassFieldDefinition.h>
  13. #include <LibJS/Runtime/ECMAScriptFunctionObject.h>
  14. #include <LibJS/Runtime/Error.h>
  15. #include <LibJS/Runtime/GlobalObject.h>
  16. #include <LibJS/Runtime/NativeFunction.h>
  17. #include <LibJS/Runtime/Object.h>
  18. #include <LibJS/Runtime/PropertyDescriptor.h>
  19. #include <LibJS/Runtime/ProxyObject.h>
  20. #include <LibJS/Runtime/Shape.h>
  21. #include <LibJS/Runtime/Value.h>
  22. namespace JS {
  23. JS_DEFINE_ALLOCATOR(Object);
  24. static HashMap<GCPtr<Object const>, HashMap<DeprecatedFlyString, Object::IntrinsicAccessor>> s_intrinsics;
  25. // 10.1.12 OrdinaryObjectCreate ( proto [ , additionalInternalSlotsList ] ), https://tc39.es/ecma262/#sec-ordinaryobjectcreate
  26. NonnullGCPtr<Object> Object::create(Realm& realm, Object* prototype)
  27. {
  28. if (!prototype)
  29. return realm.heap().allocate<Object>(realm, realm.intrinsics().empty_object_shape());
  30. if (prototype == realm.intrinsics().object_prototype())
  31. return realm.heap().allocate<Object>(realm, realm.intrinsics().new_object_shape());
  32. return realm.heap().allocate<Object>(realm, ConstructWithPrototypeTag::Tag, *prototype);
  33. }
  34. NonnullGCPtr<Object> Object::create_prototype(Realm& realm, Object* prototype)
  35. {
  36. auto shape = realm.heap().allocate_without_realm<Shape>(realm);
  37. if (prototype)
  38. shape->set_prototype_without_transition(prototype);
  39. return realm.heap().allocate<Object>(realm, shape);
  40. }
  41. NonnullGCPtr<Object> Object::create_with_premade_shape(Shape& shape)
  42. {
  43. return shape.heap().allocate<Object>(shape.realm(), shape);
  44. }
  45. Object::Object(GlobalObjectTag, Realm& realm, MayInterfereWithIndexedPropertyAccess may_interfere_with_indexed_property_access)
  46. : m_may_interfere_with_indexed_property_access(may_interfere_with_indexed_property_access == MayInterfereWithIndexedPropertyAccess::Yes)
  47. {
  48. // This is the global object
  49. m_shape = heap().allocate_without_realm<Shape>(realm);
  50. }
  51. Object::Object(ConstructWithoutPrototypeTag, Realm& realm, MayInterfereWithIndexedPropertyAccess may_interfere_with_indexed_property_access)
  52. : m_may_interfere_with_indexed_property_access(may_interfere_with_indexed_property_access == MayInterfereWithIndexedPropertyAccess::Yes)
  53. {
  54. m_shape = heap().allocate_without_realm<Shape>(realm);
  55. }
  56. Object::Object(Realm& realm, Object* prototype, MayInterfereWithIndexedPropertyAccess may_interfere_with_indexed_property_access)
  57. : m_may_interfere_with_indexed_property_access(may_interfere_with_indexed_property_access == MayInterfereWithIndexedPropertyAccess::Yes)
  58. {
  59. m_shape = realm.intrinsics().empty_object_shape();
  60. VERIFY(m_shape);
  61. if (prototype != nullptr)
  62. set_prototype(prototype);
  63. }
  64. Object::Object(ConstructWithPrototypeTag, Object& prototype, MayInterfereWithIndexedPropertyAccess may_interfere_with_indexed_property_access)
  65. : m_may_interfere_with_indexed_property_access(may_interfere_with_indexed_property_access == MayInterfereWithIndexedPropertyAccess::Yes)
  66. {
  67. m_shape = prototype.shape().realm().intrinsics().empty_object_shape();
  68. VERIFY(m_shape);
  69. set_prototype(&prototype);
  70. }
  71. Object::Object(Shape& shape, MayInterfereWithIndexedPropertyAccess may_interfere_with_indexed_property_access)
  72. : m_may_interfere_with_indexed_property_access(may_interfere_with_indexed_property_access == MayInterfereWithIndexedPropertyAccess::Yes)
  73. , m_shape(&shape)
  74. {
  75. m_storage.resize(shape.property_count());
  76. }
  77. Object::~Object()
  78. {
  79. if (m_has_intrinsic_accessors)
  80. s_intrinsics.remove(this);
  81. }
  82. void Object::initialize(Realm&)
  83. {
  84. }
  85. // 7.2 Testing and Comparison Operations, https://tc39.es/ecma262/#sec-testing-and-comparison-operations
  86. // 7.2.5 IsExtensible ( O ), https://tc39.es/ecma262/#sec-isextensible-o
  87. ThrowCompletionOr<bool> Object::is_extensible() const
  88. {
  89. // 1. Return ? O.[[IsExtensible]]().
  90. return internal_is_extensible();
  91. }
  92. // 7.3 Operations on Objects, https://tc39.es/ecma262/#sec-operations-on-objects
  93. // 7.3.2 Get ( O, P ), https://tc39.es/ecma262/#sec-get-o-p
  94. ThrowCompletionOr<Value> Object::get(PropertyKey const& property_key) const
  95. {
  96. VERIFY(property_key.is_valid());
  97. // 1. Return ? O.[[Get]](P, O).
  98. return TRY(internal_get(property_key, this));
  99. }
  100. // NOTE: 7.3.3 GetV ( V, P ) is implemented as Value::get().
  101. // 7.3.4 Set ( O, P, V, Throw ), https://tc39.es/ecma262/#sec-set-o-p-v-throw
  102. ThrowCompletionOr<void> Object::set(PropertyKey const& property_key, Value value, ShouldThrowExceptions throw_exceptions)
  103. {
  104. auto& vm = this->vm();
  105. VERIFY(property_key.is_valid());
  106. VERIFY(!value.is_empty());
  107. // 1. Let success be ? O.[[Set]](P, V, O).
  108. auto success = TRY(internal_set(property_key, value, this));
  109. // 2. If success is false and Throw is true, throw a TypeError exception.
  110. if (!success && throw_exceptions == ShouldThrowExceptions::Yes) {
  111. // FIXME: Improve/contextualize error message
  112. return vm.throw_completion<TypeError>(ErrorType::ObjectSetReturnedFalse);
  113. }
  114. // 3. Return unused.
  115. return {};
  116. }
  117. // 7.3.5 CreateDataProperty ( O, P, V ), https://tc39.es/ecma262/#sec-createdataproperty
  118. ThrowCompletionOr<bool> Object::create_data_property(PropertyKey const& property_key, Value value)
  119. {
  120. VERIFY(property_key.is_valid());
  121. // 1. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }.
  122. auto new_descriptor = PropertyDescriptor {
  123. .value = value,
  124. .writable = true,
  125. .enumerable = true,
  126. .configurable = true,
  127. };
  128. // 2. Return ? O.[[DefineOwnProperty]](P, newDesc).
  129. return internal_define_own_property(property_key, new_descriptor);
  130. }
  131. // 7.3.6 CreateMethodProperty ( O, P, V ), https://tc39.es/ecma262/#sec-createmethodproperty
  132. void Object::create_method_property(PropertyKey const& property_key, Value value)
  133. {
  134. VERIFY(property_key.is_valid());
  135. VERIFY(!value.is_empty());
  136. // 1. Assert: O is an ordinary, extensible object with no non-configurable properties.
  137. // 2. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
  138. auto new_descriptor = PropertyDescriptor {
  139. .value = value,
  140. .writable = true,
  141. .enumerable = false,
  142. .configurable = true,
  143. };
  144. // 3. Perform ! O.[[DefineOwnProperty]](P, newDesc).
  145. MUST(internal_define_own_property(property_key, new_descriptor));
  146. // 4. Return unused.
  147. }
  148. // 7.3.7 CreateDataPropertyOrThrow ( O, P, V ), https://tc39.es/ecma262/#sec-createdatapropertyorthrow
  149. ThrowCompletionOr<bool> Object::create_data_property_or_throw(PropertyKey const& property_key, Value value)
  150. {
  151. auto& vm = this->vm();
  152. VERIFY(property_key.is_valid());
  153. VERIFY(!value.is_empty());
  154. // 1. Let success be ? CreateDataProperty(O, P, V).
  155. auto success = TRY(create_data_property(property_key, value));
  156. // 2. If success is false, throw a TypeError exception.
  157. if (!success) {
  158. // FIXME: Improve/contextualize error message
  159. return vm.throw_completion<TypeError>(ErrorType::ObjectDefineOwnPropertyReturnedFalse);
  160. }
  161. // 3. Return success.
  162. return success;
  163. }
  164. // 7.3.8 CreateNonEnumerableDataPropertyOrThrow ( O, P, V ), https://tc39.es/ecma262/#sec-createnonenumerabledatapropertyorthrow
  165. void Object::create_non_enumerable_data_property_or_throw(PropertyKey const& property_key, Value value)
  166. {
  167. VERIFY(property_key.is_valid());
  168. VERIFY(!value.is_empty());
  169. // 1. Assert: O is an ordinary, extensible object with no non-configurable properties.
  170. // 2. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
  171. auto new_description = PropertyDescriptor { .value = value, .writable = true, .enumerable = false, .configurable = true };
  172. // 3. Perform ! DefinePropertyOrThrow(O, P, newDesc).
  173. MUST(define_property_or_throw(property_key, new_description));
  174. // 4. Return unused.
  175. }
  176. // 7.3.9 DefinePropertyOrThrow ( O, P, desc ), https://tc39.es/ecma262/#sec-definepropertyorthrow
  177. ThrowCompletionOr<void> Object::define_property_or_throw(PropertyKey const& property_key, PropertyDescriptor const& property_descriptor)
  178. {
  179. auto& vm = this->vm();
  180. VERIFY(property_key.is_valid());
  181. // 1. Let success be ? O.[[DefineOwnProperty]](P, desc).
  182. auto success = TRY(internal_define_own_property(property_key, property_descriptor));
  183. // 2. If success is false, throw a TypeError exception.
  184. if (!success) {
  185. // FIXME: Improve/contextualize error message
  186. return vm.throw_completion<TypeError>(ErrorType::ObjectDefineOwnPropertyReturnedFalse);
  187. }
  188. // 3. Return unused.
  189. return {};
  190. }
  191. // 7.3.10 DeletePropertyOrThrow ( O, P ), https://tc39.es/ecma262/#sec-deletepropertyorthrow
  192. ThrowCompletionOr<void> Object::delete_property_or_throw(PropertyKey const& property_key)
  193. {
  194. auto& vm = this->vm();
  195. VERIFY(property_key.is_valid());
  196. // 1. Let success be ? O.[[Delete]](P).
  197. auto success = TRY(internal_delete(property_key));
  198. // 2. If success is false, throw a TypeError exception.
  199. if (!success) {
  200. // FIXME: Improve/contextualize error message
  201. return vm.throw_completion<TypeError>(ErrorType::ObjectDeleteReturnedFalse);
  202. }
  203. // 3. Return unused.
  204. return {};
  205. }
  206. // 7.3.12 HasProperty ( O, P ), https://tc39.es/ecma262/#sec-hasproperty
  207. ThrowCompletionOr<bool> Object::has_property(PropertyKey const& property_key) const
  208. {
  209. VERIFY(property_key.is_valid());
  210. // 1. Return ? O.[[HasProperty]](P).
  211. return internal_has_property(property_key);
  212. }
  213. // 7.3.13 HasOwnProperty ( O, P ), https://tc39.es/ecma262/#sec-hasownproperty
  214. ThrowCompletionOr<bool> Object::has_own_property(PropertyKey const& property_key) const
  215. {
  216. VERIFY(property_key.is_valid());
  217. // 1. Let desc be ? O.[[GetOwnProperty]](P).
  218. auto descriptor = TRY(internal_get_own_property(property_key));
  219. // 2. If desc is undefined, return false.
  220. if (!descriptor.has_value())
  221. return false;
  222. // 3. Return true.
  223. return true;
  224. }
  225. // 7.3.16 SetIntegrityLevel ( O, level ), https://tc39.es/ecma262/#sec-setintegritylevel
  226. ThrowCompletionOr<bool> Object::set_integrity_level(IntegrityLevel level)
  227. {
  228. auto& vm = this->vm();
  229. // 1. Let status be ? O.[[PreventExtensions]]().
  230. auto status = TRY(internal_prevent_extensions());
  231. // 2. If status is false, return false.
  232. if (!status)
  233. return false;
  234. // 3. Let keys be ? O.[[OwnPropertyKeys]]().
  235. auto keys = TRY(internal_own_property_keys());
  236. // 4. If level is sealed, then
  237. if (level == IntegrityLevel::Sealed) {
  238. // a. For each element k of keys, do
  239. for (auto& key : keys) {
  240. auto property_key = MUST(PropertyKey::from_value(vm, key));
  241. // i. Perform ? DefinePropertyOrThrow(O, k, PropertyDescriptor { [[Configurable]]: false }).
  242. TRY(define_property_or_throw(property_key, { .configurable = false }));
  243. }
  244. }
  245. // 5. Else,
  246. else {
  247. // a. Assert: level is frozen.
  248. // b. For each element k of keys, do
  249. for (auto& key : keys) {
  250. auto property_key = MUST(PropertyKey::from_value(vm, key));
  251. // i. Let currentDesc be ? O.[[GetOwnProperty]](k).
  252. auto current_descriptor = TRY(internal_get_own_property(property_key));
  253. // ii. If currentDesc is not undefined, then
  254. if (!current_descriptor.has_value())
  255. continue;
  256. PropertyDescriptor descriptor;
  257. // 1. If IsAccessorDescriptor(currentDesc) is true, then
  258. if (current_descriptor->is_accessor_descriptor()) {
  259. // a. Let desc be the PropertyDescriptor { [[Configurable]]: false }.
  260. descriptor = { .configurable = false };
  261. }
  262. // 2. Else,
  263. else {
  264. // a. Let desc be the PropertyDescriptor { [[Configurable]]: false, [[Writable]]: false }.
  265. descriptor = { .writable = false, .configurable = false };
  266. }
  267. // 3. Perform ? DefinePropertyOrThrow(O, k, desc).
  268. TRY(define_property_or_throw(property_key, descriptor));
  269. }
  270. }
  271. // 6. Return true.
  272. return true;
  273. }
  274. // 7.3.17 TestIntegrityLevel ( O, level ), https://tc39.es/ecma262/#sec-testintegritylevel
  275. ThrowCompletionOr<bool> Object::test_integrity_level(IntegrityLevel level) const
  276. {
  277. auto& vm = this->vm();
  278. // 1. Let extensible be ? IsExtensible(O).
  279. auto extensible = TRY(is_extensible());
  280. // 2. If extensible is true, return false.
  281. // 3. NOTE: If the object is extensible, none of its properties are examined.
  282. if (extensible)
  283. return false;
  284. // 4. Let keys be ? O.[[OwnPropertyKeys]]().
  285. auto keys = TRY(internal_own_property_keys());
  286. // 5. For each element k of keys, do
  287. for (auto& key : keys) {
  288. auto property_key = MUST(PropertyKey::from_value(vm, key));
  289. // a. Let currentDesc be ? O.[[GetOwnProperty]](k).
  290. auto current_descriptor = TRY(internal_get_own_property(property_key));
  291. // b. If currentDesc is not undefined, then
  292. if (!current_descriptor.has_value())
  293. continue;
  294. // i. If currentDesc.[[Configurable]] is true, return false.
  295. if (*current_descriptor->configurable)
  296. return false;
  297. // ii. If level is frozen and IsDataDescriptor(currentDesc) is true, then
  298. if (level == IntegrityLevel::Frozen && current_descriptor->is_data_descriptor()) {
  299. // 1. If currentDesc.[[Writable]] is true, return false.
  300. if (*current_descriptor->writable)
  301. return false;
  302. }
  303. }
  304. // 6. Return true.
  305. return true;
  306. }
  307. // 7.3.24 EnumerableOwnPropertyNames ( O, kind ), https://tc39.es/ecma262/#sec-enumerableownpropertynames
  308. ThrowCompletionOr<MarkedVector<Value>> Object::enumerable_own_property_names(PropertyKind kind) const
  309. {
  310. // NOTE: This has been flattened for readability, so some `else` branches in the
  311. // spec text have been replaced with `continue`s in the loop below.
  312. auto& vm = this->vm();
  313. auto& realm = *vm.current_realm();
  314. // 1. Let ownKeys be ? O.[[OwnPropertyKeys]]().
  315. auto own_keys = TRY(internal_own_property_keys());
  316. // 2. Let properties be a new empty List.
  317. auto properties = MarkedVector<Value> { heap() };
  318. // 3. For each element key of ownKeys, do
  319. for (auto& key : own_keys) {
  320. // a. If Type(key) is String, then
  321. if (!key.is_string())
  322. continue;
  323. auto property_key = MUST(PropertyKey::from_value(vm, key));
  324. // i. Let desc be ? O.[[GetOwnProperty]](key).
  325. auto descriptor = TRY(internal_get_own_property(property_key));
  326. // ii. If desc is not undefined and desc.[[Enumerable]] is true, then
  327. if (descriptor.has_value() && *descriptor->enumerable) {
  328. // 1. If kind is key, append key to properties.
  329. if (kind == PropertyKind::Key) {
  330. properties.append(key);
  331. continue;
  332. }
  333. // 2. Else,
  334. // a. Let value be ? Get(O, key).
  335. auto value = TRY(get(property_key));
  336. // b. If kind is value, append value to properties.
  337. if (kind == PropertyKind::Value) {
  338. properties.append(value);
  339. continue;
  340. }
  341. // c. Else,
  342. // i. Assert: kind is key+value.
  343. VERIFY(kind == PropertyKind::KeyAndValue);
  344. // ii. Let entry be CreateArrayFromList(« key, value »).
  345. auto entry = Array::create_from(realm, { key, value });
  346. // iii. Append entry to properties.
  347. properties.append(entry);
  348. }
  349. }
  350. // 4. Return properties.
  351. return { move(properties) };
  352. }
  353. // 7.3.26 CopyDataProperties ( target, source, excludedItems ), https://tc39.es/ecma262/#sec-copydataproperties
  354. // 14.6 CopyDataProperties ( target, source, excludedItems, excludedKeys [ , excludedValues ] ), https://tc39.es/proposal-temporal/#sec-copydataproperties
  355. ThrowCompletionOr<void> Object::copy_data_properties(VM& vm, Value source, HashTable<PropertyKey> const& excluded_keys, HashTable<JS::Value> const& excluded_values)
  356. {
  357. // 1. If source is either undefined or null, return unused.
  358. if (source.is_nullish())
  359. return {};
  360. // 2. Let from be ! ToObject(source).
  361. auto from = MUST(source.to_object(vm));
  362. // 3. Let keys be ? from.[[OwnPropertyKeys]]().
  363. auto keys = TRY(from->internal_own_property_keys());
  364. // 4. For each element nextKey of keys, do
  365. for (auto& next_key_value : keys) {
  366. auto next_key = MUST(PropertyKey::from_value(vm, next_key_value));
  367. // a. Let excluded be false.
  368. // b. For each element e of excludedKeys, do
  369. // i. If SameValue(e, nextKey) is true, then
  370. // 1. Set excluded to true.
  371. if (excluded_keys.contains(next_key))
  372. continue;
  373. // c. If excluded is false, then
  374. // i. Let desc be ? from.[[GetOwnProperty]](nextKey).
  375. auto desc = TRY(from->internal_get_own_property(next_key));
  376. // ii. If desc is not undefined and desc.[[Enumerable]] is true, then
  377. if (desc.has_value() && desc->attributes().is_enumerable()) {
  378. // 1. Let propValue be ? Get(from, nextKey).
  379. auto prop_value = TRY(from->get(next_key));
  380. // 2. If excludedValues is present, then
  381. // a. For each element e of excludedValues, do
  382. // i. If SameValue(e, propValue) is true, then
  383. // i. Set excluded to true.
  384. // 3. If excluded is false, Perform ! CreateDataPropertyOrThrow(target, nextKey, propValue).
  385. // NOTE: HashTable traits for JS::Value uses SameValue.
  386. if (!excluded_values.contains(prop_value))
  387. MUST(create_data_property_or_throw(next_key, prop_value));
  388. }
  389. }
  390. // 5. Return unused.
  391. return {};
  392. }
  393. // 14.7 SnapshotOwnProperties ( source, proto [ , excludedKeys [ , excludedValues ] ] ), https://tc39.es/proposal-temporal/#sec-snapshotownproperties
  394. ThrowCompletionOr<NonnullGCPtr<Object>> Object::snapshot_own_properties(VM& vm, GCPtr<Object> prototype, HashTable<PropertyKey> const& excluded_keys, HashTable<Value> const& excluded_values)
  395. {
  396. auto& realm = *vm.current_realm();
  397. // 1. Let copy be OrdinaryObjectCreate(proto).
  398. auto copy = Object::create(realm, prototype);
  399. // 2. If excludedKeys is not present, set excludedKeys to « ».
  400. // 3. If excludedValues is not present, set excludedValues to « ».
  401. // 4. Perform ? CopyDataProperties(copy, source, excludedKeys, excludedValues).
  402. TRY(copy->copy_data_properties(vm, Value { this }, excluded_keys, excluded_values));
  403. // 5. Return copy.
  404. return copy;
  405. }
  406. // 7.3.27 PrivateElementFind ( O, P ), https://tc39.es/ecma262/#sec-privateelementfind
  407. PrivateElement* Object::private_element_find(PrivateName const& name)
  408. {
  409. if (!m_private_elements)
  410. return nullptr;
  411. // 1. If O.[[PrivateElements]] contains a PrivateElement pe such that pe.[[Key]] is P, then
  412. auto it = m_private_elements->find_if([&](auto const& element) {
  413. return element.key == name;
  414. });
  415. if (!it.is_end()) {
  416. // a. Return pe.
  417. return &(*it);
  418. }
  419. // 2. Return empty.
  420. return nullptr;
  421. }
  422. // 7.3.28 PrivateFieldAdd ( O, P, value ), https://tc39.es/ecma262/#sec-privatefieldadd
  423. ThrowCompletionOr<void> Object::private_field_add(PrivateName const& name, Value value)
  424. {
  425. auto& vm = this->vm();
  426. // 1. If the host is a web browser, then
  427. // a. Perform ? HostEnsureCanAddPrivateElement(O).
  428. // NOTE: Since LibJS has no way of knowing whether it is in a browser we just always call the hook.
  429. TRY(vm.host_ensure_can_add_private_element(*this));
  430. // 2. Let entry be PrivateElementFind(O, P).
  431. // 3. If entry is not empty, throw a TypeError exception.
  432. if (auto* entry = private_element_find(name); entry)
  433. return vm.throw_completion<TypeError>(ErrorType::PrivateFieldAlreadyDeclared, name.description);
  434. if (!m_private_elements)
  435. m_private_elements = make<Vector<PrivateElement>>();
  436. // 4. Append PrivateElement { [[Key]]: P, [[Kind]]: field, [[Value]]: value } to O.[[PrivateElements]].
  437. m_private_elements->empend(name, PrivateElement::Kind::Field, value);
  438. // 5. Return unused.
  439. return {};
  440. }
  441. // 7.3.29 PrivateMethodOrAccessorAdd ( O, method ), https://tc39.es/ecma262/#sec-privatemethodoraccessoradd
  442. ThrowCompletionOr<void> Object::private_method_or_accessor_add(PrivateElement element)
  443. {
  444. auto& vm = this->vm();
  445. // 1. Assert: method.[[Kind]] is either method or accessor.
  446. VERIFY(element.kind == PrivateElement::Kind::Method || element.kind == PrivateElement::Kind::Accessor);
  447. // 2. If the host is a web browser, then
  448. // a. Perform ? HostEnsureCanAddPrivateElement(O).
  449. // NOTE: Since LibJS has no way of knowing whether it is in a browser we just always call the hook.
  450. TRY(vm.host_ensure_can_add_private_element(*this));
  451. // 3. Let entry be PrivateElementFind(O, method.[[Key]]).
  452. // 4. If entry is not empty, throw a TypeError exception.
  453. if (auto* entry = private_element_find(element.key); entry)
  454. return vm.throw_completion<TypeError>(ErrorType::PrivateFieldAlreadyDeclared, element.key.description);
  455. if (!m_private_elements)
  456. m_private_elements = make<Vector<PrivateElement>>();
  457. // 5. Append method to O.[[PrivateElements]].
  458. m_private_elements->append(move(element));
  459. // 6. Return unused.
  460. return {};
  461. }
  462. // 7.3.31 PrivateGet ( O, P ), https://tc39.es/ecma262/#sec-privateget
  463. ThrowCompletionOr<Value> Object::private_get(PrivateName const& name)
  464. {
  465. auto& vm = this->vm();
  466. // 1. Let entry be PrivateElementFind(O, P).
  467. auto* entry = private_element_find(name);
  468. // 2. If entry is empty, throw a TypeError exception.
  469. if (!entry)
  470. return vm.throw_completion<TypeError>(ErrorType::PrivateFieldDoesNotExistOnObject, name.description);
  471. auto& value = entry->value;
  472. // 3. If entry.[[Kind]] is either field or method, then
  473. if (entry->kind != PrivateElement::Kind::Accessor) {
  474. // a. Return entry.[[Value]].
  475. return value;
  476. }
  477. // Assert: entry.[[Kind]] is accessor.
  478. VERIFY(value.is_accessor());
  479. // 6. Let getter be entry.[[Get]].
  480. auto* getter = value.as_accessor().getter();
  481. // 5. If entry.[[Get]] is undefined, throw a TypeError exception.
  482. if (!getter)
  483. return vm.throw_completion<TypeError>(ErrorType::PrivateFieldGetAccessorWithoutGetter, name.description);
  484. // 7. Return ? Call(getter, O).
  485. return TRY(call(vm, *getter, this));
  486. }
  487. // 7.3.32 PrivateSet ( O, P, value ), https://tc39.es/ecma262/#sec-privateset
  488. ThrowCompletionOr<void> Object::private_set(PrivateName const& name, Value value)
  489. {
  490. auto& vm = this->vm();
  491. // 1. Let entry be PrivateElementFind(O, P).
  492. auto* entry = private_element_find(name);
  493. // 2. If entry is empty, throw a TypeError exception.
  494. if (!entry)
  495. return vm.throw_completion<TypeError>(ErrorType::PrivateFieldDoesNotExistOnObject, name.description);
  496. // 3. If entry.[[Kind]] is field, then
  497. if (entry->kind == PrivateElement::Kind::Field) {
  498. // a. Set entry.[[Value]] to value.
  499. entry->value = value;
  500. return {};
  501. }
  502. // 4. Else if entry.[[Kind]] is method, then
  503. else if (entry->kind == PrivateElement::Kind::Method) {
  504. // a. Throw a TypeError exception.
  505. return vm.throw_completion<TypeError>(ErrorType::PrivateFieldSetMethod, name.description);
  506. }
  507. // 5. Else,
  508. // a. Assert: entry.[[Kind]] is accessor.
  509. VERIFY(entry->kind == PrivateElement::Kind::Accessor);
  510. auto& accessor = entry->value;
  511. VERIFY(accessor.is_accessor());
  512. // c. Let setter be entry.[[Set]].
  513. auto* setter = accessor.as_accessor().setter();
  514. // b. If entry.[[Set]] is undefined, throw a TypeError exception.
  515. if (!setter)
  516. return vm.throw_completion<TypeError>(ErrorType::PrivateFieldSetAccessorWithoutSetter, name.description);
  517. // d. Perform ? Call(setter, O, « value »).
  518. TRY(call(vm, *setter, this, value));
  519. // 6. Return unused.
  520. return {};
  521. }
  522. // 7.3.33 DefineField ( receiver, fieldRecord ), https://tc39.es/ecma262/#sec-definefield
  523. ThrowCompletionOr<void> Object::define_field(ClassFieldDefinition const& field)
  524. {
  525. auto& vm = this->vm();
  526. // 1. Let fieldName be fieldRecord.[[Name]].
  527. auto const& field_name = field.name;
  528. // 2. Let initializer be fieldRecord.[[Initializer]].
  529. auto const& initializer = field.initializer;
  530. auto init_value = js_undefined();
  531. // 3. If initializer is not empty, then
  532. if (!initializer.is_null()) {
  533. // a. Let initValue be ? Call(initializer, receiver).
  534. init_value = TRY(call(vm, initializer.cell(), this));
  535. }
  536. // 4. Else, let initValue be undefined.
  537. // 5. If fieldName is a Private Name, then
  538. if (field_name.has<PrivateName>()) {
  539. // a. Perform ? PrivateFieldAdd(receiver, fieldName, initValue).
  540. TRY(private_field_add(field_name.get<PrivateName>(), init_value));
  541. }
  542. // 6. Else,
  543. else {
  544. // a. Assert: IsPropertyKey(fieldName) is true.
  545. // b. Perform ? CreateDataPropertyOrThrow(receiver, fieldName, initValue).
  546. TRY(create_data_property_or_throw(field_name.get<PropertyKey>(), init_value));
  547. }
  548. // 7. Return unused.
  549. return {};
  550. }
  551. // 7.3.34 InitializeInstanceElements ( O, constructor ), https://tc39.es/ecma262/#sec-initializeinstanceelements
  552. ThrowCompletionOr<void> Object::initialize_instance_elements(ECMAScriptFunctionObject& constructor)
  553. {
  554. // 1. Let methods be the value of constructor.[[PrivateMethods]].
  555. // 2. For each PrivateElement method of methods, do
  556. for (auto const& method : constructor.private_methods()) {
  557. // a. Perform ? PrivateMethodOrAccessorAdd(O, method).
  558. TRY(private_method_or_accessor_add(method));
  559. }
  560. // 3. Let fields be the value of constructor.[[Fields]].
  561. // 4. For each element fieldRecord of fields, do
  562. for (auto const& field : constructor.fields()) {
  563. // a. Perform ? DefineField(O, fieldRecord).
  564. TRY(define_field(field));
  565. }
  566. // 5. Return unused.
  567. return {};
  568. }
  569. // 10.1 Ordinary Object Internal Methods and Internal Slots, https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots
  570. // 10.1.1 [[GetPrototypeOf]] ( ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getprototypeof
  571. ThrowCompletionOr<Object*> Object::internal_get_prototype_of() const
  572. {
  573. // 1. Return O.[[Prototype]].
  574. return const_cast<Object*>(prototype());
  575. }
  576. // 10.1.2 [[SetPrototypeOf]] ( V ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-setprototypeof-v
  577. ThrowCompletionOr<bool> Object::internal_set_prototype_of(Object* new_prototype)
  578. {
  579. // 1. Let current be O.[[Prototype]].
  580. // 2. If SameValue(V, current) is true, return true.
  581. if (prototype() == new_prototype)
  582. return true;
  583. // 3. Let extensible be O.[[Extensible]].
  584. // 4. If extensible is false, return false.
  585. if (!m_is_extensible)
  586. return false;
  587. // 5. Let p be V.
  588. auto* prototype = new_prototype;
  589. // 6. Let done be false.
  590. // 7. Repeat, while done is false,
  591. while (prototype) {
  592. // a. If p is null, set done to true.
  593. // b. Else if SameValue(p, O) is true, return false.
  594. if (prototype == this)
  595. return false;
  596. // c. Else,
  597. // i. If p.[[GetPrototypeOf]] is not the ordinary object internal method defined in 10.1.1, set done to true.
  598. // NOTE: This is a best-effort implementation; we don't have a good way of detecting whether certain virtual
  599. // Object methods have been overridden by a given object, but as ProxyObject is the only one doing that for
  600. // [[SetPrototypeOf]], this check does the trick.
  601. if (is<ProxyObject>(prototype))
  602. break;
  603. // ii. Else, set p to p.[[Prototype]].
  604. prototype = prototype->prototype();
  605. }
  606. // 8. Set O.[[Prototype]] to V.
  607. set_prototype(new_prototype);
  608. // 9. Return true.
  609. return true;
  610. }
  611. // 10.1.3 [[IsExtensible]] ( ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-isextensible
  612. ThrowCompletionOr<bool> Object::internal_is_extensible() const
  613. {
  614. // 1. Return O.[[Extensible]].
  615. return m_is_extensible;
  616. }
  617. // 10.1.4 [[PreventExtensions]] ( ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-preventextensions
  618. ThrowCompletionOr<bool> Object::internal_prevent_extensions()
  619. {
  620. // 1. Set O.[[Extensible]] to false.
  621. m_is_extensible = false;
  622. // 2. Return true.
  623. return true;
  624. }
  625. // 10.1.5 [[GetOwnProperty]] ( P ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getownproperty-p
  626. ThrowCompletionOr<Optional<PropertyDescriptor>> Object::internal_get_own_property(PropertyKey const& property_key) const
  627. {
  628. VERIFY(property_key.is_valid());
  629. // 1. If O does not have an own property with key P, return undefined.
  630. auto maybe_storage_entry = storage_get(property_key);
  631. if (!maybe_storage_entry.has_value())
  632. return Optional<PropertyDescriptor> {};
  633. // 2. Let D be a newly created Property Descriptor with no fields.
  634. PropertyDescriptor descriptor;
  635. // 3. Let X be O's own property whose key is P.
  636. auto [value, attributes, property_offset] = *maybe_storage_entry;
  637. // AD-HOC: Properties with the [[Unimplemented]] attribute are used for reporting unimplemented IDL interfaces.
  638. if (attributes.is_unimplemented()) {
  639. if (vm().on_unimplemented_property_access)
  640. vm().on_unimplemented_property_access(*this, property_key);
  641. descriptor.unimplemented = true;
  642. }
  643. // 4. If X is a data property, then
  644. if (!value.is_accessor()) {
  645. // a. Set D.[[Value]] to the value of X's [[Value]] attribute.
  646. descriptor.value = value.value_or(js_undefined());
  647. // b. Set D.[[Writable]] to the value of X's [[Writable]] attribute.
  648. descriptor.writable = attributes.is_writable();
  649. }
  650. // 5. Else,
  651. else {
  652. // a. Assert: X is an accessor property.
  653. // b. Set D.[[Get]] to the value of X's [[Get]] attribute.
  654. descriptor.get = value.as_accessor().getter();
  655. // c. Set D.[[Set]] to the value of X's [[Set]] attribute.
  656. descriptor.set = value.as_accessor().setter();
  657. }
  658. // 6. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute.
  659. descriptor.enumerable = attributes.is_enumerable();
  660. // 7. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute.
  661. descriptor.configurable = attributes.is_configurable();
  662. // Non-standard: Add the property offset to the descriptor. This is used to populate CacheablePropertyMetadata.
  663. descriptor.property_offset = property_offset;
  664. // 8. Return D.
  665. return descriptor;
  666. }
  667. // 10.1.6 [[DefineOwnProperty]] ( P, Desc ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-defineownproperty-p-desc
  668. ThrowCompletionOr<bool> Object::internal_define_own_property(PropertyKey const& property_key, PropertyDescriptor const& property_descriptor, Optional<PropertyDescriptor>* precomputed_get_own_property)
  669. {
  670. VERIFY(property_key.is_valid());
  671. // 1. Let current be ? O.[[GetOwnProperty]](P).
  672. auto current = precomputed_get_own_property ? *precomputed_get_own_property : TRY(internal_get_own_property(property_key));
  673. // 2. Let extensible be ? IsExtensible(O).
  674. auto extensible = TRY(is_extensible());
  675. // 3. Return ValidateAndApplyPropertyDescriptor(O, P, extensible, Desc, current).
  676. return validate_and_apply_property_descriptor(this, property_key, extensible, property_descriptor, current);
  677. }
  678. // 10.1.7 [[HasProperty]] ( P ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-hasproperty-p
  679. ThrowCompletionOr<bool> Object::internal_has_property(PropertyKey const& property_key) const
  680. {
  681. VERIFY(property_key.is_valid());
  682. // 1. Let hasOwn be ? O.[[GetOwnProperty]](P).
  683. auto has_own = TRY(internal_get_own_property(property_key));
  684. // 2. If hasOwn is not undefined, return true.
  685. if (has_own.has_value())
  686. return true;
  687. // 3. Let parent be ? O.[[GetPrototypeOf]]().
  688. auto* parent = TRY(internal_get_prototype_of());
  689. // 4. If parent is not null, then
  690. if (parent) {
  691. // a. Return ? parent.[[HasProperty]](P).
  692. return parent->internal_has_property(property_key);
  693. }
  694. // 5. Return false.
  695. return false;
  696. }
  697. // 10.1.8 [[Get]] ( P, Receiver ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-get-p-receiver
  698. ThrowCompletionOr<Value> Object::internal_get(PropertyKey const& property_key, Value receiver, CacheablePropertyMetadata* cacheable_metadata, PropertyLookupPhase phase) const
  699. {
  700. VERIFY(!receiver.is_empty());
  701. VERIFY(property_key.is_valid());
  702. auto& vm = this->vm();
  703. // 1. Let desc be ? O.[[GetOwnProperty]](P).
  704. auto descriptor = TRY(internal_get_own_property(property_key));
  705. // 2. If desc is undefined, then
  706. if (!descriptor.has_value()) {
  707. // a. Let parent be ? O.[[GetPrototypeOf]]().
  708. auto* parent = TRY(internal_get_prototype_of());
  709. // b. If parent is null, return undefined.
  710. if (!parent)
  711. return js_undefined();
  712. // c. Return ? parent.[[Get]](P, Receiver).
  713. return parent->internal_get(property_key, receiver, cacheable_metadata, PropertyLookupPhase::PrototypeChain);
  714. }
  715. auto update_inline_cache = [&] {
  716. // Non-standard: If the caller has requested cacheable metadata and the property is an own property, fill it in.
  717. if (!cacheable_metadata || !descriptor->property_offset.has_value() || !shape().is_cacheable())
  718. return;
  719. if (phase == PropertyLookupPhase::OwnProperty) {
  720. *cacheable_metadata = CacheablePropertyMetadata {
  721. .type = CacheablePropertyMetadata::Type::OwnProperty,
  722. .property_offset = descriptor->property_offset.value(),
  723. .prototype = nullptr,
  724. };
  725. } else if (phase == PropertyLookupPhase::PrototypeChain) {
  726. VERIFY(shape().is_prototype_shape());
  727. VERIFY(shape().prototype_chain_validity()->is_valid());
  728. *cacheable_metadata = CacheablePropertyMetadata {
  729. .type = CacheablePropertyMetadata::Type::InPrototypeChain,
  730. .property_offset = descriptor->property_offset.value(),
  731. .prototype = this,
  732. };
  733. }
  734. };
  735. // 3. If IsDataDescriptor(desc) is true, return desc.[[Value]].
  736. if (descriptor->is_data_descriptor()) {
  737. update_inline_cache();
  738. return *descriptor->value;
  739. }
  740. // 4. Assert: IsAccessorDescriptor(desc) is true.
  741. VERIFY(descriptor->is_accessor_descriptor());
  742. // 5. Let getter be desc.[[Get]].
  743. auto getter = *descriptor->get;
  744. // 6. If getter is undefined, return undefined.
  745. if (!getter)
  746. return js_undefined();
  747. update_inline_cache();
  748. // 7. Return ? Call(getter, Receiver).
  749. return TRY(call(vm, *getter, receiver));
  750. }
  751. // 10.1.9 [[Set]] ( P, V, Receiver ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-set-p-v-receiver
  752. ThrowCompletionOr<bool> Object::internal_set(PropertyKey const& property_key, Value value, Value receiver, CacheablePropertyMetadata* cacheable_metadata)
  753. {
  754. VERIFY(property_key.is_valid());
  755. VERIFY(!value.is_empty());
  756. VERIFY(!receiver.is_empty());
  757. // 2. Let ownDesc be ? O.[[GetOwnProperty]](P).
  758. auto own_descriptor = TRY(internal_get_own_property(property_key));
  759. // 3. Return ? OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc).
  760. return ordinary_set_with_own_descriptor(property_key, value, receiver, own_descriptor, cacheable_metadata);
  761. }
  762. // 10.1.9.2 OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ), https://tc39.es/ecma262/#sec-ordinarysetwithowndescriptor
  763. ThrowCompletionOr<bool> Object::ordinary_set_with_own_descriptor(PropertyKey const& property_key, Value value, Value receiver, Optional<PropertyDescriptor> own_descriptor, CacheablePropertyMetadata* cacheable_metadata)
  764. {
  765. VERIFY(property_key.is_valid());
  766. VERIFY(!value.is_empty());
  767. VERIFY(!receiver.is_empty());
  768. auto& vm = this->vm();
  769. // 1. If ownDesc is undefined, then
  770. if (!own_descriptor.has_value()) {
  771. // a. Let parent be ? O.[[GetPrototypeOf]]().
  772. auto* parent = TRY(internal_get_prototype_of());
  773. // b. If parent is not null, then
  774. if (parent) {
  775. // i. Return ? parent.[[Set]](P, V, Receiver).
  776. return TRY(parent->internal_set(property_key, value, receiver));
  777. }
  778. // c. Else,
  779. else {
  780. // i. Set ownDesc to the PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }.
  781. own_descriptor = PropertyDescriptor {
  782. .value = js_undefined(),
  783. .writable = true,
  784. .enumerable = true,
  785. .configurable = true,
  786. };
  787. }
  788. }
  789. // 2. If IsDataDescriptor(ownDesc) is true, then
  790. if (own_descriptor->is_data_descriptor()) {
  791. // a. If ownDesc.[[Writable]] is false, return false.
  792. if (!*own_descriptor->writable)
  793. return false;
  794. // b. If Type(Receiver) is not Object, return false.
  795. if (!receiver.is_object())
  796. return false;
  797. auto& receiver_object = receiver.as_object();
  798. // c. Let existingDescriptor be ? Receiver.[[GetOwnProperty]](P).
  799. auto existing_descriptor = TRY(receiver_object.internal_get_own_property(property_key));
  800. // d. If existingDescriptor is not undefined, then
  801. if (existing_descriptor.has_value()) {
  802. // i. If IsAccessorDescriptor(existingDescriptor) is true, return false.
  803. if (existing_descriptor->is_accessor_descriptor())
  804. return false;
  805. // ii. If existingDescriptor.[[Writable]] is false, return false.
  806. if (!*existing_descriptor->writable)
  807. return false;
  808. // iii. Let valueDesc be the PropertyDescriptor { [[Value]]: V }.
  809. auto value_descriptor = PropertyDescriptor { .value = value };
  810. if (cacheable_metadata && own_descriptor.has_value() && own_descriptor->property_offset.has_value() && shape().is_cacheable()) {
  811. *cacheable_metadata = CacheablePropertyMetadata {
  812. .type = CacheablePropertyMetadata::Type::OwnProperty,
  813. .property_offset = own_descriptor->property_offset.value(),
  814. .prototype = nullptr,
  815. };
  816. }
  817. // iv. Return ? Receiver.[[DefineOwnProperty]](P, valueDesc).
  818. return TRY(receiver_object.internal_define_own_property(property_key, value_descriptor, &existing_descriptor));
  819. }
  820. // e. Else,
  821. else {
  822. // i. Assert: Receiver does not currently have a property P.
  823. VERIFY(!receiver_object.storage_has(property_key));
  824. // ii. Return ? CreateDataProperty(Receiver, P, V).
  825. return TRY(receiver_object.create_data_property(property_key, value));
  826. }
  827. }
  828. // 3. Assert: IsAccessorDescriptor(ownDesc) is true.
  829. VERIFY(own_descriptor->is_accessor_descriptor());
  830. // 4. Let setter be ownDesc.[[Set]].
  831. auto setter = *own_descriptor->set;
  832. // 5. If setter is undefined, return false.
  833. if (!setter)
  834. return false;
  835. // 6. Perform ? Call(setter, Receiver, « V »).
  836. (void)TRY(call(vm, *setter, receiver, value));
  837. // 7. Return true.
  838. return true;
  839. }
  840. // 10.1.10 [[Delete]] ( P ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-delete-p
  841. ThrowCompletionOr<bool> Object::internal_delete(PropertyKey const& property_key)
  842. {
  843. VERIFY(property_key.is_valid());
  844. // 1. Let desc be ? O.[[GetOwnProperty]](P).
  845. auto descriptor = TRY(internal_get_own_property(property_key));
  846. // 2. If desc is undefined, return true.
  847. if (!descriptor.has_value())
  848. return true;
  849. // 3. If desc.[[Configurable]] is true, then
  850. if (*descriptor->configurable) {
  851. // a. Remove the own property with name P from O.
  852. storage_delete(property_key);
  853. // b. Return true.
  854. return true;
  855. }
  856. // 4. Return false.
  857. return false;
  858. }
  859. // 10.1.11 [[OwnPropertyKeys]] ( ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys
  860. ThrowCompletionOr<MarkedVector<Value>> Object::internal_own_property_keys() const
  861. {
  862. auto& vm = this->vm();
  863. // 1. Let keys be a new empty List.
  864. MarkedVector<Value> keys { heap() };
  865. // 2. For each own property key P of O such that P is an array index, in ascending numeric index order, do
  866. for (auto& entry : m_indexed_properties) {
  867. // a. Add P as the last element of keys.
  868. keys.append(PrimitiveString::create(vm, ByteString::number(entry.index())));
  869. }
  870. // 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
  871. for (auto& it : shape().property_table()) {
  872. if (it.key.is_string()) {
  873. // a. Add P as the last element of keys.
  874. keys.append(it.key.to_value(vm));
  875. }
  876. }
  877. // 4. For each own property key P of O such that Type(P) is Symbol, in ascending chronological order of property creation, do
  878. for (auto& it : shape().property_table()) {
  879. if (it.key.is_symbol()) {
  880. // a. Add P as the last element of keys.
  881. keys.append(it.key.to_value(vm));
  882. }
  883. }
  884. // 5. Return keys.
  885. return { move(keys) };
  886. }
  887. // 10.4.7.2 SetImmutablePrototype ( O, V ), https://tc39.es/ecma262/#sec-set-immutable-prototype
  888. ThrowCompletionOr<bool> Object::set_immutable_prototype(Object* prototype)
  889. {
  890. // 1. Let current be ? O.[[GetPrototypeOf]]().
  891. auto* current = TRY(internal_get_prototype_of());
  892. // 2. If SameValue(V, current) is true, return true.
  893. if (prototype == current)
  894. return true;
  895. // 3. Return false.
  896. return false;
  897. }
  898. static Optional<Object::IntrinsicAccessor> find_intrinsic_accessor(Object const* object, PropertyKey const& property_key)
  899. {
  900. if (!property_key.is_string())
  901. return {};
  902. auto intrinsics = s_intrinsics.find(object);
  903. if (intrinsics == s_intrinsics.end())
  904. return {};
  905. auto accessor_iterator = intrinsics->value.find(property_key.as_string());
  906. if (accessor_iterator == intrinsics->value.end())
  907. return {};
  908. auto accessor = accessor_iterator->value;
  909. intrinsics->value.remove(accessor_iterator);
  910. return accessor;
  911. }
  912. Optional<ValueAndAttributes> Object::storage_get(PropertyKey const& property_key) const
  913. {
  914. VERIFY(property_key.is_valid());
  915. Value value;
  916. PropertyAttributes attributes;
  917. Optional<u32> property_offset;
  918. if (property_key.is_number()) {
  919. auto value_and_attributes = m_indexed_properties.get(property_key.as_number());
  920. if (!value_and_attributes.has_value())
  921. return {};
  922. value = value_and_attributes->value;
  923. attributes = value_and_attributes->attributes;
  924. } else {
  925. auto metadata = shape().lookup(property_key.to_string_or_symbol());
  926. if (!metadata.has_value())
  927. return {};
  928. if (m_has_intrinsic_accessors) {
  929. if (auto accessor = find_intrinsic_accessor(this, property_key); accessor.has_value())
  930. const_cast<Object&>(*this).m_storage[metadata->offset] = (*accessor)(shape().realm());
  931. }
  932. value = m_storage[metadata->offset];
  933. attributes = metadata->attributes;
  934. property_offset = metadata->offset;
  935. }
  936. return ValueAndAttributes { .value = value, .attributes = attributes, .property_offset = property_offset };
  937. }
  938. bool Object::storage_has(PropertyKey const& property_key) const
  939. {
  940. VERIFY(property_key.is_valid());
  941. if (property_key.is_number())
  942. return m_indexed_properties.has_index(property_key.as_number());
  943. return shape().lookup(property_key.to_string_or_symbol()).has_value();
  944. }
  945. void Object::storage_set(PropertyKey const& property_key, ValueAndAttributes const& value_and_attributes)
  946. {
  947. VERIFY(property_key.is_valid());
  948. auto [value, attributes, _] = value_and_attributes;
  949. if (property_key.is_number()) {
  950. auto index = property_key.as_number();
  951. m_indexed_properties.put(index, value, attributes);
  952. return;
  953. }
  954. if (m_has_intrinsic_accessors && property_key.is_string()) {
  955. if (auto intrinsics = s_intrinsics.find(this); intrinsics != s_intrinsics.end())
  956. intrinsics->value.remove(property_key.as_string());
  957. }
  958. auto property_key_string_or_symbol = property_key.to_string_or_symbol();
  959. auto metadata = shape().lookup(property_key_string_or_symbol);
  960. if (!metadata.has_value()) {
  961. static constexpr size_t max_transitions_before_converting_to_dictionary = 64;
  962. if (!m_shape->is_dictionary() && m_shape->property_count() >= max_transitions_before_converting_to_dictionary)
  963. set_shape(m_shape->create_cacheable_dictionary_transition());
  964. if (m_shape->is_dictionary())
  965. m_shape->add_property_without_transition(property_key_string_or_symbol, attributes);
  966. else
  967. set_shape(*m_shape->create_put_transition(property_key_string_or_symbol, attributes));
  968. m_storage.append(value);
  969. return;
  970. }
  971. if (attributes != metadata->attributes) {
  972. if (m_shape->is_dictionary())
  973. m_shape->set_property_attributes_without_transition(property_key_string_or_symbol, attributes);
  974. else
  975. set_shape(*m_shape->create_configure_transition(property_key_string_or_symbol, attributes));
  976. }
  977. m_storage[metadata->offset] = value;
  978. }
  979. void Object::storage_delete(PropertyKey const& property_key)
  980. {
  981. VERIFY(property_key.is_valid());
  982. VERIFY(storage_has(property_key));
  983. if (property_key.is_number())
  984. return m_indexed_properties.remove(property_key.as_number());
  985. if (m_has_intrinsic_accessors && property_key.is_string()) {
  986. if (auto intrinsics = s_intrinsics.find(this); intrinsics != s_intrinsics.end())
  987. intrinsics->value.remove(property_key.as_string());
  988. }
  989. auto metadata = shape().lookup(property_key.to_string_or_symbol());
  990. VERIFY(metadata.has_value());
  991. if (m_shape->is_cacheable_dictionary()) {
  992. m_shape = m_shape->create_uncacheable_dictionary_transition();
  993. }
  994. if (m_shape->is_uncacheable_dictionary()) {
  995. m_shape->remove_property_without_transition(property_key.to_string_or_symbol(), metadata->offset);
  996. m_storage.remove(metadata->offset);
  997. return;
  998. }
  999. m_shape = m_shape->create_delete_transition(property_key.to_string_or_symbol());
  1000. m_storage.remove(metadata->offset);
  1001. }
  1002. void Object::set_prototype(Object* new_prototype)
  1003. {
  1004. if (prototype() == new_prototype)
  1005. return;
  1006. m_shape = shape().create_prototype_transition(new_prototype);
  1007. }
  1008. void Object::define_native_accessor(Realm& realm, PropertyKey const& property_key, Function<ThrowCompletionOr<Value>(VM&)> getter, Function<ThrowCompletionOr<Value>(VM&)> setter, PropertyAttributes attribute)
  1009. {
  1010. FunctionObject* getter_function = nullptr;
  1011. if (getter)
  1012. getter_function = NativeFunction::create(realm, move(getter), 0, property_key, &realm, {}, "get"sv);
  1013. FunctionObject* setter_function = nullptr;
  1014. if (setter)
  1015. setter_function = NativeFunction::create(realm, move(setter), 1, property_key, &realm, {}, "set"sv);
  1016. return define_direct_accessor(property_key, getter_function, setter_function, attribute);
  1017. }
  1018. void Object::define_direct_accessor(PropertyKey const& property_key, FunctionObject* getter, FunctionObject* setter, PropertyAttributes attributes)
  1019. {
  1020. VERIFY(property_key.is_valid());
  1021. auto existing_property = storage_get(property_key).value_or({}).value;
  1022. auto* accessor = existing_property.is_accessor() ? &existing_property.as_accessor() : nullptr;
  1023. if (!accessor) {
  1024. accessor = Accessor::create(vm(), getter, setter);
  1025. define_direct_property(property_key, accessor, attributes);
  1026. } else {
  1027. if (getter)
  1028. accessor->set_getter(getter);
  1029. if (setter)
  1030. accessor->set_setter(setter);
  1031. }
  1032. }
  1033. void Object::define_intrinsic_accessor(PropertyKey const& property_key, PropertyAttributes attributes, IntrinsicAccessor accessor)
  1034. {
  1035. VERIFY(property_key.is_string());
  1036. storage_set(property_key, { {}, attributes });
  1037. m_has_intrinsic_accessors = true;
  1038. auto& intrinsics = s_intrinsics.ensure(this);
  1039. intrinsics.set(property_key.as_string(), move(accessor));
  1040. }
  1041. // Simple side-effect free property lookup, following the prototype chain. Non-standard.
  1042. Value Object::get_without_side_effects(PropertyKey const& property_key) const
  1043. {
  1044. auto* object = this;
  1045. while (object) {
  1046. auto value_and_attributes = object->storage_get(property_key);
  1047. if (value_and_attributes.has_value())
  1048. return value_and_attributes->value;
  1049. object = object->prototype();
  1050. }
  1051. return {};
  1052. }
  1053. void Object::define_native_function(Realm& realm, PropertyKey const& property_key, Function<ThrowCompletionOr<Value>(VM&)> native_function, i32 length, PropertyAttributes attribute, Optional<Bytecode::Builtin> builtin)
  1054. {
  1055. auto function = NativeFunction::create(realm, move(native_function), length, property_key, &realm);
  1056. define_direct_property(property_key, function, attribute);
  1057. if (builtin.has_value())
  1058. realm.define_builtin(builtin.value(), function);
  1059. }
  1060. // 20.1.2.3.1 ObjectDefineProperties ( O, Properties ), https://tc39.es/ecma262/#sec-objectdefineproperties
  1061. ThrowCompletionOr<Object*> Object::define_properties(Value properties)
  1062. {
  1063. auto& vm = this->vm();
  1064. // 1. Let props be ? ToObject(Properties).
  1065. auto props = TRY(properties.to_object(vm));
  1066. // 2. Let keys be ? props.[[OwnPropertyKeys]]().
  1067. auto keys = TRY(props->internal_own_property_keys());
  1068. struct NameAndDescriptor {
  1069. PropertyKey name;
  1070. PropertyDescriptor descriptor;
  1071. };
  1072. // 3. Let descriptors be a new empty List.
  1073. Vector<NameAndDescriptor> descriptors;
  1074. // 4. For each element nextKey of keys, do
  1075. for (auto& next_key : keys) {
  1076. auto property_key = MUST(PropertyKey::from_value(vm, next_key));
  1077. // a. Let propDesc be ? props.[[GetOwnProperty]](nextKey).
  1078. auto property_descriptor = TRY(props->internal_get_own_property(property_key));
  1079. // b. If propDesc is not undefined and propDesc.[[Enumerable]] is true, then
  1080. if (property_descriptor.has_value() && *property_descriptor->enumerable) {
  1081. // i. Let descObj be ? Get(props, nextKey).
  1082. auto descriptor_object = TRY(props->get(property_key));
  1083. // ii. Let desc be ? ToPropertyDescriptor(descObj).
  1084. auto descriptor = TRY(to_property_descriptor(vm, descriptor_object));
  1085. // iii. Append the pair (a two element List) consisting of nextKey and desc to the end of descriptors.
  1086. descriptors.append({ property_key, descriptor });
  1087. }
  1088. }
  1089. // 5. For each element pair of descriptors, do
  1090. for (auto& [name, descriptor] : descriptors) {
  1091. // a. Let P be the first element of pair.
  1092. // b. Let desc be the second element of pair.
  1093. // c. Perform ? DefinePropertyOrThrow(O, P, desc).
  1094. TRY(define_property_or_throw(name, descriptor));
  1095. }
  1096. // 6. Return O.
  1097. return this;
  1098. }
  1099. // 14.7.5.9 EnumerateObjectProperties ( O ), https://tc39.es/ecma262/#sec-enumerate-object-properties
  1100. Optional<Completion> Object::enumerate_object_properties(Function<Optional<Completion>(Value)> callback) const
  1101. {
  1102. // 1. Return an Iterator object (27.1.1.2) whose next method iterates over all the String-valued keys of enumerable properties of O. The iterator object is never directly accessible to ECMAScript code. The mechanics and order of enumerating the properties is not specified but must conform to the rules specified below.
  1103. // * Returned property keys do not include keys that are Symbols.
  1104. // * Properties of the target object may be deleted during enumeration.
  1105. // * A property that is deleted before it is processed is ignored.
  1106. // * If new properties are added to the target object during enumeration, the newly added properties are not guaranteed to be processed in the active enumeration.
  1107. // * A property name will be returned at most once in any enumeration.
  1108. // * Enumerating the properties of the target object includes enumerating properties of its prototype, and the prototype of the prototype, and so on, recursively.
  1109. // * A property of a prototype is not processed if it has the same name as a property that has already been processed.
  1110. HashTable<DeprecatedFlyString> visited;
  1111. auto const* target = this;
  1112. while (target) {
  1113. auto own_keys = TRY(target->internal_own_property_keys());
  1114. for (auto& key : own_keys) {
  1115. if (!key.is_string())
  1116. continue;
  1117. DeprecatedFlyString property_key = key.as_string().byte_string();
  1118. if (visited.contains(property_key))
  1119. continue;
  1120. auto descriptor = TRY(target->internal_get_own_property(property_key));
  1121. if (!descriptor.has_value())
  1122. continue;
  1123. visited.set(property_key);
  1124. if (!*descriptor->enumerable)
  1125. continue;
  1126. if (auto completion = callback(key); completion.has_value())
  1127. return completion.release_value();
  1128. }
  1129. target = TRY(target->internal_get_prototype_of());
  1130. };
  1131. return {};
  1132. }
  1133. void Object::visit_edges(Cell::Visitor& visitor)
  1134. {
  1135. Base::visit_edges(visitor);
  1136. visitor.visit(m_shape);
  1137. visitor.visit(m_storage);
  1138. m_indexed_properties.for_each_value([&visitor](auto& value) {
  1139. visitor.visit(value);
  1140. });
  1141. if (m_private_elements) {
  1142. for (auto& private_element : *m_private_elements)
  1143. visitor.visit(private_element.value);
  1144. }
  1145. }
  1146. // 7.1.1.1 OrdinaryToPrimitive ( O, hint ), https://tc39.es/ecma262/#sec-ordinarytoprimitive
  1147. ThrowCompletionOr<Value> Object::ordinary_to_primitive(Value::PreferredType preferred_type) const
  1148. {
  1149. VERIFY(preferred_type == Value::PreferredType::String || preferred_type == Value::PreferredType::Number);
  1150. auto& vm = this->vm();
  1151. AK::Array<PropertyKey, 2> method_names;
  1152. // 1. If hint is string, then
  1153. if (preferred_type == Value::PreferredType::String) {
  1154. // a. Let methodNames be « "toString", "valueOf" ».
  1155. method_names = { vm.names.toString, vm.names.valueOf };
  1156. }
  1157. // 2. Else,
  1158. else {
  1159. // a. Let methodNames be « "valueOf", "toString" ».
  1160. method_names = { vm.names.valueOf, vm.names.toString };
  1161. }
  1162. // 3. For each element name of methodNames, do
  1163. for (auto& method_name : method_names) {
  1164. // a. Let method be ? Get(O, name).
  1165. auto method = TRY(get(method_name));
  1166. // b. If IsCallable(method) is true, then
  1167. if (method.is_function()) {
  1168. // i. Let result be ? Call(method, O).
  1169. auto result = TRY(call(vm, method.as_function(), const_cast<Object*>(this)));
  1170. // ii. If Type(result) is not Object, return result.
  1171. if (!result.is_object())
  1172. return result;
  1173. }
  1174. }
  1175. // 4. Throw a TypeError exception.
  1176. return vm.throw_completion<TypeError>(ErrorType::Convert, "object", preferred_type == Value::PreferredType::String ? "string" : "number");
  1177. }
  1178. void Object::convert_to_prototype_if_needed()
  1179. {
  1180. if (shape().is_prototype_shape())
  1181. return;
  1182. set_shape(shape().clone_for_prototype());
  1183. }
  1184. }