From 4f46dc999b9fd3f26b6586d06d099d7039ca35c8 Mon Sep 17 00:00:00 2001 From: Benjamin Gruenbaum Date: Thu, 26 Nov 2020 23:27:55 +0200 Subject: fix: "onload" event order (#8376) This commit fixes order of events for "onload" event. Previously handler attached using "window.onload" was always fired before handlers added using "addEventListener". --- cli/rt/99_main.js | 53 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 13 deletions(-) (limited to 'cli/rt') diff --git a/cli/rt/99_main.js b/cli/rt/99_main.js index 68572f79a..69c27c579 100644 --- a/cli/rt/99_main.js +++ b/cli/rt/99_main.js @@ -283,20 +283,47 @@ delete Object.prototype.__proto__; Object.defineProperties(globalThis, mainRuntimeGlobalProperties); Object.setPrototypeOf(globalThis, Window.prototype); eventTarget.setEventTargetData(globalThis); - // Registers the handler for window.onload function. - globalThis.addEventListener("load", (e) => { - const { onload } = globalThis; - if (typeof onload === "function") { - onload(e); - } - }); - // Registers the handler for window.onunload function. - globalThis.addEventListener("unload", (e) => { - const { onunload } = globalThis; - if (typeof onunload === "function") { - onunload(e); + + 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; + } + // TODO(benjamingr) reuse when we can reuse code between web crates + // This function is very similar to `defineEventHandler` in `01_web_util.js` + // but it returns `null` instead of `undefined` is handler is not defined. + function defineEventHandler(emitter, name) { + // HTML specification section 8.1.5.1 + Object.defineProperty(emitter, `on${name}`, { + get() { + return this[handlerSymbol]?.get(name)?.handler ?? null; + }, + 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, + }); + } + defineEventHandler(window, "load"); + defineEventHandler(window, "unload"); const { args, noColor, pid, ppid, unstableFlag } = runtimeStart(); -- cgit v1.2.3