diff options
Diffstat (limited to 'ext')
| -rw-r--r-- | ext/broadcast_channel/01_broadcast_channel.js | 49 | ||||
| -rw-r--r-- | ext/web/02_event.js | 62 | ||||
| -rw-r--r-- | ext/websocket/01_websocket.js | 45 |
3 files changed, 53 insertions, 103 deletions
diff --git a/ext/broadcast_channel/01_broadcast_channel.js b/ext/broadcast_channel/01_broadcast_channel.js index 42112c014..d1970b1eb 100644 --- a/ext/broadcast_channel/01_broadcast_channel.js +++ b/ext/broadcast_channel/01_broadcast_channel.js @@ -7,7 +7,7 @@ ((window) => { const core = window.Deno.core; const webidl = window.__bootstrap.webidl; - const { setTarget } = window.__bootstrap.event; + const { defineEventHandler, setTarget } = window.__bootstrap.event; const { DOMException } = window.__bootstrap.domException; const { ArrayPrototypeIndexOf, @@ -15,55 +15,8 @@ ArrayPrototypePush, Symbol, Uint8Array, - ObjectDefineProperty, - Map, - MapPrototypeSet, - MapPrototypeGet, - FunctionPrototypeCall, } = window.__bootstrap.primordials; - const handlerSymbol = Symbol("eventHandlers"); - function makeWrappedHandler(handler) { - function wrappedHandler(...args) { - if (typeof wrappedHandler.handler !== "function") { - return; - } - return FunctionPrototypeCall(wrappedHandler.handler, this, ...args); - } - wrappedHandler.handler = handler; - return wrappedHandler; - } - // TODO(lucacasonato) reuse when we can reuse code between web crates - function defineEventHandler(emitter, name) { - // HTML specification section 8.1.5.1 - ObjectDefineProperty(emitter, `on${name}`, { - get() { - // TODO(bnoordhuis) The "BroadcastChannel should have an onmessage - // event" WPT test expects that .onmessage !== undefined. Returning - // null makes it pass but is perhaps not exactly in the spirit. - if (!this[handlerSymbol]) { - return null; - } - return MapPrototypeGet(this[handlerSymbol], name)?.handler ?? null; - }, - set(value) { - if (!this[handlerSymbol]) { - this[handlerSymbol] = new Map(); - } - let handlerWrapper = MapPrototypeGet(this[handlerSymbol], name); - if (handlerWrapper) { - handlerWrapper.handler = value; - } else { - handlerWrapper = makeWrappedHandler(value); - this.addEventListener(name, handlerWrapper); - } - MapPrototypeSet(this[handlerSymbol], name, handlerWrapper); - }, - configurable: true, - enumerable: true, - }); - } - const _name = Symbol("[[name]]"); const _closed = Symbol("[[closed]]"); diff --git a/ext/web/02_event.js b/ext/web/02_event.js index 790bb35ea..5ca36300c 100644 --- a/ext/web/02_event.js +++ b/ext/web/02_event.js @@ -1226,36 +1226,76 @@ const _eventHandlers = Symbol("eventHandlers"); - function makeWrappedHandler(handler) { - function wrappedHandler(...args) { + function makeWrappedHandler(handler, isSpecialErrorEventHandler) { + function wrappedHandler(evt) { if (typeof wrappedHandler.handler !== "function") { return; } - return FunctionPrototypeCall(wrappedHandler.handler, this, ...args); + + if ( + isSpecialErrorEventHandler && + evt instanceof ErrorEvent && evt.type === "error" + ) { + const ret = FunctionPrototypeCall( + wrappedHandler.handler, + this, + evt.message, + evt.filename, + evt.lineno, + evt.colno, + evt.error, + ); + if (ret === true) { + evt.preventDefault(); + } + return; + } + + return FunctionPrototypeCall(wrappedHandler.handler, this, evt); } wrappedHandler.handler = handler; return wrappedHandler; } - // TODO(benjamingr) reuse this here and websocket where possible - function defineEventHandler(emitter, name, init) { - // HTML specification section 8.1.5.1 + // `init` is an optional function that will be called the first time that the + // event handler property is set. It will be called with the object on which + // the property is set as its argument. + // `isSpecialErrorEventHandler` can be set to true to opt into the special + // behavior of event handlers for the "error" event in a global scope. + function defineEventHandler( + emitter, + name, + init = undefined, + isSpecialErrorEventHandler = false, + ) { + // HTML specification section 8.1.7.1 ObjectDefineProperty(emitter, `on${name}`, { get() { - const map = this[_eventHandlers]; + if (!this[_eventHandlers]) { + return null; + } - if (!map) return undefined; - return MapPrototypeGet(map, name)?.handler; + return MapPrototypeGet(this[_eventHandlers], name)?.handler ?? null; }, set(value) { + // All three Web IDL event handler types are nullable callback functions + // with the [LegacyTreatNonObjectAsNull] extended attribute, meaning + // anything other than an object is treated as null. + if (typeof value !== "object" && typeof value !== "function") { + value = null; + } + if (!this[_eventHandlers]) { this[_eventHandlers] = new Map(); } let handlerWrapper = MapPrototypeGet(this[_eventHandlers], name); if (handlerWrapper) { handlerWrapper.handler = value; - } else { - handlerWrapper = makeWrappedHandler(value); + } else if (value !== null) { + handlerWrapper = makeWrappedHandler( + value, + isSpecialErrorEventHandler, + ); this.addEventListener(name, handlerWrapper); init?.(this); } diff --git a/ext/websocket/01_websocket.js b/ext/websocket/01_websocket.js index 54e05c408..200bb8659 100644 --- a/ext/websocket/01_websocket.js +++ b/ext/websocket/01_websocket.js @@ -9,6 +9,7 @@ const webidl = window.__bootstrap.webidl; const { HTTP_TOKEN_CODE_POINT_RE } = window.__bootstrap.infra; const { DOMException } = window.__bootstrap.domException; + const { defineEventHandler } = window.__bootstrap.event; const { Blob } = globalThis.__bootstrap.file; const { ArrayBuffer, @@ -16,16 +17,11 @@ ArrayPrototypeJoin, DataView, ErrorPrototypeToString, - ObjectDefineProperty, - Map, - MapPrototypeGet, - MapPrototypeSet, Set, Symbol, String, StringPrototypeToLowerCase, StringPrototypeEndsWith, - FunctionPrototypeCall, RegExpPrototypeTest, ObjectDefineProperties, ArrayPrototypeMap, @@ -65,45 +61,6 @@ const CLOSING = 2; const CLOSED = 3; - const handlerSymbol = Symbol("eventHandlers"); - function makeWrappedHandler(handler) { - function wrappedHandler(...args) { - if (typeof wrappedHandler.handler !== "function") { - return; - } - return FunctionPrototypeCall(wrappedHandler.handler, this, ...args); - } - wrappedHandler.handler = handler; - return wrappedHandler; - } - // TODO(lucacasonato) reuse when we can reuse code between web crates - function defineEventHandler(emitter, name) { - // HTML specification section 8.1.5.1 - ObjectDefineProperty(emitter, `on${name}`, { - get() { - if (!this[handlerSymbol]) { - return null; - } - return MapPrototypeGet(this[handlerSymbol], name)?.handler; - }, - set(value) { - if (!this[handlerSymbol]) { - this[handlerSymbol] = new Map(); - } - let handlerWrapper = MapPrototypeGet(this[handlerSymbol], name); - if (handlerWrapper) { - handlerWrapper.handler = value; - } else { - handlerWrapper = makeWrappedHandler(value); - this.addEventListener(name, handlerWrapper); - } - MapPrototypeSet(this[handlerSymbol], name, handlerWrapper); - }, - configurable: true, - enumerable: true, - }); - } - const _readyState = Symbol("[[readyState]]"); const _url = Symbol("[[url]]"); const _rid = Symbol("[[rid]]"); |
