VM.cpp 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014
  1. /*
  2. * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
  4. * Copyright (c) 2021-2022, David Tuin <davidot@serenityos.org>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause
  7. */
  8. #include <AK/Debug.h>
  9. #include <AK/LexicalPath.h>
  10. #include <AK/ScopeGuard.h>
  11. #include <AK/StringBuilder.h>
  12. #include <LibCore/File.h>
  13. #include <LibJS/Interpreter.h>
  14. #include <LibJS/Runtime/AbstractOperations.h>
  15. #include <LibJS/Runtime/Array.h>
  16. #include <LibJS/Runtime/BoundFunction.h>
  17. #include <LibJS/Runtime/Completion.h>
  18. #include <LibJS/Runtime/ECMAScriptFunctionObject.h>
  19. #include <LibJS/Runtime/Error.h>
  20. #include <LibJS/Runtime/FinalizationRegistry.h>
  21. #include <LibJS/Runtime/FunctionEnvironment.h>
  22. #include <LibJS/Runtime/GlobalObject.h>
  23. #include <LibJS/Runtime/IteratorOperations.h>
  24. #include <LibJS/Runtime/NativeFunction.h>
  25. #include <LibJS/Runtime/PromiseReaction.h>
  26. #include <LibJS/Runtime/Reference.h>
  27. #include <LibJS/Runtime/Symbol.h>
  28. #include <LibJS/Runtime/VM.h>
  29. #include <LibJS/SourceTextModule.h>
  30. #include <LibJS/SyntheticModule.h>
  31. namespace JS {
  32. NonnullRefPtr<VM> VM::create(OwnPtr<CustomData> custom_data)
  33. {
  34. return adopt_ref(*new VM(move(custom_data)));
  35. }
  36. VM::VM(OwnPtr<CustomData> custom_data)
  37. : m_heap(*this)
  38. , m_custom_data(move(custom_data))
  39. {
  40. m_empty_string = m_heap.allocate_without_global_object<PrimitiveString>(String::empty());
  41. for (size_t i = 0; i < 128; ++i) {
  42. m_single_ascii_character_strings[i] = m_heap.allocate_without_global_object<PrimitiveString>(String::formatted("{:c}", i));
  43. }
  44. host_resolve_imported_module = [&](ScriptOrModule referencing_script_or_module, ModuleRequest const& specifier) {
  45. return resolve_imported_module(move(referencing_script_or_module), specifier);
  46. };
  47. host_import_module_dynamically = [&](ScriptOrModule, ModuleRequest const&, PromiseCapability promise_capability) {
  48. // By default, we throw on dynamic imports this is to prevent arbitrary file access by scripts.
  49. VERIFY(current_realm());
  50. auto& global_object = current_realm()->global_object();
  51. auto* promise = Promise::create(global_object);
  52. // If you are here because you want to enable dynamic module importing make sure it won't be a security problem
  53. // by checking the default implementation of HostImportModuleDynamically and creating your own hook or calling
  54. // vm.enable_default_host_import_module_dynamically_hook().
  55. promise->reject(Error::create(global_object, ErrorType::DynamicImportNotAllowed.message()));
  56. promise->perform_then(
  57. NativeFunction::create(global_object, "", [](auto&, auto&) -> ThrowCompletionOr<Value> {
  58. VERIFY_NOT_REACHED();
  59. }),
  60. NativeFunction::create(global_object, "", [reject = make_handle(promise_capability.reject)](auto& vm, auto& global_object) -> ThrowCompletionOr<Value> {
  61. auto error = vm.argument(0);
  62. // a. Perform ! Call(promiseCapability.[[Reject]], undefined, « error »).
  63. MUST(call(global_object, reject.cell(), js_undefined(), error));
  64. // b. Return undefined.
  65. return js_undefined();
  66. }),
  67. {});
  68. };
  69. host_finish_dynamic_import = [&](ScriptOrModule referencing_script_or_module, ModuleRequest const& specifier, PromiseCapability promise_capability, Promise* promise) {
  70. return finish_dynamic_import(move(referencing_script_or_module), specifier, promise_capability, promise);
  71. };
  72. host_get_import_meta_properties = [&](SourceTextModule const&) -> HashMap<PropertyKey, Value> {
  73. return {};
  74. };
  75. host_finalize_import_meta = [&](Object*, SourceTextModule const&) {
  76. };
  77. host_get_supported_import_assertions = [&] {
  78. return Vector<String> { "type" };
  79. };
  80. #define __JS_ENUMERATE(SymbolName, snake_name) \
  81. m_well_known_symbol_##snake_name = js_symbol(*this, "Symbol." #SymbolName, false);
  82. JS_ENUMERATE_WELL_KNOWN_SYMBOLS
  83. #undef __JS_ENUMERATE
  84. }
  85. VM::~VM()
  86. {
  87. }
  88. void VM::enable_default_host_import_module_dynamically_hook()
  89. {
  90. host_import_module_dynamically = [&](ScriptOrModule referencing_script_or_module, ModuleRequest const& specifier, PromiseCapability promise_capability) {
  91. return import_module_dynamically(move(referencing_script_or_module), specifier, promise_capability);
  92. };
  93. }
  94. Interpreter& VM::interpreter()
  95. {
  96. VERIFY(!m_interpreters.is_empty());
  97. return *m_interpreters.last();
  98. }
  99. Interpreter* VM::interpreter_if_exists()
  100. {
  101. if (m_interpreters.is_empty())
  102. return nullptr;
  103. return m_interpreters.last();
  104. }
  105. void VM::push_interpreter(Interpreter& interpreter)
  106. {
  107. m_interpreters.append(&interpreter);
  108. }
  109. void VM::pop_interpreter(Interpreter& interpreter)
  110. {
  111. VERIFY(!m_interpreters.is_empty());
  112. auto* popped_interpreter = m_interpreters.take_last();
  113. VERIFY(popped_interpreter == &interpreter);
  114. }
  115. VM::InterpreterExecutionScope::InterpreterExecutionScope(Interpreter& interpreter)
  116. : m_interpreter(interpreter)
  117. {
  118. m_interpreter.vm().push_interpreter(m_interpreter);
  119. }
  120. VM::InterpreterExecutionScope::~InterpreterExecutionScope()
  121. {
  122. m_interpreter.vm().pop_interpreter(m_interpreter);
  123. }
  124. void VM::gather_roots(HashTable<Cell*>& roots)
  125. {
  126. roots.set(m_empty_string);
  127. for (auto* string : m_single_ascii_character_strings)
  128. roots.set(string);
  129. auto gather_roots_from_execution_context_stack = [&roots](Vector<ExecutionContext*> const& stack) {
  130. for (auto& execution_context : stack) {
  131. if (execution_context->this_value.is_cell())
  132. roots.set(&execution_context->this_value.as_cell());
  133. for (auto& argument : execution_context->arguments) {
  134. if (argument.is_cell())
  135. roots.set(&argument.as_cell());
  136. }
  137. roots.set(execution_context->lexical_environment);
  138. roots.set(execution_context->variable_environment);
  139. roots.set(execution_context->private_environment);
  140. }
  141. };
  142. gather_roots_from_execution_context_stack(m_execution_context_stack);
  143. for (auto& saved_stack : m_saved_execution_context_stacks)
  144. gather_roots_from_execution_context_stack(saved_stack);
  145. #define __JS_ENUMERATE(SymbolName, snake_name) \
  146. roots.set(well_known_symbol_##snake_name());
  147. JS_ENUMERATE_WELL_KNOWN_SYMBOLS
  148. #undef __JS_ENUMERATE
  149. for (auto& symbol : m_global_symbol_map)
  150. roots.set(symbol.value);
  151. for (auto* job : m_promise_jobs)
  152. roots.set(job);
  153. for (auto* finalization_registry : m_finalization_registry_cleanup_jobs)
  154. roots.set(finalization_registry);
  155. }
  156. Symbol* VM::get_global_symbol(const String& description)
  157. {
  158. auto result = m_global_symbol_map.get(description);
  159. if (result.has_value())
  160. return result.value();
  161. auto new_global_symbol = js_symbol(*this, description, true);
  162. m_global_symbol_map.set(description, new_global_symbol);
  163. return new_global_symbol;
  164. }
  165. ThrowCompletionOr<Value> VM::named_evaluation_if_anonymous_function(GlobalObject& global_object, ASTNode const& expression, FlyString const& name)
  166. {
  167. // 8.3.3 Static Semantics: IsAnonymousFunctionDefinition ( expr ), https://tc39.es/ecma262/#sec-isanonymousfunctiondefinition
  168. // And 8.3.5 Runtime Semantics: NamedEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-namedevaluation
  169. if (is<FunctionExpression>(expression)) {
  170. auto& function = static_cast<FunctionExpression const&>(expression);
  171. if (!function.has_name()) {
  172. return function.instantiate_ordinary_function_expression(interpreter(), global_object, name);
  173. }
  174. } else if (is<ClassExpression>(expression)) {
  175. auto& class_expression = static_cast<ClassExpression const&>(expression);
  176. if (!class_expression.has_name()) {
  177. return TRY(class_expression.class_definition_evaluation(interpreter(), global_object, {}, name));
  178. }
  179. }
  180. return TRY(expression.execute(interpreter(), global_object)).release_value();
  181. }
  182. // 13.15.5.2 Runtime Semantics: DestructuringAssignmentEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-destructuringassignmentevaluation
  183. ThrowCompletionOr<void> VM::destructuring_assignment_evaluation(NonnullRefPtr<BindingPattern> const& target, Value value, GlobalObject& global_object)
  184. {
  185. // Note: DestructuringAssignmentEvaluation is just like BindingInitialization without an environment
  186. // And it allows member expressions. We thus trust the parser to disallow member expressions
  187. // in any non assignment binding and just call BindingInitialization with a nullptr environment
  188. return binding_initialization(target, value, nullptr, global_object);
  189. }
  190. // 8.5.2 Runtime Semantics: BindingInitialization, https://tc39.es/ecma262/#sec-runtime-semantics-bindinginitialization
  191. ThrowCompletionOr<void> VM::binding_initialization(FlyString const& target, Value value, Environment* environment, GlobalObject& global_object)
  192. {
  193. // 1. Let name be StringValue of Identifier.
  194. // 2. Return ? InitializeBoundName(name, value, environment).
  195. return initialize_bound_name(global_object, target, value, environment);
  196. }
  197. // 8.5.2 Runtime Semantics: BindingInitialization, https://tc39.es/ecma262/#sec-runtime-semantics-bindinginitialization
  198. ThrowCompletionOr<void> VM::binding_initialization(NonnullRefPtr<BindingPattern> const& target, Value value, Environment* environment, GlobalObject& global_object)
  199. {
  200. // BindingPattern : ObjectBindingPattern
  201. if (target->kind == BindingPattern::Kind::Object) {
  202. // 1. Perform ? RequireObjectCoercible(value).
  203. TRY(require_object_coercible(global_object, value));
  204. // 2. Return the result of performing BindingInitialization of ObjectBindingPattern using value and environment as arguments.
  205. // BindingInitialization of ObjectBindingPattern
  206. // 1. Perform ? PropertyBindingInitialization of BindingPropertyList using value and environment as the arguments.
  207. TRY(property_binding_initialization(*target, value, environment, global_object));
  208. // 2. Return NormalCompletion(empty).
  209. return {};
  210. }
  211. // BindingPattern : ArrayBindingPattern
  212. else {
  213. // 1. Let iteratorRecord be ? GetIterator(value).
  214. auto iterator_record = TRY(get_iterator(global_object, value));
  215. // 2. Let result be IteratorBindingInitialization of ArrayBindingPattern with arguments iteratorRecord and environment.
  216. auto result = iterator_binding_initialization(*target, iterator_record, environment, global_object);
  217. // 3. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, result).
  218. if (!iterator_record.done) {
  219. // iterator_close() always returns a Completion, which ThrowCompletionOr will interpret as a throw
  220. // completion. So only return the result of iterator_close() if it is indeed a throw completion.
  221. auto completion = result.is_throw_completion() ? result.release_error() : normal_completion({});
  222. if (completion = iterator_close(global_object, iterator_record, move(completion)); completion.is_error())
  223. return completion.release_error();
  224. }
  225. // 4. Return result.
  226. return result;
  227. }
  228. }
  229. // 13.15.5.3 Runtime Semantics: PropertyDestructuringAssignmentEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-propertydestructuringassignmentevaluation
  230. // 14.3.3.1 Runtime Semantics: PropertyBindingInitialization, https://tc39.es/ecma262/#sec-destructuring-binding-patterns-runtime-semantics-propertybindinginitialization
  231. ThrowCompletionOr<void> VM::property_binding_initialization(BindingPattern const& binding, Value value, Environment* environment, GlobalObject& global_object)
  232. {
  233. auto* object = TRY(value.to_object(global_object));
  234. HashTable<PropertyKey> seen_names;
  235. for (auto& property : binding.entries) {
  236. VERIFY(!property.is_elision());
  237. if (property.is_rest) {
  238. Reference assignment_target;
  239. if (auto identifier_ptr = property.name.get_pointer<NonnullRefPtr<Identifier>>()) {
  240. assignment_target = TRY(resolve_binding((*identifier_ptr)->string(), environment));
  241. } else if (auto member_ptr = property.alias.get_pointer<NonnullRefPtr<MemberExpression>>()) {
  242. assignment_target = TRY((*member_ptr)->to_reference(interpreter(), global_object));
  243. } else {
  244. VERIFY_NOT_REACHED();
  245. }
  246. auto* rest_object = Object::create(global_object, global_object.object_prototype());
  247. VERIFY(rest_object);
  248. TRY(rest_object->copy_data_properties(object, seen_names, global_object));
  249. if (!environment)
  250. return assignment_target.put_value(global_object, rest_object);
  251. else
  252. return assignment_target.initialize_referenced_binding(global_object, rest_object);
  253. }
  254. auto name = TRY(property.name.visit(
  255. [&](Empty) -> ThrowCompletionOr<PropertyKey> { VERIFY_NOT_REACHED(); },
  256. [&](NonnullRefPtr<Identifier> const& identifier) -> ThrowCompletionOr<PropertyKey> {
  257. return identifier->string();
  258. },
  259. [&](NonnullRefPtr<Expression> const& expression) -> ThrowCompletionOr<PropertyKey> {
  260. auto result = TRY(expression->execute(interpreter(), global_object)).release_value();
  261. return result.to_property_key(global_object);
  262. }));
  263. seen_names.set(name);
  264. if (property.name.has<NonnullRefPtr<Identifier>>() && property.alias.has<Empty>()) {
  265. // FIXME: this branch and not taking this have a lot in common we might want to unify it more (like it was before).
  266. auto& identifier = *property.name.get<NonnullRefPtr<Identifier>>();
  267. auto reference = TRY(resolve_binding(identifier.string(), environment));
  268. auto value_to_assign = TRY(object->get(name));
  269. if (property.initializer && value_to_assign.is_undefined()) {
  270. value_to_assign = TRY(named_evaluation_if_anonymous_function(global_object, *property.initializer, identifier.string()));
  271. }
  272. if (!environment)
  273. TRY(reference.put_value(global_object, value_to_assign));
  274. else
  275. TRY(reference.initialize_referenced_binding(global_object, value_to_assign));
  276. continue;
  277. }
  278. auto reference_to_assign_to = TRY(property.alias.visit(
  279. [&](Empty) -> ThrowCompletionOr<Optional<Reference>> { return Optional<Reference> {}; },
  280. [&](NonnullRefPtr<Identifier> const& identifier) -> ThrowCompletionOr<Optional<Reference>> {
  281. return TRY(resolve_binding(identifier->string(), environment));
  282. },
  283. [&](NonnullRefPtr<BindingPattern> const&) -> ThrowCompletionOr<Optional<Reference>> { return Optional<Reference> {}; },
  284. [&](NonnullRefPtr<MemberExpression> const& member_expression) -> ThrowCompletionOr<Optional<Reference>> {
  285. return TRY(member_expression->to_reference(interpreter(), global_object));
  286. }));
  287. auto value_to_assign = TRY(object->get(name));
  288. if (property.initializer && value_to_assign.is_undefined()) {
  289. if (auto* identifier_ptr = property.alias.get_pointer<NonnullRefPtr<Identifier>>())
  290. value_to_assign = TRY(named_evaluation_if_anonymous_function(global_object, *property.initializer, (*identifier_ptr)->string()));
  291. else
  292. value_to_assign = TRY(property.initializer->execute(interpreter(), global_object)).release_value();
  293. }
  294. if (auto* binding_ptr = property.alias.get_pointer<NonnullRefPtr<BindingPattern>>()) {
  295. TRY(binding_initialization(*binding_ptr, value_to_assign, environment, global_object));
  296. } else {
  297. VERIFY(reference_to_assign_to.has_value());
  298. if (!environment)
  299. TRY(reference_to_assign_to->put_value(global_object, value_to_assign));
  300. else
  301. TRY(reference_to_assign_to->initialize_referenced_binding(global_object, value_to_assign));
  302. }
  303. }
  304. return {};
  305. }
  306. // 13.15.5.5 Runtime Semantics: IteratorDestructuringAssignmentEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-iteratordestructuringassignmentevaluation
  307. // 8.5.3 Runtime Semantics: IteratorBindingInitialization, https://tc39.es/ecma262/#sec-runtime-semantics-iteratorbindinginitialization
  308. ThrowCompletionOr<void> VM::iterator_binding_initialization(BindingPattern const& binding, Iterator& iterator_record, Environment* environment, GlobalObject& global_object)
  309. {
  310. // FIXME: this method is nearly identical to destructuring assignment!
  311. for (size_t i = 0; i < binding.entries.size(); i++) {
  312. auto& entry = binding.entries[i];
  313. Value value;
  314. auto assignment_target = TRY(entry.alias.visit(
  315. [&](Empty) -> ThrowCompletionOr<Optional<Reference>> { return Optional<Reference> {}; },
  316. [&](NonnullRefPtr<Identifier> const& identifier) -> ThrowCompletionOr<Optional<Reference>> {
  317. return TRY(resolve_binding(identifier->string(), environment));
  318. },
  319. [&](NonnullRefPtr<BindingPattern> const&) -> ThrowCompletionOr<Optional<Reference>> { return Optional<Reference> {}; },
  320. [&](NonnullRefPtr<MemberExpression> const& member_expression) -> ThrowCompletionOr<Optional<Reference>> {
  321. return TRY(member_expression->to_reference(interpreter(), global_object));
  322. }));
  323. // BindingRestElement : ... BindingIdentifier
  324. // BindingRestElement : ... BindingPattern
  325. if (entry.is_rest) {
  326. VERIFY(i == binding.entries.size() - 1);
  327. // 2. Let A be ! ArrayCreate(0).
  328. auto* array = MUST(Array::create(global_object, 0));
  329. // 3. Let n be 0.
  330. // 4. Repeat,
  331. while (true) {
  332. ThrowCompletionOr<Object*> next { nullptr };
  333. // a. If iteratorRecord.[[Done]] is false, then
  334. if (!iterator_record.done) {
  335. // i. Let next be IteratorStep(iteratorRecord).
  336. next = iterator_step(global_object, iterator_record);
  337. // ii. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
  338. // iii. ReturnIfAbrupt(next).
  339. if (next.is_error()) {
  340. iterator_record.done = true;
  341. return next.release_error();
  342. }
  343. // iv. If next is false, set iteratorRecord.[[Done]] to true.
  344. if (!next.value())
  345. iterator_record.done = true;
  346. }
  347. // b. If iteratorRecord.[[Done]] is true, then
  348. if (iterator_record.done) {
  349. // NOTE: Step i. and ii. are handled below.
  350. break;
  351. }
  352. // c. Let nextValue be IteratorValue(next).
  353. auto next_value = iterator_value(global_object, *next.value());
  354. // d. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
  355. // e. ReturnIfAbrupt(nextValue).
  356. if (next_value.is_error()) {
  357. iterator_record.done = true;
  358. return next_value.release_error();
  359. }
  360. // f. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), nextValue).
  361. array->indexed_properties().append(next_value.value());
  362. // g. Set n to n + 1.
  363. }
  364. value = array;
  365. }
  366. // SingleNameBinding : BindingIdentifier Initializer[opt]
  367. // BindingElement : BindingPattern Initializer[opt]
  368. else {
  369. // 1. Let v be undefined.
  370. value = js_undefined();
  371. // 2. If iteratorRecord.[[Done]] is false, then
  372. if (!iterator_record.done) {
  373. // a. Let next be IteratorStep(iteratorRecord).
  374. auto next = iterator_step(global_object, iterator_record);
  375. // b. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
  376. // c. ReturnIfAbrupt(next).
  377. if (next.is_error()) {
  378. iterator_record.done = true;
  379. return next.release_error();
  380. }
  381. // d. If next is false, set iteratorRecord.[[Done]] to true.
  382. if (!next.value()) {
  383. iterator_record.done = true;
  384. }
  385. // e. Else,
  386. else {
  387. // i. Set v to IteratorValue(next).
  388. auto value_or_error = iterator_value(global_object, *next.value());
  389. // ii. If v is an abrupt completion, set iteratorRecord.[[Done]] to true.
  390. // iii. ReturnIfAbrupt(v).
  391. if (value_or_error.is_throw_completion()) {
  392. iterator_record.done = true;
  393. return value_or_error.release_error();
  394. }
  395. value = value_or_error.release_value();
  396. }
  397. }
  398. // NOTE: Step 3. and 4. are handled below.
  399. }
  400. if (value.is_undefined() && entry.initializer) {
  401. VERIFY(!entry.is_rest);
  402. if (auto* identifier_ptr = entry.alias.get_pointer<NonnullRefPtr<Identifier>>())
  403. value = TRY(named_evaluation_if_anonymous_function(global_object, *entry.initializer, (*identifier_ptr)->string()));
  404. else
  405. value = TRY(entry.initializer->execute(interpreter(), global_object)).release_value();
  406. }
  407. if (auto* binding_ptr = entry.alias.get_pointer<NonnullRefPtr<BindingPattern>>()) {
  408. TRY(binding_initialization(*binding_ptr, value, environment, global_object));
  409. } else if (!entry.alias.has<Empty>()) {
  410. VERIFY(assignment_target.has_value());
  411. if (!environment)
  412. TRY(assignment_target->put_value(global_object, value));
  413. else
  414. TRY(assignment_target->initialize_referenced_binding(global_object, value));
  415. }
  416. }
  417. return {};
  418. }
  419. // 9.1.2.1 GetIdentifierReference ( env, name, strict ), https://tc39.es/ecma262/#sec-getidentifierreference
  420. ThrowCompletionOr<Reference> VM::get_identifier_reference(Environment* environment, FlyString name, bool strict, size_t hops)
  421. {
  422. // 1. If env is the value null, then
  423. if (!environment) {
  424. // a. Return the Reference Record { [[Base]]: unresolvable, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }.
  425. return Reference { Reference::BaseType::Unresolvable, move(name), strict };
  426. }
  427. // 2. Let exists be ? env.HasBinding(name).
  428. Optional<size_t> index;
  429. auto exists = TRY(environment->has_binding(name, &index));
  430. // Note: This is an optimization for looking up the same reference.
  431. Optional<EnvironmentCoordinate> environment_coordinate;
  432. if (index.has_value())
  433. environment_coordinate = EnvironmentCoordinate { .hops = hops, .index = index.value() };
  434. // 3. If exists is true, then
  435. if (exists) {
  436. // a. Return the Reference Record { [[Base]]: env, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }.
  437. return Reference { *environment, move(name), strict, environment_coordinate };
  438. }
  439. // 4. Else,
  440. else {
  441. // a. Let outer be env.[[OuterEnv]].
  442. // b. Return ? GetIdentifierReference(outer, name, strict).
  443. return get_identifier_reference(environment->outer_environment(), move(name), strict, hops + 1);
  444. }
  445. }
  446. // 9.4.2 ResolveBinding ( name [ , env ] ), https://tc39.es/ecma262/#sec-resolvebinding
  447. ThrowCompletionOr<Reference> VM::resolve_binding(FlyString const& name, Environment* environment)
  448. {
  449. // 1. If env is not present or if env is undefined, then
  450. if (!environment) {
  451. // a. Set env to the running execution context's LexicalEnvironment.
  452. environment = running_execution_context().lexical_environment;
  453. }
  454. // 2. Assert: env is an Environment Record.
  455. VERIFY(environment);
  456. // 3. If the code matching the syntactic production that is being evaluated is contained in strict mode code, let strict be true; else let strict be false.
  457. bool strict = in_strict_mode();
  458. // 4. Return ? GetIdentifierReference(env, name, strict).
  459. return get_identifier_reference(environment, name, strict);
  460. // NOTE: The spec says:
  461. // Note: The result of ResolveBinding is always a Reference Record whose [[ReferencedName]] field is name.
  462. // But this is not actually correct as GetIdentifierReference (or really the methods it calls) can throw.
  463. }
  464. // 7.3.33 InitializeInstanceElements ( O, constructor ), https://tc39.es/ecma262/#sec-initializeinstanceelements
  465. ThrowCompletionOr<void> VM::initialize_instance_elements(Object& object, ECMAScriptFunctionObject& constructor)
  466. {
  467. for (auto& method : constructor.private_methods())
  468. TRY(object.private_method_or_accessor_add(method));
  469. for (auto& field : constructor.fields())
  470. TRY(object.define_field(field.name, field.initializer));
  471. return {};
  472. }
  473. // 9.4.4 ResolveThisBinding ( ), https://tc39.es/ecma262/#sec-resolvethisbinding
  474. ThrowCompletionOr<Value> VM::resolve_this_binding(GlobalObject& global_object)
  475. {
  476. // 1. Let envRec be GetThisEnvironment().
  477. auto& environment = get_this_environment(*this);
  478. // 2. Return ? envRec.GetThisBinding().
  479. return TRY(environment.get_this_binding(global_object));
  480. }
  481. String VM::join_arguments(size_t start_index) const
  482. {
  483. StringBuilder joined_arguments;
  484. for (size_t i = start_index; i < argument_count(); ++i) {
  485. joined_arguments.append(argument(i).to_string_without_side_effects().characters());
  486. if (i != argument_count() - 1)
  487. joined_arguments.append(' ');
  488. }
  489. return joined_arguments.build();
  490. }
  491. // 9.4.5 GetNewTarget ( ), https://tc39.es/ecma262/#sec-getnewtarget
  492. Value VM::get_new_target()
  493. {
  494. // 1. Let envRec be GetThisEnvironment().
  495. auto& env = get_this_environment(*this);
  496. // 2. Assert: envRec has a [[NewTarget]] field.
  497. // 3. Return envRec.[[NewTarget]].
  498. return verify_cast<FunctionEnvironment>(env).new_target();
  499. }
  500. bool VM::in_strict_mode() const
  501. {
  502. if (execution_context_stack().is_empty())
  503. return false;
  504. return running_execution_context().is_strict_mode;
  505. }
  506. void VM::run_queued_promise_jobs()
  507. {
  508. dbgln_if(PROMISE_DEBUG, "Running queued promise jobs");
  509. while (!m_promise_jobs.is_empty()) {
  510. auto* job = m_promise_jobs.take_first();
  511. dbgln_if(PROMISE_DEBUG, "Calling promise job function @ {}", job);
  512. // NOTE: If the execution context stack is empty, we make and push a temporary context.
  513. ExecutionContext execution_context(heap());
  514. bool pushed_execution_context = false;
  515. if (m_execution_context_stack.is_empty()) {
  516. static FlyString promise_execution_context_name = "(promise execution context)";
  517. execution_context.function_name = promise_execution_context_name;
  518. // FIXME: Propagate potential failure
  519. MUST(push_execution_context(execution_context, job->global_object()));
  520. pushed_execution_context = true;
  521. }
  522. [[maybe_unused]] auto result = call(job->global_object(), *job, js_undefined());
  523. // This doesn't match the spec, it actually defines that Job Abstract Closures must return
  524. // a normal completion. In reality that's not the case however, and all major engines clear
  525. // exceptions when running Promise jobs. See the commit where these two lines were initially
  526. // added for a much more detailed explanation. (Hash: a53542e0a3fbd7bf22b685d87f0473e489e1cf42)
  527. if (pushed_execution_context)
  528. pop_execution_context();
  529. }
  530. }
  531. // 9.5.4 HostEnqueuePromiseJob ( job, realm ), https://tc39.es/ecma262/#sec-hostenqueuepromisejob
  532. void VM::enqueue_promise_job(NativeFunction& job)
  533. {
  534. m_promise_jobs.append(&job);
  535. }
  536. void VM::run_queued_finalization_registry_cleanup_jobs()
  537. {
  538. while (!m_finalization_registry_cleanup_jobs.is_empty()) {
  539. auto* registry = m_finalization_registry_cleanup_jobs.take_first();
  540. // FIXME: Handle any uncatched exceptions here.
  541. (void)registry->cleanup();
  542. }
  543. }
  544. // 9.10.4.1 HostEnqueueFinalizationRegistryCleanupJob ( finalizationRegistry ), https://tc39.es/ecma262/#sec-host-cleanup-finalization-registry
  545. void VM::enqueue_finalization_registry_cleanup_job(FinalizationRegistry& registry)
  546. {
  547. m_finalization_registry_cleanup_jobs.append(&registry);
  548. }
  549. // 27.2.1.9 HostPromiseRejectionTracker ( promise, operation ), https://tc39.es/ecma262/#sec-host-promise-rejection-tracker
  550. void VM::promise_rejection_tracker(const Promise& promise, Promise::RejectionOperation operation) const
  551. {
  552. switch (operation) {
  553. case Promise::RejectionOperation::Reject:
  554. // A promise was rejected without any handlers
  555. if (on_promise_unhandled_rejection)
  556. on_promise_unhandled_rejection(promise);
  557. break;
  558. case Promise::RejectionOperation::Handle:
  559. // A handler was added to an already rejected promise
  560. if (on_promise_rejection_handled)
  561. on_promise_rejection_handled(promise);
  562. break;
  563. default:
  564. VERIFY_NOT_REACHED();
  565. }
  566. }
  567. void VM::dump_backtrace() const
  568. {
  569. for (ssize_t i = m_execution_context_stack.size() - 1; i >= 0; --i) {
  570. auto& frame = m_execution_context_stack[i];
  571. if (frame->current_node) {
  572. auto& source_range = frame->current_node->source_range();
  573. dbgln("-> {} @ {}:{},{}", frame->function_name, source_range.filename, source_range.start.line, source_range.start.column);
  574. } else {
  575. dbgln("-> {}", frame->function_name);
  576. }
  577. }
  578. }
  579. VM::CustomData::~CustomData()
  580. {
  581. }
  582. void VM::save_execution_context_stack()
  583. {
  584. m_saved_execution_context_stacks.append(move(m_execution_context_stack));
  585. }
  586. void VM::restore_execution_context_stack()
  587. {
  588. m_execution_context_stack = m_saved_execution_context_stacks.take_last();
  589. }
  590. // 9.4.1 GetActiveScriptOrModule ( ), https://tc39.es/ecma262/#sec-getactivescriptormodule
  591. ScriptOrModule VM::get_active_script_or_module() const
  592. {
  593. // 1. If the execution context stack is empty, return null.
  594. if (m_execution_context_stack.is_empty())
  595. return Empty {};
  596. // 2. Let ec be the topmost execution context on the execution context stack whose ScriptOrModule component is not null.
  597. for (auto i = m_execution_context_stack.size() - 1; i > 0; i--) {
  598. if (!m_execution_context_stack[i]->script_or_module.has<Empty>())
  599. return m_execution_context_stack[i]->script_or_module;
  600. }
  601. // 3. If no such execution context exists, return null. Otherwise, return ec's ScriptOrModule.
  602. // Note: Since it is not empty we have 0 and since we got here all the
  603. // above contexts don't have a non-null ScriptOrModule
  604. return m_execution_context_stack[0]->script_or_module;
  605. }
  606. VM::StoredModule* VM::get_stored_module(ScriptOrModule const&, String const& filepath, String const&)
  607. {
  608. // Note the spec says:
  609. // Each time this operation is called with a specific referencingScriptOrModule, specifier pair as arguments
  610. // it must return the same Module Record instance if it completes normally.
  611. // Currently, we ignore the referencing script or module but this might not be correct in all cases.
  612. // Editor's Note from https://tc39.es/proposal-json-modules/#sec-hostresolveimportedmodule
  613. // The above text implies that is recommended but not required that hosts do not use moduleRequest.[[Assertions]]
  614. // as part of the module cache key. In either case, an exception thrown from an import with a given assertion list
  615. // does not rule out success of another import with the same specifier but a different assertion list.
  616. auto end_or_module = m_loaded_modules.find_if([&](StoredModule const& stored_module) {
  617. return stored_module.filepath == filepath;
  618. });
  619. if (end_or_module.is_end())
  620. return nullptr;
  621. return &(*end_or_module);
  622. }
  623. ThrowCompletionOr<void> VM::link_and_eval_module(Badge<Interpreter>, SourceTextModule& module)
  624. {
  625. return link_and_eval_module(module);
  626. }
  627. ThrowCompletionOr<void> VM::link_and_eval_module(Module& module)
  628. {
  629. auto filepath = module.filename();
  630. auto module_or_end = m_loaded_modules.find_if([&](StoredModule const& stored_module) {
  631. return stored_module.module.ptr() == &module;
  632. });
  633. StoredModule* stored_module;
  634. if (module_or_end.is_end()) {
  635. dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] Warning introducing module via link_and_eval_module {}", module.filename());
  636. if (m_loaded_modules.size() > 0)
  637. dbgln("Warning: Using multiple modules as entry point can lead to unexpected results");
  638. m_loaded_modules.empend(
  639. module.make_weak_ptr(),
  640. module.filename(),
  641. String {}, // Null type
  642. module,
  643. true);
  644. stored_module = &m_loaded_modules.last();
  645. } else {
  646. stored_module = module_or_end.operator->();
  647. if (stored_module->has_once_started_linking) {
  648. dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] Module already has started linking once {}", module.filename());
  649. return {};
  650. }
  651. stored_module->has_once_started_linking = true;
  652. }
  653. dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] Linking module {}", filepath);
  654. auto linked_or_error = module.link(*this);
  655. if (linked_or_error.is_error())
  656. return linked_or_error.throw_completion();
  657. dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] Linking passed, now evaluating module {}", filepath);
  658. auto evaluated_or_error = module.evaluate(*this);
  659. if (evaluated_or_error.is_error())
  660. return evaluated_or_error.throw_completion();
  661. auto* evaluated_value = evaluated_or_error.value();
  662. run_queued_promise_jobs();
  663. VERIFY(m_promise_jobs.is_empty());
  664. // FIXME: This will break if we start doing promises actually asynchronously.
  665. VERIFY(evaluated_value->state() != Promise::State::Pending);
  666. if (evaluated_value->state() == Promise::State::Rejected)
  667. return JS::throw_completion(evaluated_value->result());
  668. dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] Evaluating passed for module {}", module.filename());
  669. return {};
  670. }
  671. // 16.2.1.7 HostResolveImportedModule ( referencingScriptOrModule, specifier ), https://tc39.es/ecma262/#sec-hostresolveimportedmodule
  672. ThrowCompletionOr<NonnullRefPtr<Module>> VM::resolve_imported_module(ScriptOrModule referencing_script_or_module, ModuleRequest const& module_request)
  673. {
  674. // An implementation of HostResolveImportedModule must conform to the following requirements:
  675. // - If it completes normally, the [[Value]] slot of the completion must contain an instance of a concrete subclass of Module Record.
  676. // - If a Module Record corresponding to the pair referencingScriptOrModule, moduleRequest does not exist or cannot be created, an exception must be thrown.
  677. // - Each time this operation is called with a specific referencingScriptOrModule, moduleRequest.[[Specifier]], moduleRequest.[[Assertions]] triple
  678. // as arguments it must return the same Module Record instance if it completes normally.
  679. // * It is recommended but not required that implementations additionally conform to the following stronger constraint:
  680. // each time this operation is called with a specific referencingScriptOrModule, moduleRequest.[[Specifier]] pair as arguments it must return the same Module Record instance if it completes normally.
  681. // - moduleRequest.[[Assertions]] must not influence the interpretation of the module or the module specifier;
  682. // instead, it may be used to determine whether the algorithm completes normally or with an abrupt completion.
  683. // Multiple different referencingScriptOrModule, moduleRequest.[[Specifier]] pairs may map to the same Module Record instance.
  684. // The actual mapping semantic is host-defined but typically a normalization process is applied to specifier as part of the mapping process.
  685. // A typical normalization process would include actions such as alphabetic case folding and expansion of relative and abbreviated path specifiers.
  686. StringView base_filename = referencing_script_or_module.visit(
  687. [&](Empty) {
  688. return "."sv;
  689. },
  690. [&](auto& script_or_module) {
  691. return script_or_module->filename();
  692. });
  693. LexicalPath base_path { base_filename };
  694. auto filepath = LexicalPath::absolute_path(base_path.dirname(), module_request.module_specifier);
  695. #if JS_MODULE_DEBUG
  696. String referencing_module_string = referencing_script_or_module.visit(
  697. [&](Empty) -> String {
  698. return ".";
  699. },
  700. [&](auto& script_or_module) {
  701. if constexpr (IsSame<Script*, decltype(script_or_module)>) {
  702. return String::formatted("Script @ {}", script_or_module);
  703. }
  704. return String::formatted("Module @ {}", script_or_module);
  705. });
  706. dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] resolve_imported_module({}, {})", referencing_module_string, filepath);
  707. dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] resolved {} + {} -> {}", base_path, module_request.module_specifier, filepath);
  708. #endif
  709. // We only allow "type" as a supported assertion so it is the only valid key that should ever arrive here.
  710. VERIFY(module_request.assertions.is_empty() || (module_request.assertions.size() == 1 && module_request.assertions.first().key == "type"));
  711. auto module_type = module_request.assertions.is_empty() ? String {} : module_request.assertions.first().value;
  712. dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] module at {} has type {} [is_null={}]", module_request.module_specifier, module_type, module_type.is_null());
  713. auto* loaded_module_or_end = get_stored_module(referencing_script_or_module, filepath, module_type);
  714. if (loaded_module_or_end != nullptr) {
  715. dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] resolve_imported_module({}) already loaded at {}", filepath, loaded_module_or_end->module.ptr());
  716. return loaded_module_or_end->module;
  717. }
  718. dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] reading and parsing module {}", filepath);
  719. auto& global_object = current_realm()->global_object();
  720. auto file_or_error = Core::File::open(filepath, Core::OpenMode::ReadOnly);
  721. if (file_or_error.is_error()) {
  722. return throw_completion<SyntaxError>(global_object, ErrorType::ModuleNotFound, module_request.module_specifier);
  723. }
  724. // FIXME: Don't read the file in one go.
  725. auto file_content = file_or_error.value()->read_all();
  726. StringView content_view { file_content.data(), file_content.size() };
  727. auto module = TRY([&]() -> ThrowCompletionOr<NonnullRefPtr<Module>> {
  728. // If assertions has an entry entry such that entry.[[Key]] is "type", let type be entry.[[Value]]. The following requirements apply:
  729. // If type is "json", then this algorithm must either invoke ParseJSONModule and return the resulting Completion Record, or throw an exception.
  730. if (module_type == "json"sv) {
  731. dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] reading and parsing JSON module {}", filepath);
  732. return parse_json_module(content_view, *current_realm(), filepath);
  733. }
  734. dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] reading and parsing as SourceTextModule module {}", filepath);
  735. // Note: We treat all files as module, so if a script does not have exports it just runs it.
  736. auto module_or_errors = SourceTextModule::parse(content_view, *current_realm(), filepath);
  737. if (module_or_errors.is_error()) {
  738. VERIFY(module_or_errors.error().size() > 0);
  739. return throw_completion<SyntaxError>(global_object, module_or_errors.error().first().to_string());
  740. }
  741. return module_or_errors.release_value();
  742. }());
  743. dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] resolve_imported_module(...) parsed {} to {}", filepath, module.ptr());
  744. // We have to set it here already in case it references itself.
  745. m_loaded_modules.empend(
  746. referencing_script_or_module,
  747. filepath,
  748. module_type,
  749. module,
  750. false);
  751. return module;
  752. }
  753. // 16.2.1.8 HostImportModuleDynamically ( referencingScriptOrModule, specifier, promiseCapability ), https://tc39.es/ecma262/#sec-hostimportmoduledynamically
  754. void VM::import_module_dynamically(ScriptOrModule referencing_script_or_module, ModuleRequest module_request, PromiseCapability promise_capability)
  755. {
  756. auto& global_object = current_realm()->global_object();
  757. // Success path:
  758. // - At some future time, the host environment must perform FinishDynamicImport(referencingScriptOrModule, moduleRequest, promiseCapability, promise),
  759. // where promise is a Promise resolved with undefined.
  760. // - Any subsequent call to HostResolveImportedModule after FinishDynamicImport has completed,
  761. // given the arguments referencingScriptOrModule and moduleRequest, must complete normally.
  762. // - The completion value of any subsequent call to HostResolveImportedModule after FinishDynamicImport has completed,
  763. // given the arguments referencingScriptOrModule and moduleRequest, must be a module which has already been evaluated,
  764. // i.e. whose Evaluate concrete method has already been called and returned a normal completion.
  765. // Failure path:
  766. // - At some future time, the host environment must perform
  767. // FinishDynamicImport(referencingScriptOrModule, moduleRequest, promiseCapability, promise),
  768. // where promise is a Promise rejected with an error representing the cause of failure.
  769. auto* promise = Promise::create(global_object);
  770. ScopeGuard finish_dynamic_import = [&] {
  771. host_finish_dynamic_import(referencing_script_or_module, move(module_request), promise_capability, promise);
  772. };
  773. // Generally within ECMA262 we always get a referencing_script_or_moulde. However, ShadowRealm gives an explicit null.
  774. // To get around this is we attempt to get the active script_or_module otherwise we might start loading "random" files from the working directory.
  775. if (referencing_script_or_module.has<Empty>()) {
  776. referencing_script_or_module = get_active_script_or_module();
  777. // If there is no ScriptOrModule in any of the execution contexts
  778. if (referencing_script_or_module.has<Empty>()) {
  779. // Throw an error for now
  780. promise->reject(InternalError::create(global_object, String::formatted(ErrorType::ModuleNotFoundNoReferencingScript.message(), module_request.module_specifier)));
  781. return;
  782. }
  783. }
  784. // Note: If host_resolve_imported_module returns a module it has been loaded successfully and the next call in finish_dynamic_import will retrieve it again.
  785. auto module_or_error = host_resolve_imported_module(referencing_script_or_module, module_request);
  786. dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] HostImportModuleDynamically(..., {}) -> {}", module_request.module_specifier, module_or_error.is_error() ? "failed" : "passed");
  787. if (module_or_error.is_throw_completion()) {
  788. promise->reject(*module_or_error.throw_completion().value());
  789. } else {
  790. auto module = module_or_error.release_value();
  791. auto& source_text_module = static_cast<Module&>(*module);
  792. auto evaluated_or_error = link_and_eval_module(source_text_module);
  793. if (evaluated_or_error.is_throw_completion()) {
  794. promise->reject(*evaluated_or_error.throw_completion().value());
  795. } else {
  796. promise->fulfill(js_undefined());
  797. }
  798. }
  799. // It must return NormalCompletion(undefined).
  800. // Note: Just return void always since the resulting value cannot be accessed by user code.
  801. }
  802. // 16.2.1.9 FinishDynamicImport ( referencingScriptOrModule, specifier, promiseCapability, innerPromise ), https://tc39.es/ecma262/#sec-finishdynamicimport
  803. void VM::finish_dynamic_import(ScriptOrModule referencing_script_or_module, ModuleRequest module_request, PromiseCapability promise_capability, Promise* inner_promise)
  804. {
  805. dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] finish_dynamic_import on {}", module_request.module_specifier);
  806. // 1. Let fulfilledClosure be a new Abstract Closure with parameters (result) that captures referencingScriptOrModule, specifier, and promiseCapability and performs the following steps when called:
  807. auto fulfilled_closure = [referencing_script_or_module, module_request = move(module_request), resolve_function = make_handle(promise_capability.resolve), reject_function = make_handle(promise_capability.reject)](VM& vm, GlobalObject& global_object) -> ThrowCompletionOr<Value> {
  808. auto result = vm.argument(0);
  809. // a. Assert: result is undefined.
  810. VERIFY(result.is_undefined());
  811. // b. Let moduleRecord be ! HostResolveImportedModule(referencingScriptOrModule, specifier).
  812. auto module_record = MUST(vm.host_resolve_imported_module(referencing_script_or_module, module_request));
  813. // c. Assert: Evaluate has already been invoked on moduleRecord and successfully completed.
  814. // Note: If HostResolveImportedModule returns a module evaluate will have been called on it.
  815. // d. Let namespace be GetModuleNamespace(moduleRecord).
  816. auto namespace_ = module_record->get_module_namespace(vm);
  817. // e. If namespace is an abrupt completion, then
  818. if (namespace_.is_throw_completion()) {
  819. // i. Perform ! Call(promiseCapability.[[Reject]], undefined, « namespace.[[Value]] »).
  820. MUST(call(global_object, reject_function.cell(), js_undefined(), *namespace_.throw_completion().value()));
  821. }
  822. // f. Else,
  823. else {
  824. // i. Perform ! Call(promiseCapability.[[Resolve]], undefined, « namespace.[[Value]] »).
  825. MUST(call(global_object, resolve_function.cell(), js_undefined(), namespace_.release_value()));
  826. }
  827. // g. Return undefined.
  828. return js_undefined();
  829. };
  830. // 2. Let onFulfilled be ! CreateBuiltinFunction(fulfilledClosure, 0, "", « »).
  831. auto* on_fulfilled = NativeFunction::create(current_realm()->global_object(), "", move(fulfilled_closure));
  832. // 3. Let rejectedClosure be a new Abstract Closure with parameters (error) that captures promiseCapability and performs the following steps when called:
  833. auto rejected_closure = [rejected_function = make_handle(promise_capability.reject)](VM& vm, GlobalObject& global_object) -> ThrowCompletionOr<Value> {
  834. auto error = vm.argument(0);
  835. // a. Perform ! Call(promiseCapability.[[Reject]], undefined, « error »).
  836. MUST(call(global_object, rejected_function.cell(), js_undefined(), error));
  837. // b. Return undefined.
  838. return js_undefined();
  839. };
  840. // 4. Let onRejected be ! CreateBuiltinFunction(rejectedClosure, 0, "", « »).
  841. auto* on_rejected = NativeFunction::create(current_realm()->global_object(), "", move(rejected_closure));
  842. // 5. Perform ! PerformPromiseThen(innerPromise, onFulfilled, onRejected).
  843. inner_promise->perform_then(on_fulfilled, on_rejected, {});
  844. }
  845. }