0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 09:31:22 -05:00

fix(cli/rt): dom handler order in websocket (#8320)

This commit is contained in:
Benjamin Gruenbaum 2020-11-10 05:34:42 +02:00 committed by GitHub
parent 0982056ff6
commit 94b68f9069
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 61 additions and 18 deletions

View file

@ -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);

View file

@ -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,
};

View file

@ -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;
});

View file

@ -75,6 +75,7 @@
wrappedHandler.handler = handler;
return wrappedHandler;
}
// TODO(benjamingr) reuse this here and websocket where possible
function defineEventHandler(emitter, name) {
// HTML specification section 8.1.5.1
Object.defineProperty(emitter, `on${name}`, {