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:
parent
e9b4a0a830
commit
6c6dbcfc36
35 changed files with 297 additions and 297 deletions
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 = ???;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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&);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
|
@ -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(); }
|
||||||
|
|
||||||
}
|
}
|
29
Userland/Libraries/LibJS/Runtime/EnvironmentRecord.cpp
Normal file
29
Userland/Libraries/LibJS/Runtime/EnvironmentRecord.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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 };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -47,7 +47,7 @@ Value NativeFunction::construct(Function&)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
LexicalEnvironment* NativeFunction::create_environment()
|
DeclarativeEnvironmentRecord* NativeFunction::create_environment_record()
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
52
Userland/Libraries/LibJS/Runtime/ObjectEnvironmentRecord.cpp
Normal file
52
Userland/Libraries/LibJS/Runtime/ObjectEnvironmentRecord.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue