LibJS: Convert push_execution_context() to ThrowCompletionOr

This commit is contained in:
Linus Groh 2021-11-14 12:20:49 +00:00
parent 7cdca08090
commit 57de5056b6
10 changed files with 20 additions and 21 deletions

View file

@ -57,8 +57,7 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e
execution_context.realm = &m_realm;
// FIXME: How do we know if we're in strict mode? Maybe the Bytecode::Block should know this?
// execution_context.is_strict_mode = ???;
vm().push_execution_context(execution_context, global_object());
VERIFY(!vm().exception());
MUST(vm().push_execution_context(execution_context, global_object()));
}
auto block = entry_point ?: &executable.basic_blocks.first();

View file

@ -58,8 +58,7 @@ void Interpreter::run(GlobalObject& global_object, const Program& program)
execution_context.variable_environment = &realm().global_environment();
execution_context.realm = &realm();
execution_context.is_strict_mode = program.is_strict_mode();
vm.push_execution_context(execution_context, global_object);
VERIFY(!vm.exception());
MUST(vm.push_execution_context(execution_context, global_object));
auto value = program.execute(*this, global_object);
vm.set_last_value(Badge<Interpreter> {}, value.value_or(js_undefined()));

View file

@ -525,7 +525,7 @@ ThrowCompletionOr<Value> perform_eval(Value x, GlobalObject& caller_realm, Calle
eval_context.variable_environment = variable_environment;
eval_context.lexical_environment = lexical_environment;
eval_context.private_environment = private_environment;
vm.push_execution_context(eval_context, eval_realm->global_object());
TRY(vm.push_execution_context(eval_context, eval_realm->global_object()));
ScopeGuard pop_guard = [&] {
vm.pop_execution_context();

View file

@ -51,7 +51,7 @@ ThrowCompletionOr<Value> await(GlobalObject& global_object, Value value)
result = vm.argument(0);
// c. Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
vm.push_execution_context(async_context, global_object);
TRY(vm.push_execution_context(async_context, global_object));
// d. Resume the suspended evaluation of asyncContext using NormalCompletion(value) as the result of the operation that suspended it.
// e. Assert: When we reach this step, asyncContext has already been removed from the execution context stack and prevContext is the currently running execution context.
@ -75,7 +75,7 @@ ThrowCompletionOr<Value> await(GlobalObject& global_object, Value value)
result = vm.argument(0);
// c. Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
vm.push_execution_context(async_context, global_object);
TRY(vm.push_execution_context(async_context, global_object));
// d. Resume the suspended evaluation of asyncContext using ThrowCompletion(reason) as the result of the operation that suspended it.
// e. Assert: When we reach this step, asyncContext has already been removed from the execution context stack and prevContext is the currently running execution context.

View file

@ -597,9 +597,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::prepare_for_ordinary_call(Exec
// FIXME: We don't have this concept yet.
// 12. Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
vm.push_execution_context(callee_context, global_object());
if (auto* exception = vm.exception())
return throw_completion(exception->value());
TRY(vm.push_execution_context(callee_context, global_object()));
// 13. NOTE: Any exception objects produced after this point are associated with calleeRealm.
// 14. Return calleeContext. (See NOTE above about how contexts are allocated on the C++ stack.)
@ -729,7 +727,9 @@ void ECMAScriptFunctionObject::async_block_start(PromiseCapability const& promis
});
// 4. Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
vm.push_execution_context(async_context, global_object());
auto push_result = vm.push_execution_context(async_context, global_object());
if (push_result.is_error())
return;
// 5. Resume the suspended evaluation of asyncContext. Let result be the value returned by the resumed computation.
auto result = vm.call(*execution_steps, async_context.this_value.is_empty() ? js_undefined() : async_context.this_value);

View file

@ -92,7 +92,7 @@ ThrowCompletionOr<Value> GeneratorObject::next_impl(VM& vm, GlobalObject& global
bytecode_interpreter->enter_frame(m_frame);
// Temporarily switch to the captured execution context
vm.push_execution_context(m_execution_context, global_object);
TRY(vm.push_execution_context(m_execution_context, global_object));
// Pretend that 'yield' returned the passed value, or threw
if (value_to_throw.has_value()) {

View file

@ -104,7 +104,7 @@ ThrowCompletionOr<Value> NativeFunction::internal_call(Value this_argument, Mark
// </8.> --------------------------------------------------------------------------
// 9. Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
vm.push_execution_context(callee_context, global_object);
TRY(vm.push_execution_context(callee_context, global_object));
// 10. Let result be the Completion Record that is the result of evaluating F in a manner that conforms to the specification of F. thisArgument is the this value, argumentsList provides the named parameters, and the NewTarget value is undefined.
auto result = call();
@ -168,7 +168,7 @@ ThrowCompletionOr<Object*> NativeFunction::internal_construct(MarkedValueList ar
// </8.> --------------------------------------------------------------------------
// 9. Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
vm.push_execution_context(callee_context, global_object);
TRY(vm.push_execution_context(callee_context, global_object));
// 10. Let result be the Completion Record that is the result of evaluating F in a manner that conforms to the specification of F. The this value is uninitialized, argumentsList provides the named parameters, and newTarget provides the NewTarget value.
auto result = construct(new_target);

View file

@ -105,7 +105,7 @@ ThrowCompletionOr<Value> perform_shadow_realm_eval(GlobalObject& global_object,
eval_context.is_strict_mode = strict_eval;
// 18. Push evalContext onto the execution context stack; evalContext is now the running execution context.
vm.push_execution_context(eval_context, eval_realm.global_object());
TRY(vm.push_execution_context(eval_context, eval_realm.global_object()));
// 19. Let result be EvalDeclarationInstantiation(body, varEnv, lexEnv, null, strictEval).
auto eval_result = eval_declaration_instantiation(vm, eval_realm.global_object(), program, variable_environment, lexical_environment, nullptr, strict_eval);
@ -168,7 +168,7 @@ ThrowCompletionOr<Value> shadow_realm_import_value(GlobalObject& global_object,
// NOTE: We don't support this concept yet.
// 9. Push evalContext onto the execution context stack; evalContext is now the running execution context.
vm.push_execution_context(eval_context, eval_realm.global_object());
TRY(vm.push_execution_context(eval_context, eval_realm.global_object()));
// 10. Perform ! HostImportModuleDynamically(null, specifierString, innerCapability).
// FIXME: We don't have this yet. We generally have very little support for modules and imports.

View file

@ -535,7 +535,8 @@ void VM::run_queued_promise_jobs()
if (m_execution_context_stack.is_empty()) {
static FlyString promise_execution_context_name = "(promise execution context)";
execution_context.function_name = promise_execution_context_name;
push_execution_context(execution_context, job->global_object());
// FIXME: Propagate potential failure
MUST(push_execution_context(execution_context, job->global_object()));
pushed_execution_context = true;
}

View file

@ -98,14 +98,14 @@ public:
#endif
}
void push_execution_context(ExecutionContext& context, GlobalObject& global_object)
ThrowCompletionOr<void> push_execution_context(ExecutionContext& context, GlobalObject& global_object)
{
VERIFY(!exception());
// Ensure we got some stack space left, so the next function call doesn't kill us.
if (did_reach_stack_space_limit())
throw_exception<Error>(global_object, ErrorType::CallStackSizeExceeded);
else
m_execution_context_stack.append(&context);
return throw_completion<Error>(global_object, ErrorType::CallStackSizeExceeded);
m_execution_context_stack.append(&context);
return {};
}
void pop_execution_context()