1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-03 04:48:52 -05:00

fix: align DedicatedWorkerGlobalScope event handlers to spec (#11353)

This commit is contained in:
Andreu Botella 2021-07-10 23:32:10 +02:00 committed by GitHub
parent 67c9937e66
commit eea6000ef6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 81 additions and 32 deletions

View file

@ -1155,6 +1155,11 @@ itest!(error_import_map_unable_to_load {
exit_code: 1,
});
itest!(worker_event_handler_test {
args: "run --quiet --reload --allow-read worker_event_handler_test.js",
output: "worker_event_handler_test.js.out",
});
#[test]
fn no_validate_asm() {
let output = util::deno_cmd()

View file

@ -0,0 +1,5 @@
const w = new Worker(
new URL("./workers/worker_event_handlers.js", import.meta.url).href,
{ type: "module" },
);
w.postMessage({});

View file

@ -0,0 +1,11 @@
Target from self.onmessage: [object DedicatedWorkerGlobalScope]
Target from message event listener: [object DedicatedWorkerGlobalScope]
Arguments from self.onerror: [
"Some error message",
"",
0,
0,
Error: Some error message
at [WILDCARD]
]
Is event canceled?: true

View file

@ -0,0 +1,23 @@
self.onmessage = (evt) => {
console.log("Target from self.onmessage:", String(evt.target));
};
self.addEventListener("message", (evt) => {
console.log("Target from message event listener:", String(evt.target));
// Throw an error here so the global's error event will fire.
throw new Error("Some error message");
});
self.onerror = (...args) => {
console.log("Arguments from self.onerror:", args);
return true;
};
self.addEventListener("error", (evt) => {
// Returning true from self.onerror means that subsequent event listeners
// should see the event as canceled.
console.log("Is event canceled?:", evt.defaultPrevented);
self.close();
});

View file

@ -27,17 +27,41 @@
}
const handlerSymbol = Symbol("eventHandlers");
function makeWrappedHandler(handler) {
function makeWrappedHandler(handler, isSpecialErrorEventHandler) {
function wrappedHandler(...args) {
if (typeof wrappedHandler.handler !== "function") {
return;
}
if (isSpecialErrorEventHandler) {
const evt = args[0];
if (evt instanceof ErrorEvent && evt.type === "error") {
const ret = FunctionPrototypeCall(
wrappedHandler.handler,
this,
evt.message,
evt.filename,
evt.lineno,
evt.colno,
evt.error,
);
if (ret === true) {
evt.preventDefault();
}
return;
}
}
return FunctionPrototypeCall(wrappedHandler.handler, this, ...args);
}
wrappedHandler.handler = handler;
return wrappedHandler;
}
function defineEventHandler(emitter, name, defaultValue = undefined) {
function defineEventHandler(
emitter,
name,
defaultValue = undefined,
isSpecialErrorEventHandler = false,
) {
// HTML specification section 8.1.5.1
ObjectDefineProperty(emitter, `on${name}`, {
get() {
@ -56,7 +80,10 @@
if (handlerWrapper) {
handlerWrapper.handler = value;
} else {
handlerWrapper = makeWrappedHandler(value);
handlerWrapper = makeWrappedHandler(
value,
isSpecialErrorEventHandler,
);
this.addEventListener(name, handlerWrapper);
}
MapPrototypeSet(this[handlerSymbol], name, handlerWrapper);

View file

@ -88,11 +88,6 @@ delete Object.prototype.__proto__;
core.opSync("op_worker_close");
}
// TODO(bartlomieju): remove these functions
// Stuff for workers
const onmessage = () => {};
const onerror = () => {};
function postMessage(message, transferOrOptions = {}) {
const prefix =
"Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope'";
@ -144,39 +139,19 @@ delete Object.prototype.__proto__;
});
try {
if (globalThis.onmessage) {
await globalThis.onmessage(msgEvent);
}
globalDispatchEvent(msgEvent);
} catch (e) {
let handled = false;
const errorEvent = new ErrorEvent("error", {
cancelable: true,
message: e.message,
lineno: e.lineNumber ? e.lineNumber + 1 : undefined,
colno: e.columnNumber ? e.columnNumber + 1 : undefined,
filename: e.fileName,
error: null,
error: e,
});
if (globalThis["onerror"]) {
const ret = globalThis.onerror(
e.message,
e.fileName,
e.lineNumber,
e.columnNumber,
e,
);
handled = ret === true;
}
globalDispatchEvent(errorEvent);
if (errorEvent.defaultPrevented) {
handled = true;
}
if (!handled) {
if (!errorEvent.defaultPrevented) {
core.opSync(
"op_worker_unhandled_error",
e.message,
@ -465,8 +440,8 @@ delete Object.prototype.__proto__;
get: () => workerNavigator,
},
self: util.readOnly(globalThis),
onmessage: util.writable(onmessage),
onerror: util.writable(onerror),
onmessage: util.writable(null),
onerror: util.writable(null),
// TODO(bartlomieju): should be readonly?
close: util.nonEnumerable(workerClose),
postMessage: util.writable(postMessage),
@ -585,6 +560,9 @@ delete Object.prototype.__proto__;
eventTarget.setEventTargetData(globalThis);
defineEventHandler(self, "message", null);
defineEventHandler(self, "error", null, true);
runtimeStart(
runtimeOptions,
internalName ?? name,