index.js 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  1. 'use strict'
  2. const assert = require('node:assert')
  3. const { types, inspect } = require('node:util')
  4. const { runtimeFeatures } = require('../../util/runtime-features')
  5. const UNDEFINED = 1
  6. const BOOLEAN = 2
  7. const STRING = 3
  8. const SYMBOL = 4
  9. const NUMBER = 5
  10. const BIGINT = 6
  11. const NULL = 7
  12. const OBJECT = 8 // function and object
  13. const FunctionPrototypeSymbolHasInstance = Function.call.bind(Function.prototype[Symbol.hasInstance])
  14. /** @type {import('../../../types/webidl').Webidl} */
  15. const webidl = {
  16. converters: {},
  17. util: {},
  18. errors: {},
  19. is: {}
  20. }
  21. /**
  22. * @description Instantiate an error.
  23. *
  24. * @param {Object} opts
  25. * @param {string} opts.header
  26. * @param {string} opts.message
  27. * @returns {TypeError}
  28. */
  29. webidl.errors.exception = function (message) {
  30. return new TypeError(`${message.header}: ${message.message}`)
  31. }
  32. /**
  33. * @description Instantiate an error when conversion from one type to another has failed.
  34. *
  35. * @param {Object} opts
  36. * @param {string} opts.prefix
  37. * @param {string} opts.argument
  38. * @param {string[]} opts.types
  39. * @returns {TypeError}
  40. */
  41. webidl.errors.conversionFailed = function (opts) {
  42. const plural = opts.types.length === 1 ? '' : ' one of'
  43. const message =
  44. `${opts.argument} could not be converted to` +
  45. `${plural}: ${opts.types.join(', ')}.`
  46. return webidl.errors.exception({
  47. header: opts.prefix,
  48. message
  49. })
  50. }
  51. /**
  52. * @description Instantiate an error when an invalid argument is provided
  53. *
  54. * @param {Object} context
  55. * @param {string} context.prefix
  56. * @param {string} context.value
  57. * @param {string} context.type
  58. * @returns {TypeError}
  59. */
  60. webidl.errors.invalidArgument = function (context) {
  61. return webidl.errors.exception({
  62. header: context.prefix,
  63. message: `"${context.value}" is an invalid ${context.type}.`
  64. })
  65. }
  66. // https://webidl.spec.whatwg.org/#implements
  67. webidl.brandCheck = function (V, I) {
  68. if (!FunctionPrototypeSymbolHasInstance(I, V)) {
  69. const err = new TypeError('Illegal invocation')
  70. err.code = 'ERR_INVALID_THIS' // node compat.
  71. throw err
  72. }
  73. }
  74. webidl.brandCheckMultiple = function (List) {
  75. const prototypes = List.map((c) => webidl.util.MakeTypeAssertion(c))
  76. return (V) => {
  77. if (prototypes.every(typeCheck => !typeCheck(V))) {
  78. const err = new TypeError('Illegal invocation')
  79. err.code = 'ERR_INVALID_THIS' // node compat.
  80. throw err
  81. }
  82. }
  83. }
  84. webidl.argumentLengthCheck = function ({ length }, min, ctx) {
  85. if (length < min) {
  86. throw webidl.errors.exception({
  87. message: `${min} argument${min !== 1 ? 's' : ''} required, ` +
  88. `but${length ? ' only' : ''} ${length} found.`,
  89. header: ctx
  90. })
  91. }
  92. }
  93. webidl.illegalConstructor = function () {
  94. throw webidl.errors.exception({
  95. header: 'TypeError',
  96. message: 'Illegal constructor'
  97. })
  98. }
  99. webidl.util.MakeTypeAssertion = function (I) {
  100. return (O) => FunctionPrototypeSymbolHasInstance(I, O)
  101. }
  102. // https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values
  103. webidl.util.Type = function (V) {
  104. switch (typeof V) {
  105. case 'undefined': return UNDEFINED
  106. case 'boolean': return BOOLEAN
  107. case 'string': return STRING
  108. case 'symbol': return SYMBOL
  109. case 'number': return NUMBER
  110. case 'bigint': return BIGINT
  111. case 'function':
  112. case 'object': {
  113. if (V === null) {
  114. return NULL
  115. }
  116. return OBJECT
  117. }
  118. }
  119. }
  120. webidl.util.Types = {
  121. UNDEFINED,
  122. BOOLEAN,
  123. STRING,
  124. SYMBOL,
  125. NUMBER,
  126. BIGINT,
  127. NULL,
  128. OBJECT
  129. }
  130. webidl.util.TypeValueToString = function (o) {
  131. switch (webidl.util.Type(o)) {
  132. case UNDEFINED: return 'Undefined'
  133. case BOOLEAN: return 'Boolean'
  134. case STRING: return 'String'
  135. case SYMBOL: return 'Symbol'
  136. case NUMBER: return 'Number'
  137. case BIGINT: return 'BigInt'
  138. case NULL: return 'Null'
  139. case OBJECT: return 'Object'
  140. }
  141. }
  142. webidl.util.markAsUncloneable = runtimeFeatures.has('markAsUncloneable')
  143. ? require('node:worker_threads').markAsUncloneable
  144. : () => {}
  145. // https://webidl.spec.whatwg.org/#abstract-opdef-converttoint
  146. webidl.util.ConvertToInt = function (V, bitLength, signedness, flags) {
  147. let upperBound
  148. let lowerBound
  149. // 1. If bitLength is 64, then:
  150. if (bitLength === 64) {
  151. // 1. Let upperBound be 2^53 − 1.
  152. upperBound = Math.pow(2, 53) - 1
  153. // 2. If signedness is "unsigned", then let lowerBound be 0.
  154. if (signedness === 'unsigned') {
  155. lowerBound = 0
  156. } else {
  157. // 3. Otherwise let lowerBound be −2^53 + 1.
  158. lowerBound = Math.pow(-2, 53) + 1
  159. }
  160. } else if (signedness === 'unsigned') {
  161. // 2. Otherwise, if signedness is "unsigned", then:
  162. // 1. Let lowerBound be 0.
  163. lowerBound = 0
  164. // 2. Let upperBound be 2^bitLength − 1.
  165. upperBound = Math.pow(2, bitLength) - 1
  166. } else {
  167. // 3. Otherwise:
  168. // 1. Let lowerBound be -2^bitLength − 1.
  169. lowerBound = Math.pow(-2, bitLength) - 1
  170. // 2. Let upperBound be 2^bitLength − 1 − 1.
  171. upperBound = Math.pow(2, bitLength - 1) - 1
  172. }
  173. // 4. Let x be ? ToNumber(V).
  174. let x = Number(V)
  175. // 5. If x is −0, then set x to +0.
  176. if (x === 0) {
  177. x = 0
  178. }
  179. // 6. If the conversion is to an IDL type associated
  180. // with the [EnforceRange] extended attribute, then:
  181. if (webidl.util.HasFlag(flags, webidl.attributes.EnforceRange)) {
  182. // 1. If x is NaN, +∞, or −∞, then throw a TypeError.
  183. if (
  184. Number.isNaN(x) ||
  185. x === Number.POSITIVE_INFINITY ||
  186. x === Number.NEGATIVE_INFINITY
  187. ) {
  188. throw webidl.errors.exception({
  189. header: 'Integer conversion',
  190. message: `Could not convert ${webidl.util.Stringify(V)} to an integer.`
  191. })
  192. }
  193. // 2. Set x to IntegerPart(x).
  194. x = webidl.util.IntegerPart(x)
  195. // 3. If x < lowerBound or x > upperBound, then
  196. // throw a TypeError.
  197. if (x < lowerBound || x > upperBound) {
  198. throw webidl.errors.exception({
  199. header: 'Integer conversion',
  200. message: `Value must be between ${lowerBound}-${upperBound}, got ${x}.`
  201. })
  202. }
  203. // 4. Return x.
  204. return x
  205. }
  206. // 7. If x is not NaN and the conversion is to an IDL
  207. // type associated with the [Clamp] extended
  208. // attribute, then:
  209. if (!Number.isNaN(x) && webidl.util.HasFlag(flags, webidl.attributes.Clamp)) {
  210. // 1. Set x to min(max(x, lowerBound), upperBound).
  211. x = Math.min(Math.max(x, lowerBound), upperBound)
  212. // 2. Round x to the nearest integer, choosing the
  213. // even integer if it lies halfway between two,
  214. // and choosing +0 rather than −0.
  215. if (Math.floor(x) % 2 === 0) {
  216. x = Math.floor(x)
  217. } else {
  218. x = Math.ceil(x)
  219. }
  220. // 3. Return x.
  221. return x
  222. }
  223. // 8. If x is NaN, +0, +∞, or −∞, then return +0.
  224. if (
  225. Number.isNaN(x) ||
  226. (x === 0 && Object.is(0, x)) ||
  227. x === Number.POSITIVE_INFINITY ||
  228. x === Number.NEGATIVE_INFINITY
  229. ) {
  230. return 0
  231. }
  232. // 9. Set x to IntegerPart(x).
  233. x = webidl.util.IntegerPart(x)
  234. // 10. Set x to x modulo 2^bitLength.
  235. x = x % Math.pow(2, bitLength)
  236. // 11. If signedness is "signed" and x ≥ 2^bitLength − 1,
  237. // then return x − 2^bitLength.
  238. if (signedness === 'signed' && x >= Math.pow(2, bitLength) - 1) {
  239. return x - Math.pow(2, bitLength)
  240. }
  241. // 12. Otherwise, return x.
  242. return x
  243. }
  244. // https://webidl.spec.whatwg.org/#abstract-opdef-integerpart
  245. webidl.util.IntegerPart = function (n) {
  246. // 1. Let r be floor(abs(n)).
  247. const r = Math.floor(Math.abs(n))
  248. // 2. If n < 0, then return -1 × r.
  249. if (n < 0) {
  250. return -1 * r
  251. }
  252. // 3. Otherwise, return r.
  253. return r
  254. }
  255. webidl.util.Stringify = function (V) {
  256. const type = webidl.util.Type(V)
  257. switch (type) {
  258. case SYMBOL:
  259. return `Symbol(${V.description})`
  260. case OBJECT:
  261. return inspect(V)
  262. case STRING:
  263. return `"${V}"`
  264. case BIGINT:
  265. return `${V}n`
  266. default:
  267. return `${V}`
  268. }
  269. }
  270. webidl.util.IsResizableArrayBuffer = function (V) {
  271. if (types.isArrayBuffer(V)) {
  272. return V.resizable
  273. }
  274. if (types.isSharedArrayBuffer(V)) {
  275. return V.growable
  276. }
  277. throw webidl.errors.exception({
  278. header: 'IsResizableArrayBuffer',
  279. message: `"${webidl.util.Stringify(V)}" is not an array buffer.`
  280. })
  281. }
  282. webidl.util.HasFlag = function (flags, attributes) {
  283. return typeof flags === 'number' && (flags & attributes) === attributes
  284. }
  285. // https://webidl.spec.whatwg.org/#es-sequence
  286. webidl.sequenceConverter = function (converter) {
  287. return (V, prefix, argument, Iterable) => {
  288. // 1. If Type(V) is not Object, throw a TypeError.
  289. if (webidl.util.Type(V) !== OBJECT) {
  290. throw webidl.errors.exception({
  291. header: prefix,
  292. message: `${argument} (${webidl.util.Stringify(V)}) is not iterable.`
  293. })
  294. }
  295. // 2. Let method be ? GetMethod(V, @@iterator).
  296. /** @type {Generator} */
  297. const method = typeof Iterable === 'function' ? Iterable() : V?.[Symbol.iterator]?.()
  298. const seq = []
  299. let index = 0
  300. // 3. If method is undefined, throw a TypeError.
  301. if (
  302. method === undefined ||
  303. typeof method.next !== 'function'
  304. ) {
  305. throw webidl.errors.exception({
  306. header: prefix,
  307. message: `${argument} is not iterable.`
  308. })
  309. }
  310. // https://webidl.spec.whatwg.org/#create-sequence-from-iterable
  311. while (true) {
  312. const { done, value } = method.next()
  313. if (done) {
  314. break
  315. }
  316. seq.push(converter(value, prefix, `${argument}[${index++}]`))
  317. }
  318. return seq
  319. }
  320. }
  321. // https://webidl.spec.whatwg.org/#es-to-record
  322. webidl.recordConverter = function (keyConverter, valueConverter) {
  323. return (O, prefix, argument) => {
  324. // 1. If Type(O) is not Object, throw a TypeError.
  325. if (webidl.util.Type(O) !== OBJECT) {
  326. throw webidl.errors.exception({
  327. header: prefix,
  328. message: `${argument} ("${webidl.util.TypeValueToString(O)}") is not an Object.`
  329. })
  330. }
  331. // 2. Let result be a new empty instance of record<K, V>.
  332. const result = {}
  333. if (!types.isProxy(O)) {
  334. // 1. Let desc be ? O.[[GetOwnProperty]](key).
  335. const keys = [...Object.getOwnPropertyNames(O), ...Object.getOwnPropertySymbols(O)]
  336. for (const key of keys) {
  337. const keyName = webidl.util.Stringify(key)
  338. // 1. Let typedKey be key converted to an IDL value of type K.
  339. const typedKey = keyConverter(key, prefix, `Key ${keyName} in ${argument}`)
  340. // 2. Let value be ? Get(O, key).
  341. // 3. Let typedValue be value converted to an IDL value of type V.
  342. const typedValue = valueConverter(O[key], prefix, `${argument}[${keyName}]`)
  343. // 4. Set result[typedKey] to typedValue.
  344. result[typedKey] = typedValue
  345. }
  346. // 5. Return result.
  347. return result
  348. }
  349. // 3. Let keys be ? O.[[OwnPropertyKeys]]().
  350. const keys = Reflect.ownKeys(O)
  351. // 4. For each key of keys.
  352. for (const key of keys) {
  353. // 1. Let desc be ? O.[[GetOwnProperty]](key).
  354. const desc = Reflect.getOwnPropertyDescriptor(O, key)
  355. // 2. If desc is not undefined and desc.[[Enumerable]] is true:
  356. if (desc?.enumerable) {
  357. // 1. Let typedKey be key converted to an IDL value of type K.
  358. const typedKey = keyConverter(key, prefix, argument)
  359. // 2. Let value be ? Get(O, key).
  360. // 3. Let typedValue be value converted to an IDL value of type V.
  361. const typedValue = valueConverter(O[key], prefix, argument)
  362. // 4. Set result[typedKey] to typedValue.
  363. result[typedKey] = typedValue
  364. }
  365. }
  366. // 5. Return result.
  367. return result
  368. }
  369. }
  370. webidl.interfaceConverter = function (TypeCheck, name) {
  371. return (V, prefix, argument) => {
  372. if (!TypeCheck(V)) {
  373. throw webidl.errors.exception({
  374. header: prefix,
  375. message: `Expected ${argument} ("${webidl.util.Stringify(V)}") to be an instance of ${name}.`
  376. })
  377. }
  378. return V
  379. }
  380. }
  381. webidl.dictionaryConverter = function (converters) {
  382. return (dictionary, prefix, argument) => {
  383. const dict = {}
  384. if (dictionary != null && webidl.util.Type(dictionary) !== OBJECT) {
  385. throw webidl.errors.exception({
  386. header: prefix,
  387. message: `Expected ${dictionary} to be one of: Null, Undefined, Object.`
  388. })
  389. }
  390. for (const options of converters) {
  391. const { key, defaultValue, required, converter } = options
  392. if (required === true) {
  393. if (dictionary == null || !Object.hasOwn(dictionary, key)) {
  394. throw webidl.errors.exception({
  395. header: prefix,
  396. message: `Missing required key "${key}".`
  397. })
  398. }
  399. }
  400. let value = dictionary?.[key]
  401. const hasDefault = defaultValue !== undefined
  402. // Only use defaultValue if value is undefined and
  403. // a defaultValue options was provided.
  404. if (hasDefault && value === undefined) {
  405. value = defaultValue()
  406. }
  407. // A key can be optional and have no default value.
  408. // When this happens, do not perform a conversion,
  409. // and do not assign the key a value.
  410. if (required || hasDefault || value !== undefined) {
  411. value = converter(value, prefix, `${argument}.${key}`)
  412. if (
  413. options.allowedValues &&
  414. !options.allowedValues.includes(value)
  415. ) {
  416. throw webidl.errors.exception({
  417. header: prefix,
  418. message: `${value} is not an accepted type. Expected one of ${options.allowedValues.join(', ')}.`
  419. })
  420. }
  421. dict[key] = value
  422. }
  423. }
  424. return dict
  425. }
  426. }
  427. webidl.nullableConverter = function (converter) {
  428. return (V, prefix, argument) => {
  429. if (V === null) {
  430. return V
  431. }
  432. return converter(V, prefix, argument)
  433. }
  434. }
  435. /**
  436. * @param {*} value
  437. * @returns {boolean}
  438. */
  439. webidl.is.USVString = function (value) {
  440. return (
  441. typeof value === 'string' &&
  442. value.isWellFormed()
  443. )
  444. }
  445. webidl.is.ReadableStream = webidl.util.MakeTypeAssertion(ReadableStream)
  446. webidl.is.Blob = webidl.util.MakeTypeAssertion(Blob)
  447. webidl.is.URLSearchParams = webidl.util.MakeTypeAssertion(URLSearchParams)
  448. webidl.is.File = webidl.util.MakeTypeAssertion(File)
  449. webidl.is.URL = webidl.util.MakeTypeAssertion(URL)
  450. webidl.is.AbortSignal = webidl.util.MakeTypeAssertion(AbortSignal)
  451. webidl.is.MessagePort = webidl.util.MakeTypeAssertion(MessagePort)
  452. webidl.is.BufferSource = function (V) {
  453. return types.isArrayBuffer(V) || (
  454. ArrayBuffer.isView(V) &&
  455. types.isArrayBuffer(V.buffer)
  456. )
  457. }
  458. // https://webidl.spec.whatwg.org/#dfn-get-buffer-source-copy
  459. webidl.util.getCopyOfBytesHeldByBufferSource = function (bufferSource) {
  460. // 1. Let jsBufferSource be the result of converting bufferSource to a JavaScript value.
  461. const jsBufferSource = bufferSource
  462. // 2. Let jsArrayBuffer be jsBufferSource.
  463. let jsArrayBuffer = jsBufferSource
  464. // 3. Let offset be 0.
  465. let offset = 0
  466. // 4. Let length be 0.
  467. let length = 0
  468. // 5. If jsBufferSource has a [[ViewedArrayBuffer]] internal slot, then:
  469. if (types.isTypedArray(jsBufferSource) || types.isDataView(jsBufferSource)) {
  470. // 5.1. Set jsArrayBuffer to jsBufferSource.[[ViewedArrayBuffer]].
  471. jsArrayBuffer = jsBufferSource.buffer
  472. // 5.2. Set offset to jsBufferSource.[[ByteOffset]].
  473. offset = jsBufferSource.byteOffset
  474. // 5.3. Set length to jsBufferSource.[[ByteLength]].
  475. length = jsBufferSource.byteLength
  476. } else {
  477. // 6. Otherwise:
  478. // 6.1. Assert: jsBufferSource is an ArrayBuffer or SharedArrayBuffer object.
  479. assert(types.isAnyArrayBuffer(jsBufferSource))
  480. // 6.2. Set length to jsBufferSource.[[ArrayBufferByteLength]].
  481. length = jsBufferSource.byteLength
  482. }
  483. // 7. If IsDetachedBuffer(jsArrayBuffer) is true, then return the empty byte sequence.
  484. if (jsArrayBuffer.detached) {
  485. return new Uint8Array(0)
  486. }
  487. // 8. Let bytes be a new byte sequence of length equal to length.
  488. const bytes = new Uint8Array(length)
  489. // 9. For i in the range offset to offset + length − 1, inclusive,
  490. // set bytes[i − offset] to GetValueFromBuffer(jsArrayBuffer, i, Uint8, true, Unordered).
  491. const view = new Uint8Array(jsArrayBuffer, offset, length)
  492. bytes.set(view)
  493. // 10. Return bytes.
  494. return bytes
  495. }
  496. // https://webidl.spec.whatwg.org/#es-DOMString
  497. webidl.converters.DOMString = function (V, prefix, argument, flags) {
  498. // 1. If V is null and the conversion is to an IDL type
  499. // associated with the [LegacyNullToEmptyString]
  500. // extended attribute, then return the DOMString value
  501. // that represents the empty string.
  502. if (V === null && webidl.util.HasFlag(flags, webidl.attributes.LegacyNullToEmptyString)) {
  503. return ''
  504. }
  505. // 2. Let x be ? ToString(V).
  506. if (typeof V === 'symbol') {
  507. throw webidl.errors.exception({
  508. header: prefix,
  509. message: `${argument} is a symbol, which cannot be converted to a DOMString.`
  510. })
  511. }
  512. // 3. Return the IDL DOMString value that represents the
  513. // same sequence of code units as the one the
  514. // ECMAScript String value x represents.
  515. return String(V)
  516. }
  517. // https://webidl.spec.whatwg.org/#es-ByteString
  518. webidl.converters.ByteString = function (V, prefix, argument) {
  519. // 1. Let x be ? ToString(V).
  520. if (typeof V === 'symbol') {
  521. throw webidl.errors.exception({
  522. header: prefix,
  523. message: `${argument} is a symbol, which cannot be converted to a ByteString.`
  524. })
  525. }
  526. const x = String(V)
  527. // 2. If the value of any element of x is greater than
  528. // 255, then throw a TypeError.
  529. for (let index = 0; index < x.length; index++) {
  530. if (x.charCodeAt(index) > 255) {
  531. throw new TypeError(
  532. 'Cannot convert argument to a ByteString because the character at ' +
  533. `index ${index} has a value of ${x.charCodeAt(index)} which is greater than 255.`
  534. )
  535. }
  536. }
  537. // 3. Return an IDL ByteString value whose length is the
  538. // length of x, and where the value of each element is
  539. // the value of the corresponding element of x.
  540. return x
  541. }
  542. /**
  543. * @param {unknown} value
  544. * @returns {string}
  545. * @see https://webidl.spec.whatwg.org/#es-USVString
  546. */
  547. webidl.converters.USVString = function (value) {
  548. // TODO: rewrite this so we can control the errors thrown
  549. if (typeof value === 'string') {
  550. return value.toWellFormed()
  551. }
  552. return `${value}`.toWellFormed()
  553. }
  554. // https://webidl.spec.whatwg.org/#es-boolean
  555. webidl.converters.boolean = function (V) {
  556. // 1. Let x be the result of computing ToBoolean(V).
  557. // https://262.ecma-international.org/10.0/index.html#table-10
  558. const x = Boolean(V)
  559. // 2. Return the IDL boolean value that is the one that represents
  560. // the same truth value as the ECMAScript Boolean value x.
  561. return x
  562. }
  563. // https://webidl.spec.whatwg.org/#es-any
  564. webidl.converters.any = function (V) {
  565. return V
  566. }
  567. // https://webidl.spec.whatwg.org/#es-long-long
  568. webidl.converters['long long'] = function (V, prefix, argument) {
  569. // 1. Let x be ? ConvertToInt(V, 64, "signed").
  570. const x = webidl.util.ConvertToInt(V, 64, 'signed', 0, prefix, argument)
  571. // 2. Return the IDL long long value that represents
  572. // the same numeric value as x.
  573. return x
  574. }
  575. // https://webidl.spec.whatwg.org/#es-unsigned-long-long
  576. webidl.converters['unsigned long long'] = function (V, prefix, argument) {
  577. // 1. Let x be ? ConvertToInt(V, 64, "unsigned").
  578. const x = webidl.util.ConvertToInt(V, 64, 'unsigned', 0, prefix, argument)
  579. // 2. Return the IDL unsigned long long value that
  580. // represents the same numeric value as x.
  581. return x
  582. }
  583. // https://webidl.spec.whatwg.org/#es-unsigned-long
  584. webidl.converters['unsigned long'] = function (V, prefix, argument) {
  585. // 1. Let x be ? ConvertToInt(V, 32, "unsigned").
  586. const x = webidl.util.ConvertToInt(V, 32, 'unsigned', 0, prefix, argument)
  587. // 2. Return the IDL unsigned long value that
  588. // represents the same numeric value as x.
  589. return x
  590. }
  591. // https://webidl.spec.whatwg.org/#es-unsigned-short
  592. webidl.converters['unsigned short'] = function (V, prefix, argument, flags) {
  593. // 1. Let x be ? ConvertToInt(V, 16, "unsigned").
  594. const x = webidl.util.ConvertToInt(V, 16, 'unsigned', flags, prefix, argument)
  595. // 2. Return the IDL unsigned short value that represents
  596. // the same numeric value as x.
  597. return x
  598. }
  599. // https://webidl.spec.whatwg.org/#idl-ArrayBuffer
  600. webidl.converters.ArrayBuffer = function (V, prefix, argument, flags) {
  601. // 1. If V is not an Object, or V does not have an
  602. // [[ArrayBufferData]] internal slot, then throw a
  603. // TypeError.
  604. // 2. If IsSharedArrayBuffer(V) is true, then throw a
  605. // TypeError.
  606. // see: https://tc39.es/ecma262/#sec-properties-of-the-arraybuffer-instances
  607. if (
  608. webidl.util.Type(V) !== OBJECT ||
  609. !types.isArrayBuffer(V)
  610. ) {
  611. throw webidl.errors.conversionFailed({
  612. prefix,
  613. argument: `${argument} ("${webidl.util.Stringify(V)}")`,
  614. types: ['ArrayBuffer']
  615. })
  616. }
  617. // 3. If the conversion is not to an IDL type associated
  618. // with the [AllowResizable] extended attribute, and
  619. // IsResizableArrayBuffer(V) is true, then throw a
  620. // TypeError.
  621. if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V)) {
  622. throw webidl.errors.exception({
  623. header: prefix,
  624. message: `${argument} cannot be a resizable ArrayBuffer.`
  625. })
  626. }
  627. // 4. Return the IDL ArrayBuffer value that is a
  628. // reference to the same object as V.
  629. return V
  630. }
  631. // https://webidl.spec.whatwg.org/#idl-SharedArrayBuffer
  632. webidl.converters.SharedArrayBuffer = function (V, prefix, argument, flags) {
  633. // 1. If V is not an Object, or V does not have an
  634. // [[ArrayBufferData]] internal slot, then throw a
  635. // TypeError.
  636. // 2. If IsSharedArrayBuffer(V) is false, then throw a
  637. // TypeError.
  638. // see: https://tc39.es/ecma262/#sec-properties-of-the-sharedarraybuffer-instances
  639. if (
  640. webidl.util.Type(V) !== OBJECT ||
  641. !types.isSharedArrayBuffer(V)
  642. ) {
  643. throw webidl.errors.conversionFailed({
  644. prefix,
  645. argument: `${argument} ("${webidl.util.Stringify(V)}")`,
  646. types: ['SharedArrayBuffer']
  647. })
  648. }
  649. // 3. If the conversion is not to an IDL type associated
  650. // with the [AllowResizable] extended attribute, and
  651. // IsResizableArrayBuffer(V) is true, then throw a
  652. // TypeError.
  653. if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V)) {
  654. throw webidl.errors.exception({
  655. header: prefix,
  656. message: `${argument} cannot be a resizable SharedArrayBuffer.`
  657. })
  658. }
  659. // 4. Return the IDL SharedArrayBuffer value that is a
  660. // reference to the same object as V.
  661. return V
  662. }
  663. // https://webidl.spec.whatwg.org/#dfn-typed-array-type
  664. webidl.converters.TypedArray = function (V, T, prefix, argument, flags) {
  665. // 1. Let T be the IDL type V is being converted to.
  666. // 2. If Type(V) is not Object, or V does not have a
  667. // [[TypedArrayName]] internal slot with a value
  668. // equal to T’s name, then throw a TypeError.
  669. if (
  670. webidl.util.Type(V) !== OBJECT ||
  671. !types.isTypedArray(V) ||
  672. V.constructor.name !== T.name
  673. ) {
  674. throw webidl.errors.conversionFailed({
  675. prefix,
  676. argument: `${argument} ("${webidl.util.Stringify(V)}")`,
  677. types: [T.name]
  678. })
  679. }
  680. // 3. If the conversion is not to an IDL type associated
  681. // with the [AllowShared] extended attribute, and
  682. // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is
  683. // true, then throw a TypeError.
  684. if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) {
  685. throw webidl.errors.exception({
  686. header: prefix,
  687. message: `${argument} cannot be a view on a shared array buffer.`
  688. })
  689. }
  690. // 4. If the conversion is not to an IDL type associated
  691. // with the [AllowResizable] extended attribute, and
  692. // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is
  693. // true, then throw a TypeError.
  694. if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) {
  695. throw webidl.errors.exception({
  696. header: prefix,
  697. message: `${argument} cannot be a view on a resizable array buffer.`
  698. })
  699. }
  700. // 5. Return the IDL value of type T that is a reference
  701. // to the same object as V.
  702. return V
  703. }
  704. // https://webidl.spec.whatwg.org/#idl-DataView
  705. webidl.converters.DataView = function (V, prefix, argument, flags) {
  706. // 1. If Type(V) is not Object, or V does not have a
  707. // [[DataView]] internal slot, then throw a TypeError.
  708. if (webidl.util.Type(V) !== OBJECT || !types.isDataView(V)) {
  709. throw webidl.errors.conversionFailed({
  710. prefix,
  711. argument: `${argument} ("${webidl.util.Stringify(V)}")`,
  712. types: ['DataView']
  713. })
  714. }
  715. // 2. If the conversion is not to an IDL type associated
  716. // with the [AllowShared] extended attribute, and
  717. // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is true,
  718. // then throw a TypeError.
  719. if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) {
  720. throw webidl.errors.exception({
  721. header: prefix,
  722. message: `${argument} cannot be a view on a shared array buffer.`
  723. })
  724. }
  725. // 3. If the conversion is not to an IDL type associated
  726. // with the [AllowResizable] extended attribute, and
  727. // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is
  728. // true, then throw a TypeError.
  729. if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) {
  730. throw webidl.errors.exception({
  731. header: prefix,
  732. message: `${argument} cannot be a view on a resizable array buffer.`
  733. })
  734. }
  735. // 4. Return the IDL DataView value that is a reference
  736. // to the same object as V.
  737. return V
  738. }
  739. // https://webidl.spec.whatwg.org/#ArrayBufferView
  740. webidl.converters.ArrayBufferView = function (V, prefix, argument, flags) {
  741. if (
  742. webidl.util.Type(V) !== OBJECT ||
  743. !types.isArrayBufferView(V)
  744. ) {
  745. throw webidl.errors.conversionFailed({
  746. prefix,
  747. argument: `${argument} ("${webidl.util.Stringify(V)}")`,
  748. types: ['ArrayBufferView']
  749. })
  750. }
  751. if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) {
  752. throw webidl.errors.exception({
  753. header: prefix,
  754. message: `${argument} cannot be a view on a shared array buffer.`
  755. })
  756. }
  757. if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) {
  758. throw webidl.errors.exception({
  759. header: prefix,
  760. message: `${argument} cannot be a view on a resizable array buffer.`
  761. })
  762. }
  763. return V
  764. }
  765. // https://webidl.spec.whatwg.org/#BufferSource
  766. webidl.converters.BufferSource = function (V, prefix, argument, flags) {
  767. if (types.isArrayBuffer(V)) {
  768. return webidl.converters.ArrayBuffer(V, prefix, argument, flags)
  769. }
  770. if (types.isArrayBufferView(V)) {
  771. flags &= ~webidl.attributes.AllowShared
  772. return webidl.converters.ArrayBufferView(V, prefix, argument, flags)
  773. }
  774. // Make this explicit for easier debugging
  775. if (types.isSharedArrayBuffer(V)) {
  776. throw webidl.errors.exception({
  777. header: prefix,
  778. message: `${argument} cannot be a SharedArrayBuffer.`
  779. })
  780. }
  781. throw webidl.errors.conversionFailed({
  782. prefix,
  783. argument: `${argument} ("${webidl.util.Stringify(V)}")`,
  784. types: ['ArrayBuffer', 'ArrayBufferView']
  785. })
  786. }
  787. // https://webidl.spec.whatwg.org/#AllowSharedBufferSource
  788. webidl.converters.AllowSharedBufferSource = function (V, prefix, argument, flags) {
  789. if (types.isArrayBuffer(V)) {
  790. return webidl.converters.ArrayBuffer(V, prefix, argument, flags)
  791. }
  792. if (types.isSharedArrayBuffer(V)) {
  793. return webidl.converters.SharedArrayBuffer(V, prefix, argument, flags)
  794. }
  795. if (types.isArrayBufferView(V)) {
  796. flags |= webidl.attributes.AllowShared
  797. return webidl.converters.ArrayBufferView(V, prefix, argument, flags)
  798. }
  799. throw webidl.errors.conversionFailed({
  800. prefix,
  801. argument: `${argument} ("${webidl.util.Stringify(V)}")`,
  802. types: ['ArrayBuffer', 'SharedArrayBuffer', 'ArrayBufferView']
  803. })
  804. }
  805. webidl.converters['sequence<ByteString>'] = webidl.sequenceConverter(
  806. webidl.converters.ByteString
  807. )
  808. webidl.converters['sequence<sequence<ByteString>>'] = webidl.sequenceConverter(
  809. webidl.converters['sequence<ByteString>']
  810. )
  811. webidl.converters['record<ByteString, ByteString>'] = webidl.recordConverter(
  812. webidl.converters.ByteString,
  813. webidl.converters.ByteString
  814. )
  815. webidl.converters.Blob = webidl.interfaceConverter(webidl.is.Blob, 'Blob')
  816. webidl.converters.AbortSignal = webidl.interfaceConverter(
  817. webidl.is.AbortSignal,
  818. 'AbortSignal'
  819. )
  820. /**
  821. * [LegacyTreatNonObjectAsNull]
  822. * callback EventHandlerNonNull = any (Event event);
  823. * typedef EventHandlerNonNull? EventHandler;
  824. * @param {*} V
  825. */
  826. webidl.converters.EventHandlerNonNull = function (V) {
  827. if (webidl.util.Type(V) !== OBJECT) {
  828. return null
  829. }
  830. // [I]f the value is not an object, it will be converted to null, and if the value is not callable,
  831. // it will be converted to a callback function value that does nothing when called.
  832. if (typeof V === 'function') {
  833. return V
  834. }
  835. return () => {}
  836. }
  837. webidl.attributes = {
  838. Clamp: 1 << 0,
  839. EnforceRange: 1 << 1,
  840. AllowShared: 1 << 2,
  841. AllowResizable: 1 << 3,
  842. LegacyNullToEmptyString: 1 << 4
  843. }
  844. module.exports = {
  845. webidl
  846. }