Skip to content

Commit 3a0cfa1

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 ac78a90 commit 3a0cfa1

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
}
@@ -251,61 +220,59 @@ function createDictionaryConverter(name, dictionaries) {
251220
if (member.required) {
252221
hasRequiredKey = true;
253222
}
254-
ArrayPrototypePush(allMembers, member);
223+
allMembers[i] = member;
255224
}
256225
ArrayPrototypeSort(allMembers, (a, b) => {
257226
if (a.key === b.key) {
258227
return 0;
259228
}
260229
return a.key < b.key ? -1 : 1;
261230
});
231+
const membersLength = allMembers.length;
262232

263233
return function(V, opts = kEmptyObject) {
264-
const typeV = type(V);
265-
switch (typeV) {
266-
case 'Undefined':
267-
case 'Null':
268-
case 'Object':
269-
break;
270-
default:
271-
throw makeException(
272-
'can not be converted to a dictionary',
273-
opts);
234+
let isNullish;
235+
if (V === undefined || V === null) {
236+
isNullish = true;
237+
} else if (typeof V === 'object' || typeof V === 'function') {
238+
isNullish = false;
239+
} else {
240+
throw makeException(
241+
'can not be converted to a dictionary',
242+
opts);
274243
}
275-
const esDict = V;
244+
276245
const idlDict = {};
277246

278247
// Fast path null and undefined.
279-
if (V == null && !hasRequiredKey) {
248+
if (isNullish && !hasRequiredKey) {
280249
return idlDict;
281250
}
282251

283-
for (let i = 0; i < allMembers.length; i++) {
252+
const prefix = opts.prefix;
253+
const outerContext = opts.context;
254+
255+
for (let i = 0; i < membersLength; i++) {
284256
const member = allMembers[i];
285257
const key = member.key;
286258

287-
let esMemberValue;
288-
if (typeV === 'Undefined' || typeV === 'Null') {
289-
esMemberValue = undefined;
290-
} else {
291-
esMemberValue = esDict[key];
292-
}
259+
const esMemberValue = isNullish ? undefined : V[key];
293260

294261
if (esMemberValue !== undefined) {
295-
const context = `'${key}' of '${name}'${
296-
opts.context ? ` (${opts.context})` : ''
297-
}`;
262+
const context = outerContext ?
263+
`'${key}' of '${name}' (${outerContext})` :
264+
`'${key}' of '${name}'`;
298265
const idlMemberValue = member.converter(esMemberValue, {
299266
__proto__: null,
300-
prefix: opts.prefix,
267+
prefix,
301268
context,
302269
});
303-
member.validator?.(idlMemberValue, esDict);
270+
member.validator?.(idlMemberValue, V);
304271
setOwnProperty(idlDict, key, idlMemberValue);
305272
} else if (member.required) {
306273
throw makeException(
307274
`can not be converted to '${name}' because '${key}' is required in '${name}'.`,
308-
{ __proto__: null, prefix: opts.prefix, context: opts.context, code: 'ERR_MISSING_OPTION' });
275+
{ __proto__: null, prefix, context: outerContext, code: 'ERR_MISSING_OPTION' });
309276
}
310277
}
311278

0 commit comments

Comments
 (0)