mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 15:24:46 -05:00
feat: implement EventTarget for worker scope (#4737)
This commit is contained in:
parent
8397cd52a5
commit
2585b72c9b
5 changed files with 106 additions and 14 deletions
3
cli/js/lib.deno.worker.d.ts
vendored
3
cli/js/lib.deno.worker.d.ts
vendored
|
@ -8,7 +8,8 @@
|
|||
|
||||
declare interface DedicatedWorkerGlobalScope {
|
||||
self: DedicatedWorkerGlobalScope & typeof globalThis;
|
||||
onmessage: (e: { data: any }) => void;
|
||||
onmessage: (e: MessageEvent) => void;
|
||||
onmessageerror: (e: MessageEvent) => void;
|
||||
location: Location;
|
||||
onerror: undefined | typeof onerror;
|
||||
name: typeof __workerMain.name;
|
||||
|
|
|
@ -15,10 +15,12 @@ import {
|
|||
windowOrWorkerGlobalScopeMethods,
|
||||
windowOrWorkerGlobalScopeProperties,
|
||||
eventTargetProperties,
|
||||
setEventTargetData,
|
||||
} from "./globals.ts";
|
||||
import * as webWorkerOps from "./ops/web_worker.ts";
|
||||
import { LocationImpl } from "./web/location.ts";
|
||||
import { log, assert, immutableDefine } from "./util.ts";
|
||||
import { MessageEvent, ErrorEvent } from "./web/workers.ts";
|
||||
import { TextEncoder } from "./web/text_encoding.ts";
|
||||
import * as runtime from "./runtime.ts";
|
||||
|
||||
|
@ -48,33 +50,50 @@ export function close(): void {
|
|||
}
|
||||
|
||||
export async function workerMessageRecvCallback(data: string): Promise<void> {
|
||||
let result: void | Promise<void>;
|
||||
const event = { data };
|
||||
const msgEvent = new MessageEvent("message", {
|
||||
cancelable: false,
|
||||
data,
|
||||
});
|
||||
|
||||
try {
|
||||
//
|
||||
if (globalThis["onmessage"]) {
|
||||
result = globalThis.onmessage!(event);
|
||||
const result = globalThis.onmessage!(msgEvent);
|
||||
if (result && "then" in result) {
|
||||
await result;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: run the rest of liteners
|
||||
globalThis.dispatchEvent(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,
|
||||
});
|
||||
|
||||
if (globalThis["onerror"]) {
|
||||
const result = globalThis.onerror(
|
||||
const ret = globalThis.onerror(
|
||||
e.message,
|
||||
e.fileName,
|
||||
e.lineNumber,
|
||||
e.columnNumber,
|
||||
e
|
||||
);
|
||||
if (result === true) {
|
||||
return;
|
||||
}
|
||||
handled = ret === true;
|
||||
}
|
||||
|
||||
globalThis.dispatchEvent(errorEvent);
|
||||
if (errorEvent.defaultPrevented) {
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
throw e;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,6 +118,7 @@ export function bootstrapWorkerRuntime(name: string): void {
|
|||
Object.defineProperties(globalThis, workerRuntimeGlobalProperties);
|
||||
Object.defineProperties(globalThis, eventTargetProperties);
|
||||
Object.defineProperties(globalThis, { name: readOnly(name) });
|
||||
setEventTargetData(globalThis);
|
||||
const s = runtime.start(name);
|
||||
|
||||
const location = new LocationImpl(s.location);
|
||||
|
|
43
cli/tests/subdir/event_worker_scope.js
Normal file
43
cli/tests/subdir/event_worker_scope.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
let messageHandlersCalled = 0;
|
||||
let errorHandlersCalled = 0;
|
||||
|
||||
onmessage = function (e) {
|
||||
if (e.data === "boom") {
|
||||
throw new Error("boom error!");
|
||||
}
|
||||
messageHandlersCalled++;
|
||||
};
|
||||
|
||||
self.addEventListener("message", (_e) => {
|
||||
messageHandlersCalled++;
|
||||
});
|
||||
|
||||
self.addEventListener("message", (_e) => {
|
||||
messageHandlersCalled++;
|
||||
});
|
||||
|
||||
self.addEventListener("message", (_e) => {
|
||||
messageHandlersCalled++;
|
||||
|
||||
postMessage({
|
||||
messageHandlersCalled,
|
||||
errorHandlersCalled,
|
||||
});
|
||||
});
|
||||
|
||||
onerror = function (_e) {
|
||||
errorHandlersCalled++;
|
||||
};
|
||||
|
||||
self.addEventListener("error", (_e) => {
|
||||
errorHandlersCalled++;
|
||||
});
|
||||
|
||||
self.addEventListener("error", (_e) => {
|
||||
errorHandlersCalled++;
|
||||
});
|
||||
|
||||
self.addEventListener("error", (e) => {
|
||||
errorHandlersCalled++;
|
||||
e.preventDefault();
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
running 7 tests
|
||||
running 8 tests
|
||||
test worker terminate ... ok [WILDCARD]
|
||||
test worker nested ... ok [WILDCARD]
|
||||
test worker throws when executing ... ok [WILDCARD]
|
||||
|
@ -6,5 +6,6 @@ test worker fetch API ... ok [WILDCARD]
|
|||
test worker terminate busy loop ... ok [WILDCARD]
|
||||
test worker race condition ... ok [WILDCARD]
|
||||
test worker is event listener ... ok [WILDCARD]
|
||||
test worker scope is event listener ... ok [WILDCARD]
|
||||
|
||||
test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out [WILDCARD]
|
||||
test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out [WILDCARD]
|
||||
|
|
|
@ -231,3 +231,30 @@ Deno.test({
|
|||
worker.terminate();
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: "worker scope is event listener",
|
||||
fn: async function (): Promise<void> {
|
||||
const promise1 = createResolvable();
|
||||
|
||||
const worker = new Worker("../tests/subdir/event_worker_scope.js", {
|
||||
type: "module",
|
||||
});
|
||||
|
||||
worker.onmessage = (e: MessageEvent): void => {
|
||||
const { messageHandlersCalled, errorHandlersCalled } = e.data;
|
||||
assertEquals(messageHandlersCalled, 4);
|
||||
assertEquals(errorHandlersCalled, 4);
|
||||
promise1.resolve();
|
||||
};
|
||||
|
||||
worker.onerror = (_e): void => {
|
||||
throw new Error("unreachable");
|
||||
};
|
||||
|
||||
worker.postMessage("boom");
|
||||
worker.postMessage("ping");
|
||||
await promise1;
|
||||
worker.terminate();
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue