mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 18:02:05 -05:00
LibJS: Stop using execute_ast_node() for class property evaluation
Instead, generate bytecode to execute their AST nodes and save the resulting operands inside the NewClass instruction. Moving property expression evaluation to happen before NewClass execution also moves along creation of new private environment and its population with private members (private members should be visible during property evaluation). Before: - NewClass After: - CreatePrivateEnvironment - AddPrivateName - ... - AddPrivateName - NewClass - LeavePrivateEnvironment
This commit is contained in:
parent
b46fc47bf7
commit
6fb1d9e516
9 changed files with 153 additions and 36 deletions
|
@ -128,7 +128,7 @@ Optional<ByteString> CallExpression::expression_string() const
|
|||
return {};
|
||||
}
|
||||
|
||||
static ThrowCompletionOr<ClassElementName> class_key_to_property_name(VM& vm, Expression const& key)
|
||||
static ThrowCompletionOr<ClassElementName> class_key_to_property_name(VM& vm, Expression const& key, Value prop_key)
|
||||
{
|
||||
if (is<PrivateIdentifier>(key)) {
|
||||
auto& private_identifier = static_cast<PrivateIdentifier const&>(key);
|
||||
|
@ -137,7 +137,7 @@ static ThrowCompletionOr<ClassElementName> class_key_to_property_name(VM& vm, Ex
|
|||
return ClassElementName { private_environment->resolve_private_identifier(private_identifier.string()) };
|
||||
}
|
||||
|
||||
auto prop_key = TRY(vm.execute_ast_node(key));
|
||||
VERIFY(!prop_key.is_empty());
|
||||
|
||||
if (prop_key.is_object())
|
||||
prop_key = TRY(prop_key.to_primitive(vm, Value::PreferredType::String));
|
||||
|
@ -147,9 +147,9 @@ static ThrowCompletionOr<ClassElementName> class_key_to_property_name(VM& vm, Ex
|
|||
}
|
||||
|
||||
// 15.4.5 Runtime Semantics: MethodDefinitionEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-methoddefinitionevaluation
|
||||
ThrowCompletionOr<ClassElement::ClassValue> ClassMethod::class_element_evaluation(VM& vm, Object& target) const
|
||||
ThrowCompletionOr<ClassElement::ClassValue> ClassMethod::class_element_evaluation(VM& vm, Object& target, Value property_key) const
|
||||
{
|
||||
auto property_key_or_private_name = TRY(class_key_to_property_name(vm, *m_key));
|
||||
auto property_key_or_private_name = TRY(class_key_to_property_name(vm, *m_key, property_key));
|
||||
|
||||
auto& method_function = *ECMAScriptFunctionObject::create(*vm.current_realm(), m_function->name(), m_function->source_text(), m_function->body(), m_function->parameters(), m_function->function_length(), m_function->local_variables_names(), vm.lexical_environment(), vm.running_execution_context().private_environment, m_function->kind(), m_function->is_strict_mode(), m_function->uses_this(), m_function->might_need_arguments_object(), m_function->contains_direct_call_to_eval(), m_function->is_arrow_function());
|
||||
|
||||
|
@ -220,11 +220,11 @@ void ClassFieldInitializerStatement::dump(int) const
|
|||
}
|
||||
|
||||
// 15.7.10 Runtime Semantics: ClassFieldDefinitionEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-classfielddefinitionevaluation
|
||||
ThrowCompletionOr<ClassElement::ClassValue> ClassField::class_element_evaluation(VM& vm, Object& target) const
|
||||
ThrowCompletionOr<ClassElement::ClassValue> ClassField::class_element_evaluation(VM& vm, Object& target, Value property_key) const
|
||||
{
|
||||
auto& realm = *vm.current_realm();
|
||||
|
||||
auto property_key_or_private_name = TRY(class_key_to_property_name(vm, *m_key));
|
||||
auto property_key_or_private_name = TRY(class_key_to_property_name(vm, *m_key, property_key));
|
||||
Handle<ECMAScriptFunctionObject> initializer {};
|
||||
if (m_initializer) {
|
||||
auto copy_initializer = m_initializer;
|
||||
|
@ -268,7 +268,7 @@ Optional<DeprecatedFlyString> ClassMethod::private_bound_identifier() const
|
|||
}
|
||||
|
||||
// 15.7.11 Runtime Semantics: ClassStaticBlockDefinitionEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-classstaticblockdefinitionevaluation
|
||||
ThrowCompletionOr<ClassElement::ClassValue> StaticInitializer::class_element_evaluation(VM& vm, Object& home_object) const
|
||||
ThrowCompletionOr<ClassElement::ClassValue> StaticInitializer::class_element_evaluation(VM& vm, Object& home_object, Value) const
|
||||
{
|
||||
auto& realm = *vm.current_realm();
|
||||
|
||||
|
@ -291,7 +291,7 @@ ThrowCompletionOr<ClassElement::ClassValue> StaticInitializer::class_element_eva
|
|||
return ClassValue { normal_completion(body_function) };
|
||||
}
|
||||
|
||||
ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::create_class_constructor(VM& vm, Environment* class_environment, Environment* environment, Value super_class, Optional<DeprecatedFlyString> const& binding_name, DeprecatedFlyString const& class_name) const
|
||||
ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::create_class_constructor(VM& vm, Environment* class_environment, Environment* environment, Value super_class, ReadonlySpan<Value> element_keys, Optional<DeprecatedFlyString> const& binding_name, DeprecatedFlyString const& class_name) const
|
||||
{
|
||||
auto& realm = *vm.current_realm();
|
||||
|
||||
|
@ -300,18 +300,11 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::create_class_const
|
|||
vm.running_execution_context().lexical_environment = environment;
|
||||
};
|
||||
|
||||
auto outer_private_environment = vm.running_execution_context().private_environment;
|
||||
auto class_private_environment = new_private_environment(vm, outer_private_environment);
|
||||
vm.running_execution_context().lexical_environment = class_environment;
|
||||
|
||||
auto proto_parent = GCPtr { realm.intrinsics().object_prototype() };
|
||||
auto constructor_parent = realm.intrinsics().function_prototype();
|
||||
|
||||
for (auto const& element : m_elements) {
|
||||
auto opt_private_name = element->private_bound_identifier();
|
||||
if (opt_private_name.has_value())
|
||||
class_private_environment->add_private_name({}, opt_private_name.release_value());
|
||||
}
|
||||
|
||||
if (!m_super_class.is_null()) {
|
||||
if (super_class.is_null()) {
|
||||
proto_parent = nullptr;
|
||||
|
@ -334,12 +327,6 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::create_class_const
|
|||
auto prototype = Object::create_prototype(realm, proto_parent);
|
||||
VERIFY(prototype);
|
||||
|
||||
vm.running_execution_context().lexical_environment = class_environment;
|
||||
vm.running_execution_context().private_environment = class_private_environment;
|
||||
ScopeGuard restore_private_environment = [&] {
|
||||
vm.running_execution_context().private_environment = outer_private_environment;
|
||||
};
|
||||
|
||||
// FIXME: Step 14.a is done in the parser. By using a synthetic super(...args) which does not call @@iterator of %Array.prototype%
|
||||
auto const& constructor = *m_constructor;
|
||||
auto class_constructor = ECMAScriptFunctionObject::create(
|
||||
|
@ -377,9 +364,11 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::create_class_const
|
|||
Vector<ClassFieldDefinition> instance_fields;
|
||||
Vector<StaticElement> static_elements;
|
||||
|
||||
for (auto const& element : m_elements) {
|
||||
for (size_t element_index = 0; element_index < m_elements.size(); element_index++) {
|
||||
auto const& element = m_elements[element_index];
|
||||
|
||||
// Note: All ClassElementEvaluation start with evaluating the name (or we fake it).
|
||||
auto element_value = TRY(element->class_element_evaluation(vm, element->is_static() ? *class_constructor : *prototype));
|
||||
auto element_value = TRY(element->class_element_evaluation(vm, element->is_static() ? *class_constructor : *prototype, element_keys[element_index]));
|
||||
|
||||
if (element_value.has<PrivateElement>()) {
|
||||
auto& container = element->is_static() ? static_private_methods : instance_private_methods;
|
||||
|
|
|
@ -1326,7 +1326,7 @@ public:
|
|||
|
||||
// We use the Completion also as a ClassStaticBlockDefinition Record.
|
||||
using ClassValue = Variant<ClassFieldDefinition, Completion, PrivateElement>;
|
||||
virtual ThrowCompletionOr<ClassValue> class_element_evaluation(VM&, Object& home_object) const = 0;
|
||||
virtual ThrowCompletionOr<ClassValue> class_element_evaluation(VM&, Object& home_object, Value) const = 0;
|
||||
|
||||
virtual Optional<DeprecatedFlyString> private_bound_identifier() const { return {}; }
|
||||
|
||||
|
@ -1355,7 +1355,7 @@ public:
|
|||
virtual ElementKind class_element_kind() const override { return ElementKind::Method; }
|
||||
|
||||
virtual void dump(int indent) const override;
|
||||
virtual ThrowCompletionOr<ClassValue> class_element_evaluation(VM&, Object& home_object) const override;
|
||||
virtual ThrowCompletionOr<ClassValue> class_element_evaluation(VM&, Object& home_object, Value property_key) const override;
|
||||
virtual Optional<DeprecatedFlyString> private_bound_identifier() const override;
|
||||
|
||||
private:
|
||||
|
@ -1382,7 +1382,7 @@ public:
|
|||
virtual ElementKind class_element_kind() const override { return ElementKind::Field; }
|
||||
|
||||
virtual void dump(int indent) const override;
|
||||
virtual ThrowCompletionOr<ClassValue> class_element_evaluation(VM&, Object& home_object) const override;
|
||||
virtual ThrowCompletionOr<ClassValue> class_element_evaluation(VM&, Object& home_object, Value property_key) const override;
|
||||
virtual Optional<DeprecatedFlyString> private_bound_identifier() const override;
|
||||
|
||||
private:
|
||||
|
@ -1401,7 +1401,7 @@ public:
|
|||
}
|
||||
|
||||
virtual ElementKind class_element_kind() const override { return ElementKind::StaticInitializer; }
|
||||
virtual ThrowCompletionOr<ClassValue> class_element_evaluation(VM&, Object& home_object) const override;
|
||||
virtual ThrowCompletionOr<ClassValue> class_element_evaluation(VM&, Object& home_object, Value property_key) const override;
|
||||
|
||||
virtual void dump(int indent) const override;
|
||||
|
||||
|
@ -1446,7 +1446,7 @@ public:
|
|||
|
||||
bool has_name() const { return m_name; }
|
||||
|
||||
ThrowCompletionOr<ECMAScriptFunctionObject*> create_class_constructor(VM&, Environment* class_environment, Environment* environment, Value super_class, Optional<DeprecatedFlyString> const& binding_name = {}, DeprecatedFlyString const& class_name = {}) const;
|
||||
ThrowCompletionOr<ECMAScriptFunctionObject*> create_class_constructor(VM&, Environment* class_environment, Environment* environment, Value super_class, ReadonlySpan<Value> element_keys, Optional<DeprecatedFlyString> const& binding_name = {}, DeprecatedFlyString const& class_name = {}) const;
|
||||
|
||||
private:
|
||||
virtual bool is_class_expression() const override { return true; }
|
||||
|
|
|
@ -2757,8 +2757,35 @@ Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> ClassExpression::genera
|
|||
if (m_super_class)
|
||||
super_class = TRY(m_super_class->generate_bytecode(generator)).value();
|
||||
|
||||
generator.emit<Op::CreatePrivateEnvironment>();
|
||||
|
||||
for (auto const& element : m_elements) {
|
||||
auto opt_private_name = element->private_bound_identifier();
|
||||
if (opt_private_name.has_value()) {
|
||||
generator.emit<Op::AddPrivateName>(generator.intern_identifier(*opt_private_name));
|
||||
}
|
||||
}
|
||||
|
||||
Vector<Optional<ScopedOperand>> elements;
|
||||
for (auto const& element : m_elements) {
|
||||
Optional<ScopedOperand> key;
|
||||
if (is<ClassMethod>(*element)) {
|
||||
auto const& class_method = static_cast<ClassMethod const&>(*element);
|
||||
if (!is<PrivateIdentifier>(class_method.key()))
|
||||
key = TRY(class_method.key().generate_bytecode(generator));
|
||||
} else if (is<ClassField>(*element)) {
|
||||
auto const& class_field = static_cast<ClassField const&>(*element);
|
||||
if (!is<PrivateIdentifier>(class_field.key()))
|
||||
key = TRY(class_field.key().generate_bytecode(generator));
|
||||
}
|
||||
|
||||
elements.append({ key });
|
||||
}
|
||||
|
||||
auto dst = choose_dst(generator, preferred_dst);
|
||||
generator.emit<Bytecode::Op::NewClass>(dst, super_class.has_value() ? super_class->operand() : Optional<Operand> {}, *this, lhs_name);
|
||||
generator.emit_with_extra_slots<Op::NewClass, Optional<Operand>>(elements.size(), dst, super_class.has_value() ? super_class->operand() : Optional<Operand> {}, *this, lhs_name, elements);
|
||||
|
||||
generator.emit<Op::LeavePrivateEnvironment>();
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
|
|
@ -666,7 +666,7 @@ inline ThrowCompletionOr<void> create_variable(VM& vm, DeprecatedFlyString const
|
|||
return verify_cast<GlobalEnvironment>(vm.variable_environment())->create_global_var_binding(name, false);
|
||||
}
|
||||
|
||||
inline ThrowCompletionOr<ECMAScriptFunctionObject*> new_class(VM& vm, Value super_class, ClassExpression const& class_expression, Optional<IdentifierTableIndex> const& lhs_name)
|
||||
inline ThrowCompletionOr<ECMAScriptFunctionObject*> new_class(VM& vm, Value super_class, ClassExpression const& class_expression, Optional<IdentifierTableIndex> const& lhs_name, ReadonlySpan<Value> element_keys)
|
||||
{
|
||||
auto& interpreter = vm.bytecode_interpreter();
|
||||
auto name = class_expression.name();
|
||||
|
@ -684,7 +684,7 @@ inline ThrowCompletionOr<ECMAScriptFunctionObject*> new_class(VM& vm, Value supe
|
|||
class_name = name.is_null() ? ""sv : name;
|
||||
}
|
||||
|
||||
return TRY(class_expression.create_class_constructor(vm, class_environment, vm.lexical_environment(), super_class, binding_name, class_name));
|
||||
return TRY(class_expression.create_class_constructor(vm, class_environment, vm.lexical_environment(), super_class, element_keys, binding_name, class_name));
|
||||
}
|
||||
|
||||
// 13.3.7.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#define ENUMERATE_BYTECODE_OPS(O) \
|
||||
O(Add) \
|
||||
O(AddPrivateName) \
|
||||
O(ArrayAppend) \
|
||||
O(AsyncIteratorClose) \
|
||||
O(Await) \
|
||||
|
@ -31,6 +32,7 @@
|
|||
O(CopyObjectExcludingProperties) \
|
||||
O(CreateLexicalEnvironment) \
|
||||
O(CreateVariableEnvironment) \
|
||||
O(CreatePrivateEnvironment) \
|
||||
O(CreateVariable) \
|
||||
O(CreateRestParams) \
|
||||
O(CreateArguments) \
|
||||
|
@ -88,6 +90,7 @@
|
|||
O(JumpUndefined) \
|
||||
O(LeaveFinally) \
|
||||
O(LeaveLexicalEnvironment) \
|
||||
O(LeavePrivateEnvironment) \
|
||||
O(LeaveUnwindContext) \
|
||||
O(LeftShift) \
|
||||
O(LessThan) \
|
||||
|
|
|
@ -547,6 +547,7 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point)
|
|||
}
|
||||
|
||||
HANDLE_INSTRUCTION(Add);
|
||||
HANDLE_INSTRUCTION_WITHOUT_EXCEPTION_CHECK(AddPrivateName);
|
||||
HANDLE_INSTRUCTION(ArrayAppend);
|
||||
HANDLE_INSTRUCTION(AsyncIteratorClose);
|
||||
HANDLE_INSTRUCTION(BitwiseAnd);
|
||||
|
@ -561,6 +562,7 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point)
|
|||
HANDLE_INSTRUCTION(CopyObjectExcludingProperties);
|
||||
HANDLE_INSTRUCTION_WITHOUT_EXCEPTION_CHECK(CreateLexicalEnvironment);
|
||||
HANDLE_INSTRUCTION_WITHOUT_EXCEPTION_CHECK(CreateVariableEnvironment);
|
||||
HANDLE_INSTRUCTION_WITHOUT_EXCEPTION_CHECK(CreatePrivateEnvironment);
|
||||
HANDLE_INSTRUCTION(CreateVariable);
|
||||
HANDLE_INSTRUCTION(CreateRestParams);
|
||||
HANDLE_INSTRUCTION(CreateArguments);
|
||||
|
@ -601,6 +603,7 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point)
|
|||
HANDLE_INSTRUCTION(IteratorToArray);
|
||||
HANDLE_INSTRUCTION_WITHOUT_EXCEPTION_CHECK(LeaveFinally);
|
||||
HANDLE_INSTRUCTION_WITHOUT_EXCEPTION_CHECK(LeaveLexicalEnvironment);
|
||||
HANDLE_INSTRUCTION_WITHOUT_EXCEPTION_CHECK(LeavePrivateEnvironment);
|
||||
HANDLE_INSTRUCTION_WITHOUT_EXCEPTION_CHECK(LeaveUnwindContext);
|
||||
HANDLE_INSTRUCTION(LeftShift);
|
||||
HANDLE_INSTRUCTION(LessThan);
|
||||
|
@ -1140,6 +1143,12 @@ void NewPrimitiveArray::execute_impl(Bytecode::Interpreter& interpreter) const
|
|||
interpreter.set(dst(), array);
|
||||
}
|
||||
|
||||
void AddPrivateName::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
auto const& name = interpreter.current_executable().get_identifier(m_name);
|
||||
interpreter.vm().running_execution_context().private_environment->add_private_name(name);
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> ArrayAppend::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
return append(interpreter.vm(), interpreter.get(dst()), interpreter.get(src()), m_is_spread);
|
||||
|
@ -1266,6 +1275,13 @@ void CreateLexicalEnvironment::execute_impl(Bytecode::Interpreter& interpreter)
|
|||
running_execution_context.saved_lexical_environments.append(make_and_swap_envs(running_execution_context.lexical_environment));
|
||||
}
|
||||
|
||||
void CreatePrivateEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
auto& running_execution_context = interpreter.vm().running_execution_context();
|
||||
auto outer_private_environment = running_execution_context.private_environment;
|
||||
running_execution_context.private_environment = new_private_environment(interpreter.vm(), outer_private_environment);
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> CreateVariableEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
auto& running_execution_context = interpreter.vm().running_execution_context();
|
||||
|
@ -1754,6 +1770,12 @@ void LeaveLexicalEnvironment::execute_impl(Bytecode::Interpreter& interpreter) c
|
|||
running_execution_context.lexical_environment = running_execution_context.saved_lexical_environments.take_last();
|
||||
}
|
||||
|
||||
void LeavePrivateEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
auto& running_execution_context = interpreter.vm().running_execution_context();
|
||||
running_execution_context.private_environment = running_execution_context.private_environment->outer_environment();
|
||||
}
|
||||
|
||||
void LeaveUnwindContext::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
interpreter.leave_unwind_context();
|
||||
|
@ -1923,7 +1945,14 @@ ThrowCompletionOr<void> NewClass::execute_impl(Bytecode::Interpreter& interprete
|
|||
Value super_class;
|
||||
if (m_super_class.has_value())
|
||||
super_class = interpreter.get(m_super_class.value());
|
||||
interpreter.set(dst(), TRY(new_class(interpreter.vm(), super_class, m_class_expression, m_lhs_name)));
|
||||
Vector<Value> element_keys;
|
||||
for (size_t i = 0; i < m_element_keys_count; ++i) {
|
||||
Value element_key;
|
||||
if (m_element_keys[i].has_value())
|
||||
element_key = interpreter.get(m_element_keys[i].value());
|
||||
element_keys.append(element_key);
|
||||
}
|
||||
interpreter.set(dst(), TRY(new_class(interpreter.vm(), super_class, m_class_expression, m_lhs_name, element_keys)));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -1969,6 +1998,11 @@ ByteString NewPrimitiveArray::to_byte_string_impl(Bytecode::Executable const& ex
|
|||
format_value_list("elements"sv, elements()));
|
||||
}
|
||||
|
||||
ByteString AddPrivateName::to_byte_string_impl(Bytecode::Executable const& executable) const
|
||||
{
|
||||
return ByteString::formatted("AddPrivateName {}"sv, executable.identifier_table->get(m_name));
|
||||
}
|
||||
|
||||
ByteString ArrayAppend::to_byte_string_impl(Bytecode::Executable const& executable) const
|
||||
{
|
||||
return ByteString::formatted("Append {}, {}{}",
|
||||
|
@ -2052,6 +2086,11 @@ ByteString CreateLexicalEnvironment::to_byte_string_impl(Bytecode::Executable co
|
|||
return "CreateLexicalEnvironment"sv;
|
||||
}
|
||||
|
||||
ByteString CreatePrivateEnvironment::to_byte_string_impl(Bytecode::Executable const&) const
|
||||
{
|
||||
return "CreatePrivateEnvironment"sv;
|
||||
}
|
||||
|
||||
ByteString CreateVariableEnvironment::to_byte_string_impl(Bytecode::Executable const&) const
|
||||
{
|
||||
return "CreateVariableEnvironment"sv;
|
||||
|
@ -2421,6 +2460,11 @@ ByteString LeaveLexicalEnvironment::to_byte_string_impl(Bytecode::Executable con
|
|||
return "LeaveLexicalEnvironment"sv;
|
||||
}
|
||||
|
||||
ByteString LeavePrivateEnvironment::to_byte_string_impl(Bytecode::Executable const&) const
|
||||
{
|
||||
return "LeavePrivateEnvironment"sv;
|
||||
}
|
||||
|
||||
ByteString LeaveUnwindContext::to_byte_string_impl(Bytecode::Executable const&) const
|
||||
{
|
||||
return "LeaveUnwindContext";
|
||||
|
|
|
@ -350,6 +350,21 @@ private:
|
|||
Value m_elements[];
|
||||
};
|
||||
|
||||
class AddPrivateName final : public Instruction {
|
||||
public:
|
||||
explicit AddPrivateName(IdentifierTableIndex name)
|
||||
: Instruction(Type::AddPrivateName)
|
||||
, m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
void execute_impl(Bytecode::Interpreter&) const;
|
||||
ByteString to_byte_string_impl(Bytecode::Executable const&) const;
|
||||
|
||||
private:
|
||||
IdentifierTableIndex m_name;
|
||||
};
|
||||
|
||||
class ArrayAppend final : public Instruction {
|
||||
public:
|
||||
ArrayAppend(Operand dst, Operand src, bool is_spread)
|
||||
|
@ -471,6 +486,17 @@ private:
|
|||
u32 m_capacity { 0 };
|
||||
};
|
||||
|
||||
class CreatePrivateEnvironment final : public Instruction {
|
||||
public:
|
||||
explicit CreatePrivateEnvironment()
|
||||
: Instruction(Type::CreatePrivateEnvironment)
|
||||
{
|
||||
}
|
||||
|
||||
void execute_impl(Bytecode::Interpreter&) const;
|
||||
ByteString to_byte_string_impl(Bytecode::Executable const&) const;
|
||||
};
|
||||
|
||||
class EnterObjectEnvironment final : public Instruction {
|
||||
public:
|
||||
explicit EnterObjectEnvironment(Operand object)
|
||||
|
@ -1471,13 +1497,25 @@ private:
|
|||
|
||||
class NewClass final : public Instruction {
|
||||
public:
|
||||
explicit NewClass(Operand dst, Optional<Operand> super_class, ClassExpression const& class_expression, Optional<IdentifierTableIndex> lhs_name)
|
||||
static constexpr bool IsVariableLength = true;
|
||||
|
||||
explicit NewClass(Operand dst, Optional<Operand> super_class, ClassExpression const& class_expression, Optional<IdentifierTableIndex> lhs_name, ReadonlySpan<Optional<ScopedOperand>> elements_keys)
|
||||
: Instruction(Type::NewClass)
|
||||
, m_dst(dst)
|
||||
, m_super_class(super_class)
|
||||
, m_class_expression(class_expression)
|
||||
, m_lhs_name(lhs_name)
|
||||
, m_element_keys_count(elements_keys.size())
|
||||
{
|
||||
for (size_t i = 0; i < m_element_keys_count; i++) {
|
||||
if (elements_keys[i].has_value())
|
||||
m_element_keys[i] = elements_keys[i]->operand();
|
||||
}
|
||||
}
|
||||
|
||||
size_t length_impl() const
|
||||
{
|
||||
return round_up_to_power_of_two(alignof(void*), sizeof(*this) + sizeof(Optional<Operand>) * m_element_keys_count);
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
|
||||
|
@ -1493,6 +1531,8 @@ private:
|
|||
Optional<Operand> m_super_class;
|
||||
ClassExpression const& m_class_expression;
|
||||
Optional<IdentifierTableIndex> m_lhs_name;
|
||||
size_t m_element_keys_count { 0 };
|
||||
Optional<Operand> m_element_keys[];
|
||||
};
|
||||
|
||||
class NewFunction final : public Instruction {
|
||||
|
@ -1760,6 +1800,17 @@ public:
|
|||
ByteString to_byte_string_impl(Bytecode::Executable const&) const;
|
||||
};
|
||||
|
||||
class LeavePrivateEnvironment final : public Instruction {
|
||||
public:
|
||||
LeavePrivateEnvironment()
|
||||
: Instruction(Type::LeavePrivateEnvironment)
|
||||
{
|
||||
}
|
||||
|
||||
void execute_impl(Bytecode::Interpreter&) const;
|
||||
ByteString to_byte_string_impl(Bytecode::Executable const&) const;
|
||||
};
|
||||
|
||||
class LeaveUnwindContext final : public Instruction {
|
||||
public:
|
||||
LeaveUnwindContext()
|
||||
|
|
|
@ -34,7 +34,7 @@ PrivateName PrivateEnvironment::resolve_private_identifier(DeprecatedFlyString c
|
|||
return m_outer_environment->resolve_private_identifier(identifier);
|
||||
}
|
||||
|
||||
void PrivateEnvironment::add_private_name(Badge<ClassExpression>, DeprecatedFlyString description)
|
||||
void PrivateEnvironment::add_private_name(DeprecatedFlyString description)
|
||||
{
|
||||
if (!find_private_name(description).is_end())
|
||||
return;
|
||||
|
|
|
@ -35,7 +35,10 @@ class PrivateEnvironment : public Cell {
|
|||
public:
|
||||
PrivateName resolve_private_identifier(DeprecatedFlyString const& identifier) const;
|
||||
|
||||
void add_private_name(Badge<ClassExpression>, DeprecatedFlyString description);
|
||||
void add_private_name(DeprecatedFlyString description);
|
||||
|
||||
PrivateEnvironment* outer_environment() { return m_outer_environment; }
|
||||
PrivateEnvironment const* outer_environment() const { return m_outer_environment; }
|
||||
|
||||
private:
|
||||
explicit PrivateEnvironment(PrivateEnvironment* parent);
|
||||
|
|
Loading…
Add table
Reference in a new issue