mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 16:52:43 +00:00 
			
		
		
		
	LibJS: Set the callee context's realm in prepare_for_ordinary_call()
This includes making FunctionObject::realm() actually return a Realm, instead of a GlobalObject.
This commit is contained in:
		
							parent
							
								
									332946ab4f
								
							
						
					
					
						commit
						06e89311fa
					
				
					 8 changed files with 31 additions and 11 deletions
				
			
		|  | @ -53,7 +53,7 @@ void Interpreter::run(GlobalObject& global_object, const Program& program) | ||||||
|     execution_context.function_name = global_execution_context_name; |     execution_context.function_name = global_execution_context_name; | ||||||
|     execution_context.lexical_environment = &realm().global_environment(); |     execution_context.lexical_environment = &realm().global_environment(); | ||||||
|     execution_context.variable_environment = &realm().global_environment(); |     execution_context.variable_environment = &realm().global_environment(); | ||||||
|     VERIFY(!vm.exception()); |     execution_context.realm = &realm(); | ||||||
|     execution_context.is_strict_mode = program.is_strict_mode(); |     execution_context.is_strict_mode = program.is_strict_mode(); | ||||||
|     vm.push_execution_context(execution_context, global_object); |     vm.push_execution_context(execution_context, global_object); | ||||||
|     VERIFY(!vm.exception()); |     VERIFY(!vm.exception()); | ||||||
|  |  | ||||||
|  | @ -118,7 +118,7 @@ GlobalObject* get_function_realm(GlobalObject& global_object, FunctionObject con | ||||||
|     // 2. If obj has a [[Realm]] internal slot, then
 |     // 2. If obj has a [[Realm]] internal slot, then
 | ||||||
|     if (function.realm()) { |     if (function.realm()) { | ||||||
|         // a. Return obj.[[Realm]].
 |         // a. Return obj.[[Realm]].
 | ||||||
|         return function.realm(); |         return &function.global_object(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // 3. If obj is a bound function exotic object, then
 |     // 3. If obj is a bound function exotic object, then
 | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ | ||||||
| 
 | 
 | ||||||
| namespace JS { | namespace JS { | ||||||
| 
 | 
 | ||||||
|  | // 10.2 ECMAScript Function Objects, https://tc39.es/ecma262/#sec-ecmascript-function-objects
 | ||||||
| class FunctionObject : public Object { | class FunctionObject : public Object { | ||||||
|     JS_OBJECT(Function, Object); |     JS_OBJECT(Function, Object); | ||||||
| 
 | 
 | ||||||
|  | @ -48,7 +49,7 @@ public: | ||||||
|     virtual Environment* environment() { return nullptr; } |     virtual Environment* environment() { return nullptr; } | ||||||
| 
 | 
 | ||||||
|     // [[Realm]]
 |     // [[Realm]]
 | ||||||
|     virtual GlobalObject* realm() const { return nullptr; } |     virtual Realm* realm() const { return nullptr; } | ||||||
| 
 | 
 | ||||||
|     enum class ThisMode : u8 { |     enum class ThisMode : u8 { | ||||||
|         Lexical, |         Lexical, | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
|  * SPDX-License-Identifier: BSD-2-Clause |  * SPDX-License-Identifier: BSD-2-Clause | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | #include <LibJS/Interpreter.h> | ||||||
| #include <LibJS/Runtime/GlobalObject.h> | #include <LibJS/Runtime/GlobalObject.h> | ||||||
| #include <LibJS/Runtime/NativeFunction.h> | #include <LibJS/Runtime/NativeFunction.h> | ||||||
| #include <LibJS/Runtime/Value.h> | #include <LibJS/Runtime/Value.h> | ||||||
|  | @ -15,8 +16,13 @@ NativeFunction* NativeFunction::create(GlobalObject& global_object, const FlyStr | ||||||
|     return global_object.heap().allocate<NativeFunction>(global_object, name, move(function), *global_object.function_prototype()); |     return global_object.heap().allocate<NativeFunction>(global_object, name, move(function), *global_object.function_prototype()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // FIXME: m_realm is supposed to be the realm argument of CreateBuiltinFunction, or the current
 | ||||||
|  | //        Realm Record. The former is not something that's commonly used or we support, the
 | ||||||
|  | //        latter is impossible as no ExecutionContext exists when most NativeFunctions are created...
 | ||||||
|  | 
 | ||||||
| NativeFunction::NativeFunction(Object& prototype) | NativeFunction::NativeFunction(Object& prototype) | ||||||
|     : FunctionObject(prototype) |     : FunctionObject(prototype) | ||||||
|  |     , m_realm(&vm().interpreter().realm()) | ||||||
| { | { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -24,12 +30,14 @@ NativeFunction::NativeFunction(FlyString name, Function<Value(VM&, GlobalObject& | ||||||
|     : FunctionObject(prototype) |     : FunctionObject(prototype) | ||||||
|     , m_name(move(name)) |     , m_name(move(name)) | ||||||
|     , m_native_function(move(native_function)) |     , m_native_function(move(native_function)) | ||||||
|  |     , m_realm(&vm().interpreter().realm()) | ||||||
| { | { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| NativeFunction::NativeFunction(FlyString name, Object& prototype) | NativeFunction::NativeFunction(FlyString name, Object& prototype) | ||||||
|     : FunctionObject(prototype) |     : FunctionObject(prototype) | ||||||
|     , m_name(move(name)) |     , m_name(move(name)) | ||||||
|  |     , m_realm(&vm().interpreter().realm()) | ||||||
| { | { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     virtual bool is_strict_mode() const override; |     virtual bool is_strict_mode() const override; | ||||||
| 
 | 
 | ||||||
|     GlobalObject* realm() const override { return &global_object(); } |     virtual Realm* realm() const override { return m_realm; } | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|     NativeFunction(FlyString name, Object& prototype); |     NativeFunction(FlyString name, Object& prototype); | ||||||
|  | @ -41,6 +41,7 @@ private: | ||||||
| 
 | 
 | ||||||
|     FlyString m_name; |     FlyString m_name; | ||||||
|     Function<Value(VM&, GlobalObject&)> m_native_function; |     Function<Value(VM&, GlobalObject&)> m_native_function; | ||||||
|  |     Realm* m_realm { nullptr }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template<> | template<> | ||||||
|  |  | ||||||
|  | @ -43,7 +43,7 @@ OrdinaryFunctionObject::OrdinaryFunctionObject(GlobalObject& global_object, cons | ||||||
|     , m_body(body) |     , m_body(body) | ||||||
|     , m_parameters(move(parameters)) |     , m_parameters(move(parameters)) | ||||||
|     , m_environment(parent_scope) |     , m_environment(parent_scope) | ||||||
|     , m_realm(&global_object) |     , m_realm(vm().current_realm()) | ||||||
|     , m_function_length(function_length) |     , m_function_length(function_length) | ||||||
|     , m_kind(kind) |     , m_kind(kind) | ||||||
|     , m_is_strict(is_strict) |     , m_is_strict(is_strict) | ||||||
|  |  | ||||||
|  | @ -36,8 +36,7 @@ public: | ||||||
|     auto& bytecode_executable() const { return m_bytecode_executable; } |     auto& bytecode_executable() const { return m_bytecode_executable; } | ||||||
| 
 | 
 | ||||||
|     virtual Environment* environment() override { return m_environment; } |     virtual Environment* environment() override { return m_environment; } | ||||||
| 
 |     virtual Realm* realm() const override { return m_realm; } | ||||||
|     GlobalObject* realm() const override { return m_realm; } |  | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|     virtual bool is_strict_mode() const final { return m_is_strict; } |     virtual bool is_strict_mode() const final { return m_is_strict; } | ||||||
|  | @ -54,7 +53,7 @@ private: | ||||||
|     const Vector<FunctionNode::Parameter> m_parameters; |     const Vector<FunctionNode::Parameter> m_parameters; | ||||||
|     Optional<Bytecode::Executable> m_bytecode_executable; |     Optional<Bytecode::Executable> m_bytecode_executable; | ||||||
|     Environment* m_environment { nullptr }; |     Environment* m_environment { nullptr }; | ||||||
|     GlobalObject* m_realm { nullptr }; |     Realm* m_realm { nullptr }; | ||||||
|     i32 m_function_length { 0 }; |     i32 m_function_length { 0 }; | ||||||
|     FunctionKind m_kind { FunctionKind::Regular }; |     FunctionKind m_kind { FunctionKind::Regular }; | ||||||
|     bool m_is_strict { false }; |     bool m_is_strict { false }; | ||||||
|  |  | ||||||
|  | @ -479,6 +479,8 @@ Value VM::construct(FunctionObject& function, FunctionObject& new_target, Option | ||||||
|             return {}; |             return {}; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     // FIXME: prepare_for_ordinary_call() is not supposed to receive a BoundFunction, ProxyObject, etc. - ever.
 | ||||||
|  |     //        This needs to be moved to NativeFunction/OrdinaryFunctionObject's construct() (10.2.2 [[Construct]])
 | ||||||
|     ExecutionContext callee_context(heap()); |     ExecutionContext callee_context(heap()); | ||||||
|     prepare_for_ordinary_call(function, callee_context, &new_target); |     prepare_for_ordinary_call(function, callee_context, &new_target); | ||||||
|     if (exception()) |     if (exception()) | ||||||
|  | @ -597,9 +599,17 @@ void VM::prepare_for_ordinary_call(FunctionObject& function, ExecutionContext& c | ||||||
|     callee_context.function_name = function.name(); |     callee_context.function_name = function.name(); | ||||||
| 
 | 
 | ||||||
|     // 4. Let calleeRealm be F.[[Realm]].
 |     // 4. Let calleeRealm be F.[[Realm]].
 | ||||||
|  |     auto* callee_realm = function.realm(); | ||||||
|  |     // FIXME: See FIXME in VM::call_internal() / VM::construct().
 | ||||||
|  |     if (!callee_realm) | ||||||
|  |         callee_realm = current_realm(); | ||||||
|  |     VERIFY(callee_realm); | ||||||
|  | 
 | ||||||
|     // 5. Set the Realm of calleeContext to calleeRealm.
 |     // 5. Set the Realm of calleeContext to calleeRealm.
 | ||||||
|  |     callee_context.realm = callee_realm; | ||||||
|  | 
 | ||||||
|     // 6. Set the ScriptOrModule of calleeContext to F.[[ScriptOrModule]].
 |     // 6. Set the ScriptOrModule of calleeContext to F.[[ScriptOrModule]].
 | ||||||
|     // FIXME: Our execution context struct currently does not track these items.
 |     // FIXME: Our execution context struct currently does not track this item.
 | ||||||
| 
 | 
 | ||||||
|     // 7. Let localEnv be NewFunctionEnvironment(F, newTarget).
 |     // 7. Let localEnv be NewFunctionEnvironment(F, newTarget).
 | ||||||
|     // FIXME: This should call NewFunctionEnvironment instead of the ad-hoc FunctionObject::create_environment()
 |     // FIXME: This should call NewFunctionEnvironment instead of the ad-hoc FunctionObject::create_environment()
 | ||||||
|  | @ -643,8 +653,7 @@ void VM::ordinary_call_bind_this(FunctionObject& function, ExecutionContext& cal | ||||||
|     if (function.is_strict_mode()) { |     if (function.is_strict_mode()) { | ||||||
|         this_value = this_argument; |         this_value = this_argument; | ||||||
|     } else if (this_argument.is_nullish()) { |     } else if (this_argument.is_nullish()) { | ||||||
|         // FIXME: Make function.realm() an actual Realm, then this will become less horrendous.
 |         auto& global_environment = callee_realm->global_environment(); | ||||||
|         auto& global_environment = interpreter().realm().global_environment(); |  | ||||||
|         this_value = &global_environment.global_this_value(); |         this_value = &global_environment.global_this_value(); | ||||||
|     } else { |     } else { | ||||||
|         this_value = this_argument.to_object(function.global_object()); |         this_value = this_argument.to_object(function.global_object()); | ||||||
|  | @ -668,6 +677,8 @@ Value VM::call_internal(FunctionObject& function, Value this_value, Optional<Mar | ||||||
|         return call_internal(bound_function.target_function(), bound_function.bound_this(), move(with_bound_arguments)); |         return call_internal(bound_function.target_function(), bound_function.bound_this(), move(with_bound_arguments)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     // FIXME: prepare_for_ordinary_call() is not supposed to receive a BoundFunction, ProxyObject, etc. - ever.
 | ||||||
|  |     //        This needs to be moved to NativeFunction/OrdinaryFunctionObject's construct() (10.2.2 [[Construct]])
 | ||||||
|     ExecutionContext callee_context(heap()); |     ExecutionContext callee_context(heap()); | ||||||
|     prepare_for_ordinary_call(function, callee_context, nullptr); |     prepare_for_ordinary_call(function, callee_context, nullptr); | ||||||
|     if (exception()) |     if (exception()) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Linus Groh
						Linus Groh