webidl.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. 'use strict'
  2. const { types, inspect } = require('node:util')
  3. const { markAsUncloneable } = require('node:worker_threads')
  4. const { toUSVString } = require('../../core/util')
  5. /** @type {import('../../../types/webidl').Webidl} */
  6. const webidl = {}
  7. webidl.converters = {}
  8. webidl.util = {}
  9. webidl.errors = {}
  10. webidl.errors.exception = function (message) {
  11. return new TypeError(`${message.header}: ${message.message}`)
  12. }
  13. webidl.errors.conversionFailed = function (context) {
  14. const plural = context.types.length === 1 ? '' : ' one of'
  15. const message =
  16. `${context.argument} could not be converted to` +
  17. `${plural}: ${context.types.join(', ')}.`
  18. return webidl.errors.exception({
  19. header: context.prefix,
  20. message
  21. })
  22. }
  23. webidl.errors.invalidArgument = function (context) {
  24. return webidl.errors.exception({
  25. header: context.prefix,
  26. message: `"${context.value}" is an invalid ${context.type}.`
  27. })
  28. }
  29. // https://webidl.spec.whatwg.org/#implements
  30. webidl.brandCheck = function (V, I, opts) {
  31. if (opts?.strict !== false) {
  32. if (!(V instanceof I)) {
  33. const err = new TypeError('Illegal invocation')
  34. err.code = 'ERR_INVALID_THIS' // node compat.
  35. throw err
  36. }
  37. } else {
  38. if (V?.[Symbol.toStringTag] !== I.prototype[Symbol.toStringTag]) {
  39. const err = new TypeError('Illegal invocation')
  40. err.code = 'ERR_INVALID_THIS' // node compat.
  41. throw err
  42. }
  43. }
  44. }
  45. webidl.argumentLengthCheck = function ({ length }, min, ctx) {
  46. if (length < min) {
  47. throw webidl.errors.exception({
  48. message: `${min} argument${min !== 1 ? 's' : ''} required, ` +
  49. `but${length ? ' only' : ''} ${length} found.`,
  50. header: ctx
  51. })
  52. }
  53. }
  54. webidl.illegalConstructor = function () {
  55. throw webidl.errors.exception({
  56. header: 'TypeError',
  57. message: 'Illegal constructor'
  58. })
  59. }
  60. // https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values
  61. webidl.util.Type = function (V) {
  62. switch (typeof V) {
  63. case 'undefined': return 'Undefined'
  64. case 'boolean': return 'Boolean'
  65. case 'string': return 'String'
  66. case 'symbol': return 'Symbol'
  67. case 'number': return 'Number'
  68. case 'bigint': return 'BigInt'
  69. case 'function':
  70. case 'object': {
  71. if (V === null) {
  72. return 'Null'
  73. }
  74. return 'Object'
  75. }
  76. }
  77. }
  78. webidl.util.markAsUncloneable = markAsUncloneable || (() => {})
  79. // https://webidl.spec.whatwg.org/#abstract-opdef-converttoint
  80. webidl.util.ConvertToInt = function (V, bitLength, signedness, opts) {
  81. let upperBound
  82. let lowerBound
  83. // 1. If bitLength is 64, then:
  84. if (bitLength === 64) {
  85. // 1. Let upperBound be 2^53 − 1.
  86. upperBound = Math.pow(2, 53) - 1
  87. // 2. If signedness is "unsigned", then let lowerBound be 0.
  88. if (signedness === 'unsigned') {
  89. lowerBound = 0
  90. } else {
  91. // 3. Otherwise let lowerBound be −2^53 + 1.
  92. lowerBound = Math.pow(-2, 53) + 1
  93. }
  94. } else if (signedness === 'unsigned') {
  95. // 2. Otherwise, if signedness is "unsigned", then:
  96. // 1. Let lowerBound be 0.
  97. lowerBound = 0
  98. // 2. Let upperBound be 2^bitLength − 1.
  99. upperBound = Math.pow(2, bitLength) - 1
  100. } else {
  101. // 3. Otherwise:
  102. // 1. Let lowerBound be -2^bitLength − 1.
  103. lowerBound = Math.pow(-2, bitLength) - 1
  104. // 2. Let upperBound be 2^bitLength − 1 − 1.
  105. upperBound = Math.pow(2, bitLength - 1) - 1
  106. }
  107. // 4. Let x be ? ToNumber(V).
  108. let x = Number(V)
  109. // 5. If x is −0, then set x to +0.
  110. if (x === 0) {
  111. x = 0
  112. }
  113. // 6. If the conversion is to an IDL type associated
  114. // with the [EnforceRange] extended attribute, then:
  115. if (opts?.enforceRange === true) {
  116. // 1. If x is NaN, +∞, or −∞, then throw a TypeError.
  117. if (
  118. Number.isNaN(x) ||
  119. x === Number.POSITIVE_INFINITY ||
  120. x === Number.NEGATIVE_INFINITY
  121. ) {
  122. throw webidl.errors.exception({
  123. header: 'Integer conversion',
  124. message: `Could not convert ${webidl.util.Stringify(V)} to an integer.`
  125. })
  126. }
  127. // 2. Set x to IntegerPart(x).
  128. x = webidl.util.IntegerPart(x)
  129. // 3. If x < lowerBound or x > upperBound, then
  130. // throw a TypeError.
  131. if (x < lowerBound || x > upperBound) {
  132. throw webidl.errors.exception({
  133. header: 'Integer conversion',
  134. message: `Value must be between ${lowerBound}-${upperBound}, got ${x}.`
  135. })
  136. }
  137. // 4. Return x.
  138. return x
  139. }
  140. // 7. If x is not NaN and the conversion is to an IDL
  141. // type associated with the [Clamp] extended
  142. // attribute, then:
  143. if (!Number.isNaN(x) && opts?.clamp === true) {
  144. // 1. Set x to min(max(x, lowerBound), upperBound).
  145. x = Math.min(Math.max(x, lowerBound), upperBound)
  146. // 2. Round x to the nearest integer, choosing the
  147. // even integer if it lies halfway between two,
  148. // and choosing +0 rather than −0.
  149. if (Math.floor(x) % 2 === 0) {
  150. x = Math.floor(x)
  151. } else {
  152. x = Math.ceil(x)
  153. }
  154. // 3. Return x.
  155. return x
  156. }
  157. // 8. If x is NaN, +0, +∞, or −∞, then return +0.
  158. if (
  159. Number.isNaN(x) ||
  160. (x === 0 && Object.is(0, x)) ||
  161. x === Number.POSITIVE_INFINITY ||
  162. x === Number.NEGATIVE_INFINITY
  163. ) {
  164. return 0
  165. }
  166. // 9. Set x to IntegerPart(x).
  167. x = webidl.util.IntegerPart(x)
  168. // 10. Set x to x modulo 2^bitLength.
  169. x = x % Math.pow(2, bitLength)
  170. // 11. If signedness is "signed" and x ≥ 2^bitLength − 1,
  171. // then return x − 2^bitLength.
  172. if (signedness === 'signed' && x >= Math.pow(2, bitLength) - 1) {
  173. return x - Math.pow(2, bitLength)
  174. }
  175. // 12. Otherwise, return x.
  176. return x
  177. }
  178. // https://webidl.spec.whatwg.org/#abstract-opdef-integerpart
  179. webidl.util.IntegerPart = function (n) {
  180. // 1. Let r be floor(abs(n)).
  181. const r = Math.floor(Math.abs(n))
  182. // 2. If n < 0, then return -1 × r.
  183. if (n < 0) {
  184. return -1 * r
  185. }
  186. // 3. Otherwise, return r.
  187. return r
  188. }
  189. webidl.util.Stringify = function (V) {
  190. const type = webidl.util.Type(V)
  191. switch (type) {
  192. case 'Symbol':
  193. return `Symbol(${V.description})`
  194. case 'Object':
  195. return inspect(V)
  196. case 'String':
  197. return `"${V}"`
  198. default:
  199. return `${V}`
  200. }
  201. }
  202. // https://webidl.spec.whatwg.org/#es-sequence
  203. webidl.sequenceConverter = function (converter) {
  204. return (V, prefix, argument, Iterable) => {
  205. // 1. If Type(V) is not Object, throw a TypeError.
  206. if (webidl.util.Type(V) !== 'Object') {
  207. throw webidl.errors.exception({
  208. header: prefix,
  209. message: `${argument} (${webidl.util.Stringify(V)}) is not iterable.`
  210. })
  211. }
  212. // 2. Let method be ? GetMethod(V, @@iterator).
  213. /** @type {Generator} */
  214. const method = typeof Iterable === 'function' ? Iterable() : V?.[Symbol.iterator]?.()
  215. const seq = []
  216. let index = 0
  217. // 3. If method is undefined, throw a TypeError.
  218. if (
  219. method === undefined ||
  220. typeof method.next !== 'function'
  221. ) {
  222. throw webidl.errors.exception({
  223. header: prefix,
  224. message: `${argument} is not iterable.`
  225. })
  226. }
  227. // https://webidl.spec.whatwg.org/#create-sequence-from-iterable
  228. while (true) {
  229. const { done, value } = method.next()
  230. if (done) {
  231. break
  232. }
  233. seq.push(converter(value, prefix, `${argument}[${index++}]`))
  234. }
  235. return seq
  236. }
  237. }
  238. // https://webidl.spec.whatwg.org/#es-to-record
  239. webidl.recordConverter = function (keyConverter, valueConverter) {
  240. return (O, prefix, argument) => {
  241. // 1. If Type(O) is not Object, throw a TypeError.
  242. if (webidl.util.Type(O) !== 'Object') {
  243. throw webidl.errors.exception({
  244. header: prefix,
  245. message: `${argument} ("${webidl.util.Type(O)}") is not an Object.`
  246. })
  247. }
  248. // 2. Let result be a new empty instance of record<K, V>.
  249. const result = {}
  250. if (!types.isProxy(O)) {
  251. // 1. Let desc be ? O.[[GetOwnProperty]](key).
  252. const keys = [...Object.getOwnPropertyNames(O), ...Object.getOwnPropertySymbols(O)]
  253. for (const key of keys) {
  254. // 1. Let typedKey be key converted to an IDL value of type K.
  255. const typedKey = keyConverter(key, prefix, argument)
  256. // 2. Let value be ? Get(O, key).
  257. // 3. Let typedValue be value converted to an IDL value of type V.
  258. const typedValue = valueConverter(O[key], prefix, argument)
  259. // 4. Set result[typedKey] to typedValue.
  260. result[typedKey] = typedValue
  261. }
  262. // 5. Return result.
  263. return result
  264. }
  265. // 3. Let keys be ? O.[[OwnPropertyKeys]]().
  266. const keys = Reflect.ownKeys(O)
  267. // 4. For each key of keys.
  268. for (const key of keys) {
  269. // 1. Let desc be ? O.[[GetOwnProperty]](key).
  270. const desc = Reflect.getOwnPropertyDescriptor(O, key)
  271. // 2. If desc is not undefined and desc.[[Enumerable]] is true:
  272. if (desc?.enumerable) {
  273. // 1. Let typedKey be key converted to an IDL value of type K.
  274. const typedKey = keyConverter(key, prefix, argument)
  275. // 2. Let value be ? Get(O, key).
  276. // 3. Let typedValue be value converted to an IDL value of type V.
  277. const typedValue = valueConverter(O[key], prefix, argument)
  278. // 4. Set result[typedKey] to typedValue.
  279. result[typedKey] = typedValue
  280. }
  281. }
  282. // 5. Return result.
  283. return result
  284. }
  285. }
  286. webidl.interfaceConverter = function (i) {
  287. return (V, prefix, argument, opts) => {
  288. if (opts?.strict !== false && !(V instanceof i)) {
  289. throw webidl.errors.exception({
  290. header: prefix,
  291. message: `Expected ${argument} ("${webidl.util.Stringify(V)}") to be an instance of ${i.name}.`
  292. })
  293. }
  294. return V
  295. }
  296. }
  297. webidl.dictionaryConverter = function (converters) {
  298. return (dictionary, prefix, argument) => {
  299. const type = webidl.util.Type(dictionary)
  300. const dict = {}
  301. if (type === 'Null' || type === 'Undefined') {
  302. return dict
  303. } else if (type !== 'Object') {
  304. throw webidl.errors.exception({
  305. header: prefix,
  306. message: `Expected ${dictionary} to be one of: Null, Undefined, Object.`
  307. })
  308. }
  309. for (const options of converters) {
  310. const { key, defaultValue, required, converter } = options
  311. if (required === true) {
  312. if (!Object.hasOwn(dictionary, key)) {
  313. throw webidl.errors.exception({
  314. header: prefix,
  315. message: `Missing required key "${key}".`
  316. })
  317. }
  318. }
  319. let value = dictionary[key]
  320. const hasDefault = Object.hasOwn(options, 'defaultValue')
  321. // Only use defaultValue if value is undefined and
  322. // a defaultValue options was provided.
  323. if (hasDefault && value !== null) {
  324. value ??= defaultValue()
  325. }
  326. // A key can be optional and have no default value.
  327. // When this happens, do not perform a conversion,
  328. // and do not assign the key a value.
  329. if (required || hasDefault || value !== undefined) {
  330. value = converter(value, prefix, `${argument}.${key}`)
  331. if (
  332. options.allowedValues &&
  333. !options.allowedValues.includes(value)
  334. ) {
  335. throw webidl.errors.exception({
  336. header: prefix,
  337. message: `${value} is not an accepted type. Expected one of ${options.allowedValues.join(', ')}.`
  338. })
  339. }
  340. dict[key] = value
  341. }
  342. }
  343. return dict
  344. }
  345. }
  346. webidl.nullableConverter = function (converter) {
  347. return (V, prefix, argument) => {
  348. if (V === null) {
  349. return V
  350. }
  351. return converter(V, prefix, argument)
  352. }
  353. }
  354. // https://webidl.spec.whatwg.org/#es-DOMString
  355. webidl.converters.DOMString = function (V, prefix, argument, opts) {
  356. // 1. If V is null and the conversion is to an IDL type
  357. // associated with the [LegacyNullToEmptyString]
  358. // extended attribute, then return the DOMString value
  359. // that represents the empty string.
  360. if (V === null && opts?.legacyNullToEmptyString) {
  361. return ''
  362. }
  363. // 2. Let x be ? ToString(V).
  364. if (typeof V === 'symbol') {
  365. throw webidl.errors.exception({
  366. header: prefix,
  367. message: `${argument} is a symbol, which cannot be converted to a DOMString.`
  368. })
  369. }
  370. // 3. Return the IDL DOMString value that represents the
  371. // same sequence of code units as the one the
  372. // ECMAScript String value x represents.
  373. return String(V)
  374. }
  375. // https://webidl.spec.whatwg.org/#es-ByteString
  376. webidl.converters.ByteString = function (V, prefix, argument) {
  377. // 1. Let x be ? ToString(V).
  378. // Note: DOMString converter perform ? ToString(V)
  379. const x = webidl.converters.DOMString(V, prefix, argument)
  380. // 2. If the value of any element of x is greater than
  381. // 255, then throw a TypeError.
  382. for (let index = 0; index < x.length; index++) {
  383. if (x.charCodeAt(index) > 255) {
  384. throw new TypeError(
  385. 'Cannot convert argument to a ByteString because the character at ' +
  386. `index ${index} has a value of ${x.charCodeAt(index)} which is greater than 255.`
  387. )
  388. }
  389. }
  390. // 3. Return an IDL ByteString value whose length is the
  391. // length of x, and where the value of each element is
  392. // the value of the corresponding element of x.
  393. return x
  394. }
  395. // https://webidl.spec.whatwg.org/#es-USVString
  396. // TODO: rewrite this so we can control the errors thrown
  397. webidl.converters.USVString = toUSVString
  398. // https://webidl.spec.whatwg.org/#es-boolean
  399. webidl.converters.boolean = function (V) {
  400. // 1. Let x be the result of computing ToBoolean(V).
  401. const x = Boolean(V)
  402. // 2. Return the IDL boolean value that is the one that represents
  403. // the same truth value as the ECMAScript Boolean value x.
  404. return x
  405. }
  406. // https://webidl.spec.whatwg.org/#es-any
  407. webidl.converters.any = function (V) {
  408. return V
  409. }
  410. // https://webidl.spec.whatwg.org/#es-long-long
  411. webidl.converters['long long'] = function (V, prefix, argument) {
  412. // 1. Let x be ? ConvertToInt(V, 64, "signed").
  413. const x = webidl.util.ConvertToInt(V, 64, 'signed', undefined, prefix, argument)
  414. // 2. Return the IDL long long value that represents
  415. // the same numeric value as x.
  416. return x
  417. }
  418. // https://webidl.spec.whatwg.org/#es-unsigned-long-long
  419. webidl.converters['unsigned long long'] = function (V, prefix, argument) {
  420. // 1. Let x be ? ConvertToInt(V, 64, "unsigned").
  421. const x = webidl.util.ConvertToInt(V, 64, 'unsigned', undefined, prefix, argument)
  422. // 2. Return the IDL unsigned long long value that
  423. // represents the same numeric value as x.
  424. return x
  425. }
  426. // https://webidl.spec.whatwg.org/#es-unsigned-long
  427. webidl.converters['unsigned long'] = function (V, prefix, argument) {
  428. // 1. Let x be ? ConvertToInt(V, 32, "unsigned").
  429. const x = webidl.util.ConvertToInt(V, 32, 'unsigned', undefined, prefix, argument)
  430. // 2. Return the IDL unsigned long value that
  431. // represents the same numeric value as x.
  432. return x
  433. }
  434. // https://webidl.spec.whatwg.org/#es-unsigned-short
  435. webidl.converters['unsigned short'] = function (V, prefix, argument, opts) {
  436. // 1. Let x be ? ConvertToInt(V, 16, "unsigned").
  437. const x = webidl.util.ConvertToInt(V, 16, 'unsigned', opts, prefix, argument)
  438. // 2. Return the IDL unsigned short value that represents
  439. // the same numeric value as x.
  440. return x
  441. }
  442. // https://webidl.spec.whatwg.org/#idl-ArrayBuffer
  443. webidl.converters.ArrayBuffer = function (V, prefix, argument, opts) {
  444. // 1. If Type(V) is not Object, or V does not have an
  445. // [[ArrayBufferData]] internal slot, then throw a
  446. // TypeError.
  447. // see: https://tc39.es/ecma262/#sec-properties-of-the-arraybuffer-instances
  448. // see: https://tc39.es/ecma262/#sec-properties-of-the-sharedarraybuffer-instances
  449. if (
  450. webidl.util.Type(V) !== 'Object' ||
  451. !types.isAnyArrayBuffer(V)
  452. ) {
  453. throw webidl.errors.conversionFailed({
  454. prefix,
  455. argument: `${argument} ("${webidl.util.Stringify(V)}")`,
  456. types: ['ArrayBuffer']
  457. })
  458. }
  459. // 2. If the conversion is not to an IDL type associated
  460. // with the [AllowShared] extended attribute, and
  461. // IsSharedArrayBuffer(V) is true, then throw a
  462. // TypeError.
  463. if (opts?.allowShared === false && types.isSharedArrayBuffer(V)) {
  464. throw webidl.errors.exception({
  465. header: 'ArrayBuffer',
  466. message: 'SharedArrayBuffer is not allowed.'
  467. })
  468. }
  469. // 3. If the conversion is not to an IDL type associated
  470. // with the [AllowResizable] extended attribute, and
  471. // IsResizableArrayBuffer(V) is true, then throw a
  472. // TypeError.
  473. if (V.resizable || V.growable) {
  474. throw webidl.errors.exception({
  475. header: 'ArrayBuffer',
  476. message: 'Received a resizable ArrayBuffer.'
  477. })
  478. }
  479. // 4. Return the IDL ArrayBuffer value that is a
  480. // reference to the same object as V.
  481. return V
  482. }
  483. webidl.converters.TypedArray = function (V, T, prefix, name, opts) {
  484. // 1. Let T be the IDL type V is being converted to.
  485. // 2. If Type(V) is not Object, or V does not have a
  486. // [[TypedArrayName]] internal slot with a value
  487. // equal to T’s name, then throw a TypeError.
  488. if (
  489. webidl.util.Type(V) !== 'Object' ||
  490. !types.isTypedArray(V) ||
  491. V.constructor.name !== T.name
  492. ) {
  493. throw webidl.errors.conversionFailed({
  494. prefix,
  495. argument: `${name} ("${webidl.util.Stringify(V)}")`,
  496. types: [T.name]
  497. })
  498. }
  499. // 3. If the conversion is not to an IDL type associated
  500. // with the [AllowShared] extended attribute, and
  501. // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is
  502. // true, then throw a TypeError.
  503. if (opts?.allowShared === false && types.isSharedArrayBuffer(V.buffer)) {
  504. throw webidl.errors.exception({
  505. header: 'ArrayBuffer',
  506. message: 'SharedArrayBuffer is not allowed.'
  507. })
  508. }
  509. // 4. If the conversion is not to an IDL type associated
  510. // with the [AllowResizable] extended attribute, and
  511. // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is
  512. // true, then throw a TypeError.
  513. if (V.buffer.resizable || V.buffer.growable) {
  514. throw webidl.errors.exception({
  515. header: 'ArrayBuffer',
  516. message: 'Received a resizable ArrayBuffer.'
  517. })
  518. }
  519. // 5. Return the IDL value of type T that is a reference
  520. // to the same object as V.
  521. return V
  522. }
  523. webidl.converters.DataView = function (V, prefix, name, opts) {
  524. // 1. If Type(V) is not Object, or V does not have a
  525. // [[DataView]] internal slot, then throw a TypeError.
  526. if (webidl.util.Type(V) !== 'Object' || !types.isDataView(V)) {
  527. throw webidl.errors.exception({
  528. header: prefix,
  529. message: `${name} is not a DataView.`
  530. })
  531. }
  532. // 2. If the conversion is not to an IDL type associated
  533. // with the [AllowShared] extended attribute, and
  534. // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is true,
  535. // then throw a TypeError.
  536. if (opts?.allowShared === false && types.isSharedArrayBuffer(V.buffer)) {
  537. throw webidl.errors.exception({
  538. header: 'ArrayBuffer',
  539. message: 'SharedArrayBuffer is not allowed.'
  540. })
  541. }
  542. // 3. If the conversion is not to an IDL type associated
  543. // with the [AllowResizable] extended attribute, and
  544. // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is
  545. // true, then throw a TypeError.
  546. if (V.buffer.resizable || V.buffer.growable) {
  547. throw webidl.errors.exception({
  548. header: 'ArrayBuffer',
  549. message: 'Received a resizable ArrayBuffer.'
  550. })
  551. }
  552. // 4. Return the IDL DataView value that is a reference
  553. // to the same object as V.
  554. return V
  555. }
  556. // https://webidl.spec.whatwg.org/#BufferSource
  557. webidl.converters.BufferSource = function (V, prefix, name, opts) {
  558. if (types.isAnyArrayBuffer(V)) {
  559. return webidl.converters.ArrayBuffer(V, prefix, name, { ...opts, allowShared: false })
  560. }
  561. if (types.isTypedArray(V)) {
  562. return webidl.converters.TypedArray(V, V.constructor, prefix, name, { ...opts, allowShared: false })
  563. }
  564. if (types.isDataView(V)) {
  565. return webidl.converters.DataView(V, prefix, name, { ...opts, allowShared: false })
  566. }
  567. throw webidl.errors.conversionFailed({
  568. prefix,
  569. argument: `${name} ("${webidl.util.Stringify(V)}")`,
  570. types: ['BufferSource']
  571. })
  572. }
  573. webidl.converters['sequence<ByteString>'] = webidl.sequenceConverter(
  574. webidl.converters.ByteString
  575. )
  576. webidl.converters['sequence<sequence<ByteString>>'] = webidl.sequenceConverter(
  577. webidl.converters['sequence<ByteString>']
  578. )
  579. webidl.converters['record<ByteString, ByteString>'] = webidl.recordConverter(
  580. webidl.converters.ByteString,
  581. webidl.converters.ByteString
  582. )
  583. module.exports = {
  584. webidl
  585. }