Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve webidl.is.x performance for common case #3708

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions benchmarks/fetch/webidl-is.mjs
Original file line number Diff line number Diff line change
@@ -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()
9 changes: 7 additions & 2 deletions lib/web/fetch/formdata.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')

Expand Down Expand Up @@ -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 }
9 changes: 7 additions & 2 deletions lib/web/fetch/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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) {
Expand Down
9 changes: 7 additions & 2 deletions lib/web/fetch/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -619,7 +624,7 @@ webidl.converters.ResponseInit = webidl.dictionaryConverter([
}
])

webidl.is.Response = webidl.util.MakeTypeAssertion(Response.prototype)
webidl.is.Response = isResponse

module.exports = {
isNetworkError,
Expand Down
11 changes: 8 additions & 3 deletions lib/web/websocket/stream/websocketerror.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -78,6 +83,6 @@ Object.defineProperties(WebSocketError.prototype, {
}
})

webidl.is.WebSocketError = webidl.util.MakeTypeAssertion(WebSocketError.prototype)
webidl.is.WebSocketError = isWebSocketError

module.exports = { WebSocketError, createUnvalidatedWebSocketError }
Loading