ECMAScriptFunctionObject.cpp 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104
  1. /*
  2. * Copyright (c) 2020, Stephan Unverwerth <s.unverwerth@serenityos.org>
  3. * Copyright (c) 2020-2023, Linus Groh <linusg@serenityos.org>
  4. * Copyright (c) 2023, Andreas Kling <kling@serenityos.org>
  5. * Copyright (c) 2023, Shannon Booth <shannon@serenityos.org>
  6. *
  7. * SPDX-License-Identifier: BSD-2-Clause
  8. */
  9. #include <AK/Debug.h>
  10. #include <AK/Function.h>
  11. #include <LibJS/AST.h>
  12. #include <LibJS/Bytecode/BasicBlock.h>
  13. #include <LibJS/Bytecode/Generator.h>
  14. #include <LibJS/Bytecode/Interpreter.h>
  15. #include <LibJS/Runtime/AbstractOperations.h>
  16. #include <LibJS/Runtime/Array.h>
  17. #include <LibJS/Runtime/AsyncFunctionDriverWrapper.h>
  18. #include <LibJS/Runtime/AsyncGenerator.h>
  19. #include <LibJS/Runtime/ECMAScriptFunctionObject.h>
  20. #include <LibJS/Runtime/Error.h>
  21. #include <LibJS/Runtime/ExecutionContext.h>
  22. #include <LibJS/Runtime/FunctionEnvironment.h>
  23. #include <LibJS/Runtime/GeneratorObject.h>
  24. #include <LibJS/Runtime/GlobalEnvironment.h>
  25. #include <LibJS/Runtime/GlobalObject.h>
  26. #include <LibJS/Runtime/NativeFunction.h>
  27. #include <LibJS/Runtime/PromiseCapability.h>
  28. #include <LibJS/Runtime/PromiseConstructor.h>
  29. #include <LibJS/Runtime/Value.h>
  30. namespace JS {
  31. NonnullGCPtr<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, DeprecatedFlyString name, DeprecatedString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> parameters, i32 m_function_length, Vector<DeprecatedFlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
  32. {
  33. Object* prototype = nullptr;
  34. switch (kind) {
  35. case FunctionKind::Normal:
  36. prototype = realm.intrinsics().function_prototype();
  37. break;
  38. case FunctionKind::Generator:
  39. prototype = realm.intrinsics().generator_function_prototype();
  40. break;
  41. case FunctionKind::Async:
  42. prototype = realm.intrinsics().async_function_prototype();
  43. break;
  44. case FunctionKind::AsyncGenerator:
  45. prototype = realm.intrinsics().async_generator_function_prototype();
  46. break;
  47. }
  48. return realm.heap().allocate<ECMAScriptFunctionObject>(realm, move(name), move(source_text), ecmascript_code, move(parameters), m_function_length, move(local_variables_names), parent_environment, private_environment, *prototype, kind, is_strict, might_need_arguments_object, contains_direct_call_to_eval, is_arrow_function, move(class_field_initializer_name)).release_allocated_value_but_fixme_should_propagate_errors();
  49. }
  50. NonnullGCPtr<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, DeprecatedFlyString name, Object& prototype, DeprecatedString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> parameters, i32 m_function_length, Vector<DeprecatedFlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
  51. {
  52. return realm.heap().allocate<ECMAScriptFunctionObject>(realm, move(name), move(source_text), ecmascript_code, move(parameters), m_function_length, move(local_variables_names), parent_environment, private_environment, prototype, kind, is_strict, might_need_arguments_object, contains_direct_call_to_eval, is_arrow_function, move(class_field_initializer_name)).release_allocated_value_but_fixme_should_propagate_errors();
  53. }
  54. ECMAScriptFunctionObject::ECMAScriptFunctionObject(DeprecatedFlyString name, DeprecatedString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> formal_parameters, i32 function_length, Vector<DeprecatedFlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, Object& prototype, FunctionKind kind, bool strict, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
  55. : FunctionObject(prototype)
  56. , m_name(move(name))
  57. , m_function_length(function_length)
  58. , m_local_variables_names(move(local_variables_names))
  59. , m_environment(parent_environment)
  60. , m_private_environment(private_environment)
  61. , m_formal_parameters(move(formal_parameters))
  62. , m_ecmascript_code(ecmascript_code)
  63. , m_realm(&prototype.shape().realm())
  64. , m_source_text(move(source_text))
  65. , m_class_field_initializer_name(move(class_field_initializer_name))
  66. , m_strict(strict)
  67. , m_might_need_arguments_object(might_need_arguments_object)
  68. , m_contains_direct_call_to_eval(contains_direct_call_to_eval)
  69. , m_is_arrow_function(is_arrow_function)
  70. , m_kind(kind)
  71. {
  72. // NOTE: This logic is from OrdinaryFunctionCreate, https://tc39.es/ecma262/#sec-ordinaryfunctioncreate
  73. // 9. If thisMode is lexical-this, set F.[[ThisMode]] to lexical.
  74. if (m_is_arrow_function)
  75. m_this_mode = ThisMode::Lexical;
  76. // 10. Else if Strict is true, set F.[[ThisMode]] to strict.
  77. else if (m_strict)
  78. m_this_mode = ThisMode::Strict;
  79. else
  80. // 11. Else, set F.[[ThisMode]] to global.
  81. m_this_mode = ThisMode::Global;
  82. // 15. Set F.[[ScriptOrModule]] to GetActiveScriptOrModule().
  83. m_script_or_module = vm().get_active_script_or_module();
  84. // 15.1.3 Static Semantics: IsSimpleParameterList, https://tc39.es/ecma262/#sec-static-semantics-issimpleparameterlist
  85. m_has_simple_parameter_list = all_of(m_formal_parameters, [&](auto& parameter) {
  86. if (parameter.is_rest)
  87. return false;
  88. if (parameter.default_value)
  89. return false;
  90. if (!parameter.binding.template has<NonnullRefPtr<Identifier const>>())
  91. return false;
  92. return true;
  93. });
  94. }
  95. void ECMAScriptFunctionObject::initialize(Realm& realm)
  96. {
  97. auto& vm = this->vm();
  98. Base::initialize(realm);
  99. // Note: The ordering of these properties must be: length, name, prototype which is the order
  100. // they are defined in the spec: https://tc39.es/ecma262/#sec-function-instances .
  101. // This is observable through something like: https://tc39.es/ecma262/#sec-ordinaryownpropertykeys
  102. // which must give the properties in chronological order which in this case is the order they
  103. // are defined in the spec.
  104. MUST(define_property_or_throw(vm.names.length, { .value = Value(m_function_length), .writable = false, .enumerable = false, .configurable = true }));
  105. MUST(define_property_or_throw(vm.names.name, { .value = PrimitiveString::create(vm, m_name.is_null() ? "" : m_name), .writable = false, .enumerable = false, .configurable = true }));
  106. if (!m_is_arrow_function) {
  107. Object* prototype = nullptr;
  108. switch (m_kind) {
  109. case FunctionKind::Normal:
  110. prototype = MUST(vm.heap().allocate<Object>(realm, realm.intrinsics().new_ordinary_function_prototype_object_shape()));
  111. MUST(prototype->define_property_or_throw(vm.names.constructor, { .value = this, .writable = true, .enumerable = false, .configurable = true }));
  112. break;
  113. case FunctionKind::Generator:
  114. // prototype is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png)
  115. prototype = Object::create(realm, realm.intrinsics().generator_function_prototype_prototype());
  116. break;
  117. case FunctionKind::Async:
  118. break;
  119. case FunctionKind::AsyncGenerator:
  120. prototype = Object::create(realm, realm.intrinsics().async_generator_function_prototype_prototype());
  121. break;
  122. }
  123. // 27.7.4 AsyncFunction Instances, https://tc39.es/ecma262/#sec-async-function-instances
  124. // AsyncFunction instances do not have a prototype property as they are not constructible.
  125. if (m_kind != FunctionKind::Async)
  126. define_direct_property(vm.names.prototype, prototype, Attribute::Writable);
  127. }
  128. }
  129. // 10.2.1 [[Call]] ( thisArgument, argumentsList ), https://tc39.es/ecma262/#sec-ecmascript-function-objects-call-thisargument-argumentslist
  130. ThrowCompletionOr<Value> ECMAScriptFunctionObject::internal_call(Value this_argument, MarkedVector<Value> arguments_list)
  131. {
  132. auto& vm = this->vm();
  133. // 1. Let callerContext be the running execution context.
  134. // NOTE: No-op, kept by the VM in its execution context stack.
  135. ExecutionContext callee_context(heap());
  136. callee_context.local_variables.resize(m_local_variables_names.size());
  137. // Non-standard
  138. callee_context.arguments.extend(move(arguments_list));
  139. // 2. Let calleeContext be PrepareForOrdinaryCall(F, undefined).
  140. // NOTE: We throw if the end of the native stack is reached, so unlike in the spec this _does_ need an exception check.
  141. TRY(prepare_for_ordinary_call(callee_context, nullptr));
  142. // 3. Assert: calleeContext is now the running execution context.
  143. VERIFY(&vm.running_execution_context() == &callee_context);
  144. // 4. If F.[[IsClassConstructor]] is true, then
  145. if (m_is_class_constructor) {
  146. // a. Let error be a newly created TypeError object.
  147. // b. NOTE: error is created in calleeContext with F's associated Realm Record.
  148. auto throw_completion = vm.throw_completion<TypeError>(ErrorType::ClassConstructorWithoutNew, m_name);
  149. // c. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  150. vm.pop_execution_context();
  151. // d. Return ThrowCompletion(error).
  152. return throw_completion;
  153. }
  154. // 5. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
  155. ordinary_call_bind_this(callee_context, this_argument);
  156. // 6. Let result be Completion(OrdinaryCallEvaluateBody(F, argumentsList)).
  157. auto result = ordinary_call_evaluate_body();
  158. // 7. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  159. vm.pop_execution_context();
  160. // 8. If result.[[Type]] is return, return result.[[Value]].
  161. if (result.type() == Completion::Type::Return)
  162. return *result.value();
  163. // 9. ReturnIfAbrupt(result).
  164. if (result.is_abrupt()) {
  165. VERIFY(result.is_error());
  166. return result;
  167. }
  168. // 10. Return undefined.
  169. return js_undefined();
  170. }
  171. // 10.2.2 [[Construct]] ( argumentsList, newTarget ), https://tc39.es/ecma262/#sec-ecmascript-function-objects-construct-argumentslist-newtarget
  172. ThrowCompletionOr<NonnullGCPtr<Object>> ECMAScriptFunctionObject::internal_construct(MarkedVector<Value> arguments_list, FunctionObject& new_target)
  173. {
  174. auto& vm = this->vm();
  175. // 1. Let callerContext be the running execution context.
  176. // NOTE: No-op, kept by the VM in its execution context stack.
  177. // 2. Let kind be F.[[ConstructorKind]].
  178. auto kind = m_constructor_kind;
  179. GCPtr<Object> this_argument;
  180. // 3. If kind is base, then
  181. if (kind == ConstructorKind::Base) {
  182. // a. Let thisArgument be ? OrdinaryCreateFromConstructor(newTarget, "%Object.prototype%").
  183. this_argument = TRY(ordinary_create_from_constructor<Object>(vm, new_target, &Intrinsics::object_prototype, ConstructWithPrototypeTag::Tag));
  184. }
  185. ExecutionContext callee_context(heap());
  186. callee_context.local_variables.resize(m_local_variables_names.size());
  187. // Non-standard
  188. callee_context.arguments.extend(move(arguments_list));
  189. // 4. Let calleeContext be PrepareForOrdinaryCall(F, newTarget).
  190. // NOTE: We throw if the end of the native stack is reached, so unlike in the spec this _does_ need an exception check.
  191. TRY(prepare_for_ordinary_call(callee_context, &new_target));
  192. // 5. Assert: calleeContext is now the running execution context.
  193. VERIFY(&vm.running_execution_context() == &callee_context);
  194. // 6. If kind is base, then
  195. if (kind == ConstructorKind::Base) {
  196. // a. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
  197. ordinary_call_bind_this(callee_context, this_argument);
  198. // b. Let initializeResult be Completion(InitializeInstanceElements(thisArgument, F)).
  199. auto initialize_result = this_argument->initialize_instance_elements(*this);
  200. // c. If initializeResult is an abrupt completion, then
  201. if (initialize_result.is_throw_completion()) {
  202. // i. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  203. vm.pop_execution_context();
  204. // ii. Return ? initializeResult.
  205. return initialize_result.throw_completion();
  206. }
  207. }
  208. // 7. Let constructorEnv be the LexicalEnvironment of calleeContext.
  209. auto constructor_env = callee_context.lexical_environment;
  210. // 8. Let result be Completion(OrdinaryCallEvaluateBody(F, argumentsList)).
  211. auto result = ordinary_call_evaluate_body();
  212. // 9. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  213. vm.pop_execution_context();
  214. // 10. If result.[[Type]] is return, then
  215. if (result.type() == Completion::Type::Return) {
  216. // FIXME: This is leftover from untangling the call/construct mess - doesn't belong here in any way, but removing it breaks derived classes.
  217. // Likely fixed by making ClassDefinitionEvaluation fully spec compliant.
  218. if (kind == ConstructorKind::Derived && result.value()->is_object()) {
  219. auto prototype = TRY(new_target.get(vm.names.prototype));
  220. if (prototype.is_object())
  221. TRY(result.value()->as_object().internal_set_prototype_of(&prototype.as_object()));
  222. }
  223. // EOF (End of FIXME)
  224. // a. If Type(result.[[Value]]) is Object, return result.[[Value]].
  225. if (result.value()->is_object())
  226. return result.value()->as_object();
  227. // b. If kind is base, return thisArgument.
  228. if (kind == ConstructorKind::Base)
  229. return *this_argument;
  230. // c. If result.[[Value]] is not undefined, throw a TypeError exception.
  231. if (!result.value()->is_undefined())
  232. return vm.throw_completion<TypeError>(ErrorType::DerivedConstructorReturningInvalidValue);
  233. }
  234. // 11. Else, ReturnIfAbrupt(result).
  235. else if (result.is_abrupt()) {
  236. VERIFY(result.is_error());
  237. return result;
  238. }
  239. // 12. Let thisBinding be ? constructorEnv.GetThisBinding().
  240. auto this_binding = TRY(constructor_env->get_this_binding(vm));
  241. // 13. Assert: Type(thisBinding) is Object.
  242. VERIFY(this_binding.is_object());
  243. // 14. Return thisBinding.
  244. return this_binding.as_object();
  245. }
  246. void ECMAScriptFunctionObject::visit_edges(Visitor& visitor)
  247. {
  248. Base::visit_edges(visitor);
  249. visitor.visit(m_environment);
  250. visitor.visit(m_private_environment);
  251. visitor.visit(m_realm);
  252. visitor.visit(m_home_object);
  253. for (auto& field : m_fields) {
  254. if (auto* property_key_ptr = field.name.get_pointer<PropertyKey>(); property_key_ptr && property_key_ptr->is_symbol())
  255. visitor.visit(property_key_ptr->as_symbol());
  256. }
  257. m_script_or_module.visit(
  258. [](Empty) {},
  259. [&](auto& script_or_module) {
  260. visitor.visit(script_or_module.ptr());
  261. });
  262. }
  263. // 10.2.7 MakeMethod ( F, homeObject ), https://tc39.es/ecma262/#sec-makemethod
  264. void ECMAScriptFunctionObject::make_method(Object& home_object)
  265. {
  266. // 1. Set F.[[HomeObject]] to homeObject.
  267. m_home_object = &home_object;
  268. // 2. Return unused.
  269. }
  270. // 10.2.11 FunctionDeclarationInstantiation ( func, argumentsList ), https://tc39.es/ecma262/#sec-functiondeclarationinstantiation
  271. ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantiation()
  272. {
  273. auto& vm = this->vm();
  274. auto& realm = *vm.current_realm();
  275. // 1. Let calleeContext be the running execution context.
  276. auto& callee_context = vm.running_execution_context();
  277. // 2. Let code be func.[[ECMAScriptCode]].
  278. ScopeNode const* scope_body = nullptr;
  279. if (is<ScopeNode>(*m_ecmascript_code))
  280. scope_body = static_cast<ScopeNode const*>(m_ecmascript_code.ptr());
  281. // 3. Let strict be func.[[Strict]].
  282. bool const strict = is_strict_mode();
  283. bool has_parameter_expressions = false;
  284. // 4. Let formals be func.[[FormalParameters]].
  285. auto const& formals = m_formal_parameters;
  286. // FIXME: Maybe compute has duplicates at parse time? (We need to anyway since it's an error in some cases)
  287. // 5. Let parameterNames be the BoundNames of formals.
  288. // 6. If parameterNames has any duplicate entries, let hasDuplicates be true. Otherwise, let hasDuplicates be false.
  289. bool has_duplicates = false;
  290. HashTable<DeprecatedFlyString> parameter_names;
  291. // NOTE: This loop performs step 5, 6, and 8.
  292. for (auto const& parameter : formals) {
  293. if (parameter.default_value)
  294. has_parameter_expressions = true;
  295. parameter.binding.visit(
  296. [&](Identifier const& identifier) {
  297. if (parameter_names.set(identifier.string()) != AK::HashSetResult::InsertedNewEntry)
  298. has_duplicates = true;
  299. },
  300. [&](NonnullRefPtr<BindingPattern const> const& pattern) {
  301. if (pattern->contains_expression())
  302. has_parameter_expressions = true;
  303. // NOTE: Nothing in the callback throws an exception.
  304. MUST(pattern->for_each_bound_identifier([&](auto& identifier) {
  305. if (parameter_names.set(identifier.string()) != AK::HashSetResult::InsertedNewEntry)
  306. has_duplicates = true;
  307. }));
  308. });
  309. }
  310. // 7. Let simpleParameterList be IsSimpleParameterList of formals.
  311. bool const simple_parameter_list = has_simple_parameter_list();
  312. // 8. Let hasParameterExpressions be ContainsExpression of formals.
  313. // NOTE: Already set above.
  314. // 9. Let varNames be the VarDeclaredNames of code.
  315. // 10. Let varDeclarations be the VarScopedDeclarations of code.
  316. // 11. Let lexicalNames be the LexicallyDeclaredNames of code.
  317. // NOTE: Not needed as we use iteration helpers for this instead.
  318. // 12. Let functionNames be a new empty List.
  319. HashTable<DeprecatedFlyString> function_names;
  320. // 13. Let functionsToInitialize be a new empty List.
  321. Vector<FunctionDeclaration const&> functions_to_initialize;
  322. // 14. For each element d of varDeclarations, in reverse List order, do
  323. // a. If d is neither a VariableDeclaration nor a ForBinding nor a BindingIdentifier, then
  324. // i. Assert: d is either a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration.
  325. // ii. Let fn be the sole element of the BoundNames of d.
  326. // iii. If functionNames does not contain fn, then
  327. // 1. Insert fn as the first element of functionNames.
  328. // 2. NOTE: If there are multiple function declarations for the same name, the last declaration is used.
  329. // 3. Insert d as the first element of functionsToInitialize.
  330. // NOTE: This block is done in step 18 below.
  331. // 15. Let argumentsObjectNeeded be true.
  332. auto arguments_object_needed = m_might_need_arguments_object;
  333. // 16. If func.[[ThisMode]] is lexical, then
  334. if (this_mode() == ThisMode::Lexical) {
  335. // a. NOTE: Arrow functions never have an arguments object.
  336. // b. Set argumentsObjectNeeded to false.
  337. arguments_object_needed = false;
  338. }
  339. // 17. Else if parameterNames contains "arguments", then
  340. else if (parameter_names.contains(vm.names.arguments.as_string())) {
  341. // a. Set argumentsObjectNeeded to false.
  342. arguments_object_needed = false;
  343. }
  344. // 18. Else if hasParameterExpressions is false, then
  345. // a. If functionNames contains "arguments" or lexicalNames contains "arguments", then
  346. // i. Set argumentsObjectNeeded to false.
  347. // NOTE: The block below is a combination of step 14 and step 18.
  348. if (scope_body) {
  349. // NOTE: Nothing in the callback throws an exception.
  350. MUST(scope_body->for_each_var_function_declaration_in_reverse_order([&](FunctionDeclaration const& function) {
  351. if (function_names.set(function.name()) == AK::HashSetResult::InsertedNewEntry)
  352. functions_to_initialize.append(function);
  353. }));
  354. auto const& arguments_name = vm.names.arguments.as_string();
  355. if (!has_parameter_expressions && function_names.contains(arguments_name))
  356. arguments_object_needed = false;
  357. if (!has_parameter_expressions && arguments_object_needed) {
  358. // NOTE: Nothing in the callback throws an exception.
  359. MUST(scope_body->for_each_lexically_declared_identifier([&](auto const& identifier) {
  360. if (identifier.string() == arguments_name)
  361. arguments_object_needed = false;
  362. }));
  363. }
  364. } else {
  365. arguments_object_needed = false;
  366. }
  367. GCPtr<Environment> environment;
  368. // 19. If strict is true or hasParameterExpressions is false, then
  369. if (strict || !has_parameter_expressions) {
  370. // a. NOTE: Only a single Environment Record is needed for the parameters, since calls to eval in strict mode code cannot create new bindings which are visible outside of the eval.
  371. // b. Let env be the LexicalEnvironment of calleeContext.
  372. environment = callee_context.lexical_environment;
  373. }
  374. // 20. Else,
  375. else {
  376. // a. NOTE: A separate Environment Record is needed to ensure that bindings created by direct eval calls in the formal parameter list are outside the environment where parameters are declared.
  377. // b. Let calleeEnv be the LexicalEnvironment of calleeContext.
  378. auto callee_env = callee_context.lexical_environment;
  379. // c. Let env be NewDeclarativeEnvironment(calleeEnv).
  380. environment = new_declarative_environment(*callee_env);
  381. // d. Assert: The VariableEnvironment of calleeContext is calleeEnv.
  382. VERIFY(callee_context.variable_environment == callee_context.lexical_environment);
  383. // e. Set the LexicalEnvironment of calleeContext to env.
  384. callee_context.lexical_environment = environment;
  385. }
  386. // 21. For each String paramName of parameterNames, do
  387. for (auto const& parameter_name : parameter_names) {
  388. // a. Let alreadyDeclared be ! env.HasBinding(paramName).
  389. auto already_declared = MUST(environment->has_binding(parameter_name));
  390. // b. NOTE: Early errors ensure that duplicate parameter names can only occur in non-strict functions that do not have parameter default values or rest parameters.
  391. // c. If alreadyDeclared is false, then
  392. if (!already_declared) {
  393. // i. Perform ! env.CreateMutableBinding(paramName, false).
  394. MUST(environment->create_mutable_binding(vm, parameter_name, false));
  395. // ii. If hasDuplicates is true, then
  396. if (has_duplicates) {
  397. // 1. Perform ! env.InitializeBinding(paramName, undefined).
  398. MUST(environment->initialize_binding(vm, parameter_name, js_undefined(), Environment::InitializeBindingHint::Normal));
  399. }
  400. }
  401. }
  402. // 22. If argumentsObjectNeeded is true, then
  403. if (arguments_object_needed) {
  404. Object* arguments_object;
  405. // a. If strict is true or simpleParameterList is false, then
  406. if (strict || !simple_parameter_list) {
  407. // i. Let ao be CreateUnmappedArgumentsObject(argumentsList).
  408. arguments_object = create_unmapped_arguments_object(vm, vm.running_execution_context().arguments);
  409. }
  410. // b. Else,
  411. else {
  412. // i. NOTE: A mapped argument object is only provided for non-strict functions that don't have a rest parameter, any parameter default value initializers, or any destructured parameters.
  413. // ii. Let ao be CreateMappedArgumentsObject(func, formals, argumentsList, env).
  414. arguments_object = create_mapped_arguments_object(vm, *this, formal_parameters(), vm.running_execution_context().arguments, *environment);
  415. }
  416. // c. If strict is true, then
  417. if (strict) {
  418. // i. Perform ! env.CreateImmutableBinding("arguments", false).
  419. MUST(environment->create_immutable_binding(vm, vm.names.arguments.as_string(), false));
  420. // ii. NOTE: In strict mode code early errors prevent attempting to assign to this binding, so its mutability is not observable.
  421. }
  422. // b. Else,
  423. else {
  424. // i. Perform ! env.CreateMutableBinding("arguments", false).
  425. MUST(environment->create_mutable_binding(vm, vm.names.arguments.as_string(), false));
  426. }
  427. // c. Perform ! env.InitializeBinding("arguments", ao).
  428. MUST(environment->initialize_binding(vm, vm.names.arguments.as_string(), arguments_object, Environment::InitializeBindingHint::Normal));
  429. // f. Let parameterBindings be the list-concatenation of parameterNames and « "arguments" ».
  430. parameter_names.set(vm.names.arguments.as_string());
  431. }
  432. // 23. Else,
  433. else {
  434. // a. Let parameterBindings be parameterNames.
  435. }
  436. // NOTE: We now treat parameterBindings as parameterNames.
  437. // 24. Let iteratorRecord be CreateListIteratorRecord(argumentsList).
  438. // 25. If hasDuplicates is true, then
  439. // a. Perform ? IteratorBindingInitialization of formals with arguments iteratorRecord and undefined.
  440. // 26. Else,
  441. // a. Perform ? IteratorBindingInitialization of formals with arguments iteratorRecord and env.
  442. // NOTE: The spec makes an iterator here to do IteratorBindingInitialization but we just do it manually
  443. auto& execution_context_arguments = vm.running_execution_context().arguments;
  444. size_t default_parameter_index = 0;
  445. for (size_t i = 0; i < m_formal_parameters.size(); ++i) {
  446. auto& parameter = m_formal_parameters[i];
  447. if (parameter.default_value)
  448. ++default_parameter_index;
  449. TRY(parameter.binding.visit(
  450. [&](auto const& param) -> ThrowCompletionOr<void> {
  451. Value argument_value;
  452. if (parameter.is_rest) {
  453. auto array = MUST(Array::create(realm, 0));
  454. for (size_t rest_index = i; rest_index < execution_context_arguments.size(); ++rest_index)
  455. array->indexed_properties().append(execution_context_arguments[rest_index]);
  456. argument_value = array;
  457. } else if (i < execution_context_arguments.size() && !execution_context_arguments[i].is_undefined()) {
  458. argument_value = execution_context_arguments[i];
  459. } else if (parameter.default_value) {
  460. auto value_and_frame = vm.bytecode_interpreter().run_and_return_frame(realm, *m_default_parameter_bytecode_executables[default_parameter_index - 1], nullptr);
  461. if (value_and_frame.value.is_error())
  462. return value_and_frame.value.release_error();
  463. // Resulting value is in the accumulator.
  464. argument_value = value_and_frame.frame->registers.at(0);
  465. } else {
  466. argument_value = js_undefined();
  467. }
  468. Environment* used_environment = has_duplicates ? nullptr : environment;
  469. if constexpr (IsSame<NonnullRefPtr<Identifier const> const&, decltype(param)>) {
  470. if (param->is_local()) {
  471. callee_context.local_variables[param->local_variable_index()] = argument_value;
  472. return {};
  473. }
  474. Reference reference = TRY(vm.resolve_binding(param->string(), used_environment));
  475. // Here the difference from hasDuplicates is important
  476. if (has_duplicates)
  477. return reference.put_value(vm, argument_value);
  478. return reference.initialize_referenced_binding(vm, argument_value);
  479. }
  480. if constexpr (IsSame<NonnullRefPtr<BindingPattern const> const&, decltype(param)>) {
  481. // Here the difference from hasDuplicates is important
  482. return vm.binding_initialization(param, argument_value, used_environment);
  483. }
  484. }));
  485. }
  486. GCPtr<Environment> var_environment;
  487. HashTable<DeprecatedFlyString> instantiated_var_names;
  488. if (scope_body)
  489. instantiated_var_names.ensure_capacity(scope_body->var_declaration_count());
  490. // 27. If hasParameterExpressions is false, then
  491. if (!has_parameter_expressions) {
  492. // a. NOTE: Only a single Environment Record is needed for the parameters and top-level vars.
  493. // b. Let instantiatedVarNames be a copy of the List parameterBindings.
  494. // NOTE: Done in implementation of step 27.c.i.1 below
  495. if (scope_body) {
  496. // NOTE: Due to the use of MUST with `create_mutable_binding` and `initialize_binding` below,
  497. // an exception should not result from `for_each_var_declared_name`.
  498. // c. For each element n of varNames, do
  499. MUST(scope_body->for_each_var_declared_identifier([&](auto const& id) {
  500. // i. If instantiatedVarNames does not contain n, then
  501. if (!parameter_names.contains(id.string()) && instantiated_var_names.set(id.string()) == AK::HashSetResult::InsertedNewEntry) {
  502. // 1. Append n to instantiatedVarNames.
  503. // 2. Perform ! env.CreateMutableBinding(n, false).
  504. // 3. Perform ! env.InitializeBinding(n, undefined).
  505. if (vm.bytecode_interpreter_if_exists() && id.is_local()) {
  506. callee_context.local_variables[id.local_variable_index()] = js_undefined();
  507. } else {
  508. MUST(environment->create_mutable_binding(vm, id.string(), false));
  509. MUST(environment->initialize_binding(vm, id.string(), js_undefined(), Environment::InitializeBindingHint::Normal));
  510. }
  511. }
  512. }));
  513. }
  514. // d.Let varEnv be env
  515. var_environment = environment;
  516. }
  517. // 28. Else,
  518. else {
  519. // a. NOTE: A separate Environment Record is needed to ensure that closures created by expressions in the formal parameter list do not have visibility of declarations in the function body.
  520. // b. Let varEnv be NewDeclarativeEnvironment(env).
  521. var_environment = new_declarative_environment(*environment);
  522. // c. Set the VariableEnvironment of calleeContext to varEnv.
  523. callee_context.variable_environment = var_environment;
  524. // d. Let instantiatedVarNames be a new empty List.
  525. // NOTE: Already done above.
  526. if (scope_body) {
  527. // NOTE: Due to the use of MUST with `create_mutable_binding`, `get_binding_value` and `initialize_binding` below,
  528. // an exception should not result from `for_each_var_declared_name`.
  529. // e. For each element n of varNames, do
  530. MUST(scope_body->for_each_var_declared_identifier([&](auto const& id) {
  531. // i. If instantiatedVarNames does not contain n, then
  532. if (instantiated_var_names.set(id.string()) == AK::HashSetResult::InsertedNewEntry) {
  533. // 1. Append n to instantiatedVarNames.
  534. // 2. Perform ! varEnv.CreateMutableBinding(n, false).
  535. MUST(var_environment->create_mutable_binding(vm, id.string(), false));
  536. Value initial_value;
  537. // 3. If parameterBindings does not contain n, or if functionNames contains n, then
  538. if (!parameter_names.contains(id.string()) || function_names.contains(id.string())) {
  539. // a. Let initialValue be undefined.
  540. initial_value = js_undefined();
  541. }
  542. // 4. Else,
  543. else {
  544. // a. Let initialValue be ! env.GetBindingValue(n, false).
  545. initial_value = MUST(environment->get_binding_value(vm, id.string(), false));
  546. }
  547. // 5. Perform ! varEnv.InitializeBinding(n, initialValue).
  548. if (vm.bytecode_interpreter_if_exists() && id.is_local()) {
  549. // NOTE: Local variables are supported only in bytecode interpreter
  550. callee_context.local_variables[id.local_variable_index()] = initial_value;
  551. } else {
  552. MUST(var_environment->initialize_binding(vm, id.string(), initial_value, Environment::InitializeBindingHint::Normal));
  553. }
  554. // 6. NOTE: A var with the same name as a formal parameter initially has the same value as the corresponding initialized parameter.
  555. }
  556. }));
  557. }
  558. }
  559. // 29. NOTE: Annex B.3.2.1 adds additional steps at this point.
  560. // B.3.2.1 Changes to FunctionDeclarationInstantiation, https://tc39.es/ecma262/#sec-web-compat-functiondeclarationinstantiation
  561. if (!strict && scope_body) {
  562. // NOTE: Due to the use of MUST with `create_mutable_binding` and `initialize_binding` below,
  563. // an exception should not result from `for_each_function_hoistable_with_annexB_extension`.
  564. MUST(scope_body->for_each_function_hoistable_with_annexB_extension([&](FunctionDeclaration& function_declaration) {
  565. auto function_name = function_declaration.name();
  566. if (parameter_names.contains(function_name))
  567. return;
  568. // The spec says 'initializedBindings' here but that does not exist and it then adds it to 'instantiatedVarNames' so it probably means 'instantiatedVarNames'.
  569. if (!instantiated_var_names.contains(function_name) && function_name != vm.names.arguments.as_string()) {
  570. MUST(var_environment->create_mutable_binding(vm, function_name, false));
  571. MUST(var_environment->initialize_binding(vm, function_name, js_undefined(), Environment::InitializeBindingHint::Normal));
  572. instantiated_var_names.set(function_name);
  573. }
  574. function_declaration.set_should_do_additional_annexB_steps();
  575. }));
  576. }
  577. GCPtr<Environment> lex_environment;
  578. // 30. If strict is false, then
  579. if (!strict) {
  580. // Optimization: We avoid creating empty top-level declarative environments in non-strict mode, if both of these conditions are true:
  581. // 1. there is no direct call to eval() within this function
  582. // 2. there are no lexical declarations that would go into the environment
  583. bool can_elide_declarative_environment = !m_contains_direct_call_to_eval && (!scope_body || !scope_body->has_lexical_declarations());
  584. if (can_elide_declarative_environment) {
  585. lex_environment = var_environment;
  586. } else {
  587. // a. Let lexEnv be NewDeclarativeEnvironment(varEnv).
  588. // b. NOTE: Non-strict functions use a separate Environment Record for top-level lexical declarations so that a direct eval
  589. // can determine whether any var scoped declarations introduced by the eval code conflict with pre-existing top-level
  590. // lexically scoped declarations. This is not needed for strict functions because a strict direct eval always places
  591. // all declarations into a new Environment Record.
  592. lex_environment = new_declarative_environment(*var_environment);
  593. }
  594. }
  595. // 31. Else,
  596. else {
  597. // a. let lexEnv be varEnv.
  598. lex_environment = var_environment;
  599. }
  600. // 32. Set the LexicalEnvironment of calleeContext to lexEnv.
  601. callee_context.lexical_environment = lex_environment;
  602. if (!scope_body)
  603. return {};
  604. // 33. Let lexDeclarations be the LexicallyScopedDeclarations of code.
  605. // 34. For each element d of lexDeclarations, do
  606. // NOTE: Due to the use of MUST in the callback, an exception should not result from `for_each_lexically_scoped_declaration`.
  607. MUST(scope_body->for_each_lexically_scoped_declaration([&](Declaration const& declaration) {
  608. // NOTE: Due to the use of MUST with `create_immutable_binding` and `create_mutable_binding` below,
  609. // an exception should not result from `for_each_bound_name`.
  610. // a. NOTE: A lexically declared name cannot be the same as a function/generator declaration, formal parameter, or a var name. Lexically declared names are only instantiated here but not initialized.
  611. // b. For each element dn of the BoundNames of d, do
  612. MUST(declaration.for_each_bound_identifier([&](auto const& id) {
  613. if (vm.bytecode_interpreter_if_exists() && id.is_local()) {
  614. // NOTE: Local variables are supported only in bytecode interpreter
  615. return;
  616. }
  617. // i. If IsConstantDeclaration of d is true, then
  618. if (declaration.is_constant_declaration()) {
  619. // 1. Perform ! lexEnv.CreateImmutableBinding(dn, true).
  620. MUST(lex_environment->create_immutable_binding(vm, id.string(), true));
  621. }
  622. // ii. Else,
  623. else {
  624. // 1. Perform ! lexEnv.CreateMutableBinding(dn, false).
  625. MUST(lex_environment->create_mutable_binding(vm, id.string(), false));
  626. }
  627. }));
  628. }));
  629. // 35. Let privateEnv be the PrivateEnvironment of calleeContext.
  630. auto private_environment = callee_context.private_environment;
  631. // 36. For each Parse Node f of functionsToInitialize, do
  632. for (auto& declaration : functions_to_initialize) {
  633. // a. Let fn be the sole element of the BoundNames of f.
  634. // b. Let fo be InstantiateFunctionObject of f with arguments lexEnv and privateEnv.
  635. auto function = ECMAScriptFunctionObject::create(realm, declaration.name(), declaration.source_text(), declaration.body(), declaration.parameters(), declaration.function_length(), declaration.local_variables_names(), lex_environment, private_environment, declaration.kind(), declaration.is_strict_mode(), declaration.might_need_arguments_object(), declaration.contains_direct_call_to_eval());
  636. // c. Perform ! varEnv.SetMutableBinding(fn, fo, false).
  637. if ((vm.bytecode_interpreter_if_exists() || kind() == FunctionKind::Generator || kind() == FunctionKind::AsyncGenerator) && declaration.name_identifier()->is_local()) {
  638. callee_context.local_variables[declaration.name_identifier()->local_variable_index()] = function;
  639. } else {
  640. MUST(var_environment->set_mutable_binding(vm, declaration.name(), function, false));
  641. }
  642. }
  643. if (is<DeclarativeEnvironment>(*lex_environment))
  644. static_cast<DeclarativeEnvironment*>(lex_environment.ptr())->shrink_to_fit();
  645. if (is<DeclarativeEnvironment>(*var_environment))
  646. static_cast<DeclarativeEnvironment*>(var_environment.ptr())->shrink_to_fit();
  647. // 37. Return unused.
  648. return {};
  649. }
  650. // 10.2.1.1 PrepareForOrdinaryCall ( F, newTarget ), https://tc39.es/ecma262/#sec-prepareforordinarycall
  651. ThrowCompletionOr<void> ECMAScriptFunctionObject::prepare_for_ordinary_call(ExecutionContext& callee_context, Object* new_target)
  652. {
  653. auto& vm = this->vm();
  654. // Non-standard
  655. callee_context.is_strict_mode = m_strict;
  656. // 1. Let callerContext be the running execution context.
  657. // 2. Let calleeContext be a new ECMAScript code execution context.
  658. // NOTE: In the specification, PrepareForOrdinaryCall "returns" a new callee execution context.
  659. // To avoid heap allocations, we put our ExecutionContext objects on the C++ stack instead.
  660. // Whoever calls us should put an ExecutionContext on their stack and pass that as the `callee_context`.
  661. // 3. Set the Function of calleeContext to F.
  662. callee_context.function = this;
  663. callee_context.function_name = m_name;
  664. // 4. Let calleeRealm be F.[[Realm]].
  665. auto callee_realm = m_realm;
  666. // NOTE: This non-standard fallback is needed until we can guarantee that literally
  667. // every function has a realm - especially in LibWeb that's sometimes not the case
  668. // when a function is created while no JS is running, as we currently need to rely on
  669. // that (:acid2:, I know - see set_event_handler_attribute() for an example).
  670. // If there's no 'current realm' either, we can't continue and crash.
  671. if (!callee_realm)
  672. callee_realm = vm.current_realm();
  673. VERIFY(callee_realm);
  674. // 5. Set the Realm of calleeContext to calleeRealm.
  675. callee_context.realm = callee_realm;
  676. // 6. Set the ScriptOrModule of calleeContext to F.[[ScriptOrModule]].
  677. callee_context.script_or_module = m_script_or_module;
  678. // 7. Let localEnv be NewFunctionEnvironment(F, newTarget).
  679. auto local_environment = new_function_environment(*this, new_target);
  680. // 8. Set the LexicalEnvironment of calleeContext to localEnv.
  681. callee_context.lexical_environment = local_environment;
  682. // 9. Set the VariableEnvironment of calleeContext to localEnv.
  683. callee_context.variable_environment = local_environment;
  684. // 10. Set the PrivateEnvironment of calleeContext to F.[[PrivateEnvironment]].
  685. callee_context.private_environment = m_private_environment;
  686. // 11. If callerContext is not already suspended, suspend callerContext.
  687. // FIXME: We don't have this concept yet.
  688. // 12. Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
  689. TRY(vm.push_execution_context(callee_context, {}));
  690. // 13. NOTE: Any exception objects produced after this point are associated with calleeRealm.
  691. // 14. Return calleeContext.
  692. // NOTE: See the comment after step 2 above about how contexts are allocated on the C++ stack.
  693. return {};
  694. }
  695. // 10.2.1.2 OrdinaryCallBindThis ( F, calleeContext, thisArgument ), https://tc39.es/ecma262/#sec-ordinarycallbindthis
  696. void ECMAScriptFunctionObject::ordinary_call_bind_this(ExecutionContext& callee_context, Value this_argument)
  697. {
  698. auto& vm = this->vm();
  699. // 1. Let thisMode be F.[[ThisMode]].
  700. auto this_mode = m_this_mode;
  701. // If thisMode is lexical, return unused.
  702. if (this_mode == ThisMode::Lexical)
  703. return;
  704. // 3. Let calleeRealm be F.[[Realm]].
  705. auto callee_realm = m_realm;
  706. // NOTE: This non-standard fallback is needed until we can guarantee that literally
  707. // every function has a realm - especially in LibWeb that's sometimes not the case
  708. // when a function is created while no JS is running, as we currently need to rely on
  709. // that (:acid2:, I know - see set_event_handler_attribute() for an example).
  710. // If there's no 'current realm' either, we can't continue and crash.
  711. if (!callee_realm)
  712. callee_realm = vm.current_realm();
  713. VERIFY(callee_realm);
  714. // 4. Let localEnv be the LexicalEnvironment of calleeContext.
  715. auto local_env = callee_context.lexical_environment;
  716. Value this_value;
  717. // 5. If thisMode is strict, let thisValue be thisArgument.
  718. if (this_mode == ThisMode::Strict) {
  719. this_value = this_argument;
  720. }
  721. // 6. Else,
  722. else {
  723. // a. If thisArgument is undefined or null, then
  724. if (this_argument.is_nullish()) {
  725. // i. Let globalEnv be calleeRealm.[[GlobalEnv]].
  726. // ii. Assert: globalEnv is a global Environment Record.
  727. auto& global_env = callee_realm->global_environment();
  728. // iii. Let thisValue be globalEnv.[[GlobalThisValue]].
  729. this_value = &global_env.global_this_value();
  730. }
  731. // b. Else,
  732. else {
  733. // i. Let thisValue be ! ToObject(thisArgument).
  734. this_value = MUST(this_argument.to_object(vm));
  735. // ii. NOTE: ToObject produces wrapper objects using calleeRealm.
  736. VERIFY(vm.current_realm() == callee_realm);
  737. }
  738. }
  739. // 7. Assert: localEnv is a function Environment Record.
  740. // 8. Assert: The next step never returns an abrupt completion because localEnv.[[ThisBindingStatus]] is not initialized.
  741. // 9. Perform ! localEnv.BindThisValue(thisValue).
  742. MUST(verify_cast<FunctionEnvironment>(*local_env).bind_this_value(vm, this_value));
  743. // 10. Return unused.
  744. }
  745. // 27.7.5.1 AsyncFunctionStart ( promiseCapability, asyncFunctionBody ), https://tc39.es/ecma262/#sec-async-functions-abstract-operations-async-function-start
  746. template<typename T>
  747. void async_function_start(VM& vm, PromiseCapability const& promise_capability, T const& async_function_body)
  748. {
  749. // 1. Let runningContext be the running execution context.
  750. auto& running_context = vm.running_execution_context();
  751. // 2. Let asyncContext be a copy of runningContext.
  752. auto async_context = running_context.copy();
  753. // 3. NOTE: Copying the execution state is required for AsyncBlockStart to resume its execution. It is ill-defined to resume a currently executing context.
  754. // 4. Perform AsyncBlockStart(promiseCapability, asyncFunctionBody, asyncContext).
  755. async_block_start(vm, async_function_body, promise_capability, async_context);
  756. // 5. Return unused.
  757. }
  758. // 27.7.5.2 AsyncBlockStart ( promiseCapability, asyncBody, asyncContext ), https://tc39.es/ecma262/#sec-asyncblockstart
  759. // 12.7.1.1 AsyncBlockStart ( promiseCapability, asyncBody, asyncContext ), https://tc39.es/proposal-explicit-resource-management/#sec-asyncblockstart
  760. // 1.2.1.1 AsyncBlockStart ( promiseCapability, asyncBody, asyncContext ), https://tc39.es/proposal-array-from-async/#sec-asyncblockstart
  761. template<typename T>
  762. void async_block_start(VM& vm, T const& async_body, PromiseCapability const& promise_capability, ExecutionContext& async_context)
  763. {
  764. // NOTE: This function is a combination between two proposals, so does not exactly match spec steps of either.
  765. auto& realm = *vm.current_realm();
  766. // 1. Assert: promiseCapability is a PromiseCapability Record.
  767. // 2. Let runningContext be the running execution context.
  768. auto& running_context = vm.running_execution_context();
  769. // 3. Set the code evaluation state of asyncContext such that when evaluation is resumed for that execution context the following steps will be performed:
  770. auto execution_steps = NativeFunction::create(realm, "", [&realm, &async_body, &promise_capability, &async_context](auto& vm) -> ThrowCompletionOr<Value> {
  771. Completion result;
  772. // a. If asyncBody is a Parse Node, then
  773. if constexpr (!IsCallableWithArguments<T, Completion>) {
  774. // a. Let result be the result of evaluating asyncBody.
  775. // FIXME: Cache this executable somewhere.
  776. auto maybe_executable = Bytecode::compile(vm, async_body, FunctionKind::Async, "AsyncBlockStart"sv);
  777. if (maybe_executable.is_error())
  778. result = maybe_executable.release_error();
  779. else
  780. result = vm.bytecode_interpreter().run_and_return_frame(realm, *maybe_executable.value(), nullptr).value;
  781. }
  782. // b. Else,
  783. else {
  784. (void)realm;
  785. // i. Assert: asyncBody is an Abstract Closure with no parameters.
  786. static_assert(IsCallableWithArguments<T, Completion>);
  787. // ii. Let result be asyncBody().
  788. result = async_body();
  789. }
  790. // c. Assert: If we return here, the async function either threw an exception or performed an implicit or explicit return; all awaiting is done.
  791. // d. Remove asyncContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context.
  792. vm.pop_execution_context();
  793. // NOTE: This does not work for Array.fromAsync, likely due to conflicts between that proposal and Explicit Resource Management proposal.
  794. if constexpr (!IsCallableWithArguments<T, Completion>) {
  795. // e. Let env be asyncContext's LexicalEnvironment.
  796. auto env = async_context.lexical_environment;
  797. // f. Set result to DisposeResources(env, result).
  798. result = dispose_resources(vm, verify_cast<DeclarativeEnvironment>(env.ptr()), result);
  799. } else {
  800. (void)async_context;
  801. }
  802. // g. If result.[[Type]] is normal, then
  803. if (result.type() == Completion::Type::Normal) {
  804. // i. Perform ! Call(promiseCapability.[[Resolve]], undefined, « undefined »).
  805. MUST(call(vm, *promise_capability.resolve(), js_undefined(), js_undefined()));
  806. }
  807. // h. Else if result.[[Type]] is return, then
  808. else if (result.type() == Completion::Type::Return) {
  809. // i. Perform ! Call(promiseCapability.[[Resolve]], undefined, « result.[[Value]] »).
  810. MUST(call(vm, *promise_capability.resolve(), js_undefined(), *result.value()));
  811. }
  812. // i. Else,
  813. else {
  814. // i. Assert: result.[[Type]] is throw.
  815. VERIFY(result.type() == Completion::Type::Throw);
  816. // ii. Perform ! Call(promiseCapability.[[Reject]], undefined, « result.[[Value]] »).
  817. MUST(call(vm, *promise_capability.reject(), js_undefined(), *result.value()));
  818. }
  819. // j. Return unused.
  820. // NOTE: We don't support returning an empty/optional/unused value here.
  821. return js_undefined();
  822. });
  823. // 4. Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
  824. auto push_result = vm.push_execution_context(async_context, {});
  825. if (push_result.is_error())
  826. return;
  827. // 5. Resume the suspended evaluation of asyncContext. Let result be the value returned by the resumed computation.
  828. auto result = call(vm, *execution_steps, async_context.this_value.is_empty() ? js_undefined() : async_context.this_value);
  829. // 6. Assert: When we return here, asyncContext has already been removed from the execution context stack and runningContext is the currently running execution context.
  830. VERIFY(&vm.running_execution_context() == &running_context);
  831. // 7. Assert: result is a normal completion with a value of unused. The possible sources of this value are Await or, if the async function doesn't await anything, step 3.g above.
  832. VERIFY(result.has_value() && result.value().is_undefined());
  833. // 8. Return unused.
  834. }
  835. template void async_block_start(VM&, NonnullRefPtr<Statement const> const& async_body, PromiseCapability const&, ExecutionContext&);
  836. template void async_function_start(VM&, PromiseCapability const&, NonnullRefPtr<Statement const> const& async_function_body);
  837. template void async_block_start(VM&, SafeFunction<Completion()> const& async_body, PromiseCapability const&, ExecutionContext&);
  838. template void async_function_start(VM&, PromiseCapability const&, SafeFunction<Completion()> const& async_function_body);
  839. // 10.2.1.4 OrdinaryCallEvaluateBody ( F, argumentsList ), https://tc39.es/ecma262/#sec-ordinarycallevaluatebody
  840. // 15.8.4 Runtime Semantics: EvaluateAsyncFunctionBody, https://tc39.es/ecma262/#sec-runtime-semantics-evaluatefunctionbody
  841. Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
  842. {
  843. auto& vm = this->vm();
  844. auto& realm = *vm.current_realm();
  845. // NOTE: There's a subtle ordering issue here:
  846. // - We have to compile the default parameter values before instantiating the function.
  847. // - We have to instantiate the function before compiling the function body.
  848. // This is why FunctionDeclarationInstantiation is invoked in the middle.
  849. // The issue is that FunctionDeclarationInstantiation may mark certain functions as hoisted
  850. // per Annex B. This affects code generation for FunctionDeclaration nodes.
  851. if (!m_bytecode_executable) {
  852. size_t default_parameter_index = 0;
  853. for (auto& parameter : m_formal_parameters) {
  854. if (!parameter.default_value)
  855. continue;
  856. auto executable = TRY(Bytecode::compile(vm, *parameter.default_value, FunctionKind::Normal, DeprecatedString::formatted("default parameter #{} for {}", default_parameter_index, m_name)));
  857. m_default_parameter_bytecode_executables.append(move(executable));
  858. }
  859. }
  860. auto declaration_result = function_declaration_instantiation();
  861. if (m_kind == FunctionKind::Normal || m_kind == FunctionKind::Generator || m_kind == FunctionKind::AsyncGenerator) {
  862. if (declaration_result.is_error())
  863. return declaration_result.release_error();
  864. }
  865. if (!m_bytecode_executable)
  866. m_bytecode_executable = TRY(Bytecode::compile(vm, *m_ecmascript_code, m_kind, m_name));
  867. if (m_kind == FunctionKind::Async) {
  868. if (declaration_result.is_throw_completion()) {
  869. auto promise_capability = MUST(new_promise_capability(vm, realm.intrinsics().promise_constructor()));
  870. MUST(call(vm, *promise_capability->reject(), js_undefined(), *declaration_result.throw_completion().value()));
  871. return Completion { Completion::Type::Return, promise_capability->promise(), {} };
  872. }
  873. }
  874. auto result_and_frame = vm.bytecode_interpreter().run_and_return_frame(realm, *m_bytecode_executable, nullptr);
  875. VERIFY(result_and_frame.frame != nullptr);
  876. if (result_and_frame.value.is_error())
  877. return result_and_frame.value.release_error();
  878. auto result = result_and_frame.value.release_value();
  879. // NOTE: Running the bytecode should eventually return a completion.
  880. // Until it does, we assume "return" and include the undefined fallback from the call site.
  881. if (m_kind == FunctionKind::Normal)
  882. return { Completion::Type::Return, result.value_or(js_undefined()), {} };
  883. if (m_kind == FunctionKind::AsyncGenerator) {
  884. auto async_generator_object = TRY(AsyncGenerator::create(realm, result, this, vm.running_execution_context().copy(), move(*result_and_frame.frame)));
  885. return { Completion::Type::Return, async_generator_object, {} };
  886. }
  887. auto generator_object = TRY(GeneratorObject::create(realm, result, this, vm.running_execution_context().copy(), move(*result_and_frame.frame)));
  888. // NOTE: Async functions are entirely transformed to generator functions, and wrapped in a custom driver that returns a promise
  889. // See AwaitExpression::generate_bytecode() for the transformation.
  890. if (m_kind == FunctionKind::Async)
  891. return { Completion::Type::Return, TRY(AsyncFunctionDriverWrapper::create(realm, generator_object)), {} };
  892. VERIFY(m_kind == FunctionKind::Generator);
  893. return { Completion::Type::Return, generator_object, {} };
  894. }
  895. void ECMAScriptFunctionObject::set_name(DeprecatedFlyString const& name)
  896. {
  897. VERIFY(!name.is_null());
  898. auto& vm = this->vm();
  899. m_name = name;
  900. MUST(define_property_or_throw(vm.names.name, { .value = PrimitiveString::create(vm, m_name), .writable = false, .enumerable = false, .configurable = true }));
  901. }
  902. }