Просмотр исходного кода

LibJS: Convert perform_eval to ThrowCompletionOr

Idan Horowitz 3 лет назад
Родитель
Сommit
1da8faebf5

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

@@ -243,7 +243,7 @@ Value CallExpression::execute(Interpreter& interpreter, GlobalObject& global_obj
         && callee_reference.name().as_string() == vm.names.eval.as_string()) {
 
         auto script_value = arg_list.size() == 0 ? js_undefined() : arg_list[0];
-        return perform_eval(script_value, global_object, vm.in_strict_mode() ? CallerMode::Strict : CallerMode::NonStrict, EvalMode::Direct);
+        return TRY_OR_DISCARD(perform_eval(script_value, global_object, vm.in_strict_mode() ? CallerMode::Strict : CallerMode::NonStrict, EvalMode::Direct));
     }
 
     return vm.call(function, this_value, move(arg_list));

+ 12 - 6
Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp

@@ -407,7 +407,7 @@ ThrowCompletionOr<Reference> make_super_property_reference(GlobalObject& global_
 }
 
 // 19.2.1.1 PerformEval ( x, callerRealm, strictCaller, direct ), https://tc39.es/ecma262/#sec-performeval
-Value perform_eval(Value x, GlobalObject& caller_realm, CallerMode strict_caller, EvalMode direct)
+ThrowCompletionOr<Value> perform_eval(Value x, GlobalObject& caller_realm, CallerMode strict_caller, EvalMode direct)
 {
     VERIFY(direct == EvalMode::Direct || strict_caller == CallerMode::NonStrict);
     if (!x.is_string())
@@ -420,17 +420,23 @@ Value perform_eval(Value x, GlobalObject& caller_realm, CallerMode strict_caller
 
     if (parser.has_errors()) {
         auto& error = parser.errors()[0];
-        vm.throw_exception<SyntaxError>(caller_realm, error.to_string());
-        return {};
+        return vm.throw_completion<SyntaxError>(caller_realm, error.to_string());
     }
 
     auto& interpreter = vm.interpreter();
-    if (direct == EvalMode::Direct)
-        return interpreter.execute_statement(caller_realm, program).value_or(js_undefined());
+    if (direct == EvalMode::Direct) {
+        auto result = interpreter.execute_statement(caller_realm, program).value_or(js_undefined());
+        if (auto* exception = vm.exception())
+            return throw_completion(exception->value());
+        return result;
+    }
 
     TemporaryChange scope_change(vm.running_execution_context().lexical_environment, static_cast<Environment*>(&interpreter.realm().global_environment()));
     TemporaryChange scope_change_strict(vm.running_execution_context().is_strict_mode, strict_caller == CallerMode::Strict);
-    return interpreter.execute_statement(caller_realm, program).value_or(js_undefined());
+    auto result = interpreter.execute_statement(caller_realm, program).value_or(js_undefined());
+    if (auto* exception = vm.exception())
+        return throw_completion(exception->value());
+    return result;
 }
 
 // 10.4.4.6 CreateUnmappedArgumentsObject ( argumentsList ), https://tc39.es/ecma262/#sec-createunmappedargumentsobject

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

@@ -40,7 +40,7 @@ enum class EvalMode {
     Direct,
     Indirect
 };
-Value perform_eval(Value, GlobalObject&, CallerMode, EvalMode);
+ThrowCompletionOr<Value> perform_eval(Value, GlobalObject&, CallerMode, EvalMode);
 
 // 10.1.13 OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ), https://tc39.es/ecma262/#sec-ordinarycreatefromconstructor
 template<typename T, typename... Args>

+ 1 - 1
Userland/Libraries/LibJS/Runtime/GlobalObject.cpp

@@ -430,7 +430,7 @@ JS_DEFINE_NATIVE_FUNCTION(GlobalObject::parse_int)
 // 19.2.1 eval ( x ), https://tc39.es/ecma262/#sec-eval-x
 JS_DEFINE_NATIVE_FUNCTION(GlobalObject::eval)
 {
-    return perform_eval(vm.argument(0), global_object, CallerMode::NonStrict, EvalMode::Indirect);
+    return TRY_OR_DISCARD(perform_eval(vm.argument(0), global_object, CallerMode::NonStrict, EvalMode::Indirect));
 }
 
 // 19.2.6.1.1 Encode ( string, unescapedSet ), https://tc39.es/ecma262/#sec-encode