11'use strict' ;
22
33const {
4- ArrayFrom,
54 ArrayPrototypeSlice,
65 ObjectDefineProperties,
76 ObjectDefineProperty,
@@ -63,7 +62,9 @@ const {
6362 bigIntArrayToUnsignedBigInt,
6463 normalizeAlgorithm,
6564 hasAnyNotIn,
66- getSortedUsages,
65+ getUsagesMask,
66+ getUsagesFromMask,
67+ hasUsage,
6768} = require ( 'internal/crypto/util' ) ;
6869
6970const {
@@ -255,7 +256,7 @@ const {
255256 throw lazyDOMException ( 'Unrecognized algorithm name' , 'NotSupportedError' ) ;
256257 }
257258
258- if ( getCryptoKeyUsages ( result ) . length === 0 ) {
259+ if ( getCryptoKeyUsagesMask ( result ) === 0 ) {
259260 throw lazyDOMException (
260261 `Usages cannot be empty when importing a ${ getCryptoKeyType ( result ) } key.` ,
261262 'SyntaxError' ) ;
@@ -351,7 +352,7 @@ const {
351352 }
352353
353354 const resultType = getCryptoKeyType ( result ) ;
354- if ( resultType === 'private' && getCryptoKeyUsages ( result ) . length === 0 ) {
355+ if ( resultType === 'private' && getCryptoKeyUsagesMask ( result ) === 0 ) {
355356 throw lazyDOMException (
356357 `Usages cannot be empty when importing a ${ resultType } key.` ,
357358 'SyntaxError' ) ;
@@ -770,9 +771,9 @@ function isKeyObject(obj) {
770771}
771772
772773// CryptoKey is a plain JS class whose prototype's [[Prototype]] is
773- // Object.prototype, as Web Crypto requires. Instance storage (type,
774- // extractable, algorithm, usages, and the KeyObject handle) lives on
775- // a C++ class, NativeCryptoKey, created by createCryptoKeyClass.
774+ // Object.prototype, as Web Crypto requires. Instance storage (type enum ,
775+ // extractable, algorithm, usages mask , and the KeyObject handle) lives
776+ // on a C++ class, NativeCryptoKey, created by createCryptoKeyClass.
776777// InternalCryptoKey is the only constructor we expose to internal
777778// code; it extends NativeCryptoKey to get that storage and then has
778779// its prototype spliced so the chain visible to user code is:
@@ -786,18 +787,21 @@ function isKeyObject(obj) {
786787// reflection (`Object.getOwnPropertySymbols` etc.) and leaves each
787788// CryptoKey's hidden class pristine. The `getCryptoKey{Type,
788789// Extractable,Algorithm,Usages,Handle }` helpers index into that
789- // array; the public `algorithm` / `usages` getters further cache a
790- // cloned copy (as Web Crypto requires repeat reads to return the
791- // same object so a consumer's mutation is visible next time).
790+ // array and convert native enums/masks back to Web Crypto strings.
791+ // The public `algorithm` getter caches a cloned dictionary and the
792+ // public `usages` getter caches a synthesized array (as Web Crypto
793+ // requires repeat reads to return the same object so a consumer's
794+ // mutation is visible next time).
792795let getSlots ; // Populated by the createCryptoKeyClass callback below.
793796
794797const kSlotType = 0 ;
795798const kSlotExtractable = 1 ;
796799const kSlotAlgorithm = 2 ;
797- const kSlotUsages = 3 ;
800+ const kSlotUsagesMask = 3 ;
798801const kSlotHandle = 4 ;
799802const kSlotClonedAlgorithm = 5 ;
800803const kSlotClonedUsages = 6 ;
804+ const kSlotUsages = 7 ;
801805
802806function cloneAlgorithm ( raw ) {
803807 const cloned = { ...raw } ;
@@ -855,7 +859,7 @@ const {
855859 const slots = getSlots ( this ) ;
856860 let cached = slots [ kSlotClonedUsages ] ;
857861 if ( cached === undefined ) {
858- cached = ArrayFrom ( slots [ kSlotUsages ] ) ;
862+ cached = ArrayPrototypeSlice ( getCryptoKeyUsagesFromSlots ( slots ) , 0 ) ;
859863 slots [ kSlotClonedUsages ] = cached ;
860864 }
861865 return cached ;
@@ -900,8 +904,9 @@ const {
900904// The helpers below return a CryptoKey's internal slot value,
901905// populating the per-instance cache on first access via a single
902906// native call. The public `type` getter converts the native enum to
903- // the Web Crypto string. The public `algorithm` / `usages` getters on
904- // `CryptoKey.prototype` further clone their slot before returning.
907+ // the Web Crypto string. The `usages` helper converts the native usage
908+ // mask to Web Crypto strings. The public `algorithm` / `usages` getters
909+ // on `CryptoKey.prototype` cache their returned objects.
905910
906911/**
907912 * Returns the value of a CryptoKey's `[[type]]` internal slot.
@@ -914,7 +919,6 @@ function getCryptoKeyType(key) {
914919 case kKeyTypePublic : return 'public' ;
915920 case kKeyTypePrivate : return 'private' ;
916921 default : {
917- // It is not possible to get here because all possible cases are handled above.
918922 const assert = require ( 'internal/assert' ) ;
919923 assert . fail ( 'Unreachable code' ) ;
920924 }
@@ -940,14 +944,31 @@ function getCryptoKeyAlgorithm(key) {
940944 return getSlots ( key ) [ kSlotAlgorithm ] ;
941945}
942946
947+ function getCryptoKeyUsagesMask ( key ) {
948+ return getSlots ( key ) [ kSlotUsagesMask ] ;
949+ }
950+
951+ function hasCryptoKeyUsage ( key , usage ) {
952+ return hasUsage ( getCryptoKeyUsagesMask ( key ) , usage ) ;
953+ }
954+
955+ function getCryptoKeyUsagesFromSlots ( slots ) {
956+ let usages = slots [ kSlotUsages ] ;
957+ if ( usages === undefined ) {
958+ usages = getUsagesFromMask ( slots [ kSlotUsagesMask ] ) ;
959+ slots [ kSlotUsages ] = usages ;
960+ }
961+ return usages ;
962+ }
963+
943964/**
944965 * Returns the CryptoKey's `[[usages]]` internal slot, bypassing the
945966 * public `usages` getter (which returns a cloned array).
946967 * @param {CryptoKey } key
947968 * @returns {string[] }
948969 */
949970function getCryptoKeyUsages ( key ) {
950- return getSlots ( key ) [ kSlotUsages ] ;
971+ return getCryptoKeyUsagesFromSlots ( getSlots ( key ) ) ;
951972}
952973
953974/**
@@ -1009,7 +1030,7 @@ function importGenericSecretKey(
10091030 return new InternalCryptoKey (
10101031 handle ,
10111032 { name } ,
1012- getSortedUsages ( usagesSet ) ,
1033+ getUsagesMask ( usagesSet ) ,
10131034 false ) ;
10141035}
10151036
@@ -1038,6 +1059,8 @@ module.exports = {
10381059 getCryptoKeyExtractable,
10391060 getCryptoKeyAlgorithm,
10401061 getCryptoKeyUsages,
1062+ getCryptoKeyUsagesMask,
1063+ hasCryptoKeyUsage,
10411064 getCryptoKeyHandle,
10421065 importGenericSecretKey,
10431066} ;
0 commit comments