mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 12:38:12 +00:00
LibJS: Remove callerRealm from HostEnsureCanCompileStrings
This is a normative change in the ecma262 spec.
See: 2527be4
This commit is contained in:
parent
a0a4d169f4
commit
77ba3d3e3f
7 changed files with 79 additions and 87 deletions
|
@ -432,7 +432,7 @@ Completion CallExpression::execute(Interpreter& interpreter, GlobalObject& globa
|
||||||
&& callee_reference.name().as_string() == vm.names.eval.as_string()) {
|
&& callee_reference.name().as_string() == vm.names.eval.as_string()) {
|
||||||
|
|
||||||
auto script_value = arg_list.size() == 0 ? js_undefined() : arg_list[0];
|
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 perform_eval(global_object, script_value, vm.in_strict_mode() ? CallerMode::Strict : CallerMode::NonStrict, EvalMode::Direct);
|
||||||
}
|
}
|
||||||
|
|
||||||
return call(global_object, function, this_value, move(arg_list));
|
return call(global_object, function, this_value, move(arg_list));
|
||||||
|
|
|
@ -490,8 +490,8 @@ ThrowCompletionOr<Reference> make_super_property_reference(GlobalObject& global_
|
||||||
return Reference { bv, property_key, actual_this, strict };
|
return Reference { bv, property_key, actual_this, strict };
|
||||||
}
|
}
|
||||||
|
|
||||||
// 19.2.1.1 PerformEval ( x, callerRealm, strictCaller, direct ), https://tc39.es/ecma262/#sec-performeval
|
// 19.2.1.1 PerformEval ( x, strictCaller, direct ), https://tc39.es/ecma262/#sec-performeval
|
||||||
ThrowCompletionOr<Value> perform_eval(Value x, GlobalObject& caller_realm, CallerMode strict_caller, EvalMode direct)
|
ThrowCompletionOr<Value> perform_eval(GlobalObject& global_object, Value x, CallerMode strict_caller, EvalMode direct)
|
||||||
{
|
{
|
||||||
// 1. Assert: If direct is false, then strictCaller is also false.
|
// 1. Assert: If direct is false, then strictCaller is also false.
|
||||||
VERIFY(direct == EvalMode::Direct || strict_caller == CallerMode::NonStrict);
|
VERIFY(direct == EvalMode::Direct || strict_caller == CallerMode::NonStrict);
|
||||||
|
@ -500,27 +500,28 @@ ThrowCompletionOr<Value> perform_eval(Value x, GlobalObject& caller_realm, Calle
|
||||||
if (!x.is_string())
|
if (!x.is_string())
|
||||||
return x;
|
return x;
|
||||||
|
|
||||||
auto& vm = caller_realm.vm();
|
auto& vm = global_object.vm();
|
||||||
|
|
||||||
// 3. Let evalRealm be the current Realm Record.
|
// 3. Let evalRealm be the current Realm Record.
|
||||||
auto& eval_realm = *vm.running_execution_context().realm;
|
auto& eval_realm = *vm.running_execution_context().realm;
|
||||||
|
|
||||||
// 4. Perform ? HostEnsureCanCompileStrings(callerRealm, evalRealm).
|
// 4. NOTE: In the case of a direct eval, evalRealm is the realm of both the caller of eval and of the eval function itself.
|
||||||
TRY(vm.host_ensure_can_compile_strings(*caller_realm.associated_realm(), eval_realm));
|
// 5. Perform ? HostEnsureCanCompileStrings(evalRealm).
|
||||||
|
TRY(vm.host_ensure_can_compile_strings(eval_realm));
|
||||||
|
|
||||||
// 5. Let inFunction be false.
|
// 6. Let inFunction be false.
|
||||||
bool in_function = false;
|
bool in_function = false;
|
||||||
|
|
||||||
// 6. Let inMethod be false.
|
// 7. Let inMethod be false.
|
||||||
bool in_method = false;
|
bool in_method = false;
|
||||||
|
|
||||||
// 7. Let inDerivedConstructor be false.
|
// 8. Let inDerivedConstructor be false.
|
||||||
bool in_derived_constructor = false;
|
bool in_derived_constructor = false;
|
||||||
|
|
||||||
// 8. Let inClassFieldInitializer be false.
|
// 9. Let inClassFieldInitializer be false.
|
||||||
bool in_class_field_initializer = false;
|
bool in_class_field_initializer = false;
|
||||||
|
|
||||||
// 9. If direct is true, then
|
// 10. If direct is true, then
|
||||||
if (direct == EvalMode::Direct) {
|
if (direct == EvalMode::Direct) {
|
||||||
// a. Let thisEnvRec be GetThisEnvironment().
|
// a. Let thisEnvRec be GetThisEnvironment().
|
||||||
auto& this_environment_record = get_this_environment(vm);
|
auto& this_environment_record = get_this_environment(vm);
|
||||||
|
@ -551,7 +552,7 @@ ThrowCompletionOr<Value> perform_eval(Value x, GlobalObject& caller_realm, Calle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 10. Perform the following substeps in an implementation-defined order, possibly interleaving parsing and error detection:
|
// 11. Perform the following substeps in an implementation-defined order, possibly interleaving parsing and error detection:
|
||||||
// a. Let script be ParseText(StringToCodePoints(x), Script).
|
// a. Let script be ParseText(StringToCodePoints(x), Script).
|
||||||
// c. If script Contains ScriptBody is false, return undefined.
|
// c. If script Contains ScriptBody is false, return undefined.
|
||||||
// d. Let body be the ScriptBody of script.
|
// d. Let body be the ScriptBody of script.
|
||||||
|
@ -575,22 +576,22 @@ ThrowCompletionOr<Value> perform_eval(Value x, GlobalObject& caller_realm, Calle
|
||||||
// b. If script is a List of errors, throw a SyntaxError exception.
|
// b. If script is a List of errors, throw a SyntaxError exception.
|
||||||
if (parser.has_errors()) {
|
if (parser.has_errors()) {
|
||||||
auto& error = parser.errors()[0];
|
auto& error = parser.errors()[0];
|
||||||
return vm.throw_completion<SyntaxError>(caller_realm, error.to_string());
|
return vm.throw_completion<SyntaxError>(global_object, error.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto strict_eval = strict_caller == CallerMode::Strict;
|
auto strict_eval = strict_caller == CallerMode::Strict;
|
||||||
if (program->is_strict_mode())
|
if (program->is_strict_mode())
|
||||||
strict_eval = true;
|
strict_eval = true;
|
||||||
|
|
||||||
// 13. Let runningContext be the running execution context.
|
// 14. Let runningContext be the running execution context.
|
||||||
// 14. NOTE: If direct is true, runningContext will be the execution context that performed the direct eval. If direct is false, runningContext will be the execution context for the invocation of the eval function.
|
// 15. NOTE: If direct is true, runningContext will be the execution context that performed the direct eval. If direct is false, runningContext will be the execution context for the invocation of the eval function.
|
||||||
auto& running_context = vm.running_execution_context();
|
auto& running_context = vm.running_execution_context();
|
||||||
|
|
||||||
Environment* lexical_environment;
|
Environment* lexical_environment;
|
||||||
Environment* variable_environment;
|
Environment* variable_environment;
|
||||||
PrivateEnvironment* private_environment;
|
PrivateEnvironment* private_environment;
|
||||||
|
|
||||||
// 15. If direct is true, then
|
// 16. If direct is true, then
|
||||||
if (direct == EvalMode::Direct) {
|
if (direct == EvalMode::Direct) {
|
||||||
// a. Let lexEnv be NewDeclarativeEnvironment(runningContext's LexicalEnvironment).
|
// a. Let lexEnv be NewDeclarativeEnvironment(runningContext's LexicalEnvironment).
|
||||||
lexical_environment = new_declarative_environment(*running_context.lexical_environment);
|
lexical_environment = new_declarative_environment(*running_context.lexical_environment);
|
||||||
|
@ -601,7 +602,7 @@ ThrowCompletionOr<Value> perform_eval(Value x, GlobalObject& caller_realm, Calle
|
||||||
// c. Let privateEnv be runningContext's PrivateEnvironment.
|
// c. Let privateEnv be runningContext's PrivateEnvironment.
|
||||||
private_environment = running_context.private_environment;
|
private_environment = running_context.private_environment;
|
||||||
}
|
}
|
||||||
// 16. Else,
|
// 17. Else,
|
||||||
else {
|
else {
|
||||||
// a. Let lexEnv be NewDeclarativeEnvironment(evalRealm.[[GlobalEnv]]).
|
// a. Let lexEnv be NewDeclarativeEnvironment(evalRealm.[[GlobalEnv]]).
|
||||||
lexical_environment = new_declarative_environment(eval_realm.global_environment());
|
lexical_environment = new_declarative_environment(eval_realm.global_environment());
|
||||||
|
@ -613,7 +614,7 @@ ThrowCompletionOr<Value> perform_eval(Value x, GlobalObject& caller_realm, Calle
|
||||||
private_environment = nullptr;
|
private_environment = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 17. If strictEval is true, set varEnv to lexEnv.
|
// 18. If strictEval is true, set varEnv to lexEnv.
|
||||||
if (strict_eval)
|
if (strict_eval)
|
||||||
variable_environment = lexical_environment;
|
variable_environment = lexical_environment;
|
||||||
|
|
||||||
|
@ -624,50 +625,50 @@ ThrowCompletionOr<Value> perform_eval(Value x, GlobalObject& caller_realm, Calle
|
||||||
variable_environment->set_permanently_screwed_by_eval();
|
variable_environment->set_permanently_screwed_by_eval();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 18. If runningContext is not already suspended, suspend runningContext.
|
// 19. If runningContext is not already suspended, suspend runningContext.
|
||||||
// FIXME: We don't have this concept yet.
|
// FIXME: We don't have this concept yet.
|
||||||
|
|
||||||
// 19. Let evalContext be a new ECMAScript code execution context.
|
// 20. Let evalContext be a new ECMAScript code execution context.
|
||||||
ExecutionContext eval_context(vm.heap());
|
ExecutionContext eval_context(vm.heap());
|
||||||
|
|
||||||
// 20. Set evalContext's Function to null.
|
// 21. Set evalContext's Function to null.
|
||||||
// NOTE: This was done in the construction of eval_context.
|
// NOTE: This was done in the construction of eval_context.
|
||||||
|
|
||||||
// 21. Set evalContext's Realm to evalRealm.
|
// 22. Set evalContext's Realm to evalRealm.
|
||||||
eval_context.realm = &eval_realm;
|
eval_context.realm = &eval_realm;
|
||||||
|
|
||||||
// 22. Set evalContext's ScriptOrModule to runningContext's ScriptOrModule.
|
// 23. Set evalContext's ScriptOrModule to runningContext's ScriptOrModule.
|
||||||
eval_context.script_or_module = running_context.script_or_module;
|
eval_context.script_or_module = running_context.script_or_module;
|
||||||
|
|
||||||
// 23. Set evalContext's VariableEnvironment to varEnv.
|
// 24. Set evalContext's VariableEnvironment to varEnv.
|
||||||
eval_context.variable_environment = variable_environment;
|
eval_context.variable_environment = variable_environment;
|
||||||
|
|
||||||
// 24. Set evalContext's LexicalEnvironment to lexEnv.
|
// 25. Set evalContext's LexicalEnvironment to lexEnv.
|
||||||
eval_context.lexical_environment = lexical_environment;
|
eval_context.lexical_environment = lexical_environment;
|
||||||
|
|
||||||
// 25. Set evalContext's PrivateEnvironment to privateEnv.
|
// 26. Set evalContext's PrivateEnvironment to privateEnv.
|
||||||
eval_context.private_environment = private_environment;
|
eval_context.private_environment = private_environment;
|
||||||
|
|
||||||
// NOTE: This isn't in the spec, but we require it.
|
// NOTE: This isn't in the spec, but we require it.
|
||||||
eval_context.is_strict_mode = strict_eval;
|
eval_context.is_strict_mode = strict_eval;
|
||||||
|
|
||||||
// 26. Push evalContext onto the execution context stack; evalContext is now the running execution context.
|
// 27. Push evalContext onto the execution context stack; evalContext is now the running execution context.
|
||||||
TRY(vm.push_execution_context(eval_context, eval_realm.global_object()));
|
TRY(vm.push_execution_context(eval_context, eval_realm.global_object()));
|
||||||
|
|
||||||
// NOTE: We use a ScopeGuard to automatically pop the execution context when any of the `TRY`s below return a throw completion.
|
// NOTE: We use a ScopeGuard to automatically pop the execution context when any of the `TRY`s below return a throw completion.
|
||||||
ScopeGuard pop_guard = [&] {
|
ScopeGuard pop_guard = [&] {
|
||||||
// FIXME: 30. Suspend evalContext and remove it from the execution context stack.
|
// FIXME: 31. Suspend evalContext and remove it from the execution context stack.
|
||||||
|
|
||||||
// 31. Resume the context that is now on the top of the execution context stack as the running execution context.
|
// 32. Resume the context that is now on the top of the execution context stack as the running execution context.
|
||||||
vm.pop_execution_context();
|
vm.pop_execution_context();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 27. Let result be Completion(EvalDeclarationInstantiation(body, varEnv, lexEnv, privateEnv, strictEval)).
|
// 28. Let result be Completion(EvalDeclarationInstantiation(body, varEnv, lexEnv, privateEnv, strictEval)).
|
||||||
TRY(eval_declaration_instantiation(vm, eval_realm.global_object(), program, variable_environment, lexical_environment, private_environment, strict_eval));
|
TRY(eval_declaration_instantiation(vm, eval_realm.global_object(), program, variable_environment, lexical_environment, private_environment, strict_eval));
|
||||||
|
|
||||||
Optional<Value> eval_result;
|
Optional<Value> eval_result;
|
||||||
|
|
||||||
// 28. If result.[[Type]] is normal, then
|
// 29. If result.[[Type]] is normal, then
|
||||||
// a. Set result to the result of evaluating body.
|
// a. Set result to the result of evaluating body.
|
||||||
if (auto* bytecode_interpreter = Bytecode::Interpreter::current()) {
|
if (auto* bytecode_interpreter = Bytecode::Interpreter::current()) {
|
||||||
auto executable_result = Bytecode::Generator::generate(program);
|
auto executable_result = Bytecode::Generator::generate(program);
|
||||||
|
@ -684,14 +685,14 @@ ThrowCompletionOr<Value> perform_eval(Value x, GlobalObject& caller_realm, Calle
|
||||||
eval_result = {};
|
eval_result = {};
|
||||||
} else {
|
} else {
|
||||||
auto& ast_interpreter = vm.interpreter();
|
auto& ast_interpreter = vm.interpreter();
|
||||||
eval_result = TRY(program->execute(ast_interpreter, caller_realm));
|
eval_result = TRY(program->execute(ast_interpreter, global_object));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 29. If result.[[Type]] is normal and result.[[Value]] is empty, then
|
// 30. If result.[[Type]] is normal and result.[[Value]] is empty, then
|
||||||
// a. Set result to NormalCompletion(undefined).
|
// a. Set result to NormalCompletion(undefined).
|
||||||
// NOTE: Step 30 and 31 is handled by `pop_guard` above.
|
// NOTE: Step 31 and 32 is handled by `pop_guard` above.
|
||||||
// 32. Return ? result.
|
// 33. Return ? result.
|
||||||
// NOTE: Step 32 is also performed with each use of `TRY` above.
|
// NOTE: Step 33 is also performed with each use of `TRY` above.
|
||||||
return eval_result.value_or(js_undefined());
|
return eval_result.value_or(js_undefined());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ enum class EvalMode {
|
||||||
Direct,
|
Direct,
|
||||||
Indirect
|
Indirect
|
||||||
};
|
};
|
||||||
ThrowCompletionOr<Value> perform_eval(Value, GlobalObject&, CallerMode, EvalMode);
|
ThrowCompletionOr<Value> perform_eval(GlobalObject&, Value, CallerMode, EvalMode);
|
||||||
|
|
||||||
ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& global_object, Program const& program, Environment* variable_environment, Environment* lexical_environment, PrivateEnvironment* private_environment, bool strict);
|
ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& global_object, Program const& program, Environment* variable_environment, Environment* lexical_environment, PrivateEnvironment* private_environment, bool strict);
|
||||||
|
|
||||||
|
|
|
@ -40,22 +40,13 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
|
||||||
{
|
{
|
||||||
auto& vm = global_object.vm();
|
auto& vm = global_object.vm();
|
||||||
|
|
||||||
// 1. Assert: The execution context stack has at least two elements.
|
// 1. Let currentRealm be the current Realm Record.
|
||||||
VERIFY(vm.execution_context_stack().size() >= 2);
|
auto& current_realm = *vm.running_execution_context().realm;
|
||||||
|
|
||||||
// 2. Let callerContext be the second to top element of the execution context stack.
|
// 2. Perform ? HostEnsureCanCompileStrings(currentRealm).
|
||||||
auto& caller_context = *vm.execution_context_stack().at(vm.execution_context_stack().size() - 2);
|
TRY(vm.host_ensure_can_compile_strings(current_realm));
|
||||||
|
|
||||||
// 3. Let callerRealm be callerContext's Realm.
|
// 3. If newTarget is undefined, set newTarget to constructor.
|
||||||
auto& caller_realm = *caller_context.realm;
|
|
||||||
|
|
||||||
// 4. Let calleeRealm be the current Realm Record.
|
|
||||||
auto& callee_realm = *vm.running_execution_context().realm;
|
|
||||||
|
|
||||||
// 5. Perform ? HostEnsureCanCompileStrings(callerRealm, calleeRealm).
|
|
||||||
TRY(vm.host_ensure_can_compile_strings(caller_realm, callee_realm));
|
|
||||||
|
|
||||||
// 6. If newTarget is undefined, set newTarget to constructor.
|
|
||||||
if (new_target == nullptr)
|
if (new_target == nullptr)
|
||||||
new_target = &constructor;
|
new_target = &constructor;
|
||||||
|
|
||||||
|
@ -63,7 +54,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
|
||||||
Object* (GlobalObject::*fallback_prototype)() = nullptr;
|
Object* (GlobalObject::*fallback_prototype)() = nullptr;
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
// 7. If kind is normal, then
|
// 4. If kind is normal, then
|
||||||
case FunctionKind::Normal:
|
case FunctionKind::Normal:
|
||||||
// a. Let prefix be "function".
|
// a. Let prefix be "function".
|
||||||
prefix = "function"sv;
|
prefix = "function"sv;
|
||||||
|
@ -76,7 +67,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
|
||||||
fallback_prototype = &GlobalObject::function_prototype;
|
fallback_prototype = &GlobalObject::function_prototype;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// 8. Else if kind is generator, then
|
// 5. Else if kind is generator, then
|
||||||
case FunctionKind::Generator:
|
case FunctionKind::Generator:
|
||||||
// a. Let prefix be "function*".
|
// a. Let prefix be "function*".
|
||||||
prefix = "function*"sv;
|
prefix = "function*"sv;
|
||||||
|
@ -89,7 +80,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
|
||||||
fallback_prototype = &GlobalObject::generator_function_prototype;
|
fallback_prototype = &GlobalObject::generator_function_prototype;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// 9. Else if kind is async, then
|
// 6. Else if kind is async, then
|
||||||
case FunctionKind::Async:
|
case FunctionKind::Async:
|
||||||
// a. Let prefix be "async function".
|
// a. Let prefix be "async function".
|
||||||
prefix = "async function"sv;
|
prefix = "async function"sv;
|
||||||
|
@ -102,7 +93,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
|
||||||
fallback_prototype = &GlobalObject::async_function_prototype;
|
fallback_prototype = &GlobalObject::async_function_prototype;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// 10. Else,
|
// 7. Else,
|
||||||
case FunctionKind::AsyncGenerator:
|
case FunctionKind::AsyncGenerator:
|
||||||
// a. Assert: kind is asyncGenerator.
|
// a. Assert: kind is asyncGenerator.
|
||||||
|
|
||||||
|
@ -121,23 +112,23 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 11. Let argCount be the number of elements in args.
|
// 8. Let argCount be the number of elements in args.
|
||||||
auto arg_count = args.size();
|
auto arg_count = args.size();
|
||||||
|
|
||||||
// 12. Let P be the empty String.
|
// 9. Let P be the empty String.
|
||||||
String parameters_string = "";
|
String parameters_string = "";
|
||||||
|
|
||||||
Optional<Value> body_arg;
|
Optional<Value> body_arg;
|
||||||
|
|
||||||
// 13. If argCount = 0, let bodyArg be the empty String.
|
// 10. If argCount = 0, let bodyArg be the empty String.
|
||||||
if (arg_count == 0) {
|
if (arg_count == 0) {
|
||||||
// Optimization: Instead of creating a js_string() here, we just check if body_arg is empty in step 16.
|
// Optimization: Instead of creating a js_string() here, we just check if body_arg is empty in step 16.
|
||||||
}
|
}
|
||||||
// 14. Else if argCount = 1, let bodyArg be args[0].
|
// 11. Else if argCount = 1, let bodyArg be args[0].
|
||||||
else if (arg_count == 1) {
|
else if (arg_count == 1) {
|
||||||
body_arg = args[0];
|
body_arg = args[0];
|
||||||
}
|
}
|
||||||
// 15. Else,
|
// 12. Else,
|
||||||
else {
|
else {
|
||||||
// a. Assert: argCount > 1.
|
// a. Assert: argCount > 1.
|
||||||
VERIFY(arg_count > 1);
|
VERIFY(arg_count > 1);
|
||||||
|
@ -167,11 +158,11 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
|
||||||
body_arg = args[k];
|
body_arg = args[k];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 16. Let bodyString be the string-concatenation of 0x000A (LINE FEED), ? ToString(bodyArg), and 0x000A (LINE FEED).
|
// 13. Let bodyString be the string-concatenation of 0x000A (LINE FEED), ? ToString(bodyArg), and 0x000A (LINE FEED).
|
||||||
auto body_string = String::formatted("\n{}\n", body_arg.has_value() ? TRY(body_arg->to_string(global_object)) : "");
|
auto body_string = String::formatted("\n{}\n", body_arg.has_value() ? TRY(body_arg->to_string(global_object)) : "");
|
||||||
|
|
||||||
// 17. Let sourceString be the string-concatenation of prefix, " anonymous(", P, 0x000A (LINE FEED), ") {", bodyString, and "}".
|
// 14. Let sourceString be the string-concatenation of prefix, " anonymous(", P, 0x000A (LINE FEED), ") {", bodyString, and "}".
|
||||||
// 18. Let sourceText be StringToCodePoints(sourceString).
|
// 15. Let sourceText be StringToCodePoints(sourceString).
|
||||||
auto source_text = String::formatted("{} anonymous({}\n) {{{}}}", prefix, parameters_string, body_string);
|
auto source_text = String::formatted("{} anonymous({}\n) {{{}}}", prefix, parameters_string, body_string);
|
||||||
|
|
||||||
u8 parse_options = FunctionNodeParseOptions::CheckForFunctionAndName;
|
u8 parse_options = FunctionNodeParseOptions::CheckForFunctionAndName;
|
||||||
|
@ -180,18 +171,18 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
|
||||||
if (kind == FunctionKind::Generator || kind == FunctionKind::AsyncGenerator)
|
if (kind == FunctionKind::Generator || kind == FunctionKind::AsyncGenerator)
|
||||||
parse_options |= FunctionNodeParseOptions::IsGeneratorFunction;
|
parse_options |= FunctionNodeParseOptions::IsGeneratorFunction;
|
||||||
|
|
||||||
// 19. Let parameters be ParseText(StringToCodePoints(P), parameterSym).
|
// 16. Let parameters be ParseText(StringToCodePoints(P), parameterSym).
|
||||||
i32 function_length = 0;
|
i32 function_length = 0;
|
||||||
auto parameters_parser = Parser { Lexer { parameters_string } };
|
auto parameters_parser = Parser { Lexer { parameters_string } };
|
||||||
auto parameters = parameters_parser.parse_formal_parameters(function_length, parse_options);
|
auto parameters = parameters_parser.parse_formal_parameters(function_length, parse_options);
|
||||||
|
|
||||||
// 20. If parameters is a List of errors, throw a SyntaxError exception.
|
// 17. If parameters is a List of errors, throw a SyntaxError exception.
|
||||||
if (parameters_parser.has_errors()) {
|
if (parameters_parser.has_errors()) {
|
||||||
auto error = parameters_parser.errors()[0];
|
auto error = parameters_parser.errors()[0];
|
||||||
return vm.throw_completion<SyntaxError>(global_object, error.to_string());
|
return vm.throw_completion<SyntaxError>(global_object, error.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 21. Let body be ParseText(StringToCodePoints(bodyString), bodySym).
|
// 18. Let body be ParseText(StringToCodePoints(bodyString), bodySym).
|
||||||
bool contains_direct_call_to_eval = false;
|
bool contains_direct_call_to_eval = false;
|
||||||
auto body_parser = Parser { Lexer { body_string } };
|
auto body_parser = Parser { Lexer { body_string } };
|
||||||
// Set up some parser state to accept things like return await, and yield in the plain function body.
|
// Set up some parser state to accept things like return await, and yield in the plain function body.
|
||||||
|
@ -202,45 +193,45 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
|
||||||
body_parser.m_state.in_generator_function_context = true;
|
body_parser.m_state.in_generator_function_context = true;
|
||||||
(void)body_parser.parse_function_body(parameters, kind, contains_direct_call_to_eval);
|
(void)body_parser.parse_function_body(parameters, kind, contains_direct_call_to_eval);
|
||||||
|
|
||||||
// 22. If body is a List of errors, throw a SyntaxError exception.
|
// 19. If body is a List of errors, throw a SyntaxError exception.
|
||||||
if (body_parser.has_errors()) {
|
if (body_parser.has_errors()) {
|
||||||
auto error = body_parser.errors()[0];
|
auto error = body_parser.errors()[0];
|
||||||
return vm.throw_completion<SyntaxError>(global_object, error.to_string());
|
return vm.throw_completion<SyntaxError>(global_object, error.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 23. NOTE: The parameters and body are parsed separately to ensure that each is valid alone. For example, new Function("/*", "*/ ) {") is not legal.
|
// 20. NOTE: The parameters and body are parsed separately to ensure that each is valid alone. For example, new Function("/*", "*/ ) {") is not legal.
|
||||||
// 24. NOTE: If this step is reached, sourceText must have the syntax of exprSym (although the reverse implication does not hold). The purpose of the next two steps is to enforce any Early Error rules which apply to exprSym directly.
|
// 21. NOTE: If this step is reached, sourceText must have the syntax of exprSym (although the reverse implication does not hold). The purpose of the next two steps is to enforce any Early Error rules which apply to exprSym directly.
|
||||||
|
|
||||||
// 25. Let expr be ParseText(sourceText, exprSym).
|
// 22. Let expr be ParseText(sourceText, exprSym).
|
||||||
auto source_parser = Parser { Lexer { source_text } };
|
auto source_parser = Parser { Lexer { source_text } };
|
||||||
// This doesn't need any parse_options, it determines those & the function type based on the tokens that were found.
|
// This doesn't need any parse_options, it determines those & the function type based on the tokens that were found.
|
||||||
auto expr = source_parser.parse_function_node<FunctionExpression>();
|
auto expr = source_parser.parse_function_node<FunctionExpression>();
|
||||||
|
|
||||||
// 26. If expr is a List of errors, throw a SyntaxError exception.
|
// 23. If expr is a List of errors, throw a SyntaxError exception.
|
||||||
if (source_parser.has_errors()) {
|
if (source_parser.has_errors()) {
|
||||||
auto error = source_parser.errors()[0];
|
auto error = source_parser.errors()[0];
|
||||||
return vm.throw_completion<SyntaxError>(global_object, error.to_string());
|
return vm.throw_completion<SyntaxError>(global_object, error.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 27. Let proto be ? GetPrototypeFromConstructor(newTarget, fallbackProto).
|
// 24. Let proto be ? GetPrototypeFromConstructor(newTarget, fallbackProto).
|
||||||
auto* prototype = TRY(get_prototype_from_constructor(global_object, *new_target, fallback_prototype));
|
auto* prototype = TRY(get_prototype_from_constructor(global_object, *new_target, fallback_prototype));
|
||||||
|
|
||||||
// 28. Let realmF be the current Realm Record.
|
// 25. Let realmF be the current Realm Record.
|
||||||
auto* realm = vm.current_realm();
|
auto* realm = vm.current_realm();
|
||||||
|
|
||||||
// 29. Let env be realmF.[[GlobalEnv]].
|
// 26. Let env be realmF.[[GlobalEnv]].
|
||||||
auto* environment = &realm->global_environment();
|
auto* environment = &realm->global_environment();
|
||||||
|
|
||||||
// 30. Let privateEnv be null.
|
// 27. Let privateEnv be null.
|
||||||
PrivateEnvironment* private_environment = nullptr;
|
PrivateEnvironment* private_environment = nullptr;
|
||||||
|
|
||||||
// 31. Let F be OrdinaryFunctionCreate(proto, sourceText, parameters, body, non-lexical-this, env, privateEnv).
|
// 28. Let F be OrdinaryFunctionCreate(proto, sourceText, parameters, body, non-lexical-this, env, privateEnv).
|
||||||
auto* function = ECMAScriptFunctionObject::create(global_object, "anonymous", *prototype, move(source_text), expr->body(), expr->parameters(), expr->function_length(), environment, private_environment, expr->kind(), expr->is_strict_mode(), expr->might_need_arguments_object(), contains_direct_call_to_eval);
|
auto* function = ECMAScriptFunctionObject::create(global_object, "anonymous", *prototype, move(source_text), expr->body(), expr->parameters(), expr->function_length(), environment, private_environment, expr->kind(), expr->is_strict_mode(), expr->might_need_arguments_object(), contains_direct_call_to_eval);
|
||||||
|
|
||||||
// FIXME: Remove the name argument from create() and do this instead.
|
// FIXME: Remove the name argument from create() and do this instead.
|
||||||
// 32. Perform SetFunctionName(F, "anonymous").
|
// 29. Perform SetFunctionName(F, "anonymous").
|
||||||
|
|
||||||
// 33. If kind is generator, then
|
// 30. If kind is generator, then
|
||||||
if (kind == FunctionKind::Generator) {
|
if (kind == FunctionKind::Generator) {
|
||||||
// a. Let prototype be OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%).
|
// a. Let prototype be OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%).
|
||||||
prototype = Object::create(global_object, global_object.generator_function_prototype_prototype());
|
prototype = Object::create(global_object, global_object.generator_function_prototype_prototype());
|
||||||
|
@ -248,7 +239,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
|
||||||
// b. Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
|
// b. Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
|
||||||
function->define_direct_property(vm.names.prototype, prototype, Attribute::Writable);
|
function->define_direct_property(vm.names.prototype, prototype, Attribute::Writable);
|
||||||
}
|
}
|
||||||
// 34. Else if kind is asyncGenerator, then
|
// 31. Else if kind is asyncGenerator, then
|
||||||
else if (kind == FunctionKind::AsyncGenerator) {
|
else if (kind == FunctionKind::AsyncGenerator) {
|
||||||
// a. Let prototype be OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%).
|
// a. Let prototype be OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%).
|
||||||
prototype = Object::create(global_object, global_object.async_generator_function_prototype_prototype());
|
prototype = Object::create(global_object, global_object.async_generator_function_prototype_prototype());
|
||||||
|
@ -256,7 +247,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
|
||||||
// b. Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
|
// b. Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
|
||||||
function->define_direct_property(vm.names.prototype, prototype, Attribute::Writable);
|
function->define_direct_property(vm.names.prototype, prototype, Attribute::Writable);
|
||||||
}
|
}
|
||||||
// 35. Else if kind is normal, perform MakeConstructor(F).
|
// 32. Else if kind is normal, perform MakeConstructor(F).
|
||||||
else if (kind == FunctionKind::Normal) {
|
else if (kind == FunctionKind::Normal) {
|
||||||
// FIXME: Implement MakeConstructor
|
// FIXME: Implement MakeConstructor
|
||||||
prototype = Object::create(global_object, global_object.object_prototype());
|
prototype = Object::create(global_object, global_object.object_prototype());
|
||||||
|
@ -264,9 +255,9 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
|
||||||
function->define_direct_property(vm.names.prototype, prototype, Attribute::Writable);
|
function->define_direct_property(vm.names.prototype, prototype, Attribute::Writable);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 36. NOTE: Functions whose kind is async are not constructible and do not have a [[Construct]] internal method or a "prototype" property.
|
// 33. NOTE: Functions whose kind is async are not constructible and do not have a [[Construct]] internal method or a "prototype" property.
|
||||||
|
|
||||||
// 37. Return F.
|
// 34. Return F.
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -489,7 +489,7 @@ JS_DEFINE_NATIVE_FUNCTION(GlobalObject::parse_int)
|
||||||
// 19.2.1 eval ( x ), https://tc39.es/ecma262/#sec-eval-x
|
// 19.2.1 eval ( x ), https://tc39.es/ecma262/#sec-eval-x
|
||||||
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::eval)
|
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::eval)
|
||||||
{
|
{
|
||||||
return perform_eval(vm.argument(0), global_object, CallerMode::NonStrict, EvalMode::Indirect);
|
return perform_eval(global_object, vm.argument(0), CallerMode::NonStrict, EvalMode::Indirect);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 19.2.6.1.1 Encode ( string, unescapedSet ), https://tc39.es/ecma262/#sec-encode
|
// 19.2.6.1.1 Encode ( string, unescapedSet ), https://tc39.es/ecma262/#sec-encode
|
||||||
|
|
|
@ -132,9 +132,9 @@ VM::VM(OwnPtr<CustomData> custom_data)
|
||||||
};
|
};
|
||||||
|
|
||||||
// 19.2.1.2 HostEnsureCanCompileStrings ( callerRealm, calleeRealm ), https://tc39.es/ecma262/#sec-hostensurecancompilestrings
|
// 19.2.1.2 HostEnsureCanCompileStrings ( callerRealm, calleeRealm ), https://tc39.es/ecma262/#sec-hostensurecancompilestrings
|
||||||
host_ensure_can_compile_strings = [](Realm&, Realm&) -> ThrowCompletionOr<void> {
|
host_ensure_can_compile_strings = [](Realm&) -> ThrowCompletionOr<void> {
|
||||||
// The host-defined abstract operation HostEnsureCanCompileStrings takes arguments callerRealm (a Realm Record) and calleeRealm (a Realm Record)
|
// The host-defined abstract operation HostEnsureCanCompileStrings takes argument calleeRealm (a Realm Record)
|
||||||
// and returns either a normal completion containing unused or an abrupt completion.
|
// and returns either a normal completion containing unused or a throw completion.
|
||||||
// It allows host environments to block certain ECMAScript functions which allow developers to compile strings into ECMAScript code.
|
// It allows host environments to block certain ECMAScript functions which allow developers to compile strings into ECMAScript code.
|
||||||
// An implementation of HostEnsureCanCompileStrings must conform to the following requirements:
|
// An implementation of HostEnsureCanCompileStrings must conform to the following requirements:
|
||||||
// - If the returned Completion Record is a normal completion, it must be a normal completion containing unused.
|
// - If the returned Completion Record is a normal completion, it must be a normal completion containing unused.
|
||||||
|
|
|
@ -234,7 +234,7 @@ public:
|
||||||
Function<void(Function<ThrowCompletionOr<Value>()>, Realm*)> host_enqueue_promise_job;
|
Function<void(Function<ThrowCompletionOr<Value>()>, Realm*)> host_enqueue_promise_job;
|
||||||
Function<JobCallback(FunctionObject&)> host_make_job_callback;
|
Function<JobCallback(FunctionObject&)> host_make_job_callback;
|
||||||
Function<ThrowCompletionOr<HostResizeArrayBufferResult>(GlobalObject&, size_t)> host_resize_array_buffer;
|
Function<ThrowCompletionOr<HostResizeArrayBufferResult>(GlobalObject&, size_t)> host_resize_array_buffer;
|
||||||
Function<ThrowCompletionOr<void>(Realm&, Realm&)> host_ensure_can_compile_strings;
|
Function<ThrowCompletionOr<void>(Realm&)> host_ensure_can_compile_strings;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit VM(OwnPtr<CustomData>);
|
explicit VM(OwnPtr<CustomData>);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue