Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion lib/web/fetch/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ class Response {
}

if (body !== null) {
body = webidl.converters.BodyInit(body)
body = webidl.converters.BodyInit(body, 'Response', 'body')
}

init = webidl.converters.ResponseInit(init)
Expand Down
53 changes: 31 additions & 22 deletions lib/web/webidl/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,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 (webidl.util.HasFlag(opts, webidl.attributes.EnforceRange)) {
// 1. If x is NaN, +∞, or −∞, then throw a TypeError.
if (
Number.isNaN(x) ||
Expand Down Expand Up @@ -236,7 +236,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) && webidl.util.HasFlag(opts, webidl.attributes.Clamp)) {
// 1. Set x to min(max(x, lowerBound), upperBound).
x = Math.min(Math.max(x, lowerBound), upperBound)

Expand Down Expand Up @@ -325,6 +325,10 @@ webidl.util.IsResizableArrayBuffer = function (V) {
})
}

webidl.util.HasFlag = function (opts, flag) {
return typeof opts === 'number' && (opts & flag) === flag
}

// https://webidl.spec.whatwg.org/#es-sequence
webidl.sequenceConverter = function (converter) {
return (V, prefix, argument, Iterable) => {
Expand Down Expand Up @@ -542,7 +546,7 @@ webidl.converters.DOMString = function (V, prefix, argument, opts) {
// associated with the [LegacyNullToEmptyString]
// extended attribute, then return the DOMString value
// that represents the empty string.
if (V === null && opts?.legacyNullToEmptyString) {
if (V === null && webidl.util.HasFlag(opts, webidl.attributes.LegacyNullToEmptyString)) {
return ''
}

Expand Down Expand Up @@ -621,7 +625,7 @@ webidl.converters.any = function (V) {
// https://webidl.spec.whatwg.org/#es-long-long
webidl.converters['long long'] = function (V, prefix, argument) {
// 1. Let x be ? ConvertToInt(V, 64, "signed").
const x = webidl.util.ConvertToInt(V, 64, 'signed', undefined, prefix, argument)
const x = webidl.util.ConvertToInt(V, 64, 'signed', 0, prefix, argument)

// 2. Return the IDL long long value that represents
// the same numeric value as x.
Expand All @@ -631,7 +635,7 @@ webidl.converters['long long'] = function (V, prefix, argument) {
// https://webidl.spec.whatwg.org/#es-unsigned-long-long
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', undefined, prefix, argument)
const x = webidl.util.ConvertToInt(V, 64, 'unsigned', 0, prefix, argument)

// 2. Return the IDL unsigned long long value that
// represents the same numeric value as x.
Expand All @@ -641,7 +645,7 @@ webidl.converters['unsigned long long'] = function (V, prefix, argument) {
// https://webidl.spec.whatwg.org/#es-unsigned-long
webidl.converters['unsigned long'] = function (V, prefix, argument) {
// 1. Let x be ? ConvertToInt(V, 32, "unsigned").
const x = webidl.util.ConvertToInt(V, 32, 'unsigned', undefined, prefix, argument)
const x = webidl.util.ConvertToInt(V, 32, 'unsigned', 0, prefix, argument)

// 2. Return the IDL unsigned long value that
// represents the same numeric value as x.
Expand Down Expand Up @@ -681,7 +685,7 @@ webidl.converters.ArrayBuffer = function (V, prefix, argument, opts) {
// with the [AllowResizable] extended attribute, and
// IsResizableArrayBuffer(V) is true, then throw a
// TypeError.
if (!opts?.allowResizable && webidl.util.IsResizableArrayBuffer(V)) {
if (!webidl.util.HasFlag(opts, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V)) {
throw webidl.errors.exception({
header: prefix,
message: `${argument} cannot be a resizable ArrayBuffer.`
Expand Down Expand Up @@ -716,7 +720,7 @@ webidl.converters.SharedArrayBuffer = function (V, prefix, argument, opts) {
// with the [AllowResizable] extended attribute, and
// IsResizableArrayBuffer(V) is true, then throw a
// TypeError.
if (!opts?.allowResizable && webidl.util.IsResizableArrayBuffer(V)) {
if (!webidl.util.HasFlag(opts, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V)) {
throw webidl.errors.exception({
header: prefix,
message: `${argument} cannot be a resizable SharedArrayBuffer.`
Expand Down Expand Up @@ -751,7 +755,7 @@ webidl.converters.TypedArray = function (V, T, prefix, argument, opts) {
// with the [AllowShared] extended attribute, and
// IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is
// true, then throw a TypeError.
if (!opts?.allowShared && types.isSharedArrayBuffer(V.buffer)) {
if (!webidl.util.HasFlag(opts, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) {
throw webidl.errors.exception({
header: prefix,
message: `${argument} cannot be a view on a shared array buffer.`
Expand All @@ -762,7 +766,7 @@ webidl.converters.TypedArray = function (V, T, prefix, argument, opts) {
// with the [AllowResizable] extended attribute, and
// IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is
// true, then throw a TypeError.
if (!opts?.allowResizable && webidl.util.IsResizableArrayBuffer(V.buffer)) {
if (!webidl.util.HasFlag(opts, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) {
throw webidl.errors.exception({
header: prefix,
message: `${argument} cannot be a view on a resizable array buffer.`
Expand Down Expand Up @@ -790,7 +794,7 @@ webidl.converters.DataView = function (V, prefix, argument, opts) {
// with the [AllowShared] extended attribute, and
// IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is true,
// then throw a TypeError.
if (!opts?.allowShared && types.isSharedArrayBuffer(V.buffer)) {
if (!webidl.util.HasFlag(opts, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) {
throw webidl.errors.exception({
header: prefix,
message: `${argument} cannot be a view on a shared array buffer.`
Expand All @@ -801,7 +805,7 @@ webidl.converters.DataView = function (V, prefix, argument, opts) {
// with the [AllowResizable] extended attribute, and
// IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is
// true, then throw a TypeError.
if (!opts?.allowResizable && webidl.util.IsResizableArrayBuffer(V.buffer)) {
if (!webidl.util.HasFlag(opts, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) {
throw webidl.errors.exception({
header: prefix,
message: `${argument} cannot be a view on a resizable array buffer.`
Expand All @@ -826,14 +830,14 @@ webidl.converters.ArrayBufferView = function (V, prefix, argument, opts) {
})
}

if (!opts?.allowShared && types.isSharedArrayBuffer(V.buffer)) {
if (!webidl.util.HasFlag(opts, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) {
throw webidl.errors.exception({
header: prefix,
message: `${argument} cannot be a view on a shared array buffer.`
})
}

if (!opts?.allowResizable && webidl.util.IsResizableArrayBuffer(V.buffer)) {
if (!webidl.util.HasFlag(opts, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) {
throw webidl.errors.exception({
header: prefix,
message: `${argument} cannot be a view on a resizable array buffer.`
Expand All @@ -850,10 +854,9 @@ webidl.converters.BufferSource = function (V, prefix, argument, opts) {
}

if (types.isArrayBufferView(V)) {
return webidl.converters.ArrayBufferView(V, prefix, argument, {
...opts,
allowShared: false
})
opts &= ~webidl.attributes.AllowShared

return webidl.converters.ArrayBufferView(V, prefix, argument, opts)
}

// Make this explicit for easier debugging
Expand Down Expand Up @@ -882,10 +885,8 @@ webidl.converters.AllowSharedBufferSource = function (V, prefix, argument, opts)
}

if (types.isArrayBufferView(V)) {
return webidl.converters.ArrayBufferView(V, prefix, argument, {
...opts,
allowShared: true
})
opts |= webidl.attributes.AllowShared
return webidl.converters.ArrayBufferView(V, prefix, argument, opts)
}

throw webidl.errors.conversionFailed({
Expand Down Expand Up @@ -935,6 +936,14 @@ webidl.converters.EventHandlerNonNull = function (V) {
return () => {}
}

webidl.attributes = {
Clamp: 1 << 0,
EnforceRange: 1 << 1,
AllowShared: 1 << 2,
AllowResizable: 1 << 3,
LegacyNullToEmptyString: 1 << 4
}

module.exports = {
webidl
}
2 changes: 1 addition & 1 deletion lib/web/websocket/stream/websocketstream.js
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ webidl.converters.WebSocketStreamOptions = webidl.dictionaryConverter([
webidl.converters.WebSocketCloseInfo = webidl.dictionaryConverter([
{
key: 'closeCode',
converter: (V) => webidl.converters['unsigned short'](V, { enforceRange: true })
converter: (V) => webidl.converters['unsigned short'](V, webidl.attributes.EnforceRange)
},
{
key: 'reason',
Expand Down
8 changes: 6 additions & 2 deletions lib/web/websocket/websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ class WebSocket extends EventTarget {
const prefix = 'WebSocket.close'

if (code !== undefined) {
code = webidl.converters['unsigned short'](code, prefix, 'code', { clamp: true })
code = webidl.converters['unsigned short'](code, prefix, 'code', webidl.attributes.Clamp)
}

if (reason !== undefined) {
Expand Down Expand Up @@ -739,7 +739,11 @@ webidl.converters['DOMString or sequence<DOMString> or WebSocketInit'] = functio

webidl.converters.WebSocketSendData = function (V) {
if (webidl.util.Type(V) === webidl.util.Types.OBJECT) {
if (webidl.is.Blob(V) || webidl.is.BufferSource(V)) {
if (webidl.is.Blob(V)) {
return V
}

if (webidl.is.BufferSource(V)) {
return V
}
}
Expand Down
26 changes: 6 additions & 20 deletions test/fetch/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ const {
fetch
} = require('../../')

const hasSignalReason = 'reason' in AbortSignal.prototype

test('arg validation', async (t) => {
// constructor
assert.throws(() => {
Expand Down Expand Up @@ -261,23 +259,17 @@ test('pre aborted signal', () => {
ac.abort('gwak')
const req = new Request('http://asd', { signal: ac.signal })
assert.strictEqual(req.signal.aborted, true)
if (hasSignalReason) {
assert.strictEqual(req.signal.reason, 'gwak')
}
assert.strictEqual(req.signal.reason, 'gwak')
})

test('post aborted signal', (t) => {
const { strictEqual, ok } = tspl(t, { plan: 2 })
const { strictEqual } = tspl(t, { plan: 2 })

const ac = new AbortController()
const req = new Request('http://asd', { signal: ac.signal })
strictEqual(req.signal.aborted, false)
ac.signal.addEventListener('abort', () => {
if (hasSignalReason) {
strictEqual(req.signal.reason, 'gwak')
} else {
ok(true)
}
strictEqual(req.signal.reason, 'gwak')
}, { once: true })
ac.abort('gwak')
})
Expand All @@ -287,9 +279,7 @@ test('pre aborted signal cloned', () => {
ac.abort('gwak')
const req = new Request('http://asd', { signal: ac.signal }).clone()
assert.strictEqual(req.signal.aborted, true)
if (hasSignalReason) {
assert.strictEqual(req.signal.reason, 'gwak')
}
assert.strictEqual(req.signal.reason, 'gwak')
})

test('URLSearchParams body with Headers object - issue #1407', async () => {
Expand All @@ -314,17 +304,13 @@ test('URLSearchParams body with Headers object - issue #1407', async () => {
})

test('post aborted signal cloned', (t) => {
const { strictEqual, ok } = tspl(t, { plan: 2 })
const { strictEqual } = tspl(t, { plan: 2 })

const ac = new AbortController()
const req = new Request('http://asd', { signal: ac.signal }).clone()
strictEqual(req.signal.aborted, false)
ac.signal.addEventListener('abort', () => {
if (hasSignalReason) {
strictEqual(req.signal.reason, 'gwak')
} else {
ok(true)
}
strictEqual(req.signal.reason, 'gwak')
}, { once: true })
ac.abort('gwak')
})
Expand Down
20 changes: 8 additions & 12 deletions test/web-platform-tests/expectation.json
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@
"message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\""
},
{
"name": "Fetch http://web-platform.test:61288/fetch/api/resources/top.txt with no-cors mode",
"name": "Fetch http://web-platform.test:61273/fetch/api/resources/top.txt with no-cors mode",
"success": false,
"message": "assert_equals: Opaque filter: status is 0 expected 0 but got 200"
}
Expand Down Expand Up @@ -4869,7 +4869,7 @@
{
"name": "Consume response's body: from FormData to blob",
"success": false,
"message": "assert_equals: Blob body type should be computed from the response Content-Type expected \"multipart/form-data; boundary=----formdata-undici-021177090905\" but got \"multipart/form-data;boundary=----formdata-undici-021177090905\""
"message": "assert_equals: Blob body type should be computed from the response Content-Type expected \"multipart/form-data; boundary=----formdata-undici-081851221061\" but got \"multipart/form-data;boundary=----formdata-undici-081851221061\""
},
{
"name": "Consume response's body: from FormData to text",
Expand Down Expand Up @@ -10982,8 +10982,7 @@
},
{
"name": "Same origin redirection, empty init, no-referrer-when-downgrade redirect header ",
"success": false,
"message": "assert_equals: Check referrer header expected \"http://web-platform.test:8000/fetch/api/redirect/redirect-referrer.any.html\" but got \"http://web-platform.test:8000/\""
"success": true
},
{
"name": "Same origin redirection, empty init, same-origin redirect header ",
Expand Down Expand Up @@ -11017,8 +11016,7 @@
},
{
"name": "Same origin redirection, empty redirect header, no-referrer-when-downgrade init ",
"success": false,
"message": "assert_equals: Check referrer header expected \"http://web-platform.test:8000/fetch/api/redirect/redirect-referrer.any.html\" but got \"http://web-platform.test:8000/\""
"success": true
},
{
"name": "Same origin redirection, empty redirect header, same-origin init ",
Expand Down Expand Up @@ -11052,8 +11050,7 @@
},
{
"name": "Cross origin redirection, empty init, no-referrer-when-downgrade redirect header ",
"success": false,
"message": "assert_equals: Check referrer header expected \"http://web-platform.test:8000/fetch/api/redirect/redirect-referrer.any.html\" but got \"http://web-platform.test:8000/\""
"success": true
},
{
"name": "Cross origin redirection, empty init, same-origin redirect header ",
Expand Down Expand Up @@ -11085,8 +11082,7 @@
},
{
"name": "Cross origin redirection, empty redirect header, no-referrer-when-downgrade init ",
"success": false,
"message": "assert_equals: Check referrer header expected \"http://web-platform.test:8000/fetch/api/redirect/redirect-referrer.any.html\" but got \"http://web-platform.test:8000/\""
"success": true
},
{
"name": "Cross origin redirection, empty redirect header, same-origin init ",
Expand Down Expand Up @@ -15129,7 +15125,7 @@
{
"name": "Response with Cache-Control: max-age=2592000, public and Pragma: no-cache should be cached",
"success": false,
"message": "assert_equals: Responses should be identical, indicating caching expected \"Timestamp: 1756764774.678671\" but got \"Timestamp: 1756764774.6756718\""
"message": "assert_equals: Responses should be identical, indicating caching expected \"Timestamp: 1756778464.9260645\" but got \"Timestamp: 1756778464.9230638\""
}
]
},
Expand Down Expand Up @@ -24889,7 +24885,7 @@
{
"name": "Second fetch returns same response",
"success": false,
"message": "assert_equals: expected \"kifkoeecooqjsfkzmpwg\" but got \"ufxtucitipiyrqotmakz\""
"message": "assert_equals: expected \"ohqqejvmbaayfsbxnlht\" but got \"xbssfkdevkjnzvyehxux\""
}
]
},
Expand Down
Loading
Loading