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:
parent
67c9937e66
commit
eea6000ef6
6 changed files with 81 additions and 32 deletions
|
@ -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()
|
||||
|
|
5
cli/tests/worker_event_handler_test.js
Normal file
5
cli/tests/worker_event_handler_test.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
const w = new Worker(
|
||||
new URL("./workers/worker_event_handlers.js", import.meta.url).href,
|
||||
{ type: "module" },
|
||||
);
|
||||
w.postMessage({});
|
11
cli/tests/worker_event_handler_test.js.out
Normal file
11
cli/tests/worker_event_handler_test.js.out
Normal 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
|
23
cli/tests/workers/worker_event_handlers.js
Normal file
23
cli/tests/workers/worker_event_handlers.js
Normal 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();
|
||||
});
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue