aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2023-07-28 01:33:00 -0700
committerGravatar GitHub <noreply@github.com> 2023-07-28 01:33:00 -0700
commite110ccf84d8d9034e82a79bf7abf1fa92b2370be (patch)
treea4be8d322c2c61b767abce74ad670eeb65620b2e
parentc2a744f0cc1af080b2803e8b3b678bdaa4a1d14f (diff)
downloadbun-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.mjs20
-rw-r--r--src/bun.js/bindings/ScriptExecutionContext.cpp11
-rw-r--r--src/bun.js/bindings/ScriptExecutionContext.h2
-rw-r--r--src/bun.js/bindings/webcrypto/CryptoAlgorithm.cpp4
-rw-r--r--src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA1.cpp15
-rw-r--r--src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA224.cpp14
-rw-r--r--src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA256.cpp13
-rw-r--r--src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA384.cpp15
-rw-r--r--src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA512.cpp15
-rw-r--r--test/js/web/crypto/keeps-alive-fixture.js12
-rw-r--r--test/js/web/crypto/web-crypto.test.ts25
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");