mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-06 08:10:02 +00: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
Notes:
sideshowbarker
2024-07-17 03:10:07 +09:00
Author: https://github.com/kalenikaliaksandr
Commit: 6fb1d9e516
Pull-request: https://github.com/SerenityOS/serenity/pull/24290
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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue