diff --git a/lib/web/cache/cache.js b/lib/web/cache/cache.js index 5a66d08cb6c..45c6fec3467 100644 --- a/lib/web/cache/cache.js +++ b/lib/web/cache/cache.js @@ -42,10 +42,12 @@ class Cache { async match (request, options = {}) { webidl.brandCheck(this, Cache) - webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.match' }) - request = webidl.converters.RequestInfo(request) - options = webidl.converters.CacheQueryOptions(options) + const prefix = 'Cache.match' + webidl.argumentLengthCheck(arguments, 1, prefix) + + request = webidl.converters.RequestInfo(request, prefix, 'request') + options = webidl.converters.CacheQueryOptions(options, prefix, 'options') const p = this.#internalMatchAll(request, options, 1) @@ -59,17 +61,20 @@ class Cache { async matchAll (request = undefined, options = {}) { webidl.brandCheck(this, Cache) - if (request !== undefined) request = webidl.converters.RequestInfo(request) - options = webidl.converters.CacheQueryOptions(options) + const prefix = 'Cache.matchAll' + if (request !== undefined) request = webidl.converters.RequestInfo(request, prefix, 'request') + options = webidl.converters.CacheQueryOptions(options, prefix, 'options') return this.#internalMatchAll(request, options) } async add (request) { webidl.brandCheck(this, Cache) - webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.add' }) - request = webidl.converters.RequestInfo(request) + const prefix = 'Cache.add' + webidl.argumentLengthCheck(arguments, 1, prefix) + + request = webidl.converters.RequestInfo(request, prefix, 'request') // 1. const requests = [request] @@ -83,7 +88,9 @@ class Cache { async addAll (requests) { webidl.brandCheck(this, Cache) - webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.addAll' }) + + const prefix = 'Cache.addAll' + webidl.argumentLengthCheck(arguments, 1, prefix) // 1. const responsePromises = [] @@ -95,7 +102,7 @@ class Cache { for (let request of requests) { if (request === undefined) { throw webidl.errors.conversionFailed({ - prefix: 'Cache.addAll', + prefix, argument: 'Argument 1', types: ['undefined is not allowed'] }) @@ -113,7 +120,7 @@ class Cache { // 3.2 if (!urlIsHttpHttpsScheme(r.url) || r.method !== 'GET') { throw webidl.errors.exception({ - header: 'Cache.addAll', + header: prefix, message: 'Expected http/s scheme when method is not GET.' }) } @@ -131,7 +138,7 @@ class Cache { // 5.2 if (!urlIsHttpHttpsScheme(r.url)) { throw webidl.errors.exception({ - header: 'Cache.addAll', + header: prefix, message: 'Expected http/s scheme.' }) } @@ -251,10 +258,12 @@ class Cache { async put (request, response) { webidl.brandCheck(this, Cache) - webidl.argumentLengthCheck(arguments, 2, { header: 'Cache.put' }) - request = webidl.converters.RequestInfo(request) - response = webidl.converters.Response(response) + const prefix = 'Cache.put' + webidl.argumentLengthCheck(arguments, 2, prefix) + + request = webidl.converters.RequestInfo(request, prefix, 'request') + response = webidl.converters.Response(response, prefix, 'response') // 1. let innerRequest = null @@ -269,7 +278,7 @@ class Cache { // 4. if (!urlIsHttpHttpsScheme(innerRequest.url) || innerRequest.method !== 'GET') { throw webidl.errors.exception({ - header: 'Cache.put', + header: prefix, message: 'Expected an http/s scheme when method is not GET' }) } @@ -280,7 +289,7 @@ class Cache { // 6. if (innerResponse.status === 206) { throw webidl.errors.exception({ - header: 'Cache.put', + header: prefix, message: 'Got 206 status' }) } @@ -295,7 +304,7 @@ class Cache { // 7.2.1 if (fieldValue === '*') { throw webidl.errors.exception({ - header: 'Cache.put', + header: prefix, message: 'Got * vary field value' }) } @@ -305,7 +314,7 @@ class Cache { // 8. if (innerResponse.body && (isDisturbed(innerResponse.body.stream) || innerResponse.body.stream.locked)) { throw webidl.errors.exception({ - header: 'Cache.put', + header: prefix, message: 'Response body is locked or disturbed' }) } @@ -380,10 +389,12 @@ class Cache { async delete (request, options = {}) { webidl.brandCheck(this, Cache) - webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.delete' }) - request = webidl.converters.RequestInfo(request) - options = webidl.converters.CacheQueryOptions(options) + const prefix = 'Cache.delete' + webidl.argumentLengthCheck(arguments, 1, prefix) + + request = webidl.converters.RequestInfo(request, prefix, 'request') + options = webidl.converters.CacheQueryOptions(options, prefix, 'options') /** * @type {Request} @@ -445,8 +456,10 @@ class Cache { async keys (request = undefined, options = {}) { webidl.brandCheck(this, Cache) - if (request !== undefined) request = webidl.converters.RequestInfo(request) - options = webidl.converters.CacheQueryOptions(options) + const prefix = 'Cache.keys' + + if (request !== undefined) request = webidl.converters.RequestInfo(request, prefix, 'request') + options = webidl.converters.CacheQueryOptions(options, prefix, 'options') // 1. let r = null @@ -810,17 +823,17 @@ const cacheQueryOptionConverters = [ { key: 'ignoreSearch', converter: webidl.converters.boolean, - defaultValue: false + defaultValue: () => false }, { key: 'ignoreMethod', converter: webidl.converters.boolean, - defaultValue: false + defaultValue: () => false }, { key: 'ignoreVary', converter: webidl.converters.boolean, - defaultValue: false + defaultValue: () => false } ] diff --git a/lib/web/cache/cachestorage.js b/lib/web/cache/cachestorage.js index de3813cfecb..cc773b94b49 100644 --- a/lib/web/cache/cachestorage.js +++ b/lib/web/cache/cachestorage.js @@ -20,7 +20,7 @@ class CacheStorage { async match (request, options = {}) { webidl.brandCheck(this, CacheStorage) - webidl.argumentLengthCheck(arguments, 1, { header: 'CacheStorage.match' }) + webidl.argumentLengthCheck(arguments, 1, 'CacheStorage.match') request = webidl.converters.RequestInfo(request) options = webidl.converters.MultiCacheQueryOptions(options) @@ -57,9 +57,11 @@ class CacheStorage { */ async has (cacheName) { webidl.brandCheck(this, CacheStorage) - webidl.argumentLengthCheck(arguments, 1, { header: 'CacheStorage.has' }) - cacheName = webidl.converters.DOMString(cacheName) + const prefix = 'CacheStorage.has' + webidl.argumentLengthCheck(arguments, 1, prefix) + + cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName') // 2.1.1 // 2.2 @@ -73,9 +75,11 @@ class CacheStorage { */ async open (cacheName) { webidl.brandCheck(this, CacheStorage) - webidl.argumentLengthCheck(arguments, 1, { header: 'CacheStorage.open' }) - cacheName = webidl.converters.DOMString(cacheName) + const prefix = 'CacheStorage.open' + webidl.argumentLengthCheck(arguments, 1, prefix) + + cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName') // 2.1 if (this.#caches.has(cacheName)) { @@ -105,9 +109,11 @@ class CacheStorage { */ async delete (cacheName) { webidl.brandCheck(this, CacheStorage) - webidl.argumentLengthCheck(arguments, 1, { header: 'CacheStorage.delete' }) - cacheName = webidl.converters.DOMString(cacheName) + const prefix = 'CacheStorage.delete' + webidl.argumentLengthCheck(arguments, 1, prefix) + + cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName') return this.#caches.delete(cacheName) } diff --git a/lib/web/cookies/index.js b/lib/web/cookies/index.js index 1fc2bd295f6..d40c71318e5 100644 --- a/lib/web/cookies/index.js +++ b/lib/web/cookies/index.js @@ -24,7 +24,7 @@ const { Headers } = require('../fetch/headers') * @returns {Record} */ function getCookies (headers) { - webidl.argumentLengthCheck(arguments, 1, { header: 'getCookies' }) + webidl.argumentLengthCheck(arguments, 1, 'getCookies') webidl.brandCheck(headers, Headers, { strict: false }) @@ -51,11 +51,12 @@ function getCookies (headers) { * @returns {void} */ function deleteCookie (headers, name, attributes) { - webidl.argumentLengthCheck(arguments, 2, { header: 'deleteCookie' }) - webidl.brandCheck(headers, Headers, { strict: false }) - name = webidl.converters.DOMString(name) + const prefix = 'deleteCookie' + webidl.argumentLengthCheck(arguments, 2, prefix) + + name = webidl.converters.DOMString(name, prefix, 'name') attributes = webidl.converters.DeleteCookieAttributes(attributes) // Matches behavior of @@ -73,7 +74,7 @@ function deleteCookie (headers, name, attributes) { * @returns {Cookie[]} */ function getSetCookies (headers) { - webidl.argumentLengthCheck(arguments, 1, { header: 'getSetCookies' }) + webidl.argumentLengthCheck(arguments, 1, 'getSetCookies') webidl.brandCheck(headers, Headers, { strict: false }) @@ -93,7 +94,7 @@ function getSetCookies (headers) { * @returns {void} */ function setCookie (headers, cookie) { - webidl.argumentLengthCheck(arguments, 2, { header: 'setCookie' }) + webidl.argumentLengthCheck(arguments, 2, 'setCookie') webidl.brandCheck(headers, Headers, { strict: false }) @@ -110,12 +111,12 @@ webidl.converters.DeleteCookieAttributes = webidl.dictionaryConverter([ { converter: webidl.nullableConverter(webidl.converters.DOMString), key: 'path', - defaultValue: null + defaultValue: () => null }, { converter: webidl.nullableConverter(webidl.converters.DOMString), key: 'domain', - defaultValue: null + defaultValue: () => null } ]) @@ -137,32 +138,32 @@ webidl.converters.Cookie = webidl.dictionaryConverter([ return new Date(value) }), key: 'expires', - defaultValue: null + defaultValue: () => null }, { converter: webidl.nullableConverter(webidl.converters['long long']), key: 'maxAge', - defaultValue: null + defaultValue: () => null }, { converter: webidl.nullableConverter(webidl.converters.DOMString), key: 'domain', - defaultValue: null + defaultValue: () => null }, { converter: webidl.nullableConverter(webidl.converters.DOMString), key: 'path', - defaultValue: null + defaultValue: () => null }, { converter: webidl.nullableConverter(webidl.converters.boolean), key: 'secure', - defaultValue: null + defaultValue: () => null }, { converter: webidl.nullableConverter(webidl.converters.boolean), key: 'httpOnly', - defaultValue: null + defaultValue: () => null }, { converter: webidl.converters.USVString, @@ -172,7 +173,7 @@ webidl.converters.Cookie = webidl.dictionaryConverter([ { converter: webidl.sequenceConverter(webidl.converters.DOMString), key: 'unparsed', - defaultValue: [] + defaultValue: () => new Array(0) } ]) diff --git a/lib/web/eventsource/eventsource.js b/lib/web/eventsource/eventsource.js index 0b1e48dbd2d..51634c1779f 100644 --- a/lib/web/eventsource/eventsource.js +++ b/lib/web/eventsource/eventsource.js @@ -105,7 +105,8 @@ class EventSource extends EventTarget { // 1. Let ev be a new EventSource object. super() - webidl.argumentLengthCheck(arguments, 1, { header: 'EventSource constructor' }) + const prefix = 'EventSource constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) if (!experimentalWarned) { experimentalWarned = true @@ -114,8 +115,8 @@ class EventSource extends EventTarget { }) } - url = webidl.converters.USVString(url) - eventSourceInitDict = webidl.converters.EventSourceInitDict(eventSourceInitDict) + url = webidl.converters.USVString(url, prefix, 'url') + eventSourceInitDict = webidl.converters.EventSourceInitDict(eventSourceInitDict, prefix, 'eventSourceInitDict') this.#dispatcher = eventSourceInitDict.dispatcher this.#state = { @@ -463,7 +464,7 @@ webidl.converters.EventSourceInitDict = webidl.dictionaryConverter([ { key: 'withCredentials', converter: webidl.converters.boolean, - defaultValue: false + defaultValue: () => false }, { key: 'dispatcher', // undici only diff --git a/lib/web/fetch/formdata.js b/lib/web/fetch/formdata.js index 029419ffe94..94a84b03ab3 100644 --- a/lib/web/fetch/formdata.js +++ b/lib/web/fetch/formdata.js @@ -28,7 +28,8 @@ class FormData { append (name, value, filename = undefined) { webidl.brandCheck(this, FormData) - webidl.argumentLengthCheck(arguments, 2, { header: 'FormData.append' }) + const prefix = 'FormData.append' + webidl.argumentLengthCheck(arguments, 2, prefix) if (arguments.length === 3 && !isBlobLike(value)) { throw new TypeError( @@ -38,12 +39,12 @@ class FormData { // 1. Let value be value if given; otherwise blobValue. - name = webidl.converters.USVString(name) + name = webidl.converters.USVString(name, prefix, 'name') value = isBlobLike(value) - ? webidl.converters.Blob(value, { strict: false }) - : webidl.converters.USVString(value) + ? webidl.converters.Blob(value, prefix, 'value', { strict: false }) + : webidl.converters.USVString(value, prefix, 'value') filename = arguments.length === 3 - ? webidl.converters.USVString(filename) + ? webidl.converters.USVString(filename, prefix, 'filename') : undefined // 2. Let entry be the result of creating an entry with @@ -57,9 +58,10 @@ class FormData { delete (name) { webidl.brandCheck(this, FormData) - webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.delete' }) + const prefix = 'FormData.delete' + webidl.argumentLengthCheck(arguments, 1, prefix) - name = webidl.converters.USVString(name) + name = webidl.converters.USVString(name, prefix, 'name') // The delete(name) method steps are to remove all entries whose name // is name from this’s entry list. @@ -69,9 +71,10 @@ class FormData { get (name) { webidl.brandCheck(this, FormData) - webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.get' }) + const prefix = 'FormData.get' + webidl.argumentLengthCheck(arguments, 1, prefix) - name = webidl.converters.USVString(name) + name = webidl.converters.USVString(name, prefix, 'name') // 1. If there is no entry whose name is name in this’s entry list, // then return null. @@ -88,9 +91,10 @@ class FormData { getAll (name) { webidl.brandCheck(this, FormData) - webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.getAll' }) + const prefix = 'FormData.getAll' + webidl.argumentLengthCheck(arguments, 1, prefix) - name = webidl.converters.USVString(name) + name = webidl.converters.USVString(name, prefix, 'name') // 1. If there is no entry whose name is name in this’s entry list, // then return the empty list. @@ -104,9 +108,10 @@ class FormData { has (name) { webidl.brandCheck(this, FormData) - webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.has' }) + const prefix = 'FormData.has' + webidl.argumentLengthCheck(arguments, 1, prefix) - name = webidl.converters.USVString(name) + name = webidl.converters.USVString(name, prefix, 'name') // The has(name) method steps are to return true if there is an entry // whose name is name in this’s entry list; otherwise false. @@ -116,7 +121,8 @@ class FormData { set (name, value, filename = undefined) { webidl.brandCheck(this, FormData) - webidl.argumentLengthCheck(arguments, 2, { header: 'FormData.set' }) + const prefix = 'FormData.set' + webidl.argumentLengthCheck(arguments, 2, prefix) if (arguments.length === 3 && !isBlobLike(value)) { throw new TypeError( @@ -129,12 +135,12 @@ class FormData { // 1. Let value be value if given; otherwise blobValue. - name = webidl.converters.USVString(name) + name = webidl.converters.USVString(name, prefix, 'name') value = isBlobLike(value) - ? webidl.converters.Blob(value, { strict: false }) - : webidl.converters.USVString(value) + ? webidl.converters.Blob(value, prefix, 'name', { strict: false }) + : webidl.converters.USVString(value, prefix, 'name') filename = arguments.length === 3 - ? webidl.converters.USVString(filename) + ? webidl.converters.USVString(filename, prefix, 'name') : undefined // 2. Let entry be the result of creating an entry with name, value, and diff --git a/lib/web/fetch/headers.js b/lib/web/fetch/headers.js index 7f2f526a9cb..3157561b470 100644 --- a/lib/web/fetch/headers.js +++ b/lib/web/fetch/headers.js @@ -366,7 +366,7 @@ class Headers { // 2. If init is given, then fill this with init. if (init !== undefined) { - init = webidl.converters.HeadersInit(init) + init = webidl.converters.HeadersInit(init, 'Headers contructor', 'init') fill(this, init) } } @@ -375,10 +375,11 @@ class Headers { append (name, value) { webidl.brandCheck(this, Headers) - webidl.argumentLengthCheck(arguments, 2, { header: 'Headers.append' }) + webidl.argumentLengthCheck(arguments, 2, 'Headers.append') - name = webidl.converters.ByteString(name) - value = webidl.converters.ByteString(value) + const prefix = 'Headers.append' + name = webidl.converters.ByteString(name, prefix, 'name') + value = webidl.converters.ByteString(value, prefix, 'value') return appendHeader(this, name, value) } @@ -387,9 +388,10 @@ class Headers { delete (name) { webidl.brandCheck(this, Headers) - webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.delete' }) + webidl.argumentLengthCheck(arguments, 1, 'Headers.delete') - name = webidl.converters.ByteString(name) + const prefix = 'Headers.delete' + name = webidl.converters.ByteString(name, prefix, 'name') // 1. If name is not a header name, then throw a TypeError. if (!isValidHeaderName(name)) { @@ -432,14 +434,15 @@ class Headers { get (name) { webidl.brandCheck(this, Headers) - webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.get' }) + webidl.argumentLengthCheck(arguments, 1, 'Headers.get') - name = webidl.converters.ByteString(name) + const prefix = 'Headers.get' + name = webidl.converters.ByteString(name, prefix, 'name') // 1. If name is not a header name, then throw a TypeError. if (!isValidHeaderName(name)) { throw webidl.errors.invalidArgument({ - prefix: 'Headers.get', + prefix, value: name, type: 'header name' }) @@ -454,14 +457,15 @@ class Headers { has (name) { webidl.brandCheck(this, Headers) - webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.has' }) + webidl.argumentLengthCheck(arguments, 1, 'Headers.has') - name = webidl.converters.ByteString(name) + const prefix = 'Headers.has' + name = webidl.converters.ByteString(name, prefix, 'name') // 1. If name is not a header name, then throw a TypeError. if (!isValidHeaderName(name)) { throw webidl.errors.invalidArgument({ - prefix: 'Headers.has', + prefix, value: name, type: 'header name' }) @@ -476,10 +480,11 @@ class Headers { set (name, value) { webidl.brandCheck(this, Headers) - webidl.argumentLengthCheck(arguments, 2, { header: 'Headers.set' }) + webidl.argumentLengthCheck(arguments, 2, 'Headers.set') - name = webidl.converters.ByteString(name) - value = webidl.converters.ByteString(value) + const prefix = 'Headers.set' + name = webidl.converters.ByteString(name, prefix, 'name') + value = webidl.converters.ByteString(value, prefix, 'value') // 1. Normalize value. value = headerValueNormalize(value) @@ -488,13 +493,13 @@ class Headers { // header value, then throw a TypeError. if (!isValidHeaderName(name)) { throw webidl.errors.invalidArgument({ - prefix: 'Headers.set', + prefix, value: name, type: 'header name' }) } else if (!isValidHeaderValue(value)) { throw webidl.errors.invalidArgument({ - prefix: 'Headers.set', + prefix, value, type: 'header value' }) @@ -616,7 +621,7 @@ Object.defineProperties(Headers.prototype, { } }) -webidl.converters.HeadersInit = function (V) { +webidl.converters.HeadersInit = function (V, prefix, argument) { if (webidl.util.Type(V) === 'Object') { const iterator = Reflect.get(V, Symbol.iterator) @@ -627,10 +632,10 @@ webidl.converters.HeadersInit = function (V) { } if (typeof iterator === 'function') { - return webidl.converters['sequence>'](V, iterator.bind(V)) + return webidl.converters['sequence>'](V, prefix, argument, iterator.bind(V)) } - return webidl.converters['record'](V) + return webidl.converters['record'](V, prefix, argument) } throw webidl.errors.conversionFailed({ diff --git a/lib/web/fetch/index.js b/lib/web/fetch/index.js index a082797e575..82ccb26865c 100644 --- a/lib/web/fetch/index.js +++ b/lib/web/fetch/index.js @@ -122,7 +122,7 @@ class Fetch extends EE { // https://fetch.spec.whatwg.org/#fetch-method function fetch (input, init = undefined) { - webidl.argumentLengthCheck(arguments, 1, { header: 'globalThis.fetch' }) + webidl.argumentLengthCheck(arguments, 1, 'globalThis.fetch') // 1. Let p be a new promise. const p = createDeferredPromise() diff --git a/lib/web/fetch/request.js b/lib/web/fetch/request.js index d963986ce2d..1441a58b06e 100644 --- a/lib/web/fetch/request.js +++ b/lib/web/fetch/request.js @@ -88,10 +88,11 @@ class Request { return } - webidl.argumentLengthCheck(arguments, 1, { header: 'Request constructor' }) + const prefix = 'Request constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) - input = webidl.converters.RequestInfo(input) - init = webidl.converters.RequestInit(init) + input = webidl.converters.RequestInfo(input, prefix, 'input') + init = webidl.converters.RequestInit(init, prefix, 'init') // 1. Let request be null. let request = null @@ -932,16 +933,16 @@ webidl.converters.Request = webidl.interfaceConverter( ) // https://fetch.spec.whatwg.org/#requestinfo -webidl.converters.RequestInfo = function (V) { +webidl.converters.RequestInfo = function (V, prefix, argument) { if (typeof V === 'string') { - return webidl.converters.USVString(V) + return webidl.converters.USVString(V, prefix, argument) } if (V instanceof Request) { - return webidl.converters.Request(V) + return webidl.converters.Request(V, prefix, argument) } - return webidl.converters.USVString(V) + return webidl.converters.USVString(V, prefix, argument) } webidl.converters.AbortSignal = webidl.interfaceConverter( @@ -1011,6 +1012,8 @@ webidl.converters.RequestInit = webidl.dictionaryConverter([ converter: webidl.nullableConverter( (signal) => webidl.converters.AbortSignal( signal, + 'RequestInit', + 'signal', { strict: false } ) ) diff --git a/lib/web/fetch/response.js b/lib/web/fetch/response.js index f609e3d4c5d..222a9a5b2f7 100644 --- a/lib/web/fetch/response.js +++ b/lib/web/fetch/response.js @@ -43,7 +43,7 @@ class Response { // https://fetch.spec.whatwg.org/#dom-response-json static json (data, init = {}) { - webidl.argumentLengthCheck(arguments, 1, { header: 'Response.json' }) + webidl.argumentLengthCheck(arguments, 1, 'Response.json') if (init !== null) { init = webidl.converters.ResponseInit(init) @@ -70,7 +70,7 @@ class Response { // Creates a redirect Response that redirects to url with status status. static redirect (url, status = 302) { - webidl.argumentLengthCheck(arguments, 1, { header: 'Response.redirect' }) + webidl.argumentLengthCheck(arguments, 1, 'Response.redirect') url = webidl.converters.USVString(url) status = webidl.converters['unsigned short'](status) @@ -526,34 +526,34 @@ webidl.converters.URLSearchParams = webidl.interfaceConverter( ) // https://fetch.spec.whatwg.org/#typedefdef-xmlhttprequestbodyinit -webidl.converters.XMLHttpRequestBodyInit = function (V) { +webidl.converters.XMLHttpRequestBodyInit = function (V, prefix, name) { if (typeof V === 'string') { - return webidl.converters.USVString(V) + return webidl.converters.USVString(V, prefix, name) } if (isBlobLike(V)) { - return webidl.converters.Blob(V, { strict: false }) + return webidl.converters.Blob(V, prefix, name, { strict: false }) } if (ArrayBuffer.isView(V) || types.isArrayBuffer(V)) { - return webidl.converters.BufferSource(V) + return webidl.converters.BufferSource(V, prefix, name) } if (util.isFormDataLike(V)) { - return webidl.converters.FormData(V, { strict: false }) + return webidl.converters.FormData(V, prefix, name, { strict: false }) } if (V instanceof URLSearchParams) { - return webidl.converters.URLSearchParams(V) + return webidl.converters.URLSearchParams(V, prefix, name) } - return webidl.converters.DOMString(V) + return webidl.converters.DOMString(V, prefix, name) } // https://fetch.spec.whatwg.org/#bodyinit -webidl.converters.BodyInit = function (V) { +webidl.converters.BodyInit = function (V, prefix, argument) { if (V instanceof ReadableStream) { - return webidl.converters.ReadableStream(V) + return webidl.converters.ReadableStream(V, prefix, argument) } // Note: the spec doesn't include async iterables, @@ -562,19 +562,19 @@ webidl.converters.BodyInit = function (V) { return V } - return webidl.converters.XMLHttpRequestBodyInit(V) + return webidl.converters.XMLHttpRequestBodyInit(V, prefix, argument) } webidl.converters.ResponseInit = webidl.dictionaryConverter([ { key: 'status', converter: webidl.converters['unsigned short'], - defaultValue: 200 + defaultValue: () => 200 }, { key: 'statusText', converter: webidl.converters.ByteString, - defaultValue: '' + defaultValue: () => '' }, { key: 'headers', diff --git a/lib/web/fetch/util.js b/lib/web/fetch/util.js index a684c27d883..299f4e64c81 100644 --- a/lib/web/fetch/util.js +++ b/lib/web/fetch/util.js @@ -1016,7 +1016,7 @@ function iteratorMixin (name, object, kInternalIterator, keyIndex = 0, valueInde configurable: true, value: function forEach (callbackfn, thisArg = globalThis) { webidl.brandCheck(this, object) - webidl.argumentLengthCheck(arguments, 1, { header: `${name}.forEach` }) + webidl.argumentLengthCheck(arguments, 1, `${name}.forEach`) if (typeof callbackfn !== 'function') { throw new TypeError( `Failed to execute 'forEach' on '${name}': parameter 1 is not of type 'Function'.` diff --git a/lib/web/fetch/webidl.js b/lib/web/fetch/webidl.js index ceb7f3e8b09..c90e411afca 100644 --- a/lib/web/fetch/webidl.js +++ b/lib/web/fetch/webidl.js @@ -33,14 +33,18 @@ webidl.errors.invalidArgument = function (context) { } // https://webidl.spec.whatwg.org/#implements -webidl.brandCheck = function (V, I, opts = undefined) { +webidl.brandCheck = function (V, I, opts) { if (opts?.strict !== false) { if (!(V instanceof I)) { - throw new TypeError('Illegal invocation') + const err = new TypeError('Illegal invocation') + err.code = 'ERR_INVALID_THIS' // node compat. + throw err } } else { if (V?.[Symbol.toStringTag] !== I.prototype[Symbol.toStringTag]) { - throw new TypeError('Illegal invocation') + const err = new TypeError('Illegal invocation') + err.code = 'ERR_INVALID_THIS' // node compat. + throw err } } } @@ -50,7 +54,7 @@ webidl.argumentLengthCheck = function ({ length }, min, ctx) { throw webidl.errors.exception({ message: `${min} argument${min !== 1 ? 's' : ''} required, ` + `but${length ? ' only' : ''} ${length} found.`, - ...ctx + header: ctx }) } } @@ -83,7 +87,7 @@ webidl.util.Type = function (V) { } // https://webidl.spec.whatwg.org/#abstract-opdef-converttoint -webidl.util.ConvertToInt = function (V, bitLength, signedness, opts = {}) { +webidl.util.ConvertToInt = function (V, bitLength, signedness, opts) { let upperBound let lowerBound @@ -127,7 +131,7 @@ webidl.util.ConvertToInt = function (V, bitLength, signedness, opts = {}) { // 6. If the conversion is to an IDL type associated // with the [EnforceRange] extended attribute, then: - if (opts.enforceRange === true) { + if (opts?.enforceRange === true) { // 1. If x is NaN, +∞, or −∞, then throw a TypeError. if ( Number.isNaN(x) || @@ -159,7 +163,7 @@ webidl.util.ConvertToInt = function (V, bitLength, signedness, opts = {}) { // 7. If x is not NaN and the conversion is to an IDL // type associated with the [Clamp] extended // attribute, then: - if (!Number.isNaN(x) && opts.clamp === true) { + if (!Number.isNaN(x) && opts?.clamp === true) { // 1. Set x to min(max(x, lowerBound), upperBound). x = Math.min(Math.max(x, lowerBound), upperBound) @@ -233,12 +237,12 @@ webidl.util.Stringify = function (V) { // https://webidl.spec.whatwg.org/#es-sequence webidl.sequenceConverter = function (converter) { - return (V, Iterable) => { + return (V, prefix, argument, Iterable) => { // 1. If Type(V) is not Object, throw a TypeError. if (webidl.util.Type(V) !== 'Object') { throw webidl.errors.exception({ - header: 'Sequence', - message: `Value of type ${webidl.util.Type(V)} is not an Object.` + header: prefix, + message: `${argument} (${webidl.util.Stringify(V)}) is not an Object.` }) } @@ -253,8 +257,8 @@ webidl.sequenceConverter = function (converter) { typeof method.next !== 'function' ) { throw webidl.errors.exception({ - header: 'Sequence', - message: 'Object is not an iterator.' + header: prefix, + message: `${argument} is not iterable.` }) } @@ -266,7 +270,7 @@ webidl.sequenceConverter = function (converter) { break } - seq.push(converter(value)) + seq.push(converter(value, prefix, argument)) } return seq @@ -275,12 +279,12 @@ webidl.sequenceConverter = function (converter) { // https://webidl.spec.whatwg.org/#es-to-record webidl.recordConverter = function (keyConverter, valueConverter) { - return (O) => { + return (O, prefix, argument) => { // 1. If Type(O) is not Object, throw a TypeError. if (webidl.util.Type(O) !== 'Object') { throw webidl.errors.exception({ - header: 'Record', - message: `Value of type ${webidl.util.Type(O)} is not an Object.` + header: prefix, + message: `${argument} ("${webidl.util.Type(O)}") is not an Object.` }) } @@ -293,11 +297,11 @@ webidl.recordConverter = function (keyConverter, valueConverter) { for (const key of keys) { // 1. Let typedKey be key converted to an IDL value of type K. - const typedKey = keyConverter(key) + const typedKey = keyConverter(key, prefix, argument) // 2. Let value be ? Get(O, key). // 3. Let typedValue be value converted to an IDL value of type V. - const typedValue = valueConverter(O[key]) + const typedValue = valueConverter(O[key], prefix, argument) // 4. Set result[typedKey] to typedValue. result[typedKey] = typedValue @@ -318,11 +322,11 @@ webidl.recordConverter = function (keyConverter, valueConverter) { // 2. If desc is not undefined and desc.[[Enumerable]] is true: if (desc?.enumerable) { // 1. Let typedKey be key converted to an IDL value of type K. - const typedKey = keyConverter(key) + const typedKey = keyConverter(key, prefix, argument) // 2. Let value be ? Get(O, key). // 3. Let typedValue be value converted to an IDL value of type V. - const typedValue = valueConverter(O[key]) + const typedValue = valueConverter(O[key], prefix, argument) // 4. Set result[typedKey] to typedValue. result[typedKey] = typedValue @@ -335,11 +339,11 @@ webidl.recordConverter = function (keyConverter, valueConverter) { } webidl.interfaceConverter = function (i) { - return (V, opts = {}) => { - if (opts.strict !== false && !(V instanceof i)) { + return (V, prefix, argument, opts) => { + if (opts?.strict !== false && !(V instanceof i)) { throw webidl.errors.exception({ - header: i.name, - message: `Expected ${webidl.util.Stringify(V)} to be an instance of ${i.name}.` + header: prefix, + message: `Expected ${argument} ("${webidl.util.Stringify(V)}") to be an instance of ${i.name}.` }) } @@ -348,7 +352,7 @@ webidl.interfaceConverter = function (i) { } webidl.dictionaryConverter = function (converters) { - return (dictionary) => { + return (dictionary, prefix, argument) => { const type = webidl.util.Type(dictionary) const dict = {} @@ -356,7 +360,7 @@ webidl.dictionaryConverter = function (converters) { return dict } else if (type !== 'Object') { throw webidl.errors.exception({ - header: 'Dictionary', + header: prefix, message: `Expected ${dictionary} to be one of: Null, Undefined, Object.` }) } @@ -367,7 +371,7 @@ webidl.dictionaryConverter = function (converters) { if (required === true) { if (!Object.hasOwn(dictionary, key)) { throw webidl.errors.exception({ - header: 'Dictionary', + header: prefix, message: `Missing required key "${key}".` }) } @@ -379,21 +383,21 @@ webidl.dictionaryConverter = function (converters) { // Only use defaultValue if value is undefined and // a defaultValue options was provided. if (hasDefault && value !== null) { - value = value ?? defaultValue + value ??= defaultValue() } // A key can be optional and have no default value. // When this happens, do not perform a conversion, // and do not assign the key a value. if (required || hasDefault || value !== undefined) { - value = converter(value) + value = converter(value, prefix, argument) if ( options.allowedValues && !options.allowedValues.includes(value) ) { throw webidl.errors.exception({ - header: 'Dictionary', + header: prefix, message: `${value} is not an accepted type. Expected one of ${options.allowedValues.join(', ')}.` }) } @@ -407,28 +411,31 @@ webidl.dictionaryConverter = function (converters) { } webidl.nullableConverter = function (converter) { - return (V) => { + return (V, prefix, argument) => { if (V === null) { return V } - return converter(V) + return converter(V, prefix, argument) } } // https://webidl.spec.whatwg.org/#es-DOMString -webidl.converters.DOMString = function (V, opts = {}) { +webidl.converters.DOMString = function (V, prefix, argument, opts) { // 1. If V is null and the conversion is to an IDL type // associated with the [LegacyNullToEmptyString] // extended attribute, then return the DOMString value // that represents the empty string. - if (V === null && opts.legacyNullToEmptyString) { + if (V === null && opts?.legacyNullToEmptyString) { return '' } // 2. Let x be ? ToString(V). if (typeof V === 'symbol') { - throw new TypeError('Could not convert argument of type symbol to string.') + throw webidl.errors.exception({ + header: prefix, + message: `${argument} is a symbol, which cannot be converted to a DOMString.` + }) } // 3. Return the IDL DOMString value that represents the @@ -438,10 +445,10 @@ webidl.converters.DOMString = function (V, opts = {}) { } // https://webidl.spec.whatwg.org/#es-ByteString -webidl.converters.ByteString = function (V) { +webidl.converters.ByteString = function (V, prefix, argument) { // 1. Let x be ? ToString(V). // Note: DOMString converter perform ? ToString(V) - const x = webidl.converters.DOMString(V) + const x = webidl.converters.DOMString(V, prefix, argument) // 2. If the value of any element of x is greater than // 255, then throw a TypeError. @@ -461,6 +468,7 @@ webidl.converters.ByteString = function (V) { } // https://webidl.spec.whatwg.org/#es-USVString +// TODO: rewrite this so we can control the errors thrown webidl.converters.USVString = toUSVString // https://webidl.spec.whatwg.org/#es-boolean @@ -479,9 +487,9 @@ webidl.converters.any = function (V) { } // https://webidl.spec.whatwg.org/#es-long-long -webidl.converters['long long'] = function (V) { +webidl.converters['long long'] = function (V, prefix, argument) { // 1. Let x be ? ConvertToInt(V, 64, "signed"). - const x = webidl.util.ConvertToInt(V, 64, 'signed') + const x = webidl.util.ConvertToInt(V, 64, 'signed', undefined, prefix, argument) // 2. Return the IDL long long value that represents // the same numeric value as x. @@ -489,9 +497,9 @@ webidl.converters['long long'] = function (V) { } // https://webidl.spec.whatwg.org/#es-unsigned-long-long -webidl.converters['unsigned long long'] = function (V) { +webidl.converters['unsigned long long'] = function (V, prefix, argument) { // 1. Let x be ? ConvertToInt(V, 64, "unsigned"). - const x = webidl.util.ConvertToInt(V, 64, 'unsigned') + const x = webidl.util.ConvertToInt(V, 64, 'unsigned', undefined, prefix, argument) // 2. Return the IDL unsigned long long value that // represents the same numeric value as x. @@ -499,9 +507,9 @@ webidl.converters['unsigned long long'] = function (V) { } // https://webidl.spec.whatwg.org/#es-unsigned-long -webidl.converters['unsigned long'] = function (V) { +webidl.converters['unsigned long'] = function (V, prefix, argument) { // 1. Let x be ? ConvertToInt(V, 32, "unsigned"). - const x = webidl.util.ConvertToInt(V, 32, 'unsigned') + const x = webidl.util.ConvertToInt(V, 32, 'unsigned', undefined, prefix, argument) // 2. Return the IDL unsigned long value that // represents the same numeric value as x. @@ -509,9 +517,9 @@ webidl.converters['unsigned long'] = function (V) { } // https://webidl.spec.whatwg.org/#es-unsigned-short -webidl.converters['unsigned short'] = function (V, opts) { +webidl.converters['unsigned short'] = function (V, prefix, argument, opts) { // 1. Let x be ? ConvertToInt(V, 16, "unsigned"). - const x = webidl.util.ConvertToInt(V, 16, 'unsigned', opts) + const x = webidl.util.ConvertToInt(V, 16, 'unsigned', opts, prefix, argument) // 2. Return the IDL unsigned short value that represents // the same numeric value as x. @@ -519,7 +527,7 @@ webidl.converters['unsigned short'] = function (V, opts) { } // https://webidl.spec.whatwg.org/#idl-ArrayBuffer -webidl.converters.ArrayBuffer = function (V, opts = {}) { +webidl.converters.ArrayBuffer = function (V, prefix, argument, opts) { // 1. If Type(V) is not Object, or V does not have an // [[ArrayBufferData]] internal slot, then throw a // TypeError. @@ -530,8 +538,8 @@ webidl.converters.ArrayBuffer = function (V, opts = {}) { !types.isAnyArrayBuffer(V) ) { throw webidl.errors.conversionFailed({ - prefix: webidl.util.Stringify(V), - argument: webidl.util.Stringify(V), + prefix, + argument: `${argument} ("${webidl.util.Stringify(V)}")`, types: ['ArrayBuffer'] }) } @@ -540,7 +548,7 @@ webidl.converters.ArrayBuffer = function (V, opts = {}) { // with the [AllowShared] extended attribute, and // IsSharedArrayBuffer(V) is true, then throw a // TypeError. - if (opts.allowShared === false && types.isSharedArrayBuffer(V)) { + if (opts?.allowShared === false && types.isSharedArrayBuffer(V)) { throw webidl.errors.exception({ header: 'ArrayBuffer', message: 'SharedArrayBuffer is not allowed.' @@ -563,7 +571,7 @@ webidl.converters.ArrayBuffer = function (V, opts = {}) { return V } -webidl.converters.TypedArray = function (V, T, opts = {}) { +webidl.converters.TypedArray = function (V, T, prefix, name, opts) { // 1. Let T be the IDL type V is being converted to. // 2. If Type(V) is not Object, or V does not have a @@ -575,8 +583,8 @@ webidl.converters.TypedArray = function (V, T, opts = {}) { V.constructor.name !== T.name ) { throw webidl.errors.conversionFailed({ - prefix: `${T.name}`, - argument: webidl.util.Stringify(V), + prefix, + argument: `${name} ("${webidl.util.Stringify(V)}")`, types: [T.name] }) } @@ -585,7 +593,7 @@ webidl.converters.TypedArray = function (V, T, opts = {}) { // with the [AllowShared] extended attribute, and // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is // true, then throw a TypeError. - if (opts.allowShared === false && types.isSharedArrayBuffer(V.buffer)) { + if (opts?.allowShared === false && types.isSharedArrayBuffer(V.buffer)) { throw webidl.errors.exception({ header: 'ArrayBuffer', message: 'SharedArrayBuffer is not allowed.' @@ -608,13 +616,13 @@ webidl.converters.TypedArray = function (V, T, opts = {}) { return V } -webidl.converters.DataView = function (V, opts = {}) { +webidl.converters.DataView = function (V, prefix, name, opts) { // 1. If Type(V) is not Object, or V does not have a // [[DataView]] internal slot, then throw a TypeError. if (webidl.util.Type(V) !== 'Object' || !types.isDataView(V)) { throw webidl.errors.exception({ - header: 'DataView', - message: 'Object is not a DataView.' + header: prefix, + message: `${name} is not a DataView.` }) } @@ -622,7 +630,7 @@ webidl.converters.DataView = function (V, opts = {}) { // with the [AllowShared] extended attribute, and // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is true, // then throw a TypeError. - if (opts.allowShared === false && types.isSharedArrayBuffer(V.buffer)) { + if (opts?.allowShared === false && types.isSharedArrayBuffer(V.buffer)) { throw webidl.errors.exception({ header: 'ArrayBuffer', message: 'SharedArrayBuffer is not allowed.' @@ -646,20 +654,24 @@ webidl.converters.DataView = function (V, opts = {}) { } // https://webidl.spec.whatwg.org/#BufferSource -webidl.converters.BufferSource = function (V, opts = {}) { +webidl.converters.BufferSource = function (V, prefix, name, opts) { if (types.isAnyArrayBuffer(V)) { - return webidl.converters.ArrayBuffer(V, { ...opts, allowShared: false }) + return webidl.converters.ArrayBuffer(V, prefix, name, { ...opts, allowShared: false }) } if (types.isTypedArray(V)) { - return webidl.converters.TypedArray(V, V.constructor, { ...opts, allowShared: false }) + return webidl.converters.TypedArray(V, V.constructor, prefix, name, { ...opts, allowShared: false }) } if (types.isDataView(V)) { - return webidl.converters.DataView(V, opts, { ...opts, allowShared: false }) + return webidl.converters.DataView(V, prefix, name, { ...opts, allowShared: false }) } - throw new TypeError(`Could not convert ${webidl.util.Stringify(V)} to a BufferSource.`) + throw webidl.errors.conversionFailed({ + prefix, + argument: `${name} ("${webidl.util.Stringify(V)}")`, + types: ['BufferSource'] + }) } webidl.converters['sequence'] = webidl.sequenceConverter( diff --git a/lib/web/fileapi/filereader.js b/lib/web/fileapi/filereader.js index 0cca813994e..ccebe692a6f 100644 --- a/lib/web/fileapi/filereader.js +++ b/lib/web/fileapi/filereader.js @@ -39,7 +39,7 @@ class FileReader extends EventTarget { readAsArrayBuffer (blob) { webidl.brandCheck(this, FileReader) - webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsArrayBuffer' }) + webidl.argumentLengthCheck(arguments, 1, 'FileReader.readAsArrayBuffer') blob = webidl.converters.Blob(blob, { strict: false }) @@ -55,7 +55,7 @@ class FileReader extends EventTarget { readAsBinaryString (blob) { webidl.brandCheck(this, FileReader) - webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsBinaryString' }) + webidl.argumentLengthCheck(arguments, 1, 'FileReader.readAsBinaryString') blob = webidl.converters.Blob(blob, { strict: false }) @@ -72,12 +72,12 @@ class FileReader extends EventTarget { readAsText (blob, encoding = undefined) { webidl.brandCheck(this, FileReader) - webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsText' }) + webidl.argumentLengthCheck(arguments, 1, 'FileReader.readAsText') blob = webidl.converters.Blob(blob, { strict: false }) if (encoding !== undefined) { - encoding = webidl.converters.DOMString(encoding) + encoding = webidl.converters.DOMString(encoding, 'FileReader.readAsText', 'encoding') } // The readAsText(blob, encoding) method, when invoked, @@ -92,7 +92,7 @@ class FileReader extends EventTarget { readAsDataURL (blob) { webidl.brandCheck(this, FileReader) - webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsDataURL' }) + webidl.argumentLengthCheck(arguments, 1, 'FileReader.readAsDataURL') blob = webidl.converters.Blob(blob, { strict: false }) diff --git a/lib/web/fileapi/progressevent.js b/lib/web/fileapi/progressevent.js index 778cf224c6a..2d09d18107d 100644 --- a/lib/web/fileapi/progressevent.js +++ b/lib/web/fileapi/progressevent.js @@ -9,7 +9,7 @@ const kState = Symbol('ProgressEvent state') */ class ProgressEvent extends Event { constructor (type, eventInitDict = {}) { - type = webidl.converters.DOMString(type) + type = webidl.converters.DOMString(type, 'ProgressEvent constructor', 'type') eventInitDict = webidl.converters.ProgressEventInit(eventInitDict ?? {}) super(type, eventInitDict) @@ -44,32 +44,32 @@ webidl.converters.ProgressEventInit = webidl.dictionaryConverter([ { key: 'lengthComputable', converter: webidl.converters.boolean, - defaultValue: false + defaultValue: () => false }, { key: 'loaded', converter: webidl.converters['unsigned long long'], - defaultValue: 0 + defaultValue: () => 0 }, { key: 'total', converter: webidl.converters['unsigned long long'], - defaultValue: 0 + defaultValue: () => 0 }, { key: 'bubbles', converter: webidl.converters.boolean, - defaultValue: false + defaultValue: () => false }, { key: 'cancelable', converter: webidl.converters.boolean, - defaultValue: false + defaultValue: () => false }, { key: 'composed', converter: webidl.converters.boolean, - defaultValue: false + defaultValue: () => false } ]) diff --git a/lib/web/websocket/events.js b/lib/web/websocket/events.js index 7b3bb263c61..760b7297359 100644 --- a/lib/web/websocket/events.js +++ b/lib/web/websocket/events.js @@ -17,10 +17,11 @@ class MessageEvent extends Event { return } - webidl.argumentLengthCheck(arguments, 1, { header: 'MessageEvent constructor' }) + const prefix = 'MessageEvent constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) - type = webidl.converters.DOMString(type) - eventInitDict = webidl.converters.MessageEventInit(eventInitDict) + type = webidl.converters.DOMString(type, prefix, 'type') + eventInitDict = webidl.converters.MessageEventInit(eventInitDict, prefix, 'eventInitDict') super(type, eventInitDict) @@ -73,7 +74,7 @@ class MessageEvent extends Event { ) { webidl.brandCheck(this, MessageEvent) - webidl.argumentLengthCheck(arguments, 1, { header: 'MessageEvent.initMessageEvent' }) + webidl.argumentLengthCheck(arguments, 1, 'MessageEvent.initMessageEvent') return new MessageEvent(type, { bubbles, cancelable, data, origin, lastEventId, source, ports @@ -102,9 +103,10 @@ class CloseEvent extends Event { #eventInit constructor (type, eventInitDict = {}) { - webidl.argumentLengthCheck(arguments, 1, { header: 'CloseEvent constructor' }) + const prefix = 'CloseEvent constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) - type = webidl.converters.DOMString(type) + type = webidl.converters.DOMString(type, prefix, 'type') eventInitDict = webidl.converters.CloseEventInit(eventInitDict) super(type, eventInitDict) @@ -136,11 +138,12 @@ class ErrorEvent extends Event { #eventInit constructor (type, eventInitDict) { - webidl.argumentLengthCheck(arguments, 1, { header: 'ErrorEvent constructor' }) + const prefix = 'ErrorEvent constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) super(type, eventInitDict) - type = webidl.converters.DOMString(type) + type = webidl.converters.DOMString(type, prefix, 'type') eventInitDict = webidl.converters.ErrorEventInit(eventInitDict ?? {}) this.#eventInit = eventInitDict @@ -222,17 +225,17 @@ const eventInit = [ { key: 'bubbles', converter: webidl.converters.boolean, - defaultValue: false + defaultValue: () => false }, { key: 'cancelable', converter: webidl.converters.boolean, - defaultValue: false + defaultValue: () => false }, { key: 'composed', converter: webidl.converters.boolean, - defaultValue: false + defaultValue: () => false } ] @@ -241,31 +244,29 @@ webidl.converters.MessageEventInit = webidl.dictionaryConverter([ { key: 'data', converter: webidl.converters.any, - defaultValue: null + defaultValue: () => null }, { key: 'origin', converter: webidl.converters.USVString, - defaultValue: '' + defaultValue: () => '' }, { key: 'lastEventId', converter: webidl.converters.DOMString, - defaultValue: '' + defaultValue: () => '' }, { key: 'source', // Node doesn't implement WindowProxy or ServiceWorker, so the only // valid value for source is a MessagePort. converter: webidl.nullableConverter(webidl.converters.MessagePort), - defaultValue: null + defaultValue: () => null }, { key: 'ports', converter: webidl.converters['sequence'], - get defaultValue () { - return [] - } + defaultValue: () => new Array(0) } ]) @@ -274,17 +275,17 @@ webidl.converters.CloseEventInit = webidl.dictionaryConverter([ { key: 'wasClean', converter: webidl.converters.boolean, - defaultValue: false + defaultValue: () => false }, { key: 'code', converter: webidl.converters['unsigned short'], - defaultValue: 0 + defaultValue: () => 0 }, { key: 'reason', converter: webidl.converters.USVString, - defaultValue: '' + defaultValue: () => '' } ]) @@ -293,22 +294,22 @@ webidl.converters.ErrorEventInit = webidl.dictionaryConverter([ { key: 'message', converter: webidl.converters.DOMString, - defaultValue: '' + defaultValue: () => '' }, { key: 'filename', converter: webidl.converters.USVString, - defaultValue: '' + defaultValue: () => '' }, { key: 'lineno', converter: webidl.converters['unsigned long'], - defaultValue: 0 + defaultValue: () => 0 }, { key: 'colno', converter: webidl.converters['unsigned long'], - defaultValue: 0 + defaultValue: () => 0 }, { key: 'error', diff --git a/lib/web/websocket/websocket.js b/lib/web/websocket/websocket.js index c4b40b43188..00e81cbafca 100644 --- a/lib/web/websocket/websocket.js +++ b/lib/web/websocket/websocket.js @@ -51,7 +51,8 @@ class WebSocket extends EventTarget { constructor (url, protocols = []) { super() - webidl.argumentLengthCheck(arguments, 1, { header: 'WebSocket constructor' }) + const prefix = 'WebSocket constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) if (!experimentalWarned) { experimentalWarned = true @@ -60,9 +61,9 @@ class WebSocket extends EventTarget { }) } - const options = webidl.converters['DOMString or sequence or WebSocketInit'](protocols) + const options = webidl.converters['DOMString or sequence or WebSocketInit'](protocols, prefix, 'options') - url = webidl.converters.USVString(url) + url = webidl.converters.USVString(url, prefix, 'url') protocols = options.protocols // 1. Let baseURL be this's relevant settings object's API base URL. @@ -159,12 +160,14 @@ class WebSocket extends EventTarget { close (code = undefined, reason = undefined) { webidl.brandCheck(this, WebSocket) + const prefix = 'WebSocket.close' + if (code !== undefined) { - code = webidl.converters['unsigned short'](code, { clamp: true }) + code = webidl.converters['unsigned short'](code, prefix, 'code', { clamp: true }) } if (reason !== undefined) { - reason = webidl.converters.USVString(reason) + reason = webidl.converters.USVString(reason, prefix, 'reason') } // 1. If code is present, but is neither an integer equal to 1000 nor an @@ -264,9 +267,10 @@ class WebSocket extends EventTarget { send (data) { webidl.brandCheck(this, WebSocket) - webidl.argumentLengthCheck(arguments, 1, { header: 'WebSocket.send' }) + const prefix = 'WebSocket.send' + webidl.argumentLengthCheck(arguments, 1, prefix) - data = webidl.converters.WebSocketSendData(data) + data = webidl.converters.WebSocketSendData(data, prefix, 'data') // 1. If this's ready state is CONNECTING, then throw an // "InvalidStateError" DOMException. @@ -595,12 +599,12 @@ webidl.converters['sequence'] = webidl.sequenceConverter( webidl.converters.DOMString ) -webidl.converters['DOMString or sequence'] = function (V) { +webidl.converters['DOMString or sequence'] = function (V, prefix, argument) { if (webidl.util.Type(V) === 'Object' && Symbol.iterator in V) { return webidl.converters['sequence'](V) } - return webidl.converters.DOMString(V) + return webidl.converters.DOMString(V, prefix, argument) } // This implements the propsal made in https://github.com/whatwg/websockets/issues/42 @@ -608,16 +612,12 @@ webidl.converters.WebSocketInit = webidl.dictionaryConverter([ { key: 'protocols', converter: webidl.converters['DOMString or sequence'], - get defaultValue () { - return [] - } + defaultValue: () => new Array(0) }, { key: 'dispatcher', converter: (V) => V, - get defaultValue () { - return getGlobalDispatcher() - } + defaultValue: () => getGlobalDispatcher() }, { key: 'headers', diff --git a/test/fetch/headers.js b/test/fetch/headers.js index ac1183eeded..91ba61f6e23 100644 --- a/test/fetch/headers.js +++ b/test/fetch/headers.js @@ -27,7 +27,7 @@ test('Headers initialization', async (t) => { throws(() => new Headers(['undici', 'fetch', 'fetch']), TypeError) throws( () => new Headers([0, 1, 2]), - TypeError('Sequence: Value of type Number is not an Object.') + TypeError('Headers contructor: init (0) is not an Object.') ) }) @@ -42,7 +42,7 @@ test('Headers initialization', async (t) => { const init = ['undici', 'fetch', 'fetch', 'undici'] throws( () => new Headers(init), - TypeError('Sequence: Value of type String is not an Object.') + TypeError('Headers contructor: init ("undici") is not an Object.') ) }) }) diff --git a/test/webidl/converters.js b/test/webidl/converters.js index f39c05a8d7b..c5f4ce88d71 100644 --- a/test/webidl/converters.js +++ b/test/webidl/converters.js @@ -12,19 +12,19 @@ test('sequence', () => { assert.deepStrictEqual(converter([1, 2, 3]), ['1', '2', '3']) assert.throws(() => { - converter(3) + converter(3, 'converter', 'converter') }, TypeError, 'disallows non-objects') assert.throws(() => { - converter(null) + converter(null, 'converter', 'converter') }, TypeError) assert.throws(() => { - converter(undefined) + converter(undefined, 'converter', 'converter') }, TypeError) assert.throws(() => { - converter({}) + converter({}, 'converter', 'converter') }, TypeError, 'no Symbol.iterator') assert.throws(() => { @@ -40,7 +40,7 @@ test('sequence', () => { next: 'never!' } } - })) + }), 'converter', 'converter') }, TypeError, 'invalid generator') }) @@ -49,12 +49,12 @@ describe('webidl.dictionaryConverter', () => { const converter = webidl.dictionaryConverter([]) assert.throws(() => { - converter(true) + converter(true, 'converter', 'converter') }, TypeError) for (const value of [{}, undefined, null]) { assert.doesNotThrow(() => { - converter(value) + converter(value, 'converter', 'converter') }) } }) @@ -69,47 +69,47 @@ describe('webidl.dictionaryConverter', () => { ]) assert.throws(() => { - converter({ wrongKey: 'key' }) + converter({ wrongKey: 'key' }, 'converter', 'converter') }, TypeError) assert.doesNotThrow(() => { - converter({ Key: 'this key was required!' }) + converter({ Key: 'this key was required!' }, 'converter', 'converter') }) }) }) test('ArrayBuffer', () => { assert.throws(() => { - webidl.converters.ArrayBuffer(true) + webidl.converters.ArrayBuffer(true, 'converter', 'converter') }, TypeError) assert.throws(() => { - webidl.converters.ArrayBuffer({}) + webidl.converters.ArrayBuffer({}, 'converter', 'converter') }, TypeError) assert.throws(() => { const sab = new SharedArrayBuffer(1024) - webidl.converters.ArrayBuffer(sab, { allowShared: false }) + webidl.converters.ArrayBuffer(sab, 'converter', 'converter', { allowShared: false }) }, TypeError) assert.doesNotThrow(() => { const sab = new SharedArrayBuffer(1024) - webidl.converters.ArrayBuffer(sab) + webidl.converters.ArrayBuffer(sab, 'converter', 'converter') }) assert.doesNotThrow(() => { const ab = new ArrayBuffer(8) - webidl.converters.ArrayBuffer(ab) + webidl.converters.ArrayBuffer(ab, 'converter', 'converter') }) }) test('TypedArray', () => { assert.throws(() => { - webidl.converters.TypedArray(3) + webidl.converters.TypedArray(3, 'converter', 'converter') }, TypeError) assert.throws(() => { - webidl.converters.TypedArray({}) + webidl.converters.TypedArray({}, 'converter', 'converter') }, TypeError) assert.throws(() => { @@ -120,7 +120,7 @@ test('TypedArray', () => { } }) - webidl.converters.TypedArray(uint8, Uint8Array, { + webidl.converters.TypedArray(uint8, Uint8Array, 'converter', 'converter', { allowShared: false }) }, TypeError) @@ -128,11 +128,11 @@ test('TypedArray', () => { test('DataView', () => { assert.throws(() => { - webidl.converters.DataView(3) + webidl.converters.DataView(3, 'converter', 'converter') }, TypeError) assert.throws(() => { - webidl.converters.DataView({}) + webidl.converters.DataView({}, 'converter', 'converter') }, TypeError) assert.throws(() => { @@ -145,7 +145,7 @@ test('DataView', () => { } }) - webidl.converters.DataView(view, { + webidl.converters.DataView(view, 'converter', 'converter', { allowShared: false }) }) @@ -153,7 +153,7 @@ test('DataView', () => { const buffer = new ArrayBuffer(16) const view = new DataView(buffer, 0) - assert.equal(webidl.converters.DataView(view), view) + assert.equal(webidl.converters.DataView(view, 'converter', 'converter'), view) }) test('BufferSource', () => { @@ -161,23 +161,23 @@ test('BufferSource', () => { const buffer = new ArrayBuffer(16) const view = new DataView(buffer, 0) - webidl.converters.BufferSource(view) + webidl.converters.BufferSource(view, 'converter', 'converter') }) assert.throws(() => { - webidl.converters.BufferSource(3) + webidl.converters.BufferSource(3, 'converter', 'converter') }, TypeError) }) test('ByteString', () => { assert.doesNotThrow(() => { - webidl.converters.ByteString('') + webidl.converters.ByteString('', 'converter', 'converter') }) // https://github.com/nodejs/undici/issues/1590 assert.throws(() => { const char = String.fromCharCode(256) - webidl.converters.ByteString(`invalid${char}char`) + webidl.converters.ByteString(`invalid${char}char`, 'converter', 'converter') }, { message: 'Cannot convert argument to a ByteString because the character at ' + 'index 7 has a value of 256 which is greater than 255.' diff --git a/test/webidl/errors.js b/test/webidl/errors.js new file mode 100644 index 00000000000..11449fbfd60 --- /dev/null +++ b/test/webidl/errors.js @@ -0,0 +1,23 @@ +'use strict' + +const { test } = require('node:test') +const assert = require('node:assert') +const { Headers } = require('../..') + +test('ByteString', (t) => { + const name = Symbol('') + const value = Symbol('') + + for (const method of [ + 'get', + 'set', + 'delete', + 'append', + 'has' + ]) { + assert.throws( + () => new Headers()[method](name, value), + new TypeError(`Headers.${method}: name is a symbol, which cannot be converted to a DOMString.`) + ) + } +}) diff --git a/test/webidl/helpers.js b/test/webidl/helpers.js index b18baa5fb7b..fcd375f68b4 100644 --- a/test/webidl/helpers.js +++ b/test/webidl/helpers.js @@ -11,11 +11,11 @@ test('webidl.interfaceConverter', () => { const converter = webidl.interfaceConverter(A) assert.throws(() => { - converter(new B()) + converter(new B(), 'converter', 'converter') }, TypeError) assert.doesNotThrow(() => { - converter(new A()) + converter(new A(), 'converter', 'converter') }) }) @@ -38,7 +38,7 @@ describe('webidl.dictionaryConverter', () => { get value () { return 6 } - }), + }, 'converter', 'converter'), { key: 'string' } ) }) @@ -52,7 +52,7 @@ describe('webidl.dictionaryConverter', () => { } ]) - assert.deepStrictEqual(converter({ key: null }), { key: 0 }) + assert.deepStrictEqual(converter({ key: null }, 'converter', 'converter'), { key: 0 }) }) test('no defaultValue and optional', () => { @@ -63,6 +63,6 @@ describe('webidl.dictionaryConverter', () => { } ]) - assert.deepStrictEqual(converter({ a: 'b', c: 'd' }), {}) + assert.deepStrictEqual(converter({ a: 'b', c: 'd' }, 'converter', 'converter'), {}) }) }) diff --git a/test/websocket/messageevent.js b/test/websocket/messageevent.js index de3b6c5fc8e..b1381019c27 100644 --- a/test/websocket/messageevent.js +++ b/test/websocket/messageevent.js @@ -99,25 +99,25 @@ test('test/parallel/test-worker-message-port.js', () => { assert.throws(() => new MessageEvent('message', { source: 1 }), { constructor: TypeError, - message: 'MessagePort: Expected 1 to be an instance of MessagePort.' + message: 'MessageEvent constructor: Expected eventInitDict ("1") to be an instance of MessagePort.' }) assert.throws(() => new MessageEvent('message', { source: {} }), { constructor: TypeError, - message: 'MessagePort: Expected {} to be an instance of MessagePort.' + message: 'MessageEvent constructor: Expected eventInitDict ("{}") to be an instance of MessagePort.' }) assert.throws(() => new MessageEvent('message', { ports: 0 }), { constructor: TypeError, - message: 'Sequence: Value of type Number is not an Object.' + message: 'MessageEvent constructor: eventInitDict (0) is not an Object.' }) assert.throws(() => new MessageEvent('message', { ports: [null] }), { constructor: TypeError, - message: 'MessagePort: Expected null to be an instance of MessagePort.' + message: 'MessageEvent constructor: Expected eventInitDict ("null") to be an instance of MessagePort.' }) assert.throws(() => new MessageEvent('message', { ports: [{}] }) , { constructor: TypeError, - message: 'MessagePort: Expected {} to be an instance of MessagePort.' + message: 'MessageEvent constructor: Expected eventInitDict ("{}") to be an instance of MessagePort.' }) assert(new MessageEvent('message') instanceof Event) diff --git a/types/webidl.d.ts b/types/webidl.d.ts index 1e362d6f40d..fe802a20124 100644 --- a/types/webidl.d.ts +++ b/types/webidl.d.ts @@ -55,7 +55,9 @@ interface WebidlUtil { V: unknown, bitLength: number, signedness: 'signed' | 'unsigned', - opts?: ConvertToIntOpts + opts?: ConvertToIntOpts, + prefix: string, + argument: string ): number /** @@ -73,14 +75,14 @@ interface WebidlConverters { /** * @see https://webidl.spec.whatwg.org/#es-DOMString */ - DOMString (V: unknown, opts?: { + DOMString (V: unknown, prefix: string, argument: string, opts?: { legacyNullToEmptyString: boolean }): string /** * @see https://webidl.spec.whatwg.org/#es-ByteString */ - ByteString (V: unknown): string + ByteString (V: unknown, prefix: string, argument: string): string /** * @see https://webidl.spec.whatwg.org/#es-USVString @@ -204,7 +206,7 @@ export interface Webidl { */ dictionaryConverter (converters: { key: string, - defaultValue?: unknown, + defaultValue?: () => unknown, required?: boolean, converter: (...args: unknown[]) => unknown, allowedValues?: unknown[] @@ -218,8 +220,5 @@ export interface Webidl { converter: Converter ): (V: unknown) => ReturnType | null - argumentLengthCheck (args: { length: number }, min: number, context: { - header: string - message?: string - }): void + argumentLengthCheck (args: { length: number }, min: number, context: string): void }