lib: refactor internal webidl converters · nodejs/node@1c16b45 · GitHub
Skip to content

Commit 1c16b45

Browse files
panvasxa
authored andcommitted
lib: refactor internal webidl converters
Rework lib/internal/webidl.js into a documented shared converter module that follows the Web IDL conversion algorithms more closely. Improvements: - Add documented converters and helper factories for primitive values, dictionaries, enums, sequences, interfaces, required arguments, integers, `Uint8Array`, and `BufferSource`. - Move WebCrypto onto the shared converters, while keeping compatibility wrappers for its existing `BufferSource` and `BigInteger` behavior. - Use shared converters from Blob, Performance, Web Locks, and structured clone option handling. - Add benchmarks for `ConvertToInt` and WebCrypto Web IDL converter hot paths. - Add focused tests for core converters, WebCrypto converters, integer conversion, and buffer source behavior. Fixes: - Make the shared `BufferSource` and `Uint8Array` converters reject resizable `ArrayBuffer` and growable `SharedArrayBuffer` backing stores unless explicitly allowed. WebCrypto preserves its legacy resizable backing-store behavior through compatibility wrappers until a semver-major follow-up can opt in to the stricter behavior. - Use Web IDL `ToNumber` and `ToString` behavior for BigInt, Symbol, and object primitive conversion. - Use exact BigInt modulo for 64-bit `ConvertToInt` wrapping and document the final Number approximation behavior. - Normalize mathematical modulo results to `+0` where Web IDL requires it. - Process inherited dictionaries in least-derived to most-derived order, sorting members only within each dictionary level. - Use `IteratorComplete` truthiness for sequence conversion. - Cover detached buffers, resizable-backed views, growable-backed views, cross-realm buffer sources, mutation-after-call behavior, inherited dictionary member order, and sequence iterator completion behavior. Signed-off-by: Filip Skokan <panva.ip@gmail.com> PR-URL: #62979 Backport-PR-URL: #63563 Reviewed-By: Сковорода Никита Андреевич <chalkerx@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent a835363 commit 1c16b45

18 files changed

Lines changed: 2811 additions & 1070 deletions

benchmark/misc/webcrypto-webidl.js

Lines changed: 109 additions & 0 deletions
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
'use strict';
2+
3+
const assert = require('assert');
4+
const common = require('../common.js');
5+
6+
const bench = common.createBenchmark(main, {
7+
converter: [
8+
'byte',
9+
'octet',
10+
'unsigned short',
11+
'unsigned long',
12+
'long long',
13+
],
14+
input: [
15+
'integer',
16+
'fractional',
17+
'wrap',
18+
'clamp',
19+
'enforce-range',
20+
'object',
21+
],
22+
n: [1e6],
23+
}, { flags: ['--expose-internals'] });
24+
25+
function getConverter(converter) {
26+
switch (converter) {
27+
case 'byte':
28+
return { bitLength: 8, signedness: 'signed' };
29+
case 'octet':
30+
return { bitLength: 8 };
31+
case 'unsigned short':
32+
return { bitLength: 16 };
33+
case 'unsigned long':
34+
return { bitLength: 32 };
35+
case 'long long':
36+
return { bitLength: 64, signedness: 'signed' };
37+
default:
38+
throw new Error(`Unsupported converter: ${converter}`);
39+
}
40+
}
41+
42+
function getInput(input) {
43+
switch (input) {
44+
case 'integer':
45+
return { value: 7 };
46+
case 'fractional':
47+
return { value: 7.9 };
48+
case 'wrap':
49+
return { value: 2 ** 63 + 2 ** 11 };
50+
case 'clamp':
51+
return { value: 300.8, options: { clamp: true } };
52+
case 'enforce-range':
53+
return { value: 7.9, options: { enforceRange: true } };
54+
case 'object':
55+
return {
56+
value: {
57+
valueOf() { return 7; },
58+
},
59+
};
60+
default:
61+
throw new Error(`Unsupported input: ${input}`);
62+
}
63+
}
64+
65+
function main({ n, converter, input }) {
66+
const { convertToInt } = require('internal/webidl');
67+
const { bitLength, signedness } = getConverter(converter);
68+
const { value, options } = getInput(input);
69+
70+
let noDead;
71+
bench.start();
72+
if (options === undefined) {
73+
for (let i = 0; i < n; i++)
74+
noDead = convertToInt(value, bitLength, signedness);
75+
} else {
76+
for (let i = 0; i < n; i++)
77+
noDead = convertToInt(value, bitLength, signedness, options);
78+
}
79+
bench.end(n);
80+
81+
assert.strictEqual(typeof noDead, 'number');
82+
}

lib/internal/blob.js

Lines changed: 8 additions & 5 deletions

0 commit comments

Comments
 (0)