Skip to content
Merged
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
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
81 changes: 45 additions & 36 deletions lib/web/webidl/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ webidl.util.TypeValueToString = function (o) {
webidl.util.markAsUncloneable = markAsUncloneable || (() => {})

// https://webidl.spec.whatwg.org/#abstract-opdef-converttoint
webidl.util.ConvertToInt = function (V, bitLength, signedness, opts) {
webidl.util.ConvertToInt = function (V, bitLength, signedness, flags) {
let upperBound
let lowerBound

Expand Down 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(flags, 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(flags, 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 (flags, attributes) {
return typeof flags === 'number' && (flags & attributes) === attributes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we really need to check if flags is a number? cant we expect that we are smart enough to pass numbers?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flags are optional

}

// https://webidl.spec.whatwg.org/#es-sequence
webidl.sequenceConverter = function (converter) {
return (V, prefix, argument, Iterable) => {
Expand Down Expand Up @@ -537,12 +541,12 @@ webidl.is.BufferSource = function (V) {
}

// https://webidl.spec.whatwg.org/#es-DOMString
webidl.converters.DOMString = function (V, prefix, argument, opts) {
webidl.converters.DOMString = function (V, prefix, argument, flags) {
// 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 && webidl.util.HasFlag(flags, 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,25 +645,25 @@ 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.
return x
}

// https://webidl.spec.whatwg.org/#es-unsigned-short
webidl.converters['unsigned short'] = function (V, prefix, argument, opts) {
webidl.converters['unsigned short'] = function (V, prefix, argument, flags) {
// 1. Let x be ? ConvertToInt(V, 16, "unsigned").
const x = webidl.util.ConvertToInt(V, 16, 'unsigned', opts, prefix, argument)
const x = webidl.util.ConvertToInt(V, 16, 'unsigned', flags, prefix, argument)

// 2. Return the IDL unsigned short value that represents
// the same numeric value as x.
return x
}

// https://webidl.spec.whatwg.org/#idl-ArrayBuffer
webidl.converters.ArrayBuffer = function (V, prefix, argument, opts) {
webidl.converters.ArrayBuffer = function (V, prefix, argument, flags) {
// 1. If V is not an Object, or V does not have an
// [[ArrayBufferData]] internal slot, then throw a
// TypeError.
Expand All @@ -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(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V)) {
throw webidl.errors.exception({
header: prefix,
message: `${argument} cannot be a resizable ArrayBuffer.`
Expand All @@ -694,7 +698,7 @@ webidl.converters.ArrayBuffer = function (V, prefix, argument, opts) {
}

// https://webidl.spec.whatwg.org/#idl-SharedArrayBuffer
webidl.converters.SharedArrayBuffer = function (V, prefix, argument, opts) {
webidl.converters.SharedArrayBuffer = function (V, prefix, argument, flags) {
// 1. If V is not an Object, or V does not have an
// [[ArrayBufferData]] internal slot, then throw a
// TypeError.
Expand All @@ -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(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V)) {
throw webidl.errors.exception({
header: prefix,
message: `${argument} cannot be a resizable SharedArrayBuffer.`
Expand All @@ -729,7 +733,7 @@ webidl.converters.SharedArrayBuffer = function (V, prefix, argument, opts) {
}

// https://webidl.spec.whatwg.org/#dfn-typed-array-type
webidl.converters.TypedArray = function (V, T, prefix, argument, opts) {
webidl.converters.TypedArray = function (V, T, prefix, argument, flags) {
// 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
Expand All @@ -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(flags, 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(flags, 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 @@ -775,7 +779,7 @@ webidl.converters.TypedArray = function (V, T, prefix, argument, opts) {
}

// https://webidl.spec.whatwg.org/#idl-DataView
webidl.converters.DataView = function (V, prefix, argument, opts) {
webidl.converters.DataView = function (V, prefix, argument, flags) {
// 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)) {
Expand All @@ -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(flags, 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(flags, 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 @@ -814,7 +818,7 @@ webidl.converters.DataView = function (V, prefix, argument, opts) {
}

// https://webidl.spec.whatwg.org/#ArrayBufferView
webidl.converters.ArrayBufferView = function (V, prefix, argument, opts) {
webidl.converters.ArrayBufferView = function (V, prefix, argument, flags) {
if (
webidl.util.Type(V) !== OBJECT ||
!types.isArrayBufferView(V)
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(flags, 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(flags, 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 @@ -844,16 +848,15 @@ webidl.converters.ArrayBufferView = function (V, prefix, argument, opts) {
}

// https://webidl.spec.whatwg.org/#BufferSource
webidl.converters.BufferSource = function (V, prefix, argument, opts) {
webidl.converters.BufferSource = function (V, prefix, argument, flags) {
if (types.isArrayBuffer(V)) {
return webidl.converters.ArrayBuffer(V, prefix, argument, opts)
return webidl.converters.ArrayBuffer(V, prefix, argument, flags)
}

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

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

// Make this explicit for easier debugging
Expand All @@ -872,20 +875,18 @@ webidl.converters.BufferSource = function (V, prefix, argument, opts) {
}

// https://webidl.spec.whatwg.org/#AllowSharedBufferSource
webidl.converters.AllowSharedBufferSource = function (V, prefix, argument, opts) {
webidl.converters.AllowSharedBufferSource = function (V, prefix, argument, flags) {
if (types.isArrayBuffer(V)) {
return webidl.converters.ArrayBuffer(V, prefix, argument, opts)
return webidl.converters.ArrayBuffer(V, prefix, argument, flags)
}

if (types.isSharedArrayBuffer(V)) {
return webidl.converters.SharedArrayBuffer(V, prefix, argument, opts)
return webidl.converters.SharedArrayBuffer(V, prefix, argument, flags)
}

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

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
Loading
Loading