* Converts a JavaScript value to a Web IDL integer value. * @see https://webidl.spec.whatwg.org/#abstract-opdef-converttoint * @param {any} V JavaScript value. * @param {number} bitLength Integer bit length. * @param {'signed'|'unsigned'} [signedness] Integer signedness. * @param {ConversionOpt
( V, bitLength, signedness = 'unsigned', options = kEmptyObject, )
| 319 | * @returns {number} |
| 320 | */ |
| 321 | function convertToInt( |
| 322 | V, |
| 323 | bitLength, |
| 324 | signedness = 'unsigned', |
| 325 | options = kEmptyObject, |
| 326 | ) { |
| 327 | const signed = signedness === 'signed'; |
| 328 | let upperBound; |
| 329 | let lowerBound; |
| 330 | |
| 331 | // Web IDL ConvertToInt steps 1-3: determine lower/upper bounds. |
| 332 | if (bitLength === 64) { |
| 333 | // Steps 1.1-1.3 set upperBound to 2^53 - 1 and lowerBound to 0 |
| 334 | // for unsigned, or -2^53 + 1 for signed. This ensures 64-bit |
| 335 | // integer types associated with [EnforceRange] or [Clamp] are |
| 336 | // representable in JavaScript's Number type as unambiguous integers. |
| 337 | upperBound = NumberMAX_SAFE_INTEGER; |
| 338 | lowerBound = signed ? NumberMIN_SAFE_INTEGER : 0; |
| 339 | } else if (!signed) { |
| 340 | // Spell out the common Web IDL integer sizes so hot converters avoid |
| 341 | // recomputing powers of two on every call. |
| 342 | lowerBound = 0; |
| 343 | if (bitLength === 8) { |
| 344 | upperBound = 0xff; |
| 345 | } else if (bitLength === 16) { |
| 346 | upperBound = 0xffff; |
| 347 | } else if (bitLength === 32) { |
| 348 | upperBound = 0xffff_ffff; |
| 349 | } else { |
| 350 | upperBound = pow2(bitLength) - 1; |
| 351 | } |
| 352 | } else if (bitLength === 8) { |
| 353 | // Signed 8/16/32-bit conversions are mostly exercised through direct |
| 354 | // convertToInt() calls, but keep their common bounds cheap too. |
| 355 | lowerBound = -0x80; |
| 356 | upperBound = 0x7f; |
| 357 | } else if (bitLength === 16) { |
| 358 | lowerBound = -0x8000; |
| 359 | upperBound = 0x7fff; |
| 360 | } else if (bitLength === 32) { |
| 361 | lowerBound = -0x8000_0000; |
| 362 | upperBound = 0x7fff_ffff; |
| 363 | } else { |
| 364 | lowerBound = -pow2(bitLength - 1); |
| 365 | upperBound = pow2(bitLength - 1) - 1; |
| 366 | } |
| 367 | |
| 368 | // Common case: primitive Number values that already fit the Web IDL |
| 369 | // range and have no fractional part are returned unchanged by every |
| 370 | // ConvertToInt path, except that -0 must become +0. This skips the |
| 371 | // generic ToNumber and option handling without skipping observable |
| 372 | // object coercion. |
| 373 | let x; |
| 374 | if (typeof V === 'number') { |
| 375 | // For primitive Numbers, in-range non-[Clamp] conversion is either |
| 376 | // identity or IntegerPart(V). This keeps the default and [EnforceRange] |
| 377 | // paths out of the generic ToNumber/options flow. |
| 378 | if (V >= lowerBound && V <= upperBound) { |
no test coverage detected
searching dependent graphs…