1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 10:28:10 +00:00

LibJS: Implement "throw"

You can now throw an expression to the nearest catcher! :^)

To support throwing arbitrary values, I added an Exception class that
sits as a wrapper around whatever is thrown. In the future it will be
a logical place to store a call stack.
This commit is contained in:
Andreas Kling 2020-03-24 22:03:50 +01:00
parent db024a9cb1
commit faddf3a1db
13 changed files with 160 additions and 7 deletions

View file

@ -480,7 +480,7 @@ Value Identifier::execute(Interpreter& interpreter) const
{
auto value = interpreter.get_variable(string());
if (value.is_undefined())
return interpreter.throw_exception(interpreter.heap().allocate<Error>("ReferenceError", String::format("'%s' not known", string().characters())));
return interpreter.throw_exception<Error>("ReferenceError", String::format("'%s' not known", string().characters()));
return value;
}
@ -762,13 +762,19 @@ void CatchClause::dump(int indent) const
body().dump(indent + 1);
}
void ThrowStatement::dump(int indent) const
{
ASTNode::dump(indent);
argument().dump(indent + 1);
}
Value TryStatement::execute(Interpreter& interpreter) const
{
interpreter.run(block(), {}, ScopeType::Try);
if (auto* exception = interpreter.exception()) {
if (m_handler) {
interpreter.clear_exception();
Vector<Argument> arguments { { m_handler->parameter(), Value(exception) } };
Vector<Argument> arguments { { m_handler->parameter(), exception->value() } };
interpreter.run(m_handler->body(), move(arguments));
}
}
@ -786,4 +792,10 @@ Value CatchClause::execute(Interpreter&) const
return {};
}
Value ThrowStatement::execute(Interpreter& interrupt) const
{
auto value = m_argument->execute(interrupt);
return interrupt.throw_exception(value);
}
}