aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/bun-linux-aarch64.yml2
-rw-r--r--.github/workflows/bun-linux-build.yml4
-rw-r--r--.github/workflows/bun-mac-aarch64.yml16
-rw-r--r--.github/workflows/bun-mac-x64-baseline.yml16
-rw-r--r--.github/workflows/bun-mac-x64.yml16
-rw-r--r--Dockerfile2
-rwxr-xr-xbun.lockbbin73628 -> 73628 bytes
-rw-r--r--package.json2
m---------src/bun.js/WebKit0
-rw-r--r--src/bun.js/bindings/BunClientData.cpp8
-rw-r--r--src/bun.js/bindings/BunClientData.h6
-rw-r--r--src/bun.js/bindings/JSCTaskScheduler.cpp101
-rw-r--r--src/bun.js/bindings/JSCTaskScheduler.h25
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.cpp2
-rw-r--r--src/bun.js/bindings/bindings.cpp6
-rw-r--r--src/bun.js/bindings/bindings.zig10
-rw-r--r--src/bun.js/bindings/headers.h1
-rw-r--r--src/bun.js/bindings/headers.zig1
-rw-r--r--src/bun.js/event_loop.zig52
-rw-r--r--src/bun.js/web_worker.zig4
-rw-r--r--src/bun.js/webcore/response.zig2
-rw-r--r--src/bun.js/webcore/streams.zig2
-rw-r--r--src/cli/test_command.zig1
-rw-r--r--src/deps/uws.zig12
-rw-r--r--src/js/bun/wasi-runner.js15
-rw-r--r--src/js/out/modules/bun/wasi-runner.js11
-rw-r--r--src/napi/napi.zig6
-rw-r--r--src/tagged_pointer.zig4
-rwxr-xr-xtest/bun.lockbbin148960 -> 148992 bytes
-rw-r--r--test/js/third_party/es-module-lexer/.gitignore169
-rw-r--r--test/js/third_party/es-module-lexer/README.md14
-rw-r--r--test/js/third_party/es-module-lexer/es-module-lexer.test.ts45
-rw-r--r--test/js/third_party/es-module-lexer/index.ts13
-rw-r--r--test/js/third_party/es-module-lexer/package.json11
-rw-r--r--test/js/third_party/es-module-lexer/tsconfig.json21
-rw-r--r--test/package.json1
36 files changed, 530 insertions, 71 deletions
diff --git a/.github/workflows/bun-linux-aarch64.yml b/.github/workflows/bun-linux-aarch64.yml
index df6a75892..721e5d052 100644
--- a/.github/workflows/bun-linux-aarch64.yml
+++ b/.github/workflows/bun-linux-aarch64.yml
@@ -36,7 +36,7 @@ jobs:
arch: aarch64
build_arch: arm64
runner: linux-arm64
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-linux-arm64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-linux-arm64-lto.tar.gz"
webkit_basename: "bun-webkit-linux-arm64-lto"
build_machine_arch: aarch64
diff --git a/.github/workflows/bun-linux-build.yml b/.github/workflows/bun-linux-build.yml
index 00a7443a0..f69b165bd 100644
--- a/.github/workflows/bun-linux-build.yml
+++ b/.github/workflows/bun-linux-build.yml
@@ -46,7 +46,7 @@ jobs:
arch: x86_64
build_arch: amd64
runner: big-ubuntu
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-linux-amd64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-linux-amd64-lto.tar.gz"
webkit_basename: "bun-webkit-linux-amd64-lto"
build_machine_arch: x86_64
- cpu: nehalem
@@ -54,7 +54,7 @@ jobs:
arch: x86_64
build_arch: amd64
runner: big-ubuntu
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-linux-amd64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-linux-amd64-lto.tar.gz"
webkit_basename: "bun-webkit-linux-amd64-lto"
build_machine_arch: x86_64
diff --git a/.github/workflows/bun-mac-aarch64.yml b/.github/workflows/bun-mac-aarch64.yml
index 13fb3aa0b..db81f7d6b 100644
--- a/.github/workflows/bun-mac-aarch64.yml
+++ b/.github/workflows/bun-mac-aarch64.yml
@@ -117,7 +117,7 @@ jobs:
# obj: bun-obj-darwin-x64-baseline
# runner: macos-11
# artifact: bun-obj-darwin-x64-baseline
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: true
# compile_obj: false
# - cpu: haswell
@@ -126,7 +126,7 @@ jobs:
# obj: bun-obj-darwin-x64
# runner: macos-11
# artifact: bun-obj-darwin-x64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: true
# compile_obj: false
# - cpu: nehalem
@@ -135,7 +135,7 @@ jobs:
# obj: bun-obj-darwin-x64-baseline
# runner: macos-11
# artifact: bun-obj-darwin-x64-baseline
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: false
# compile_obj: true
# - cpu: haswell
@@ -144,7 +144,7 @@ jobs:
# obj: bun-obj-darwin-x64
# runner: macos-11
# artifact: bun-obj-darwin-x64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: false
# compile_obj: true
- cpu: native
@@ -152,7 +152,7 @@ jobs:
tag: bun-darwin-aarch64
obj: bun-obj-darwin-aarch64
artifact: bun-obj-darwin-aarch64
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-arm64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-arm64-lto.tar.gz"
runner: macos-arm64
dependencies: true
compile_obj: true
@@ -257,7 +257,7 @@ jobs:
# package: bun-darwin-x64
# runner: macos-11
# artifact: bun-obj-darwin-x64-baseline
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
# - cpu: haswell
# arch: x86_64
# tag: bun-darwin-x64
@@ -265,14 +265,14 @@ jobs:
# package: bun-darwin-x64
# runner: macos-11
# artifact: bun-obj-darwin-x64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
- cpu: native
arch: aarch64
tag: bun-darwin-aarch64
obj: bun-obj-darwin-aarch64
package: bun-darwin-aarch64
artifact: bun-obj-darwin-aarch64
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-arm64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-arm64-lto.tar.gz"
runner: macos-arm64
steps:
- uses: actions/checkout@v3
diff --git a/.github/workflows/bun-mac-x64-baseline.yml b/.github/workflows/bun-mac-x64-baseline.yml
index 163d8cac8..80765d29c 100644
--- a/.github/workflows/bun-mac-x64-baseline.yml
+++ b/.github/workflows/bun-mac-x64-baseline.yml
@@ -117,7 +117,7 @@ jobs:
obj: bun-obj-darwin-x64-baseline
runner: macos-11
artifact: bun-obj-darwin-x64-baseline
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
dependencies: true
compile_obj: false
# - cpu: haswell
@@ -126,7 +126,7 @@ jobs:
# obj: bun-obj-darwin-x64
# runner: macos-11
# artifact: bun-obj-darwin-x64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: true
# compile_obj: false
- cpu: nehalem
@@ -135,7 +135,7 @@ jobs:
obj: bun-obj-darwin-x64-baseline
runner: macos-11
artifact: bun-obj-darwin-x64-baseline
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
dependencies: false
compile_obj: true
# - cpu: haswell
@@ -144,7 +144,7 @@ jobs:
# obj: bun-obj-darwin-x64
# runner: macos-11
# artifact: bun-obj-darwin-x64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: false
# compile_obj: true
# - cpu: native
@@ -152,7 +152,7 @@ jobs:
# tag: bun-darwin-aarch64
# obj: bun-obj-darwin-aarch64
# artifact: bun-obj-darwin-aarch64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
# runner: macos-arm64
# dependencies: true
# compile_obj: true
@@ -258,7 +258,7 @@ jobs:
package: bun-darwin-x64
runner: macos-11
artifact: bun-obj-darwin-x64-baseline
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
# - cpu: haswell
# arch: x86_64
# tag: bun-darwin-x64
@@ -266,14 +266,14 @@ jobs:
# package: bun-darwin-x64
# runner: macos-11
# artifact: bun-obj-darwin-x64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
# - cpu: native
# arch: aarch64
# tag: bun-darwin-aarch64
# obj: bun-obj-darwin-aarch64
# package: bun-darwin-aarch64
# artifact: bun-obj-darwin-aarch64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
# runner: macos-arm64
steps:
- uses: actions/checkout@v3
diff --git a/.github/workflows/bun-mac-x64.yml b/.github/workflows/bun-mac-x64.yml
index d3ed46015..0f1e00b44 100644
--- a/.github/workflows/bun-mac-x64.yml
+++ b/.github/workflows/bun-mac-x64.yml
@@ -117,7 +117,7 @@ jobs:
# obj: bun-obj-darwin-x64-baseline
# runner: macos-11
# artifact: bun-obj-darwin-x64-baseline
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: true
# compile_obj: false
- cpu: haswell
@@ -126,7 +126,7 @@ jobs:
obj: bun-obj-darwin-x64
runner: macos-11
artifact: bun-obj-darwin-x64
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
dependencies: true
compile_obj: false
# - cpu: nehalem
@@ -135,7 +135,7 @@ jobs:
# obj: bun-obj-darwin-x64-baseline
# runner: macos-11
# artifact: bun-obj-darwin-x64-baseline
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: false
# compile_obj: true
- cpu: haswell
@@ -144,7 +144,7 @@ jobs:
obj: bun-obj-darwin-x64
runner: macos-11
artifact: bun-obj-darwin-x64
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
dependencies: false
compile_obj: true
# - cpu: native
@@ -152,7 +152,7 @@ jobs:
# tag: bun-darwin-aarch64
# obj: bun-obj-darwin-aarch64
# artifact: bun-obj-darwin-aarch64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-arm64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-arm64-lto.tar.gz"
# runner: macos-arm64
# dependencies: true
# compile_obj: true
@@ -260,7 +260,7 @@ jobs:
# package: bun-darwin-x64
# runner: macos-11
# artifact: bun-obj-darwin-x64-baseline
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
- cpu: haswell
arch: x86_64
tag: bun-darwin-x64
@@ -268,14 +268,14 @@ jobs:
package: bun-darwin-x64
runner: macos-11
artifact: bun-obj-darwin-x64
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-amd64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-amd64-lto.tar.gz"
# - cpu: native
# arch: aarch64
# tag: bun-darwin-aarch64
# obj: bun-obj-darwin-aarch64
# package: bun-darwin-aarch64
# artifact: bun-obj-darwin-aarch64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-5/bun-webkit-macos-arm64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-6/bun-webkit-macos-arm64-lto.tar.gz"
# runner: macos-arm64
steps:
- uses: actions/checkout@v3
diff --git a/Dockerfile b/Dockerfile
index a8ded783d..c7fa8d523 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -10,7 +10,7 @@ ARG ARCH=x86_64
ARG BUILD_MACHINE_ARCH=x86_64
ARG TRIPLET=${ARCH}-linux-gnu
ARG BUILDARCH=amd64
-ARG WEBKIT_TAG=may20-5
+ARG WEBKIT_TAG=may20-6
ARG ZIG_TAG=jul1
ARG ZIG_VERSION="0.11.0-dev.4006+bf827d0b5"
ARG WEBKIT_BASENAME="bun-webkit-linux-$BUILDARCH"
diff --git a/bun.lockb b/bun.lockb
index aca2a9460..a2c13a922 100755
--- a/bun.lockb
+++ b/bun.lockb
Binary files differ
diff --git a/package.json b/package.json
index f8f511eb0..c6e47404f 100644
--- a/package.json
+++ b/package.json
@@ -25,7 +25,7 @@
"@types/ws": "^8.5.5",
"@typescript-eslint/eslint-plugin": "^5.31.0",
"@typescript-eslint/parser": "^5.31.0",
- "bun-webkit": "0.0.1-770ebc986b8ae9a0dd2e85f8f94646b410110b7f"
+ "bun-webkit": "0.0.1-1e5c61ef78b14e22278dd884e163a8a95e0529ea"
},
"version": "0.0.0",
"prettier": "./.prettierrc.cjs"
diff --git a/src/bun.js/WebKit b/src/bun.js/WebKit
-Subproject 5e65b9ae7756b6353cfeac5206f7076b00e9ecf
+Subproject ecf1b9c4bc2247020add7b14a732bb0085f25d5
diff --git a/src/bun.js/bindings/BunClientData.cpp b/src/bun.js/bindings/BunClientData.cpp
index 2cdd8b25a..9af17d638 100644
--- a/src/bun.js/bindings/BunClientData.cpp
+++ b/src/bun.js/bindings/BunClientData.cpp
@@ -21,6 +21,7 @@
#include "JavaScriptCore/JSCInlines.h"
#include "JSDOMWrapper.h"
+#include <JavaScriptCore/DeferredWorkTimer.h>
namespace WebCore {
using namespace JSC;
@@ -69,9 +70,14 @@ JSVMClientData::~JSVMClientData()
ASSERT(m_normalWorld->hasOneRef());
m_normalWorld = nullptr;
}
-void JSVMClientData::create(VM* vm)
+void JSVMClientData::create(VM* vm, void* bunVM)
{
JSVMClientData* clientData = new JSVMClientData(*vm);
+ clientData->bunVM = bunVM;
+ vm->deferredWorkTimer->onAddPendingWork = Bun::JSCTaskScheduler::onAddPendingWork;
+ vm->deferredWorkTimer->onScheduleWorkSoon = Bun::JSCTaskScheduler::onScheduleWorkSoon;
+ vm->deferredWorkTimer->onCancelPendingWork = Bun::JSCTaskScheduler::onCancelPendingWork;
+
vm->clientData = clientData; // ~VM deletes this pointer.
clientData->m_normalWorld = DOMWrapperWorld::create(*vm, DOMWrapperWorld::Type::Normal);
diff --git a/src/bun.js/bindings/BunClientData.h b/src/bun.js/bindings/BunClientData.h
index e3c2d3748..0bee575df 100644
--- a/src/bun.js/bindings/BunClientData.h
+++ b/src/bun.js/bindings/BunClientData.h
@@ -24,6 +24,7 @@ class DOMWrapperWorld;
#include "JavaScriptCore/IsoSubspacePerVM.h"
#include "wtf/StdLibExtras.h"
#include "WebCoreJSBuiltins.h"
+#include "JSCTaskScheduler.h"
namespace Zig {
}
@@ -80,7 +81,7 @@ public:
virtual ~JSVMClientData();
- static void create(JSC::VM*);
+ static void create(JSC::VM*, void*);
JSHeapData& heapData() { return *m_heapData; }
BunBuiltinNames& builtinNames() { return m_builtinNames; }
@@ -107,6 +108,9 @@ public:
func(*space);
}
+ void* bunVM;
+ Bun::JSCTaskScheduler deferredWorkTimer;
+
private:
BunBuiltinNames m_builtinNames;
JSBuiltinFunctions m_builtinFunctions;
diff --git a/src/bun.js/bindings/JSCTaskScheduler.cpp b/src/bun.js/bindings/JSCTaskScheduler.cpp
new file mode 100644
index 000000000..436be4c0a
--- /dev/null
+++ b/src/bun.js/bindings/JSCTaskScheduler.cpp
@@ -0,0 +1,101 @@
+#include "config.h"
+#include <JavaScriptCore/VM.h>
+#include "JSCTaskScheduler.h"
+#include "BunClientData.h"
+
+using Ticket = JSC::DeferredWorkTimer::Ticket;
+using Task = JSC::DeferredWorkTimer::Task;
+using TicketData = JSC::DeferredWorkTimer::TicketData;
+
+namespace Bun {
+using namespace JSC;
+
+extern "C" void Bun__queueJSCDeferredWorkTaskConcurrently(void* bunVM, void* task);
+extern "C" void Bun__eventLoop__incrementRefConcurrently(void* bunVM, int delta);
+
+class JSCDeferredWorkTask {
+public:
+ JSCDeferredWorkTask(Ticket ticket, Task&& task)
+ : ticket(ticket)
+ , task(WTFMove(task))
+ {
+ }
+
+ Ticket ticket;
+ Task task;
+
+ WTF_MAKE_FAST_ALLOCATED;
+};
+
+static JSC::VM& getVM(Ticket ticket)
+{
+ return ticket->scriptExecutionOwner.get()->vm();
+}
+
+void JSCTaskScheduler::onAddPendingWork(std::unique_ptr<TicketData> ticket, JSC::DeferredWorkTimer::WorkKind kind)
+{
+ JSC::VM& vm = getVM(ticket.get());
+ auto clientData = WebCore::clientData(vm);
+ auto& scheduler = clientData->deferredWorkTimer;
+ LockHolder holder { scheduler.m_lock };
+ if (kind != DeferredWorkTimer::WorkKind::Other) {
+
+ Bun__eventLoop__incrementRefConcurrently(clientData->bunVM, 1);
+ scheduler.m_pendingTicketsKeepingEventLoopAlive.add(WTFMove(ticket));
+ } else {
+ scheduler.m_pendingTicketsOther.add(WTFMove(ticket));
+ }
+}
+void JSCTaskScheduler::onScheduleWorkSoon(Ticket ticket, Task&& task)
+{
+ auto* job = new JSCDeferredWorkTask(ticket, WTFMove(task));
+ Bun__queueJSCDeferredWorkTaskConcurrently(WebCore::clientData(getVM(ticket))->bunVM, job);
+}
+
+void JSCTaskScheduler::onCancelPendingWork(Ticket ticket)
+{
+ auto& scheduler = WebCore::clientData(getVM(ticket))->deferredWorkTimer;
+
+ LockHolder holder { scheduler.m_lock };
+ bool isKeepingEventLoopAlive = scheduler.m_pendingTicketsKeepingEventLoopAlive.removeIf([ticket](const auto& pendingTicket) {
+ return pendingTicket.get() == ticket;
+ });
+
+ if (isKeepingEventLoopAlive) {
+ holder.unlockEarly();
+ JSC::VM& vm = getVM(ticket);
+ Bun__eventLoop__incrementRefConcurrently(WebCore::clientData(vm)->bunVM, -1);
+ } else {
+ scheduler.m_pendingTicketsOther.removeIf([ticket](const auto& pendingTicket) {
+ return pendingTicket.get() == ticket;
+ });
+ }
+}
+
+static void runPendingWork(void* bunVM, Bun::JSCTaskScheduler& scheduler, JSCDeferredWorkTask* job)
+{
+ LockHolder holder { scheduler.m_lock };
+ auto pendingTicket = scheduler.m_pendingTicketsKeepingEventLoopAlive.take(job->ticket);
+ if (!pendingTicket) {
+ pendingTicket = scheduler.m_pendingTicketsOther.take(job->ticket);
+ } else {
+ Bun__eventLoop__incrementRefConcurrently(bunVM, -1);
+ }
+ holder.unlockEarly();
+
+ if (pendingTicket && !pendingTicket->isCancelled()) {
+ job->task(job->ticket);
+ }
+
+ delete job;
+}
+
+extern "C" void Bun__runDeferredWork(Bun::JSCDeferredWorkTask* job)
+{
+ auto& vm = getVM(job->ticket);
+ auto clientData = WebCore::clientData(vm);
+
+ runPendingWork(clientData->bunVM, clientData->deferredWorkTimer, job);
+}
+
+}
diff --git a/src/bun.js/bindings/JSCTaskScheduler.h b/src/bun.js/bindings/JSCTaskScheduler.h
new file mode 100644
index 000000000..3257eb9c8
--- /dev/null
+++ b/src/bun.js/bindings/JSCTaskScheduler.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <JavaScriptCore/DeferredWorkTimer.h>
+
+namespace Bun {
+
+class JSCTaskScheduler {
+public:
+ JSCTaskScheduler()
+ : m_pendingTicketsKeepingEventLoopAlive()
+ , m_pendingTicketsOther()
+ {
+ }
+
+ static void onAddPendingWork(std::unique_ptr<JSC::DeferredWorkTimer::TicketData> ticket, JSC::DeferredWorkTimer::WorkKind kind);
+ static void onScheduleWorkSoon(JSC::DeferredWorkTimer::Ticket ticket, JSC::DeferredWorkTimer::Task&& task);
+ static void onCancelPendingWork(JSC::DeferredWorkTimer::Ticket ticket);
+
+public:
+ Lock m_lock;
+ HashSet<std::unique_ptr<JSC::DeferredWorkTimer::TicketData>> m_pendingTicketsKeepingEventLoopAlive;
+ HashSet<std::unique_ptr<JSC::DeferredWorkTimer::TicketData>> m_pendingTicketsOther;
+};
+
+} \ No newline at end of file
diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp
index f267fcbb7..52f633f3d 100644
--- a/src/bun.js/bindings/ZigGlobalObject.cpp
+++ b/src/bun.js/bindings/ZigGlobalObject.cpp
@@ -431,7 +431,7 @@ extern "C" JSC__JSGlobalObject* Zig__GlobalObject__create(JSClassRef* globalObje
// This must happen before JSVMClientData::create
vm.heap.acquireAccess();
- WebCore::JSVMClientData::create(&vm);
+ WebCore::JSVMClientData::create(&vm, Bun__getVM());
JSC::JSLockHolder locker(vm);
Zig::GlobalObject* globalObject;
diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp
index 55f718207..9fb0c18d5 100644
--- a/src/bun.js/bindings/bindings.cpp
+++ b/src/bun.js/bindings/bindings.cpp
@@ -9,7 +9,6 @@
#include "JavaScriptCore/BytecodeIndex.h"
#include "JavaScriptCore/CodeBlock.h"
#include "JavaScriptCore/Completion.h"
-#include "JavaScriptCore/DeferredWorkTimer.h"
#include "JavaScriptCore/ErrorInstance.h"
#include "JavaScriptCore/ExceptionHelpers.h"
#include "JavaScriptCore/ExceptionScope.h"
@@ -3893,11 +3892,6 @@ void JSC__VM__deleteAllCode(JSC__VM* arg1, JSC__JSGlobalObject* globalObject)
arg1->heap.reportAbandonedObjectGraph();
}
-void JSC__VM__doWork(JSC__VM* vm)
-{
- vm->deferredWorkTimer->doWork(*vm);
-}
-
void JSC__VM__deinit(JSC__VM* arg1, JSC__JSGlobalObject* globalObject) {}
void JSC__VM__drainMicrotasks(JSC__VM* arg0) { arg0->drainMicrotasks(); }
diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig
index edd1be1a9..924eb27a1 100644
--- a/src/bun.js/bindings/bindings.zig
+++ b/src/bun.js/bindings/bindings.zig
@@ -5083,14 +5083,6 @@ pub const VM = extern struct {
});
}
- pub fn doWork(
- vm: *VM,
- ) void {
- return cppFn("doWork", .{
- vm,
- });
- }
-
pub fn externalMemorySize(vm: *VM) usize {
return cppFn("externalMemorySize", .{vm});
}
@@ -5101,7 +5093,7 @@ pub const VM = extern struct {
return cppFn("blockBytesAllocated", .{vm});
}
- pub const Extern = [_][]const u8{ "collectAsync", "externalMemorySize", "blockBytesAllocated", "heapSize", "releaseWeakRefs", "throwError", "doWork", "deferGC", "holdAPILock", "runGC", "generateHeapSnapshot", "isJITEnabled", "deleteAllCode", "create", "deinit", "setExecutionForbidden", "executionForbidden", "isEntered", "throwError", "drainMicrotasks", "whenIdle", "shrinkFootprint", "setExecutionTimeLimit", "clearExecutionTimeLimit" };
+ pub const Extern = [_][]const u8{ "collectAsync", "externalMemorySize", "blockBytesAllocated", "heapSize", "releaseWeakRefs", "throwError", "deferGC", "holdAPILock", "runGC", "generateHeapSnapshot", "isJITEnabled", "deleteAllCode", "create", "deinit", "setExecutionForbidden", "executionForbidden", "isEntered", "throwError", "drainMicrotasks", "whenIdle", "shrinkFootprint", "setExecutionTimeLimit", "clearExecutionTimeLimit" };
};
pub const ThrowScope = extern struct {
diff --git a/src/bun.js/bindings/headers.h b/src/bun.js/bindings/headers.h
index 8cce986dc..05c708a48 100644
--- a/src/bun.js/bindings/headers.h
+++ b/src/bun.js/bindings/headers.h
@@ -419,7 +419,6 @@ CPP_DECL JSC__VM* JSC__VM__create(unsigned char HeapType0);
CPP_DECL void JSC__VM__deferGC(JSC__VM* arg0, void* arg1, void(* ArgFn2)(void* arg0)) __attribute__((nonnull (2)));
CPP_DECL void JSC__VM__deinit(JSC__VM* arg0, JSC__JSGlobalObject* arg1);
CPP_DECL void JSC__VM__deleteAllCode(JSC__VM* arg0, JSC__JSGlobalObject* arg1);
-CPP_DECL void JSC__VM__doWork(JSC__VM* arg0);
CPP_DECL void JSC__VM__drainMicrotasks(JSC__VM* arg0);
CPP_DECL bool JSC__VM__executionForbidden(JSC__VM* arg0);
CPP_DECL size_t JSC__VM__externalMemorySize(JSC__VM* arg0);
diff --git a/src/bun.js/bindings/headers.zig b/src/bun.js/bindings/headers.zig
index e87e59946..fbca33a30 100644
--- a/src/bun.js/bindings/headers.zig
+++ b/src/bun.js/bindings/headers.zig
@@ -313,7 +313,6 @@ pub extern fn JSC__VM__create(HeapType0: u8) *bindings.VM;
pub extern fn JSC__VM__deferGC(arg0: *bindings.VM, arg1: ?*anyopaque, ArgFn2: ?*const fn (?*anyopaque) callconv(.C) void) void;
pub extern fn JSC__VM__deinit(arg0: *bindings.VM, arg1: *bindings.JSGlobalObject) void;
pub extern fn JSC__VM__deleteAllCode(arg0: *bindings.VM, arg1: *bindings.JSGlobalObject) void;
-pub extern fn JSC__VM__doWork(arg0: *bindings.VM) void;
pub extern fn JSC__VM__drainMicrotasks(arg0: *bindings.VM) void;
pub extern fn JSC__VM__executionForbidden(arg0: *bindings.VM) bool;
pub extern fn JSC__VM__externalMemorySize(arg0: *bindings.VM) usize;
diff --git a/src/bun.js/event_loop.zig b/src/bun.js/event_loop.zig
index 2dbe88d47..6688eaeea 100644
--- a/src/bun.js/event_loop.zig
+++ b/src/bun.js/event_loop.zig
@@ -73,7 +73,7 @@ pub fn ConcurrentPromiseTask(comptime Context: type) type {
}
pub fn onFinish(this: *This) void {
- this.event_loop.enqueueTaskConcurrent(this.concurrent_task.from(this));
+ this.event_loop.enqueueTaskConcurrent(this.concurrent_task.from(this, .manual_deinit));
}
pub fn deinit(this: *This) void {
@@ -136,7 +136,7 @@ pub fn WorkTask(comptime Context: type, comptime async_io: bool) type {
}
pub fn onFinish(this: *This) void {
- this.event_loop.enqueueTaskConcurrent(this.concurrent_task.from(this));
+ this.event_loop.enqueueTaskConcurrent(this.concurrent_task.from(this, .manual_deinit));
}
pub fn deinit(this: *This) void {
@@ -221,6 +221,35 @@ pub const CppTask = opaque {
Bun__performTask(global, this);
}
};
+pub const JSCScheduler = struct {
+ pub const JSCDeferredWorkTask = opaque {
+ extern fn Bun__runDeferredWork(task: *JSCScheduler.JSCDeferredWorkTask) void;
+ pub const run = Bun__runDeferredWork;
+ };
+
+ export fn Bun__eventLoop__incrementRefConcurrently(jsc_vm: *VirtualMachine, delta: c_int) void {
+ JSC.markBinding(@src());
+
+ if (delta > 0) {
+ jsc_vm.uws_event_loop.?.refConcurrently();
+ } else {
+ jsc_vm.uws_event_loop.?.unrefConcurrently();
+ }
+ }
+
+ export fn Bun__queueJSCDeferredWorkTaskConcurrently(jsc_vm: *VirtualMachine, task: *JSCScheduler.JSCDeferredWorkTask) void {
+ JSC.markBinding(@src());
+ var loop = jsc_vm.eventLoop();
+ var concurrent_task = bun.default_allocator.create(ConcurrentTask) catch @panic("out of memory!");
+ loop.enqueueTaskConcurrent(concurrent_task.from(task, .auto_deinit));
+ }
+
+ comptime {
+ _ = Bun__eventLoop__incrementRefConcurrently;
+ _ = Bun__queueJSCDeferredWorkTaskConcurrently;
+ }
+};
+
const ThreadSafeFunction = JSC.napi.ThreadSafeFunction;
const MicrotaskForDefaultGlobalObject = JSC.MicrotaskForDefaultGlobalObject;
const HotReloadTask = JSC.HotReloader.HotReloadTask;
@@ -228,6 +257,7 @@ const FSWatchTask = JSC.Node.FSWatcher.FSWatchTask;
const PollPendingModulesTask = JSC.ModuleLoader.AsyncModule.Queue;
// const PromiseTask = JSInternalPromise.Completion.PromiseTask;
const GetAddrInfoRequestTask = JSC.DNS.GetAddrInfoRequest.Task;
+const JSCDeferredWorkTask = JSCScheduler.JSCDeferredWorkTask;
pub const Task = TaggedPointerUnion(.{
FetchTasklet,
Microtask,
@@ -244,6 +274,8 @@ pub const Task = TaggedPointerUnion(.{
PollPendingModulesTask,
GetAddrInfoRequestTask,
FSWatchTask,
+ JSCDeferredWorkTask,
+
// PromiseTask,
// TimeoutTasklet,
});
@@ -255,10 +287,15 @@ pub const ConcurrentTask = struct {
pub const Queue = UnboundedQueue(ConcurrentTask, .next);
- pub fn from(this: *ConcurrentTask, of: anytype) *ConcurrentTask {
+ pub const AutoDeinit = enum {
+ manual_deinit,
+ auto_deinit,
+ };
+ pub fn from(this: *ConcurrentTask, of: anytype, auto_deinit: AutoDeinit) *ConcurrentTask {
this.* = .{
.task = Task.init(of),
.next = null,
+ .auto_delete = auto_deinit == .auto_deinit,
};
return this;
}
@@ -457,6 +494,11 @@ pub const EventLoop = struct {
transform_task.*.runFromJS();
transform_task.deinit();
},
+ @field(Task.Tag, bun.meta.typeBaseName(@typeName(JSCDeferredWorkTask))) => {
+ var jsc_task: *JSCDeferredWorkTask = task.get(JSCDeferredWorkTask).?;
+ JSC.markBinding(@src());
+ jsc_task.run();
+ },
@field(Task.Tag, @typeName(WriteFileTask)) => {
var transform_task: *WriteFileTask = task.get(WriteFileTask).?;
transform_task.*.runFromJS();
@@ -627,10 +669,6 @@ pub const EventLoop = struct {
break;
}
- // TODO: unify the event loops
- // This needs a hook into JSC to schedule timers
- this.global.vm().doWork();
-
while (this.tickWithCount() > 0) {
this.tickConcurrent();
}
diff --git a/src/bun.js/web_worker.zig b/src/bun.js/web_worker.zig
index 504b0adeb..130e99be1 100644
--- a/src/bun.js/web_worker.zig
+++ b/src/bun.js/web_worker.zig
@@ -141,7 +141,7 @@ pub const WebWorker = struct {
var any_task = bun.default_allocator.create(JSC.AnyTask) catch @panic("OOM");
any_task.* = AnyTask.init(this);
var concurrent_task = bun.default_allocator.create(JSC.ConcurrentTask) catch @panic("OOM");
- this.parent.eventLoop().enqueueTaskConcurrent(concurrent_task.from(any_task));
+ this.parent.eventLoop().enqueueTaskConcurrent(concurrent_task.from(any_task, .auto_deinit));
}
pub fn startWithErrorHandling(
@@ -413,7 +413,7 @@ pub const WebWorker = struct {
var concurrent_task = bun.default_allocator.create(JSC.ConcurrentTask) catch @panic("OOM");
var task = bun.default_allocator.create(JSC.AnyTask) catch @panic("OOM");
task.* = JSC.AnyTask.New(WebWorker, onTerminate).init(this);
- vm.eventLoop().enqueueTaskConcurrent(concurrent_task.from(task));
+ vm.eventLoop().enqueueTaskConcurrent(concurrent_task.from(task, .auto_deinit));
return true;
}
};
diff --git a/src/bun.js/webcore/response.zig b/src/bun.js/webcore/response.zig
index ab2a6010d..a70a4f0ee 100644
--- a/src/bun.js/webcore/response.zig
+++ b/src/bun.js/webcore/response.zig
@@ -979,7 +979,7 @@ pub const Fetch = struct {
pub fn callback(task: *FetchTasklet, result: HTTPClient.HTTPClientResult) void {
task.response_buffer = result.body.?.*;
task.result = result;
- task.javascript_vm.eventLoop().enqueueTaskConcurrent(task.concurrent_task.from(task));
+ task.javascript_vm.eventLoop().enqueueTaskConcurrent(task.concurrent_task.from(task, .manual_deinit));
}
};
diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig
index 03b1dcdc9..5dc4ea830 100644
--- a/src/bun.js/webcore/streams.zig
+++ b/src/bun.js/webcore/streams.zig
@@ -4168,7 +4168,7 @@ pub const File = struct {
pub fn scheduleMainThreadTask(this: *File) void {
this.concurrent.main_thread_task.ctx = this;
- this.loop.enqueueTaskConcurrent(this.concurrent.concurrent_task.from(&this.concurrent.main_thread_task));
+ this.loop.enqueueTaskConcurrent(this.concurrent.concurrent_task.from(&this.concurrent.main_thread_task, .manual_deinit));
}
fn runAsync(this: *File) void {
diff --git a/src/cli/test_command.zig b/src/cli/test_command.zig
index f53c8121c..14eca012e 100644
--- a/src/cli/test_command.zig
+++ b/src/cli/test_command.zig
@@ -806,7 +806,6 @@ pub const TestCommand = struct {
vm.global.vm().drainMicrotasks();
vm.global.handleRejectedPromises();
}
- vm.global.vm().doWork();
}
const file_end = reporter.jest.files.len;
diff --git a/src/deps/uws.zig b/src/deps/uws.zig
index 6e9d43e5f..15e6eaa68 100644
--- a/src/deps/uws.zig
+++ b/src/deps/uws.zig
@@ -760,6 +760,18 @@ pub const Loop = extern struct {
this.num_polls += 1;
this.active += 1;
}
+ pub fn refConcurrently(this: *Loop) void {
+ log("ref", .{});
+ _ = @atomicRmw(@TypeOf(this.num_polls), &this.num_polls, .Add, 1, .Monotonic);
+ _ = @atomicRmw(@TypeOf(this.active), &this.active, .Add, 1, .Monotonic);
+ }
+
+ pub fn unrefConcurrently(this: *Loop) void {
+ log("unref", .{});
+ _ = @atomicRmw(@TypeOf(this.num_polls), &this.num_polls, .Sub, 1, .Monotonic);
+ _ = @atomicRmw(@TypeOf(this.active), &this.active, .Sub, 1, .Monotonic);
+ }
+
pub fn unref(this: *Loop) void {
log("unref", .{});
this.num_polls -= 1;
diff --git a/src/js/bun/wasi-runner.js b/src/js/bun/wasi-runner.js
index a292c6380..9f7b469e1 100644
--- a/src/js/bun/wasi-runner.js
+++ b/src/js/bun/wasi-runner.js
@@ -11,7 +11,12 @@ if (!filePath) {
// The module specifier is the resolved path to the wasm file
-var { WASM_CWD = process.cwd(), WASM_ROOT_DIR = "/", WASM_ENV_STR = undefined, WASM_USE_ASYNC_INIT = "" } = process.env;
+var {
+ WASM_CWD = process.cwd(),
+ WASM_ROOT_DIR = "/",
+ WASM_ENV_STR = undefined,
+ WASM_USE_ASYNC_INIT = "1",
+} = process.env;
var env = process.env;
if (WASM_ENV_STR?.length) {
@@ -34,10 +39,12 @@ if (!source) {
source = fs.readFileSync(file);
}
-const wasm = new WebAssembly.Module(source);
-const instance = !WASM_USE_ASYNC_INIT
+const wasm = await WebAssembly.compile(source);
+
+const instance = !Number(WASM_USE_ASYNC_INIT)
? new WebAssembly.Instance(wasm, wasi.getImports(wasm))
: await WebAssembly.instantiate(wasm, wasi.getImports(wasm));
+
wasi.start(instance);
-process.exit(0);
+process.reallyExit(0);
diff --git a/src/js/out/modules/bun/wasi-runner.js b/src/js/out/modules/bun/wasi-runner.js
index 9dfd27b23..47c5ade3c 100644
--- a/src/js/out/modules/bun/wasi-runner.js
+++ b/src/js/out/modules/bun/wasi-runner.js
@@ -1,7 +1,12 @@
var filePath = process.argv.at(1);
if (!filePath)
throw err = new Error("To run a wasm file with Bun, the first argument must be a path to a .wasm file"), err.name = "WasmFileNotFound", err;
-var err, { WASM_CWD = process.cwd(), WASM_ROOT_DIR = "/", WASM_ENV_STR = void 0, WASM_USE_ASYNC_INIT = "" } = process.env, env = process.env;
+var err, {
+ WASM_CWD = process.cwd(),
+ WASM_ROOT_DIR = "/",
+ WASM_ENV_STR = void 0,
+ WASM_USE_ASYNC_INIT = "1"
+} = process.env, env = process.env;
if (WASM_ENV_STR?.length)
env = JSON.parse(WASM_ENV_STR);
var wasi = new WASI({
@@ -16,6 +21,6 @@ if (!source) {
const fs = Bun.fs(), file = import.meta.path;
source = fs.readFileSync(file);
}
-var wasm = new WebAssembly.Module(source), instance = !WASM_USE_ASYNC_INIT ? new WebAssembly.Instance(wasm, wasi.getImports(wasm)) : await WebAssembly.instantiate(wasm, wasi.getImports(wasm));
+var wasm = await WebAssembly.compile(source), instance = !Number(WASM_USE_ASYNC_INIT) ? new WebAssembly.Instance(wasm, wasi.getImports(wasm)) : await WebAssembly.instantiate(wasm, wasi.getImports(wasm));
wasi.start(instance);
-process.exit(0);
+process.reallyExit(0);
diff --git a/src/napi/napi.zig b/src/napi/napi.zig
index bb8f19df2..abe8316ad 100644
--- a/src/napi/napi.zig
+++ b/src/napi/napi.zig
@@ -962,7 +962,7 @@ pub const napi_async_work = struct {
this.execute.?(this.global, this.ctx);
this.status.store(@intFromEnum(Status.completed), .SeqCst);
- this.event_loop.enqueueTaskConcurrent(this.concurrent_task.from(this));
+ this.event_loop.enqueueTaskConcurrent(this.concurrent_task.from(this, .manual_deinit));
}
pub fn schedule(this: *napi_async_work) void {
@@ -1338,7 +1338,7 @@ pub const ThreadSafeFunction = struct {
}
}
- this.event_loop.enqueueTaskConcurrent(this.concurrent_task.from(this));
+ this.event_loop.enqueueTaskConcurrent(this.concurrent_task.from(this, .manual_deinit));
}
pub fn finalize(opaq: *anyopaque) void {
@@ -1387,7 +1387,7 @@ pub const ThreadSafeFunction = struct {
if (this.owning_threads.count() == 0) {
this.finalizer_task = JSC.AnyTask{ .ctx = this, .callback = finalize };
- this.event_loop.enqueueTaskConcurrent(this.concurrent_finalizer_task.from(&this.finalizer_task));
+ this.event_loop.enqueueTaskConcurrent(this.concurrent_finalizer_task.from(&this.finalizer_task, .manual_deinit));
return;
}
}
diff --git a/src/tagged_pointer.zig b/src/tagged_pointer.zig
index 6c2462139..b5555a8b4 100644
--- a/src/tagged_pointer.zig
+++ b/src/tagged_pointer.zig
@@ -159,6 +159,10 @@ pub fn TaggedPointerUnion(comptime Types: anytype) type {
pub inline fn init(_ptr: anytype) This {
const Type = std.meta.Child(@TypeOf(_ptr));
+ return initWithType(Type, _ptr);
+ }
+
+ pub inline fn initWithType(comptime Type: type, _ptr: anytype) This {
const name = comptime typeBaseName(@typeName(Type));
// there will be a compiler error if the passed in type doesn't exist in the enum
diff --git a/test/bun.lockb b/test/bun.lockb
index 7caf819fd..f6b48c1bb 100755
--- a/test/bun.lockb
+++ b/test/bun.lockb
Binary files differ
diff --git a/test/js/third_party/es-module-lexer/.gitignore b/test/js/third_party/es-module-lexer/.gitignore
new file mode 100644
index 000000000..f81d56eaa
--- /dev/null
+++ b/test/js/third_party/es-module-lexer/.gitignore
@@ -0,0 +1,169 @@
+# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
+
+# Logs
+
+logs
+_.log
+npm-debug.log_
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+.pnpm-debug.log*
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+
+report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
+
+# Runtime data
+
+pids
+_.pid
+_.seed
+\*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+
+lib-cov
+
+# Coverage directory used by tools like istanbul
+
+coverage
+\*.lcov
+
+# nyc test coverage
+
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+
+bower_components
+
+# node-waf configuration
+
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+
+build/Release
+
+# Dependency directories
+
+node_modules/
+jspm_packages/
+
+# Snowpack dependency directory (https://snowpack.dev/)
+
+web_modules/
+
+# TypeScript cache
+
+\*.tsbuildinfo
+
+# Optional npm cache directory
+
+.npm
+
+# Optional eslint cache
+
+.eslintcache
+
+# Optional stylelint cache
+
+.stylelintcache
+
+# Microbundle cache
+
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+
+.node_repl_history
+
+# Output of 'npm pack'
+
+\*.tgz
+
+# Yarn Integrity file
+
+.yarn-integrity
+
+# dotenv environment variable files
+
+.env
+.env.development.local
+.env.test.local
+.env.production.local
+.env.local
+
+# parcel-bundler cache (https://parceljs.org/)
+
+.cache
+.parcel-cache
+
+# Next.js build output
+
+.next
+out
+
+# Nuxt.js build / generate output
+
+.nuxt
+dist
+
+# Gatsby files
+
+.cache/
+
+# Comment in the public line in if your project uses Gatsby and not Next.js
+
+# https://nextjs.org/blog/next-9-1#public-directory-support
+
+# public
+
+# vuepress build output
+
+.vuepress/dist
+
+# vuepress v2.x temp and cache directory
+
+.temp
+.cache
+
+# Docusaurus cache and generated files
+
+.docusaurus
+
+# Serverless directories
+
+.serverless/
+
+# FuseBox cache
+
+.fusebox/
+
+# DynamoDB Local files
+
+.dynamodb/
+
+# TernJS port file
+
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+
+.vscode-test
+
+# yarn v2
+
+.yarn/cache
+.yarn/unplugged
+.yarn/build-state.yml
+.yarn/install-state.gz
+.pnp.\*
diff --git a/test/js/third_party/es-module-lexer/README.md b/test/js/third_party/es-module-lexer/README.md
new file mode 100644
index 000000000..c3575ac85
--- /dev/null
+++ b/test/js/third_party/es-module-lexer/README.md
@@ -0,0 +1,14 @@
+## es-module-lexer test
+
+The purpose of this test is to check that event loop tasks scheduled from
+JavaScriptCore (rather than Bun) keep the process alive.
+
+The problem used to be that Bun may close prematurely when async work was
+scheduled by JavaScriptCore (rather than IO work).
+
+At the time of writing, that list is:
+
+- WebAssembly compilation
+- Atomics
+
+FinalizationRegistry is also scheduled by JSC, but that doesn't need to keep the process alive.
diff --git a/test/js/third_party/es-module-lexer/es-module-lexer.test.ts b/test/js/third_party/es-module-lexer/es-module-lexer.test.ts
new file mode 100644
index 000000000..2202a61a6
--- /dev/null
+++ b/test/js/third_party/es-module-lexer/es-module-lexer.test.ts
@@ -0,0 +1,45 @@
+import { test, expect } from "bun:test";
+import { spawnSync } from "bun";
+import { bunEnv, bunExe } from "../../../harness";
+import { join } from "path";
+
+// The purpose of this test is to check that event loop tasks scheduled from
+// JavaScriptCore (rather than Bun) keep the process alive.
+//
+// The problem used to be that Bun would close prematurely when async work was
+// scheduled by JavaScriptCore.
+//
+// At the time of writing, this includes WebAssembly compilation and Atomics
+// It excludes FinalizationRegistry since that doesn't need to keep the process alive.
+test("es-module-lexer consistently loads", () => {
+ for (let i = 0; i < 10; i++) {
+ const { stdout, exitCode } = spawnSync({
+ cmd: [bunExe(), join(import.meta.dir, "index.ts")],
+ env: bunEnv,
+ });
+ expect(JSON.parse(stdout?.toString())).toEqual({
+ imports: [
+ {
+ n: "b",
+ s: 19,
+ e: 20,
+ ss: 0,
+ se: 21,
+ d: -1,
+ a: -1,
+ },
+ ],
+ exports: [
+ {
+ s: 36,
+ e: 37,
+ ls: 36,
+ le: 37,
+ n: "c",
+ ln: "c",
+ },
+ ],
+ });
+ expect(exitCode).toBe(42);
+ }
+});
diff --git a/test/js/third_party/es-module-lexer/index.ts b/test/js/third_party/es-module-lexer/index.ts
new file mode 100644
index 000000000..f11a849bc
--- /dev/null
+++ b/test/js/third_party/es-module-lexer/index.ts
@@ -0,0 +1,13 @@
+async function main() {
+ const { init, parse } = require("es-module-lexer");
+ await init;
+ const [imports, exports] = parse("import { a } from 'b'; export const c = 1;");
+ console.write(JSON.stringify({ imports, exports }));
+ process.exit(42);
+}
+
+exports.forceCommonJS = true;
+
+if (require.main === module) {
+ main();
+}
diff --git a/test/js/third_party/es-module-lexer/package.json b/test/js/third_party/es-module-lexer/package.json
new file mode 100644
index 000000000..4d2194ec2
--- /dev/null
+++ b/test/js/third_party/es-module-lexer/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "es-module-lexer-test",
+ "module": "index.ts",
+ "type": "module",
+ "devDependencies": {
+ "bun-types": "latest"
+ },
+ "dependencies": {
+ "es-module-lexer": "1.3.0"
+ }
+}
diff --git a/test/js/third_party/es-module-lexer/tsconfig.json b/test/js/third_party/es-module-lexer/tsconfig.json
new file mode 100644
index 000000000..29f8aa003
--- /dev/null
+++ b/test/js/third_party/es-module-lexer/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "compilerOptions": {
+ "lib": ["ESNext"],
+ "module": "esnext",
+ "target": "esnext",
+ "moduleResolution": "bundler",
+ "moduleDetection": "force",
+ "allowImportingTsExtensions": true,
+ "strict": true,
+ "downlevelIteration": true,
+ "skipLibCheck": true,
+ "jsx": "preserve",
+ "allowSyntheticDefaultImports": true,
+ "forceConsistentCasingInFileNames": true,
+ "allowJs": true,
+ "noEmit": true,
+ "types": [
+ "bun-types" // add Bun global
+ ]
+ }
+}
diff --git a/test/package.json b/test/package.json
index aeaa9d1d5..3ab8d5143 100644
--- a/test/package.json
+++ b/test/package.json
@@ -13,6 +13,7 @@
"body-parser": "1.20.2",
"comlink": "4.4.1",
"dedent": "0.7.0",
+ "es-module-lexer": "1.3.0",
"esbuild": "0.18.6",
"express": "4.18.2",
"iconv-lite": "0.6.3",