diff options
author | 2023-07-28 01:33:00 -0700 | |
---|---|---|
committer | 2023-07-28 01:33:00 -0700 | |
commit | e110ccf84d8d9034e82a79bf7abf1fa92b2370be (patch) | |
tree | a4be8d322c2c61b767abce74ad670eeb65620b2e | |
parent | c2a744f0cc1af080b2803e8b3b678bdaa4a1d14f (diff) | |
download | bun-e110ccf84d8d9034e82a79bf7abf1fa92b2370be.tar.gz bun-e110ccf84d8d9034e82a79bf7abf1fa92b2370be.tar.zst bun-e110ccf84d8d9034e82a79bf7abf1fa92b2370be.zip |
Fixes #3795 (#3856)
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
-rw-r--r-- | bench/snippets/webcrypto.mjs | 20 | ||||
-rw-r--r-- | src/bun.js/bindings/ScriptExecutionContext.cpp | 11 | ||||
-rw-r--r-- | src/bun.js/bindings/ScriptExecutionContext.h | 2 | ||||
-rw-r--r-- | src/bun.js/bindings/webcrypto/CryptoAlgorithm.cpp | 4 | ||||
-rw-r--r-- | src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA1.cpp | 15 | ||||
-rw-r--r-- | src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA224.cpp | 14 | ||||
-rw-r--r-- | src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA256.cpp | 13 | ||||
-rw-r--r-- | src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA384.cpp | 15 | ||||
-rw-r--r-- | src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA512.cpp | 15 | ||||
-rw-r--r-- | test/js/web/crypto/keeps-alive-fixture.js | 12 | ||||
-rw-r--r-- | test/js/web/crypto/web-crypto.test.ts | 25 |
11 files changed, 140 insertions, 6 deletions
diff --git a/bench/snippets/webcrypto.mjs b/bench/snippets/webcrypto.mjs new file mode 100644 index 000000000..2d1256cf8 --- /dev/null +++ b/bench/snippets/webcrypto.mjs @@ -0,0 +1,20 @@ +import { group } from "mitata"; +import { bench, run } from "./runner.mjs"; + +const sizes = [ + ["small (63 bytes)", 63], + ["medium (4096 bytes)", 4096], + ["large (64 MB)", 64 * 1024 * 1024], +]; +for (let [name, size] of sizes) { + group(name, () => { + var buf = new Uint8Array(size); + for (let algorithm of ["SHA-1", "SHA-256", "SHA-384", "SHA-512"]) { + bench(algorithm, async () => { + await crypto.subtle.digest(algorithm, buf); + }); + } + }); +} + +await run(); diff --git a/src/bun.js/bindings/ScriptExecutionContext.cpp b/src/bun.js/bindings/ScriptExecutionContext.cpp index d93478ed8..47908b385 100644 --- a/src/bun.js/bindings/ScriptExecutionContext.cpp +++ b/src/bun.js/bindings/ScriptExecutionContext.cpp @@ -5,6 +5,7 @@ #include "webcore/WebSocket.h" #include "libusockets.h" #include "_libusockets.h" +#include "BunClientData.h" extern "C" void Bun__startLoop(us_loop_t* loop); @@ -58,6 +59,16 @@ us_socket_context_t* ScriptExecutionContext::webSocketContextSSL() return m_ssl_client_websockets_ctx; } +extern "C" void Bun__eventLoop__incrementRefConcurrently(void* bunVM, int delta); + +void ScriptExecutionContext::refEventLoop() +{ + Bun__eventLoop__incrementRefConcurrently(WebCore::clientData(vm())->bunVM, 1); +} +void ScriptExecutionContext::unrefEventLoop() +{ + Bun__eventLoop__incrementRefConcurrently(WebCore::clientData(vm())->bunVM, -1); +} bool ScriptExecutionContext::postTaskTo(ScriptExecutionContextIdentifier identifier, Function<void(ScriptExecutionContext&)>&& task) { diff --git a/src/bun.js/bindings/ScriptExecutionContext.h b/src/bun.js/bindings/ScriptExecutionContext.h index 580c1be25..b0e4e2096 100644 --- a/src/bun.js/bindings/ScriptExecutionContext.h +++ b/src/bun.js/bindings/ScriptExecutionContext.h @@ -107,6 +107,8 @@ public: } static ScriptExecutionContext* getScriptExecutionContext(ScriptExecutionContextIdentifier identifier); + void refEventLoop(); + void unrefEventLoop(); const WTF::URL& url() const { diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithm.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithm.cpp index ca3b97bff..3c958bdfc 100644 --- a/src/bun.js/bindings/webcrypto/CryptoAlgorithm.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithm.cpp @@ -95,10 +95,12 @@ ExceptionOr<size_t> CryptoAlgorithm::getKeyLength(const CryptoAlgorithmParameter template<typename ResultCallbackType, typename OperationType> static void dispatchAlgorithmOperation(WorkQueue& workQueue, ScriptExecutionContext& context, ResultCallbackType&& callback, CryptoAlgorithm::ExceptionCallback&& exceptionCallback, OperationType&& operation) { + context.refEventLoop(); workQueue.dispatch( [operation = WTFMove(operation), callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback), contextIdentifier = context.identifier()]() mutable { auto result = operation(); - ScriptExecutionContext::postTaskTo(contextIdentifier, [result = crossThreadCopy(WTFMove(result)), callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback)](auto&) mutable { + ScriptExecutionContext::postTaskTo(contextIdentifier, [result = crossThreadCopy(WTFMove(result)), callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback)](auto& context) mutable { + context.unrefEventLoop(); if (result.hasException()) { exceptionCallback(result.releaseException().code()); return; diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA1.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA1.cpp index f602467e0..8a2a8829f 100644 --- a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA1.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA1.cpp @@ -51,10 +51,23 @@ void CryptoAlgorithmSHA1::digest(Vector<uint8_t>&& message, VectorCallback&& cal return; } + if (message.size() < 64) { + auto moved = WTFMove(message); + digest->addBytes(moved.data(), moved.size()); + auto result = digest->computeHash(); + ScriptExecutionContext::postTaskTo(context.identifier(), [callback = WTFMove(callback), result = WTFMove(result)](auto&) { + callback(result); + }); + return; + } + + context.refEventLoop(); + workQueue.dispatch([digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { digest->addBytes(message.data(), message.size()); auto result = digest->computeHash(); - ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto&) { + ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto& context) { + context.unrefEventLoop(); callback(result); }); }); diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA224.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA224.cpp index dfb8204b5..3591215bf 100644 --- a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA224.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA224.cpp @@ -51,10 +51,22 @@ void CryptoAlgorithmSHA224::digest(Vector<uint8_t>&& message, VectorCallback&& c return; } + if (message.size() < 64) { + auto moved = WTFMove(message); + digest->addBytes(moved.data(), moved.size()); + auto result = digest->computeHash(); + ScriptExecutionContext::postTaskTo(context.identifier(), [callback = WTFMove(callback), result = WTFMove(result)](auto&) { + callback(result); + }); + return; + } + + context.refEventLoop(); workQueue.dispatch([digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { digest->addBytes(message.data(), message.size()); auto result = digest->computeHash(); - ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto&) { + ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto& context) { + context.unrefEventLoop(); callback(result); }); }); diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA256.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA256.cpp index 216eccb5d..c9bad917b 100644 --- a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA256.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA256.cpp @@ -51,10 +51,21 @@ void CryptoAlgorithmSHA256::digest(Vector<uint8_t>&& message, VectorCallback&& c return; } + if (message.size() < 64) { + auto moved = WTFMove(message); + digest->addBytes(moved.data(), moved.size()); + auto result = digest->computeHash(); + ScriptExecutionContext::postTaskTo(context.identifier(), [callback = WTFMove(callback), result = WTFMove(result)](auto&) { + callback(result); + }); + return; + } + context.refEventLoop(); workQueue.dispatch([digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { digest->addBytes(message.data(), message.size()); auto result = digest->computeHash(); - ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto&) { + ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto& context) { + context.unrefEventLoop(); callback(result); }); }); diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA384.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA384.cpp index 134e89bd8..890d317b9 100644 --- a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA384.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA384.cpp @@ -51,10 +51,23 @@ void CryptoAlgorithmSHA384::digest(Vector<uint8_t>&& message, VectorCallback&& c return; } + if (message.size() < 64) { + auto moved = WTFMove(message); + digest->addBytes(moved.data(), moved.size()); + auto result = digest->computeHash(); + ScriptExecutionContext::postTaskTo(context.identifier(), [callback = WTFMove(callback), result = WTFMove(result)](auto&) { + callback(result); + }); + return; + } + + context.refEventLoop(); + workQueue.dispatch([digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { digest->addBytes(message.data(), message.size()); auto result = digest->computeHash(); - ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto&) { + ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto& context) { + context.unrefEventLoop(); callback(result); }); }); diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA512.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA512.cpp index 016a47bf1..38a9fbe18 100644 --- a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA512.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA512.cpp @@ -51,10 +51,23 @@ void CryptoAlgorithmSHA512::digest(Vector<uint8_t>&& message, VectorCallback&& c return; } + if (message.size() < 64) { + auto moved = WTFMove(message); + digest->addBytes(moved.data(), moved.size()); + auto result = digest->computeHash(); + ScriptExecutionContext::postTaskTo(context.identifier(), [callback = WTFMove(callback), result = WTFMove(result)](auto&) { + callback(result); + }); + return; + } + + context.refEventLoop(); workQueue.dispatch([digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { digest->addBytes(message.data(), message.size()); auto result = digest->computeHash(); - ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto&) { + + ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto& context) { + context.unrefEventLoop(); callback(result); }); }); diff --git a/test/js/web/crypto/keeps-alive-fixture.js b/test/js/web/crypto/keeps-alive-fixture.js new file mode 100644 index 000000000..0740923a5 --- /dev/null +++ b/test/js/web/crypto/keeps-alive-fixture.js @@ -0,0 +1,12 @@ +const algorithms = ["SHA-1", "SHA-256", "SHA-384", "SHA-512"]; +const data = [ + "Hello World!", + "Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World!Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World!", +]; +for (let bytes of data) { + for (const algorithm of algorithms) { + crypto.subtle.digest(algorithm, Buffer.from(bytes)).then(data => { + console.log(Buffer.from(data).toString("hex")); + }); + } +} diff --git a/test/js/web/crypto/web-crypto.test.ts b/test/js/web/crypto/web-crypto.test.ts index b8155c3ba..006d48851 100644 --- a/test/js/web/crypto/web-crypto.test.ts +++ b/test/js/web/crypto/web-crypto.test.ts @@ -1,6 +1,31 @@ +import { spawnSync } from "bun"; import { describe, expect, it } from "bun:test"; +import { bunEnv, bunExe } from "harness"; describe("Web Crypto", () => { + // https://github.com/oven-sh/bun/issues/3795 + it("keeps event loop alive", () => { + const { stdout, exitCode } = spawnSync({ + cmd: [bunExe(), import.meta.resolveSync("./keeps-alive-fixture.js")], + env: bunEnv, + }); + + const lines = stdout.toString().trim().split("\n").sort(); + const results = [ + "2ef7bde608ce5404e97d5f042f95f89f1c232871", + "6b3e626d70787e3dc3f0bca509a7e1e5f6802643fde54a18d4353aa9b24ccb2fb874bbc8a70ff587df2bd6ed41471f82", + "7dc2af5ef620a4b1c8871371526b664512b82193", + "7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069", + "861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8", + "bf6873609ce720ec489bb2f5ae116716058c06cda7dc9a7e1dadee90da98e71aee22519505af61adbecd5b94bbefa855c2ede623e8b383bb179b150e25861441", + "bfd76c0ebbd006fee583410547c1887b0292be76d582d96c242d2a792723e3fd6fd061f9d5cfd13b8f961358e6adba4a", + "e1061f7858d68c3818ec9967ea1f7bf8e3c65f5603af95004bdfcb64b9ea4148", + ]; + + expect(exitCode).toBe(0); + expect(lines).toStrictEqual(results); + }); + it("has globals", () => { expect(crypto.subtle !== undefined).toBe(true); expect(CryptoKey.name).toBe("CryptoKey"); |