Object.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2020-2021, Linus Groh <mail@linusgroh.de>
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form must reproduce the above copyright notice,
  13. * this list of conditions and the following disclaimer in the documentation
  14. * and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  20. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  23. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  24. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  25. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include <AK/Debug.h>
  28. #include <AK/String.h>
  29. #include <AK/TemporaryChange.h>
  30. #include <LibJS/Heap/Heap.h>
  31. #include <LibJS/Interpreter.h>
  32. #include <LibJS/Runtime/Accessor.h>
  33. #include <LibJS/Runtime/Array.h>
  34. #include <LibJS/Runtime/Error.h>
  35. #include <LibJS/Runtime/GlobalObject.h>
  36. #include <LibJS/Runtime/NativeFunction.h>
  37. #include <LibJS/Runtime/NativeProperty.h>
  38. #include <LibJS/Runtime/Object.h>
  39. #include <LibJS/Runtime/Shape.h>
  40. #include <LibJS/Runtime/StringObject.h>
  41. #include <LibJS/Runtime/Value.h>
  42. namespace JS {
  43. PropertyDescriptor PropertyDescriptor::from_dictionary(VM& vm, const Object& object)
  44. {
  45. PropertyAttributes attributes;
  46. if (object.has_property(vm.names.configurable)) {
  47. attributes.set_has_configurable();
  48. if (object.get(vm.names.configurable).value_or(Value(false)).to_boolean())
  49. attributes.set_configurable();
  50. if (vm.exception())
  51. return {};
  52. }
  53. if (object.has_property(vm.names.enumerable)) {
  54. attributes.set_has_enumerable();
  55. if (object.get(vm.names.enumerable).value_or(Value(false)).to_boolean())
  56. attributes.set_enumerable();
  57. if (vm.exception())
  58. return {};
  59. }
  60. if (object.has_property(vm.names.writable)) {
  61. attributes.set_has_writable();
  62. if (object.get(vm.names.writable).value_or(Value(false)).to_boolean())
  63. attributes.set_writable();
  64. if (vm.exception())
  65. return {};
  66. }
  67. PropertyDescriptor descriptor { attributes, object.get(vm.names.value), nullptr, nullptr };
  68. if (vm.exception())
  69. return {};
  70. auto getter = object.get(vm.names.get);
  71. if (vm.exception())
  72. return {};
  73. if (getter.is_function())
  74. descriptor.getter = &getter.as_function();
  75. auto setter = object.get(vm.names.set);
  76. if (vm.exception())
  77. return {};
  78. if (setter.is_function())
  79. descriptor.setter = &setter.as_function();
  80. return descriptor;
  81. }
  82. Object* Object::create_empty(GlobalObject& global_object)
  83. {
  84. return global_object.heap().allocate<Object>(global_object, *global_object.new_object_shape());
  85. }
  86. Object::Object(GlobalObjectTag)
  87. {
  88. // This is the global object
  89. m_shape = heap().allocate_without_global_object<Shape>(*this);
  90. }
  91. Object::Object(ConstructWithoutPrototypeTag, GlobalObject& global_object)
  92. {
  93. m_shape = heap().allocate_without_global_object<Shape>(global_object);
  94. }
  95. Object::Object(Object& prototype)
  96. {
  97. m_shape = prototype.global_object().empty_object_shape();
  98. set_prototype(&prototype);
  99. }
  100. Object::Object(Shape& shape)
  101. : m_shape(&shape)
  102. {
  103. m_storage.resize(shape.property_count());
  104. }
  105. void Object::initialize(GlobalObject&)
  106. {
  107. }
  108. Object::~Object()
  109. {
  110. }
  111. Object* Object::prototype()
  112. {
  113. return shape().prototype();
  114. }
  115. const Object* Object::prototype() const
  116. {
  117. return shape().prototype();
  118. }
  119. bool Object::set_prototype(Object* new_prototype)
  120. {
  121. if (prototype() == new_prototype)
  122. return true;
  123. if (!m_is_extensible)
  124. return false;
  125. if (shape().is_unique()) {
  126. shape().set_prototype_without_transition(new_prototype);
  127. return true;
  128. }
  129. m_shape = m_shape->create_prototype_transition(new_prototype);
  130. return true;
  131. }
  132. bool Object::has_prototype(const Object* prototype) const
  133. {
  134. for (auto* object = this->prototype(); object; object = object->prototype()) {
  135. if (vm().exception())
  136. return false;
  137. if (object == prototype)
  138. return true;
  139. }
  140. return false;
  141. }
  142. bool Object::prevent_extensions()
  143. {
  144. m_is_extensible = false;
  145. return true;
  146. }
  147. // 7.3.15 SetIntegrityLevel, https://tc39.es/ecma262/#sec-setintegritylevel
  148. bool Object::set_integrity_level(IntegrityLevel level)
  149. {
  150. // FIXME: This feels clunky and should get nicer abstractions.
  151. auto update_property = [this](auto& key, auto attributes) {
  152. auto property_name = PropertyName::from_value(global_object(), key);
  153. auto metadata = shape().lookup(property_name.to_string_or_symbol());
  154. VERIFY(metadata.has_value());
  155. auto value = get_direct(metadata->offset);
  156. define_property(property_name, value, metadata->attributes.bits() & attributes);
  157. };
  158. auto& vm = this->vm();
  159. auto status = prevent_extensions();
  160. if (vm.exception())
  161. return false;
  162. if (!status)
  163. return false;
  164. auto keys = get_own_properties(PropertyKind::Key);
  165. if (vm.exception())
  166. return false;
  167. switch (level) {
  168. case IntegrityLevel::Sealed:
  169. for (auto& key : keys) {
  170. update_property(key, ~Attribute::Configurable);
  171. if (vm.exception())
  172. return {};
  173. }
  174. break;
  175. case IntegrityLevel::Frozen:
  176. for (auto& key : keys) {
  177. auto property_name = PropertyName::from_value(global_object(), key);
  178. auto property_descriptor = get_own_property_descriptor(property_name);
  179. VERIFY(property_descriptor.has_value());
  180. u8 attributes = property_descriptor->is_accessor_descriptor()
  181. ? ~Attribute::Configurable
  182. : ~Attribute::Configurable & ~Attribute::Writable;
  183. update_property(key, attributes);
  184. if (vm.exception())
  185. return {};
  186. }
  187. break;
  188. default:
  189. VERIFY_NOT_REACHED();
  190. }
  191. return true;
  192. }
  193. // 7.3.16 TestIntegrityLevel, https://tc39.es/ecma262/#sec-testintegritylevel
  194. bool Object::test_integrity_level(IntegrityLevel level)
  195. {
  196. auto& vm = this->vm();
  197. auto extensible = is_extensible();
  198. if (vm.exception())
  199. return false;
  200. if (extensible)
  201. return false;
  202. auto keys = get_own_properties(PropertyKind::Key);
  203. if (vm.exception())
  204. return false;
  205. for (auto& key : keys) {
  206. auto property_name = PropertyName::from_value(global_object(), key);
  207. auto property_descriptor = get_own_property_descriptor(property_name);
  208. VERIFY(property_descriptor.has_value());
  209. if (property_descriptor->attributes.is_configurable())
  210. return false;
  211. if (level == IntegrityLevel::Frozen && property_descriptor->is_data_descriptor()) {
  212. if (property_descriptor->attributes.is_writable())
  213. return false;
  214. }
  215. }
  216. return true;
  217. }
  218. Value Object::get_own_property(const PropertyName& property_name, Value receiver, bool without_side_effects) const
  219. {
  220. VERIFY(property_name.is_valid());
  221. VERIFY(!receiver.is_empty());
  222. Value value_here;
  223. if (property_name.is_number()) {
  224. auto existing_property = m_indexed_properties.get(nullptr, property_name.as_number(), false);
  225. if (!existing_property.has_value())
  226. return {};
  227. value_here = existing_property.value().value.value_or(js_undefined());
  228. } else {
  229. auto metadata = shape().lookup(property_name.to_string_or_symbol());
  230. if (!metadata.has_value())
  231. return {};
  232. value_here = m_storage[metadata.value().offset].value_or(js_undefined());
  233. }
  234. VERIFY(!value_here.is_empty());
  235. if (!without_side_effects) {
  236. if (value_here.is_accessor())
  237. return value_here.as_accessor().call_getter(receiver);
  238. if (value_here.is_native_property())
  239. return call_native_property_getter(value_here.as_native_property(), receiver);
  240. }
  241. return value_here;
  242. }
  243. MarkedValueList Object::get_own_properties(PropertyKind kind, bool only_enumerable_properties, GetOwnPropertyReturnType return_type) const
  244. {
  245. MarkedValueList properties(heap());
  246. // FIXME: Support generic iterables
  247. if (is<StringObject>(*this)) {
  248. auto str = static_cast<const StringObject&>(*this).primitive_string().string();
  249. for (size_t i = 0; i < str.length(); ++i) {
  250. if (kind == PropertyKind::Key) {
  251. properties.append(js_string(vm(), String::number(i)));
  252. } else if (kind == PropertyKind::Value) {
  253. properties.append(js_string(vm(), String::formatted("{:c}", str[i])));
  254. } else {
  255. auto* entry_array = Array::create(global_object());
  256. entry_array->define_property(0, js_string(vm(), String::number(i)));
  257. entry_array->define_property(1, js_string(vm(), String::formatted("{:c}", str[i])));
  258. properties.append(entry_array);
  259. }
  260. if (vm().exception())
  261. return MarkedValueList { heap() };
  262. }
  263. return properties;
  264. }
  265. for (auto& entry : m_indexed_properties) {
  266. auto value_and_attributes = entry.value_and_attributes(const_cast<Object*>(this));
  267. if (only_enumerable_properties && !value_and_attributes.attributes.is_enumerable())
  268. continue;
  269. if (kind == PropertyKind::Key) {
  270. properties.append(js_string(vm(), String::number(entry.index())));
  271. } else if (kind == PropertyKind::Value) {
  272. properties.append(value_and_attributes.value);
  273. } else {
  274. auto* entry_array = Array::create(global_object());
  275. entry_array->define_property(0, js_string(vm(), String::number(entry.index())));
  276. entry_array->define_property(1, value_and_attributes.value);
  277. properties.append(entry_array);
  278. }
  279. if (vm().exception())
  280. return MarkedValueList { heap() };
  281. }
  282. auto add_property_to_results = [&](auto& property) {
  283. if (kind == PropertyKind::Key) {
  284. properties.append(property.key.to_value(vm()));
  285. } else if (kind == PropertyKind::Value) {
  286. properties.append(get(property.key));
  287. } else {
  288. auto* entry_array = Array::create(global_object());
  289. entry_array->define_property(0, property.key.to_value(vm()));
  290. entry_array->define_property(1, get(property.key));
  291. properties.append(entry_array);
  292. }
  293. };
  294. // NOTE: Most things including for..in/of and Object.{keys,values,entries}() use StringOnly, and in those
  295. // cases we won't be iterating the ordered property table twice. We can certainly improve this though.
  296. if (return_type == GetOwnPropertyReturnType::All || return_type == GetOwnPropertyReturnType::StringOnly) {
  297. for (auto& it : shape().property_table_ordered()) {
  298. if (only_enumerable_properties && !it.value.attributes.is_enumerable())
  299. continue;
  300. if (it.key.is_symbol())
  301. continue;
  302. add_property_to_results(it);
  303. if (vm().exception())
  304. return MarkedValueList { heap() };
  305. }
  306. }
  307. if (return_type == GetOwnPropertyReturnType::All || return_type == GetOwnPropertyReturnType::SymbolOnly) {
  308. for (auto& it : shape().property_table_ordered()) {
  309. if (only_enumerable_properties && !it.value.attributes.is_enumerable())
  310. continue;
  311. if (it.key.is_string())
  312. continue;
  313. add_property_to_results(it);
  314. if (vm().exception())
  315. return MarkedValueList { heap() };
  316. }
  317. }
  318. return properties;
  319. }
  320. // 7.3.23 EnumerableOwnPropertyNames, https://tc39.es/ecma262/#sec-enumerableownpropertynames
  321. MarkedValueList Object::get_enumerable_own_property_names(PropertyKind kind) const
  322. {
  323. return get_own_properties(kind, true, Object::GetOwnPropertyReturnType::StringOnly);
  324. }
  325. Optional<PropertyDescriptor> Object::get_own_property_descriptor(const PropertyName& property_name) const
  326. {
  327. VERIFY(property_name.is_valid());
  328. Value value;
  329. PropertyAttributes attributes;
  330. if (property_name.is_number()) {
  331. auto existing_value = m_indexed_properties.get(nullptr, property_name.as_number(), false);
  332. if (!existing_value.has_value())
  333. return {};
  334. value = existing_value.value().value;
  335. attributes = existing_value.value().attributes;
  336. attributes = default_attributes;
  337. } else {
  338. auto metadata = shape().lookup(property_name.to_string_or_symbol());
  339. if (!metadata.has_value())
  340. return {};
  341. value = m_storage[metadata.value().offset];
  342. attributes = metadata.value().attributes;
  343. }
  344. PropertyDescriptor descriptor { attributes, {}, nullptr, nullptr };
  345. if (value.is_native_property()) {
  346. auto result = call_native_property_getter(value.as_native_property(), const_cast<Object*>(this));
  347. descriptor.value = result.value_or(js_undefined());
  348. } else if (value.is_accessor()) {
  349. auto& pair = value.as_accessor();
  350. if (pair.getter())
  351. descriptor.getter = pair.getter();
  352. if (pair.setter())
  353. descriptor.setter = pair.setter();
  354. } else {
  355. descriptor.value = value.value_or(js_undefined());
  356. }
  357. return descriptor;
  358. }
  359. Value Object::get_own_property_descriptor_object(const PropertyName& property_name) const
  360. {
  361. VERIFY(property_name.is_valid());
  362. auto& vm = this->vm();
  363. auto descriptor_opt = get_own_property_descriptor(property_name);
  364. if (!descriptor_opt.has_value())
  365. return js_undefined();
  366. auto descriptor = descriptor_opt.value();
  367. auto* descriptor_object = Object::create_empty(global_object());
  368. descriptor_object->define_property(vm.names.enumerable, Value(descriptor.attributes.is_enumerable()));
  369. if (vm.exception())
  370. return {};
  371. descriptor_object->define_property(vm.names.configurable, Value(descriptor.attributes.is_configurable()));
  372. if (vm.exception())
  373. return {};
  374. if (descriptor.is_data_descriptor()) {
  375. descriptor_object->define_property(vm.names.value, descriptor.value.value_or(js_undefined()));
  376. if (vm.exception())
  377. return {};
  378. descriptor_object->define_property(vm.names.writable, Value(descriptor.attributes.is_writable()));
  379. if (vm.exception())
  380. return {};
  381. } else if (descriptor.is_accessor_descriptor()) {
  382. if (descriptor.getter) {
  383. descriptor_object->define_property(vm.names.get, Value(descriptor.getter));
  384. if (vm.exception())
  385. return {};
  386. }
  387. if (descriptor.setter) {
  388. descriptor_object->define_property(vm.names.set, Value(descriptor.setter));
  389. if (vm.exception())
  390. return {};
  391. }
  392. }
  393. return descriptor_object;
  394. }
  395. void Object::set_shape(Shape& new_shape)
  396. {
  397. m_storage.resize(new_shape.property_count());
  398. m_shape = &new_shape;
  399. }
  400. bool Object::define_property(const StringOrSymbol& property_name, const Object& descriptor, bool throw_exceptions)
  401. {
  402. auto& vm = this->vm();
  403. bool is_accessor_property = descriptor.has_property(vm.names.get) || descriptor.has_property(vm.names.set);
  404. PropertyAttributes attributes;
  405. if (descriptor.has_property(vm.names.configurable)) {
  406. attributes.set_has_configurable();
  407. if (descriptor.get(vm.names.configurable).value_or(Value(false)).to_boolean())
  408. attributes.set_configurable();
  409. if (vm.exception())
  410. return false;
  411. }
  412. if (descriptor.has_property(vm.names.enumerable)) {
  413. attributes.set_has_enumerable();
  414. if (descriptor.get(vm.names.enumerable).value_or(Value(false)).to_boolean())
  415. attributes.set_enumerable();
  416. if (vm.exception())
  417. return false;
  418. }
  419. if (is_accessor_property) {
  420. if (descriptor.has_property(vm.names.value) || descriptor.has_property(vm.names.writable)) {
  421. if (throw_exceptions)
  422. vm.throw_exception<TypeError>(global_object(), ErrorType::AccessorValueOrWritable);
  423. return false;
  424. }
  425. auto getter = descriptor.get(vm.names.get).value_or(js_undefined());
  426. if (vm.exception())
  427. return {};
  428. auto setter = descriptor.get(vm.names.set).value_or(js_undefined());
  429. if (vm.exception())
  430. return {};
  431. Function* getter_function { nullptr };
  432. Function* setter_function { nullptr };
  433. if (getter.is_function()) {
  434. getter_function = &getter.as_function();
  435. } else if (!getter.is_undefined()) {
  436. vm.throw_exception<TypeError>(global_object(), ErrorType::AccessorBadField, "get");
  437. return false;
  438. }
  439. if (setter.is_function()) {
  440. setter_function = &setter.as_function();
  441. } else if (!setter.is_undefined()) {
  442. vm.throw_exception<TypeError>(global_object(), ErrorType::AccessorBadField, "set");
  443. return false;
  444. }
  445. #if OBJECT_DEBUG
  446. dbgln("Defining new property {} with accessor descriptor {{ attributes={}, getter={}, setter={} }}", property_name.to_display_string(), attributes, getter, setter);
  447. #endif
  448. return define_property(property_name, Accessor::create(vm, getter_function, setter_function), attributes, throw_exceptions);
  449. }
  450. auto value = descriptor.get(vm.names.value);
  451. if (vm.exception())
  452. return {};
  453. if (descriptor.has_property(vm.names.writable)) {
  454. attributes.set_has_writable();
  455. if (descriptor.get(vm.names.writable).value_or(Value(false)).to_boolean())
  456. attributes.set_writable();
  457. if (vm.exception())
  458. return false;
  459. }
  460. if (vm.exception())
  461. return {};
  462. #if OBJECT_DEBUG
  463. dbgln("Defining new property {} with data descriptor {{ attributes={}, value={} }}", property_name.to_display_string(), attributes, value);
  464. #endif
  465. return define_property(property_name, value, attributes, throw_exceptions);
  466. }
  467. bool Object::define_property_without_transition(const PropertyName& property_name, Value value, PropertyAttributes attributes, bool throw_exceptions)
  468. {
  469. TemporaryChange change(m_transitions_enabled, false);
  470. return define_property(property_name, value, attributes, throw_exceptions);
  471. }
  472. bool Object::define_property(const PropertyName& property_name, Value value, PropertyAttributes attributes, bool throw_exceptions)
  473. {
  474. VERIFY(property_name.is_valid());
  475. if (property_name.is_number())
  476. return put_own_property_by_index(property_name.as_number(), value, attributes, PutOwnPropertyMode::DefineProperty, throw_exceptions);
  477. if (property_name.is_string()) {
  478. i32 property_index = property_name.as_string().to_int().value_or(-1);
  479. if (property_index >= 0)
  480. return put_own_property_by_index(property_index, value, attributes, PutOwnPropertyMode::DefineProperty, throw_exceptions);
  481. }
  482. return put_own_property(property_name.to_string_or_symbol(), value, attributes, PutOwnPropertyMode::DefineProperty, throw_exceptions);
  483. }
  484. bool Object::define_accessor(const PropertyName& property_name, Function* getter, Function* setter, PropertyAttributes attributes, bool throw_exceptions)
  485. {
  486. VERIFY(property_name.is_valid());
  487. Accessor* accessor { nullptr };
  488. auto property_metadata = shape().lookup(property_name.to_string_or_symbol());
  489. if (property_metadata.has_value()) {
  490. auto existing_property = get_direct(property_metadata.value().offset);
  491. if (existing_property.is_accessor())
  492. accessor = &existing_property.as_accessor();
  493. }
  494. if (!accessor) {
  495. accessor = Accessor::create(vm(), getter, setter);
  496. bool definition_success = define_property(property_name, accessor, attributes, throw_exceptions);
  497. if (vm().exception())
  498. return {};
  499. if (!definition_success)
  500. return false;
  501. } else {
  502. if (getter)
  503. accessor->set_getter(getter);
  504. if (setter)
  505. accessor->set_setter(setter);
  506. }
  507. return true;
  508. }
  509. bool Object::put_own_property(const StringOrSymbol& property_name, Value value, PropertyAttributes attributes, PutOwnPropertyMode mode, bool throw_exceptions)
  510. {
  511. VERIFY(!(mode == PutOwnPropertyMode::Put && value.is_accessor()));
  512. if (value.is_accessor()) {
  513. auto& accessor = value.as_accessor();
  514. if (accessor.getter())
  515. attributes.set_has_getter();
  516. if (accessor.setter())
  517. attributes.set_has_setter();
  518. }
  519. // NOTE: We disable transitions during initialize(), this makes building common runtime objects significantly faster.
  520. // Transitions are primarily interesting when scripts add properties to objects.
  521. if (!m_transitions_enabled && !m_shape->is_unique()) {
  522. m_shape->add_property_without_transition(property_name, attributes);
  523. m_storage.resize(m_shape->property_count());
  524. m_storage[m_shape->property_count() - 1] = value;
  525. return true;
  526. }
  527. auto metadata = shape().lookup(property_name);
  528. bool new_property = !metadata.has_value();
  529. if (!is_extensible() && new_property) {
  530. #if OBJECT_DEBUG
  531. dbgln("Disallow define_property of non-extensible object");
  532. #endif
  533. if (throw_exceptions && vm().in_strict_mode())
  534. vm().throw_exception<TypeError>(global_object(), ErrorType::NonExtensibleDefine, property_name.to_display_string());
  535. return false;
  536. }
  537. if (new_property) {
  538. if (!m_shape->is_unique() && shape().property_count() > 100) {
  539. // If you add more than 100 properties to an object, let's stop doing
  540. // transitions to avoid filling up the heap with shapes.
  541. ensure_shape_is_unique();
  542. }
  543. if (m_shape->is_unique()) {
  544. m_shape->add_property_to_unique_shape(property_name, attributes);
  545. m_storage.resize(m_shape->property_count());
  546. } else if (m_transitions_enabled) {
  547. set_shape(*m_shape->create_put_transition(property_name, attributes));
  548. } else {
  549. m_shape->add_property_without_transition(property_name, attributes);
  550. m_storage.resize(m_shape->property_count());
  551. }
  552. metadata = shape().lookup(property_name);
  553. VERIFY(metadata.has_value());
  554. }
  555. if (!new_property && mode == PutOwnPropertyMode::DefineProperty && !metadata.value().attributes.is_configurable() && attributes != metadata.value().attributes) {
  556. #if OBJECT_DEBUG
  557. dbgln("Disallow reconfig of non-configurable property");
  558. #endif
  559. if (throw_exceptions)
  560. vm().throw_exception<TypeError>(global_object(), ErrorType::DescChangeNonConfigurable, property_name.to_display_string());
  561. return false;
  562. }
  563. if (mode == PutOwnPropertyMode::DefineProperty && attributes != metadata.value().attributes) {
  564. if (m_shape->is_unique()) {
  565. m_shape->reconfigure_property_in_unique_shape(property_name, attributes);
  566. } else {
  567. set_shape(*m_shape->create_configure_transition(property_name, attributes));
  568. }
  569. metadata = shape().lookup(property_name);
  570. #if OBJECT_DEBUG
  571. dbgln("Reconfigured property {}, new shape says offset is {} and my storage capacity is {}", property_name.to_display_string(), metadata.value().offset, m_storage.size());
  572. #endif
  573. }
  574. auto value_here = m_storage[metadata.value().offset];
  575. if (!new_property && mode == PutOwnPropertyMode::Put && !value_here.is_accessor() && !metadata.value().attributes.is_writable()) {
  576. #if OBJECT_DEBUG
  577. dbgln("Disallow write to non-writable property");
  578. #endif
  579. return false;
  580. }
  581. if (value.is_empty())
  582. return true;
  583. if (value_here.is_native_property()) {
  584. call_native_property_setter(value_here.as_native_property(), this, value);
  585. } else {
  586. m_storage[metadata.value().offset] = value;
  587. }
  588. return true;
  589. }
  590. bool Object::put_own_property_by_index(u32 property_index, Value value, PropertyAttributes attributes, PutOwnPropertyMode mode, bool throw_exceptions)
  591. {
  592. VERIFY(!(mode == PutOwnPropertyMode::Put && value.is_accessor()));
  593. auto existing_property = m_indexed_properties.get(nullptr, property_index, false);
  594. auto new_property = !existing_property.has_value();
  595. if (!is_extensible() && new_property) {
  596. #if OBJECT_DEBUG
  597. dbgln("Disallow define_property of non-extensible object");
  598. #endif
  599. if (throw_exceptions && vm().in_strict_mode())
  600. vm().throw_exception<TypeError>(global_object(), ErrorType::NonExtensibleDefine, property_index);
  601. return false;
  602. }
  603. if (value.is_accessor()) {
  604. auto& accessor = value.as_accessor();
  605. if (accessor.getter())
  606. attributes.set_has_getter();
  607. if (accessor.setter())
  608. attributes.set_has_setter();
  609. }
  610. PropertyAttributes existing_attributes = new_property ? 0 : existing_property.value().attributes;
  611. if (!new_property && mode == PutOwnPropertyMode::DefineProperty && !existing_attributes.is_configurable() && attributes != existing_attributes) {
  612. #if OBJECT_DEBUG
  613. dbgln("Disallow reconfig of non-configurable property");
  614. #endif
  615. if (throw_exceptions)
  616. vm().throw_exception<TypeError>(global_object(), ErrorType::DescChangeNonConfigurable, property_index);
  617. return false;
  618. }
  619. auto value_here = new_property ? Value() : existing_property.value().value;
  620. if (!new_property && mode == PutOwnPropertyMode::Put && !value_here.is_accessor() && !existing_attributes.is_writable()) {
  621. #if OBJECT_DEBUG
  622. dbgln("Disallow write to non-writable property");
  623. #endif
  624. return false;
  625. }
  626. if (value.is_empty())
  627. return true;
  628. if (value_here.is_native_property()) {
  629. call_native_property_setter(value_here.as_native_property(), this, value);
  630. } else {
  631. m_indexed_properties.put(this, property_index, value, attributes, mode == PutOwnPropertyMode::Put);
  632. }
  633. return true;
  634. }
  635. bool Object::delete_property(const PropertyName& property_name)
  636. {
  637. VERIFY(property_name.is_valid());
  638. if (property_name.is_number())
  639. return m_indexed_properties.remove(property_name.as_number());
  640. if (property_name.is_string()) {
  641. i32 property_index = property_name.as_string().to_int().value_or(-1);
  642. if (property_index >= 0)
  643. return m_indexed_properties.remove(property_index);
  644. }
  645. auto metadata = shape().lookup(property_name.to_string_or_symbol());
  646. if (!metadata.has_value())
  647. return true;
  648. if (!metadata.value().attributes.is_configurable())
  649. return false;
  650. size_t deleted_offset = metadata.value().offset;
  651. ensure_shape_is_unique();
  652. shape().remove_property_from_unique_shape(property_name.to_string_or_symbol(), deleted_offset);
  653. m_storage.remove(deleted_offset);
  654. return true;
  655. }
  656. void Object::ensure_shape_is_unique()
  657. {
  658. if (shape().is_unique())
  659. return;
  660. m_shape = m_shape->create_unique_clone();
  661. }
  662. Value Object::get_by_index(u32 property_index) const
  663. {
  664. const Object* object = this;
  665. while (object) {
  666. if (is<StringObject>(*object)) {
  667. auto& string = static_cast<const StringObject&>(*object).primitive_string().string();
  668. if (property_index < string.length())
  669. return js_string(heap(), string.substring(property_index, 1));
  670. } else if (static_cast<size_t>(property_index) < object->m_indexed_properties.array_like_size()) {
  671. auto result = object->m_indexed_properties.get(const_cast<Object*>(this), property_index);
  672. if (vm().exception())
  673. return {};
  674. if (result.has_value() && !result.value().value.is_empty())
  675. return result.value().value;
  676. }
  677. object = object->prototype();
  678. if (vm().exception())
  679. return {};
  680. }
  681. return {};
  682. }
  683. Value Object::get(const PropertyName& property_name, Value receiver, bool without_side_effects) const
  684. {
  685. VERIFY(property_name.is_valid());
  686. if (property_name.is_number())
  687. return get_by_index(property_name.as_number());
  688. if (property_name.is_string()) {
  689. auto property_string = property_name.to_string();
  690. i32 property_index = property_string.to_int().value_or(-1);
  691. if (property_index >= 0)
  692. return get_by_index(property_index);
  693. }
  694. if (receiver.is_empty())
  695. receiver = Value(this);
  696. const Object* object = this;
  697. while (object) {
  698. auto value = object->get_own_property(property_name, receiver, without_side_effects);
  699. if (vm().exception())
  700. return {};
  701. if (!value.is_empty())
  702. return value;
  703. object = object->prototype();
  704. if (vm().exception())
  705. return {};
  706. }
  707. return {};
  708. }
  709. Value Object::get_without_side_effects(const PropertyName& property_name) const
  710. {
  711. return get(property_name, {}, true);
  712. }
  713. bool Object::put_by_index(u32 property_index, Value value)
  714. {
  715. VERIFY(!value.is_empty());
  716. // If there's a setter in the prototype chain, we go to the setter.
  717. // Otherwise, it goes in the own property storage.
  718. Object* object = this;
  719. while (object) {
  720. auto existing_value = object->m_indexed_properties.get(nullptr, property_index, false);
  721. if (existing_value.has_value()) {
  722. auto value_here = existing_value.value();
  723. if (value_here.value.is_accessor()) {
  724. value_here.value.as_accessor().call_setter(object, value);
  725. return true;
  726. }
  727. if (value_here.value.is_native_property()) {
  728. // FIXME: Why doesn't put_by_index() receive the receiver value from put()?!
  729. auto receiver = this;
  730. call_native_property_setter(value_here.value.as_native_property(), receiver, value);
  731. return true;
  732. }
  733. }
  734. object = object->prototype();
  735. if (vm().exception())
  736. return {};
  737. }
  738. return put_own_property_by_index(property_index, value, default_attributes, PutOwnPropertyMode::Put);
  739. }
  740. bool Object::put(const PropertyName& property_name, Value value, Value receiver)
  741. {
  742. VERIFY(property_name.is_valid());
  743. if (property_name.is_number())
  744. return put_by_index(property_name.as_number(), value);
  745. VERIFY(!value.is_empty());
  746. if (property_name.is_string()) {
  747. auto& property_string = property_name.as_string();
  748. i32 property_index = property_string.to_int().value_or(-1);
  749. if (property_index >= 0)
  750. return put_by_index(property_index, value);
  751. }
  752. auto string_or_symbol = property_name.to_string_or_symbol();
  753. if (receiver.is_empty())
  754. receiver = Value(this);
  755. // If there's a setter in the prototype chain, we go to the setter.
  756. // Otherwise, it goes in the own property storage.
  757. Object* object = this;
  758. while (object) {
  759. auto metadata = object->shape().lookup(string_or_symbol);
  760. if (metadata.has_value()) {
  761. auto value_here = object->m_storage[metadata.value().offset];
  762. if (value_here.is_accessor()) {
  763. value_here.as_accessor().call_setter(receiver, value);
  764. return true;
  765. }
  766. if (value_here.is_native_property()) {
  767. call_native_property_setter(value_here.as_native_property(), receiver, value);
  768. return true;
  769. }
  770. }
  771. object = object->prototype();
  772. if (vm().exception())
  773. return false;
  774. }
  775. return put_own_property(string_or_symbol, value, default_attributes, PutOwnPropertyMode::Put);
  776. }
  777. bool Object::define_native_function(const StringOrSymbol& property_name, AK::Function<Value(VM&, GlobalObject&)> native_function, i32 length, PropertyAttributes attribute)
  778. {
  779. auto& vm = this->vm();
  780. String function_name;
  781. if (property_name.is_string()) {
  782. function_name = property_name.as_string();
  783. } else {
  784. function_name = String::formatted("[{}]", property_name.as_symbol()->description());
  785. }
  786. auto* function = NativeFunction::create(global_object(), function_name, move(native_function));
  787. function->define_property_without_transition(vm.names.length, Value(length), Attribute::Configurable);
  788. if (vm.exception())
  789. return {};
  790. function->define_property_without_transition(vm.names.name, js_string(vm.heap(), function_name), Attribute::Configurable);
  791. if (vm.exception())
  792. return {};
  793. return define_property(property_name, function, attribute);
  794. }
  795. bool Object::define_native_property(const StringOrSymbol& property_name, AK::Function<Value(VM&, GlobalObject&)> getter, AK::Function<void(VM&, GlobalObject&, Value)> setter, PropertyAttributes attribute)
  796. {
  797. return define_property(property_name, heap().allocate_without_global_object<NativeProperty>(move(getter), move(setter)), attribute);
  798. }
  799. // 20.1.2.3.1 ObjectDefineProperties, https://tc39.es/ecma262/#sec-objectdefineproperties
  800. void Object::define_properties(Value properties)
  801. {
  802. auto& vm = this->vm();
  803. auto* props = properties.to_object(global_object());
  804. if (!props)
  805. return;
  806. auto keys = props->get_own_properties(PropertyKind::Key);
  807. if (vm.exception())
  808. return;
  809. struct NameAndDescriptor {
  810. PropertyName name;
  811. PropertyDescriptor descriptor;
  812. };
  813. Vector<NameAndDescriptor> descriptors;
  814. for (auto& key : keys) {
  815. auto property_name = PropertyName::from_value(global_object(), key);
  816. auto property_descriptor = props->get_own_property_descriptor(property_name);
  817. if (property_descriptor.has_value() && property_descriptor->attributes.is_enumerable()) {
  818. auto descriptor_object = props->get(property_name);
  819. if (vm.exception())
  820. return;
  821. if (!descriptor_object.is_object()) {
  822. vm.throw_exception<TypeError>(global_object(), ErrorType::NotAnObject, descriptor_object.to_string_without_side_effects());
  823. return;
  824. }
  825. auto descriptor = PropertyDescriptor::from_dictionary(vm, descriptor_object.as_object());
  826. if (vm.exception())
  827. return;
  828. descriptors.append({ property_name, descriptor });
  829. }
  830. }
  831. for (auto& [name, descriptor] : descriptors) {
  832. // FIXME: The spec has both of this handled by DefinePropertyOrThrow(O, P, desc).
  833. // We should invest some time in improving object property handling, it not being
  834. // super close to the spec makes this and other things unnecessarily complicated.
  835. if (descriptor.is_accessor_descriptor())
  836. define_accessor(name, descriptor.getter, descriptor.setter, descriptor.attributes);
  837. else
  838. define_property(name, descriptor.value, descriptor.attributes);
  839. }
  840. }
  841. void Object::visit_edges(Cell::Visitor& visitor)
  842. {
  843. Cell::visit_edges(visitor);
  844. visitor.visit(m_shape);
  845. for (auto& value : m_storage)
  846. visitor.visit(value);
  847. m_indexed_properties.for_each_value([&visitor](auto& value) {
  848. visitor.visit(value);
  849. });
  850. }
  851. bool Object::has_property(const PropertyName& property_name) const
  852. {
  853. const Object* object = this;
  854. while (object) {
  855. if (object->has_own_property(property_name))
  856. return true;
  857. object = object->prototype();
  858. if (vm().exception())
  859. return false;
  860. }
  861. return false;
  862. }
  863. bool Object::has_own_property(const PropertyName& property_name) const
  864. {
  865. VERIFY(property_name.is_valid());
  866. auto has_indexed_property = [&](u32 index) -> bool {
  867. if (is<StringObject>(*this))
  868. return index < static_cast<const StringObject*>(this)->primitive_string().string().length();
  869. return m_indexed_properties.has_index(index);
  870. };
  871. if (property_name.is_number())
  872. return has_indexed_property(property_name.as_number());
  873. if (property_name.is_string()) {
  874. i32 property_index = property_name.as_string().to_int().value_or(-1);
  875. if (property_index >= 0)
  876. return has_indexed_property(property_index);
  877. }
  878. return shape().lookup(property_name.to_string_or_symbol()).has_value();
  879. }
  880. Value Object::ordinary_to_primitive(Value::PreferredType preferred_type) const
  881. {
  882. VERIFY(preferred_type == Value::PreferredType::String || preferred_type == Value::PreferredType::Number);
  883. auto& vm = this->vm();
  884. Vector<FlyString, 2> method_names;
  885. if (preferred_type == Value::PreferredType::String)
  886. method_names = { vm.names.toString, vm.names.valueOf };
  887. else
  888. method_names = { vm.names.valueOf, vm.names.toString };
  889. for (auto& method_name : method_names) {
  890. auto method = get(method_name);
  891. if (vm.exception())
  892. return {};
  893. if (method.is_function()) {
  894. auto result = vm.call(method.as_function(), const_cast<Object*>(this));
  895. if (!result.is_object())
  896. return result;
  897. }
  898. }
  899. vm.throw_exception<TypeError>(global_object(), ErrorType::Convert, "object", preferred_type == Value::PreferredType::String ? "string" : "number");
  900. return {};
  901. }
  902. Value Object::invoke_internal(const StringOrSymbol& property_name, Optional<MarkedValueList> arguments)
  903. {
  904. auto& vm = this->vm();
  905. auto property = get(property_name).value_or(js_undefined());
  906. if (vm.exception())
  907. return {};
  908. if (!property.is_function()) {
  909. vm.throw_exception<TypeError>(global_object(), ErrorType::NotAFunction, property.to_string_without_side_effects());
  910. return {};
  911. }
  912. return vm.call(property.as_function(), this, move(arguments));
  913. }
  914. Value Object::call_native_property_getter(NativeProperty& property, Value this_value) const
  915. {
  916. auto& vm = this->vm();
  917. CallFrame call_frame;
  918. if (auto* interpreter = vm.interpreter_if_exists())
  919. call_frame.current_node = interpreter->current_node();
  920. call_frame.is_strict_mode = vm.in_strict_mode();
  921. call_frame.this_value = this_value;
  922. vm.push_call_frame(call_frame, global_object());
  923. if (vm.exception())
  924. return {};
  925. auto result = property.get(vm, global_object());
  926. vm.pop_call_frame();
  927. return result;
  928. }
  929. void Object::call_native_property_setter(NativeProperty& property, Value this_value, Value setter_value) const
  930. {
  931. auto& vm = this->vm();
  932. CallFrame call_frame;
  933. if (auto* interpreter = vm.interpreter_if_exists())
  934. call_frame.current_node = interpreter->current_node();
  935. call_frame.is_strict_mode = vm.in_strict_mode();
  936. call_frame.this_value = this_value;
  937. vm.push_call_frame(call_frame, global_object());
  938. if (vm.exception())
  939. return;
  940. property.set(vm, global_object(), setter_value);
  941. vm.pop_call_frame();
  942. }
  943. }