diff options
-rw-r--r-- | op_crates/web/02_abort_signal.js | 27 | ||||
-rw-r--r-- | op_crates/web/abort_controller_test.js | 18 |
2 files changed, 38 insertions, 7 deletions
diff --git a/op_crates/web/02_abort_signal.js b/op_crates/web/02_abort_signal.js index 53745c52b..5e8943161 100644 --- a/op_crates/web/02_abort_signal.js +++ b/op_crates/web/02_abort_signal.js @@ -64,22 +64,35 @@ } 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); + return this[handlerSymbol]?.get(name)?.handler; }, set(value) { - const oldListener = this[handlerSymbol]?.get(name); - if (oldListener) { - this.removeEventListener(name, oldListener); - } if (!this[handlerSymbol]) { this[handlerSymbol] = new Map(); } - this.addEventListener(name, value); - this[handlerSymbol].set(value); + 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, diff --git a/op_crates/web/abort_controller_test.js b/op_crates/web/abort_controller_test.js index 4d3741986..a65bc69ff 100644 --- a/op_crates/web/abort_controller_test.js +++ b/op_crates/web/abort_controller_test.js @@ -95,6 +95,23 @@ function abortSignalEventOrder() { assertEquals(arr[1], 2); assertEquals(arr[2], 3); } + +function abortSignalEventOrderComplex() { + const arr = []; + const controller = new AbortController(); + const { signal } = controller; + signal.addEventListener("abort", () => arr.push(1)); + signal.onabort = () => { + throw new Error(); + }; + signal.addEventListener("abort", () => arr.push(3)); + signal.onabort = () => arr.push(2); + controller.abort(); + assertEquals(arr[0], 1); + assertEquals(arr[1], 2); + assertEquals(arr[2], 3); +} + function abortSignalHandlerLocation() { const controller = new AbortController(); const { signal } = controller; @@ -109,6 +126,7 @@ function main() { controllerHasProperToString(); abortSignalIllegalConstructor(); abortSignalEventOrder(); + abortSignalEventOrderComplex(); abortSignalHandlerLocation(); } |