Skip to content

Commit e1004ed

Browse files
committed
crypto: streamline WebIDL dictionary converter hot loop
Simplify the generated dictionary converter's per-call work: classify V with `typeof` instead of `type()`, hoist `opts.prefix`/`opts.context` and `allMembers.length` out of the loop, and initialize `allMembers` with direct index assignment instead of `ArrayPrototypePush`. Also drops the now-unused `type()` helper. Signed-off-by: Filip Skokan <panva.ip@gmail.com>
1 parent 6cba07e commit e1004ed

File tree

1 file changed

+24
-57
lines changed

1 file changed

+24
-57
lines changed

lib/internal/crypto/webidl.js

Lines changed: 24 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
const {
1414
ArrayBufferIsView,
1515
ArrayPrototypeIncludes,
16-
ArrayPrototypePush,
1716
ArrayPrototypeSort,
1817
MathPow,
1918
MathTrunc,
@@ -67,37 +66,7 @@ function toNumber(value, opts = kEmptyObject) {
6766
}
6867
}
6968

70-
function type(V) {
71-
if (V === null)
72-
return 'Null';
73-
74-
switch (typeof V) {
75-
case 'undefined':
76-
return 'Undefined';
77-
case 'boolean':
78-
return 'Boolean';
79-
case 'number':
80-
return 'Number';
81-
case 'string':
82-
return 'String';
83-
case 'symbol':
84-
return 'Symbol';
85-
case 'bigint':
86-
return 'BigInt';
87-
case 'object': // Fall through
88-
case 'function': // Fall through
89-
default:
90-
// Per ES spec, typeof returns an implementation-defined value that is not
91-
// any of the existing ones for uncallable non-standard exotic objects.
92-
// Yet Type() which the Web IDL spec depends on returns Object for such
93-
// cases. So treat the default case as an object.
94-
return 'Object';
95-
}
96-
}
97-
9869
// Fast check for the WebIDL Object type: a non-null object or a function.
99-
// Equivalent to `type(V) === 'Object'` but avoids allocating and comparing
100-
// the intermediate string tag on hot paths.
10170
function isObjectType(V) {
10271
return V !== null && (typeof V === 'object' || typeof V === 'function');
10372
}
@@ -271,61 +240,59 @@ function createDictionaryConverter(name, dictionaries) {
271240
if (member.required) {
272241
hasRequiredKey = true;
273242
}
274-
ArrayPrototypePush(allMembers, member);
243+
allMembers[i] = member;
275244
}
276245
ArrayPrototypeSort(allMembers, (a, b) => {
277246
if (a.key === b.key) {
278247
return 0;
279248
}
280249
return a.key < b.key ? -1 : 1;
281250
});
251+
const membersLength = allMembers.length;
282252

283253
return function(V, opts = kEmptyObject) {
284-
const typeV = type(V);
285-
switch (typeV) {
286-
case 'Undefined':
287-
case 'Null':
288-
case 'Object':
289-
break;
290-
default:
291-
throw makeException(
292-
'can not be converted to a dictionary',
293-
opts);
254+
let isNullish;
255+
if (V === undefined || V === null) {
256+
isNullish = true;
257+
} else if (typeof V === 'object' || typeof V === 'function') {
258+
isNullish = false;
259+
} else {
260+
throw makeException(
261+
'can not be converted to a dictionary',
262+
opts);
294263
}
295-
const esDict = V;
264+
296265
const idlDict = {};
297266

298267
// Fast path null and undefined.
299-
if (V == null && !hasRequiredKey) {
268+
if (isNullish && !hasRequiredKey) {
300269
return idlDict;
301270
}
302271

303-
for (let i = 0; i < allMembers.length; i++) {
272+
const prefix = opts.prefix;
273+
const outerContext = opts.context;
274+
275+
for (let i = 0; i < membersLength; i++) {
304276
const member = allMembers[i];
305277
const key = member.key;
306278

307-
let esMemberValue;
308-
if (typeV === 'Undefined' || typeV === 'Null') {
309-
esMemberValue = undefined;
310-
} else {
311-
esMemberValue = esDict[key];
312-
}
279+
const esMemberValue = isNullish ? undefined : V[key];
313280

314281
if (esMemberValue !== undefined) {
315-
const context = `'${key}' of '${name}'${
316-
opts.context ? ` (${opts.context})` : ''
317-
}`;
282+
const context = outerContext ?
283+
`'${key}' of '${name}' (${outerContext})` :
284+
`'${key}' of '${name}'`;
318285
const idlMemberValue = member.converter(esMemberValue, {
319286
__proto__: null,
320-
prefix: opts.prefix,
287+
prefix,
321288
context,
322289
});
323-
member.validator?.(idlMemberValue, esDict);
290+
member.validator?.(idlMemberValue, V);
324291
setOwnProperty(idlDict, key, idlMemberValue);
325292
} else if (member.required) {
326293
throw makeException(
327294
`can not be converted to '${name}' because '${key}' is required in '${name}'.`,
328-
{ __proto__: null, prefix: opts.prefix, context: opts.context, code: 'ERR_MISSING_OPTION' });
295+
{ __proto__: null, prefix, context: outerContext, code: 'ERR_MISSING_OPTION' });
329296
}
330297
}
331298

0 commit comments

Comments
 (0)