AbstractOperations.cpp 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183
  1. /*
  2. * Copyright (c) 2020-2022, 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/Bytecode/Interpreter.h>
  13. #include <LibJS/Interpreter.h>
  14. #include <LibJS/Parser.h>
  15. #include <LibJS/Runtime/AbstractOperations.h>
  16. #include <LibJS/Runtime/Accessor.h>
  17. #include <LibJS/Runtime/ArgumentsObject.h>
  18. #include <LibJS/Runtime/Array.h>
  19. #include <LibJS/Runtime/BoundFunction.h>
  20. #include <LibJS/Runtime/Completion.h>
  21. #include <LibJS/Runtime/DeclarativeEnvironment.h>
  22. #include <LibJS/Runtime/ECMAScriptFunctionObject.h>
  23. #include <LibJS/Runtime/ErrorTypes.h>
  24. #include <LibJS/Runtime/FunctionEnvironment.h>
  25. #include <LibJS/Runtime/FunctionObject.h>
  26. #include <LibJS/Runtime/GlobalObject.h>
  27. #include <LibJS/Runtime/Object.h>
  28. #include <LibJS/Runtime/ObjectEnvironment.h>
  29. #include <LibJS/Runtime/PropertyDescriptor.h>
  30. #include <LibJS/Runtime/PropertyKey.h>
  31. #include <LibJS/Runtime/ProxyObject.h>
  32. #include <LibJS/Runtime/Reference.h>
  33. namespace JS {
  34. // 7.2.1 RequireObjectCoercible ( argument ), https://tc39.es/ecma262/#sec-requireobjectcoercible
  35. ThrowCompletionOr<Value> require_object_coercible(GlobalObject& global_object, Value value)
  36. {
  37. auto& vm = global_object.vm();
  38. if (value.is_nullish())
  39. return vm.throw_completion<TypeError>(global_object, ErrorType::NotObjectCoercible, value.to_string_without_side_effects());
  40. return value;
  41. }
  42. // 7.3.14 Call ( F, V [ , argumentsList ] ), https://tc39.es/ecma262/#sec-call
  43. ThrowCompletionOr<Value> call_impl(GlobalObject& global_object, Value function, Value this_value, Optional<MarkedVector<Value>> arguments_list)
  44. {
  45. auto& vm = global_object.vm();
  46. // 1. If argumentsList is not present, set argumentsList to a new empty List.
  47. if (!arguments_list.has_value())
  48. arguments_list = MarkedVector<Value> { global_object.heap() };
  49. // 2. If IsCallable(F) is false, throw a TypeError exception.
  50. if (!function.is_function())
  51. return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, function.to_string_without_side_effects());
  52. // 3. Return ? F.[[Call]](V, argumentsList).
  53. return function.as_function().internal_call(this_value, move(*arguments_list));
  54. }
  55. ThrowCompletionOr<Value> call_impl(GlobalObject& global_object, FunctionObject& function, Value this_value, Optional<MarkedVector<Value>> arguments_list)
  56. {
  57. // 1. If argumentsList is not present, set argumentsList to a new empty List.
  58. if (!arguments_list.has_value())
  59. arguments_list = MarkedVector<Value> { global_object.heap() };
  60. // 2. If IsCallable(F) is false, throw a TypeError exception.
  61. // Note: Called with a FunctionObject ref
  62. // 3. Return ? F.[[Call]](V, argumentsList).
  63. return function.internal_call(this_value, move(*arguments_list));
  64. }
  65. // 7.3.15 Construct ( F [ , argumentsList [ , newTarget ] ] ), https://tc39.es/ecma262/#sec-construct
  66. ThrowCompletionOr<Object*> construct_impl(GlobalObject& global_object, FunctionObject& function, Optional<MarkedVector<Value>> arguments_list, FunctionObject* new_target)
  67. {
  68. // 1. If newTarget is not present, set newTarget to F.
  69. if (!new_target)
  70. new_target = &function;
  71. // 2. If argumentsList is not present, set argumentsList to a new empty List.
  72. if (!arguments_list.has_value())
  73. arguments_list = MarkedVector<Value> { global_object.heap() };
  74. // 3. Return ? F.[[Construct]](argumentsList, newTarget).
  75. return function.internal_construct(move(*arguments_list), *new_target);
  76. }
  77. // 7.3.19 LengthOfArrayLike ( obj ), https://tc39.es/ecma262/#sec-lengthofarraylike
  78. ThrowCompletionOr<size_t> length_of_array_like(GlobalObject& global_object, Object const& object)
  79. {
  80. auto& vm = global_object.vm();
  81. auto result = TRY(object.get(vm.names.length));
  82. return result.to_length(global_object);
  83. }
  84. // 7.3.20 CreateListFromArrayLike ( obj [ , elementTypes ] ), https://tc39.es/ecma262/#sec-createlistfromarraylike
  85. ThrowCompletionOr<MarkedVector<Value>> create_list_from_array_like(GlobalObject& global_object, Value value, Function<ThrowCompletionOr<void>(Value)> check_value)
  86. {
  87. auto& vm = global_object.vm();
  88. auto& heap = global_object.heap();
  89. // 1. If elementTypes is not present, set elementTypes to « Undefined, Null, Boolean, String, Symbol, Number, BigInt, Object ».
  90. // 2. If Type(obj) is not Object, throw a TypeError exception.
  91. if (!value.is_object())
  92. return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObject, value.to_string_without_side_effects());
  93. auto& array_like = value.as_object();
  94. // 3. Let len be ? LengthOfArrayLike(obj).
  95. auto length = TRY(length_of_array_like(global_object, array_like));
  96. // 4. Let list be a new empty List.
  97. auto list = MarkedVector<Value> { heap };
  98. list.ensure_capacity(length);
  99. // 5. Let index be 0.
  100. // 6. Repeat, while index < len,
  101. for (size_t i = 0; i < length; ++i) {
  102. // a. Let indexName be ! ToString(𝔽(index)).
  103. auto index_name = PropertyKey { i };
  104. // b. Let next be ? Get(obj, indexName).
  105. auto next = TRY(array_like.get(index_name));
  106. // c. If Type(next) is not an element of elementTypes, throw a TypeError exception.
  107. if (check_value)
  108. TRY(check_value(next));
  109. // d. Append next as the last element of list.
  110. list.unchecked_append(next);
  111. }
  112. // 7. Return list.
  113. return ThrowCompletionOr(move(list));
  114. }
  115. // 7.3.23 SpeciesConstructor ( O, defaultConstructor ), https://tc39.es/ecma262/#sec-speciesconstructor
  116. ThrowCompletionOr<FunctionObject*> species_constructor(GlobalObject& global_object, Object const& object, FunctionObject& default_constructor)
  117. {
  118. auto& vm = global_object.vm();
  119. // 1. Let C be ? Get(O, "constructor").
  120. auto constructor = TRY(object.get(vm.names.constructor));
  121. // 2. If C is undefined, return defaultConstructor.
  122. if (constructor.is_undefined())
  123. return &default_constructor;
  124. // 3. If Type(C) is not Object, throw a TypeError exception.
  125. if (!constructor.is_object())
  126. return vm.throw_completion<TypeError>(global_object, ErrorType::NotAConstructor, constructor.to_string_without_side_effects());
  127. // 4. Let S be ? Get(C, @@species).
  128. auto species = TRY(constructor.as_object().get(*vm.well_known_symbol_species()));
  129. // 5. If S is either undefined or null, return defaultConstructor.
  130. if (species.is_nullish())
  131. return &default_constructor;
  132. // 6. If IsConstructor(S) is true, return S.
  133. if (species.is_constructor())
  134. return &species.as_function();
  135. // 7. Throw a TypeError exception.
  136. return vm.throw_completion<TypeError>(global_object, ErrorType::NotAConstructor, species.to_string_without_side_effects());
  137. }
  138. // 7.3.25 GetFunctionRealm ( obj ), https://tc39.es/ecma262/#sec-getfunctionrealm
  139. ThrowCompletionOr<Realm*> get_function_realm(GlobalObject& global_object, FunctionObject const& function)
  140. {
  141. auto& vm = global_object.vm();
  142. // 1. Assert: ! IsCallable(obj) is true.
  143. // 2. If obj has a [[Realm]] internal slot, then
  144. if (function.realm()) {
  145. // a. Return obj.[[Realm]].
  146. return function.realm();
  147. }
  148. // 3. If obj is a bound function exotic object, then
  149. if (is<BoundFunction>(function)) {
  150. auto& bound_function = static_cast<BoundFunction const&>(function);
  151. // a. Let target be obj.[[BoundTargetFunction]].
  152. auto& target = bound_function.bound_target_function();
  153. // b. Return ? GetFunctionRealm(target).
  154. return get_function_realm(global_object, target);
  155. }
  156. // 4. If obj is a Proxy exotic object, then
  157. if (is<ProxyObject>(function)) {
  158. auto& proxy = static_cast<ProxyObject const&>(function);
  159. // a. If obj.[[ProxyHandler]] is null, throw a TypeError exception.
  160. if (proxy.is_revoked())
  161. return vm.throw_completion<TypeError>(global_object, ErrorType::ProxyRevoked);
  162. // b. Let proxyTarget be obj.[[ProxyTarget]].
  163. auto& proxy_target = proxy.target();
  164. // c. Return ? GetFunctionRealm(proxyTarget).
  165. VERIFY(proxy_target.is_function());
  166. return get_function_realm(global_object, static_cast<FunctionObject const&>(proxy_target));
  167. }
  168. // 5. Return the current Realm Record.
  169. return vm.current_realm();
  170. }
  171. // 8.5.2.1 InitializeBoundName ( name, value, environment ), https://tc39.es/ecma262/#sec-initializeboundname
  172. ThrowCompletionOr<void> initialize_bound_name(GlobalObject& global_object, FlyString const& name, Value value, Environment* environment)
  173. {
  174. auto& vm = global_object.vm();
  175. // 1. If environment is not undefined, then
  176. if (environment) {
  177. // a. Perform environment.InitializeBinding(name, value).
  178. MUST(environment->initialize_binding(global_object, name, value));
  179. // b. Return NormalCompletion(undefined).
  180. return {};
  181. }
  182. // 2. Else,
  183. else {
  184. // a. Let lhs be ResolveBinding(name).
  185. // NOTE: Although the spec pretends resolve_binding cannot fail it can just not in this case.
  186. auto lhs = MUST(vm.resolve_binding(name));
  187. // b. Return ? PutValue(lhs, value).
  188. return TRY(lhs.put_value(global_object, value));
  189. }
  190. VERIFY_NOT_REACHED();
  191. }
  192. // 10.1.6.2 IsCompatiblePropertyDescriptor ( Extensible, Desc, Current ), https://tc39.es/ecma262/#sec-iscompatiblepropertydescriptor
  193. bool is_compatible_property_descriptor(bool extensible, PropertyDescriptor const& descriptor, Optional<PropertyDescriptor> const& current)
  194. {
  195. // 1. Return ValidateAndApplyPropertyDescriptor(undefined, undefined, Extensible, Desc, Current).
  196. return validate_and_apply_property_descriptor(nullptr, {}, extensible, descriptor, current);
  197. }
  198. // 10.1.6.3 ValidateAndApplyPropertyDescriptor ( O, P, extensible, Desc, current ), https://tc39.es/ecma262/#sec-validateandapplypropertydescriptor
  199. bool validate_and_apply_property_descriptor(Object* object, PropertyKey const& property_key, bool extensible, PropertyDescriptor const& descriptor, Optional<PropertyDescriptor> const& current)
  200. {
  201. // 1. Assert: If O is not undefined, then IsPropertyKey(P) is true.
  202. if (object)
  203. VERIFY(property_key.is_valid());
  204. // 2. If current is undefined, then
  205. if (!current.has_value()) {
  206. // a. If extensible is false, return false.
  207. if (!extensible)
  208. return false;
  209. // b. Assert: extensible is true.
  210. // c. If IsGenericDescriptor(Desc) is true or IsDataDescriptor(Desc) is true, then
  211. if (descriptor.is_generic_descriptor() || descriptor.is_data_descriptor()) {
  212. // i. If O is not undefined, create an own data property named P of object O whose [[Value]], [[Writable]],
  213. // [[Enumerable]], and [[Configurable]] attribute values are described by Desc.
  214. // If the value of an attribute field of Desc is absent, the attribute of the newly created property is set
  215. // to its default value.
  216. if (object) {
  217. auto value = descriptor.value.value_or(js_undefined());
  218. object->storage_set(property_key, { value, descriptor.attributes() });
  219. }
  220. }
  221. // d. Else,
  222. else {
  223. // i. Assert: ! IsAccessorDescriptor(Desc) is true.
  224. VERIFY(descriptor.is_accessor_descriptor());
  225. // ii. If O is not undefined, create an own accessor property named P of object O whose [[Get]], [[Set]],
  226. // [[Enumerable]], and [[Configurable]] attribute values are described by Desc.
  227. // If the value of an attribute field of Desc is absent, the attribute of the newly created property is set
  228. // to its default value.
  229. if (object) {
  230. auto accessor = Accessor::create(object->vm(), descriptor.get.value_or(nullptr), descriptor.set.value_or(nullptr));
  231. object->storage_set(property_key, { accessor, descriptor.attributes() });
  232. }
  233. }
  234. // e. Return true.
  235. return true;
  236. }
  237. // 3. If every field in Desc is absent, return true.
  238. if (descriptor.is_empty())
  239. return true;
  240. // 4. If current.[[Configurable]] is false, then
  241. if (!*current->configurable) {
  242. // a. If Desc.[[Configurable]] is present and its value is true, return false.
  243. if (descriptor.configurable.has_value() && *descriptor.configurable)
  244. return false;
  245. // b. If Desc.[[Enumerable]] is present and ! SameValue(Desc.[[Enumerable]], current.[[Enumerable]]) is false, return false.
  246. if (descriptor.enumerable.has_value() && *descriptor.enumerable != *current->enumerable)
  247. return false;
  248. }
  249. // 5. If ! IsGenericDescriptor(Desc) is true, then
  250. if (descriptor.is_generic_descriptor()) {
  251. // a. NOTE: No further validation is required.
  252. }
  253. // 6. Else if ! SameValue(! IsDataDescriptor(current), ! IsDataDescriptor(Desc)) is false, then
  254. else if (current->is_data_descriptor() != descriptor.is_data_descriptor()) {
  255. // a. If current.[[Configurable]] is false, return false.
  256. if (!*current->configurable)
  257. return false;
  258. // b. If IsDataDescriptor(current) is true, then
  259. if (current->is_data_descriptor()) {
  260. // If O is not undefined, convert the property named P of object O from a data property to an accessor property.
  261. // Preserve the existing values of the converted property's [[Configurable]] and [[Enumerable]] attributes and
  262. // set the rest of the property's attributes to their default values.
  263. if (object) {
  264. auto accessor = Accessor::create(object->vm(), nullptr, nullptr);
  265. object->storage_set(property_key, { accessor, current->attributes() });
  266. }
  267. }
  268. // c. Else,
  269. else {
  270. // If O is not undefined, convert the property named P of object O from an accessor property to a data property.
  271. // Preserve the existing values of the converted property's [[Configurable]] and [[Enumerable]] attributes and
  272. // set the rest of the property's attributes to their default values.
  273. if (object) {
  274. auto value = js_undefined();
  275. object->storage_set(property_key, { value, current->attributes() });
  276. }
  277. }
  278. }
  279. // 7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both true, then
  280. else if (current->is_data_descriptor() && descriptor.is_data_descriptor()) {
  281. // a. If current.[[Configurable]] is false and current.[[Writable]] is false, then
  282. if (!*current->configurable && !*current->writable) {
  283. // i. If Desc.[[Writable]] is present and Desc.[[Writable]] is true, return false.
  284. if (descriptor.writable.has_value() && *descriptor.writable)
  285. return false;
  286. // ii. If Desc.[[Value]] is present and SameValue(Desc.[[Value]], current.[[Value]]) is false, return false.
  287. if (descriptor.value.has_value() && !same_value(*descriptor.value, *current->value))
  288. return false;
  289. // iii. Return true.
  290. return true;
  291. }
  292. }
  293. // 8. Else,
  294. else {
  295. // a. Assert: ! IsAccessorDescriptor(current) and ! IsAccessorDescriptor(Desc) are both true.
  296. VERIFY(current->is_accessor_descriptor());
  297. VERIFY(descriptor.is_accessor_descriptor());
  298. // b. If current.[[Configurable]] is false, then
  299. if (!*current->configurable) {
  300. // i. If Desc.[[Set]] is present and SameValue(Desc.[[Set]], current.[[Set]]) is false, return false.
  301. if (descriptor.set.has_value() && *descriptor.set != *current->set)
  302. return false;
  303. // ii. If Desc.[[Get]] is present and SameValue(Desc.[[Get]], current.[[Get]]) is false, return false.
  304. if (descriptor.get.has_value() && *descriptor.get != *current->get)
  305. return false;
  306. // iii. Return true.
  307. return true;
  308. }
  309. }
  310. // 9. If O is not undefined, then
  311. if (object) {
  312. // 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.
  313. Value value;
  314. if (descriptor.is_accessor_descriptor() || (current->is_accessor_descriptor() && !descriptor.is_data_descriptor())) {
  315. auto* getter = descriptor.get.value_or(current->get.value_or(nullptr));
  316. auto* setter = descriptor.set.value_or(current->set.value_or(nullptr));
  317. value = Accessor::create(object->vm(), getter, setter);
  318. } else {
  319. value = descriptor.value.value_or(current->value.value_or({}));
  320. }
  321. PropertyAttributes attributes;
  322. attributes.set_writable(descriptor.writable.value_or(current->writable.value_or(false)));
  323. attributes.set_enumerable(descriptor.enumerable.value_or(current->enumerable.value_or(false)));
  324. attributes.set_configurable(descriptor.configurable.value_or(current->configurable.value_or(false)));
  325. object->storage_set(property_key, { value, attributes });
  326. }
  327. // 10. Return true.
  328. return true;
  329. }
  330. // 10.1.14 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ), https://tc39.es/ecma262/#sec-getprototypefromconstructor
  331. ThrowCompletionOr<Object*> get_prototype_from_constructor(GlobalObject& global_object, FunctionObject const& constructor, Object* (GlobalObject::*intrinsic_default_prototype)())
  332. {
  333. auto& vm = global_object.vm();
  334. // 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.
  335. // 2. Let proto be ? Get(constructor, "prototype").
  336. auto prototype = TRY(constructor.get(vm.names.prototype));
  337. // 3. If Type(proto) is not Object, then
  338. if (!prototype.is_object()) {
  339. // a. Let realm be ? GetFunctionRealm(constructor).
  340. auto* realm = TRY(get_function_realm(global_object, constructor));
  341. // b. Set proto to realm's intrinsic object named intrinsicDefaultProto.
  342. prototype = (realm->global_object().*intrinsic_default_prototype)();
  343. }
  344. // 4. Return proto.
  345. return &prototype.as_object();
  346. }
  347. // 9.1.2.2 NewDeclarativeEnvironment ( E ), https://tc39.es/ecma262/#sec-newdeclarativeenvironment
  348. DeclarativeEnvironment* new_declarative_environment(Environment& environment)
  349. {
  350. return environment.heap().allocate_without_global_object<DeclarativeEnvironment>(&environment);
  351. }
  352. // 9.1.2.3 NewObjectEnvironment ( O, W, E ), https://tc39.es/ecma262/#sec-newobjectenvironment
  353. ObjectEnvironment* new_object_environment(Object& object, bool is_with_environment, Environment* environment)
  354. {
  355. auto& heap = object.heap();
  356. return heap.allocate_without_global_object<ObjectEnvironment>(object, is_with_environment ? ObjectEnvironment::IsWithEnvironment::Yes : ObjectEnvironment::IsWithEnvironment::No, environment);
  357. }
  358. // 9.1.2.4 NewFunctionEnvironment ( F, newTarget ), https://tc39.es/ecma262/#sec-newfunctionenvironment
  359. FunctionEnvironment* new_function_environment(ECMAScriptFunctionObject& function, Object* new_target)
  360. {
  361. auto& heap = function.heap();
  362. // 1. Let env be a new function Environment Record containing no bindings.
  363. auto* env = heap.allocate_without_global_object<FunctionEnvironment>(function.environment());
  364. // 2. Set env.[[FunctionObject]] to F.
  365. env->set_function_object(function);
  366. // 3. If F.[[ThisMode]] is lexical, set env.[[ThisBindingStatus]] to lexical.
  367. if (function.this_mode() == ECMAScriptFunctionObject::ThisMode::Lexical)
  368. env->set_this_binding_status(FunctionEnvironment::ThisBindingStatus::Lexical);
  369. // 4. Else, set env.[[ThisBindingStatus]] to uninitialized.
  370. else
  371. env->set_this_binding_status(FunctionEnvironment::ThisBindingStatus::Uninitialized);
  372. // 5. Set env.[[NewTarget]] to newTarget.
  373. env->set_new_target(new_target ?: js_undefined());
  374. // 6. Set env.[[OuterEnv]] to F.[[Environment]].
  375. // NOTE: Done in step 1 via the FunctionEnvironment constructor.
  376. // 7. Return env.
  377. return env;
  378. }
  379. // 9.2.1.1 NewPrivateEnvironment ( outerPrivEnv ), https://tc39.es/ecma262/#sec-newprivateenvironment
  380. PrivateEnvironment* new_private_environment(VM& vm, PrivateEnvironment* outer)
  381. {
  382. // 1. Let names be a new empty List.
  383. // 2. Return the PrivateEnvironment Record { [[OuterPrivateEnvironment]]: outerPrivEnv, [[Names]]: names }.
  384. return vm.heap().allocate_without_global_object<PrivateEnvironment>(outer);
  385. }
  386. // 9.4.3 GetThisEnvironment ( ), https://tc39.es/ecma262/#sec-getthisenvironment
  387. Environment& get_this_environment(VM& vm)
  388. {
  389. for (auto* env = vm.lexical_environment(); env; env = env->outer_environment()) {
  390. if (env->has_this_binding())
  391. return *env;
  392. }
  393. VERIFY_NOT_REACHED();
  394. }
  395. // 13.3.7.2 GetSuperConstructor ( ), https://tc39.es/ecma262/#sec-getsuperconstructor
  396. Object* get_super_constructor(VM& vm)
  397. {
  398. // 1. Let envRec be GetThisEnvironment().
  399. auto& env = get_this_environment(vm);
  400. // 2. Assert: envRec is a function Environment Record.
  401. // 3. Let activeFunction be envRec.[[FunctionObject]].
  402. // 4. Assert: activeFunction is an ECMAScript function object.
  403. auto& active_function = verify_cast<FunctionEnvironment>(env).function_object();
  404. // 5. Let superConstructor be ! activeFunction.[[GetPrototypeOf]]().
  405. auto* super_constructor = MUST(active_function.internal_get_prototype_of());
  406. // 6. Return superConstructor.
  407. return super_constructor;
  408. }
  409. // 13.3.7.3 MakeSuperPropertyReference ( actualThis, propertyKey, strict ), https://tc39.es/ecma262/#sec-makesuperpropertyreference
  410. ThrowCompletionOr<Reference> make_super_property_reference(GlobalObject& global_object, Value actual_this, PropertyKey const& property_key, bool strict)
  411. {
  412. auto& vm = global_object.vm();
  413. // 1. Let env be GetThisEnvironment().
  414. auto& env = verify_cast<FunctionEnvironment>(get_this_environment(vm));
  415. // 2. Assert: env.HasSuperBinding() is true.
  416. VERIFY(env.has_super_binding());
  417. // 3. Let baseValue be ? env.GetSuperBase().
  418. auto base_value = TRY(env.get_super_base());
  419. // 4. Let bv be ? RequireObjectCoercible(baseValue).
  420. auto bv = TRY(require_object_coercible(global_object, base_value));
  421. // 5. Return the Reference Record { [[Base]]: bv, [[ReferencedName]]: propertyKey, [[Strict]]: strict, [[ThisValue]]: actualThis }.
  422. // 6. NOTE: This returns a Super Reference Record.
  423. return Reference { bv, property_key, actual_this, strict };
  424. }
  425. // 19.2.1.1 PerformEval ( x, callerRealm, strictCaller, direct ), https://tc39.es/ecma262/#sec-performeval
  426. ThrowCompletionOr<Value> perform_eval(Value x, GlobalObject& caller_realm, CallerMode strict_caller, EvalMode direct)
  427. {
  428. VERIFY(direct == EvalMode::Direct || strict_caller == CallerMode::NonStrict);
  429. if (!x.is_string())
  430. return x;
  431. auto& vm = caller_realm.vm();
  432. auto& eval_realm = vm.running_execution_context().realm;
  433. auto& code_string = x.as_string();
  434. Parser parser { Lexer { code_string.string() } };
  435. auto program = parser.parse_program(strict_caller == CallerMode::Strict);
  436. if (parser.has_errors()) {
  437. auto& error = parser.errors()[0];
  438. return vm.throw_completion<SyntaxError>(caller_realm, error.to_string());
  439. }
  440. auto strict_eval = strict_caller == CallerMode::Strict;
  441. if (program->is_strict_mode())
  442. strict_eval = true;
  443. auto& running_context = vm.running_execution_context();
  444. Environment* lexical_environment;
  445. Environment* variable_environment;
  446. PrivateEnvironment* private_environment;
  447. if (direct == EvalMode::Direct) {
  448. lexical_environment = new_declarative_environment(*running_context.lexical_environment);
  449. variable_environment = running_context.variable_environment;
  450. private_environment = running_context.private_environment;
  451. } else {
  452. lexical_environment = new_declarative_environment(eval_realm->global_environment());
  453. variable_environment = &eval_realm->global_environment();
  454. private_environment = nullptr;
  455. }
  456. if (strict_eval)
  457. variable_environment = lexical_environment;
  458. if (direct == EvalMode::Direct && !strict_eval) {
  459. // NOTE: Non-strict direct eval() forces us to deoptimize variable accesses.
  460. // Mark the variable environment chain as screwed since we will not be able
  461. // to rely on cached environment coordinates from this point on.
  462. variable_environment->set_permanently_screwed_by_eval();
  463. }
  464. // 18. If runningContext is not already suspended, suspend runningContext.
  465. // FIXME: We don't have this concept yet.
  466. ExecutionContext eval_context(vm.heap());
  467. eval_context.realm = eval_realm;
  468. eval_context.variable_environment = variable_environment;
  469. eval_context.lexical_environment = lexical_environment;
  470. eval_context.private_environment = private_environment;
  471. TRY(vm.push_execution_context(eval_context, eval_realm->global_object()));
  472. ScopeGuard pop_guard = [&] {
  473. vm.pop_execution_context();
  474. };
  475. TRY(eval_declaration_instantiation(vm, eval_realm->global_object(), program, variable_environment, lexical_environment, private_environment, strict_eval));
  476. TemporaryChange scope_change_strict(vm.running_execution_context().is_strict_mode, strict_eval);
  477. Optional<Value> eval_result;
  478. if (auto* bytecode_interpreter = Bytecode::Interpreter::current()) {
  479. auto executable_result = JS::Bytecode::Generator::generate(program);
  480. if (executable_result.is_error())
  481. return vm.throw_completion<InternalError>(bytecode_interpreter->global_object(), ErrorType::NotImplemented, executable_result.error().to_string());
  482. auto executable = executable_result.release_value();
  483. executable->name = "eval"sv;
  484. if (JS::Bytecode::g_dump_bytecode)
  485. executable->dump();
  486. eval_result = TRY(bytecode_interpreter->run(*executable));
  487. // Turn potentially empty JS::Value from the bytecode interpreter into an empty Optional
  488. if (eval_result.has_value() && eval_result->is_empty())
  489. eval_result = {};
  490. } else {
  491. auto& ast_interpreter = vm.interpreter();
  492. eval_result = TRY(program->execute(ast_interpreter, caller_realm));
  493. }
  494. return eval_result.value_or(js_undefined());
  495. }
  496. // 19.2.1.3 EvalDeclarationInstantiation ( body, varEnv, lexEnv, privateEnv, strict ), https://tc39.es/ecma262/#sec-evaldeclarationinstantiation
  497. ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& global_object, Program const& program, Environment* variable_environment, Environment* lexical_environment, PrivateEnvironment* private_environment, bool strict)
  498. {
  499. GlobalEnvironment* global_var_environment = variable_environment->is_global_environment() ? static_cast<GlobalEnvironment*>(variable_environment) : nullptr;
  500. // 1. Let varNames be the VarDeclaredNames of body.
  501. // 2. Let varDeclarations be the VarScopedDeclarations of body.
  502. // 3. If strict is false, then
  503. if (!strict) {
  504. // a. If varEnv is a global Environment Record, then
  505. if (global_var_environment) {
  506. // i. For each element name of varNames, do
  507. TRY(program.for_each_var_declared_name([&](auto const& name) -> ThrowCompletionOr<void> {
  508. // 1. If varEnv.HasLexicalDeclaration(name) is true, throw a SyntaxError exception.
  509. if (global_var_environment->has_lexical_declaration(name))
  510. return vm.throw_completion<SyntaxError>(global_object, ErrorType::TopLevelVariableAlreadyDeclared, name);
  511. // 2. NOTE: eval will not create a global var declaration that would be shadowed by a global lexical declaration.
  512. return {};
  513. }));
  514. }
  515. // b. Let thisEnv be lexEnv.
  516. auto* this_environment = lexical_environment;
  517. // c. Assert: The following loop will terminate.
  518. // d. Repeat, while thisEnv is not the same as varEnv,
  519. while (this_environment != variable_environment) {
  520. // i. If thisEnv is not an object Environment Record, then
  521. if (!is<ObjectEnvironment>(*this_environment)) {
  522. // 1. NOTE: The environment of with statements cannot contain any lexical declaration so it doesn't need to be checked for var/let hoisting conflicts.
  523. // 2. For each element name of varNames, do
  524. TRY(program.for_each_var_declared_name([&](auto const& name) -> ThrowCompletionOr<void> {
  525. // a. If thisEnv.HasBinding(name) is true, then
  526. if (MUST(this_environment->has_binding(name))) {
  527. // i. Throw a SyntaxError exception.
  528. return vm.throw_completion<SyntaxError>(global_object, ErrorType::TopLevelVariableAlreadyDeclared, name);
  529. // FIXME: ii. NOTE: Annex B.3.4 defines alternate semantics for the above step.
  530. // In particular it only throw the syntax error if it is not an environment from a catchclause.
  531. }
  532. // b. NOTE: A direct eval will not hoist var declaration over a like-named lexical declaration.
  533. return {};
  534. }));
  535. }
  536. // ii. Set thisEnv to thisEnv.[[OuterEnv]].
  537. this_environment = this_environment->outer_environment();
  538. VERIFY(this_environment);
  539. }
  540. }
  541. // 4. Let privateIdentifiers be a new empty List.
  542. // 5. Let pointer be privateEnv.
  543. // 6. Repeat, while pointer is not null,
  544. // a. For each Private Name binding of pointer.[[Names]], do
  545. // i. If privateIdentifiers does not contain binding.[[Description]], append binding.[[Description]] to privateIdentifiers.
  546. // b. Set pointer to pointer.[[OuterPrivateEnvironment]].
  547. // 7. If AllPrivateIdentifiersValid of body with argument privateIdentifiers is false, throw a SyntaxError exception.
  548. // FIXME: Add Private identifiers check here.
  549. // 8. Let functionsToInitialize be a new empty List.
  550. Vector<FunctionDeclaration const&> functions_to_initialize;
  551. // 9. Let declaredFunctionNames be a new empty List.
  552. HashTable<FlyString> declared_function_names;
  553. // 10. For each element d of varDeclarations, in reverse List order, do
  554. TRY(program.for_each_var_function_declaration_in_reverse_order([&](FunctionDeclaration const& function) -> ThrowCompletionOr<void> {
  555. // a. If d is neither a VariableDeclaration nor a ForBinding nor a BindingIdentifier, then
  556. // i. Assert: d is either a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration.
  557. // Note: This is done by for_each_var_function_declaration_in_reverse_order.
  558. // ii. NOTE: If there are multiple function declarations for the same name, the last declaration is used.
  559. // iii. Let fn be the sole element of the BoundNames of d.
  560. // iv. If fn is not an element of declaredFunctionNames, then
  561. if (declared_function_names.set(function.name()) != AK::HashSetResult::InsertedNewEntry)
  562. return {};
  563. // 1. If varEnv is a global Environment Record, then
  564. if (global_var_environment) {
  565. // a. Let fnDefinable be ? varEnv.CanDeclareGlobalFunction(fn).
  566. auto function_definable = TRY(global_var_environment->can_declare_global_function(function.name()));
  567. // b. If fnDefinable is false, throw a TypeError exception.
  568. if (!function_definable)
  569. return vm.throw_completion<TypeError>(global_object, ErrorType::CannotDeclareGlobalFunction, function.name());
  570. }
  571. // 2. Append fn to declaredFunctionNames.
  572. // Note: Already done in step iv.
  573. // 3. Insert d as the first element of functionsToInitialize.
  574. functions_to_initialize.append(function);
  575. return {};
  576. }));
  577. // 11. NOTE: Annex B.3.2.3 adds additional steps at this point.
  578. // B.3.2.3 Changes to EvalDeclarationInstantiation, https://tc39.es/ecma262/#sec-web-compat-evaldeclarationinstantiation
  579. // 11. If strict is false, then
  580. if (!strict) {
  581. // a. Let declaredFunctionOrVarNames be the list-concatenation of declaredFunctionNames and declaredVarNames.
  582. // The spec here uses 'declaredVarNames' but that has not been declared yet.
  583. HashTable<FlyString> hoisted_functions;
  584. // b. For each FunctionDeclaration f that is directly contained in the StatementList of a Block, CaseClause, or DefaultClause Contained within body, do
  585. TRY(program.for_each_function_hoistable_with_annexB_extension([&](FunctionDeclaration& function_declaration) -> ThrowCompletionOr<void> {
  586. // i. Let F be StringValue of the BindingIdentifier of f.
  587. auto& function_name = function_declaration.name();
  588. // ii. If replacing the FunctionDeclaration f with a VariableStatement that has F as a BindingIdentifier would not produce any Early Errors for body, then
  589. // Note: This is checked during parsing and for_each_function_hoistable_with_annexB_extension so it always passes here.
  590. // 1. Let bindingExists be false.
  591. // 2. Let thisEnv be lexEnv.
  592. auto* this_environment = lexical_environment;
  593. // 3. Assert: The following loop will terminate.
  594. // 4. Repeat, while thisEnv is not the same as varEnv,
  595. while (this_environment != variable_environment) {
  596. // a. If thisEnv is not an object Environment Record, then
  597. if (!is<ObjectEnvironment>(*this_environment)) {
  598. // i. If thisEnv.HasBinding(F) is true, then
  599. if (MUST(this_environment->has_binding(function_name))) {
  600. // i. Let bindingExists be true.
  601. // Note: When bindingExists is true we skip all the other steps.
  602. return {};
  603. }
  604. }
  605. // b. Set thisEnv to thisEnv.[[OuterEnv]].
  606. this_environment = this_environment->outer_environment();
  607. VERIFY(this_environment);
  608. }
  609. // Note: At this point bindingExists is false.
  610. // 5. If bindingExists is false and varEnv is a global Environment Record, then
  611. if (global_var_environment) {
  612. // a. If varEnv.HasLexicalDeclaration(F) is false, then
  613. if (!global_var_environment->has_lexical_declaration(function_name)) {
  614. // i. Let fnDefinable be ? varEnv.CanDeclareGlobalVar(F).
  615. if (!TRY(global_var_environment->can_declare_global_var(function_name)))
  616. return {};
  617. }
  618. // b. Else,
  619. else {
  620. // i. Let fnDefinable be false.
  621. return {};
  622. }
  623. }
  624. // 6. Else,
  625. // a. Let fnDefinable be true.
  626. // Note: At this point fnDefinable is true.
  627. // 7. If bindingExists is false and fnDefinable is true, then
  628. // a. If declaredFunctionOrVarNames does not contain F, then
  629. if (!declared_function_names.contains(function_name) && !hoisted_functions.contains(function_name)) {
  630. // i. If varEnv is a global Environment Record, then
  631. if (global_var_environment) {
  632. // i. Perform ? varEnv.CreateGlobalVarBinding(F, true).
  633. TRY(global_var_environment->create_global_var_binding(function_name, true));
  634. }
  635. // ii. Else,
  636. else {
  637. // i. Let bindingExists be varEnv.HasBinding(F).
  638. // ii. If bindingExists is false, then
  639. if (!MUST(variable_environment->has_binding(function_name))) {
  640. // i. Perform ! varEnv.CreateMutableBinding(F, true).
  641. // ii. Perform ! varEnv.InitializeBinding(F, undefined).
  642. MUST(variable_environment->create_mutable_binding(global_object, function_name, true));
  643. MUST(variable_environment->initialize_binding(global_object, function_name, js_undefined()));
  644. }
  645. }
  646. }
  647. // iii. Append F to declaredFunctionOrVarNames.
  648. hoisted_functions.set(function_name);
  649. // b. When the FunctionDeclaration f is evaluated, perform the following steps in place of the FunctionDeclaration Evaluation algorithm provided in 15.2.6:
  650. // i. Let genv be the running execution context's VariableEnvironment.
  651. // ii. Let benv be the running execution context's LexicalEnvironment.
  652. // iii. Let fobj be ! benv.GetBindingValue(F, false).
  653. // iv. Perform ? genv.SetMutableBinding(F, fobj, false).
  654. // v. Return NormalCompletion(empty).
  655. function_declaration.set_should_do_additional_annexB_steps();
  656. return {};
  657. }));
  658. }
  659. // 12. Let declaredVarNames be a new empty List.
  660. HashTable<FlyString> declared_var_names;
  661. // 13. For each element d of varDeclarations, do
  662. TRY(program.for_each_var_scoped_variable_declaration([&](VariableDeclaration const& declaration) {
  663. // a. If d is a VariableDeclaration, a ForBinding, or a BindingIdentifier, then
  664. // Note: This is handled by for_each_var_scoped_variable_declaration.
  665. // i. For each String vn of the BoundNames of d, do
  666. return declaration.for_each_bound_name([&](auto const& name) -> ThrowCompletionOr<void> {
  667. // 1. If vn is not an element of declaredFunctionNames, then
  668. if (!declared_function_names.contains(name)) {
  669. // a. If varEnv is a global Environment Record, then
  670. if (global_var_environment) {
  671. // i. Let vnDefinable be ? varEnv.CanDeclareGlobalVar(vn).
  672. auto variable_definable = TRY(global_var_environment->can_declare_global_var(name));
  673. // ii. If vnDefinable is false, throw a TypeError exception.
  674. if (!variable_definable)
  675. return vm.throw_completion<TypeError>(global_object, ErrorType::CannotDeclareGlobalVariable, name);
  676. }
  677. // b. If vn is not an element of declaredVarNames, then
  678. // i. Append vn to declaredVarNames.
  679. declared_var_names.set(name);
  680. }
  681. return {};
  682. });
  683. }));
  684. // 14. NOTE: No abnormal terminations occur after this algorithm step unless varEnv is a global Environment Record and the global object is a Proxy exotic object.
  685. // 15. Let lexDeclarations be the LexicallyScopedDeclarations of body.
  686. // 16. For each element d of lexDeclarations, do
  687. TRY(program.for_each_lexically_scoped_declaration([&](Declaration const& declaration) {
  688. // a. NOTE: Lexically declared names are only instantiated here but not initialized.
  689. // b. For each element dn of the BoundNames of d, do
  690. return declaration.for_each_bound_name([&](auto const& name) -> ThrowCompletionOr<void> {
  691. // i. If IsConstantDeclaration of d is true, then
  692. if (declaration.is_constant_declaration()) {
  693. // 1. Perform ? lexEnv.CreateImmutableBinding(dn, true).
  694. TRY(lexical_environment->create_immutable_binding(global_object, name, true));
  695. }
  696. // ii. Else,
  697. else {
  698. // 1. Perform ? lexEnv.CreateMutableBinding(dn, false).
  699. TRY(lexical_environment->create_mutable_binding(global_object, name, false));
  700. }
  701. return {};
  702. });
  703. }));
  704. // 17. For each Parse Node f of functionsToInitialize, do
  705. for (auto& declaration : functions_to_initialize) {
  706. // a. Let fn be the sole element of the BoundNames of f.
  707. // b. Let fo be InstantiateFunctionObject of f with arguments lexEnv and privateEnv.
  708. auto* function = ECMAScriptFunctionObject::create(global_object, declaration.name(), declaration.source_text(), declaration.body(), declaration.parameters(), declaration.function_length(), lexical_environment, private_environment, declaration.kind(), declaration.is_strict_mode(), declaration.might_need_arguments_object());
  709. // c. If varEnv is a global Environment Record, then
  710. if (global_var_environment) {
  711. // i. Perform ? varEnv.CreateGlobalFunctionBinding(fn, fo, true).
  712. TRY(global_var_environment->create_global_function_binding(declaration.name(), function, true));
  713. }
  714. // d. Else,
  715. else {
  716. // i. Let bindingExists be varEnv.HasBinding(fn).
  717. auto binding_exists = MUST(variable_environment->has_binding(declaration.name()));
  718. // ii. If bindingExists is false, then
  719. if (!binding_exists) {
  720. // 1. Let status be ! varEnv.CreateMutableBinding(fn, true).
  721. // 2. Assert: status is not an abrupt completion because of validation preceding step 14.
  722. MUST(variable_environment->create_mutable_binding(global_object, declaration.name(), true));
  723. // 3. Perform ! varEnv.InitializeBinding(fn, fo).
  724. MUST(variable_environment->initialize_binding(global_object, declaration.name(), function));
  725. }
  726. // iii. Else,
  727. else {
  728. // 1. Perform ! varEnv.SetMutableBinding(fn, fo, false).
  729. MUST(variable_environment->set_mutable_binding(global_object, declaration.name(), function, false));
  730. }
  731. }
  732. }
  733. // 18. For each String vn of declaredVarNames, do
  734. for (auto& var_name : declared_var_names) {
  735. // a. If varEnv is a global Environment Record, then
  736. if (global_var_environment) {
  737. // i. Perform ? varEnv.CreateGlobalVarBinding(vn, true).
  738. TRY(global_var_environment->create_global_var_binding(var_name, true));
  739. }
  740. // b. Else,
  741. else {
  742. // i. Let bindingExists be varEnv.HasBinding(vn).
  743. auto binding_exists = MUST(variable_environment->has_binding(var_name));
  744. // ii. If bindingExists is false, then
  745. if (!binding_exists) {
  746. // 1. Let status be ! varEnv.CreateMutableBinding(vn, true).
  747. // 2. Assert: status is not an abrupt completion because of validation preceding step 14.
  748. MUST(variable_environment->create_mutable_binding(global_object, var_name, true));
  749. // 3. Perform ! varEnv.InitializeBinding(vn, undefined).
  750. MUST(variable_environment->initialize_binding(global_object, var_name, js_undefined()));
  751. }
  752. }
  753. }
  754. // 19. Return NormalCompletion(empty).
  755. return {};
  756. }
  757. // 10.4.4.6 CreateUnmappedArgumentsObject ( argumentsList ), https://tc39.es/ecma262/#sec-createunmappedargumentsobject
  758. Object* create_unmapped_arguments_object(GlobalObject& global_object, Span<Value> arguments)
  759. {
  760. auto& vm = global_object.vm();
  761. // 1. Let len be the number of elements in argumentsList.
  762. auto length = arguments.size();
  763. // 2. Let obj be ! OrdinaryObjectCreate(%Object.prototype%, « [[ParameterMap]] »).
  764. // 3. Set obj.[[ParameterMap]] to undefined.
  765. auto* object = Object::create(global_object, global_object.object_prototype());
  766. object->set_has_parameter_map();
  767. // 4. Perform DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
  768. MUST(object->define_property_or_throw(vm.names.length, { .value = Value(length), .writable = true, .enumerable = false, .configurable = true }));
  769. // 5. Let index be 0.
  770. // 6. Repeat, while index < len,
  771. for (size_t index = 0; index < length; ++index) {
  772. // a. Let val be argumentsList[index].
  773. auto value = arguments[index];
  774. // b. Perform ! CreateDataPropertyOrThrow(obj, ! ToString(𝔽(index)), val).
  775. MUST(object->create_data_property_or_throw(index, value));
  776. // c. Set index to index + 1.
  777. }
  778. // 7. Perform ! DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor { [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
  779. auto* array_prototype_values = global_object.array_prototype_values_function();
  780. MUST(object->define_property_or_throw(*vm.well_known_symbol_iterator(), { .value = array_prototype_values, .writable = true, .enumerable = false, .configurable = true }));
  781. // 8. Perform ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Get]]: %ThrowTypeError%, [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false }).
  782. auto* throw_type_error = global_object.throw_type_error_function();
  783. MUST(object->define_property_or_throw(vm.names.callee, { .get = throw_type_error, .set = throw_type_error, .enumerable = false, .configurable = false }));
  784. // 9. Return obj.
  785. return object;
  786. }
  787. // 10.4.4.7 CreateMappedArgumentsObject ( func, formals, argumentsList, env ), https://tc39.es/ecma262/#sec-createmappedargumentsobject
  788. Object* create_mapped_arguments_object(GlobalObject& global_object, FunctionObject& function, Vector<FunctionNode::Parameter> const& formals, Span<Value> arguments, Environment& environment)
  789. {
  790. auto& vm = global_object.vm();
  791. // 1. Assert: formals does not contain a rest parameter, any binding patterns, or any initializers. It may contain duplicate identifiers.
  792. // 2. Let len be the number of elements in argumentsList.
  793. VERIFY(arguments.size() <= NumericLimits<i32>::max());
  794. i32 length = static_cast<i32>(arguments.size());
  795. // 3. Let obj be ! MakeBasicObject(« [[Prototype]], [[Extensible]], [[ParameterMap]] »).
  796. // 4. Set obj.[[GetOwnProperty]] as specified in 10.4.4.1.
  797. // 5. Set obj.[[DefineOwnProperty]] as specified in 10.4.4.2.
  798. // 6. Set obj.[[Get]] as specified in 10.4.4.3.
  799. // 7. Set obj.[[Set]] as specified in 10.4.4.4.
  800. // 8. Set obj.[[Delete]] as specified in 10.4.4.5.
  801. // 9. Set obj.[[Prototype]] to %Object.prototype%.
  802. auto* object = vm.heap().allocate<ArgumentsObject>(global_object, global_object, environment);
  803. // 14. Let index be 0.
  804. // 15. Repeat, while index < len,
  805. for (i32 index = 0; index < length; ++index) {
  806. // a. Let val be argumentsList[index].
  807. auto value = arguments[index];
  808. // b. Perform ! CreateDataPropertyOrThrow(obj, ! ToString(𝔽(index)), val).
  809. MUST(object->create_data_property_or_throw(index, value));
  810. // c. Set index to index + 1.
  811. }
  812. // 16. Perform ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
  813. MUST(object->define_property_or_throw(vm.names.length, { .value = Value(length), .writable = true, .enumerable = false, .configurable = true }));
  814. // 17. Let mappedNames be a new empty List.
  815. HashTable<FlyString> mapped_names;
  816. // 18. Set index to numberOfParameters - 1.
  817. // 19. Repeat, while index ≥ 0,
  818. VERIFY(formals.size() <= NumericLimits<i32>::max());
  819. for (i32 index = static_cast<i32>(formals.size()) - 1; index >= 0; --index) {
  820. // a. Let name be parameterNames[index].
  821. auto const& name = formals[index].binding.get<FlyString>();
  822. // b. If name is not an element of mappedNames, then
  823. if (mapped_names.contains(name))
  824. continue;
  825. // i. Add name as an element of the list mappedNames.
  826. mapped_names.set(name);
  827. // ii. If index < len, then
  828. if (index < length) {
  829. // 1. Let g be MakeArgGetter(name, env).
  830. // 2. Let p be MakeArgSetter(name, env).
  831. // 3. Perform map.[[DefineOwnProperty]](! ToString(𝔽(index)), PropertyDescriptor { [[Set]]: p, [[Get]]: g, [[Enumerable]]: false, [[Configurable]]: true }).
  832. object->parameter_map().define_native_accessor(
  833. PropertyKey { index },
  834. [&environment, name](VM&, GlobalObject& global_object_getter) -> JS::ThrowCompletionOr<Value> {
  835. return MUST(environment.get_binding_value(global_object_getter, name, false));
  836. },
  837. [&environment, name](VM& vm, GlobalObject& global_object_setter) {
  838. MUST(environment.set_mutable_binding(global_object_setter, name, vm.argument(0), false));
  839. return js_undefined();
  840. },
  841. Attribute::Configurable);
  842. }
  843. }
  844. // 20. Perform ! DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor { [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
  845. auto* array_prototype_values = global_object.array_prototype_values_function();
  846. MUST(object->define_property_or_throw(*vm.well_known_symbol_iterator(), { .value = array_prototype_values, .writable = true, .enumerable = false, .configurable = true }));
  847. // 21. Perform ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Value]]: func, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
  848. MUST(object->define_property_or_throw(vm.names.callee, { .value = &function, .writable = true, .enumerable = false, .configurable = true }));
  849. // 22. Return obj.
  850. return object;
  851. }
  852. // 7.1.21 CanonicalNumericIndexString ( argument ), https://tc39.es/ecma262/#sec-canonicalnumericindexstring
  853. CanonicalIndex canonical_numeric_index_string(PropertyKey const& property_key, CanonicalIndexMode mode)
  854. {
  855. // NOTE: If the property name is a number type (An implementation-defined optimized
  856. // property key type), it can be treated as a string property that has already been
  857. // converted successfully into a canonical numeric index.
  858. VERIFY(property_key.is_string() || property_key.is_number());
  859. if (property_key.is_number())
  860. return CanonicalIndex(CanonicalIndex::Type::Index, property_key.as_number());
  861. if (mode != CanonicalIndexMode::DetectNumericRoundtrip)
  862. return CanonicalIndex(CanonicalIndex::Type::Undefined, 0);
  863. // 1. Assert: Type(argument) is String.
  864. auto& argument = property_key.as_string();
  865. // Handle trivial cases without a full round trip test
  866. // We do not need to check for argument == "0" at this point because we
  867. // already covered it with the is_number() == true path.
  868. if (argument.is_empty())
  869. return CanonicalIndex(CanonicalIndex::Type::Undefined, 0);
  870. u32 current_index = 0;
  871. if (argument.characters()[current_index] == '-') {
  872. current_index++;
  873. if (current_index == argument.length())
  874. return CanonicalIndex(CanonicalIndex::Type::Undefined, 0);
  875. }
  876. if (argument.characters()[current_index] == '0') {
  877. current_index++;
  878. if (current_index == argument.length())
  879. return CanonicalIndex(CanonicalIndex::Type::Numeric, 0);
  880. if (argument.characters()[current_index] != '.')
  881. return CanonicalIndex(CanonicalIndex::Type::Undefined, 0);
  882. current_index++;
  883. if (current_index == argument.length())
  884. return CanonicalIndex(CanonicalIndex::Type::Undefined, 0);
  885. }
  886. // Short circuit a few common cases
  887. if (argument == "Infinity" || argument == "-Infinity" || argument == "NaN")
  888. return CanonicalIndex(CanonicalIndex::Type::Numeric, 0);
  889. // Short circuit any string that doesn't start with digits
  890. if (char first_non_zero = argument.characters()[current_index]; first_non_zero < '0' || first_non_zero > '9')
  891. return CanonicalIndex(CanonicalIndex::Type::Undefined, 0);
  892. // 3. Let n be ! ToNumber(argument).
  893. char* endptr;
  894. auto n = Value(strtod(argument.characters(), &endptr));
  895. if (endptr != argument.characters() + argument.length())
  896. return CanonicalIndex(CanonicalIndex::Type::Undefined, 0);
  897. // 4. If SameValue(! ToString(n), argument) is false, return undefined.
  898. if (n.to_string_without_side_effects() != argument)
  899. return CanonicalIndex(CanonicalIndex::Type::Undefined, 0);
  900. // 5. Return n.
  901. return CanonicalIndex(CanonicalIndex::Type::Numeric, 0);
  902. }
  903. // 22.1.3.17.1 GetSubstitution ( matched, str, position, captures, namedCaptures, replacement ), https://tc39.es/ecma262/#sec-getsubstitution
  904. ThrowCompletionOr<String> get_substitution(GlobalObject& global_object, Utf16View const& matched, Utf16View const& str, size_t position, Span<Value> captures, Value named_captures, Value replacement)
  905. {
  906. auto replace_string = TRY(replacement.to_utf16_string(global_object));
  907. auto replace_view = replace_string.view();
  908. StringBuilder result;
  909. for (size_t i = 0; i < replace_view.length_in_code_units(); ++i) {
  910. u16 curr = replace_view.code_unit_at(i);
  911. if ((curr != '$') || (i + 1 >= replace_view.length_in_code_units())) {
  912. result.append(curr);
  913. continue;
  914. }
  915. u16 next = replace_view.code_unit_at(i + 1);
  916. if (next == '$') {
  917. result.append('$');
  918. ++i;
  919. } else if (next == '&') {
  920. result.append(matched);
  921. ++i;
  922. } else if (next == '`') {
  923. auto substring = str.substring_view(0, position);
  924. result.append(substring);
  925. ++i;
  926. } else if (next == '\'') {
  927. auto tail_pos = position + matched.length_in_code_units();
  928. if (tail_pos < str.length_in_code_units()) {
  929. auto substring = str.substring_view(tail_pos);
  930. result.append(substring);
  931. }
  932. ++i;
  933. } else if (is_ascii_digit(next)) {
  934. bool is_two_digits = (i + 2 < replace_view.length_in_code_units()) && is_ascii_digit(replace_view.code_unit_at(i + 2));
  935. auto capture_postition_string = replace_view.substring_view(i + 1, is_two_digits ? 2 : 1).to_utf8();
  936. auto capture_position = capture_postition_string.to_uint();
  937. if (capture_position.has_value() && (*capture_position > 0) && (*capture_position <= captures.size())) {
  938. auto& value = captures[*capture_position - 1];
  939. if (!value.is_undefined()) {
  940. auto value_string = TRY(value.to_string(global_object));
  941. result.append(value_string);
  942. }
  943. i += is_two_digits ? 2 : 1;
  944. } else {
  945. result.append(curr);
  946. }
  947. } else if (next == '<') {
  948. auto start_position = i + 2;
  949. Optional<size_t> end_position;
  950. for (size_t j = start_position; j < replace_view.length_in_code_units(); ++j) {
  951. if (replace_view.code_unit_at(j) == '>') {
  952. end_position = j;
  953. break;
  954. }
  955. }
  956. if (named_captures.is_undefined() || !end_position.has_value()) {
  957. result.append(curr);
  958. } else {
  959. auto group_name_view = replace_view.substring_view(start_position, *end_position - start_position);
  960. auto group_name = group_name_view.to_utf8(Utf16View::AllowInvalidCodeUnits::Yes);
  961. auto capture = TRY(named_captures.as_object().get(group_name));
  962. if (!capture.is_undefined()) {
  963. auto capture_string = TRY(capture.to_string(global_object));
  964. result.append(capture_string);
  965. }
  966. i = *end_position;
  967. }
  968. } else {
  969. result.append(curr);
  970. }
  971. }
  972. return result.build();
  973. }
  974. }