From 97787beb4c644b7d3c274b65164bd6992e97753f Mon Sep 17 00:00:00 2001 From: Oleg Bespalov Date: Wed, 17 Apr 2024 16:18:55 +0200 Subject: [PATCH] refactor: GenerateKey to make it event loop safe --- webcrypto/subtle_crypto.go | 62 +++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/webcrypto/subtle_crypto.go b/webcrypto/subtle_crypto.go index 6cf6560..661a4e9 100644 --- a/webcrypto/subtle_crypto.go +++ b/webcrypto/subtle_crypto.go @@ -496,46 +496,66 @@ func (sc *SubtleCrypto) Digest(algorithm goja.Value, data goja.Value) *goja.Prom // // The `keyUsages` parameter is an array of strings indicating what the key can be used for. func (sc *SubtleCrypto) GenerateKey(algorithm goja.Value, extractable bool, keyUsages []CryptoKeyUsage) *goja.Promise { - promise, resolve, reject := promises.New(sc.vu) + rt := sc.vu.Runtime() - normalized, err := normalizeAlgorithm(sc.vu.Runtime(), algorithm, OperationIdentifierGenerateKey) - if err != nil { - reject(err) - return promise - } + var keyGenerator KeyGenerator + + err := func() error { + normalized, err := normalizeAlgorithm(rt, algorithm, OperationIdentifierGenerateKey) + if err != nil { + return err + } - keyGenerator, err := newKeyGenerator(sc.vu.Runtime(), normalized, algorithm) + keyGenerator, err = newKeyGenerator(rt, normalized, algorithm) + if err != nil { + return err + } + + return nil + }() + + promise, resolve, reject := rt.NewPromise() if err != nil { reject(err) return promise } + callback := sc.vu.RegisterCallback() go func() { - // 7. - result, err := keyGenerator.GenerateKey(extractable, keyUsages) - if err != nil { - reject(err) - return - } + result, err := func() (CryptoKeyGenerationResult, error) { + result, err := keyGenerator.GenerateKey(extractable, keyUsages) + if err != nil { + return nil, err + } + + if result.IsKeyPair() { + return result, nil + } - if !result.IsKeyPair() { cryptoKey, err := result.ResolveCryptoKey() if err != nil { - reject(NewError(OperationError, "usages cannot not be empty for a secret or private CryptoKey")) - return + return nil, NewError(OperationError, "usages cannot not be empty for a secret or private CryptoKey") } - // 8. isSecretKey := cryptoKey.Type == SecretCryptoKeyType isPrivateKey := cryptoKey.Type == PrivateCryptoKeyType isUsagesEmpty := len(cryptoKey.Usages) == 0 if (isSecretKey || isPrivateKey) && isUsagesEmpty { - reject(NewError(SyntaxError, "usages cannot not be empty for a secret or private CryptoKey")) - return + return nil, NewError(SyntaxError, "usages cannot not be empty for a secret or private CryptoKey") } - } - resolve(result) + return result, nil + }() + + callback(func() error { + if err != nil { + reject(err) + return nil //nolint:nilerr // we return nil to indicate that the error was handled + } + + resolve(result) + return nil + }) }() return promise