| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 9623d9a commit 8bb5360
1 file changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -17,6 +17,7 @@ const { | |||
| 17 | 17 | PromisePrototypeThen, | |
| 18 | 18 | PromiseReject, | |
| 19 | 19 | PromiseWithResolvers, | |
| 20 | + SafeMap, | ||
| 20 | 21 | SafeSet, | |
| 21 | 22 | StringPrototypeToUpperCase, | |
| 22 | 23 | Symbol, | |
@@ -455,8 +456,11 @@ const experimentalAlgorithms = [ | |||
| 455 | 456 | ]; | |
| 456 | 457 | ||
| 457 | 458 | // Transform the algorithm definitions into the operation-keyed structure | |
| 459 | + // Also builds a parallel Map<UPPERCASED_NAME, canonicalName> per operation | ||
| 460 | + // for O(1) case-insensitive algorithm name lookup in normalizeAlgorithm. | ||
| 458 | 461 | function createSupportedAlgorithms(algorithmDefs) { | |
| 459 | 462 | const result = {}; | |
| 463 | + const nameMap = {}; | ||
| 460 | 464 | ||
| 461 | 465 | for (const { 0: algorithmName, 1: operations } of ObjectEntries(algorithmDefs)) { | |
| 462 | 466 | // Skip algorithms that are conditionally not supported | |
@@ -467,6 +471,8 @@ function createSupportedAlgorithms(algorithmDefs) { | |||
| 467 | 471 | ||
| 468 | 472 | for (const { 0: operation, 1: dict } of ObjectEntries(operations)) { | |
| 469 | 473 | result[operation] ||= {}; | |
| 474 | + nameMap[operation] ||= new SafeMap(); | ||
| 475 | + nameMap[operation].set(StringPrototypeToUpperCase(algorithmName), algorithmName); | ||
| 470 | 476 | ||
| 471 | 477 | // Add experimental warnings for experimental algorithms | |
| 472 | 478 | if (ArrayPrototypeIncludes(experimentalAlgorithms, algorithmName)) { | |
@@ -484,10 +490,11 @@ function createSupportedAlgorithms(algorithmDefs) { | |||
| 484 | 490 | } | |
| 485 | 491 | } | |
| 486 | 492 | ||
| 487 | - return result; | ||
| 493 | + return { algorithms: result, nameMap }; | ||
| 488 | 494 | } | |
| 489 | 495 | ||
| 490 | - const kSupportedAlgorithms = createSupportedAlgorithms(kAlgorithmDefinitions); | ||
| 496 | + const { algorithms: kSupportedAlgorithms, nameMap: kAlgorithmNameMap } = | ||
| 497 | + createSupportedAlgorithms(kAlgorithmDefinitions); | ||
| 491 | 498 | ||
| 492 | 499 | const simpleAlgorithmDictionaries = { | |
| 493 | 500 | AesCbcParams: { iv: 'BufferSource' }, | |
@@ -529,6 +536,12 @@ const simpleAlgorithmDictionaries = { | |||
| 529 | 536 | TurboShakeParams: {}, | |
| 530 | 537 | }; | |
| 531 | 538 | ||
| 539 | + // Pre-compute ObjectKeys() for each dictionary entry at module init | ||
| 540 | + // to avoid allocating a new keys array on every normalizeAlgorithm call. | ||
| 541 | + for (const { 0: name, 1: types } of ObjectEntries(simpleAlgorithmDictionaries)) { | ||
| 542 | + simpleAlgorithmDictionaries[name] = { keys: ObjectKeys(types), types }; | ||
| 543 | + } | ||
| 544 | + | ||
| 532 | 545 | function validateMaxBufferLength(data, name, max = kMaxBufferLength) { | |
| 533 | 546 | if (data.byteLength > max) { | |
| 534 | 547 | throw lazyDOMException( | |
@@ -539,6 +552,14 @@ function validateMaxBufferLength(data, name, max = kMaxBufferLength) { | |||
| 539 | 552 | ||
| 540 | 553 | let webidl; | |
| 541 | 554 | ||
| 555 | + // Keep this as a regular object. The WebIDL converters read and spread these | ||
| 556 | + // options on the normalizeAlgorithm hot path, and a null-prototype object | ||
| 557 | + // measurably regresses benchmark/misc/webcrypto-webidl normalizeAlgorithm-*. | ||
| 558 | + const kNormalizeAlgorithmOpts = { | ||
| 559 | + prefix: 'Failed to normalize algorithm', | ||
| 560 | + context: 'passed algorithm', | ||
| 561 | + }; | ||
| 562 | + | ||
| 542 | 563 | // https://w3c.github.io/webcrypto/#algorithm-normalization-normalize-an-algorithm | |
| 543 | 564 | // adapted for Node.js from Deno's implementation | |
| 544 | 565 | // https://github.com/denoland/deno/blob/v1.29.1/ext/crypto/00_crypto.js#L195 | |
@@ -551,69 +572,56 @@ function normalizeAlgorithm(algorithm, op) { | |||
| 551 | 572 | // 1. | |
| 552 | 573 | const registeredAlgorithms = kSupportedAlgorithms[op]; | |
| 553 | 574 | // 2. 3. | |
| 554 | - const initialAlg = webidl.converters.Algorithm(algorithm, { | ||
| 555 | - prefix: 'Failed to normalize algorithm', | ||
| 556 | - context: 'passed algorithm', | ||
| 557 | - }); | ||
| 575 | + const initialAlg = webidl.converters.Algorithm(algorithm, | ||
| 576 | + kNormalizeAlgorithmOpts); | ||
| 558 | 577 | // 4. | |
| 559 | 578 | let algName = initialAlg.name; | |
| 560 | 579 | ||
| 561 | - // 5. | ||
| 562 | - let desiredType; | ||
| 563 | - for (const key in registeredAlgorithms) { | ||
| 564 | - if (!ObjectPrototypeHasOwnProperty(registeredAlgorithms, key)) { | ||
| 565 | - continue; | ||
| 566 | - } | ||
| 567 | - if ( | ||
| 568 | - StringPrototypeToUpperCase(key) === StringPrototypeToUpperCase(algName) | ||
| 569 | - ) { | ||
| 570 | - algName = key; | ||
| 571 | - desiredType = registeredAlgorithms[key]; | ||
| 572 | - } | ||
| 573 | - } | ||
| 574 | - if (desiredType === undefined) | ||
| 580 | + // 5. Case-insensitive lookup via pre-built Map (O(1) instead of O(n)). | ||
| 581 | + const canonicalName = kAlgorithmNameMap[op]?.get( | ||
| 582 | + StringPrototypeToUpperCase(algName)); | ||
| 583 | + if (canonicalName === undefined) | ||
| 575 | 584 | throw lazyDOMException('Unrecognized algorithm name', 'NotSupportedError'); | |
| 576 | 585 | ||
| 586 | + algName = canonicalName; | ||
| 587 | + const desiredType = registeredAlgorithms[algName]; | ||
| 588 | + | ||
| 577 | 589 | // Fast path everything below if the registered dictionary is null | |
| 578 | 590 | if (desiredType === null) | |
| 579 | 591 | return { name: algName }; | |
| 580 | 592 | ||
| 581 | 593 | // 6. | |
| 582 | 594 | const normalizedAlgorithm = webidl.converters[desiredType]( | |
| 583 | 595 | { __proto__: algorithm, name: algName }, | |
| 584 | - { | ||
| 585 | - prefix: 'Failed to normalize algorithm', | ||
| 586 | - context: 'passed algorithm', | ||
| 587 | - }, | ||
| 596 | + kNormalizeAlgorithmOpts, | ||
| 588 | 597 | ); | |
| 589 | 598 | // 7. | |
| 590 | 599 | normalizedAlgorithm.name = algName; | |
| 591 | 600 | ||
| 592 | - // 9. | ||
| 593 | - const dict = simpleAlgorithmDictionaries[desiredType]; | ||
| 594 | - // 10. | ||
| 595 | - const dictKeys = dict ? ObjectKeys(dict) : []; | ||
| 596 | - for (let i = 0; i < dictKeys.length; i++) { | ||
| 597 | - const member = dictKeys[i]; | ||
| 598 | - if (!ObjectPrototypeHasOwnProperty(dict, member)) | ||
| 599 | - continue; | ||
| 600 | - const idlType = dict[member]; | ||
| 601 | - const idlValue = normalizedAlgorithm[member]; | ||
| 602 | - // 3. | ||
| 603 | - if (idlType === 'BufferSource' && idlValue) { | ||
| 604 | - const isView = ArrayBufferIsView(idlValue); | ||
| 605 | - normalizedAlgorithm[member] = TypedArrayPrototypeSlice( | ||
| 606 | - new Uint8Array( | ||
| 607 | - isView ? getDataViewOrTypedArrayBuffer(idlValue) : idlValue, | ||
| 608 | - isView ? getDataViewOrTypedArrayByteOffset(idlValue) : 0, | ||
| 609 | - isView ? getDataViewOrTypedArrayByteLength(idlValue) : ArrayBufferPrototypeGetByteLength(idlValue), | ||
| 610 | - ), | ||
| 611 | - ); | ||
| 612 | - } else if (idlType === 'HashAlgorithmIdentifier') { | ||
| 613 | - normalizedAlgorithm[member] = normalizeAlgorithm(idlValue, 'digest'); | ||
| 614 | - } else if (idlType === 'AlgorithmIdentifier') { | ||
| 615 | - // This extension point is not used by any supported algorithm (yet?) | ||
| 616 | - throw lazyDOMException('Not implemented.', 'NotSupportedError'); | ||
| 601 | + // 9. 10. Pre-computed keys and types from simpleAlgorithmDictionaries. | ||
| 602 | + const dictMeta = simpleAlgorithmDictionaries[desiredType]; | ||
| 603 | + if (dictMeta) { | ||
| 604 | + const { keys: dictKeys, types: dictTypes } = dictMeta; | ||
| 605 | + for (let i = 0; i < dictKeys.length; i++) { | ||
| 606 | + const member = dictKeys[i]; | ||
| 607 | + const idlType = dictTypes[member]; | ||
| 608 | + const idlValue = normalizedAlgorithm[member]; | ||
| 609 | + // 3. | ||
| 610 | + if (idlType === 'BufferSource' && idlValue) { | ||
| 611 | + const isView = ArrayBufferIsView(idlValue); | ||
| 612 | + normalizedAlgorithm[member] = TypedArrayPrototypeSlice( | ||
| 613 | + new Uint8Array( | ||
| 614 | + isView ? getDataViewOrTypedArrayBuffer(idlValue) : idlValue, | ||
| 615 | + isView ? getDataViewOrTypedArrayByteOffset(idlValue) : 0, | ||
| 616 | + isView ? getDataViewOrTypedArrayByteLength(idlValue) : ArrayBufferPrototypeGetByteLength(idlValue), | ||
| 617 | + ), | ||
| 618 | + ); | ||
| 619 | + } else if (idlType === 'HashAlgorithmIdentifier') { | ||
| 620 | + normalizedAlgorithm[member] = normalizeAlgorithm(idlValue, 'digest'); | ||
| 621 | + } else if (idlType === 'AlgorithmIdentifier') { | ||
| 622 | + // This extension point is not used by any supported algorithm (yet?) | ||
| 623 | + throw lazyDOMException('Not implemented.', 'NotSupportedError'); | ||
| 624 | + } | ||
| 617 | 625 | } | |
| 618 | 626 | } | |
| 619 | 627 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments