Created
November 27, 2022 16:45
-
-
Save awesomekling/7e977f4c8349b3915a7f8269ef13c9f3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp | |
index 2e2c483824..ddf3b66c7a 100644 | |
--- a/Userland/Libraries/LibJS/AST.cpp | |
+++ b/Userland/Libraries/LibJS/AST.cpp | |
@@ -289,42 +289,358 @@ Completion FunctionDeclaration::execute(Interpreter& interpreter) const | |
} | |
// 15.2.6 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-function-definitions-runtime-semantics-evaluation | |
+// 15.3.5 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-arrow-function-definitions-runtime-semantics-evaluation | |
+// 15.5.5 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-generator-function-definitions-runtime-semantics-evaluation | |
+// 15.6.5 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-asyncgenerator-definitions-evaluation | |
+// 15.8.5 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-async-function-definitions-runtime-semantics-evaluation | |
+Value FunctionExpression::instantiate_function_expression(Interpreter& interpreter, FlyString name) const | |
+{ | |
+ if (is_arrow_function()) { | |
+ // 1. Return InstantiateArrowFunctionExpression of ArrowFunction. | |
+ return instantiate_arrow_function_expression(interpreter, move(name)); | |
+ } | |
+ | |
+ switch (kind()) { | |
+ case FunctionKind::Normal: | |
+ // 1. Return InstantiateOrdinaryFunctionExpression of FunctionExpression. | |
+ return instantiate_ordinary_function_expression(interpreter, move(name)); | |
+ case FunctionKind::Async: | |
+ // 1. Return InstantiateAsyncFunctionExpression of AsyncFunctionExpression with argument name. | |
+ return instantiate_async_function_expression(interpreter, move(name)); | |
+ case FunctionKind::Generator: | |
+ // 1. Return InstantiateGeneratorFunctionExpression of GeneratorExpression with argument name. | |
+ return instantiate_generator_function_expression(interpreter, move(name)); | |
+ case FunctionKind::AsyncGenerator: | |
+ // 1. Return InstantiateAsyncGeneratorFunctionExpression of AsyncGeneratorExpression. | |
+ return instantiate_async_generator_function_expression(interpreter, move(name)); | |
+ } | |
+ | |
+ VERIFY_NOT_REACHED(); | |
+} | |
+ | |
Completion FunctionExpression::execute(Interpreter& interpreter) const | |
{ | |
InterpreterNodeScope node_scope { interpreter, *this }; | |
- | |
- // 1. Return InstantiateOrdinaryFunctionExpression of FunctionExpression. | |
- return instantiate_ordinary_function_expression(interpreter, name()); | |
+ return instantiate_function_expression(interpreter, name()); | |
} | |
// 15.2.5 Runtime Semantics: InstantiateOrdinaryFunctionExpression, https://tc39.es/ecma262/#sec-runtime-semantics-instantiateordinaryfunctionexpression | |
-Value FunctionExpression::instantiate_ordinary_function_expression(Interpreter& interpreter, FlyString given_name) const | |
+Value FunctionExpression::instantiate_ordinary_function_expression(Interpreter& interpreter, FlyString name) const | |
+{ | |
+ auto& vm = interpreter.vm(); | |
+ auto& realm = *vm.current_realm(); | |
+ | |
+ // FunctionExpression : function ( FormalParameters ) { FunctionBody } | |
+ if (!has_name()) { | |
+ | |
+ // 1. If name is not present, set name to "". | |
+ if (name.is_null()) | |
+ name = ""; | |
+ | |
+ // 2. Let env be the LexicalEnvironment of the running execution context. | |
+ auto* environment = vm.running_execution_context().lexical_environment; | |
+ | |
+ // 3. Let privateEnv be the running execution context's PrivateEnvironment. | |
+ auto* private_environment = vm.running_execution_context().private_environment; | |
+ | |
+ // 4. Let sourceText be the source text matched by FunctionExpression. | |
+ auto source_text = this->source_text(); | |
+ | |
+ // 5. Let closure be OrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, env, privateEnv). | |
+ auto closure = ECMAScriptFunctionObject::create(realm, name, source_text, body(), parameters(), function_length(), environment, private_environment, kind(), is_strict_mode(), might_need_arguments_object(), contains_direct_call_to_eval(), is_arrow_function()); | |
+ | |
+ // 6. Perform SetFunctionName(closure, name). | |
+ closure->set_name(name); | |
+ | |
+ // 7. Perform MakeConstructor(closure). | |
+ make_constructor(*closure); | |
+ | |
+ return closure; | |
+ } | |
+ | |
+ // FunctionExpression : function BindingIdentifier ( FormalParameters ) { FunctionBody } | |
+ | |
+ // 1. Assert: name is not present. | |
+ // 2. Set name to StringValue of BindingIdentifier. | |
+ name = this->name(); | |
+ | |
+ // 3. Let outerEnv be the LexicalEnvironment of the running execution context. | |
+ auto* outer_environment = vm.running_execution_context().lexical_environment; | |
+ | |
+ // 4. Let funcEnv be NewDeclarativeEnvironment(outerEnv). | |
+ auto* function_environment = new_declarative_environment(*outer_environment); | |
+ | |
+ // 5. Perform ! funcEnv.CreateImmutableBinding(name, false). | |
+ MUST(function_environment->create_immutable_binding(vm, name, false)); | |
+ | |
+ // 6. Let privateEnv be the running execution context's PrivateEnvironment. | |
+ auto* private_environment = vm.running_execution_context().private_environment; | |
+ | |
+ // 7. Let sourceText be the source text matched by FunctionExpression. | |
+ auto source_text = this->source_text(); | |
+ | |
+ // 8. Let closure be OrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, funcEnv, privateEnv). | |
+ auto closure = ECMAScriptFunctionObject::create(realm, name, source_text, body(), parameters(), function_length(), function_environment, private_environment, kind(), is_strict_mode(), might_need_arguments_object(), contains_direct_call_to_eval(), is_arrow_function()); | |
+ | |
+ // 9. Perform SetFunctionName(closure, name). | |
+ closure->set_name(name); | |
+ | |
+ // 10. Perform MakeConstructor(closure). | |
+ make_constructor(*closure); | |
+ | |
+ // 11. Perform ! funcEnv.InitializeBinding(name, closure). | |
+ MUST(function_environment->initialize_binding(vm, name, closure)); | |
+ | |
+ // 12. Return closure. | |
+ return closure; | |
+} | |
+ | |
+// 15.3.4 Runtime Semantics: InstantiateArrowFunctionExpression, https://tc39.es/ecma262/#sec-runtime-semantics-instantiatearrowfunctionexpression | |
+Value FunctionExpression::instantiate_arrow_function_expression(Interpreter& interpreter, FlyString name) const | |
+{ | |
+ auto& vm = interpreter.vm(); | |
+ auto& realm = *vm.current_realm(); | |
+ | |
+ // 1. If name is not present, set name to "". | |
+ if (name.is_null()) | |
+ name = ""; | |
+ | |
+ // 2. Let env be the LexicalEnvironment of the running execution context. | |
+ auto* environment = vm.running_execution_context().lexical_environment; | |
+ | |
+ // 3. Let privateEnv be the running execution context's PrivateEnvironment. | |
+ auto* private_environment = vm.running_execution_context().private_environment; | |
+ | |
+ // 4. Let sourceText be the source text matched by ArrowFunction. | |
+ auto source_text = this->source_text(); | |
+ | |
+ // 5. Let closure be OrdinaryFunctionCreate(%Function.prototype%, sourceText, ArrowParameters, ConciseBody, lexical-this, env, privateEnv). | |
+ auto closure = ECMAScriptFunctionObject::create(realm, name, source_text, body(), parameters(), function_length(), environment, private_environment, kind(), is_strict_mode(), might_need_arguments_object(), contains_direct_call_to_eval(), is_arrow_function()); | |
+ | |
+ // 6. Perform SetFunctionName(closure, name). | |
+ closure->set_name(name); | |
+ | |
+ // 7. Return closure. | |
+ return closure; | |
+} | |
+ | |
+// 15.5.4 Runtime Semantics: InstantiateGeneratorFunctionExpression, https://tc39.es/ecma262/#sec-runtime-semantics-instantiategeneratorfunctionexpression | |
+Value FunctionExpression::instantiate_generator_function_expression(Interpreter& interpreter, FlyString name) const | |
+{ | |
+ auto& vm = interpreter.vm(); | |
+ auto& realm = *vm.current_realm(); | |
+ | |
+ // GeneratorExpression : function * ( FormalParameters ) { GeneratorBody } | |
+ if (!has_name()) { | |
+ | |
+ // 1. If name is not present, set name to "". | |
+ if (name.is_null()) | |
+ name = ""; | |
+ | |
+ // 2. Let env be the LexicalEnvironment of the running execution context. | |
+ auto* environment = vm.running_execution_context().lexical_environment; | |
+ | |
+ // 3. Let privateEnv be the running execution context's PrivateEnvironment. | |
+ auto* private_environment = vm.running_execution_context().private_environment; | |
+ | |
+ // 4. Let sourceText be the source text matched by GeneratorExpression. | |
+ auto source_text = this->source_text(); | |
+ | |
+ // 5. Let closure be OrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, env, privateEnv). | |
+ auto closure = ECMAScriptFunctionObject::create(realm, name, source_text, body(), parameters(), function_length(), environment, private_environment, kind(), is_strict_mode(), might_need_arguments_object(), contains_direct_call_to_eval(), is_arrow_function()); | |
+ | |
+ // 6. Perform SetFunctionName(closure, name). | |
+ closure->set_name(name); | |
+ | |
+ // 7. Let prototype be OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%). | |
+ auto* prototype = Object::create(realm, realm.intrinsics().generator_function_prototype_prototype()); | |
+ | |
+ // 8. Perform ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }). | |
+ MUST(closure->define_property_or_throw(vm.names.prototype, { .value = prototype, .writable = true, .enumerable = false, .configurable = false })); | |
+ | |
+ // 9. Return closure. | |
+ return closure; | |
+ } | |
+ | |
+ // GeneratorExpression : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } | |
+ | |
+ // 1. Assert: name is not present. | |
+ // 2. Set name to StringValue of BindingIdentifier. | |
+ name = this->name(); | |
+ | |
+ // 3. Let outerEnv be the LexicalEnvironment of the running execution context. | |
+ auto* outer_environment = vm.running_execution_context().lexical_environment; | |
+ | |
+ // 4. Let funcEnv be NewDeclarativeEnvironment(outerEnv). | |
+ auto* function_environment = new_declarative_environment(*outer_environment); | |
+ | |
+ // 5. Perform ! funcEnv.CreateImmutableBinding(name, false). | |
+ MUST(function_environment->create_immutable_binding(vm, name, false)); | |
+ | |
+ // 6. Let privateEnv be the running execution context's PrivateEnvironment. | |
+ auto* private_environment = vm.running_execution_context().private_environment; | |
+ | |
+ // 7. Let sourceText be the source text matched by GeneratorExpression. | |
+ auto source_text = this->source_text(); | |
+ | |
+ // 8. Let closure be OrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, funcEnv, privateEnv). | |
+ auto closure = ECMAScriptFunctionObject::create(realm, name, source_text, body(), parameters(), function_length(), function_environment, private_environment, kind(), is_strict_mode(), might_need_arguments_object(), contains_direct_call_to_eval(), is_arrow_function()); | |
+ | |
+ // 9. Perform SetFunctionName(closure, name). | |
+ closure->set_name(name); | |
+ | |
+ // 10. Let prototype be OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%). | |
+ auto* prototype = Object::create(realm, realm.intrinsics().generator_function_prototype_prototype()); | |
+ | |
+ // 11. Perform ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }). | |
+ MUST(closure->define_property_or_throw(vm.names.prototype, { .value = prototype, .writable = true, .enumerable = false, .configurable = false })); | |
+ | |
+ // 12. Perform ! funcEnv.InitializeBinding(name, closure). | |
+ MUST(function_environment->initialize_binding(vm, name, closure)); | |
+ | |
+ // 13. Return closure. | |
+ return closure; | |
+} | |
+ | |
+// 15.8.3 Runtime Semantics: InstantiateAsyncFunctionExpression, https://tc39.es/ecma262/#sec-runtime-semantics-instantiateasyncfunctionexpression | |
+Value FunctionExpression::instantiate_async_function_expression(Interpreter& interpreter, FlyString name) const | |
{ | |
auto& vm = interpreter.vm(); | |
auto& realm = *vm.current_realm(); | |
- if (given_name.is_empty()) | |
- given_name = ""; | |
- auto has_own_name = !name().is_empty(); | |
+ // AsyncFunctionExpression : async function ( FormalParameters ) { AsyncFunctionBody } | |
+ if (!has_name()) { | |
+ // 1. If name is not present, set name to "". | |
+ if (name.is_null()) | |
+ name = ""; | |
+ | |
+ // 2. Let env be the LexicalEnvironment of the running execution context. | |
+ auto* environment = vm.running_execution_context().lexical_environment; | |
+ | |
+ // 3. Let privateEnv be the running execution context's PrivateEnvironment. | |
+ auto* private_environment = vm.running_execution_context().private_environment; | |
- auto const& used_name = has_own_name ? name() : given_name; | |
- auto* environment = interpreter.lexical_environment(); | |
- if (has_own_name) { | |
- VERIFY(environment); | |
- environment = new_declarative_environment(*environment); | |
- MUST(environment->create_immutable_binding(vm, name(), false)); | |
+ // 4. Let sourceText be the source text matched by ArrowFunction. | |
+ auto source_text = this->source_text(); | |
+ | |
+ // 5. Let closure be OrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, env, privateEnv). | |
+ auto closure = ECMAScriptFunctionObject::create(realm, name, source_text, body(), parameters(), function_length(), environment, private_environment, kind(), is_strict_mode(), might_need_arguments_object(), contains_direct_call_to_eval(), is_arrow_function()); | |
+ | |
+ // 6. Perform SetFunctionName(closure, name). | |
+ closure->set_name(name); | |
+ | |
+ // 7. Return closure. | |
+ return closure; | |
} | |
+ // AsyncFunctionExpression : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } | |
+ | |
+ // 1. Assert: name is not present. | |
+ // 2. Set name to StringValue of BindingIdentifier. | |
+ name = this->name(); | |
+ | |
+ // 3. Let outerEnv be the LexicalEnvironment of the running execution context. | |
+ auto* outer_environment = vm.running_execution_context().lexical_environment; | |
+ | |
+ // 4. Let funcEnv be NewDeclarativeEnvironment(outerEnv). | |
+ auto* function_environment = new_declarative_environment(*outer_environment); | |
+ | |
+ // 5. Perform ! funcEnv.CreateImmutableBinding(name, false). | |
+ MUST(function_environment->create_immutable_binding(vm, name, false)); | |
+ | |
+ // 6. Let privateEnv be the running execution context's PrivateEnvironment. | |
auto* private_environment = vm.running_execution_context().private_environment; | |
- auto closure = ECMAScriptFunctionObject::create(realm, used_name, source_text(), body(), parameters(), function_length(), environment, private_environment, kind(), is_strict_mode(), might_need_arguments_object(), contains_direct_call_to_eval(), is_arrow_function()); | |
+ // 7. Let sourceText be the source text matched by AsyncFunctionExpression. | |
+ auto source_text = this->source_text(); | |
+ | |
+ // 8. Let closure be OrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, funcEnv, privateEnv). | |
+ auto closure = ECMAScriptFunctionObject::create(realm, name, source_text, body(), parameters(), function_length(), function_environment, private_environment, kind(), is_strict_mode(), might_need_arguments_object(), contains_direct_call_to_eval(), is_arrow_function()); | |
+ | |
+ // 9. Perform SetFunctionName(closure, name). | |
+ closure->set_name(name); | |
+ | |
+ // 10. Perform ! funcEnv.InitializeBinding(name, closure). | |
+ MUST(function_environment->initialize_binding(vm, name, closure)); | |
+ | |
+ // 11. Return closure. | |
+ return closure; | |
+} | |
+ | |
+// 15.6.4 Runtime Semantics: InstantiateAsyncGeneratorFunctionExpression, https://tc39.es/ecma262/#sec-runtime-semantics-instantiateasyncgeneratorfunctionexpression | |
+Value FunctionExpression::instantiate_async_generator_function_expression(Interpreter& interpreter, FlyString name) const | |
+{ | |
+ auto& vm = interpreter.vm(); | |
+ auto& realm = *vm.current_realm(); | |
+ | |
+ // AsyncGeneratorExpression : async function * ( FormalParameters ) { AsyncGeneratorBody } | |
+ if (!has_name()) { | |
+ // 1. If name is not present, set name to "". | |
+ if (name.is_null()) | |
+ name = ""; | |
+ | |
+ // 2. Let env be the LexicalEnvironment of the running execution context. | |
+ auto* environment = vm.running_execution_context().lexical_environment; | |
+ | |
+ // 3. Let privateEnv be the running execution context's PrivateEnvironment. | |
+ auto* private_environment = vm.running_execution_context().private_environment; | |
+ | |
+ // 4. Let sourceText be the source text matched by AsyncGeneratorExpression. | |
+ auto source_text = this->source_text(); | |
+ | |
+ // 5. Let closure be OrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, env, privateEnv). | |
+ auto closure = ECMAScriptFunctionObject::create(realm, name, source_text, body(), parameters(), function_length(), environment, private_environment, kind(), is_strict_mode(), might_need_arguments_object(), contains_direct_call_to_eval(), is_arrow_function()); | |
+ | |
+ // 6. Perform SetFunctionName(closure, name). | |
+ closure->set_name(name); | |
+ | |
+ // 7. Let prototype be OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%). | |
+ auto* prototype = Object::create(realm, realm.intrinsics().async_generator_function_prototype_prototype()); | |
+ | |
+ // 8. Perform ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }). | |
+ MUST(closure->define_property_or_throw(vm.names.prototype, { .value = prototype, .writable = true, .enumerable = false, .configurable = false })); | |
+ | |
+ // 9. Return closure. | |
+ return closure; | |
+ } | |
+ | |
+ // AsyncGeneratorExpression : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } | |
+ | |
+ // 1. Assert: name is not present. | |
+ // 2. Set name to StringValue of BindingIdentifier. | |
+ name = this->name(); | |
+ | |
+ // 3. Let outerEnv be the LexicalEnvironment of the running execution context. | |
+ auto* outer_environment = vm.running_execution_context().lexical_environment; | |
+ | |
+ // 4. Let funcEnv be NewDeclarativeEnvironment(outerEnv). | |
+ auto* function_environment = new_declarative_environment(*outer_environment); | |
+ | |
+ // 5. Perform ! funcEnv.CreateImmutableBinding(name, false). | |
+ MUST(function_environment->create_immutable_binding(vm, name, false)); | |
+ | |
+ // 6. Let privateEnv be the running execution context's PrivateEnvironment. | |
+ auto* private_environment = vm.running_execution_context().private_environment; | |
+ | |
+ // 7. Let sourceText be the source text matched by AsyncGeneratorExpression. | |
+ auto source_text = this->source_text(); | |
+ | |
+ // 8. Let closure be OrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, funcEnv, privateEnv). | |
+ auto closure = ECMAScriptFunctionObject::create(realm, name, source_text, body(), parameters(), function_length(), function_environment, private_environment, kind(), is_strict_mode(), might_need_arguments_object(), contains_direct_call_to_eval(), is_arrow_function()); | |
+ | |
+ // 9. Perform SetFunctionName(closure, name). | |
+ closure->set_name(name); | |
+ | |
+ // 10. Let prototype be OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%). | |
+ auto* prototype = Object::create(realm, realm.intrinsics().async_generator_function_prototype_prototype()); | |
- // FIXME: 6. Perform SetFunctionName(closure, name). | |
- // FIXME: 7. Perform MakeConstructor(closure). | |
+ // 11. Perform ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }). | |
+ MUST(closure->define_property_or_throw(vm.names.prototype, { .value = prototype, .writable = true, .enumerable = false, .configurable = false })); | |
- if (has_own_name) | |
- MUST(environment->initialize_binding(vm, name(), closure)); | |
+ // 12. Perform ! funcEnv.InitializeBinding(name, closure). | |
+ MUST(function_environment->initialize_binding(vm, name, closure)); | |
+ // 13. Return closure. | |
return closure; | |
} | |
diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h | |
index 58cbd3e399..005c46b56c 100644 | |
--- a/Userland/Libraries/LibJS/AST.h | |
+++ b/Userland/Libraries/LibJS/AST.h | |
@@ -731,9 +731,15 @@ public: | |
bool has_name() const { return !name().is_empty(); } | |
- Value instantiate_ordinary_function_expression(Interpreter&, FlyString given_name) const; | |
+ Value instantiate_function_expression(Interpreter&, FlyString name) const; | |
private: | |
+ Value instantiate_arrow_function_expression(Interpreter&, FlyString name) const; | |
+ Value instantiate_ordinary_function_expression(Interpreter&, FlyString name) const; | |
+ Value instantiate_async_function_expression(Interpreter&, FlyString name) const; | |
+ Value instantiate_async_generator_function_expression(Interpreter&, FlyString name) const; | |
+ Value instantiate_generator_function_expression(Interpreter&, FlyString name) const; | |
+ | |
virtual bool is_function_expression() const override { return true; } | |
}; | |
diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp | |
index 77dfb031bb..7a645211e3 100644 | |
--- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp | |
+++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp | |
@@ -460,6 +460,25 @@ bool can_be_held_weakly(Value value) | |
return false; | |
} | |
+// 10.2.5 MakeConstructor ( F [ , writablePrototype [ , prototype ] ] ), https://tc39.es/ecma262/#sec-makeconstructor | |
+void make_constructor(FunctionObject& function_object, bool writable_prototype, Object* prototype) | |
+{ | |
+ auto& vm = function_object.vm(); | |
+ | |
+ // NOTE: Steps 1-4 are done by the C++ type system. | |
+ | |
+ // 5. If prototype is not present, then | |
+ if (!prototype) { | |
+ // a. Set prototype to OrdinaryObjectCreate(%Object.prototype%). | |
+ prototype = Object::create(*function_object.realm(), function_object.realm()->intrinsics().object_prototype()); | |
+ | |
+ // b. Perform ! DefinePropertyOrThrow(prototype, "constructor", PropertyDescriptor { [[Value]]: F, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: true }). | |
+ MUST(prototype->define_property_or_throw(vm.names.constructor, { .value = &function_object, .writable = writable_prototype, .enumerable = false, .configurable = true })); | |
+ } | |
+ // 6. Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: false }). | |
+ MUST(function_object.define_property_or_throw(vm.names.prototype, { .value = prototype, .writable = writable_prototype, .enumerable = false, .configurable = false })); | |
+} | |
+ | |
// 13.3.7.2 GetSuperConstructor ( ), https://tc39.es/ecma262/#sec-getsuperconstructor | |
Object* get_super_constructor(VM& vm) | |
{ | |
diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h | |
index 7ba8d4237f..9d8334097b 100644 | |
--- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h | |
+++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h | |
@@ -24,6 +24,7 @@ FunctionEnvironment* new_function_environment(ECMAScriptFunctionObject&, Object* | |
PrivateEnvironment* new_private_environment(VM& vm, PrivateEnvironment* outer); | |
Environment& get_this_environment(VM&); | |
bool can_be_held_weakly(Value); | |
+void make_constructor(FunctionObject&, bool writable_prototype = true, Object* prototype = nullptr); | |
Object* get_super_constructor(VM&); | |
ThrowCompletionOr<Reference> make_super_property_reference(VM&, Value actual_this, PropertyKey const&, bool strict); | |
ThrowCompletionOr<Value> require_object_coercible(VM&, Value); | |
diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp | |
index f6a36846f6..251df0cd06 100644 | |
--- a/Userland/Libraries/LibJS/Runtime/VM.cpp | |
+++ b/Userland/Libraries/LibJS/Runtime/VM.cpp | |
@@ -249,7 +249,7 @@ ThrowCompletionOr<Value> VM::named_evaluation_if_anonymous_function(ASTNode cons | |
if (is<FunctionExpression>(expression)) { | |
auto& function = static_cast<FunctionExpression const&>(expression); | |
if (!function.has_name()) { | |
- return function.instantiate_ordinary_function_expression(interpreter(), name); | |
+ return function.instantiate_function_expression(interpreter(), name); | |
} | |
} else if (is<ClassExpression>(expression)) { | |
auto& class_expression = static_cast<ClassExpression const&>(expression); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment