1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 18:07:34 +00:00

LibJS: Rename Environment Records so they match the spec :^)

This patch makes the following name changes:

- ScopeObject => EnvironmentRecord
- LexicalEnvironment => DeclarativeEnvironmentRecord
- WithScope => ObjectEnvironmentRecord
This commit is contained in:
Andreas Kling 2021-06-21 23:17:24 +02:00
parent e9b4a0a830
commit 6c6dbcfc36
35 changed files with 297 additions and 297 deletions

View file

@ -44,9 +44,9 @@ Value BoundFunction::construct(Function& new_target)
return m_target_function->construct(new_target);
}
LexicalEnvironment* BoundFunction::create_environment()
DeclarativeEnvironmentRecord* BoundFunction::create_environment_record()
{
return m_target_function->create_environment();
return m_target_function->create_environment_record();
}
void BoundFunction::visit_edges(Visitor& visitor)

View file

@ -22,7 +22,7 @@ public:
virtual Value construct(Function& new_target) override;
virtual LexicalEnvironment* create_environment() override;
virtual DeclarativeEnvironmentRecord* create_environment_record() override;
virtual void visit_edges(Visitor&) override;

View file

@ -1,47 +1,47 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Interpreter.h>
#include <LibJS/Runtime/DeclarativeEnvironmentRecord.h>
#include <LibJS/Runtime/Error.h>
#include <LibJS/Runtime/Function.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/LexicalEnvironment.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
LexicalEnvironment::LexicalEnvironment()
: ScopeObject(nullptr)
DeclarativeEnvironmentRecord::DeclarativeEnvironmentRecord()
: EnvironmentRecord(nullptr)
{
}
LexicalEnvironment::LexicalEnvironment(EnvironmentRecordType environment_record_type)
: ScopeObject(nullptr)
DeclarativeEnvironmentRecord::DeclarativeEnvironmentRecord(EnvironmentRecordType environment_record_type)
: EnvironmentRecord(nullptr)
, m_environment_record_type(environment_record_type)
{
}
LexicalEnvironment::LexicalEnvironment(HashMap<FlyString, Variable> variables, ScopeObject* parent_scope)
: ScopeObject(parent_scope)
DeclarativeEnvironmentRecord::DeclarativeEnvironmentRecord(HashMap<FlyString, Variable> variables, EnvironmentRecord* parent_scope)
: EnvironmentRecord(parent_scope)
, m_variables(move(variables))
{
}
LexicalEnvironment::LexicalEnvironment(HashMap<FlyString, Variable> variables, ScopeObject* parent_scope, EnvironmentRecordType environment_record_type)
: ScopeObject(parent_scope)
DeclarativeEnvironmentRecord::DeclarativeEnvironmentRecord(HashMap<FlyString, Variable> variables, EnvironmentRecord* parent_scope, EnvironmentRecordType environment_record_type)
: EnvironmentRecord(parent_scope)
, m_environment_record_type(environment_record_type)
, m_variables(move(variables))
{
}
LexicalEnvironment::~LexicalEnvironment()
DeclarativeEnvironmentRecord::~DeclarativeEnvironmentRecord()
{
}
void LexicalEnvironment::visit_edges(Visitor& visitor)
void DeclarativeEnvironmentRecord::visit_edges(Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_this_value);
@ -52,27 +52,27 @@ void LexicalEnvironment::visit_edges(Visitor& visitor)
visitor.visit(it.value.value);
}
Optional<Variable> LexicalEnvironment::get_from_scope(const FlyString& name) const
Optional<Variable> DeclarativeEnvironmentRecord::get_from_scope(const FlyString& name) const
{
return m_variables.get(name);
}
void LexicalEnvironment::put_to_scope(const FlyString& name, Variable variable)
void DeclarativeEnvironmentRecord::put_to_scope(const FlyString& name, Variable variable)
{
m_variables.set(name, variable);
}
bool LexicalEnvironment::delete_from_scope(FlyString const& name)
bool DeclarativeEnvironmentRecord::delete_from_scope(FlyString const& name)
{
return m_variables.remove(name);
}
bool LexicalEnvironment::has_super_binding() const
bool DeclarativeEnvironmentRecord::has_super_binding() const
{
return m_environment_record_type == EnvironmentRecordType::Function && this_binding_status() != ThisBindingStatus::Lexical && m_home_object.is_object();
}
Value LexicalEnvironment::get_super_base()
Value DeclarativeEnvironmentRecord::get_super_base()
{
VERIFY(has_super_binding());
if (m_home_object.is_object())
@ -80,7 +80,7 @@ Value LexicalEnvironment::get_super_base()
return {};
}
bool LexicalEnvironment::has_this_binding() const
bool DeclarativeEnvironmentRecord::has_this_binding() const
{
// More like "is_capable_of_having_a_this_binding".
switch (m_environment_record_type) {
@ -95,7 +95,7 @@ bool LexicalEnvironment::has_this_binding() const
VERIFY_NOT_REACHED();
}
Value LexicalEnvironment::get_this_binding(GlobalObject& global_object) const
Value DeclarativeEnvironmentRecord::get_this_binding(GlobalObject& global_object) const
{
VERIFY(has_this_binding());
if (this_binding_status() == ThisBindingStatus::Uninitialized) {
@ -105,7 +105,7 @@ Value LexicalEnvironment::get_this_binding(GlobalObject& global_object) const
return m_this_value;
}
void LexicalEnvironment::bind_this_value(GlobalObject& global_object, Value this_value)
void DeclarativeEnvironmentRecord::bind_this_value(GlobalObject& global_object, Value this_value)
{
VERIFY(has_this_binding());
if (m_this_binding_status == ThisBindingStatus::Initialized) {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -8,13 +8,13 @@
#include <AK/FlyString.h>
#include <AK/HashMap.h>
#include <LibJS/Runtime/ScopeObject.h>
#include <LibJS/Runtime/EnvironmentRecord.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
class LexicalEnvironment final : public ScopeObject {
JS_OBJECT(LexicalEnvironment, ScopeObject);
class DeclarativeEnvironmentRecord final : public EnvironmentRecord {
JS_OBJECT(DeclarativeEnvironmentRecord, EnvironmentRecord);
public:
enum class ThisBindingStatus {
@ -30,13 +30,13 @@ public:
Module,
};
LexicalEnvironment();
LexicalEnvironment(EnvironmentRecordType);
LexicalEnvironment(HashMap<FlyString, Variable> variables, ScopeObject* parent_scope);
LexicalEnvironment(HashMap<FlyString, Variable> variables, ScopeObject* parent_scope, EnvironmentRecordType);
virtual ~LexicalEnvironment() override;
DeclarativeEnvironmentRecord();
DeclarativeEnvironmentRecord(EnvironmentRecordType);
DeclarativeEnvironmentRecord(HashMap<FlyString, Variable> variables, EnvironmentRecord* parent_scope);
DeclarativeEnvironmentRecord(HashMap<FlyString, Variable> variables, EnvironmentRecord* parent_scope, EnvironmentRecordType);
virtual ~DeclarativeEnvironmentRecord() override;
// ^ScopeObject
// ^EnvironmentRecord
virtual Optional<Variable> get_from_scope(const FlyString&) const override;
virtual void put_to_scope(const FlyString&, Variable) override;
virtual bool delete_from_scope(FlyString const&) override;
@ -66,7 +66,7 @@ public:
EnvironmentRecordType type() const { return m_environment_record_type; }
private:
virtual bool is_lexical_environment() const override { return true; }
virtual bool is_declarative_environment_record() const override { return true; }
virtual void visit_edges(Visitor&) override;
EnvironmentRecordType m_environment_record_type : 8 { EnvironmentRecordType::Declarative };
@ -80,6 +80,6 @@ private:
};
template<>
inline bool Object::fast_is<LexicalEnvironment>() const { return is_lexical_environment(); }
inline bool Object::fast_is<DeclarativeEnvironmentRecord>() const { return is_declarative_environment_record(); }
}

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/EnvironmentRecord.h>
#include <LibJS/Runtime/VM.h>
namespace JS {
EnvironmentRecord::EnvironmentRecord(EnvironmentRecord* parent)
: Object(vm().environment_record_shape())
, m_parent(parent)
{
}
EnvironmentRecord::EnvironmentRecord(GlobalObjectTag tag)
: Object(tag)
{
}
void EnvironmentRecord::visit_edges(Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_parent);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -15,8 +15,8 @@ struct Variable {
DeclarationKind declaration_kind;
};
class ScopeObject : public Object {
JS_OBJECT(ScopeObject, Object);
class EnvironmentRecord : public Object {
JS_OBJECT(EnvironmentRecord, Object);
public:
virtual Optional<Variable> get_from_scope(const FlyString&) const = 0;
@ -25,17 +25,17 @@ public:
virtual bool has_this_binding() const = 0;
virtual Value get_this_binding(GlobalObject&) const = 0;
ScopeObject* parent() { return m_parent; }
const ScopeObject* parent() const { return m_parent; }
EnvironmentRecord* parent() { return m_parent; }
const EnvironmentRecord* parent() const { return m_parent; }
protected:
explicit ScopeObject(ScopeObject* parent);
explicit ScopeObject(GlobalObjectTag);
explicit EnvironmentRecord(EnvironmentRecord* parent);
explicit EnvironmentRecord(GlobalObjectTag);
virtual void visit_edges(Visitor&) override;
private:
ScopeObject* m_parent { nullptr };
EnvironmentRecord* m_parent { nullptr };
};
}

View file

@ -26,7 +26,7 @@ public:
virtual Value call() = 0;
virtual Value construct(Function& new_target) = 0;
virtual const FlyString& name() const = 0;
virtual LexicalEnvironment* create_environment() = 0;
virtual DeclarativeEnvironmentRecord* create_environment_record() = 0;
BoundFunction* bind(Value bound_this_value, Vector<Value> arguments);

View file

@ -13,7 +13,7 @@
namespace JS {
GeneratorObject* GeneratorObject::create(GlobalObject& global_object, Value initial_value, ScriptFunction* generating_function, ScopeObject* generating_scope, Bytecode::RegisterWindow frame)
GeneratorObject* GeneratorObject::create(GlobalObject& global_object, Value initial_value, ScriptFunction* generating_function, EnvironmentRecord* generating_scope, Bytecode::RegisterWindow frame)
{
// This is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png)
auto generating_function_proto_property = generating_function->get(global_object.vm().names.prototype).to_object(global_object);
@ -22,7 +22,7 @@ GeneratorObject* GeneratorObject::create(GlobalObject& global_object, Value init
auto object = global_object.heap().allocate<GeneratorObject>(global_object, global_object, *generating_function_proto_property);
object->m_generating_function = generating_function;
object->m_scope = generating_scope;
object->m_environment_record = generating_scope;
object->m_frame = move(frame);
object->m_previous_value = initial_value;
return object;
@ -44,7 +44,7 @@ GeneratorObject::~GeneratorObject()
void GeneratorObject::visit_edges(Cell::Visitor& visitor)
{
Object::visit_edges(visitor);
visitor.visit(m_scope);
visitor.visit(m_environment_record);
visitor.visit(m_generating_function);
if (m_previous_value.is_object())
visitor.visit(&m_previous_value.as_object());
@ -106,8 +106,8 @@ Value GeneratorObject::next_impl(VM& vm, GlobalObject& global_object, Optional<V
bytecode_interpreter->accumulator() = vm.argument(0);
}
// Temporarily switch to the captured scope
TemporaryChange change { vm.call_frame().scope, m_scope };
// Temporarily switch to the captured environment record
TemporaryChange change { vm.call_frame().environment_record, m_environment_record };
m_previous_value = bytecode_interpreter->run(*m_generating_function->bytecode_executable(), next_block);

View file

@ -15,7 +15,7 @@ class GeneratorObject final : public Object {
JS_OBJECT(GeneratorObject, Object);
public:
static GeneratorObject* create(GlobalObject&, Value, ScriptFunction*, ScopeObject*, Bytecode::RegisterWindow);
static GeneratorObject* create(GlobalObject&, Value, ScriptFunction*, EnvironmentRecord*, Bytecode::RegisterWindow);
GeneratorObject(GlobalObject&, Object& prototype);
virtual void initialize(GlobalObject&) override;
virtual ~GeneratorObject() override;
@ -25,7 +25,7 @@ public:
void set_done() { m_done = true; }
private:
ScopeObject* m_scope { nullptr };
EnvironmentRecord* m_environment_record { nullptr };
ScriptFunction* m_generating_function { nullptr };
Value m_previous_value;
Bytecode::RegisterWindow m_frame;

View file

@ -82,7 +82,7 @@
namespace JS {
GlobalObject::GlobalObject()
: ScopeObject(GlobalObjectTag::Tag)
: EnvironmentRecord(GlobalObjectTag::Tag)
, m_console(make<Console>(*this))
{
}
@ -372,7 +372,7 @@ JS_DEFINE_NATIVE_FUNCTION(GlobalObject::eval)
}
auto& caller_frame = vm.call_stack().at(vm.call_stack().size() - 2);
TemporaryChange scope_change(vm.call_frame().scope, caller_frame->scope);
TemporaryChange scope_change(vm.call_frame().environment_record, caller_frame->environment_record);
auto& interpreter = vm.interpreter();
return interpreter.execute_statement(global_object, program).value_or(js_undefined());

View file

@ -7,13 +7,13 @@
#pragma once
#include <LibJS/Heap/Heap.h>
#include <LibJS/Runtime/ScopeObject.h>
#include <LibJS/Runtime/EnvironmentRecord.h>
#include <LibJS/Runtime/VM.h>
namespace JS {
class GlobalObject : public ScopeObject {
JS_OBJECT(GlobalObject, ScopeObject);
class GlobalObject : public EnvironmentRecord {
JS_OBJECT(GlobalObject, EnvironmentRecord);
public:
explicit GlobalObject();

View file

@ -47,7 +47,7 @@ Value NativeFunction::construct(Function&)
return {};
}
LexicalEnvironment* NativeFunction::create_environment()
DeclarativeEnvironmentRecord* NativeFunction::create_environment_record()
{
return nullptr;
}

View file

@ -34,7 +34,7 @@ protected:
explicit NativeFunction(Object& prototype);
private:
virtual LexicalEnvironment* create_environment() override final;
virtual DeclarativeEnvironmentRecord* create_environment_record() override final;
virtual bool is_native_function() const final { return true; }
FlyString m_name;

View file

@ -108,7 +108,7 @@ public:
virtual bool is_global_object() const { return false; }
virtual bool is_proxy_object() const { return false; }
virtual bool is_native_function() const { return false; }
virtual bool is_lexical_environment() const { return false; }
virtual bool is_declarative_environment_record() const { return false; }
// B.3.7 The [[IsHTMLDDA]] Internal Slot, https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot
virtual bool is_htmldda() const { return false; }

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/AST.h>
#include <LibJS/Runtime/ObjectEnvironmentRecord.h>
namespace JS {
ObjectEnvironmentRecord::ObjectEnvironmentRecord(Object& object, EnvironmentRecord* parent_scope)
: EnvironmentRecord(parent_scope)
, m_object(object)
{
}
void ObjectEnvironmentRecord::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(&m_object);
}
Optional<Variable> ObjectEnvironmentRecord::get_from_scope(const FlyString& name) const
{
auto value = m_object.get(name);
if (value.is_empty())
return {};
return Variable { value, DeclarationKind::Var };
}
void ObjectEnvironmentRecord::put_to_scope(const FlyString& name, Variable variable)
{
m_object.put(name, variable.value);
}
bool ObjectEnvironmentRecord::delete_from_scope(FlyString const& name)
{
return m_object.delete_property(name);
}
bool ObjectEnvironmentRecord::has_this_binding() const
{
return parent()->has_this_binding();
}
Value ObjectEnvironmentRecord::get_this_binding(GlobalObject& global_object) const
{
return parent()->get_this_binding(global_object);
}
}

View file

@ -1,20 +1,20 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Runtime/ScopeObject.h>
#include <LibJS/Runtime/EnvironmentRecord.h>
namespace JS {
class WithScope : public ScopeObject {
JS_OBJECT(WithScope, ScopeObject);
class ObjectEnvironmentRecord : public EnvironmentRecord {
JS_OBJECT(ObjectEnvironmentRecord, EnvironmentRecord);
public:
WithScope(Object&, ScopeObject* parent_scope);
ObjectEnvironmentRecord(Object&, EnvironmentRecord* parent_scope);
virtual Optional<Variable> get_from_scope(const FlyString&) const override;
virtual void put_to_scope(const FlyString&, Variable) override;

View file

@ -478,10 +478,10 @@ const FlyString& ProxyObject::name() const
return static_cast<Function&>(m_target).name();
}
LexicalEnvironment* ProxyObject::create_environment()
DeclarativeEnvironmentRecord* ProxyObject::create_environment_record()
{
VERIFY(is_function());
return static_cast<Function&>(m_target).create_environment();
return static_cast<Function&>(m_target).create_environment_record();
}
}

View file

@ -22,7 +22,7 @@ public:
virtual Value call() override;
virtual Value construct(Function& new_target) override;
virtual const FlyString& name() const override;
virtual LexicalEnvironment* create_environment() override;
virtual DeclarativeEnvironmentRecord* create_environment_record() override;
const Object& target() const { return m_target; }
const Object& handler() const { return m_handler; }

View file

@ -1,29 +0,0 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/ScopeObject.h>
#include <LibJS/Runtime/VM.h>
namespace JS {
ScopeObject::ScopeObject(ScopeObject* parent)
: Object(vm().scope_object_shape())
, m_parent(parent)
{
}
ScopeObject::ScopeObject(GlobalObjectTag tag)
: Object(tag)
{
}
void ScopeObject::visit_edges(Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_parent);
}
}

View file

@ -35,7 +35,7 @@ static ScriptFunction* typed_this(VM& vm, GlobalObject& global_object)
return static_cast<ScriptFunction*>(this_object);
}
ScriptFunction* ScriptFunction::create(GlobalObject& global_object, const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, ScopeObject* parent_scope, FunctionKind kind, bool is_strict, bool is_arrow_function)
ScriptFunction* ScriptFunction::create(GlobalObject& global_object, const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, EnvironmentRecord* parent_scope, FunctionKind kind, bool is_strict, bool is_arrow_function)
{
Object* prototype = nullptr;
switch (kind) {
@ -49,7 +49,7 @@ ScriptFunction* ScriptFunction::create(GlobalObject& global_object, const FlyStr
return global_object.heap().allocate<ScriptFunction>(global_object, global_object, name, body, move(parameters), m_function_length, parent_scope, *prototype, kind, is_strict, is_arrow_function);
}
ScriptFunction::ScriptFunction(GlobalObject& global_object, const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, ScopeObject* parent_scope, Object& prototype, FunctionKind kind, bool is_strict, bool is_arrow_function)
ScriptFunction::ScriptFunction(GlobalObject& global_object, const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, EnvironmentRecord* parent_scope, Object& prototype, FunctionKind kind, bool is_strict, bool is_arrow_function)
: Function(is_arrow_function ? vm().this_value(global_object) : Value(), {}, prototype)
, m_name(name)
, m_body(body)
@ -93,7 +93,7 @@ void ScriptFunction::visit_edges(Visitor& visitor)
visitor.visit(m_parent_scope);
}
LexicalEnvironment* ScriptFunction::create_environment()
DeclarativeEnvironmentRecord* ScriptFunction::create_environment_record()
{
HashMap<FlyString, Variable> variables;
for (auto& parameter : m_parameters) {
@ -122,12 +122,12 @@ LexicalEnvironment* ScriptFunction::create_environment()
}
}
auto* environment = heap().allocate<LexicalEnvironment>(global_object(), move(variables), m_parent_scope, LexicalEnvironment::EnvironmentRecordType::Function);
auto* environment = heap().allocate<DeclarativeEnvironmentRecord>(global_object(), move(variables), m_parent_scope, DeclarativeEnvironmentRecord::EnvironmentRecordType::Function);
environment->set_home_object(home_object());
environment->set_current_function(*this);
if (m_is_arrow_function) {
if (is<LexicalEnvironment>(m_parent_scope))
environment->set_new_target(static_cast<LexicalEnvironment*>(m_parent_scope)->new_target());
if (is<DeclarativeEnvironmentRecord>(m_parent_scope))
environment->set_new_target(static_cast<DeclarativeEnvironmentRecord*>(m_parent_scope)->new_target());
}
return environment;
}
@ -191,7 +191,7 @@ Value ScriptFunction::execute_function_body()
if (m_kind != FunctionKind::Generator)
return result;
return GeneratorObject::create(global_object(), result, this, vm.call_frame().scope, bytecode_interpreter->snapshot_frame());
return GeneratorObject::create(global_object(), result, this, vm.call_frame().environment_record, bytecode_interpreter->snapshot_frame());
} else {
VERIFY(m_kind != FunctionKind::Generator);
OwnPtr<Interpreter> local_interpreter;

View file

@ -16,9 +16,9 @@ class ScriptFunction final : public Function {
JS_OBJECT(ScriptFunction, Function);
public:
static ScriptFunction* create(GlobalObject&, const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, ScopeObject* parent_scope, FunctionKind, bool is_strict, bool is_arrow_function = false);
static ScriptFunction* create(GlobalObject&, const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, EnvironmentRecord* parent_scope, FunctionKind, bool is_strict, bool is_arrow_function = false);
ScriptFunction(GlobalObject&, const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, ScopeObject* parent_scope, Object& prototype, FunctionKind, bool is_strict, bool is_arrow_function = false);
ScriptFunction(GlobalObject&, const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, EnvironmentRecord* parent_scope, Object& prototype, FunctionKind, bool is_strict, bool is_arrow_function = false);
virtual void initialize(GlobalObject&) override;
virtual ~ScriptFunction();
@ -39,7 +39,7 @@ protected:
virtual bool is_strict_mode() const final { return m_is_strict; }
private:
virtual LexicalEnvironment* create_environment() override;
virtual DeclarativeEnvironmentRecord* create_environment_record() override;
virtual void visit_edges(Visitor&) override;
Value execute_function_body();
@ -51,7 +51,7 @@ private:
NonnullRefPtr<Statement> m_body;
const Vector<FunctionNode::Parameter> m_parameters;
Optional<Bytecode::Executable> m_bytecode_executable;
ScopeObject* m_parent_scope { nullptr };
EnvironmentRecord* m_parent_scope { nullptr };
i32 m_function_length { 0 };
FunctionKind m_kind { FunctionKind::Regular };
bool m_is_strict { false };

View file

@ -37,7 +37,7 @@ VM::VM()
m_single_ascii_character_strings[i] = m_heap.allocate_without_global_object<PrimitiveString>(String::formatted("{:c}", i));
}
m_scope_object_shape = m_heap.allocate_without_global_object<Shape>(Shape::ShapeWithoutGlobalObjectTag::Tag);
m_environment_record_shape = m_heap.allocate_without_global_object<Shape>(Shape::ShapeWithoutGlobalObjectTag::Tag);
#define __JS_ENUMERATE(SymbolName, snake_name) \
m_well_known_symbol_##snake_name = js_symbol(*this, "Symbol." #SymbolName, false);
@ -91,7 +91,7 @@ void VM::gather_roots(HashTable<Cell*>& roots)
for (auto* string : m_single_ascii_character_strings)
roots.set(string);
roots.set(m_scope_object_shape);
roots.set(m_environment_record_shape);
roots.set(m_exception);
if (m_last_value.is_cell())
@ -105,7 +105,7 @@ void VM::gather_roots(HashTable<Cell*>& roots)
if (argument.is_cell())
roots.set(&argument.as_cell());
}
roots.set(call_frame->scope);
roots.set(call_frame->environment_record);
}
#define __JS_ENUMERATE(SymbolName, snake_name) \
@ -131,7 +131,7 @@ Symbol* VM::get_global_symbol(const String& description)
return new_global_symbol;
}
void VM::set_variable(const FlyString& name, Value value, GlobalObject& global_object, bool first_assignment, ScopeObject* specific_scope)
void VM::set_variable(const FlyString& name, Value value, GlobalObject& global_object, bool first_assignment, EnvironmentRecord* specific_scope)
{
Optional<Variable> possible_match;
if (!specific_scope && m_call_stack.size()) {
@ -164,7 +164,7 @@ void VM::set_variable(const FlyString& name, Value value, GlobalObject& global_o
bool VM::delete_variable(FlyString const& name)
{
ScopeObject* specific_scope = nullptr;
EnvironmentRecord* specific_scope = nullptr;
Optional<Variable> possible_match;
if (!m_call_stack.is_empty()) {
for (auto* scope = current_scope(); scope; scope = scope->parent()) {
@ -185,12 +185,12 @@ bool VM::delete_variable(FlyString const& name)
return specific_scope->delete_from_scope(name);
}
void VM::assign(const FlyString& target, Value value, GlobalObject& global_object, bool first_assignment, ScopeObject* specific_scope)
void VM::assign(const FlyString& target, Value value, GlobalObject& global_object, bool first_assignment, EnvironmentRecord* specific_scope)
{
set_variable(target, move(value), global_object, first_assignment, specific_scope);
}
void VM::assign(const Variant<NonnullRefPtr<Identifier>, NonnullRefPtr<BindingPattern>>& target, Value value, GlobalObject& global_object, bool first_assignment, ScopeObject* specific_scope)
void VM::assign(const Variant<NonnullRefPtr<Identifier>, NonnullRefPtr<BindingPattern>>& target, Value value, GlobalObject& global_object, bool first_assignment, EnvironmentRecord* specific_scope)
{
if (auto id_ptr = target.get_pointer<NonnullRefPtr<Identifier>>())
return assign((*id_ptr)->string(), move(value), global_object, first_assignment, specific_scope);
@ -198,7 +198,7 @@ void VM::assign(const Variant<NonnullRefPtr<Identifier>, NonnullRefPtr<BindingPa
assign(target.get<NonnullRefPtr<BindingPattern>>(), move(value), global_object, first_assignment, specific_scope);
}
void VM::assign(const NonnullRefPtr<BindingPattern>& target, Value value, GlobalObject& global_object, bool first_assignment, ScopeObject* specific_scope)
void VM::assign(const NonnullRefPtr<BindingPattern>& target, Value value, GlobalObject& global_object, bool first_assignment, EnvironmentRecord* specific_scope)
{
auto& binding = *target;
@ -424,8 +424,8 @@ Value VM::construct(Function& function, Function& new_target, Optional<MarkedVal
call_frame.arguments = function.bound_arguments();
if (arguments.has_value())
call_frame.arguments.extend(arguments.value().values());
auto* environment = function.create_environment();
call_frame.scope = environment;
auto* environment = function.create_environment_record();
call_frame.environment_record = environment;
if (environment)
environment->set_new_target(&new_target);
@ -460,8 +460,8 @@ Value VM::construct(Function& function, Function& new_target, Optional<MarkedVal
// set the prototype on objects created by constructors that return an object (i.e. NativeFunction subclasses).
if (function.constructor_kind() == Function::ConstructorKind::Base && new_target.constructor_kind() == Function::ConstructorKind::Derived && result.is_object()) {
if (environment) {
VERIFY(is<LexicalEnvironment>(current_scope()));
static_cast<LexicalEnvironment*>(current_scope())->replace_this_binding(result);
VERIFY(is<DeclarativeEnvironmentRecord>(current_scope()));
static_cast<DeclarativeEnvironmentRecord*>(current_scope())->replace_this_binding(result);
}
auto prototype = new_target.get(names.prototype);
if (exception())
@ -505,7 +505,7 @@ Value VM::resolve_this_binding(GlobalObject& global_object) const
return find_this_scope()->get_this_binding(global_object);
}
const ScopeObject* VM::find_this_scope() const
const EnvironmentRecord* VM::find_this_scope() const
{
// We will always return because the Global environment will always be reached, which has a |this| binding.
for (auto* scope = current_scope(); scope; scope = scope->parent()) {
@ -517,8 +517,8 @@ const ScopeObject* VM::find_this_scope() const
Value VM::get_new_target() const
{
VERIFY(is<LexicalEnvironment>(find_this_scope()));
return static_cast<const LexicalEnvironment*>(find_this_scope())->new_target();
VERIFY(is<DeclarativeEnvironmentRecord>(find_this_scope()));
return static_cast<const DeclarativeEnvironmentRecord*>(find_this_scope())->new_target();
}
Value VM::call_internal(Function& function, Value this_value, Optional<MarkedValueList> arguments)
@ -536,11 +536,11 @@ Value VM::call_internal(Function& function, Value this_value, Optional<MarkedVal
call_frame.arguments = function.bound_arguments();
if (arguments.has_value())
call_frame.arguments.extend(arguments.value().values());
auto* environment = function.create_environment();
call_frame.scope = environment;
auto* environment = function.create_environment_record();
call_frame.environment_record = environment;
if (environment) {
VERIFY(environment->this_binding_status() == LexicalEnvironment::ThisBindingStatus::Uninitialized);
VERIFY(environment->this_binding_status() == DeclarativeEnvironmentRecord::ThisBindingStatus::Uninitialized);
environment->bind_this_value(function.global_object(), call_frame.this_value);
}
@ -626,9 +626,9 @@ void VM::dump_scope_chain() const
{
for (auto* scope = current_scope(); scope; scope = scope->parent()) {
dbgln("+> {} ({:p})", scope->class_name(), scope);
if (is<LexicalEnvironment>(*scope)) {
auto& lexical_environment = static_cast<LexicalEnvironment const&>(*scope);
for (auto& variable : lexical_environment.variables()) {
if (is<DeclarativeEnvironmentRecord>(*scope)) {
auto& environment_record = static_cast<DeclarativeEnvironmentRecord const&>(*scope);
for (auto& variable : environment_record.variables()) {
dbgln(" {}", variable.key);
}
}

View file

@ -49,7 +49,7 @@ struct CallFrame {
Value this_value;
Vector<Value> arguments;
Array* arguments_object { nullptr };
ScopeObject* scope { nullptr };
EnvironmentRecord* environment_record { nullptr };
bool is_strict_mode { false };
};
@ -122,8 +122,8 @@ public:
const Vector<CallFrame*>& call_stack() const { return m_call_stack; }
Vector<CallFrame*>& call_stack() { return m_call_stack; }
const ScopeObject* current_scope() const { return call_frame().scope; }
ScopeObject* current_scope() { return call_frame().scope; }
const EnvironmentRecord* current_scope() const { return call_frame().environment_record; }
EnvironmentRecord* current_scope() { return call_frame().environment_record; }
bool in_strict_mode() const;
@ -192,11 +192,11 @@ public:
FlyString unwind_until_label() const { return m_unwind_until_label; }
Value get_variable(const FlyString& name, GlobalObject&);
void set_variable(const FlyString& name, Value, GlobalObject&, bool first_assignment = false, ScopeObject* specific_scope = nullptr);
void set_variable(const FlyString& name, Value, GlobalObject&, bool first_assignment = false, EnvironmentRecord* specific_scope = nullptr);
bool delete_variable(FlyString const& name);
void assign(const Variant<NonnullRefPtr<Identifier>, NonnullRefPtr<BindingPattern>>& target, Value, GlobalObject&, bool first_assignment = false, ScopeObject* specific_scope = nullptr);
void assign(const FlyString& target, Value, GlobalObject&, bool first_assignment = false, ScopeObject* specific_scope = nullptr);
void assign(const NonnullRefPtr<BindingPattern>& target, Value, GlobalObject&, bool first_assignment = false, ScopeObject* specific_scope = nullptr);
void assign(const Variant<NonnullRefPtr<Identifier>, NonnullRefPtr<BindingPattern>>& target, Value, GlobalObject&, bool first_assignment = false, EnvironmentRecord* specific_scope = nullptr);
void assign(const FlyString& target, Value, GlobalObject&, bool first_assignment = false, EnvironmentRecord* specific_scope = nullptr);
void assign(const NonnullRefPtr<BindingPattern>& target, Value, GlobalObject&, bool first_assignment = false, EnvironmentRecord* specific_scope = nullptr);
Reference get_reference(const FlyString& name);
@ -223,7 +223,7 @@ public:
String join_arguments(size_t start_index = 0) const;
Value resolve_this_binding(GlobalObject&) const;
const ScopeObject* find_this_scope() const;
const EnvironmentRecord* find_this_scope() const;
Value get_new_target() const;
template<typename... Args>
@ -240,7 +240,7 @@ public:
CommonPropertyNames names;
Shape& scope_object_shape() { return *m_scope_object_shape; }
Shape& environment_record_shape() { return *m_environment_record_shape; }
void run_queued_promise_jobs();
void enqueue_promise_job(NativeFunction&);
@ -286,7 +286,7 @@ private:
JS_ENUMERATE_WELL_KNOWN_SYMBOLS
#undef __JS_ENUMERATE
Shape* m_scope_object_shape { nullptr };
Shape* m_environment_record_shape { nullptr };
bool m_underscore_is_last_value { false };

View file

@ -1,52 +0,0 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/AST.h>
#include <LibJS/Runtime/WithScope.h>
namespace JS {
WithScope::WithScope(Object& object, ScopeObject* parent_scope)
: ScopeObject(parent_scope)
, m_object(object)
{
}
void WithScope::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(&m_object);
}
Optional<Variable> WithScope::get_from_scope(const FlyString& name) const
{
auto value = m_object.get(name);
if (value.is_empty())
return {};
return Variable { value, DeclarationKind::Var };
}
void WithScope::put_to_scope(const FlyString& name, Variable variable)
{
m_object.put(name, variable.value);
}
bool WithScope::delete_from_scope(FlyString const& name)
{
return m_object.delete_property(name);
}
bool WithScope::has_this_binding() const
{
return parent()->has_this_binding();
}
Value WithScope::get_this_binding(GlobalObject& global_object) const
{
return parent()->get_this_binding(global_object);
}
}