summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
Diffstat (limited to 'cli')
-rw-r--r--cli/rt/01_web_util.js35
-rw-r--r--cli/rt/27_websocket.js23
-rw-r--r--cli/tests/websocket_test.ts20
3 files changed, 60 insertions, 18 deletions
diff --git a/cli/rt/01_web_util.js b/cli/rt/01_web_util.js
index 4a3df65ce..c843ac086 100644
--- a/cli/rt/01_web_util.js
+++ b/cli/rt/01_web_util.js
@@ -113,9 +113,44 @@
}
}
+ const handlerSymbol = Symbol("eventHandlers");
+ function makeWrappedHandler(handler) {
+ function wrappedHandler(...args) {
+ if (typeof wrappedHandler.handler !== "function") {
+ return;
+ }
+ return wrappedHandler.handler.call(this, ...args);
+ }
+ wrappedHandler.handler = handler;
+ return wrappedHandler;
+ }
+ function defineEventHandler(emitter, name) {
+ // HTML specification section 8.1.5.1
+ Object.defineProperty(emitter, `on${name}`, {
+ get() {
+ return this[handlerSymbol]?.get(name)?.handler;
+ },
+ set(value) {
+ if (!this[handlerSymbol]) {
+ this[handlerSymbol] = new Map();
+ }
+ let handlerWrapper = this[handlerSymbol]?.get(name);
+ if (handlerWrapper) {
+ handlerWrapper.handler = value;
+ } else {
+ handlerWrapper = makeWrappedHandler(value);
+ this.addEventListener(name, handlerWrapper);
+ }
+ this[handlerSymbol].set(name, handlerWrapper);
+ },
+ configurable: true,
+ enumerable: true,
+ });
+ }
window.__bootstrap.webUtil = {
illegalConstructorKey,
requiredArguments,
+ defineEventHandler,
cloneValue,
};
})(this);
diff --git a/cli/rt/27_websocket.js b/cli/rt/27_websocket.js
index c0790d14d..675c1e836 100644
--- a/cli/rt/27_websocket.js
+++ b/cli/rt/27_websocket.js
@@ -2,7 +2,7 @@
((window) => {
const core = window.Deno.core;
- const { requiredArguments } = window.__bootstrap.webUtil;
+ const { requiredArguments, defineEventHandler } = window.__bootstrap.webUtil;
const CONNECTING = 0;
const OPEN = 1;
const CLOSING = 2;
@@ -63,12 +63,10 @@
const errEvent = new ErrorEvent("error");
errEvent.target = this;
- this.onerror?.(errEvent);
this.dispatchEvent(errEvent);
const event = new CloseEvent("close");
event.target = this;
- this.onclose?.(event);
this.dispatchEvent(event);
core.close(this.#rid);
});
@@ -76,7 +74,6 @@
this.#readyState = OPEN;
const event = new Event("open");
event.target = this;
- this.onopen?.(event);
this.dispatchEvent(event);
this.#eventLoop();
@@ -86,12 +83,10 @@
const errEvent = new ErrorEvent("error");
errEvent.target = this;
- this.onerror?.(errEvent);
this.dispatchEvent(errEvent);
const closeEvent = new CloseEvent("close");
closeEvent.target = this;
- this.onclose?.(closeEvent);
this.dispatchEvent(closeEvent);
}
}).catch((err) => {
@@ -102,12 +97,10 @@
{ error: err, message: err.toString() },
);
errorEv.target = this;
- this.onerror?.(errorEv);
this.dispatchEvent(errorEv);
const closeEv = new CloseEvent("close");
closeEv.target = this;
- this.onclose?.(closeEv);
this.dispatchEvent(closeEv);
});
}
@@ -159,11 +152,6 @@
return this.#url;
}
- onopen = () => {};
- onerror = () => {};
- onclose = () => {};
- onmessage = () => {};
-
send(data) {
requiredArguments("WebSocket.send", arguments.length, 1);
@@ -241,7 +229,6 @@
reason,
});
event.target = this;
- this.onclose?.(event);
this.dispatchEvent(event);
core.close(this.#rid);
});
@@ -272,7 +259,6 @@
origin: this.#url,
});
event.target = this;
- this.onmessage?.(event);
this.dispatchEvent(event);
this.#eventLoop();
@@ -284,20 +270,17 @@
reason: message.reason,
});
event.target = this;
- this.onclose?.(event);
this.dispatchEvent(event);
} else if (message.type === "error") {
this.#readyState = CLOSED;
const errorEv = new ErrorEvent("error");
errorEv.target = this;
- this.onerror?.(errorEv);
this.dispatchEvent(errorEv);
this.#readyState = CLOSED;
const closeEv = new CloseEvent("close");
closeEv.target = this;
- this.onclose?.(closeEv);
this.dispatchEvent(closeEv);
}
}
@@ -319,6 +302,10 @@
},
});
+ defineEventHandler(WebSocket.prototype, "message");
+ defineEventHandler(WebSocket.prototype, "error");
+ defineEventHandler(WebSocket.prototype, "close");
+ defineEventHandler(WebSocket.prototype, "open");
window.__bootstrap.webSocket = {
WebSocket,
};
diff --git a/cli/tests/websocket_test.ts b/cli/tests/websocket_test.ts
index 93fddf446..0a91ac308 100644
--- a/cli/tests/websocket_test.ts
+++ b/cli/tests/websocket_test.ts
@@ -273,3 +273,23 @@ Deno.test("echo arraybuffer with binaryType arraybuffer", async () => {
};
await promise;
});
+
+Deno.test("Event Handlers order", async () => {
+ const promise = createResolvable();
+ const ws = new WebSocket("ws://localhost:4242");
+ const arr: number[] = [];
+ ws.onerror = (): void => fail();
+ ws.addEventListener("message", () => arr.push(1));
+ ws.onmessage = () => fail();
+ ws.addEventListener("message", () => {
+ arr.push(3);
+ ws.close();
+ assertEquals(arr, [1, 2, 3]);
+ });
+ ws.onmessage = () => arr.push(2);
+ ws.onopen = (): void => ws.send("Echo");
+ ws.onclose = (): void => {
+ promise.resolve();
+ };
+ await promise;
+});