Commit 197a3b25 authored by Hiroki Nakagawa's avatar Hiroki Nakagawa Committed by Commit Bot

Worker: Throw an ErrorEvent on a failure of module loading

This behavior is defined in the HTML spec:

  Step 13: "If the algorithm asynchronously completes with null, queue a task to
  fire an event named error at worker, and return."
  https://html.spec.whatwg.org/multipage/workers.html#worker-processing-model

An ErrorEvent is created on a worker thread, and passed to the main thread to
dispatch it on a worker object in a document context.

Bug: 843031
Change-Id: I1fd82cba1e02b1658bb2b556742f7a206ee754a7
Reviewed-on: https://chromium-review.googlesource.com/1058998
Commit-Queue: Hiroki Nakagawa <nhiroki@chromium.org>
Reviewed-by: default avatarKouhei Ueno <kouhei@chromium.org>
Cr-Commit-Position: refs/heads/master@{#558903}
parent 9df5e553
......@@ -52,4 +52,25 @@ promise_test(() => {
.then(e => assert_equals(e.data, 'TypeError'));
}, 'importScripts() on module worker should throw an exception.');
promise_test(() => {
const scriptURL = 'resources/non-existent-worker.js';
const worker = new Worker(scriptURL, { type: 'module' });
return new Promise(resolve => worker.onerror = resolve);
}, 'Worker construction for non-existent script should throw an exception.');
promise_test(() => {
const scriptURL = 'resources/static-import-non-existent-script-worker.js';
const worker = new Worker(scriptURL, { type: 'module' });
return new Promise(resolve => worker.onerror = resolve);
}, 'Static import for non-existent script should throw an exception.');
promise_test(() => {
const script_url = './non-existent-worker.js';
const worker = new Worker('resources/dynamic-import-given-url-worker.js',
{ type: 'module' });
worker.postMessage(script_url);
return new Promise(resolve => worker.onmessage = resolve)
.then(msg_event => assert_equals(msg_event.data, 'ERROR'));
}, 'Dynamic import for non-existent script should throw an exception.');
</script>
// Dynamically import the script URL sent by postMessage().
self.addEventListener('message', e => {
import(e.data);
import(e.data).catch(error_event => postMessage('ERROR'));
});
......@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/workers/worker_module_tree_client.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/events/error_event.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/script/module_script.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
......@@ -20,24 +21,29 @@ WorkerModuleTreeClient::WorkerModuleTreeClient(Modulator* modulator)
// https://html.spec.whatwg.org/multipage/workers.html#worker-processing-model
void WorkerModuleTreeClient::NotifyModuleTreeLoadFinished(
ModuleScript* module_script) {
auto* execution_context =
ExecutionContext::From(modulator_->GetScriptState());
if (!module_script) {
// Step 11: ... "If the algorithm asynchronously completes with null, queue
// a task to fire an event named error at worker, and abort these steps."
// ...
// TODO(nhiroki): Throw an ErrorEvent at the Worker object on the owner
// Document.
// Step 13: "If the algorithm asynchronously completes with null, queue
// a task to fire an event named error at worker, and return."
// This ErrorEvent object is just used for passing error information to a
// worker object on the parent context thread and not dispatched directly.
execution_context->ExceptionThrown(
ErrorEvent::Create("Failed to load a module script.",
SourceLocation::Capture(), nullptr /* world */));
return;
}
// Step 11: ... "Otherwise, continue the rest of these steps after the
// algorithm's asynchronous completion, with script being the asynchronous
// completion value." ...
// Step 13: "Otherwise, continue the rest of these steps after the algorithm's
// asynchronous completion, with script being the asynchronous completion
// value."
ScriptValue error = modulator_->ExecuteModule(
module_script, Modulator::CaptureEvalErrorFlag::kReport);
WorkerGlobalScope* global_scope =
ToWorkerGlobalScope(ExecutionContext::From(modulator_->GetScriptState()));
global_scope->ReportingProxy().DidEvaluateModuleScript(error.IsEmpty());
ToWorkerGlobalScope(execution_context)
->ReportingProxy()
.DidEvaluateModuleScript(error.IsEmpty());
}
void WorkerModuleTreeClient::Trace(blink::Visitor* visitor) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment