Forráskód Böngészése

LibJS: Implement and use the InitializeBoundName AO

Linus Groh 3 éve
szülő
commit
df931e6a83

+ 1 - 6
Userland/Libraries/LibJS/AST.cpp

@@ -1479,12 +1479,7 @@ Value ClassDeclaration::execute(Interpreter& interpreter, GlobalObject& global_o
     VERIFY(!name.is_empty());
     auto class_constructor = TRY_OR_DISCARD(m_class_expression->class_definition_evaluation(interpreter, global_object, name, name));
 
-    if (interpreter.lexical_environment()) {
-        MUST(interpreter.lexical_environment()->initialize_binding(global_object, name, class_constructor));
-    } else {
-        auto reference = interpreter.vm().resolve_binding(name);
-        TRY_OR_DISCARD(reference.put_value(global_object, class_constructor));
-    }
+    TRY_OR_DISCARD(initialize_bound_name(global_object, name, class_constructor, interpreter.lexical_environment()));
 
     return {};
 }

+ 25 - 0
Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp

@@ -199,6 +199,31 @@ ThrowCompletionOr<Realm*> get_function_realm(GlobalObject& global_object, Functi
     return vm.current_realm();
 }
 
+// 8.5.2.1 InitializeBoundName ( name, value, environment ), 8.5.2.1 InitializeBoundName ( name, value, environment )
+ThrowCompletionOr<void> initialize_bound_name(GlobalObject& global_object, FlyString const& name, Value value, Environment* environment)
+{
+    auto& vm = global_object.vm();
+
+    // 1. If environment is not undefined, then
+    if (environment) {
+        // a. Perform environment.InitializeBinding(name, value).
+        MUST(environment->initialize_binding(global_object, name, value));
+
+        // b. Return NormalCompletion(undefined).
+        return {};
+    }
+    // 2. Else,
+    else {
+        // a. Let lhs be ResolveBinding(name).
+        auto lhs = vm.resolve_binding(name);
+
+        // b. Return ? PutValue(lhs, value).
+        return TRY(lhs.put_value(global_object, value));
+    }
+
+    VERIFY_NOT_REACHED();
+}
+
 // 10.1.6.2 IsCompatiblePropertyDescriptor ( Extensible, Desc, Current ), https://tc39.es/ecma262/#sec-iscompatiblepropertydescriptor
 bool is_compatible_property_descriptor(bool extensible, PropertyDescriptor const& descriptor, Optional<PropertyDescriptor> const& current)
 {

+ 1 - 0
Userland/Libraries/LibJS/Runtime/AbstractOperations.h

@@ -30,6 +30,7 @@ ThrowCompletionOr<size_t> length_of_array_like(GlobalObject&, Object const&);
 ThrowCompletionOr<MarkedValueList> create_list_from_array_like(GlobalObject&, Value, Function<ThrowCompletionOr<void>(Value)> = {});
 ThrowCompletionOr<FunctionObject*> species_constructor(GlobalObject&, Object const&, FunctionObject& default_constructor);
 ThrowCompletionOr<Realm*> get_function_realm(GlobalObject&, FunctionObject const&);
+ThrowCompletionOr<void> initialize_bound_name(GlobalObject&, FlyString const&, Value, Environment*);
 bool is_compatible_property_descriptor(bool extensible, PropertyDescriptor const&, Optional<PropertyDescriptor> const& current);
 bool validate_and_apply_property_descriptor(Object*, PropertyKey const&, bool extensible, PropertyDescriptor const&, Optional<PropertyDescriptor> const& current);
 ThrowCompletionOr<Object*> get_prototype_from_constructor(GlobalObject&, FunctionObject const& constructor, Object* (GlobalObject::*intrinsic_default_prototype)());

+ 1 - 7
Userland/Libraries/LibJS/Runtime/VM.cpp

@@ -180,13 +180,7 @@ ThrowCompletionOr<void> VM::binding_initialization(FlyString const& target, Valu
 {
     // 1. Let name be StringValue of Identifier.
     // 2. Return ? InitializeBoundName(name, value, environment).
-    // TODO: Use the right AO here
-    if (environment) {
-        MUST(environment->initialize_binding(global_object, target, value));
-        return {};
-    }
-    auto reference = resolve_binding(target);
-    return reference.put_value(global_object, value);
+    return initialize_bound_name(global_object, target, value, environment);
 }
 
 // 8.5.2 Runtime Semantics: BindingInitialization, https://tc39.es/ecma262/#sec-runtime-semantics-bindinginitialization