mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 21:52:45 +00:00 
			
		
		
		
	 fe9dc47320
			
		
	
	
		fe9dc47320
		
	
	
	
	
		
			
			As the name implies (and the spec confirms), this is only ever going to be an object or "nothing", or "undefined" in the spec. By taking this literally and updating a check to check for `is_undefined()`, we introduced a bug - the value was still initialized as an empty value. Instead, use a pointer to an Object - either we have one, or we don't. Fixes #8448.
		
			
				
	
	
		
			83 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			83 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #include <LibJS/Interpreter.h>
 | |
| #include <LibJS/Runtime/FunctionEnvironment.h>
 | |
| #include <LibJS/Runtime/FunctionObject.h>
 | |
| #include <LibJS/Runtime/GlobalObject.h>
 | |
| 
 | |
| namespace JS {
 | |
| 
 | |
| FunctionEnvironment::FunctionEnvironment(Environment* parent_scope, HashMap<FlyString, Variable> variables)
 | |
|     : DeclarativeEnvironment(variables, parent_scope)
 | |
| {
 | |
| }
 | |
| 
 | |
| FunctionEnvironment::~FunctionEnvironment()
 | |
| {
 | |
| }
 | |
| 
 | |
| void FunctionEnvironment::visit_edges(Visitor& visitor)
 | |
| {
 | |
|     Base::visit_edges(visitor);
 | |
|     visitor.visit(m_this_value);
 | |
|     visitor.visit(m_new_target);
 | |
|     visitor.visit(m_function_object);
 | |
| }
 | |
| 
 | |
| // 9.1.1.3.5 GetSuperBase ( ), https://tc39.es/ecma262/#sec-getsuperbase
 | |
| Value FunctionEnvironment::get_super_base() const
 | |
| {
 | |
|     VERIFY(m_function_object);
 | |
|     auto home_object = m_function_object->home_object();
 | |
|     if (!home_object)
 | |
|         return js_undefined();
 | |
|     return home_object->internal_get_prototype_of();
 | |
| }
 | |
| 
 | |
| // 9.1.1.3.2 HasThisBinding ( ), https://tc39.es/ecma262/#sec-function-environment-records-hasthisbinding
 | |
| bool FunctionEnvironment::has_this_binding() const
 | |
| {
 | |
|     if (this_binding_status() == ThisBindingStatus::Lexical)
 | |
|         return false;
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| // 9.1.1.3.3 HasSuperBinding ( ), https://tc39.es/ecma262/#sec-function-environment-records-hassuperbinding
 | |
| bool FunctionEnvironment::has_super_binding() const
 | |
| {
 | |
|     if (this_binding_status() == ThisBindingStatus::Lexical)
 | |
|         return false;
 | |
|     if (!function_object().home_object())
 | |
|         return false;
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| // 9.1.1.3.4 GetThisBinding ( ), https://tc39.es/ecma262/#sec-function-environment-records-getthisbinding
 | |
| Value FunctionEnvironment::get_this_binding(GlobalObject& global_object) const
 | |
| {
 | |
|     VERIFY(has_this_binding());
 | |
|     if (this_binding_status() == ThisBindingStatus::Uninitialized) {
 | |
|         vm().throw_exception<ReferenceError>(global_object, ErrorType::ThisHasNotBeenInitialized);
 | |
|         return {};
 | |
|     }
 | |
|     return m_this_value;
 | |
| }
 | |
| 
 | |
| // 9.1.1.3.1 BindThisValue ( V ), https://tc39.es/ecma262/#sec-bindthisvalue
 | |
| Value FunctionEnvironment::bind_this_value(GlobalObject& global_object, Value this_value)
 | |
| {
 | |
|     VERIFY(this_binding_status() != ThisBindingStatus::Lexical);
 | |
|     if (this_binding_status() == ThisBindingStatus::Initialized) {
 | |
|         vm().throw_exception<ReferenceError>(global_object, ErrorType::ThisIsAlreadyInitialized);
 | |
|         return {};
 | |
|     }
 | |
|     m_this_value = this_value;
 | |
|     m_this_binding_status = ThisBindingStatus::Initialized;
 | |
|     return this_value;
 | |
| }
 | |
| 
 | |
| }
 |