diff --git a/benchmarks/fetch/webidl-is.mjs b/benchmarks/fetch/webidl-is.mjs new file mode 100644 index 00000000000..937c1658e47 --- /dev/null +++ b/benchmarks/fetch/webidl-is.mjs @@ -0,0 +1,32 @@ +import { group, bench, run } from 'mitata' +import { webidl } from '../../lib/web/fetch/webidl.js' +import { FormData, Headers } from '../../index.js' + +function assert (value) { + if (!value) { + throw new TypeError('value is not truthy') + } +} + +const isPrototypeOf = webidl.util.MakeTypeAssertion(FormData.prototype) +const privatePropertyIn = webidl.is.FormData + +const fd = new FormData() +const notFd = new Headers() + +group(() => { + bench('common (good) case - isPrototypeOf', () => { + assert(isPrototypeOf(fd)) + }) + bench('uncommon (bad) case - isPrototypeOf', () => { + assert(!isPrototypeOf(notFd)) + }) + bench('common (good) case - #symbol in fd', () => { + assert(privatePropertyIn(fd)) + }) + bench('uncommon (bad) case - #symbol in fd', () => { + assert(!privatePropertyIn(notFd)) + }) +}) + +await run() diff --git a/lib/web/fetch/formdata.js b/lib/web/fetch/formdata.js index ef45cefb369..563a50111d5 100644 --- a/lib/web/fetch/formdata.js +++ b/lib/web/fetch/formdata.js @@ -194,11 +194,16 @@ class FormData { static setFormDataState (formData, newState) { formData.#state = newState } + + static isFormData (value) { + return value !== null && typeof value === 'object' && #state in value + } } -const { getFormDataState, setFormDataState } = FormData +const { getFormDataState, setFormDataState, isFormData } = FormData Reflect.deleteProperty(FormData, 'getFormDataState') Reflect.deleteProperty(FormData, 'setFormDataState') +Reflect.deleteProperty(FormData, 'isFormData') iteratorMixin('FormData', FormData, getFormDataState, 'name', 'value') @@ -256,6 +261,6 @@ function makeEntry (name, value, filename) { return { name, value } } -webidl.is.FormData = webidl.util.MakeTypeAssertion(FormData.prototype) +webidl.is.FormData = isFormData module.exports = { FormData, makeEntry, setFormDataState } diff --git a/lib/web/fetch/request.js b/lib/web/fetch/request.js index fec12b58308..00e49b4f475 100644 --- a/lib/web/fetch/request.js +++ b/lib/web/fetch/request.js @@ -864,15 +864,20 @@ class Request { static setRequestState (request, newState) { request.#state = newState } + + static isRequest (value) { + return value !== null && typeof value === 'object' && #state in value + } } -const { setRequestSignal, getRequestDispatcher, setRequestDispatcher, setRequestHeaders, getRequestState, setRequestState } = Request +const { setRequestSignal, getRequestDispatcher, setRequestDispatcher, setRequestHeaders, getRequestState, setRequestState, isRequest } = Request Reflect.deleteProperty(Request, 'setRequestSignal') Reflect.deleteProperty(Request, 'getRequestDispatcher') Reflect.deleteProperty(Request, 'setRequestDispatcher') Reflect.deleteProperty(Request, 'setRequestHeaders') Reflect.deleteProperty(Request, 'getRequestState') Reflect.deleteProperty(Request, 'setRequestState') +Reflect.deleteProperty(Request, 'isRequest') mixinBody(Request, getRequestState) @@ -986,7 +991,7 @@ Object.defineProperties(Request.prototype, { } }) -webidl.is.Request = webidl.util.MakeTypeAssertion(Request.prototype) +webidl.is.Request = isRequest // https://fetch.spec.whatwg.org/#requestinfo webidl.converters.RequestInfo = function (V, prefix, argument) { diff --git a/lib/web/fetch/response.js b/lib/web/fetch/response.js index 60cee8bb26e..3d7ead654b3 100644 --- a/lib/web/fetch/response.js +++ b/lib/web/fetch/response.js @@ -297,13 +297,18 @@ class Response { static setResponseState (response, newState) { response.#state = newState } + + static isResponse (value) { + return value !== null && typeof value === 'object' && #state in value + } } -const { getResponseHeaders, setResponseHeaders, getResponseState, setResponseState } = Response +const { getResponseHeaders, setResponseHeaders, getResponseState, setResponseState, isResponse } = Response Reflect.deleteProperty(Response, 'getResponseHeaders') Reflect.deleteProperty(Response, 'setResponseHeaders') Reflect.deleteProperty(Response, 'getResponseState') Reflect.deleteProperty(Response, 'setResponseState') +Reflect.deleteProperty(Response, 'isResponse') mixinBody(Response, getResponseState) @@ -619,7 +624,7 @@ webidl.converters.ResponseInit = webidl.dictionaryConverter([ } ]) -webidl.is.Response = webidl.util.MakeTypeAssertion(Response.prototype) +webidl.is.Response = isResponse module.exports = { isNetworkError, diff --git a/lib/web/websocket/stream/websocketerror.js b/lib/web/websocket/stream/websocketerror.js index e47551a96b9..f3d81dc36e9 100644 --- a/lib/web/websocket/stream/websocketerror.js +++ b/lib/web/websocket/stream/websocketerror.js @@ -62,10 +62,15 @@ class WebSocketError extends DOMException { error.#reason = reason return error } + + static isWebSocketError (value) { + return value !== null && typeof value === 'object' && #closeCode in value + } } -const { createUnvalidatedWebSocketError } = WebSocketError -delete WebSocketError.createUnvalidatedWebSocketError +const { createUnvalidatedWebSocketError, isWebSocketError } = WebSocketError +Reflect.deleteProperty(WebSocketError, 'createUnvalidatedWebSocketError') +Reflect.deleteProperty(WebSocketError, 'isWebSocketError') Object.defineProperties(WebSocketError.prototype, { closeCode: kEnumerableProperty, @@ -78,6 +83,6 @@ Object.defineProperties(WebSocketError.prototype, { } }) -webidl.is.WebSocketError = webidl.util.MakeTypeAssertion(WebSocketError.prototype) +webidl.is.WebSocketError = isWebSocketError module.exports = { WebSocketError, createUnvalidatedWebSocketError }