1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 04:08:11 +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

@ -22,12 +22,12 @@
#include <LibJS/Runtime/IteratorOperations.h> #include <LibJS/Runtime/IteratorOperations.h>
#include <LibJS/Runtime/MarkedValueList.h> #include <LibJS/Runtime/MarkedValueList.h>
#include <LibJS/Runtime/NativeFunction.h> #include <LibJS/Runtime/NativeFunction.h>
#include <LibJS/Runtime/ObjectEnvironmentRecord.h>
#include <LibJS/Runtime/PrimitiveString.h> #include <LibJS/Runtime/PrimitiveString.h>
#include <LibJS/Runtime/Reference.h> #include <LibJS/Runtime/Reference.h>
#include <LibJS/Runtime/RegExpObject.h> #include <LibJS/Runtime/RegExpObject.h>
#include <LibJS/Runtime/ScriptFunction.h> #include <LibJS/Runtime/ScriptFunction.h>
#include <LibJS/Runtime/Shape.h> #include <LibJS/Runtime/Shape.h>
#include <LibJS/Runtime/WithScope.h>
#include <typeinfo> #include <typeinfo>
namespace JS { namespace JS {
@ -227,11 +227,11 @@ Value CallExpression::execute(Interpreter& interpreter, GlobalObject& global_obj
new_object = &result.as_object(); new_object = &result.as_object();
} else if (is<SuperExpression>(*m_callee)) { } else if (is<SuperExpression>(*m_callee)) {
// FIXME: This is merely a band-aid to make super() inside catch {} work (which constructs // FIXME: This is merely a band-aid to make super() inside catch {} work (which constructs
// a new LexicalEnvironment without current function). Implement GetSuperConstructor() // a new DeclarativeEnvironmentRecord without current function). Implement GetSuperConstructor()
// and subsequently GetThisEnvironment() instead. // and subsequently GetThisEnvironment() instead.
auto* function_environment = interpreter.current_environment(); auto* function_environment = interpreter.current_environment();
if (!function_environment->current_function()) if (!function_environment->current_function())
function_environment = static_cast<LexicalEnvironment*>(function_environment->parent()); function_environment = static_cast<DeclarativeEnvironmentRecord*>(function_environment->parent());
auto* super_constructor = function_environment->current_function()->prototype(); auto* super_constructor = function_environment->current_function()->prototype();
// FIXME: Functions should track their constructor kind. // FIXME: Functions should track their constructor kind.
@ -306,8 +306,8 @@ Value WithStatement::execute(Interpreter& interpreter, GlobalObject& global_obje
VERIFY(object); VERIFY(object);
auto* with_scope = interpreter.heap().allocate<WithScope>(global_object, *object, interpreter.vm().call_frame().scope); auto* object_environment_record = interpreter.heap().allocate<ObjectEnvironmentRecord>(global_object, *object, interpreter.vm().call_frame().environment_record);
TemporaryChange<ScopeObject*> scope_change(interpreter.vm().call_frame().scope, with_scope); TemporaryChange<EnvironmentRecord*> scope_change(interpreter.vm().call_frame().environment_record, object_environment_record);
return interpreter.execute_statement(global_object, m_body).value_or(js_undefined()); return interpreter.execute_statement(global_object, m_body).value_or(js_undefined());
} }
@ -2055,8 +2055,8 @@ Value TryStatement::execute(Interpreter& interpreter, GlobalObject& global_objec
HashMap<FlyString, Variable> parameters; HashMap<FlyString, Variable> parameters;
parameters.set(m_handler->parameter(), Variable { exception->value(), DeclarationKind::Var }); parameters.set(m_handler->parameter(), Variable { exception->value(), DeclarationKind::Var });
auto* catch_scope = interpreter.heap().allocate<LexicalEnvironment>(global_object, move(parameters), interpreter.vm().call_frame().scope); auto* catch_scope = interpreter.heap().allocate<DeclarativeEnvironmentRecord>(global_object, move(parameters), interpreter.vm().call_frame().environment_record);
TemporaryChange<ScopeObject*> scope_change(interpreter.vm().call_frame().scope, catch_scope); TemporaryChange<EnvironmentRecord*> scope_change(interpreter.vm().call_frame().environment_record, catch_scope);
result = interpreter.execute_statement(global_object, m_handler->body()); result = interpreter.execute_statement(global_object, m_handler->body());
} }
} }

View file

@ -14,7 +14,7 @@
#include <LibJS/Bytecode/Op.h> #include <LibJS/Bytecode/Op.h>
#include <LibJS/Bytecode/Register.h> #include <LibJS/Bytecode/Register.h>
#include <LibJS/Bytecode/StringTable.h> #include <LibJS/Bytecode/StringTable.h>
#include <LibJS/Runtime/ScopeObject.h> #include <LibJS/Runtime/EnvironmentRecord.h>
namespace JS { namespace JS {
@ -63,7 +63,7 @@ void ScopeNode::generate_bytecode(Bytecode::Generator& generator) const
} }
if (!scope_variables_with_declaration_kind.is_empty()) { if (!scope_variables_with_declaration_kind.is_empty()) {
generator.emit<Bytecode::Op::PushLexicalEnvironment>(move(scope_variables_with_declaration_kind)); generator.emit<Bytecode::Op::PushDeclarativeEnvironmentRecord>(move(scope_variables_with_declaration_kind));
} }
for (auto& child : children()) { for (auto& child : children()) {
@ -1219,7 +1219,7 @@ void TryStatement::generate_bytecode(Bytecode::Generator& generator) const
if (!m_finalizer) if (!m_finalizer)
generator.emit<Bytecode::Op::LeaveUnwindContext>(); generator.emit<Bytecode::Op::LeaveUnwindContext>();
if (!m_handler->parameter().is_empty()) { if (!m_handler->parameter().is_empty()) {
// FIXME: We need a separate LexicalEnvironment here // FIXME: We need a separate DeclarativeEnvironmentRecord here
generator.emit<Bytecode::Op::SetVariable>(generator.intern_string(m_handler->parameter())); generator.emit<Bytecode::Op::SetVariable>(generator.intern_string(m_handler->parameter()));
} }
m_handler->body().generate_bytecode(generator); m_handler->body().generate_bytecode(generator);

View file

@ -9,70 +9,70 @@
#include <AK/Forward.h> #include <AK/Forward.h>
#include <LibJS/Forward.h> #include <LibJS/Forward.h>
#define ENUMERATE_BYTECODE_OPS(O) \ #define ENUMERATE_BYTECODE_OPS(O) \
O(Load) \ O(Load) \
O(LoadImmediate) \ O(LoadImmediate) \
O(Store) \ O(Store) \
O(Add) \ O(Add) \
O(Sub) \ O(Sub) \
O(Mul) \ O(Mul) \
O(Div) \ O(Div) \
O(Mod) \ O(Mod) \
O(Exp) \ O(Exp) \
O(GreaterThan) \ O(GreaterThan) \
O(GreaterThanEquals) \ O(GreaterThanEquals) \
O(LessThan) \ O(LessThan) \
O(LessThanEquals) \ O(LessThanEquals) \
O(AbstractInequals) \ O(AbstractInequals) \
O(AbstractEquals) \ O(AbstractEquals) \
O(TypedInequals) \ O(TypedInequals) \
O(TypedEquals) \ O(TypedEquals) \
O(NewBigInt) \ O(NewBigInt) \
O(NewArray) \ O(NewArray) \
O(IteratorToArray) \ O(IteratorToArray) \
O(NewString) \ O(NewString) \
O(NewObject) \ O(NewObject) \
O(NewRegExp) \ O(NewRegExp) \
O(CopyObjectExcludingProperties) \ O(CopyObjectExcludingProperties) \
O(GetVariable) \ O(GetVariable) \
O(SetVariable) \ O(SetVariable) \
O(PutById) \ O(PutById) \
O(GetById) \ O(GetById) \
O(PutByValue) \ O(PutByValue) \
O(GetByValue) \ O(GetByValue) \
O(Jump) \ O(Jump) \
O(JumpConditional) \ O(JumpConditional) \
O(JumpNullish) \ O(JumpNullish) \
O(JumpUndefined) \ O(JumpUndefined) \
O(Call) \ O(Call) \
O(NewFunction) \ O(NewFunction) \
O(Return) \ O(Return) \
O(BitwiseAnd) \ O(BitwiseAnd) \
O(BitwiseOr) \ O(BitwiseOr) \
O(BitwiseXor) \ O(BitwiseXor) \
O(BitwiseNot) \ O(BitwiseNot) \
O(Not) \ O(Not) \
O(UnaryPlus) \ O(UnaryPlus) \
O(UnaryMinus) \ O(UnaryMinus) \
O(Typeof) \ O(Typeof) \
O(LeftShift) \ O(LeftShift) \
O(RightShift) \ O(RightShift) \
O(UnsignedRightShift) \ O(UnsignedRightShift) \
O(In) \ O(In) \
O(InstanceOf) \ O(InstanceOf) \
O(ConcatString) \ O(ConcatString) \
O(Increment) \ O(Increment) \
O(Decrement) \ O(Decrement) \
O(Throw) \ O(Throw) \
O(PushLexicalEnvironment) \ O(PushDeclarativeEnvironmentRecord) \
O(LoadArgument) \ O(LoadArgument) \
O(EnterUnwindContext) \ O(EnterUnwindContext) \
O(LeaveUnwindContext) \ O(LeaveUnwindContext) \
O(ContinuePendingUnwind) \ O(ContinuePendingUnwind) \
O(Yield) \ O(Yield) \
O(GetIterator) \ O(GetIterator) \
O(IteratorNext) \ O(IteratorNext) \
O(IteratorResultDone) \ O(IteratorResultDone) \
O(IteratorResultValue) O(IteratorResultValue)
namespace JS::Bytecode { namespace JS::Bytecode {

View file

@ -48,7 +48,7 @@ Value Interpreter::run(Executable const& executable, BasicBlock const* entry_poi
global_call_frame.this_value = &global_object(); global_call_frame.this_value = &global_object();
static FlyString global_execution_context_name = "(*BC* global execution context)"; static FlyString global_execution_context_name = "(*BC* global execution context)";
global_call_frame.function_name = global_execution_context_name; global_call_frame.function_name = global_execution_context_name;
global_call_frame.scope = &global_object(); global_call_frame.environment_record = &global_object();
VERIFY(!vm().exception()); VERIFY(!vm().exception());
// FIXME: How do we know if we're in strict mode? Maybe the Bytecode::Block should know this? // FIXME: How do we know if we're in strict mode? Maybe the Bytecode::Block should know this?
// global_call_frame.is_strict_mode = ???; // global_call_frame.is_strict_mode = ???;

View file

@ -12,11 +12,11 @@
#include <LibJS/Bytecode/Op.h> #include <LibJS/Bytecode/Op.h>
#include <LibJS/Runtime/Array.h> #include <LibJS/Runtime/Array.h>
#include <LibJS/Runtime/BigInt.h> #include <LibJS/Runtime/BigInt.h>
#include <LibJS/Runtime/DeclarativeEnvironmentRecord.h>
#include <LibJS/Runtime/EnvironmentRecord.h>
#include <LibJS/Runtime/GlobalObject.h> #include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/IteratorOperations.h> #include <LibJS/Runtime/IteratorOperations.h>
#include <LibJS/Runtime/LexicalEnvironment.h>
#include <LibJS/Runtime/RegExpObject.h> #include <LibJS/Runtime/RegExpObject.h>
#include <LibJS/Runtime/ScopeObject.h>
#include <LibJS/Runtime/ScriptFunction.h> #include <LibJS/Runtime/ScriptFunction.h>
#include <LibJS/Runtime/Value.h> #include <LibJS/Runtime/Value.h>
@ -381,13 +381,13 @@ void ContinuePendingUnwind::replace_references_impl(BasicBlock const& from, Basi
m_resume_target = Label { to }; m_resume_target = Label { to };
} }
void PushLexicalEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const void PushDeclarativeEnvironmentRecord::execute_impl(Bytecode::Interpreter& interpreter) const
{ {
HashMap<FlyString, Variable> resolved_variables; HashMap<FlyString, Variable> resolved_variables;
for (auto& it : m_variables) for (auto& it : m_variables)
resolved_variables.set(interpreter.current_executable().get_string(it.key), it.value); resolved_variables.set(interpreter.current_executable().get_string(it.key), it.value);
auto* block_lexical_environment = interpreter.vm().heap().allocate<LexicalEnvironment>(interpreter.global_object(), move(resolved_variables), interpreter.vm().current_scope()); auto* environment_record = interpreter.vm().heap().allocate<DeclarativeEnvironmentRecord>(interpreter.global_object(), move(resolved_variables), interpreter.vm().current_scope());
interpreter.vm().call_frame().scope = block_lexical_environment; interpreter.vm().call_frame().environment_record = environment_record;
} }
void Yield::execute_impl(Bytecode::Interpreter& interpreter) const void Yield::execute_impl(Bytecode::Interpreter& interpreter) const
@ -639,10 +639,10 @@ String ContinuePendingUnwind::to_string_impl(Bytecode::Executable const&) const
return String::formatted("ContinuePendingUnwind resume:{}", m_resume_target); return String::formatted("ContinuePendingUnwind resume:{}", m_resume_target);
} }
String PushLexicalEnvironment::to_string_impl(const Bytecode::Executable& executable) const String PushDeclarativeEnvironmentRecord::to_string_impl(const Bytecode::Executable& executable) const
{ {
StringBuilder builder; StringBuilder builder;
builder.append("PushLexicalEnvironment"); builder.append("PushDeclarativeEnvironmentRecord");
if (!m_variables.is_empty()) { if (!m_variables.is_empty()) {
builder.append(" {"); builder.append(" {");
Vector<String> names; Vector<String> names;

View file

@ -14,7 +14,7 @@
#include <LibJS/Bytecode/Register.h> #include <LibJS/Bytecode/Register.h>
#include <LibJS/Bytecode/StringTable.h> #include <LibJS/Bytecode/StringTable.h>
#include <LibJS/Heap/Cell.h> #include <LibJS/Heap/Cell.h>
#include <LibJS/Runtime/ScopeObject.h> #include <LibJS/Runtime/EnvironmentRecord.h>
#include <LibJS/Runtime/Value.h> #include <LibJS/Runtime/Value.h>
namespace JS::Bytecode::Op { namespace JS::Bytecode::Op {
@ -635,10 +635,10 @@ private:
Optional<Label> m_continuation_label; Optional<Label> m_continuation_label;
}; };
class PushLexicalEnvironment final : public Instruction { class PushDeclarativeEnvironmentRecord final : public Instruction {
public: public:
explicit PushLexicalEnvironment(HashMap<u32, Variable> variables) explicit PushDeclarativeEnvironmentRecord(HashMap<u32, Variable> variables)
: Instruction(Type::PushLexicalEnvironment) : Instruction(Type::PushDeclarativeEnvironmentRecord)
, m_variables(move(variables)) , m_variables(move(variables))
{ {
} }

View file

@ -49,6 +49,8 @@ set(SOURCES
Runtime/DateConstructor.cpp Runtime/DateConstructor.cpp
Runtime/Date.cpp Runtime/Date.cpp
Runtime/DatePrototype.cpp Runtime/DatePrototype.cpp
Runtime/DeclarativeEnvironmentRecord.cpp
Runtime/EnvironmentRecord.cpp
Runtime/ErrorConstructor.cpp Runtime/ErrorConstructor.cpp
Runtime/Error.cpp Runtime/Error.cpp
Runtime/ErrorPrototype.cpp Runtime/ErrorPrototype.cpp
@ -69,7 +71,6 @@ set(SOURCES
Runtime/IteratorOperations.cpp Runtime/IteratorOperations.cpp
Runtime/IteratorPrototype.cpp Runtime/IteratorPrototype.cpp
Runtime/JSONObject.cpp Runtime/JSONObject.cpp
Runtime/LexicalEnvironment.cpp
Runtime/Map.cpp Runtime/Map.cpp
Runtime/MapConstructor.cpp Runtime/MapConstructor.cpp
Runtime/MapIterator.cpp Runtime/MapIterator.cpp
@ -82,8 +83,9 @@ set(SOURCES
Runtime/NumberConstructor.cpp Runtime/NumberConstructor.cpp
Runtime/NumberObject.cpp Runtime/NumberObject.cpp
Runtime/NumberPrototype.cpp Runtime/NumberPrototype.cpp
Runtime/ObjectConstructor.cpp
Runtime/Object.cpp Runtime/Object.cpp
Runtime/ObjectConstructor.cpp
Runtime/ObjectEnvironmentRecord.cpp
Runtime/ObjectPrototype.cpp Runtime/ObjectPrototype.cpp
Runtime/PrimitiveString.cpp Runtime/PrimitiveString.cpp
Runtime/Promise.cpp Runtime/Promise.cpp
@ -99,7 +101,6 @@ set(SOURCES
Runtime/RegExpConstructor.cpp Runtime/RegExpConstructor.cpp
Runtime/RegExpObject.cpp Runtime/RegExpObject.cpp
Runtime/RegExpPrototype.cpp Runtime/RegExpPrototype.cpp
Runtime/ScopeObject.cpp
Runtime/ScriptFunction.cpp Runtime/ScriptFunction.cpp
Runtime/Set.cpp Runtime/Set.cpp
Runtime/SetConstructor.cpp Runtime/SetConstructor.cpp
@ -130,7 +131,6 @@ set(SOURCES
Runtime/WeakSet.cpp Runtime/WeakSet.cpp
Runtime/WeakSetConstructor.cpp Runtime/WeakSetConstructor.cpp
Runtime/WeakSetPrototype.cpp Runtime/WeakSetPrototype.cpp
Runtime/WithScope.cpp
SyntaxHighlighter.cpp SyntaxHighlighter.cpp
Token.cpp Token.cpp
) )

View file

@ -131,7 +131,7 @@ class HandleImpl;
class Heap; class Heap;
class HeapBlock; class HeapBlock;
class Interpreter; class Interpreter;
class LexicalEnvironment; class DeclarativeEnvironmentRecord;
class MarkedValueList; class MarkedValueList;
class NativeFunction; class NativeFunction;
class NativeProperty; class NativeProperty;
@ -142,7 +142,7 @@ class PromiseResolveThenableJob;
class PropertyName; class PropertyName;
class Reference; class Reference;
class ScopeNode; class ScopeNode;
class ScopeObject; class EnvironmentRecord;
class Shape; class Shape;
class Statement; class Statement;
class StringOrSymbol; class StringOrSymbol;

View file

@ -9,8 +9,8 @@
#include <AK/StringBuilder.h> #include <AK/StringBuilder.h>
#include <LibJS/AST.h> #include <LibJS/AST.h>
#include <LibJS/Interpreter.h> #include <LibJS/Interpreter.h>
#include <LibJS/Runtime/DeclarativeEnvironmentRecord.h>
#include <LibJS/Runtime/GlobalObject.h> #include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/LexicalEnvironment.h>
#include <LibJS/Runtime/Object.h> #include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/Reference.h> #include <LibJS/Runtime/Reference.h>
#include <LibJS/Runtime/ScriptFunction.h> #include <LibJS/Runtime/ScriptFunction.h>
@ -50,7 +50,7 @@ void Interpreter::run(GlobalObject& global_object, const Program& program)
global_call_frame.this_value = &global_object; global_call_frame.this_value = &global_object;
static FlyString global_execution_context_name = "(global execution context)"; static FlyString global_execution_context_name = "(global execution context)";
global_call_frame.function_name = global_execution_context_name; global_call_frame.function_name = global_execution_context_name;
global_call_frame.scope = &global_object; global_call_frame.environment_record = &global_object;
VERIFY(!vm.exception()); VERIFY(!vm.exception());
global_call_frame.is_strict_mode = program.is_strict_mode(); global_call_frame.is_strict_mode = program.is_strict_mode();
vm.push_call_frame(global_call_frame, global_object); vm.push_call_frame(global_call_frame, global_object);
@ -128,15 +128,15 @@ void Interpreter::enter_scope(const ScopeNode& scope_node, ScopeType scope_type,
} }
} }
bool pushed_lexical_environment = false; bool pushed_environment_record = false;
if (!scope_variables_with_declaration_kind.is_empty()) { if (!scope_variables_with_declaration_kind.is_empty()) {
auto* block_lexical_environment = heap().allocate<LexicalEnvironment>(global_object, move(scope_variables_with_declaration_kind), current_scope()); auto* environment_record = heap().allocate<DeclarativeEnvironmentRecord>(global_object, move(scope_variables_with_declaration_kind), current_scope());
vm().call_frame().scope = block_lexical_environment; vm().call_frame().environment_record = environment_record;
pushed_lexical_environment = true; pushed_environment_record = true;
} }
push_scope({ scope_type, scope_node, pushed_lexical_environment }); push_scope({ scope_type, scope_node, pushed_environment_record });
} }
void Interpreter::exit_scope(const ScopeNode& scope_node) void Interpreter::exit_scope(const ScopeNode& scope_node)
@ -144,7 +144,7 @@ void Interpreter::exit_scope(const ScopeNode& scope_node)
while (!m_scope_stack.is_empty()) { while (!m_scope_stack.is_empty()) {
auto popped_scope = m_scope_stack.take_last(); auto popped_scope = m_scope_stack.take_last();
if (popped_scope.pushed_environment) if (popped_scope.pushed_environment)
vm().call_frame().scope = vm().call_frame().scope->parent(); vm().call_frame().environment_record = vm().call_frame().environment_record->parent();
if (popped_scope.scope_node.ptr() == &scope_node) if (popped_scope.scope_node.ptr() == &scope_node)
break; break;
} }
@ -193,10 +193,10 @@ Value Interpreter::execute_statement(GlobalObject& global_object, const Statemen
return last_value; return last_value;
} }
LexicalEnvironment* Interpreter::current_environment() DeclarativeEnvironmentRecord* Interpreter::current_environment()
{ {
VERIFY(is<LexicalEnvironment>(vm().call_frame().scope)); VERIFY(is<DeclarativeEnvironmentRecord>(vm().call_frame().environment_record));
return static_cast<LexicalEnvironment*>(vm().call_frame().scope); return static_cast<DeclarativeEnvironmentRecord*>(vm().call_frame().environment_record);
} }
} }

View file

@ -15,9 +15,9 @@
#include <LibJS/Forward.h> #include <LibJS/Forward.h>
#include <LibJS/Heap/DeferGC.h> #include <LibJS/Heap/DeferGC.h>
#include <LibJS/Heap/Heap.h> #include <LibJS/Heap/Heap.h>
#include <LibJS/Runtime/DeclarativeEnvironmentRecord.h>
#include <LibJS/Runtime/ErrorTypes.h> #include <LibJS/Runtime/ErrorTypes.h>
#include <LibJS/Runtime/Exception.h> #include <LibJS/Runtime/Exception.h>
#include <LibJS/Runtime/LexicalEnvironment.h>
#include <LibJS/Runtime/MarkedValueList.h> #include <LibJS/Runtime/MarkedValueList.h>
#include <LibJS/Runtime/VM.h> #include <LibJS/Runtime/VM.h>
#include <LibJS/Runtime/Value.h> #include <LibJS/Runtime/Value.h>
@ -56,8 +56,8 @@ public:
ALWAYS_INLINE Heap& heap() { return vm().heap(); } ALWAYS_INLINE Heap& heap() { return vm().heap(); }
ALWAYS_INLINE Exception* exception() { return vm().exception(); } ALWAYS_INLINE Exception* exception() { return vm().exception(); }
ScopeObject* current_scope() { return vm().current_scope(); } EnvironmentRecord* current_scope() { return vm().current_scope(); }
LexicalEnvironment* current_environment(); DeclarativeEnvironmentRecord* current_environment();
void enter_scope(const ScopeNode&, ScopeType, GlobalObject&); void enter_scope(const ScopeNode&, ScopeType, GlobalObject&);
void exit_scope(const ScopeNode&); void exit_scope(const ScopeNode&);

View file

@ -258,7 +258,7 @@ NonnullRefPtr<Program> Parser::parse_program()
program->add_variables(m_state.let_scopes.last()); program->add_variables(m_state.let_scopes.last());
program->add_functions(m_state.function_scopes.last()); program->add_functions(m_state.function_scopes.last());
} else { } else {
syntax_error("Unclosed scope"); syntax_error("Unclosed environment_record");
} }
program->source_range().end = position(); program->source_range().end = position();
return program; return program;

View file

@ -44,9 +44,9 @@ Value BoundFunction::construct(Function& new_target)
return m_target_function->construct(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) void BoundFunction::visit_edges(Visitor& visitor)

View file

@ -22,7 +22,7 @@ public:
virtual Value construct(Function& new_target) override; virtual Value construct(Function& new_target) override;
virtual LexicalEnvironment* create_environment() override; virtual DeclarativeEnvironmentRecord* create_environment_record() override;
virtual void visit_edges(Visitor&) 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 * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <LibJS/Interpreter.h> #include <LibJS/Interpreter.h>
#include <LibJS/Runtime/DeclarativeEnvironmentRecord.h>
#include <LibJS/Runtime/Error.h> #include <LibJS/Runtime/Error.h>
#include <LibJS/Runtime/Function.h> #include <LibJS/Runtime/Function.h>
#include <LibJS/Runtime/GlobalObject.h> #include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/LexicalEnvironment.h>
#include <LibJS/Runtime/Value.h> #include <LibJS/Runtime/Value.h>
namespace JS { namespace JS {
LexicalEnvironment::LexicalEnvironment() DeclarativeEnvironmentRecord::DeclarativeEnvironmentRecord()
: ScopeObject(nullptr) : EnvironmentRecord(nullptr)
{ {
} }
LexicalEnvironment::LexicalEnvironment(EnvironmentRecordType environment_record_type) DeclarativeEnvironmentRecord::DeclarativeEnvironmentRecord(EnvironmentRecordType environment_record_type)
: ScopeObject(nullptr) : EnvironmentRecord(nullptr)
, m_environment_record_type(environment_record_type) , m_environment_record_type(environment_record_type)
{ {
} }
LexicalEnvironment::LexicalEnvironment(HashMap<FlyString, Variable> variables, ScopeObject* parent_scope) DeclarativeEnvironmentRecord::DeclarativeEnvironmentRecord(HashMap<FlyString, Variable> variables, EnvironmentRecord* parent_scope)
: ScopeObject(parent_scope) : EnvironmentRecord(parent_scope)
, m_variables(move(variables)) , m_variables(move(variables))
{ {
} }
LexicalEnvironment::LexicalEnvironment(HashMap<FlyString, Variable> variables, ScopeObject* parent_scope, EnvironmentRecordType environment_record_type) DeclarativeEnvironmentRecord::DeclarativeEnvironmentRecord(HashMap<FlyString, Variable> variables, EnvironmentRecord* parent_scope, EnvironmentRecordType environment_record_type)
: ScopeObject(parent_scope) : EnvironmentRecord(parent_scope)
, m_environment_record_type(environment_record_type) , m_environment_record_type(environment_record_type)
, m_variables(move(variables)) , m_variables(move(variables))
{ {
} }
LexicalEnvironment::~LexicalEnvironment() DeclarativeEnvironmentRecord::~DeclarativeEnvironmentRecord()
{ {
} }
void LexicalEnvironment::visit_edges(Visitor& visitor) void DeclarativeEnvironmentRecord::visit_edges(Visitor& visitor)
{ {
Base::visit_edges(visitor); Base::visit_edges(visitor);
visitor.visit(m_this_value); visitor.visit(m_this_value);
@ -52,27 +52,27 @@ void LexicalEnvironment::visit_edges(Visitor& visitor)
visitor.visit(it.value.value); 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); 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); 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); 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(); 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()); VERIFY(has_super_binding());
if (m_home_object.is_object()) if (m_home_object.is_object())
@ -80,7 +80,7 @@ Value LexicalEnvironment::get_super_base()
return {}; return {};
} }
bool LexicalEnvironment::has_this_binding() const bool DeclarativeEnvironmentRecord::has_this_binding() const
{ {
// More like "is_capable_of_having_a_this_binding". // More like "is_capable_of_having_a_this_binding".
switch (m_environment_record_type) { switch (m_environment_record_type) {
@ -95,7 +95,7 @@ bool LexicalEnvironment::has_this_binding() const
VERIFY_NOT_REACHED(); 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()); VERIFY(has_this_binding());
if (this_binding_status() == ThisBindingStatus::Uninitialized) { if (this_binding_status() == ThisBindingStatus::Uninitialized) {
@ -105,7 +105,7 @@ Value LexicalEnvironment::get_this_binding(GlobalObject& global_object) const
return m_this_value; 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()); VERIFY(has_this_binding());
if (m_this_binding_status == ThisBindingStatus::Initialized) { 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 * SPDX-License-Identifier: BSD-2-Clause
*/ */
@ -8,13 +8,13 @@
#include <AK/FlyString.h> #include <AK/FlyString.h>
#include <AK/HashMap.h> #include <AK/HashMap.h>
#include <LibJS/Runtime/ScopeObject.h> #include <LibJS/Runtime/EnvironmentRecord.h>
#include <LibJS/Runtime/Value.h> #include <LibJS/Runtime/Value.h>
namespace JS { namespace JS {
class LexicalEnvironment final : public ScopeObject { class DeclarativeEnvironmentRecord final : public EnvironmentRecord {
JS_OBJECT(LexicalEnvironment, ScopeObject); JS_OBJECT(DeclarativeEnvironmentRecord, EnvironmentRecord);
public: public:
enum class ThisBindingStatus { enum class ThisBindingStatus {
@ -30,13 +30,13 @@ public:
Module, Module,
}; };
LexicalEnvironment(); DeclarativeEnvironmentRecord();
LexicalEnvironment(EnvironmentRecordType); DeclarativeEnvironmentRecord(EnvironmentRecordType);
LexicalEnvironment(HashMap<FlyString, Variable> variables, ScopeObject* parent_scope); DeclarativeEnvironmentRecord(HashMap<FlyString, Variable> variables, EnvironmentRecord* parent_scope);
LexicalEnvironment(HashMap<FlyString, Variable> variables, ScopeObject* parent_scope, EnvironmentRecordType); DeclarativeEnvironmentRecord(HashMap<FlyString, Variable> variables, EnvironmentRecord* parent_scope, EnvironmentRecordType);
virtual ~LexicalEnvironment() override; virtual ~DeclarativeEnvironmentRecord() override;
// ^ScopeObject // ^EnvironmentRecord
virtual Optional<Variable> get_from_scope(const FlyString&) const override; virtual Optional<Variable> get_from_scope(const FlyString&) const override;
virtual void put_to_scope(const FlyString&, Variable) override; virtual void put_to_scope(const FlyString&, Variable) override;
virtual bool delete_from_scope(FlyString const&) override; virtual bool delete_from_scope(FlyString const&) override;
@ -66,7 +66,7 @@ public:
EnvironmentRecordType type() const { return m_environment_record_type; } EnvironmentRecordType type() const { return m_environment_record_type; }
private: 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; virtual void visit_edges(Visitor&) override;
EnvironmentRecordType m_environment_record_type : 8 { EnvironmentRecordType::Declarative }; EnvironmentRecordType m_environment_record_type : 8 { EnvironmentRecordType::Declarative };
@ -80,6 +80,6 @@ private:
}; };
template<> 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 * SPDX-License-Identifier: BSD-2-Clause
*/ */
@ -15,8 +15,8 @@ struct Variable {
DeclarationKind declaration_kind; DeclarationKind declaration_kind;
}; };
class ScopeObject : public Object { class EnvironmentRecord : public Object {
JS_OBJECT(ScopeObject, Object); JS_OBJECT(EnvironmentRecord, Object);
public: public:
virtual Optional<Variable> get_from_scope(const FlyString&) const = 0; virtual Optional<Variable> get_from_scope(const FlyString&) const = 0;
@ -25,17 +25,17 @@ public:
virtual bool has_this_binding() const = 0; virtual bool has_this_binding() const = 0;
virtual Value get_this_binding(GlobalObject&) const = 0; virtual Value get_this_binding(GlobalObject&) const = 0;
ScopeObject* parent() { return m_parent; } EnvironmentRecord* parent() { return m_parent; }
const ScopeObject* parent() const { return m_parent; } const EnvironmentRecord* parent() const { return m_parent; }
protected: protected:
explicit ScopeObject(ScopeObject* parent); explicit EnvironmentRecord(EnvironmentRecord* parent);
explicit ScopeObject(GlobalObjectTag); explicit EnvironmentRecord(GlobalObjectTag);
virtual void visit_edges(Visitor&) override; virtual void visit_edges(Visitor&) override;
private: private:
ScopeObject* m_parent { nullptr }; EnvironmentRecord* m_parent { nullptr };
}; };
} }

View file

@ -26,7 +26,7 @@ public:
virtual Value call() = 0; virtual Value call() = 0;
virtual Value construct(Function& new_target) = 0; virtual Value construct(Function& new_target) = 0;
virtual const FlyString& name() const = 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); BoundFunction* bind(Value bound_this_value, Vector<Value> arguments);

View file

@ -13,7 +13,7 @@
namespace JS { 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) // 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); 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); auto object = global_object.heap().allocate<GeneratorObject>(global_object, global_object, *generating_function_proto_property);
object->m_generating_function = generating_function; object->m_generating_function = generating_function;
object->m_scope = generating_scope; object->m_environment_record = generating_scope;
object->m_frame = move(frame); object->m_frame = move(frame);
object->m_previous_value = initial_value; object->m_previous_value = initial_value;
return object; return object;
@ -44,7 +44,7 @@ GeneratorObject::~GeneratorObject()
void GeneratorObject::visit_edges(Cell::Visitor& visitor) void GeneratorObject::visit_edges(Cell::Visitor& visitor)
{ {
Object::visit_edges(visitor); Object::visit_edges(visitor);
visitor.visit(m_scope); visitor.visit(m_environment_record);
visitor.visit(m_generating_function); visitor.visit(m_generating_function);
if (m_previous_value.is_object()) if (m_previous_value.is_object())
visitor.visit(&m_previous_value.as_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); bytecode_interpreter->accumulator() = vm.argument(0);
} }
// Temporarily switch to the captured scope // Temporarily switch to the captured environment record
TemporaryChange change { vm.call_frame().scope, m_scope }; TemporaryChange change { vm.call_frame().environment_record, m_environment_record };
m_previous_value = bytecode_interpreter->run(*m_generating_function->bytecode_executable(), next_block); 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); JS_OBJECT(GeneratorObject, Object);
public: public:
static GeneratorObject* create(GlobalObject&, Value, ScriptFunction*, ScopeObject*, Bytecode::RegisterWindow); static GeneratorObject* create(GlobalObject&, Value, ScriptFunction*, EnvironmentRecord*, Bytecode::RegisterWindow);
GeneratorObject(GlobalObject&, Object& prototype); GeneratorObject(GlobalObject&, Object& prototype);
virtual void initialize(GlobalObject&) override; virtual void initialize(GlobalObject&) override;
virtual ~GeneratorObject() override; virtual ~GeneratorObject() override;
@ -25,7 +25,7 @@ public:
void set_done() { m_done = true; } void set_done() { m_done = true; }
private: private:
ScopeObject* m_scope { nullptr }; EnvironmentRecord* m_environment_record { nullptr };
ScriptFunction* m_generating_function { nullptr }; ScriptFunction* m_generating_function { nullptr };
Value m_previous_value; Value m_previous_value;
Bytecode::RegisterWindow m_frame; Bytecode::RegisterWindow m_frame;

View file

@ -82,7 +82,7 @@
namespace JS { namespace JS {
GlobalObject::GlobalObject() GlobalObject::GlobalObject()
: ScopeObject(GlobalObjectTag::Tag) : EnvironmentRecord(GlobalObjectTag::Tag)
, m_console(make<Console>(*this)) , 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); 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(); auto& interpreter = vm.interpreter();
return interpreter.execute_statement(global_object, program).value_or(js_undefined()); return interpreter.execute_statement(global_object, program).value_or(js_undefined());

View file

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

View file

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

View file

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

View file

@ -108,7 +108,7 @@ public:
virtual bool is_global_object() const { return false; } virtual bool is_global_object() const { return false; }
virtual bool is_proxy_object() const { return false; } virtual bool is_proxy_object() const { return false; }
virtual bool is_native_function() 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 // B.3.7 The [[IsHTMLDDA]] Internal Slot, https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot
virtual bool is_htmldda() const { return false; } 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 * SPDX-License-Identifier: BSD-2-Clause
*/ */
#pragma once #pragma once
#include <LibJS/Runtime/ScopeObject.h> #include <LibJS/Runtime/EnvironmentRecord.h>
namespace JS { namespace JS {
class WithScope : public ScopeObject { class ObjectEnvironmentRecord : public EnvironmentRecord {
JS_OBJECT(WithScope, ScopeObject); JS_OBJECT(ObjectEnvironmentRecord, EnvironmentRecord);
public: public:
WithScope(Object&, ScopeObject* parent_scope); ObjectEnvironmentRecord(Object&, EnvironmentRecord* parent_scope);
virtual Optional<Variable> get_from_scope(const FlyString&) const override; virtual Optional<Variable> get_from_scope(const FlyString&) const override;
virtual void put_to_scope(const FlyString&, Variable) 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(); return static_cast<Function&>(m_target).name();
} }
LexicalEnvironment* ProxyObject::create_environment() DeclarativeEnvironmentRecord* ProxyObject::create_environment_record()
{ {
VERIFY(is_function()); 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 call() override;
virtual Value construct(Function& new_target) override; virtual Value construct(Function& new_target) override;
virtual const FlyString& name() const 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& target() const { return m_target; }
const Object& handler() const { return m_handler; } 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); 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; Object* prototype = nullptr;
switch (kind) { 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); 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) : Function(is_arrow_function ? vm().this_value(global_object) : Value(), {}, prototype)
, m_name(name) , m_name(name)
, m_body(body) , m_body(body)
@ -93,7 +93,7 @@ void ScriptFunction::visit_edges(Visitor& visitor)
visitor.visit(m_parent_scope); visitor.visit(m_parent_scope);
} }
LexicalEnvironment* ScriptFunction::create_environment() DeclarativeEnvironmentRecord* ScriptFunction::create_environment_record()
{ {
HashMap<FlyString, Variable> variables; HashMap<FlyString, Variable> variables;
for (auto& parameter : m_parameters) { 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_home_object(home_object());
environment->set_current_function(*this); environment->set_current_function(*this);
if (m_is_arrow_function) { if (m_is_arrow_function) {
if (is<LexicalEnvironment>(m_parent_scope)) if (is<DeclarativeEnvironmentRecord>(m_parent_scope))
environment->set_new_target(static_cast<LexicalEnvironment*>(m_parent_scope)->new_target()); environment->set_new_target(static_cast<DeclarativeEnvironmentRecord*>(m_parent_scope)->new_target());
} }
return environment; return environment;
} }
@ -191,7 +191,7 @@ Value ScriptFunction::execute_function_body()
if (m_kind != FunctionKind::Generator) if (m_kind != FunctionKind::Generator)
return result; 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 { } else {
VERIFY(m_kind != FunctionKind::Generator); VERIFY(m_kind != FunctionKind::Generator);
OwnPtr<Interpreter> local_interpreter; OwnPtr<Interpreter> local_interpreter;

View file

@ -16,9 +16,9 @@ class ScriptFunction final : public Function {
JS_OBJECT(ScriptFunction, Function); JS_OBJECT(ScriptFunction, Function);
public: 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 void initialize(GlobalObject&) override;
virtual ~ScriptFunction(); virtual ~ScriptFunction();
@ -39,7 +39,7 @@ protected:
virtual bool is_strict_mode() const final { return m_is_strict; } virtual bool is_strict_mode() const final { return m_is_strict; }
private: private:
virtual LexicalEnvironment* create_environment() override; virtual DeclarativeEnvironmentRecord* create_environment_record() override;
virtual void visit_edges(Visitor&) override; virtual void visit_edges(Visitor&) override;
Value execute_function_body(); Value execute_function_body();
@ -51,7 +51,7 @@ private:
NonnullRefPtr<Statement> m_body; NonnullRefPtr<Statement> m_body;
const Vector<FunctionNode::Parameter> m_parameters; const Vector<FunctionNode::Parameter> m_parameters;
Optional<Bytecode::Executable> m_bytecode_executable; Optional<Bytecode::Executable> m_bytecode_executable;
ScopeObject* m_parent_scope { nullptr }; EnvironmentRecord* m_parent_scope { 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 };

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_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) \ #define __JS_ENUMERATE(SymbolName, snake_name) \
m_well_known_symbol_##snake_name = js_symbol(*this, "Symbol." #SymbolName, false); 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) for (auto* string : m_single_ascii_character_strings)
roots.set(string); roots.set(string);
roots.set(m_scope_object_shape); roots.set(m_environment_record_shape);
roots.set(m_exception); roots.set(m_exception);
if (m_last_value.is_cell()) if (m_last_value.is_cell())
@ -105,7 +105,7 @@ void VM::gather_roots(HashTable<Cell*>& roots)
if (argument.is_cell()) if (argument.is_cell())
roots.set(&argument.as_cell()); roots.set(&argument.as_cell());
} }
roots.set(call_frame->scope); roots.set(call_frame->environment_record);
} }
#define __JS_ENUMERATE(SymbolName, snake_name) \ #define __JS_ENUMERATE(SymbolName, snake_name) \
@ -131,7 +131,7 @@ Symbol* VM::get_global_symbol(const String& description)
return new_global_symbol; 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; Optional<Variable> possible_match;
if (!specific_scope && m_call_stack.size()) { 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) bool VM::delete_variable(FlyString const& name)
{ {
ScopeObject* specific_scope = nullptr; EnvironmentRecord* specific_scope = nullptr;
Optional<Variable> possible_match; Optional<Variable> possible_match;
if (!m_call_stack.is_empty()) { if (!m_call_stack.is_empty()) {
for (auto* scope = current_scope(); scope; scope = scope->parent()) { 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); 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); 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>>()) if (auto id_ptr = target.get_pointer<NonnullRefPtr<Identifier>>())
return assign((*id_ptr)->string(), move(value), global_object, first_assignment, specific_scope); 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); 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; auto& binding = *target;
@ -424,8 +424,8 @@ Value VM::construct(Function& function, Function& new_target, Optional<MarkedVal
call_frame.arguments = function.bound_arguments(); call_frame.arguments = function.bound_arguments();
if (arguments.has_value()) if (arguments.has_value())
call_frame.arguments.extend(arguments.value().values()); call_frame.arguments.extend(arguments.value().values());
auto* environment = function.create_environment(); auto* environment = function.create_environment_record();
call_frame.scope = environment; call_frame.environment_record = environment;
if (environment) if (environment)
environment->set_new_target(&new_target); 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). // 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 (function.constructor_kind() == Function::ConstructorKind::Base && new_target.constructor_kind() == Function::ConstructorKind::Derived && result.is_object()) {
if (environment) { if (environment) {
VERIFY(is<LexicalEnvironment>(current_scope())); VERIFY(is<DeclarativeEnvironmentRecord>(current_scope()));
static_cast<LexicalEnvironment*>(current_scope())->replace_this_binding(result); static_cast<DeclarativeEnvironmentRecord*>(current_scope())->replace_this_binding(result);
} }
auto prototype = new_target.get(names.prototype); auto prototype = new_target.get(names.prototype);
if (exception()) if (exception())
@ -505,7 +505,7 @@ Value VM::resolve_this_binding(GlobalObject& global_object) const
return find_this_scope()->get_this_binding(global_object); 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. // 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()) { 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 Value VM::get_new_target() const
{ {
VERIFY(is<LexicalEnvironment>(find_this_scope())); VERIFY(is<DeclarativeEnvironmentRecord>(find_this_scope()));
return static_cast<const LexicalEnvironment*>(find_this_scope())->new_target(); return static_cast<const DeclarativeEnvironmentRecord*>(find_this_scope())->new_target();
} }
Value VM::call_internal(Function& function, Value this_value, Optional<MarkedValueList> arguments) 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(); call_frame.arguments = function.bound_arguments();
if (arguments.has_value()) if (arguments.has_value())
call_frame.arguments.extend(arguments.value().values()); call_frame.arguments.extend(arguments.value().values());
auto* environment = function.create_environment(); auto* environment = function.create_environment_record();
call_frame.scope = environment; call_frame.environment_record = environment;
if (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); 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()) { for (auto* scope = current_scope(); scope; scope = scope->parent()) {
dbgln("+> {} ({:p})", scope->class_name(), scope); dbgln("+> {} ({:p})", scope->class_name(), scope);
if (is<LexicalEnvironment>(*scope)) { if (is<DeclarativeEnvironmentRecord>(*scope)) {
auto& lexical_environment = static_cast<LexicalEnvironment const&>(*scope); auto& environment_record = static_cast<DeclarativeEnvironmentRecord const&>(*scope);
for (auto& variable : lexical_environment.variables()) { for (auto& variable : environment_record.variables()) {
dbgln(" {}", variable.key); dbgln(" {}", variable.key);
} }
} }

View file

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