LibJS: Move ordinary_call_bind_this() to ECMAScriptFunctionObject
Now that it only needs to deal with ECMAScriptFunctionObject via internal_call() / internal_construct(), we can: - Remove the generic FunctionObject parameter - Move it from the VM to ECMAScriptFunctionObject - Make it private
This commit is contained in:
parent
25bcd36116
commit
53af66d57d
Notes:
sideshowbarker
2024-07-18 02:53:11 +09:00
Author: https://github.com/linusg Commit: https://github.com/SerenityOS/serenity/commit/53af66d57d0 Pull-request: https://github.com/SerenityOS/serenity/pull/10402 Reviewed-by: https://github.com/awesomekling ✅
4 changed files with 52 additions and 33 deletions
|
@ -136,7 +136,7 @@ ThrowCompletionOr<Value> ECMAScriptFunctionObject::internal_call(Value this_argu
|
|||
}
|
||||
|
||||
// 5. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
|
||||
vm.ordinary_call_bind_this(*this, callee_context, this_argument);
|
||||
ordinary_call_bind_this(callee_context, this_argument);
|
||||
|
||||
// 6. Let result be OrdinaryCallEvaluateBody(F, argumentsList).
|
||||
auto result = ordinary_call_evaluate_body();
|
||||
|
@ -200,7 +200,7 @@ ThrowCompletionOr<Object*> ECMAScriptFunctionObject::internal_construct(MarkedVa
|
|||
// 6. If kind is base, then
|
||||
if (kind == ConstructorKind::Base) {
|
||||
// a. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
|
||||
vm.ordinary_call_bind_this(*this, callee_context, this_argument);
|
||||
ordinary_call_bind_this(callee_context, this_argument);
|
||||
|
||||
// b. Let initializeResult be InitializeInstanceElements(thisArgument, F).
|
||||
auto initialize_result = vm.initialize_instance_elements(*this_argument, *this);
|
||||
|
@ -615,6 +615,55 @@ void ECMAScriptFunctionObject::prepare_for_ordinary_call(ExecutionContext& calle
|
|||
// 14. Return calleeContext. (See NOTE above about how contexts are allocated on the C++ stack.)
|
||||
}
|
||||
|
||||
// 10.2.1.2 OrdinaryCallBindThis ( F, calleeContext, thisArgument ), https://tc39.es/ecma262/#sec-ordinarycallbindthis
|
||||
void ECMAScriptFunctionObject::ordinary_call_bind_this(ExecutionContext& callee_context, Value this_argument)
|
||||
{
|
||||
// 1. Let thisMode be F.[[ThisMode]].
|
||||
auto this_mode = m_this_mode;
|
||||
|
||||
// If thisMode is lexical, return NormalCompletion(undefined).
|
||||
if (this_mode == ThisMode::Lexical)
|
||||
return;
|
||||
|
||||
// 3. Let calleeRealm be F.[[Realm]].
|
||||
auto* callee_realm = m_realm;
|
||||
|
||||
// 4. Let localEnv be the LexicalEnvironment of calleeContext.
|
||||
auto* local_env = callee_context.lexical_environment;
|
||||
|
||||
Value this_value;
|
||||
|
||||
// 5. If thisMode is strict, let thisValue be thisArgument.
|
||||
if (this_mode == ThisMode::Strict) {
|
||||
this_value = this_argument;
|
||||
}
|
||||
// 6. Else,
|
||||
else {
|
||||
// a. If thisArgument is undefined or null, then
|
||||
if (this_argument.is_nullish()) {
|
||||
// i. Let globalEnv be calleeRealm.[[GlobalEnv]].
|
||||
// ii. Assert: globalEnv is a global Environment Record.
|
||||
auto& global_env = callee_realm->global_environment();
|
||||
|
||||
// iii. Let thisValue be globalEnv.[[GlobalThisValue]].
|
||||
this_value = &global_env.global_this_value();
|
||||
}
|
||||
// b. Else,
|
||||
else {
|
||||
// i. Let thisValue be ! ToObject(thisArgument).
|
||||
this_value = this_argument.to_object(global_object());
|
||||
|
||||
// ii. NOTE: ToObject produces wrapper objects using calleeRealm.
|
||||
// FIXME: It currently doesn't, as we pass the function's global object.
|
||||
}
|
||||
}
|
||||
|
||||
// 7. Assert: localEnv is a function Environment Record.
|
||||
// 8. Assert: The next step never returns an abrupt completion because localEnv.[[ThisBindingStatus]] is not initialized.
|
||||
// 9. Return localEnv.BindThisValue(thisValue).
|
||||
verify_cast<FunctionEnvironment>(local_env)->bind_this_value(global_object(), this_value);
|
||||
}
|
||||
|
||||
// 10.2.1.4 OrdinaryCallEvaluateBody ( F, argumentsList ), https://tc39.es/ecma262/#sec-ordinarycallevaluatebody
|
||||
Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
|
||||
{
|
||||
|
|
|
@ -83,6 +83,7 @@ private:
|
|||
virtual void visit_edges(Visitor&) override;
|
||||
|
||||
void prepare_for_ordinary_call(ExecutionContext& callee_context, Object* new_target);
|
||||
void ordinary_call_bind_this(ExecutionContext&, Value this_argument);
|
||||
Completion ordinary_call_evaluate_body();
|
||||
ThrowCompletionOr<void> function_declaration_instantiation(Interpreter*);
|
||||
|
||||
|
|
|
@ -525,34 +525,6 @@ Value VM::get_new_target()
|
|||
return verify_cast<FunctionEnvironment>(env).new_target();
|
||||
}
|
||||
|
||||
// 10.2.1.2 OrdinaryCallBindThis ( F, calleeContext, thisArgument ), https://tc39.es/ecma262/#sec-ordinarycallbindthis
|
||||
void VM::ordinary_call_bind_this(FunctionObject& function, ExecutionContext& callee_context, Value this_argument)
|
||||
{
|
||||
auto* callee_realm = function.realm();
|
||||
|
||||
auto* local_environment = callee_context.lexical_environment;
|
||||
auto& function_environment = verify_cast<FunctionEnvironment>(*local_environment);
|
||||
|
||||
// This almost as the spec describes it however we sometimes don't have callee_realm when dealing
|
||||
// with proxies and arrow functions however this does seemingly achieve spec like behavior.
|
||||
if (!callee_realm || (is<ECMAScriptFunctionObject>(function) && static_cast<ECMAScriptFunctionObject&>(function).this_mode() == ECMAScriptFunctionObject::ThisMode::Lexical)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Value this_value;
|
||||
if (function.is_strict_mode()) {
|
||||
this_value = this_argument;
|
||||
} else if (this_argument.is_nullish()) {
|
||||
auto& global_environment = callee_realm->global_environment();
|
||||
this_value = &global_environment.global_this_value();
|
||||
} else {
|
||||
this_value = this_argument.to_object(function.global_object());
|
||||
}
|
||||
|
||||
function_environment.bind_this_value(function.global_object(), this_value);
|
||||
callee_context.this_value = this_value;
|
||||
}
|
||||
|
||||
// NOTE: This is only here because there's a million invocations of vm.call() - it used to be tied to the VM in weird ways.
|
||||
// We should update all of those and then remove this, along with the call() template functions in VM.h, and use the standalone call() AO.
|
||||
ThrowCompletionOr<Value> VM::call_internal(FunctionObject& function, Value this_value, Optional<MarkedValueList> arguments)
|
||||
|
|
|
@ -274,9 +274,6 @@ public:
|
|||
void save_execution_context_stack();
|
||||
void restore_execution_context_stack();
|
||||
|
||||
// TODO: Move these elsewhere once only used for ECMAScriptFunctionObject.
|
||||
void ordinary_call_bind_this(FunctionObject&, ExecutionContext&, Value this_argument);
|
||||
|
||||
private:
|
||||
explicit VM(OwnPtr<CustomData>);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue