AbstractOperations.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. /*
  2. * Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
  3. * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/CharacterTypes.h>
  8. #include <AK/Function.h>
  9. #include <AK/Optional.h>
  10. #include <AK/TemporaryChange.h>
  11. #include <AK/Utf16View.h>
  12. #include <LibJS/Interpreter.h>
  13. #include <LibJS/Parser.h>
  14. #include <LibJS/Runtime/AbstractOperations.h>
  15. #include <LibJS/Runtime/Accessor.h>
  16. #include <LibJS/Runtime/ArgumentsObject.h>
  17. #include <LibJS/Runtime/Array.h>
  18. #include <LibJS/Runtime/BoundFunction.h>
  19. #include <LibJS/Runtime/Completion.h>
  20. #include <LibJS/Runtime/DeclarativeEnvironment.h>
  21. #include <LibJS/Runtime/ErrorTypes.h>
  22. #include <LibJS/Runtime/FunctionEnvironment.h>
  23. #include <LibJS/Runtime/FunctionObject.h>
  24. #include <LibJS/Runtime/GlobalObject.h>
  25. #include <LibJS/Runtime/Object.h>
  26. #include <LibJS/Runtime/ObjectEnvironment.h>
  27. #include <LibJS/Runtime/PropertyDescriptor.h>
  28. #include <LibJS/Runtime/PropertyName.h>
  29. #include <LibJS/Runtime/ProxyObject.h>
  30. #include <LibJS/Runtime/Reference.h>
  31. namespace JS {
  32. // 7.2.1 RequireObjectCoercible ( argument ), https://tc39.es/ecma262/#sec-requireobjectcoercible
  33. ThrowCompletionOr<Value> require_object_coercible(GlobalObject& global_object, Value value)
  34. {
  35. auto& vm = global_object.vm();
  36. if (value.is_nullish())
  37. return vm.throw_completion<TypeError>(global_object, ErrorType::NotObjectCoercible, value.to_string_without_side_effects());
  38. return value;
  39. }
  40. // 7.3.18 LengthOfArrayLike ( obj ), https://tc39.es/ecma262/#sec-lengthofarraylike
  41. ThrowCompletionOr<size_t> length_of_array_like(GlobalObject& global_object, Object const& object)
  42. {
  43. auto& vm = global_object.vm();
  44. auto result = object.get(vm.names.length);
  45. if (auto* exception = vm.exception())
  46. return throw_completion(exception->value());
  47. auto length = result.to_length(global_object);
  48. if (auto* exception = vm.exception())
  49. return throw_completion(exception->value());
  50. return length;
  51. }
  52. // 7.3.19 CreateListFromArrayLike ( obj [ , elementTypes ] ), https://tc39.es/ecma262/#sec-createlistfromarraylike
  53. ThrowCompletionOr<MarkedValueList> create_list_from_array_like(GlobalObject& global_object, Value value, Function<ThrowCompletionOr<void>(Value)> check_value)
  54. {
  55. auto& vm = global_object.vm();
  56. auto& heap = global_object.heap();
  57. // 1. If elementTypes is not present, set elementTypes to « Undefined, Null, Boolean, String, Symbol, Number, BigInt, Object ».
  58. // 2. If Type(obj) is not Object, throw a TypeError exception.
  59. if (!value.is_object())
  60. return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObject, value.to_string_without_side_effects());
  61. auto& array_like = value.as_object();
  62. // 3. Let len be ? LengthOfArrayLike(obj).
  63. auto length = TRY(length_of_array_like(global_object, array_like));
  64. // 4. Let list be a new empty List.
  65. auto list = MarkedValueList { heap };
  66. // 5. Let index be 0.
  67. // 6. Repeat, while index < len,
  68. for (size_t i = 0; i < length; ++i) {
  69. // a. Let indexName be ! ToString(𝔽(index)).
  70. auto index_name = String::number(i);
  71. // b. Let next be ? Get(obj, indexName).
  72. auto next = array_like.get(index_name);
  73. if (auto* exception = vm.exception())
  74. return throw_completion(exception->value());
  75. // c. If Type(next) is not an element of elementTypes, throw a TypeError exception.
  76. if (check_value)
  77. TRY(check_value(next));
  78. // d. Append next as the last element of list.
  79. list.append(next);
  80. }
  81. // 7. Return list.
  82. return ThrowCompletionOr(move(list));
  83. }
  84. // 7.3.22 SpeciesConstructor ( O, defaultConstructor ), https://tc39.es/ecma262/#sec-speciesconstructor
  85. ThrowCompletionOr<FunctionObject*> species_constructor(GlobalObject& global_object, Object const& object, FunctionObject& default_constructor)
  86. {
  87. auto& vm = global_object.vm();
  88. // 1. Let C be ? Get(O, "constructor").
  89. auto constructor = object.get(vm.names.constructor);
  90. if (auto* exception = vm.exception())
  91. return throw_completion(exception->value());
  92. // 2. If C is undefined, return defaultConstructor.
  93. if (constructor.is_undefined())
  94. return &default_constructor;
  95. // 3. If Type(C) is not Object, throw a TypeError exception.
  96. if (!constructor.is_object())
  97. return vm.throw_completion<TypeError>(global_object, ErrorType::NotAConstructor, constructor.to_string_without_side_effects());
  98. // 4. Let S be ? Get(C, @@species).
  99. auto species = constructor.as_object().get(*vm.well_known_symbol_species());
  100. if (auto* exception = vm.exception())
  101. return throw_completion(exception->value());
  102. // 5. If S is either undefined or null, return defaultConstructor.
  103. if (species.is_nullish())
  104. return &default_constructor;
  105. // 6. If IsConstructor(S) is true, return S.
  106. if (species.is_constructor())
  107. return &species.as_function();
  108. // 7. Throw a TypeError exception.
  109. return vm.throw_completion<TypeError>(global_object, ErrorType::NotAConstructor, species.to_string_without_side_effects());
  110. }
  111. // 7.3.24 GetFunctionRealm ( obj ), https://tc39.es/ecma262/#sec-getfunctionrealm
  112. ThrowCompletionOr<Realm*> get_function_realm(GlobalObject& global_object, FunctionObject const& function)
  113. {
  114. auto& vm = global_object.vm();
  115. // 1. Assert: ! IsCallable(obj) is true.
  116. // 2. If obj has a [[Realm]] internal slot, then
  117. if (function.realm()) {
  118. // a. Return obj.[[Realm]].
  119. return function.realm();
  120. }
  121. // 3. If obj is a bound function exotic object, then
  122. if (is<BoundFunction>(function)) {
  123. auto& bound_function = static_cast<BoundFunction const&>(function);
  124. // a. Let target be obj.[[BoundTargetFunction]].
  125. auto& target = bound_function.target_function();
  126. // b. Return ? GetFunctionRealm(target).
  127. return get_function_realm(global_object, target);
  128. }
  129. // 4. If obj is a Proxy exotic object, then
  130. if (is<ProxyObject>(function)) {
  131. auto& proxy = static_cast<ProxyObject const&>(function);
  132. // a. If obj.[[ProxyHandler]] is null, throw a TypeError exception.
  133. if (proxy.is_revoked())
  134. return vm.throw_completion<TypeError>(global_object, ErrorType::ProxyRevoked);
  135. // b. Let proxyTarget be obj.[[ProxyTarget]].
  136. auto& proxy_target = proxy.target();
  137. // c. Return ? GetFunctionRealm(proxyTarget).
  138. VERIFY(proxy_target.is_function());
  139. return get_function_realm(global_object, static_cast<FunctionObject const&>(proxy_target));
  140. }
  141. // 5. Return the current Realm Record.
  142. return vm.current_realm();
  143. }
  144. // 10.1.6.2 IsCompatiblePropertyDescriptor ( Extensible, Desc, Current ), https://tc39.es/ecma262/#sec-iscompatiblepropertydescriptor
  145. bool is_compatible_property_descriptor(bool extensible, PropertyDescriptor const& descriptor, Optional<PropertyDescriptor> const& current)
  146. {
  147. // 1. Return ValidateAndApplyPropertyDescriptor(undefined, undefined, Extensible, Desc, Current).
  148. return validate_and_apply_property_descriptor(nullptr, {}, extensible, descriptor, current);
  149. }
  150. // 10.1.6.3 ValidateAndApplyPropertyDescriptor ( O, P, extensible, Desc, current ), https://tc39.es/ecma262/#sec-validateandapplypropertydescriptor
  151. bool validate_and_apply_property_descriptor(Object* object, PropertyName const& property_name, bool extensible, PropertyDescriptor const& descriptor, Optional<PropertyDescriptor> const& current)
  152. {
  153. // 1. Assert: If O is not undefined, then IsPropertyKey(P) is true.
  154. if (object)
  155. VERIFY(property_name.is_valid());
  156. // 2. If current is undefined, then
  157. if (!current.has_value()) {
  158. // a. If extensible is false, return false.
  159. if (!extensible)
  160. return false;
  161. // b. Assert: extensible is true.
  162. // c. If IsGenericDescriptor(Desc) is true or IsDataDescriptor(Desc) is true, then
  163. if (descriptor.is_generic_descriptor() || descriptor.is_data_descriptor()) {
  164. // i. If O is not undefined, create an own data property named P of object O whose [[Value]], [[Writable]],
  165. // [[Enumerable]], and [[Configurable]] attribute values are described by Desc.
  166. // If the value of an attribute field of Desc is absent, the attribute of the newly created property is set
  167. // to its default value.
  168. if (object) {
  169. auto value = descriptor.value.value_or(js_undefined());
  170. object->storage_set(property_name, { value, descriptor.attributes() });
  171. }
  172. }
  173. // d. Else,
  174. else {
  175. // i. Assert: ! IsAccessorDescriptor(Desc) is true.
  176. VERIFY(descriptor.is_accessor_descriptor());
  177. // ii. If O is not undefined, create an own accessor property named P of object O whose [[Get]], [[Set]],
  178. // [[Enumerable]], and [[Configurable]] attribute values are described by Desc.
  179. // If the value of an attribute field of Desc is absent, the attribute of the newly created property is set
  180. // to its default value.
  181. if (object) {
  182. auto accessor = Accessor::create(object->vm(), descriptor.get.value_or(nullptr), descriptor.set.value_or(nullptr));
  183. object->storage_set(property_name, { accessor, descriptor.attributes() });
  184. }
  185. }
  186. // e. Return true.
  187. return true;
  188. }
  189. // 3. If every field in Desc is absent, return true.
  190. if (descriptor.is_empty())
  191. return true;
  192. // 4. If current.[[Configurable]] is false, then
  193. if (!*current->configurable) {
  194. // a. If Desc.[[Configurable]] is present and its value is true, return false.
  195. if (descriptor.configurable.has_value() && *descriptor.configurable)
  196. return false;
  197. // b. If Desc.[[Enumerable]] is present and ! SameValue(Desc.[[Enumerable]], current.[[Enumerable]]) is false, return false.
  198. if (descriptor.enumerable.has_value() && *descriptor.enumerable != *current->enumerable)
  199. return false;
  200. }
  201. // 5. If ! IsGenericDescriptor(Desc) is true, then
  202. if (descriptor.is_generic_descriptor()) {
  203. // a. NOTE: No further validation is required.
  204. }
  205. // 6. Else if ! SameValue(! IsDataDescriptor(current), ! IsDataDescriptor(Desc)) is false, then
  206. else if (current->is_data_descriptor() != descriptor.is_data_descriptor()) {
  207. // a. If current.[[Configurable]] is false, return false.
  208. if (!*current->configurable)
  209. return false;
  210. // b. If IsDataDescriptor(current) is true, then
  211. if (current->is_data_descriptor()) {
  212. // If O is not undefined, convert the property named P of object O from a data property to an accessor property.
  213. // Preserve the existing values of the converted property's [[Configurable]] and [[Enumerable]] attributes and
  214. // set the rest of the property's attributes to their default values.
  215. if (object) {
  216. auto accessor = Accessor::create(object->vm(), nullptr, nullptr);
  217. object->storage_set(property_name, { accessor, current->attributes() });
  218. }
  219. }
  220. // c. Else,
  221. else {
  222. // If O is not undefined, convert the property named P of object O from an accessor property to a data property.
  223. // Preserve the existing values of the converted property's [[Configurable]] and [[Enumerable]] attributes and
  224. // set the rest of the property's attributes to their default values.
  225. if (object) {
  226. auto value = js_undefined();
  227. object->storage_set(property_name, { value, current->attributes() });
  228. }
  229. }
  230. }
  231. // 7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both true, then
  232. else if (current->is_data_descriptor() && descriptor.is_data_descriptor()) {
  233. // a. If current.[[Configurable]] is false and current.[[Writable]] is false, then
  234. if (!*current->configurable && !*current->writable) {
  235. // i. If Desc.[[Writable]] is present and Desc.[[Writable]] is true, return false.
  236. if (descriptor.writable.has_value() && *descriptor.writable)
  237. return false;
  238. // ii. If Desc.[[Value]] is present and SameValue(Desc.[[Value]], current.[[Value]]) is false, return false.
  239. if (descriptor.value.has_value() && !same_value(*descriptor.value, *current->value))
  240. return false;
  241. // iii. Return true.
  242. return true;
  243. }
  244. }
  245. // 8. Else,
  246. else {
  247. // a. Assert: ! IsAccessorDescriptor(current) and ! IsAccessorDescriptor(Desc) are both true.
  248. VERIFY(current->is_accessor_descriptor());
  249. VERIFY(descriptor.is_accessor_descriptor());
  250. // b. If current.[[Configurable]] is false, then
  251. if (!*current->configurable) {
  252. // i. If Desc.[[Set]] is present and SameValue(Desc.[[Set]], current.[[Set]]) is false, return false.
  253. if (descriptor.set.has_value() && *descriptor.set != *current->set)
  254. return false;
  255. // ii. If Desc.[[Get]] is present and SameValue(Desc.[[Get]], current.[[Get]]) is false, return false.
  256. if (descriptor.get.has_value() && *descriptor.get != *current->get)
  257. return false;
  258. // iii. Return true.
  259. return true;
  260. }
  261. }
  262. // 9. If O is not undefined, then
  263. if (object) {
  264. // a. For each field of Desc that is present, set the corresponding attribute of the property named P of object O to the value of the field.
  265. Value value;
  266. if (descriptor.is_accessor_descriptor() || (current->is_accessor_descriptor() && !descriptor.is_data_descriptor())) {
  267. auto* getter = descriptor.get.value_or(current->get.value_or(nullptr));
  268. auto* setter = descriptor.set.value_or(current->set.value_or(nullptr));
  269. value = Accessor::create(object->vm(), getter, setter);
  270. } else {
  271. value = descriptor.value.value_or(current->value.value_or({}));
  272. }
  273. PropertyAttributes attributes;
  274. attributes.set_writable(descriptor.writable.value_or(current->writable.value_or(false)));
  275. attributes.set_enumerable(descriptor.enumerable.value_or(current->enumerable.value_or(false)));
  276. attributes.set_configurable(descriptor.configurable.value_or(current->configurable.value_or(false)));
  277. object->storage_set(property_name, { value, attributes });
  278. }
  279. // 10. Return true.
  280. return true;
  281. }
  282. // 10.1.14 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ), https://tc39.es/ecma262/#sec-getprototypefromconstructor
  283. ThrowCompletionOr<Object*> get_prototype_from_constructor(GlobalObject& global_object, FunctionObject const& constructor, Object* (GlobalObject::*intrinsic_default_prototype)())
  284. {
  285. auto& vm = global_object.vm();
  286. // 1. Assert: intrinsicDefaultProto is this specification's name of an intrinsic object. The corresponding object must be an intrinsic that is intended to be used as the [[Prototype]] value of an object.
  287. // 2. Let proto be ? Get(constructor, "prototype").
  288. auto prototype = constructor.get(vm.names.prototype);
  289. if (auto* exception = vm.exception())
  290. return throw_completion(exception->value());
  291. // 3. If Type(proto) is not Object, then
  292. if (!prototype.is_object()) {
  293. // a. Let realm be ? GetFunctionRealm(constructor).
  294. auto* realm = TRY(get_function_realm(global_object, constructor));
  295. // b. Set proto to realm's intrinsic object named intrinsicDefaultProto.
  296. prototype = (realm->global_object().*intrinsic_default_prototype)();
  297. }
  298. // 4. Return proto.
  299. return &prototype.as_object();
  300. }
  301. // 9.1.2.2 NewDeclarativeEnvironment ( E ), https://tc39.es/ecma262/#sec-newdeclarativeenvironment
  302. DeclarativeEnvironment* new_declarative_environment(Environment& environment)
  303. {
  304. auto& global_object = environment.global_object();
  305. return global_object.heap().allocate<DeclarativeEnvironment>(global_object, &environment);
  306. }
  307. // 9.1.2.3 NewObjectEnvironment ( O, W, E ), https://tc39.es/ecma262/#sec-newobjectenvironment
  308. ObjectEnvironment* new_object_environment(Object& object, bool is_with_environment, Environment* environment)
  309. {
  310. auto& global_object = object.global_object();
  311. return global_object.heap().allocate<ObjectEnvironment>(global_object, object, is_with_environment ? ObjectEnvironment::IsWithEnvironment::Yes : ObjectEnvironment::IsWithEnvironment::No, environment);
  312. }
  313. // 9.4.3 GetThisEnvironment ( ), https://tc39.es/ecma262/#sec-getthisenvironment
  314. Environment& get_this_environment(VM& vm)
  315. {
  316. for (auto* env = vm.lexical_environment(); env; env = env->outer_environment()) {
  317. if (env->has_this_binding())
  318. return *env;
  319. }
  320. VERIFY_NOT_REACHED();
  321. }
  322. // 13.3.7.2 GetSuperConstructor ( ), https://tc39.es/ecma262/#sec-getsuperconstructor
  323. Object* get_super_constructor(VM& vm)
  324. {
  325. auto& env = get_this_environment(vm);
  326. auto& active_function = verify_cast<FunctionEnvironment>(env).function_object();
  327. auto* super_constructor = active_function.internal_get_prototype_of();
  328. return super_constructor;
  329. }
  330. // 13.3.7.3 MakeSuperPropertyReference ( actualThis, propertyKey, strict ), https://tc39.es/ecma262/#sec-makesuperpropertyreference
  331. ThrowCompletionOr<Reference> make_super_property_reference(GlobalObject& global_object, Value actual_this, StringOrSymbol const& property_key, bool strict)
  332. {
  333. auto& vm = global_object.vm();
  334. // 1. Let env be GetThisEnvironment().
  335. auto& env = verify_cast<FunctionEnvironment>(get_this_environment(vm));
  336. // 2. Assert: env.HasSuperBinding() is true.
  337. VERIFY(env.has_super_binding());
  338. // 3. Let baseValue be ? env.GetSuperBase().
  339. auto base_value = env.get_super_base();
  340. // 4. Let bv be ? RequireObjectCoercible(baseValue).
  341. auto bv = TRY(require_object_coercible(global_object, base_value));
  342. // 5. Return the Reference Record { [[Base]]: bv, [[ReferencedName]]: propertyKey, [[Strict]]: strict, [[ThisValue]]: actualThis }.
  343. // 6. NOTE: This returns a Super Reference Record.
  344. return Reference { bv, property_key, actual_this, strict };
  345. }
  346. // 19.2.1.1 PerformEval ( x, callerRealm, strictCaller, direct ), https://tc39.es/ecma262/#sec-performeval
  347. Value perform_eval(Value x, GlobalObject& caller_realm, CallerMode strict_caller, EvalMode direct)
  348. {
  349. VERIFY(direct == EvalMode::Direct || strict_caller == CallerMode::NonStrict);
  350. if (!x.is_string())
  351. return x;
  352. auto& vm = caller_realm.vm();
  353. auto& code_string = x.as_string();
  354. Parser parser { Lexer { code_string.string() } };
  355. auto program = parser.parse_program(strict_caller == CallerMode::Strict);
  356. if (parser.has_errors()) {
  357. auto& error = parser.errors()[0];
  358. vm.throw_exception<SyntaxError>(caller_realm, error.to_string());
  359. return {};
  360. }
  361. auto& interpreter = vm.interpreter();
  362. if (direct == EvalMode::Direct)
  363. return interpreter.execute_statement(caller_realm, program).value_or(js_undefined());
  364. TemporaryChange scope_change(vm.running_execution_context().lexical_environment, static_cast<Environment*>(&interpreter.realm().global_environment()));
  365. TemporaryChange scope_change_strict(vm.running_execution_context().is_strict_mode, strict_caller == CallerMode::Strict);
  366. return interpreter.execute_statement(caller_realm, program).value_or(js_undefined());
  367. }
  368. // 10.4.4.6 CreateUnmappedArgumentsObject ( argumentsList ), https://tc39.es/ecma262/#sec-createunmappedargumentsobject
  369. Object* create_unmapped_arguments_object(GlobalObject& global_object, Span<Value> arguments)
  370. {
  371. auto& vm = global_object.vm();
  372. // 1. Let len be the number of elements in argumentsList.
  373. auto length = arguments.size();
  374. // 2. Let obj be ! OrdinaryObjectCreate(%Object.prototype%, « [[ParameterMap]] »).
  375. // 3. Set obj.[[ParameterMap]] to undefined.
  376. auto* object = Object::create(global_object, global_object.object_prototype());
  377. object->set_has_parameter_map();
  378. // 4. Perform DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
  379. object->define_property_or_throw(vm.names.length, { .value = Value(length), .writable = true, .enumerable = false, .configurable = true });
  380. VERIFY(!vm.exception());
  381. // 5. Let index be 0.
  382. // 6. Repeat, while index < len,
  383. for (size_t index = 0; index < length; ++index) {
  384. // a. Let val be argumentsList[index].
  385. auto value = arguments[index];
  386. // b. Perform ! CreateDataPropertyOrThrow(obj, ! ToString(𝔽(index)), val).
  387. object->create_data_property_or_throw(index, value);
  388. VERIFY(!vm.exception());
  389. // c. Set index to index + 1.
  390. }
  391. // 7. Perform ! DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor { [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
  392. auto* array_prototype_values = global_object.array_prototype_values_function();
  393. object->define_property_or_throw(*vm.well_known_symbol_iterator(), { .value = array_prototype_values, .writable = true, .enumerable = false, .configurable = true });
  394. VERIFY(!vm.exception());
  395. // 8. Perform ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Get]]: %ThrowTypeError%, [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false }).
  396. auto* throw_type_error = global_object.throw_type_error_function();
  397. object->define_property_or_throw(vm.names.callee, { .get = throw_type_error, .set = throw_type_error, .enumerable = false, .configurable = false });
  398. VERIFY(!vm.exception());
  399. // 9. Return obj.
  400. return object;
  401. }
  402. // 10.4.4.7 CreateMappedArgumentsObject ( func, formals, argumentsList, env ), https://tc39.es/ecma262/#sec-createmappedargumentsobject
  403. Object* create_mapped_arguments_object(GlobalObject& global_object, FunctionObject& function, Vector<FunctionNode::Parameter> const& formals, Span<Value> arguments, Environment& environment)
  404. {
  405. auto& vm = global_object.vm();
  406. // 1. Assert: formals does not contain a rest parameter, any binding patterns, or any initializers. It may contain duplicate identifiers.
  407. // 2. Let len be the number of elements in argumentsList.
  408. VERIFY(arguments.size() <= NumericLimits<i32>::max());
  409. i32 length = static_cast<i32>(arguments.size());
  410. // 3. Let obj be ! MakeBasicObject(« [[Prototype]], [[Extensible]], [[ParameterMap]] »).
  411. // 4. Set obj.[[GetOwnProperty]] as specified in 10.4.4.1.
  412. // 5. Set obj.[[DefineOwnProperty]] as specified in 10.4.4.2.
  413. // 6. Set obj.[[Get]] as specified in 10.4.4.3.
  414. // 7. Set obj.[[Set]] as specified in 10.4.4.4.
  415. // 8. Set obj.[[Delete]] as specified in 10.4.4.5.
  416. // 9. Set obj.[[Prototype]] to %Object.prototype%.
  417. auto* object = vm.heap().allocate<ArgumentsObject>(global_object, global_object, environment);
  418. if (vm.exception())
  419. return nullptr;
  420. // 14. Let index be 0.
  421. // 15. Repeat, while index < len,
  422. for (i32 index = 0; index < length; ++index) {
  423. // a. Let val be argumentsList[index].
  424. auto value = arguments[index];
  425. // b. Perform ! CreateDataPropertyOrThrow(obj, ! ToString(𝔽(index)), val).
  426. object->create_data_property_or_throw(index, value);
  427. VERIFY(!vm.exception());
  428. // c. Set index to index + 1.
  429. }
  430. // 16. Perform ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
  431. object->define_property_or_throw(vm.names.length, { .value = Value(length), .writable = true, .enumerable = false, .configurable = true });
  432. VERIFY(!vm.exception());
  433. // 17. Let mappedNames be a new empty List.
  434. HashTable<FlyString> mapped_names;
  435. // 18. Set index to numberOfParameters - 1.
  436. // 19. Repeat, while index ≥ 0,
  437. VERIFY(formals.size() <= NumericLimits<i32>::max());
  438. for (i32 index = static_cast<i32>(formals.size()) - 1; index >= 0; --index) {
  439. // a. Let name be parameterNames[index].
  440. auto const& name = formals[index].binding.get<FlyString>();
  441. // b. If name is not an element of mappedNames, then
  442. if (mapped_names.contains(name))
  443. continue;
  444. // i. Add name as an element of the list mappedNames.
  445. mapped_names.set(name);
  446. // ii. If index < len, then
  447. if (index < length) {
  448. // 1. Let g be MakeArgGetter(name, env).
  449. // 2. Let p be MakeArgSetter(name, env).
  450. // 3. Perform map.[[DefineOwnProperty]](! ToString(𝔽(index)), PropertyDescriptor { [[Set]]: p, [[Get]]: g, [[Enumerable]]: false, [[Configurable]]: true }).
  451. object->parameter_map().define_native_accessor(
  452. String::number(index),
  453. [&environment, name](VM&, GlobalObject&) -> Value {
  454. auto variable = environment.get_from_environment(name);
  455. if (!variable.has_value())
  456. return {};
  457. return variable->value;
  458. },
  459. [&environment, name](VM& vm, GlobalObject&) {
  460. auto value = vm.argument(0);
  461. environment.put_into_environment(name, Variable { value, DeclarationKind::Var });
  462. return js_undefined();
  463. },
  464. Attribute::Configurable);
  465. }
  466. }
  467. // 20. Perform ! DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor { [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
  468. auto* array_prototype_values = global_object.array_prototype_values_function();
  469. object->define_property_or_throw(*vm.well_known_symbol_iterator(), { .value = array_prototype_values, .writable = true, .enumerable = false, .configurable = true });
  470. VERIFY(!vm.exception());
  471. // 21. Perform ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Value]]: func, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
  472. object->define_property_or_throw(vm.names.callee, { .value = &function, .writable = true, .enumerable = false, .configurable = true });
  473. VERIFY(!vm.exception());
  474. // 22. Return obj.
  475. return object;
  476. }
  477. // 7.1.21 CanonicalNumericIndexString ( argument ), https://tc39.es/ecma262/#sec-canonicalnumericindexstring
  478. Value canonical_numeric_index_string(GlobalObject& global_object, PropertyName const& property_name)
  479. {
  480. // NOTE: If the property name is a number type (An implementation-defined optimized
  481. // property key type), it can be treated as a string property that has already been
  482. // converted successfully into a canonical numeric index.
  483. VERIFY(property_name.is_string() || property_name.is_number());
  484. if (property_name.is_number())
  485. return Value(property_name.as_number());
  486. // 1. Assert: Type(argument) is String.
  487. auto argument = Value(js_string(global_object.vm(), property_name.as_string()));
  488. // 2. If argument is "-0", return -0𝔽.
  489. if (argument.as_string().string() == "-0")
  490. return Value(-0.0);
  491. // 3. Let n be ! ToNumber(argument).
  492. auto n = argument.to_number(global_object);
  493. // 4. If SameValue(! ToString(n), argument) is false, return undefined.
  494. if (!same_value(n.to_primitive_string(global_object), argument))
  495. return js_undefined();
  496. // 5. Return n.
  497. return n;
  498. }
  499. // 22.1.3.17.1 GetSubstitution ( matched, str, position, captures, namedCaptures, replacement ), https://tc39.es/ecma262/#sec-getsubstitution
  500. String get_substitution(GlobalObject& global_object, Utf16View const& matched, Utf16View const& str, size_t position, Span<Value> captures, Value named_captures, Value replacement)
  501. {
  502. auto& vm = global_object.vm();
  503. auto replace_string = replacement.to_utf16_string(global_object);
  504. if (vm.exception())
  505. return {};
  506. auto replace_view = replace_string.view();
  507. StringBuilder result;
  508. for (size_t i = 0; i < replace_view.length_in_code_units(); ++i) {
  509. u16 curr = replace_view.code_unit_at(i);
  510. if ((curr != '$') || (i + 1 >= replace_view.length_in_code_units())) {
  511. result.append(curr);
  512. continue;
  513. }
  514. u16 next = replace_view.code_unit_at(i + 1);
  515. if (next == '$') {
  516. result.append('$');
  517. ++i;
  518. } else if (next == '&') {
  519. result.append(matched);
  520. ++i;
  521. } else if (next == '`') {
  522. auto substring = str.substring_view(0, position);
  523. result.append(substring);
  524. ++i;
  525. } else if (next == '\'') {
  526. auto tail_pos = position + matched.length_in_code_units();
  527. if (tail_pos < str.length_in_code_units()) {
  528. auto substring = str.substring_view(tail_pos);
  529. result.append(substring);
  530. }
  531. ++i;
  532. } else if (is_ascii_digit(next)) {
  533. bool is_two_digits = (i + 2 < replace_view.length_in_code_units()) && is_ascii_digit(replace_view.code_unit_at(i + 2));
  534. auto capture_postition_string = replace_view.substring_view(i + 1, is_two_digits ? 2 : 1).to_utf8();
  535. auto capture_position = capture_postition_string.to_uint();
  536. if (capture_position.has_value() && (*capture_position > 0) && (*capture_position <= captures.size())) {
  537. auto& value = captures[*capture_position - 1];
  538. if (!value.is_undefined()) {
  539. auto value_string = value.to_string(global_object);
  540. if (vm.exception())
  541. return {};
  542. result.append(value_string);
  543. }
  544. i += is_two_digits ? 2 : 1;
  545. } else {
  546. result.append(curr);
  547. }
  548. } else if (next == '<') {
  549. auto start_position = i + 2;
  550. Optional<size_t> end_position;
  551. for (size_t j = start_position; j < replace_view.length_in_code_units(); ++j) {
  552. if (replace_view.code_unit_at(j) == '>') {
  553. end_position = j;
  554. break;
  555. }
  556. }
  557. if (named_captures.is_undefined() || !end_position.has_value()) {
  558. result.append(curr);
  559. } else {
  560. auto group_name_view = replace_view.substring_view(start_position, *end_position - start_position);
  561. auto group_name = group_name_view.to_utf8(Utf16View::AllowInvalidCodeUnits::Yes);
  562. auto capture = named_captures.as_object().get(group_name);
  563. if (vm.exception())
  564. return {};
  565. if (!capture.is_undefined()) {
  566. auto capture_string = capture.to_string(global_object);
  567. if (vm.exception())
  568. return {};
  569. result.append(capture_string);
  570. }
  571. i = *end_position;
  572. }
  573. } else {
  574. result.append(curr);
  575. }
  576. }
  577. return result.build();
  578. }
  579. }