mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-24 10:22:05 -05:00
LibWeb: Implement the "error to rethrow" mechanism in HTML::Script
This allows JS module loads to fail and throw without crashing the WebContent process due to a TODO() assertion.
This commit is contained in:
parent
2959c2f2eb
commit
819fb39a87
6 changed files with 47 additions and 22 deletions
|
@ -42,8 +42,9 @@ JS::NonnullGCPtr<ClassicScript> ClassicScript::create(DeprecatedString filename,
|
|||
// 8. Set script's muted errors to muted errors.
|
||||
script->m_muted_errors = muted_errors;
|
||||
|
||||
// FIXME: 9. Set script's parse error and error to rethrow to null.
|
||||
// NOTE: Error to rethrow was set to null in the construction of ClassicScript. We do not have parse error as it would currently go unused.
|
||||
// 9. Set script's parse error and error to rethrow to null.
|
||||
script->set_parse_error(JS::js_null());
|
||||
script->set_error_to_rethrow(JS::js_null());
|
||||
|
||||
// 10. Let result be ParseScript(source, settings's Realm, script).
|
||||
auto parse_timer = Core::ElapsedTimer::start_new();
|
||||
|
@ -55,9 +56,9 @@ JS::NonnullGCPtr<ClassicScript> ClassicScript::create(DeprecatedString filename,
|
|||
auto& parse_error = result.error().first();
|
||||
dbgln_if(HTML_SCRIPT_DEBUG, "ClassicScript: Failed to parse: {}", parse_error.to_deprecated_string());
|
||||
|
||||
// FIXME: 1. Set script's parse error and its error to rethrow to result[0].
|
||||
// We do not have parse error as it would currently go unused.
|
||||
script->m_error_to_rethrow = parse_error;
|
||||
// 1. Set script's parse error and its error to rethrow to result[0].
|
||||
script->set_parse_error(JS::SyntaxError::create(environment_settings_object.realm(), parse_error.to_string().release_value_but_fixme_should_propagate_errors()));
|
||||
script->set_error_to_rethrow(script->parse_error());
|
||||
|
||||
// 2. Return script.
|
||||
return script;
|
||||
|
@ -73,8 +74,6 @@ JS::NonnullGCPtr<ClassicScript> ClassicScript::create(DeprecatedString filename,
|
|||
// https://html.spec.whatwg.org/multipage/webappapis.html#run-a-classic-script
|
||||
JS::Completion ClassicScript::run(RethrowErrors rethrow_errors, JS::GCPtr<JS::Environment> lexical_environment_override)
|
||||
{
|
||||
auto& vm = settings_object().realm().vm();
|
||||
|
||||
// 1. Let settings be the settings object of script.
|
||||
auto& settings = settings_object();
|
||||
|
||||
|
@ -89,8 +88,8 @@ JS::Completion ClassicScript::run(RethrowErrors rethrow_errors, JS::GCPtr<JS::En
|
|||
JS::Completion evaluation_status;
|
||||
|
||||
// 5. If script's error to rethrow is not null, then set evaluationStatus to Completion { [[Type]]: throw, [[Value]]: script's error to rethrow, [[Target]]: empty }.
|
||||
if (m_error_to_rethrow.has_value()) {
|
||||
evaluation_status = vm.throw_completion<JS::SyntaxError>(TRY_OR_THROW_OOM(vm, m_error_to_rethrow.value().to_string()));
|
||||
if (!error_to_rethrow().is_null()) {
|
||||
evaluation_status = JS::Completion { JS::Completion::Type::Throw, error_to_rethrow(), {} };
|
||||
} else {
|
||||
auto timer = Core::ElapsedTimer::start_new();
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@ private:
|
|||
|
||||
JS::GCPtr<JS::Script> m_script_record;
|
||||
MutedErrors m_muted_errors { MutedErrors::No };
|
||||
Optional<JS::ParserError> m_error_to_rethrow;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -619,9 +619,10 @@ void fetch_descendants_of_and_link_a_module_script(JavaScriptModuleScript& modul
|
|||
// 2. Perform record.Link().
|
||||
auto linking_result = const_cast<JS::SourceTextModule&>(record).link(result->vm());
|
||||
|
||||
// TODO: If this throws an exception, set result's error to rethrow to that exception.
|
||||
if (linking_result.is_error())
|
||||
TODO();
|
||||
// If this throws an exception, set result's error to rethrow to that exception.
|
||||
if (linking_result.is_throw_completion()) {
|
||||
result->set_error_to_rethrow(linking_result.release_error().value().value());
|
||||
}
|
||||
} else {
|
||||
// FIXME: 4. Otherwise, set result's error to rethrow to parse error.
|
||||
TODO();
|
||||
|
|
|
@ -49,7 +49,8 @@ WebIDL::ExceptionOr<JS::GCPtr<JavaScriptModuleScript>> JavaScriptModuleScript::c
|
|||
// FIXME: 5. Set script's fetch options to options.
|
||||
|
||||
// 6. Set script's parse error and error to rethrow to null.
|
||||
// NOTE: Parse error and error to rethrow were set to null in the construction of Script.
|
||||
script->set_parse_error(JS::js_null());
|
||||
script->set_error_to_rethrow(JS::js_null());
|
||||
|
||||
// 7. Let result be ParseModule(source, settings's Realm, script).
|
||||
auto result = JS::SourceTextModule::parse(source, settings_object.realm(), filename.view(), script);
|
||||
|
@ -59,7 +60,8 @@ WebIDL::ExceptionOr<JS::GCPtr<JavaScriptModuleScript>> JavaScriptModuleScript::c
|
|||
auto& parse_error = result.error().first();
|
||||
dbgln("JavaScriptModuleScript: Failed to parse: {}", parse_error.to_deprecated_string());
|
||||
|
||||
// FIXME: 1. Set script's parse error to result[0].
|
||||
// 1. Set script's parse error to result[0].
|
||||
script->set_parse_error(JS::SyntaxError::create(settings_object.realm(), parse_error.to_string().release_value_but_fixme_should_propagate_errors()));
|
||||
|
||||
// 2. Return script.
|
||||
return script;
|
||||
|
@ -123,12 +125,16 @@ JS::Promise* JavaScriptModuleScript::run(PreventErrorReporting)
|
|||
// 4. Let evaluationPromise be null.
|
||||
JS::Promise* evaluation_promise = nullptr;
|
||||
|
||||
// FIXME: 5. If script's error to rethrow is not null, then set evaluationPromise to a promise rejected with script's error to rethrow.
|
||||
|
||||
// 5. If script's error to rethrow is not null, then set evaluationPromise to a promise rejected with script's error to rethrow.
|
||||
if (!error_to_rethrow().is_null()) {
|
||||
evaluation_promise = JS::Promise::create(settings.realm());
|
||||
evaluation_promise->reject(error_to_rethrow());
|
||||
}
|
||||
// 6. Otherwise:
|
||||
if (m_record) {
|
||||
else {
|
||||
// 1. Let record be script's record.
|
||||
auto record = m_record;
|
||||
VERIFY(record);
|
||||
|
||||
auto interpreter = JS::Interpreter::create_with_existing_realm(settings.realm());
|
||||
JS::VM::InterpreterExecutionScope scope(*interpreter);
|
||||
|
@ -147,8 +153,6 @@ JS::Promise* JavaScriptModuleScript::run(PreventErrorReporting)
|
|||
} else {
|
||||
evaluation_promise = elevation_promise_or_error.value();
|
||||
}
|
||||
} else {
|
||||
TODO();
|
||||
}
|
||||
|
||||
// FIXME: 7. If preventErrorReporting is false, then upon rejection of evaluationPromise with reason, report the exception given by reason for script.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021-2023, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -23,4 +23,12 @@ void Script::visit_host_defined_self(JS::Cell::Visitor& visitor)
|
|||
visitor.visit(this);
|
||||
}
|
||||
|
||||
void Script::visit_edges(Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_settings_object);
|
||||
visitor.visit(m_parse_error);
|
||||
visitor.visit(m_error_to_rethrow);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021-2023, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -27,15 +27,29 @@ public:
|
|||
|
||||
EnvironmentSettingsObject& settings_object() { return m_settings_object; }
|
||||
|
||||
[[nodiscard]] JS::Value error_to_rethrow() const { return m_error_to_rethrow; }
|
||||
void set_error_to_rethrow(JS::Value value) { m_error_to_rethrow = value; }
|
||||
|
||||
[[nodiscard]] JS::Value parse_error() const { return m_parse_error; }
|
||||
void set_parse_error(JS::Value value) { m_parse_error = value; }
|
||||
|
||||
protected:
|
||||
Script(AK::URL base_url, DeprecatedString filename, EnvironmentSettingsObject& environment_settings_object);
|
||||
|
||||
virtual void visit_edges(Visitor&) override;
|
||||
|
||||
private:
|
||||
virtual void visit_host_defined_self(JS::Cell::Visitor&) override;
|
||||
|
||||
AK::URL m_base_url;
|
||||
DeprecatedString m_filename;
|
||||
JS::NonnullGCPtr<EnvironmentSettingsObject> m_settings_object;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-parse-error
|
||||
JS::Value m_parse_error;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-error-to-rethrow
|
||||
JS::Value m_error_to_rethrow;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue