mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 19:17:44 +00:00
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
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).
|
// 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).
|
// 6. Let result be OrdinaryCallEvaluateBody(F, argumentsList).
|
||||||
auto result = ordinary_call_evaluate_body();
|
auto result = ordinary_call_evaluate_body();
|
||||||
|
@ -200,7 +200,7 @@ ThrowCompletionOr<Object*> ECMAScriptFunctionObject::internal_construct(MarkedVa
|
||||||
// 6. If kind is base, then
|
// 6. If kind is base, then
|
||||||
if (kind == ConstructorKind::Base) {
|
if (kind == ConstructorKind::Base) {
|
||||||
// a. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
|
// 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).
|
// b. Let initializeResult be InitializeInstanceElements(thisArgument, F).
|
||||||
auto initialize_result = vm.initialize_instance_elements(*this_argument, *this);
|
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.)
|
// 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
|
// 10.2.1.4 OrdinaryCallEvaluateBody ( F, argumentsList ), https://tc39.es/ecma262/#sec-ordinarycallevaluatebody
|
||||||
Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
|
Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
|
||||||
{
|
{
|
||||||
|
|
|
@ -83,6 +83,7 @@ private:
|
||||||
virtual void visit_edges(Visitor&) override;
|
virtual void visit_edges(Visitor&) override;
|
||||||
|
|
||||||
void prepare_for_ordinary_call(ExecutionContext& callee_context, Object* new_target);
|
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();
|
Completion ordinary_call_evaluate_body();
|
||||||
ThrowCompletionOr<void> function_declaration_instantiation(Interpreter*);
|
ThrowCompletionOr<void> function_declaration_instantiation(Interpreter*);
|
||||||
|
|
||||||
|
|
|
@ -525,34 +525,6 @@ Value VM::get_new_target()
|
||||||
return verify_cast<FunctionEnvironment>(env).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.
|
// 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.
|
// 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)
|
ThrowCompletionOr<Value> VM::call_internal(FunctionObject& function, Value this_value, Optional<MarkedValueList> arguments)
|
||||||
|
|
|
@ -274,9 +274,6 @@ public:
|
||||||
void save_execution_context_stack();
|
void save_execution_context_stack();
|
||||||
void restore_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:
|
private:
|
||||||
explicit VM(OwnPtr<CustomData>);
|
explicit VM(OwnPtr<CustomData>);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue