index.js 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  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. // "For each dictionary member member declared on dictionary, in lexicographical order:"
  383. converters.sort((a, b) => (a.key > b.key) - (a.key < b.key))
  384. return (dictionary, prefix, argument) => {
  385. const dict = {}
  386. if (dictionary != null && webidl.util.Type(dictionary) !== OBJECT) {
  387. throw webidl.errors.exception({
  388. header: prefix,
  389. message: `Expected ${dictionary} to be one of: Null, Undefined, Object.`
  390. })
  391. }
  392. for (const options of converters) {
  393. const { key, defaultValue, required, converter } = options
  394. if (required === true) {
  395. if (dictionary == null || !Object.hasOwn(dictionary, key)) {
  396. throw webidl.errors.exception({
  397. header: prefix,
  398. message: `Missing required key "${key}".`
  399. })
  400. }
  401. }
  402. let value = dictionary?.[key]
  403. const hasDefault = defaultValue !== undefined
  404. // Only use defaultValue if value is undefined and
  405. // a defaultValue options was provided.
  406. if (hasDefault && value === undefined) {
  407. value = defaultValue()
  408. }
  409. // A key can be optional and have no default value.
  410. // When this happens, do not perform a conversion,
  411. // and do not assign the key a value.
  412. if (required || hasDefault || value !== undefined) {
  413. value = converter(value, prefix, `${argument}.${key}`)
  414. if (
  415. options.allowedValues &&
  416. !options.allowedValues.includes(value)
  417. ) {
  418. throw webidl.errors.exception({
  419. header: prefix,
  420. message: `${value} is not an accepted type. Expected one of ${options.allowedValues.join(', ')}.`
  421. })
  422. }
  423. dict[key] = value
  424. }
  425. }
  426. return dict
  427. }
  428. }
  429. webidl.nullableConverter = function (converter) {
  430. return (V, prefix, argument) => {
  431. if (V === null) {
  432. return V
  433. }
  434. return converter(V, prefix, argument)
  435. }
  436. }
  437. /**
  438. * @param {*} value
  439. * @returns {boolean}
  440. */
  441. webidl.is.USVString = function (value) {
  442. return (
  443. typeof value === 'string' &&
  444. value.isWellFormed()
  445. )
  446. }
  447. webidl.is.ReadableStream = webidl.util.MakeTypeAssertion(ReadableStream)
  448. webidl.is.Blob = webidl.util.MakeTypeAssertion(Blob)
  449. webidl.is.URLSearchParams = webidl.util.MakeTypeAssertion(URLSearchParams)
  450. webidl.is.File = webidl.util.MakeTypeAssertion(File)
  451. webidl.is.URL = webidl.util.MakeTypeAssertion(URL)
  452. webidl.is.AbortSignal = webidl.util.MakeTypeAssertion(AbortSignal)
  453. webidl.is.MessagePort = webidl.util.MakeTypeAssertion(MessagePort)
  454. webidl.is.BufferSource = function (V) {
  455. return types.isArrayBuffer(V) || (
  456. ArrayBuffer.isView(V) &&
  457. types.isArrayBuffer(V.buffer)
  458. )
  459. }
  460. // https://webidl.spec.whatwg.org/#dfn-get-buffer-source-copy
  461. webidl.util.getCopyOfBytesHeldByBufferSource = function (bufferSource) {
  462. // 1. Let jsBufferSource be the result of converting bufferSource to a JavaScript value.
  463. const jsBufferSource = bufferSource
  464. // 2. Let jsArrayBuffer be jsBufferSource.
  465. let jsArrayBuffer = jsBufferSource
  466. // 3. Let offset be 0.
  467. let offset = 0
  468. // 4. Let length be 0.
  469. let length = 0
  470. // 5. If jsBufferSource has a [[ViewedArrayBuffer]] internal slot, then:
  471. if (types.isTypedArray(jsBufferSource) || types.isDataView(jsBufferSource)) {
  472. // 5.1. Set jsArrayBuffer to jsBufferSource.[[ViewedArrayBuffer]].
  473. jsArrayBuffer = jsBufferSource.buffer
  474. // 5.2. Set offset to jsBufferSource.[[ByteOffset]].
  475. offset = jsBufferSource.byteOffset
  476. // 5.3. Set length to jsBufferSource.[[ByteLength]].
  477. length = jsBufferSource.byteLength
  478. } else {
  479. // 6. Otherwise:
  480. // 6.1. Assert: jsBufferSource is an ArrayBuffer or SharedArrayBuffer object.
  481. assert(types.isAnyArrayBuffer(jsBufferSource))
  482. // 6.2. Set length to jsBufferSource.[[ArrayBufferByteLength]].
  483. length = jsBufferSource.byteLength
  484. }
  485. // 7. If IsDetachedBuffer(jsArrayBuffer) is true, then return the empty byte sequence.
  486. if (jsArrayBuffer.detached) {
  487. return new Uint8Array(0)
  488. }
  489. // 8. Let bytes be a new byte sequence of length equal to length.
  490. const bytes = new Uint8Array(length)
  491. // 9. For i in the range offset to offset + length − 1, inclusive,
  492. // set bytes[i − offset] to GetValueFromBuffer(jsArrayBuffer, i, Uint8, true, Unordered).
  493. const view = new Uint8Array(jsArrayBuffer, offset, length)
  494. bytes.set(view)
  495. // 10. Return bytes.
  496. return bytes
  497. }
  498. // https://webidl.spec.whatwg.org/#es-DOMString
  499. webidl.converters.DOMString = function (V, prefix, argument, flags) {
  500. // 1. If V is null and the conversion is to an IDL type
  501. // associated with the [LegacyNullToEmptyString]
  502. // extended attribute, then return the DOMString value
  503. // that represents the empty string.
  504. if (V === null && webidl.util.HasFlag(flags, webidl.attributes.LegacyNullToEmptyString)) {
  505. return ''
  506. }
  507. // 2. Let x be ? ToString(V).
  508. if (typeof V === 'symbol') {
  509. throw webidl.errors.exception({
  510. header: prefix,
  511. message: `${argument} is a symbol, which cannot be converted to a DOMString.`
  512. })
  513. }
  514. // 3. Return the IDL DOMString value that represents the
  515. // same sequence of code units as the one the
  516. // ECMAScript String value x represents.
  517. return String(V)
  518. }
  519. // https://webidl.spec.whatwg.org/#es-ByteString
  520. webidl.converters.ByteString = function (V, prefix, argument) {
  521. // 1. Let x be ? ToString(V).
  522. if (typeof V === 'symbol') {
  523. throw webidl.errors.exception({
  524. header: prefix,
  525. message: `${argument} is a symbol, which cannot be converted to a ByteString.`
  526. })
  527. }
  528. const x = String(V)
  529. // 2. If the value of any element of x is greater than
  530. // 255, then throw a TypeError.
  531. for (let index = 0; index < x.length; index++) {
  532. if (x.charCodeAt(index) > 255) {
  533. throw new TypeError(
  534. 'Cannot convert argument to a ByteString because the character at ' +
  535. `index ${index} has a value of ${x.charCodeAt(index)} which is greater than 255.`
  536. )
  537. }
  538. }
  539. // 3. Return an IDL ByteString value whose length is the
  540. // length of x, and where the value of each element is
  541. // the value of the corresponding element of x.
  542. return x
  543. }
  544. /**
  545. * @param {unknown} value
  546. * @returns {string}
  547. * @see https://webidl.spec.whatwg.org/#es-USVString
  548. */
  549. webidl.converters.USVString = function (value) {
  550. // TODO: rewrite this so we can control the errors thrown
  551. if (typeof value === 'string') {
  552. return value.toWellFormed()
  553. }
  554. return `${value}`.toWellFormed()
  555. }
  556. // https://webidl.spec.whatwg.org/#es-boolean
  557. webidl.converters.boolean = function (V) {
  558. // 1. Let x be the result of computing ToBoolean(V).
  559. // https://262.ecma-international.org/10.0/index.html#table-10
  560. const x = Boolean(V)
  561. // 2. Return the IDL boolean value that is the one that represents
  562. // the same truth value as the ECMAScript Boolean value x.
  563. return x
  564. }
  565. // https://webidl.spec.whatwg.org/#es-any
  566. webidl.converters.any = function (V) {
  567. return V
  568. }
  569. // https://webidl.spec.whatwg.org/#es-long-long
  570. webidl.converters['long long'] = function (V, prefix, argument) {
  571. // 1. Let x be ? ConvertToInt(V, 64, "signed").
  572. const x = webidl.util.ConvertToInt(V, 64, 'signed', 0, prefix, argument)
  573. // 2. Return the IDL long long value that represents
  574. // the same numeric value as x.
  575. return x
  576. }
  577. // https://webidl.spec.whatwg.org/#es-unsigned-long-long
  578. webidl.converters['unsigned long long'] = function (V, prefix, argument) {
  579. // 1. Let x be ? ConvertToInt(V, 64, "unsigned").
  580. const x = webidl.util.ConvertToInt(V, 64, 'unsigned', 0, prefix, argument)
  581. // 2. Return the IDL unsigned long long value that
  582. // represents the same numeric value as x.
  583. return x
  584. }
  585. // https://webidl.spec.whatwg.org/#es-unsigned-long
  586. webidl.converters['unsigned long'] = function (V, prefix, argument) {
  587. // 1. Let x be ? ConvertToInt(V, 32, "unsigned").
  588. const x = webidl.util.ConvertToInt(V, 32, 'unsigned', 0, prefix, argument)
  589. // 2. Return the IDL unsigned long value that
  590. // represents the same numeric value as x.
  591. return x
  592. }
  593. // https://webidl.spec.whatwg.org/#es-unsigned-short
  594. webidl.converters['unsigned short'] = function (V, prefix, argument, flags) {
  595. // 1. Let x be ? ConvertToInt(V, 16, "unsigned").
  596. const x = webidl.util.ConvertToInt(V, 16, 'unsigned', flags, prefix, argument)
  597. // 2. Return the IDL unsigned short value that represents
  598. // the same numeric value as x.
  599. return x
  600. }
  601. // https://webidl.spec.whatwg.org/#idl-ArrayBuffer
  602. webidl.converters.ArrayBuffer = function (V, prefix, argument, flags) {
  603. // 1. If V is not an Object, or V does not have an
  604. // [[ArrayBufferData]] internal slot, then throw a
  605. // TypeError.
  606. // 2. If IsSharedArrayBuffer(V) is true, then throw a
  607. // TypeError.
  608. // see: https://tc39.es/ecma262/#sec-properties-of-the-arraybuffer-instances
  609. if (
  610. webidl.util.Type(V) !== OBJECT ||
  611. !types.isArrayBuffer(V)
  612. ) {
  613. throw webidl.errors.conversionFailed({
  614. prefix,
  615. argument: `${argument} ("${webidl.util.Stringify(V)}")`,
  616. types: ['ArrayBuffer']
  617. })
  618. }
  619. // 3. If the conversion is not to an IDL type associated
  620. // with the [AllowResizable] extended attribute, and
  621. // IsResizableArrayBuffer(V) is true, then throw a
  622. // TypeError.
  623. if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V)) {
  624. throw webidl.errors.exception({
  625. header: prefix,
  626. message: `${argument} cannot be a resizable ArrayBuffer.`
  627. })
  628. }
  629. // 4. Return the IDL ArrayBuffer value that is a
  630. // reference to the same object as V.
  631. return V
  632. }
  633. // https://webidl.spec.whatwg.org/#idl-SharedArrayBuffer
  634. webidl.converters.SharedArrayBuffer = function (V, prefix, argument, flags) {
  635. // 1. If V is not an Object, or V does not have an
  636. // [[ArrayBufferData]] internal slot, then throw a
  637. // TypeError.
  638. // 2. If IsSharedArrayBuffer(V) is false, then throw a
  639. // TypeError.
  640. // see: https://tc39.es/ecma262/#sec-properties-of-the-sharedarraybuffer-instances
  641. if (
  642. webidl.util.Type(V) !== OBJECT ||
  643. !types.isSharedArrayBuffer(V)
  644. ) {
  645. throw webidl.errors.conversionFailed({
  646. prefix,
  647. argument: `${argument} ("${webidl.util.Stringify(V)}")`,
  648. types: ['SharedArrayBuffer']
  649. })
  650. }
  651. // 3. If the conversion is not to an IDL type associated
  652. // with the [AllowResizable] extended attribute, and
  653. // IsResizableArrayBuffer(V) is true, then throw a
  654. // TypeError.
  655. if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V)) {
  656. throw webidl.errors.exception({
  657. header: prefix,
  658. message: `${argument} cannot be a resizable SharedArrayBuffer.`
  659. })
  660. }
  661. // 4. Return the IDL SharedArrayBuffer value that is a
  662. // reference to the same object as V.
  663. return V
  664. }
  665. // https://webidl.spec.whatwg.org/#dfn-typed-array-type
  666. webidl.converters.TypedArray = function (V, T, prefix, argument, flags) {
  667. // 1. Let T be the IDL type V is being converted to.
  668. // 2. If Type(V) is not Object, or V does not have a
  669. // [[TypedArrayName]] internal slot with a value
  670. // equal to T’s name, then throw a TypeError.
  671. if (
  672. webidl.util.Type(V) !== OBJECT ||
  673. !types.isTypedArray(V) ||
  674. V.constructor.name !== T.name
  675. ) {
  676. throw webidl.errors.conversionFailed({
  677. prefix,
  678. argument: `${argument} ("${webidl.util.Stringify(V)}")`,
  679. types: [T.name]
  680. })
  681. }
  682. // 3. If the conversion is not to an IDL type associated
  683. // with the [AllowShared] extended attribute, and
  684. // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is
  685. // true, then throw a TypeError.
  686. if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) {
  687. throw webidl.errors.exception({
  688. header: prefix,
  689. message: `${argument} cannot be a view on a shared array buffer.`
  690. })
  691. }
  692. // 4. If the conversion is not to an IDL type associated
  693. // with the [AllowResizable] extended attribute, and
  694. // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is
  695. // true, then throw a TypeError.
  696. if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) {
  697. throw webidl.errors.exception({
  698. header: prefix,
  699. message: `${argument} cannot be a view on a resizable array buffer.`
  700. })
  701. }
  702. // 5. Return the IDL value of type T that is a reference
  703. // to the same object as V.
  704. return V
  705. }
  706. // https://webidl.spec.whatwg.org/#idl-DataView
  707. webidl.converters.DataView = function (V, prefix, argument, flags) {
  708. // 1. If Type(V) is not Object, or V does not have a
  709. // [[DataView]] internal slot, then throw a TypeError.
  710. if (webidl.util.Type(V) !== OBJECT || !types.isDataView(V)) {
  711. throw webidl.errors.conversionFailed({
  712. prefix,
  713. argument: `${argument} ("${webidl.util.Stringify(V)}")`,
  714. types: ['DataView']
  715. })
  716. }
  717. // 2. If the conversion is not to an IDL type associated
  718. // with the [AllowShared] extended attribute, and
  719. // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is true,
  720. // then throw a TypeError.
  721. if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) {
  722. throw webidl.errors.exception({
  723. header: prefix,
  724. message: `${argument} cannot be a view on a shared array buffer.`
  725. })
  726. }
  727. // 3. If the conversion is not to an IDL type associated
  728. // with the [AllowResizable] extended attribute, and
  729. // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is
  730. // true, then throw a TypeError.
  731. if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) {
  732. throw webidl.errors.exception({
  733. header: prefix,
  734. message: `${argument} cannot be a view on a resizable array buffer.`
  735. })
  736. }
  737. // 4. Return the IDL DataView value that is a reference
  738. // to the same object as V.
  739. return V
  740. }
  741. // https://webidl.spec.whatwg.org/#ArrayBufferView
  742. webidl.converters.ArrayBufferView = function (V, prefix, argument, flags) {
  743. if (
  744. webidl.util.Type(V) !== OBJECT ||
  745. !types.isArrayBufferView(V)
  746. ) {
  747. throw webidl.errors.conversionFailed({
  748. prefix,
  749. argument: `${argument} ("${webidl.util.Stringify(V)}")`,
  750. types: ['ArrayBufferView']
  751. })
  752. }
  753. if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) {
  754. throw webidl.errors.exception({
  755. header: prefix,
  756. message: `${argument} cannot be a view on a shared array buffer.`
  757. })
  758. }
  759. if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) {
  760. throw webidl.errors.exception({
  761. header: prefix,
  762. message: `${argument} cannot be a view on a resizable array buffer.`
  763. })
  764. }
  765. return V
  766. }
  767. // https://webidl.spec.whatwg.org/#BufferSource
  768. webidl.converters.BufferSource = function (V, prefix, argument, flags) {
  769. if (types.isArrayBuffer(V)) {
  770. return webidl.converters.ArrayBuffer(V, prefix, argument, flags)
  771. }
  772. if (types.isArrayBufferView(V)) {
  773. flags &= ~webidl.attributes.AllowShared
  774. return webidl.converters.ArrayBufferView(V, prefix, argument, flags)
  775. }
  776. // Make this explicit for easier debugging
  777. if (types.isSharedArrayBuffer(V)) {
  778. throw webidl.errors.exception({
  779. header: prefix,
  780. message: `${argument} cannot be a SharedArrayBuffer.`
  781. })
  782. }
  783. throw webidl.errors.conversionFailed({
  784. prefix,
  785. argument: `${argument} ("${webidl.util.Stringify(V)}")`,
  786. types: ['ArrayBuffer', 'ArrayBufferView']
  787. })
  788. }
  789. // https://webidl.spec.whatwg.org/#AllowSharedBufferSource
  790. webidl.converters.AllowSharedBufferSource = function (V, prefix, argument, flags) {
  791. if (types.isArrayBuffer(V)) {
  792. return webidl.converters.ArrayBuffer(V, prefix, argument, flags)
  793. }
  794. if (types.isSharedArrayBuffer(V)) {
  795. return webidl.converters.SharedArrayBuffer(V, prefix, argument, flags)
  796. }
  797. if (types.isArrayBufferView(V)) {
  798. flags |= webidl.attributes.AllowShared
  799. return webidl.converters.ArrayBufferView(V, prefix, argument, flags)
  800. }
  801. throw webidl.errors.conversionFailed({
  802. prefix,
  803. argument: `${argument} ("${webidl.util.Stringify(V)}")`,
  804. types: ['ArrayBuffer', 'SharedArrayBuffer', 'ArrayBufferView']
  805. })
  806. }
  807. webidl.converters['sequence<ByteString>'] = webidl.sequenceConverter(
  808. webidl.converters.ByteString
  809. )
  810. webidl.converters['sequence<sequence<ByteString>>'] = webidl.sequenceConverter(
  811. webidl.converters['sequence<ByteString>']
  812. )
  813. webidl.converters['record<ByteString, ByteString>'] = webidl.recordConverter(
  814. webidl.converters.ByteString,
  815. webidl.converters.ByteString
  816. )
  817. webidl.converters.Blob = webidl.interfaceConverter(webidl.is.Blob, 'Blob')
  818. webidl.converters.AbortSignal = webidl.interfaceConverter(
  819. webidl.is.AbortSignal,
  820. 'AbortSignal'
  821. )
  822. /**
  823. * [LegacyTreatNonObjectAsNull]
  824. * callback EventHandlerNonNull = any (Event event);
  825. * typedef EventHandlerNonNull? EventHandler;
  826. * @param {*} V
  827. */
  828. webidl.converters.EventHandlerNonNull = function (V) {
  829. if (webidl.util.Type(V) !== OBJECT) {
  830. return null
  831. }
  832. // [I]f the value is not an object, it will be converted to null, and if the value is not callable,
  833. // it will be converted to a callback function value that does nothing when called.
  834. if (typeof V === 'function') {
  835. return V
  836. }
  837. return () => {}
  838. }
  839. webidl.attributes = {
  840. Clamp: 1 << 0,
  841. EnforceRange: 1 << 1,
  842. AllowShared: 1 << 2,
  843. AllowResizable: 1 << 3,
  844. LegacyNullToEmptyString: 1 << 4
  845. }
  846. module.exports = {
  847. webidl
  848. }