diff --git a/ext/web/10_filereader.js b/ext/web/10_filereader.js index 760533f321..f93eb5feee 100644 --- a/ext/web/10_filereader.js +++ b/ext/web/10_filereader.js @@ -41,6 +41,7 @@ const result = Symbol("[[result]]"); const error = Symbol("[[error]]"); const aborted = Symbol("[[aborted]]"); + const handlerSymbol = Symbol("eventHandlers"); class FileReader extends EventTarget { get [SymbolToStringTag]() { @@ -263,6 +264,32 @@ })(); } + #getEventHandlerFor(name) { + webidl.assertBranded(this, FileReader); + + const maybeMap = this[handlerSymbol]; + if (!maybeMap) return null; + + return MapPrototypeGet(maybeMap, name)?.handler ?? null; + } + + #setEventHandlerFor(name, value) { + webidl.assertBranded(this, FileReader); + + 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); + } + constructor() { super(); this[webidl.brand] = webidl.brand; @@ -368,6 +395,48 @@ // alias for readAsArrayBuffer this.#readOperation(blob, { kind: "Text", encoding }); } + + get onerror() { + return this.#getEventHandlerFor("error"); + } + set onerror(value) { + this.#setEventHandlerFor("error", value); + } + + get onloadstart() { + return this.#getEventHandlerFor("loadstart"); + } + set onloadstart(value) { + this.#setEventHandlerFor("loadstart", value); + } + + get onload() { + return this.#getEventHandlerFor("load"); + } + set onload(value) { + this.#setEventHandlerFor("load", value); + } + + get onloadend() { + return this.#getEventHandlerFor("loadend"); + } + set onloadend(value) { + this.#setEventHandlerFor("loadend", value); + } + + get onprogress() { + return this.#getEventHandlerFor("progress"); + } + set onprogress(value) { + this.#setEventHandlerFor("progress", value); + } + + get onabort() { + return this.#getEventHandlerFor("abort"); + } + set onabort(value) { + this.#setEventHandlerFor("abort", value); + } } webidl.configurePrototype(FileReader); @@ -409,8 +478,6 @@ value: 2, }); - const handlerSymbol = Symbol("eventHandlers"); - function makeWrappedHandler(handler) { function wrappedHandler(...args) { if (typeof wrappedHandler.handler !== "function") { @@ -421,39 +488,6 @@ wrappedHandler.handler = handler; return wrappedHandler; } - // TODO(benjamingr) 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() { - const maybeMap = this[handlerSymbol]; - if (!maybeMap) return null; - - return MapPrototypeGet(maybeMap, 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, - }); - } - defineEventHandler(FileReader.prototype, "error"); - defineEventHandler(FileReader.prototype, "loadstart"); - defineEventHandler(FileReader.prototype, "load"); - defineEventHandler(FileReader.prototype, "loadend"); - defineEventHandler(FileReader.prototype, "progress"); - defineEventHandler(FileReader.prototype, "abort"); window.__bootstrap.fileReader = { FileReader, diff --git a/tools/wpt/expectation.json b/tools/wpt/expectation.json index e5053dfd9d..3ff6968991 100644 --- a/tools/wpt/expectation.json +++ b/tools/wpt/expectation.json @@ -13761,13 +13761,7 @@ "FileList interface: existence and properties of interface prototype object's \"constructor\" property", "FileList interface: existence and properties of interface prototype object's @@unscopables property", "FileList interface: operation item(unsigned long)", - "FileList interface: attribute length", - "FileReader interface: attribute onloadstart", - "FileReader interface: attribute onprogress", - "FileReader interface: attribute onload", - "FileReader interface: attribute onabort", - "FileReader interface: attribute onerror", - "FileReader interface: attribute onloadend" + "FileList interface: attribute length" ] }, "html": { @@ -14287,4 +14281,4 @@ "Pattern: [{\"pathname\":\"/foo/bar\"}] Inputs: [\"./foo/bar\",\"https://example.com\"]" ] } -} \ No newline at end of file +}