aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar dave caruso <me@paperdave.net> 2023-09-28 03:53:24 -0700
committerGravatar GitHub <noreply@github.com> 2023-09-28 03:53:24 -0700
commit387f1260c9dc0cea667b44ec0152fff0cd4def25 (patch)
tree24dde83cf812481b6d1c8de316a30ece7b745a54
parente60b3607c12c91959ec795228cc299703d5b09d0 (diff)
downloadbun-387f1260c9dc0cea667b44ec0152fff0cd4def25.tar.gz
bun-387f1260c9dc0cea667b44ec0152fff0cd4def25.tar.zst
bun-387f1260c9dc0cea667b44ec0152fff0cd4def25.zip
Get Next.js Pages Router to work (#6095)
* hell * make it so bun-debug-src * teag * wild * yippee * fas * fix async hooks assertions * yap * yeah that's wild * aa * a * increase time allowed * so trivial
-rw-r--r--packages/bun-types/bun.d.ts2
m---------src/bun.js/WebKit0
-rw-r--r--src/bun.js/bindings/CommonJSModuleRecord.cpp69
-rw-r--r--src/bun.js/bindings/CommonJSModuleRecord.h6
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.cpp34
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.lut.h107
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.lut.txt2
-rw-r--r--src/bun.js/module_loader.zig22
-rw-r--r--src/bun.js/modules/NodeModuleModule.h44
-rw-r--r--src/bundler.zig2
-rw-r--r--src/js/_codegen/builtin-parser.ts6
-rw-r--r--src/js/_codegen/client-js.ts12
-rw-r--r--src/js/_codegen/replacements.ts17
-rw-r--r--src/js/builtins.d.ts6
-rw-r--r--src/js/builtins/BunBuiltinNames.h7
-rw-r--r--src/js/builtins/Module.ts5
-rw-r--r--src/js/builtins/ProcessObjectInternals.ts3
-rw-r--r--src/js/node/async_hooks.ts117
-rw-r--r--src/js/node/tty.js16
-rw-r--r--src/js/out/InternalModuleRegistryConstants.h12
-rw-r--r--src/js/out/WebCoreJSBuiltins.cpp16
-rw-r--r--src/js/out/WebCoreJSBuiltins.h11
-rw-r--r--src/js_ast.zig1
-rw-r--r--src/js_parser.zig216
-rw-r--r--src/js_printer.zig16
-rw-r--r--src/string.zig22
-rw-r--r--test/.gitignore1
-rw-r--r--test/README.md83
-rwxr-xr-xtest/bun.lockbbin163311 -> 163310 bytes
-rw-r--r--test/integration/next/default-pages-dir/.eslintrc.json3
-rw-r--r--test/integration/next/default-pages-dir/.gitignore38
-rw-r--r--test/integration/next/default-pages-dir/README.md40
-rwxr-xr-xtest/integration/next/default-pages-dir/bun.lockbbin0 -> 167519 bytes
-rw-r--r--test/integration/next/default-pages-dir/next.config.js10
-rw-r--r--test/integration/next/default-pages-dir/package.json28
-rw-r--r--test/integration/next/default-pages-dir/postcss.config.js6
-rw-r--r--test/integration/next/default-pages-dir/public/favicon.icobin0 -> 25931 bytes
-rw-r--r--test/integration/next/default-pages-dir/public/next.svg1
-rw-r--r--test/integration/next/default-pages-dir/public/vercel.svg1
-rw-r--r--test/integration/next/default-pages-dir/src/Counter1.txt27
-rw-r--r--test/integration/next/default-pages-dir/src/Counter2.txt27
-rw-r--r--test/integration/next/default-pages-dir/src/pages/_app.tsx6
-rw-r--r--test/integration/next/default-pages-dir/src/pages/_document.tsx13
-rw-r--r--test/integration/next/default-pages-dir/src/pages/api/hello.ts10
-rw-r--r--test/integration/next/default-pages-dir/src/pages/index.tsx128
-rw-r--r--test/integration/next/default-pages-dir/src/styles/globals.css27
-rw-r--r--test/integration/next/default-pages-dir/tailwind.config.ts19
-rw-r--r--test/integration/next/default-pages-dir/test/dev-server-puppeteer.ts101
-rw-r--r--test/integration/next/default-pages-dir/test/dev-server.test.ts79
-rw-r--r--test/integration/next/default-pages-dir/test/next-build.test.ts141
-rw-r--r--test/integration/next/default-pages-dir/tsconfig.json22
-rw-r--r--test/integration/next/default-pages-dir/tsconfig_for_build.json23
-rw-r--r--test/js/node/async_hooks/async_hooks.node.test.ts28
-rw-r--r--test/js/node/module/modulePrototypeOverwrite-fixture.cjs1
-rw-r--r--test/js/node/module/modulePrototypeOverwrite.cjs17
-rw-r--r--test/js/node/module/node-module-module.test.js11
-rw-r--r--test/js/node/process/process-stdio.test.ts2
-rw-r--r--test/js/node/stream/node-stream.test.js12
-rwxr-xr-xtest/js/third_party/got/bun.lockbbin0 -> 9072 bytes
-rwxr-xr-xtest/js/third_party/prisma/bun.lockbbin0 -> 2951 bytes
-rwxr-xr-xtest/js/third_party/yargs/bun.lockbbin0 -> 6747 bytes
61 files changed, 1283 insertions, 393 deletions
diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts
index a74274667..bd8b75023 100644
--- a/packages/bun-types/bun.d.ts
+++ b/packages/bun-types/bun.d.ts
@@ -3827,7 +3827,7 @@ declare module "bun" {
: undefined;
type ReadableToSyncIO<X extends Readable> = X extends "pipe" | undefined
- ? Uint8Array
+ ? Buffer
: undefined;
type WritableIO = FileSink | number | undefined;
diff --git a/src/bun.js/WebKit b/src/bun.js/WebKit
-Subproject e1aa0a58e282b53fc20503d6e7ec93c621bc557
+Subproject 6ee85cc2dc431e146723885bc73ac14f33e0d82
diff --git a/src/bun.js/bindings/CommonJSModuleRecord.cpp b/src/bun.js/bindings/CommonJSModuleRecord.cpp
index eea3b2a6f..38b55ba4d 100644
--- a/src/bun.js/bindings/CommonJSModuleRecord.cpp
+++ b/src/bun.js/bindings/CommonJSModuleRecord.cpp
@@ -8,7 +8,7 @@
* Then, at runtime, we create a JSCommonJSModule object.
*
* On this special object, we override the setter for the "exports" property in
- * a non-observable way (`static bool put ...`)
+ * a non-observable way using a CustomGetterSetter.
*
* When the setter is called, we set the internal "exports" property to the
* value passed in and we also update the requireMap with the new value.
@@ -20,17 +20,13 @@
*
* If an exception occurs, we remove the entry from the requireMap.
*
- * We tried using a CustomGetterSetter instead of overriding `put`, but it led
- * to returning the getter itself
- *
- * How cyclical dependencies are handled
+ * How cyclical dependencies are handled:
*
* Before executing the CommonJS module, we set the exports object in the
* requireMap to an empty object. When the CommonJS module is required again, we
* return the exports object from the requireMap. The values should be in sync
* while the module is being executed, unless module.exports is re-assigned to a
* different value. In that case, it will have a stale value.
- *
*/
#include "root.h"
@@ -98,29 +94,35 @@ static bool canPerformFastEnumeration(Structure* s)
static bool evaluateCommonJSModuleOnce(JSC::VM& vm, Zig::GlobalObject* globalObject, JSCommonJSModule* moduleObject, JSString* dirname, JSValue filename, WTF::NakedPtr<Exception>& exception)
{
JSC::Structure* thisObjectStructure = globalObject->commonJSFunctionArgumentsStructure();
- JSC::JSObject* thisObject = JSC::constructEmptyObject(
- vm,
- thisObjectStructure);
- thisObject->putDirectOffset(
- vm,
- 0,
- moduleObject);
- thisObject->putDirectOffset(
- vm,
- 1,
- dirname);
+ JSFunction* resolveFunction = JSC::JSBoundFunction::create(vm,
+ globalObject,
+ globalObject->requireResolveFunctionUnbound(),
+ moduleObject->id(),
+ ArgList(), 1, jsString(vm, String("resolve"_s)));
+ JSFunction* requireFunction = JSC::JSBoundFunction::create(vm,
+ globalObject,
+ globalObject->requireFunctionUnbound(),
+ moduleObject,
+ ArgList(), 1, jsString(vm, String("require"_s)));
+ requireFunction->putDirect(vm, vm.propertyNames->resolve, resolveFunction, 0);
+ moduleObject->putDirect(vm, WebCore::clientData(vm)->builtinNames().requirePublicName(), requireFunction, 0);
- thisObject->putDirectOffset(
- vm,
- 2,
- filename);
+ JSC::JSObject* thisObject = JSC::constructEmptyObject(vm, thisObjectStructure);
+ thisObject->putDirectOffset(vm, 0, moduleObject);
+ thisObject->putDirectOffset(vm, 1, requireFunction);
+ thisObject->putDirectOffset(vm, 2, resolveFunction);
+ thisObject->putDirectOffset(vm, 3, dirname);
+ thisObject->putDirectOffset(vm, 4, filename);
moduleObject->hasEvaluated = true;
+ // TODO: try to not use this write barrier. it needs some extensive testing.
+ // there is some possible GC issue where `thisObject` is gc'd before it should be
globalObject->m_BunCommonJSModuleValue.set(vm, globalObject, thisObject);
JSValue empty = JSC::evaluate(globalObject, moduleObject->sourceCode.get()->sourceCode(), thisObject, exception);
+ ensureStillAliveHere(thisObject);
globalObject->m_BunCommonJSModuleValue.clear();
moduleObject->sourceCode.clear();
@@ -398,9 +400,9 @@ JSC_DEFINE_HOST_FUNCTION(functionCommonJSModuleRecord_compile, (JSGlobalObject *
RETURN_IF_EXCEPTION(throwScope, JSValue::encode({}));
String wrappedString = makeString(
- "(function(module,exports,require,__dirname,__filename){"_s,
+ "(function(exports,require,module,__filename,__dirname){"_s,
sourceString,
- "\n}).call($_BunCommonJSModule_$.module.exports, $_BunCommonJSModule_$.module, $_BunCommonJSModule_$.module.exports, ($_BunCommonJSModule_$.module.require = $_BunCommonJSModule_$.module.require.bind($_BunCommonJSModule_$.module), $_BunCommonJSModule_$.module.require.path = $_BunCommonJSModule_$.module.id, $_BunCommonJSModule_$.module.require.resolve = $_BunCommonJSModule_$.module.require.resolve.bind($_BunCommonJSModule_$.module.id), $_BunCommonJSModule_$.module.require), $_BunCommonJSModule_$.__dirname, $_BunCommonJSModule_$.__filename);"_s);
+ "\n}).call(this.module.exports,this.module.exports,this.require,this.module,this.__filename,this.__dirname)"_s);
SourceCode sourceCode = makeSource(
WTFMove(wrappedString),
@@ -483,14 +485,12 @@ public:
ASSERT(inherits(vm, info()));
reifyStaticProperties(vm, JSCommonJSModule::info(), JSCommonJSModulePrototypeTableValues, *this);
- this->putDirect(vm, clientData(vm)->builtinNames().requirePublicName(), (static_cast<Zig::GlobalObject*>(globalObject))->requireFunctionUnbound(), PropertyAttribute::Builtin | PropertyAttribute::Function | 0);
-
this->putDirectNativeFunction(
vm,
globalObject,
clientData(vm)->builtinNames().requirePrivateName(),
2,
- jsFunctionRequireCommonJS, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | 0);
+ jsFunctionRequireCommonJS, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete);
}
};
@@ -774,21 +774,6 @@ JSValue JSCommonJSModule::id()
return m_id.get();
}
-bool JSCommonJSModule::put(
- JSC::JSCell* cell,
- JSC::JSGlobalObject* globalObject,
- JSC::PropertyName propertyName,
- JSC::JSValue value,
- JSC::PutPropertySlot& slot)
-{
-
- auto& vm = globalObject->vm();
- auto* clientData = WebCore::clientData(vm);
- auto throwScope = DECLARE_THROW_SCOPE(vm);
-
- RELEASE_AND_RETURN(throwScope, Base::put(cell, globalObject, propertyName, value, slot));
-}
-
template<typename, SubspaceAccess mode> JSC::GCClient::IsoSubspace* JSCommonJSModule::subspaceFor(JSC::VM& vm)
{
if constexpr (mode == JSC::SubspaceAccess::Concurrently)
@@ -1022,7 +1007,7 @@ JSObject* JSCommonJSModule::createBoundRequireFunction(VM& vm, JSGlobalObject* l
globalObject,
globalObject->requireResolveFunctionUnbound(),
moduleObject,
- ArgList(), 1, jsString(vm, String("require"_s)));
+ ArgList(), 1, jsString(vm, String("resolve"_s)));
requireFunction->putDirect(vm, builtinNames.resolvePublicName(), resolveFunction, PropertyAttribute::Function | 0);
diff --git a/src/bun.js/bindings/CommonJSModuleRecord.h b/src/bun.js/bindings/CommonJSModuleRecord.h
index 14d045478..2f9ba648f 100644
--- a/src/bun.js/bindings/CommonJSModuleRecord.h
+++ b/src/bun.js/bindings/CommonJSModuleRecord.h
@@ -20,7 +20,7 @@ JSC_DECLARE_HOST_FUNCTION(jsFunctionLoadModule);
class JSCommonJSModule final : public JSC::JSDestructibleObject {
public:
using Base = JSC::JSDestructibleObject;
- static constexpr unsigned StructureFlags = Base::StructureFlags | JSC::OverridesPut;
+ static constexpr unsigned StructureFlags = Base::StructureFlags;
mutable JSC::WriteBarrier<JSString> m_id;
mutable JSC::WriteBarrier<Unknown> m_filename;
@@ -74,10 +74,6 @@ public:
DECLARE_VISIT_CHILDREN;
- static bool put(JSC::JSCell* cell, JSC::JSGlobalObject* globalObject,
- JSC::PropertyName propertyName, JSC::JSValue value,
- JSC::PutPropertySlot& slot);
-
DECLARE_INFO;
template<typename, SubspaceAccess mode>
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm);
diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp
index 54fb58776..7ffd75ccf 100644
--- a/src/bun.js/bindings/ZigGlobalObject.cpp
+++ b/src/bun.js/bindings/ZigGlobalObject.cpp
@@ -1948,6 +1948,11 @@ JSC_DECLARE_HOST_FUNCTION(getInternalWritableStream);
JSC_DECLARE_HOST_FUNCTION(whenSignalAborted);
JSC_DECLARE_HOST_FUNCTION(isAbortSignal);
+JSC_DEFINE_HOST_FUNCTION(jsCreateCJSImportMeta, (JSGlobalObject * globalObject, CallFrame* callFrame))
+{
+ return JSValue::encode(Zig::ImportMetaObject::create(globalObject, callFrame->argument(0).toString(globalObject)));
+}
+
JSC_DEFINE_HOST_FUNCTION(makeThisTypeErrorForBuiltins, (JSGlobalObject * globalObject, CallFrame* callFrame))
{
ASSERT(callFrame);
@@ -2825,11 +2830,20 @@ void GlobalObject::finishCreation(VM& vm)
m_commonJSFunctionArgumentsStructure.initLater(
[](const Initializer<Structure>& init) {
auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(init.owner);
+
+ auto prototype = JSC::constructEmptyObject(init.owner, globalObject->objectPrototype(), 1);
+ prototype->putDirect(
+ init.vm,
+ Identifier::fromString(init.vm, "createImportMeta"_s),
+ JSFunction::create(init.vm, init.owner, 2, ""_s, jsCreateCJSImportMeta, ImplementationVisibility::Public),
+ PropertyAttribute::DontDelete | PropertyAttribute::DontEnum | 0);
+
JSC::Structure* structure = globalObject->structureCache().emptyObjectStructureForPrototype(
globalObject,
- globalObject->objectPrototype(),
- 3);
+ prototype,
+ 5);
JSC::PropertyOffset offset;
+
auto& vm = globalObject->vm();
structure = structure->addPropertyTransition(
@@ -2842,6 +2856,20 @@ void GlobalObject::finishCreation(VM& vm)
structure = structure->addPropertyTransition(
vm,
structure,
+ JSC::Identifier::fromString(vm, "require"_s),
+ 0,
+ offset);
+
+ structure = structure->addPropertyTransition(
+ vm,
+ structure,
+ JSC::Identifier::fromString(vm, "resolve"_s),
+ 0,
+ offset);
+
+ structure = structure->addPropertyTransition(
+ vm,
+ structure,
JSC::Identifier::fromString(vm, "__dirname"_s),
0,
offset);
@@ -3647,6 +3675,8 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm)
putDirectBuiltinFunction(vm, this, builtinNames.internalRequirePrivateName(), importMetaObjectInternalRequireCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
putDirectBuiltinFunction(vm, this, builtinNames.requireNativeModulePrivateName(), moduleRequireNativeModuleCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
+ putDirectBuiltinFunction(vm, this, builtinNames.overridableRequirePrivateName(), moduleOverridableRequireCodeGenerator(vm), 0);
+
putDirectNativeFunction(vm, this, builtinNames.createUninitializedArrayBufferPrivateName(), 1, functionCreateUninitializedArrayBuffer, ImplementationVisibility::Public, NoIntrinsic, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::Function);
putDirectNativeFunction(vm, this, builtinNames.resolveSyncPrivateName(), 1, functionImportMeta__resolveSyncPrivate, ImplementationVisibility::Public, NoIntrinsic, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::Function);
putDirectNativeFunction(vm, this, builtinNames.createInternalModuleByIdPrivateName(), 1, InternalModuleRegistry::jsCreateInternalModuleById, ImplementationVisibility::Public, NoIntrinsic, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::Function);
diff --git a/src/bun.js/bindings/ZigGlobalObject.lut.h b/src/bun.js/bindings/ZigGlobalObject.lut.h
index 8363a994d..6516648e8 100644
--- a/src/bun.js/bindings/ZigGlobalObject.lut.h
+++ b/src/bun.js/bindings/ZigGlobalObject.lut.h
@@ -4,7 +4,7 @@ static const struct CompactHashIndex bunGlobalObjectTableIndex[260] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 43, -1 },
+ { 42, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
@@ -13,7 +13,7 @@ static const struct CompactHashIndex bunGlobalObjectTableIndex[260] = {
{ 6, -1 },
{ 3, -1 },
{ -1, -1 },
- { 35, -1 },
+ { 34, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
@@ -21,10 +21,10 @@ static const struct CompactHashIndex bunGlobalObjectTableIndex[260] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 30, 258 },
+ { 29, 258 },
{ -1, -1 },
{ -1, -1 },
- { 55, 257 },
+ { 54, 257 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
@@ -33,7 +33,7 @@ static const struct CompactHashIndex bunGlobalObjectTableIndex[260] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 52, -1 },
+ { 51, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
@@ -45,7 +45,7 @@ static const struct CompactHashIndex bunGlobalObjectTableIndex[260] = {
{ -1, -1 },
{ -1, -1 },
{ 18, -1 },
- { 57, -1 },
+ { 56, -1 },
{ -1, -1 },
{ -1, -1 },
{ 14, -1 },
@@ -57,25 +57,25 @@ static const struct CompactHashIndex bunGlobalObjectTableIndex[260] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 42, -1 },
- { 48, -1 },
+ { 41, -1 },
+ { 47, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 70, -1 },
+ { 69, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 40, -1 },
+ { 39, -1 },
{ -1, -1 },
{ -1, -1 },
- { 39, -1 },
- { 64, -1 },
+ { 38, -1 },
+ { 63, -1 },
{ -1, -1 },
- { 58, -1 },
+ { 57, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
@@ -83,47 +83,47 @@ static const struct CompactHashIndex bunGlobalObjectTableIndex[260] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 50, -1 },
+ { 49, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 59, -1 },
+ { 58, -1 },
{ 11, -1 },
{ -1, -1 },
{ -1, -1 },
{ 0, -1 },
{ -1, -1 },
- { 38, -1 },
- { 22, -1 },
- { 67, -1 },
+ { 37, -1 },
+ { 21, -1 },
+ { 66, -1 },
{ -1, -1 },
{ -1, -1 },
- { 71, -1 },
+ { 70, -1 },
{ -1, -1 },
- { 46, -1 },
+ { 45, -1 },
{ -1, -1 },
- { 49, -1 },
+ { 48, -1 },
{ -1, -1 },
{ -1, -1 },
- { 25, -1 },
+ { 24, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 34, -1 },
+ { 33, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 51, -1 },
- { 47, -1 },
+ { 50, -1 },
+ { 46, -1 },
{ -1, -1 },
{ 13, -1 },
{ -1, -1 },
{ -1, -1 },
- { 44, -1 },
+ { 43, -1 },
{ -1, -1 },
{ 1, -1 },
{ -1, -1 },
@@ -131,35 +131,35 @@ static const struct CompactHashIndex bunGlobalObjectTableIndex[260] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 21, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 33, -1 },
{ -1, -1 },
+ { 32, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 29, -1 },
{ -1, -1 },
+ { 28, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 27, -1 },
+ { -1, -1 },
+ { 26, -1 },
{ -1, -1 },
{ -1, -1 },
{ 17, -1 },
{ -1, -1 },
- { 32, -1 },
+ { 31, -1 },
{ -1, -1 },
{ -1, -1 },
- { 36, -1 },
- { 72, -1 },
+ { 35, -1 },
+ { 71, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 23, -1 },
+ { 22, -1 },
{ -1, -1 },
{ -1, -1 },
{ 4, -1 },
@@ -167,15 +167,15 @@ static const struct CompactHashIndex bunGlobalObjectTableIndex[260] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 24, -1 },
+ { 23, -1 },
{ -1, -1 },
{ -1, -1 },
- { 56, -1 },
+ { 55, -1 },
{ -1, -1 },
- { 54, -1 },
+ { 53, -1 },
{ -1, -1 },
{ 12, -1 },
- { 26, -1 },
+ { 25, -1 },
{ 7, -1 },
{ -1, -1 },
{ 9, -1 },
@@ -186,16 +186,16 @@ static const struct CompactHashIndex bunGlobalObjectTableIndex[260] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 62, -1 },
{ 61, -1 },
+ { 60, -1 },
{ -1, -1 },
{ 5, 256 },
{ -1, -1 },
- { 65, -1 },
+ { 64, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 37, -1 },
+ { 36, -1 },
{ -1, -1 },
{ 15, -1 },
{ -1, -1 },
@@ -204,10 +204,10 @@ static const struct CompactHashIndex bunGlobalObjectTableIndex[260] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 41, 259 },
+ { 40, 259 },
{ -1, -1 },
{ -1, -1 },
- { 69, -1 },
+ { 68, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
@@ -217,7 +217,7 @@ static const struct CompactHashIndex bunGlobalObjectTableIndex[260] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 53, -1 },
+ { 52, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
@@ -228,19 +228,19 @@ static const struct CompactHashIndex bunGlobalObjectTableIndex[260] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 31, -1 },
+ { 30, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 28, -1 },
+ { 27, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 45, -1 },
+ { 44, -1 },
{ -1, -1 },
{ -1, -1 },
- { 66, -1 },
+ { 65, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
@@ -257,12 +257,12 @@ static const struct CompactHashIndex bunGlobalObjectTableIndex[260] = {
{ 19, -1 },
{ -1, -1 },
{ 8, -1 },
- { 60, -1 },
- { 63, -1 },
- { 68, -1 },
+ { 59, -1 },
+ { 62, -1 },
+ { 67, -1 },
};
-static const struct HashTableValue bunGlobalObjectTableValues[73] = {
+static const struct HashTableValue bunGlobalObjectTableValues[72] = {
{ "addEventListener"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsFunctionAddEventListener, 2 } },
{ "alert"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, WebCore__alert, 1 } },
{ "atob"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, functionATOB, 1 } },
@@ -284,7 +284,6 @@ static const struct HashTableValue bunGlobalObjectTableValues[73] = {
{ "structuredClone"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, functionStructuredClone, 2 } },
{ "global"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, GlobalObject_getGlobalThis } },
{ "EventSource"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, getEventSourceConstructor } },
- { "$_BunCommonJSModule_$"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor|PropertyAttribute::DontDelete|PropertyAttribute::ReadOnly), NoIntrinsic, { HashTableValue::GetterSetterType, BunCommonJSModule_getter, 0 } },
{ "Bun"_s, static_cast<unsigned>(PropertyAttribute::CellProperty|PropertyAttribute::DontDelete|PropertyAttribute::ReadOnly), NoIntrinsic, { HashTableValue::LazyCellPropertyType, OBJECT_OFFSETOF(GlobalObject, m_bunObject) } },
{ "File"_s, static_cast<unsigned>(PropertyAttribute::CellProperty), NoIntrinsic, { HashTableValue::LazyCellPropertyType, OBJECT_OFFSETOF(GlobalObject, m_JSDOMFileConstructor) } },
{ "crypto"_s, static_cast<unsigned>(PropertyAttribute::CellProperty), NoIntrinsic, { HashTableValue::LazyCellPropertyType, OBJECT_OFFSETOF(GlobalObject, m_cryptoObject) } },
@@ -339,4 +338,4 @@ static const struct HashTableValue bunGlobalObjectTableValues[73] = {
};
static const struct HashTable bunGlobalObjectTable =
- { 73, 255, true, nullptr, bunGlobalObjectTableValues, bunGlobalObjectTableIndex };
+ { 72, 255, false, nullptr, bunGlobalObjectTableValues, bunGlobalObjectTableIndex };
diff --git a/src/bun.js/bindings/ZigGlobalObject.lut.txt b/src/bun.js/bindings/ZigGlobalObject.lut.txt
index 7700dcc8d..aadaee92a 100644
--- a/src/bun.js/bindings/ZigGlobalObject.lut.txt
+++ b/src/bun.js/bindings/ZigGlobalObject.lut.txt
@@ -25,8 +25,6 @@
global GlobalObject_getGlobalThis PropertyCallback
EventSource getEventSourceConstructor PropertyCallback
- $_BunCommonJSModule_$ BunCommonJSModule_getter CustomAccessor|DontDelete|ReadOnly
-
Bun GlobalObject::m_bunObject CellProperty|DontDelete|ReadOnly
File GlobalObject::m_JSDOMFileConstructor CellProperty
crypto GlobalObject::m_cryptoObject CellProperty
diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig
index ca066450d..89dca35b0 100644
--- a/src/bun.js/module_loader.zig
+++ b/src/bun.js/module_loader.zig
@@ -154,21 +154,26 @@ const BunDebugHolder = struct {
pub var lock: bun.Lock = undefined;
};
-fn dumpSource(specifier: string, printer: anytype) !void {
+/// Dumps the module source to a file in /tmp/bun-debug-src/{filepath}
+///
+/// This can technically fail if concurrent access across processes happens, or permission issues.
+/// Errors here should always be ignored.
+fn dumpSource(specifier: string, printer: anytype) void {
if (BunDebugHolder.dir == null) {
- BunDebugHolder.dir = try std.fs.cwd().makeOpenPathIterable("/tmp/bun-debug-src/", .{});
+ BunDebugHolder.dir = std.fs.cwd().makeOpenPathIterable("/tmp/bun-debug-src/", .{}) catch return;
BunDebugHolder.lock = bun.Lock.init();
}
BunDebugHolder.lock.lock();
defer BunDebugHolder.lock.unlock();
+ const dir = BunDebugHolder.dir orelse return;
if (std.fs.path.dirname(specifier)) |dir_path| {
- var parent = try BunDebugHolder.dir.?.dir.makeOpenPathIterable(dir_path[1..], .{});
+ var parent = dir.dir.makeOpenPathIterable(dir_path[1..], .{}) catch return;
defer parent.close();
- try parent.dir.writeFile(std.fs.path.basename(specifier), printer.ctx.getWritten());
+ parent.dir.writeFile(std.fs.path.basename(specifier), printer.ctx.getWritten()) catch return;
} else {
- try BunDebugHolder.dir.?.dir.writeFile(std.fs.path.basename(specifier), printer.ctx.getWritten());
+ dir.dir.writeFile(std.fs.path.basename(specifier), printer.ctx.getWritten()) catch return;
}
}
@@ -545,7 +550,7 @@ pub const RuntimeTranspilerStore = struct {
}
if (comptime Environment.dump_source) {
- dumpSource(specifier, &printer) catch {};
+ dumpSource(specifier, &printer);
}
this.resolved_source = ResolvedSource{
@@ -1230,7 +1235,7 @@ pub const ModuleLoader = struct {
}
if (comptime Environment.dump_source) {
- try dumpSource(specifier, &printer);
+ dumpSource(specifier, &printer);
}
var commonjs_exports = try bun.default_allocator.alloc(ZigString, parse_result.ast.commonjs_export_names.len);
@@ -1626,7 +1631,7 @@ pub const ModuleLoader = struct {
};
if (comptime Environment.dump_source) {
- try dumpSource(specifier, &printer);
+ dumpSource(specifier, &printer);
}
var commonjs_exports = try bun.default_allocator.alloc(ZigString, parse_result.ast.commonjs_export_names.len);
@@ -1979,6 +1984,7 @@ pub const ModuleLoader = struct {
if (err == error.PluginError) {
return null;
}
+
VirtualMachine.processFetchLog(globalObject, specifier_ptr.*, referrer.*, &log, ret, err);
return null;
},
diff --git a/src/bun.js/modules/NodeModuleModule.h b/src/bun.js/modules/NodeModuleModule.h
index 6d8654024..ddb273de4 100644
--- a/src/bun.js/modules/NodeModuleModule.h
+++ b/src/bun.js/modules/NodeModuleModule.h
@@ -304,6 +304,39 @@ JSC_DEFINE_CUSTOM_SETTER(set_resolveFilename,
return false;
}
+// These two setters are only used if you directly hit
+// `Module.prototype.require` or `module.require`. When accessing the cjs
+// require argument, this is a bound version of `require`, which calls into the
+// overridden one.
+//
+// This require function also intentionally does not have .resolve on it, nor
+// does it have any of the other properties.
+//
+// Note: allowing require to be overridable at all is only needed for Next.js to
+// work (they do Module.prototype.require = ...)
+
+JSC_DEFINE_CUSTOM_GETTER(getterRequireFunction,
+ (JSC::JSGlobalObject * globalObject,
+ JSC::EncodedJSValue thisValue, JSC::PropertyName)) {
+ return JSValue::encode(globalObject->getDirect(
+ globalObject->vm(), WebCore::clientData(globalObject->vm())
+ ->builtinNames()
+ .overridableRequirePrivateName()));
+}
+
+JSC_DEFINE_CUSTOM_SETTER(setterRequireFunction,
+ (JSC::JSGlobalObject * globalObject,
+ JSC::EncodedJSValue thisValue,
+ JSC::EncodedJSValue value,
+ JSC::PropertyName propertyName)) {
+ globalObject->putDirect(globalObject->vm(),
+ WebCore::clientData(globalObject->vm())
+ ->builtinNames()
+ .overridableRequirePrivateName(),
+ JSValue::decode(value), 0);
+ return true;
+}
+
namespace Zig {
DEFINE_NATIVE_MODULE(NodeModule) {
@@ -371,8 +404,15 @@ DEFINE_NATIVE_MODULE(NodeModule) {
put(Identifier::fromString(vm, "globalPaths"_s),
constructEmptyArray(globalObject, nullptr, 0));
- put(Identifier::fromString(vm, "prototype"_s),
- constructEmptyObject(globalObject));
+ auto prototype =
+ constructEmptyObject(globalObject, globalObject->objectPrototype(), 1);
+ prototype->putDirectCustomAccessor(
+ vm, JSC::Identifier::fromString(vm, "require"_s),
+ JSC::CustomGetterSetter::create(vm, getterRequireFunction,
+ setterRequireFunction),
+ 0);
+
+ defaultObject->putDirect(vm, vm.propertyNames->prototype, prototype);
JSC::JSArray *builtinModules = JSC::JSArray::create(
vm,
diff --git a/src/bundler.zig b/src/bundler.zig
index cf0e0a4f8..479843bcd 100644
--- a/src/bundler.zig
+++ b/src/bundler.zig
@@ -1106,6 +1106,7 @@ pub const Bundler = struct {
.minify_syntax = bundler.options.minify_syntax,
.minify_identifiers = bundler.options.minify_identifiers,
.transform_only = bundler.options.transform_only,
+ .import_meta_ref = ast.import_meta_ref,
},
enable_source_map,
),
@@ -1129,6 +1130,7 @@ pub const Bundler = struct {
.transform_only = bundler.options.transform_only,
.module_type = if (ast.exports_kind == .cjs) .cjs else .esm,
.inline_require_and_import_errors = false,
+ .import_meta_ref = ast.import_meta_ref,
},
enable_source_map,
),
diff --git a/src/js/_codegen/builtin-parser.ts b/src/js/_codegen/builtin-parser.ts
index ffd5671c1..4e35f13dd 100644
--- a/src/js/_codegen/builtin-parser.ts
+++ b/src/js/_codegen/builtin-parser.ts
@@ -79,12 +79,14 @@ export function sliceSourceCode(
i = 1;
} else if (endOnComma && contents.startsWith(",")) {
if (bracketCount <= 1) {
- result += ",";
contents = contents.slice(1);
- // if the next non-whitespace character is ), also consume
+ // if the next non-whitespace character is ), we will treat it like a )
let match = contents.match(/^\s*\)/);
if (match) {
contents = contents.slice(match[0].length);
+ result += ")";
+ } else {
+ result += ",";
}
break;
}
diff --git a/src/js/_codegen/client-js.ts b/src/js/_codegen/client-js.ts
index 2db3305fa..bd9ed63f4 100644
--- a/src/js/_codegen/client-js.ts
+++ b/src/js/_codegen/client-js.ts
@@ -27,10 +27,18 @@ export function createAssertClientJS(publicName: string) {
return `
let $assert = function(check, sourceString, ...message) {
if (!check) {
- console.error('[${publicName}] ASSERTION FAILED: ' + sourceString);
- if(message.length)console.warn (' ${" ".repeat(publicName.length)}', ...message);
+ const prevPrepareStackTrace = Error.prepareStackTrace;
+ Error.prepareStackTrace = (e, stack) => {
+ return e.name + ': ' + e.message + '\\n' + stack.slice(1).map(x => ' at ' + x.toString()).join('\\n');
+ };
const e = new Error(sourceString);
+ e.stack; // materialize stack
e.name = 'AssertionError';
+ Error.prepareStackTrace = prevPrepareStackTrace;
+ console.error('[${publicName}] ASSERTION FAILED: ' + sourceString);
+ if (message.length) console.warn(...message);
+ console.warn(e.stack.split('\\n')[1] + '\\n');
+ if (Bun.env.ASSERT === 'CRASH') process.exit(0xAA);
throw e;
}
}
diff --git a/src/js/_codegen/replacements.ts b/src/js/_codegen/replacements.ts
index 5ce646ad5..45f2426b5 100644
--- a/src/js/_codegen/replacements.ts
+++ b/src/js/_codegen/replacements.ts
@@ -141,14 +141,27 @@ export function applyReplacements(src: string, length: number) {
];
} else if (name === "assert") {
const checkSlice = sliceSourceCode(rest, true, undefined, true);
+ let rest2 = checkSlice.rest;
+ let extraArgs = "";
+ if (checkSlice.result.at(-1) === ",") {
+ const sliced = sliceSourceCode("(" + rest2.slice(1), true, undefined, false);
+ extraArgs = ", " + sliced.result.slice(1, -1);
+ rest2 = sliced.rest;
+ }
return [
slice.slice(0, match.index) +
"(IS_BUN_DEVELOPMENT?$assert(" +
checkSlice.result.slice(1, -1) +
"," +
- JSON.stringify(checkSlice.result.slice(1, -1).replace(/__intrinsic__/g, "$")) +
+ JSON.stringify(
+ checkSlice.result
+ .slice(1, -1)
+ .replace(/__intrinsic__/g, "$")
+ .trim(),
+ ) +
+ extraArgs +
"):void 0)",
- checkSlice.rest,
+ rest2,
true,
];
}
diff --git a/src/js/builtins.d.ts b/src/js/builtins.d.ts
index cdda3ffe1..ee7bd68cf 100644
--- a/src/js/builtins.d.ts
+++ b/src/js/builtins.d.ts
@@ -12,7 +12,9 @@ declare function $debug(...args: any[]): void;
/** $assert is a preprocessor macro that only runs in debug mode. it throws an error if the first argument is falsy.
* The source code passed to `check` is inlined in the message, but in addition you can pass additional messages.
*/
-declare function $assert(check: any, ...message: any[]): void;
+declare function $assert(check: any, ...message: any[]): asserts check;
+
+declare const IS_BUN_DEVELOPMENT: boolean;
/** Place this directly above a function declaration (like a decorator) to make it a getter. */
declare const $getter: never;
@@ -439,6 +441,8 @@ declare function $createCommonJSModule(
parent: CommonJSModuleRecord,
): CommonJSModuleRecord;
+declare function $overridableRequire(this: CommonJSModuleRecord, id: string): any;
+
// The following I cannot find any definitions of, but they are functional.
declare function $toLength(length: number): number;
declare function $isTypedArrayView(obj: unknown): obj is ArrayBufferView | DataView | Uint8Array;
diff --git a/src/js/builtins/BunBuiltinNames.h b/src/js/builtins/BunBuiltinNames.h
index caaba1738..d124a7683 100644
--- a/src/js/builtins/BunBuiltinNames.h
+++ b/src/js/builtins/BunBuiltinNames.h
@@ -69,6 +69,7 @@ using namespace JSC;
macro(createCommonJSModule) \
macro(createEmptyReadableStream) \
macro(createFIFO) \
+ macro(createInternalModuleById) \
macro(createNativeReadableStream) \
macro(createReadableStream) \
macro(createUninitializedArrayBuffer) \
@@ -119,6 +120,7 @@ using namespace JSC;
macro(inFlightCloseRequest) \
macro(inFlightWriteRequest) \
macro(initializeWith) \
+ macro(internalModuleRegistry) \
macro(internalRequire) \
macro(internalStream) \
macro(internalWritable) \
@@ -145,6 +147,7 @@ using namespace JSC;
macro(once) \
macro(options) \
macro(origin) \
+ macro(overridableRequire) \
macro(ownerReadableStream) \
macro(parse) \
macro(password) \
@@ -185,6 +188,7 @@ using namespace JSC;
macro(require) \
macro(requireESM) \
macro(requireMap) \
+ macro(requireNativeModule) \
macro(resolve) \
macro(resolveSync) \
macro(resume) \
@@ -238,9 +242,6 @@ using namespace JSC;
macro(writer) \
macro(writing) \
macro(written) \
- macro(createInternalModuleById) \
- macro(internalModuleRegistry) \
- macro(requireNativeModule) \
class BunBuiltinNames {
public:
diff --git a/src/js/builtins/Module.ts b/src/js/builtins/Module.ts
index 3d88f2484..b074d3488 100644
--- a/src/js/builtins/Module.ts
+++ b/src/js/builtins/Module.ts
@@ -4,6 +4,11 @@ export function main() {
}
export function require(this: CommonJSModuleRecord, id: string) {
+ return $overridableRequire.$call(this, id);
+}
+
+// overridableRequire can be overridden by setting `Module.prototype.require`
+export function overridableRequire(this: CommonJSModuleRecord, id: string) {
const existing = $requireMap.$get(id) || $requireMap.$get((id = $resolveSync(id, this.path, false)));
if (existing) {
// Scenario where this is necessary:
diff --git a/src/js/builtins/ProcessObjectInternals.ts b/src/js/builtins/ProcessObjectInternals.ts
index ef8f1f9ce..aa7c9b783 100644
--- a/src/js/builtins/ProcessObjectInternals.ts
+++ b/src/js/builtins/ProcessObjectInternals.ts
@@ -89,7 +89,8 @@ export function getStdinStream(fd) {
const tty = require("node:tty");
- const stream = new tty.ReadStream(fd);
+ const ReadStream = tty.isatty(fd) ? tty.ReadStream : require("node:fs").ReadStream;
+ const stream = new ReadStream(fd);
const originalOn = stream.on;
stream.on = function (event, listener) {
diff --git a/src/js/node/async_hooks.ts b/src/js/node/async_hooks.ts
index ef77b79f7..83b313912 100644
--- a/src/js/node/async_hooks.ts
+++ b/src/js/node/async_hooks.ts
@@ -19,17 +19,53 @@
// use. But the nature of this approach makes the implementation *itself* very low-impact on performance.
//
// AsyncContextData is an immutable array managed in here, formatted [key, value, key, value] where
-// each key is an AsyncLocalStorage object and the value is the associated value.
+// each key is an AsyncLocalStorage object and the value is the associated value. There are a ton of
+// calls to $assert which will verify this invariant (only during bun-debug)
//
const { cleanupLater, setAsyncHooksEnabled } = $lazy("async_hooks");
+// Only run during debug
+function assertValidAsyncContextArray(array: unknown): array is ReadonlyArray<any> | undefined {
+ // undefined is OK
+ if (array === undefined) return true;
+ // Otherwise, it must be an array
+ $assert(
+ Array.isArray(array),
+ "AsyncContextData must be an array or undefined, got",
+ Bun.inspect(array, { depth: 1 }),
+ );
+ // the array has to be even
+ $assert(array.length % 2 === 0, "AsyncContextData should be even-length, got", Bun.inspect(array, { depth: 1 }));
+ // if it is zero-length, use undefined instead
+ $assert(array.length > 0, "AsyncContextData should be undefined if empty, got", Bun.inspect(array, { depth: 1 }));
+ for (var i = 0; i < array.length; i += 2) {
+ $assert(
+ array[i] instanceof AsyncLocalStorage,
+ `Odd indexes in AsyncContextData should be an array of AsyncLocalStorage\nIndex %s was %s`,
+ i,
+ array[i],
+ );
+ }
+ return true;
+}
+
+// Only run during debug
+function debugFormatContextValue(value: ReadonlyArray<any> | undefined) {
+ if (value === undefined) return "{}";
+ let str = "{\n";
+ for (var i = 0; i < value.length; i += 2) {
+ str += ` ${value[i].__id__}: ${Bun.inspect(value[i + 1], { depth: 1, colors: Bun.enableANSIColors })}\n`;
+ }
+}
+
function get(): ReadonlyArray<any> | undefined {
- $debug("get", $getInternalField($asyncContext, 0));
+ $debug("get", debugFormatContextValue($getInternalField($asyncContext, 0)));
return $getInternalField($asyncContext, 0);
}
function set(contextValue: ReadonlyArray<any> | undefined) {
- $debug("set", contextValue);
+ $assert(assertValidAsyncContextArray(contextValue));
+ $debug("set", debugFormatContextValue(contextValue));
return $putInternalField($asyncContext, 0, contextValue);
}
@@ -38,6 +74,14 @@ class AsyncLocalStorage {
constructor() {
setAsyncHooksEnabled(true);
+
+ // In debug mode assign every AsyncLocalStorage a unique ID
+ if (IS_BUN_DEVELOPMENT) {
+ (this as any).__id__ =
+ Math.random().toString(36).slice(2, 8) +
+ "@" +
+ require("node:path").basename(require("bun:jsc").callerSourceOrigin());
+ }
}
static bind(fn, ...args: any) {
@@ -67,8 +111,11 @@ class AsyncLocalStorage {
return;
}
var { length } = context;
+ $assert(length > 0);
+ $assert(length % 2 === 0);
for (var i = 0; i < length; i += 2) {
if (context[i] === this) {
+ $assert(length > i + 1);
const clone = context.slice();
clone[i + 1] = store;
set(clone);
@@ -76,33 +123,42 @@ class AsyncLocalStorage {
}
}
set(context.concat(this, store));
+ $assert(this.getStore() === store);
}
exit(cb, ...args) {
return this.run(undefined, cb, ...args);
}
- run(store, callback, ...args) {
+ // This function is literred with $asserts to ensure that everything that
+ // is assumed to be true is *actually* true.
+ run(store_value, callback, ...args) {
var context = get() as any[]; // we make sure to .slice() before mutating
var hasPrevious = false;
- var previous;
+ var previous_value;
var i = 0;
- var contextWasInit = !context;
- if (contextWasInit) {
- set((context = [this, store]));
+ var contextWasAlreadyInit = !context;
+ if (contextWasAlreadyInit) {
+ set((context = [this, store_value]));
} else {
// it's safe to mutate context now that it was cloned
context = context!.slice();
i = context.indexOf(this);
if (i > -1) {
+ $assert(i % 2 === 0);
hasPrevious = true;
- previous = context[i + 1];
- context[i + 1] = store;
+ previous_value = context[i + 1];
+ context[i + 1] = store_value;
} else {
- context.push(this, store);
+ i = context.length;
+ context.push(this, store_value);
+ $assert(i % 2 === 0);
+ $assert(context.length % 2 === 0);
}
set(context);
}
+ $assert(i > -1, "i was not set");
+ $assert(this.getStore() === store_value, "run: store_value was not set");
try {
return callback(...args);
} catch (e) {
@@ -111,24 +167,36 @@ class AsyncLocalStorage {
// Note: early `return` will prevent `throw` above from working. I think...
// Set AsyncContextFrame to undefined if we are out of context values
if (!this.#disableCalled) {
- var context2 = get()! as any[];
- if (context2 === context && contextWasInit) {
+ var context2 = get()! as any[]; // we make sure to .slice() before mutating
+ if (context2 === context && contextWasAlreadyInit) {
+ $assert(context2.length === 2, "context was mutated without copy");
set(undefined);
} else {
context2 = context2.slice(); // array is cloned here
+ $assert(context2[i] === this);
if (hasPrevious) {
- context2[i + 1] = previous;
+ context2[i + 1] = previous_value;
set(context2);
} else {
+ // i wonder if this is a fair assert to make
context2.splice(i, 2);
+ $assert(context2.length % 2 === 0);
set(context2.length ? context2 : undefined);
}
}
+ $assert(
+ this.getStore() === previous_value,
+ "run: previous_value",
+ Bun.inspect(previous_value),
+ "was not restored, i see",
+ this.getStore(),
+ );
}
}
}
disable() {
+ $debug("disable " + (this as any).__id__);
// In this case, we actually do want to mutate the context state
if (!this.#disableCalled) {
var context = get() as any[];
@@ -156,11 +224,21 @@ class AsyncLocalStorage {
}
}
+if (IS_BUN_DEVELOPMENT) {
+ AsyncLocalStorage.prototype[Bun.inspect.custom] = function (depth, options) {
+ if (depth < 0) return `AsyncLocalStorage { ${Bun.inspect((this as any).__id__, options)} }`;
+ return `AsyncLocalStorage { [${options.stylize("debug id", "special")}]: ${Bun.inspect(
+ (this as any).__id__,
+ options,
+ )} }`;
+ };
+}
+
class AsyncResource {
type;
#snapshot;
- constructor(type, options) {
+ constructor(type, options?) {
if (typeof type !== "string") {
throw new TypeError('The "type" argument must be of type string. Received type ' + typeof type);
}
@@ -200,6 +278,15 @@ class AsyncResource {
set(prev);
}
}
+
+ bind(fn, thisArg) {
+ return this.runInAsyncScope.bind(this, fn, thisArg ?? this);
+ }
+
+ static bind(fn, type, thisArg) {
+ type = type || fn.name;
+ return new AsyncResource(type || "bound-anonymous-fn").bind(fn, thisArg);
+ }
}
// The rest of async_hooks is not implemented and is stubbed with no-ops and warnings.
diff --git a/src/js/node/tty.js b/src/js/node/tty.js
index 2ffc2d764..1c3fb2fac 100644
--- a/src/js/node/tty.js
+++ b/src/js/node/tty.js
@@ -11,30 +11,34 @@ function ReadStream(fd) {
const stream = require("node:fs").ReadStream.call(this, "", {
fd,
});
+ Object.setPrototypeOf(stream, ReadStream.prototype);
stream.isRaw = false;
- stream.isTTY = isatty(stream.fd);
+ stream.isTTY = true;
+
+ $assert(stream instanceof ReadStream);
return stream;
}
Object.defineProperty(ReadStream, "prototype", {
get() {
- const Real = require("node:fs").ReadStream.prototype;
+ const Prototype = Object.create(require("node:fs").ReadStream.prototype);
- Object.defineProperty(ReadStream, "prototype", { value: Real });
- ReadStream.prototype.setRawMode = function (flag) {
+ Prototype.setRawMode = function (flag) {
const mode = flag ? 1 : 0;
const err = ttySetMode(this.fd, mode);
if (err) {
- this.emit("error", new Error("setRawMode failed with errno:", err));
+ this.emit("error", new Error("setRawMode failed with errno: " + err));
return this;
}
this.isRaw = flag;
return this;
};
- return Real;
+ Object.defineProperty(ReadStream, "prototype", { value: Prototype });
+
+ return Prototype;
},
enumerable: true,
configurable: true,
diff --git a/src/js/out/InternalModuleRegistryConstants.h b/src/js/out/InternalModuleRegistryConstants.h
index 344433952..b4a181d60 100644
--- a/src/js/out/InternalModuleRegistryConstants.h
+++ b/src/js/out/InternalModuleRegistryConstants.h
@@ -46,7 +46,7 @@ static constexpr ASCIILiteral NodeAssertStrictCode = "(function (){\"use strict\
//
//
-static constexpr ASCIILiteral NodeAsyncHooksCode = "(function (){\"use strict\";// src/js/out/tmp/node/async_hooks.ts\nvar get = function() {\n return @getInternalField(@asyncContext, 0);\n}, set = function(contextValue) {\n return @putInternalField(@asyncContext, 0, contextValue);\n}, createWarning = function(message) {\n let warned = !1;\n var wrapped = function() {\n if (warned)\n return;\n if (new Error().stack.includes(\"zx/build/core.js\"))\n return;\n warned = !0, console.warn(\"[bun] Warning:\", message);\n };\n return wrapped;\n}, createHook = function(callbacks) {\n return {\n enable: createHookNotImpl,\n disable: createHookNotImpl\n };\n}, executionAsyncId = function() {\n return executionAsyncIdNotImpl(), 0;\n}, triggerAsyncId = function() {\n return 0;\n}, executionAsyncResource = function() {\n return executionAsyncResourceWarning(), process.stdin;\n}, $, { cleanupLater, setAsyncHooksEnabled } = @lazy(\"async_hooks\");\n\nclass AsyncLocalStorage {\n #disableCalled = !1;\n constructor() {\n setAsyncHooksEnabled(!0);\n }\n static bind(fn, ...args) {\n return this.snapshot().bind(null, fn, ...args);\n }\n static snapshot() {\n var context = get();\n return (fn, ...args) => {\n var prev = get();\n set(context);\n try {\n return fn(...args);\n } catch (error) {\n throw error;\n } finally {\n set(prev);\n }\n };\n }\n enterWith(store) {\n cleanupLater();\n var context = get();\n if (!context) {\n set([this, store]);\n return;\n }\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this) {\n const clone = context.slice();\n clone[i + 1] = store, set(clone);\n return;\n }\n set(context.concat(this, store));\n }\n exit(cb, ...args) {\n return this.run(@undefined, cb, ...args);\n }\n run(store, callback, ...args) {\n var context = get(), hasPrevious = !1, previous, i = 0, contextWasInit = !context;\n if (contextWasInit)\n set(context = [this, store]);\n else {\n if (context = context.slice(), i = context.indexOf(this), i > -1)\n hasPrevious = !0, previous = context[i + 1], context[i + 1] = store;\n else\n context.push(this, store);\n set(context);\n }\n try {\n return callback(...args);\n } catch (e) {\n throw e;\n } finally {\n if (!this.#disableCalled) {\n var context2 = get();\n if (context2 === context && contextWasInit)\n set(@undefined);\n else if (context2 = context2.slice(), hasPrevious)\n context2[i + 1] = previous, set(context2);\n else\n context2.splice(i, 2), set(context2.length \? context2 : @undefined);\n }\n }\n }\n disable() {\n if (!this.#disableCalled) {\n var context = get();\n if (context) {\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this) {\n context.splice(i, 2), set(context.length \? context : @undefined);\n break;\n }\n }\n this.#disableCalled = !0;\n }\n }\n getStore() {\n var context = get();\n if (!context)\n return;\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this)\n return context[i + 1];\n }\n}\n\nclass AsyncResource {\n type;\n #snapshot;\n constructor(type, options) {\n if (typeof type !== \"string\")\n @throwTypeError('The \"type\" argument must be of type string. Received type ' + typeof type);\n setAsyncHooksEnabled(!0), this.type = type, this.#snapshot = get();\n }\n emitBefore() {\n return !0;\n }\n emitAfter() {\n return !0;\n }\n asyncId() {\n return 0;\n }\n triggerAsyncId() {\n return 0;\n }\n emitDestroy() {\n }\n runInAsyncScope(fn, thisArg, ...args) {\n var prev = get();\n set(this.#snapshot);\n try {\n return fn.apply(thisArg, args);\n } catch (error) {\n throw error;\n } finally {\n set(prev);\n }\n }\n}\nvar createHookNotImpl = createWarning(\"async_hooks.createHook is not implemented in Bun. Hooks can still be created but will never be called.\"), executionAsyncIdNotImpl = createWarning(\"async_hooks.executionAsyncId/triggerAsyncId are not implemented in Bun. It will return 0 every time.\"), executionAsyncResourceWarning = createWarning(\"async_hooks.executionAsyncResource is not implemented in Bun. It returns a reference to process.stdin every time.\"), asyncWrapProviders = {\n NONE: 0,\n DIRHANDLE: 1,\n DNSCHANNEL: 2,\n ELDHISTOGRAM: 3,\n FILEHANDLE: 4,\n FILEHANDLECLOSEREQ: 5,\n FIXEDSIZEBLOBCOPY: 6,\n FSEVENTWRAP: 7,\n FSREQCALLBACK: 8,\n FSREQPROMISE: 9,\n GETADDRINFOREQWRAP: 10,\n GETNAMEINFOREQWRAP: 11,\n HEAPSNAPSHOT: 12,\n HTTP2SESSION: 13,\n HTTP2STREAM: 14,\n HTTP2PING: 15,\n HTTP2SETTINGS: 16,\n HTTPINCOMINGMESSAGE: 17,\n HTTPCLIENTREQUEST: 18,\n JSSTREAM: 19,\n JSUDPWRAP: 20,\n MESSAGEPORT: 21,\n PIPECONNECTWRAP: 22,\n PIPESERVERWRAP: 23,\n PIPEWRAP: 24,\n PROCESSWRAP: 25,\n PROMISE: 26,\n QUERYWRAP: 27,\n SHUTDOWNWRAP: 28,\n SIGNALWRAP: 29,\n STATWATCHER: 30,\n STREAMPIPE: 31,\n TCPCONNECTWRAP: 32,\n TCPSERVERWRAP: 33,\n TCPWRAP: 34,\n TTYWRAP: 35,\n UDPSENDWRAP: 36,\n UDPWRAP: 37,\n SIGINTWATCHDOG: 38,\n WORKER: 39,\n WORKERHEAPSNAPSHOT: 40,\n WRITEWRAP: 41,\n ZLIB: 42,\n CHECKPRIMEREQUEST: 43,\n PBKDF2REQUEST: 44,\n KEYPAIRGENREQUEST: 45,\n KEYGENREQUEST: 46,\n KEYEXPORTREQUEST: 47,\n CIPHERREQUEST: 48,\n DERIVEBITSREQUEST: 49,\n HASHREQUEST: 50,\n RANDOMBYTESREQUEST: 51,\n RANDOMPRIMEREQUEST: 52,\n SCRYPTREQUEST: 53,\n SIGNREQUEST: 54,\n TLSWRAP: 55,\n VERIFYREQUEST: 56,\n INSPECTORJSBINDING: 57\n};\n$ = {\n AsyncLocalStorage,\n createHook,\n executionAsyncId,\n triggerAsyncId,\n executionAsyncResource,\n asyncWrapProviders,\n AsyncResource\n};\nreturn $})\n"_s;
+static constexpr ASCIILiteral NodeAsyncHooksCode = "(function (){\"use strict\";// src/js/out/tmp/node/async_hooks.ts\nvar get = function() {\n return @getInternalField(@asyncContext, 0);\n}, set = function(contextValue) {\n return @putInternalField(@asyncContext, 0, contextValue);\n}, createWarning = function(message) {\n let warned = !1;\n var wrapped = function() {\n if (warned)\n return;\n if (new Error().stack.includes(\"zx/build/core.js\"))\n return;\n warned = !0, console.warn(\"[bun] Warning:\", message);\n };\n return wrapped;\n}, createHook = function(callbacks) {\n return {\n enable: createHookNotImpl,\n disable: createHookNotImpl\n };\n}, executionAsyncId = function() {\n return executionAsyncIdNotImpl(), 0;\n}, triggerAsyncId = function() {\n return 0;\n}, executionAsyncResource = function() {\n return executionAsyncResourceWarning(), process.stdin;\n}, $, { cleanupLater, setAsyncHooksEnabled } = @lazy(\"async_hooks\");\n\nclass AsyncLocalStorage {\n #disableCalled = !1;\n constructor() {\n setAsyncHooksEnabled(!0);\n }\n static bind(fn, ...args) {\n return this.snapshot().bind(null, fn, ...args);\n }\n static snapshot() {\n var context = get();\n return (fn, ...args) => {\n var prev = get();\n set(context);\n try {\n return fn(...args);\n } catch (error) {\n throw error;\n } finally {\n set(prev);\n }\n };\n }\n enterWith(store) {\n cleanupLater();\n var context = get();\n if (!context) {\n set([this, store]);\n return;\n }\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this) {\n const clone = context.slice();\n clone[i + 1] = store, set(clone);\n return;\n }\n set(context.concat(this, store));\n }\n exit(cb, ...args) {\n return this.run(@undefined, cb, ...args);\n }\n run(store_value, callback, ...args) {\n var context = get(), hasPrevious = !1, previous_value, i = 0, contextWasAlreadyInit = !context;\n if (contextWasAlreadyInit)\n set(context = [this, store_value]);\n else {\n if (context = context.slice(), i = context.indexOf(this), i > -1)\n hasPrevious = !0, previous_value = context[i + 1], context[i + 1] = store_value;\n else\n i = context.length, context.push(this, store_value);\n set(context);\n }\n try {\n return callback(...args);\n } catch (e) {\n throw e;\n } finally {\n if (!this.#disableCalled) {\n var context2 = get();\n if (context2 === context && contextWasAlreadyInit)\n set(@undefined);\n else if (context2 = context2.slice(), hasPrevious)\n context2[i + 1] = previous_value, set(context2);\n else\n context2.splice(i, 2), set(context2.length \? context2 : @undefined);\n }\n }\n }\n disable() {\n if (!this.#disableCalled) {\n var context = get();\n if (context) {\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this) {\n context.splice(i, 2), set(context.length \? context : @undefined);\n break;\n }\n }\n this.#disableCalled = !0;\n }\n }\n getStore() {\n var context = get();\n if (!context)\n return;\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this)\n return context[i + 1];\n }\n}\n\nclass AsyncResource {\n type;\n #snapshot;\n constructor(type, options) {\n if (typeof type !== \"string\")\n @throwTypeError('The \"type\" argument must be of type string. Received type ' + typeof type);\n setAsyncHooksEnabled(!0), this.type = type, this.#snapshot = get();\n }\n emitBefore() {\n return !0;\n }\n emitAfter() {\n return !0;\n }\n asyncId() {\n return 0;\n }\n triggerAsyncId() {\n return 0;\n }\n emitDestroy() {\n }\n runInAsyncScope(fn, thisArg, ...args) {\n var prev = get();\n set(this.#snapshot);\n try {\n return fn.apply(thisArg, args);\n } catch (error) {\n throw error;\n } finally {\n set(prev);\n }\n }\n bind(fn, thisArg) {\n return this.runInAsyncScope.bind(this, fn, thisArg \?\? this);\n }\n static bind(fn, type, thisArg) {\n return type = type || fn.name, new AsyncResource(type || \"bound-anonymous-fn\").bind(fn, thisArg);\n }\n}\nvar createHookNotImpl = createWarning(\"async_hooks.createHook is not implemented in Bun. Hooks can still be created but will never be called.\"), executionAsyncIdNotImpl = createWarning(\"async_hooks.executionAsyncId/triggerAsyncId are not implemented in Bun. It will return 0 every time.\"), executionAsyncResourceWarning = createWarning(\"async_hooks.executionAsyncResource is not implemented in Bun. It returns a reference to process.stdin every time.\"), asyncWrapProviders = {\n NONE: 0,\n DIRHANDLE: 1,\n DNSCHANNEL: 2,\n ELDHISTOGRAM: 3,\n FILEHANDLE: 4,\n FILEHANDLECLOSEREQ: 5,\n FIXEDSIZEBLOBCOPY: 6,\n FSEVENTWRAP: 7,\n FSREQCALLBACK: 8,\n FSREQPROMISE: 9,\n GETADDRINFOREQWRAP: 10,\n GETNAMEINFOREQWRAP: 11,\n HEAPSNAPSHOT: 12,\n HTTP2SESSION: 13,\n HTTP2STREAM: 14,\n HTTP2PING: 15,\n HTTP2SETTINGS: 16,\n HTTPINCOMINGMESSAGE: 17,\n HTTPCLIENTREQUEST: 18,\n JSSTREAM: 19,\n JSUDPWRAP: 20,\n MESSAGEPORT: 21,\n PIPECONNECTWRAP: 22,\n PIPESERVERWRAP: 23,\n PIPEWRAP: 24,\n PROCESSWRAP: 25,\n PROMISE: 26,\n QUERYWRAP: 27,\n SHUTDOWNWRAP: 28,\n SIGNALWRAP: 29,\n STATWATCHER: 30,\n STREAMPIPE: 31,\n TCPCONNECTWRAP: 32,\n TCPSERVERWRAP: 33,\n TCPWRAP: 34,\n TTYWRAP: 35,\n UDPSENDWRAP: 36,\n UDPWRAP: 37,\n SIGINTWATCHDOG: 38,\n WORKER: 39,\n WORKERHEAPSNAPSHOT: 40,\n WRITEWRAP: 41,\n ZLIB: 42,\n CHECKPRIMEREQUEST: 43,\n PBKDF2REQUEST: 44,\n KEYPAIRGENREQUEST: 45,\n KEYGENREQUEST: 46,\n KEYEXPORTREQUEST: 47,\n CIPHERREQUEST: 48,\n DERIVEBITSREQUEST: 49,\n HASHREQUEST: 50,\n RANDOMBYTESREQUEST: 51,\n RANDOMPRIMEREQUEST: 52,\n SCRYPTREQUEST: 53,\n SIGNREQUEST: 54,\n TLSWRAP: 55,\n VERIFYREQUEST: 56,\n INSPECTORJSBINDING: 57\n};\n$ = {\n AsyncLocalStorage,\n createHook,\n executionAsyncId,\n triggerAsyncId,\n executionAsyncResource,\n asyncWrapProviders,\n AsyncResource\n};\nreturn $})\n"_s;
//
//
@@ -190,7 +190,7 @@ static constexpr ASCIILiteral NodeTraceEventsCode = "(function (){\"use strict\"
//
//
-static constexpr ASCIILiteral NodeTtyCode = "(function (){\"use strict\";// src/js/out/tmp/node/tty.ts\nvar ReadStream = function(fd) {\n if (!(this instanceof ReadStream))\n return new ReadStream(fd);\n if (fd >> 0 !== fd || fd < 0)\n @throwRangeError(\"fd must be a positive integer\");\n const stream = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).ReadStream.call(this, \"\", {\n fd\n });\n return stream.isRaw = !1, stream.isTTY = isatty(stream.fd), stream;\n}, warnOnDeactivatedColors = function(env) {\n if (warned)\n return;\n let name = \"\";\n if (env.NODE_DISABLE_COLORS !== @undefined)\n name = \"NODE_DISABLE_COLORS\";\n if (env.NO_COLOR !== @undefined) {\n if (name !== \"\")\n name += \"' and '\";\n name += \"NO_COLOR\";\n }\n if (name !== \"\")\n process.emitWarning(`The '${name}' env is ignored due to the 'FORCE_COLOR' env being set.`, \"Warning\"), warned = !0;\n}, WriteStream = function(fd) {\n if (!(this instanceof WriteStream))\n return new WriteStream(fd);\n if (fd >> 0 !== fd || fd < 0)\n @throwRangeError(\"fd must be a positive integer\");\n const stream = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).WriteStream.call(this, \"\", {\n fd\n });\n if (stream.columns = @undefined, stream.rows = @undefined, stream.isTTY = isatty(stream.fd), stream.isTTY) {\n const windowSizeArray = [0, 0];\n if (_getWindowSize(fd, windowSizeArray) === !0)\n stream.columns = windowSizeArray[0], stream.rows = windowSizeArray[1];\n }\n return stream;\n}, { ttySetMode, isatty, getWindowSize: _getWindowSize } = @lazy(\"tty\"), StringPrototypeSplit = Function.prototype.call.bind(@String.prototype.split), RegExpPrototypeExec = Function.prototype.call.bind(@RegExp.prototype.exec), StringPrototypeToLowerCase = Function.prototype.call.bind(@String.prototype.toLowerCase), ArrayPrototypeSome = Function.prototype.call.bind(@Array.prototype.some), NumberIsInteger = Number.isInteger;\nObject.defineProperty(ReadStream, \"prototype\", {\n get() {\n const Real = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).ReadStream.prototype;\n return Object.defineProperty(ReadStream, \"prototype\", { value: Real }), ReadStream.prototype.setRawMode = function(flag) {\n const mode = flag \? 1 : 0, err = ttySetMode(this.fd, mode);\n if (err)\n return this.emit(\"error\", new Error(\"setRawMode failed with errno:\", err)), this;\n return this.isRaw = flag, this;\n }, Real;\n },\n enumerable: !0,\n configurable: !0\n});\nvar COLORS_2 = 1, COLORS_16 = 4, COLORS_256 = 8, COLORS_16m = 24, TERM_ENVS = {\n eterm: COLORS_16,\n cons25: COLORS_16,\n console: COLORS_16,\n cygwin: COLORS_16,\n dtterm: COLORS_16,\n gnome: COLORS_16,\n hurd: COLORS_16,\n jfbterm: COLORS_16,\n konsole: COLORS_16,\n kterm: COLORS_16,\n mlterm: COLORS_16,\n mosh: COLORS_16m,\n putty: COLORS_16,\n st: COLORS_16,\n \"rxvt-unicode-24bit\": COLORS_16m,\n terminator: COLORS_16m\n}, TERM_ENVS_REG_EXP = [/ansi/, /color/, /linux/, /^con[0-9]*x[0-9]/, /^rxvt/, /^screen/, /^xterm/, /^vt100/], warned = !1;\nObject.defineProperty(WriteStream, \"prototype\", {\n get() {\n const Real = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).WriteStream.prototype;\n Object.defineProperty(WriteStream, \"prototype\", { value: Real }), WriteStream.prototype._refreshSize = function() {\n const oldCols = this.columns, oldRows = this.rows, windowSizeArray = [0, 0];\n if (_getWindowSize(this.fd, windowSizeArray) === !0) {\n if (oldCols !== windowSizeArray[0] || oldRows !== windowSizeArray[1])\n this.columns = windowSizeArray[0], this.rows = windowSizeArray[1], this.emit(\"resize\");\n }\n };\n var readline = @undefined;\n return WriteStream.prototype.clearLine = function(dir, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).clearLine(this, dir, cb);\n }, WriteStream.prototype.clearScreenDown = function(cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).clearScreenDown(this, cb);\n }, WriteStream.prototype.cursorTo = function(x, y, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).cursorTo(this, x, y, cb);\n }, WriteStream.prototype.getColorDepth = function(env = process.env) {\n if (env.FORCE_COLOR !== @undefined)\n switch (env.FORCE_COLOR) {\n case \"\":\n case \"1\":\n case \"true\":\n return warnOnDeactivatedColors(env), COLORS_16;\n case \"2\":\n return warnOnDeactivatedColors(env), COLORS_256;\n case \"3\":\n return warnOnDeactivatedColors(env), COLORS_16m;\n default:\n return COLORS_2;\n }\n if (env.NODE_DISABLE_COLORS !== @undefined || env.NO_COLOR !== @undefined || env.TERM === \"dumb\")\n return COLORS_2;\n if (env.TMUX)\n return COLORS_256;\n if (env.CI) {\n if ([\"APPVEYOR\", \"BUILDKITE\", \"CIRCLECI\", \"DRONE\", \"GITHUB_ACTIONS\", \"GITLAB_CI\", \"TRAVIS\"].some((sign) => (sign in env)) || env.CI_NAME === \"codeship\")\n return COLORS_256;\n return COLORS_2;\n }\n if (\"TEAMCITY_VERSION\" in env)\n return /^(9\\.(0*[1-9]\\d*)\\.|\\d{2,}\\.)/.test(env.TEAMCITY_VERSION) \? COLORS_16 : COLORS_2;\n switch (env.TERM_PROGRAM) {\n case \"iTerm.app\":\n if (!env.TERM_PROGRAM_VERSION || /^[0-2]\\./.test(env.TERM_PROGRAM_VERSION))\n return COLORS_256;\n return COLORS_16m;\n case \"HyperTerm\":\n case \"MacTerm\":\n return COLORS_16m;\n case \"Apple_Terminal\":\n return COLORS_256;\n }\n if (env.COLORTERM === \"truecolor\" || env.COLORTERM === \"24bit\")\n return COLORS_16m;\n if (env.TERM) {\n if (/^xterm-256/.test(env.TERM) !== null)\n return COLORS_256;\n const termEnv = env.TERM.toLowerCase();\n if (TERM_ENVS[termEnv])\n return TERM_ENVS[termEnv];\n if (TERM_ENVS_REG_EXP.some((term) => term.test(termEnv)))\n return COLORS_16;\n }\n if (env.COLORTERM)\n return COLORS_16;\n return COLORS_2;\n }, WriteStream.prototype.getWindowSize = function() {\n return [this.columns, this.rows];\n }, WriteStream.prototype.hasColors = function(count, env) {\n if (env === @undefined && (count === @undefined || typeof count === \"object\" && count !== null))\n env = count, count = 16;\n else\n validateInteger(count, \"count\", 2);\n return count <= 2 ** this.getColorDepth(env);\n }, WriteStream.prototype.moveCursor = function(dx, dy, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).moveCursor(this, dx, dy, cb);\n }, Real;\n },\n enumerable: !0,\n configurable: !0\n});\nvar validateInteger = (value, name, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) => {\n if (typeof value !== \"number\")\n throw new ERR_INVALID_ARG_TYPE(name, \"number\", value);\n if (!NumberIsInteger(value))\n throw new ERR_OUT_OF_RANGE(name, \"an integer\", value);\n if (value < min || value > max)\n throw new ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value);\n};\nreturn { ReadStream, WriteStream, isatty }})\n"_s;
+static constexpr ASCIILiteral NodeTtyCode = "(function (){\"use strict\";// src/js/out/tmp/node/tty.ts\nvar ReadStream = function(fd) {\n if (!(this instanceof ReadStream))\n return new ReadStream(fd);\n if (fd >> 0 !== fd || fd < 0)\n @throwRangeError(\"fd must be a positive integer\");\n const stream = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).ReadStream.call(this, \"\", {\n fd\n });\n return Object.setPrototypeOf(stream, ReadStream.prototype), stream.isRaw = !1, stream.isTTY = !0, stream;\n}, warnOnDeactivatedColors = function(env) {\n if (warned)\n return;\n let name = \"\";\n if (env.NODE_DISABLE_COLORS !== @undefined)\n name = \"NODE_DISABLE_COLORS\";\n if (env.NO_COLOR !== @undefined) {\n if (name !== \"\")\n name += \"' and '\";\n name += \"NO_COLOR\";\n }\n if (name !== \"\")\n process.emitWarning(`The '${name}' env is ignored due to the 'FORCE_COLOR' env being set.`, \"Warning\"), warned = !0;\n}, WriteStream = function(fd) {\n if (!(this instanceof WriteStream))\n return new WriteStream(fd);\n if (fd >> 0 !== fd || fd < 0)\n @throwRangeError(\"fd must be a positive integer\");\n const stream = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).WriteStream.call(this, \"\", {\n fd\n });\n if (stream.columns = @undefined, stream.rows = @undefined, stream.isTTY = isatty(stream.fd), stream.isTTY) {\n const windowSizeArray = [0, 0];\n if (_getWindowSize(fd, windowSizeArray) === !0)\n stream.columns = windowSizeArray[0], stream.rows = windowSizeArray[1];\n }\n return stream;\n}, { ttySetMode, isatty, getWindowSize: _getWindowSize } = @lazy(\"tty\"), StringPrototypeSplit = Function.prototype.call.bind(@String.prototype.split), NumberIsInteger = Number.isInteger;\nObject.defineProperty(ReadStream, \"prototype\", {\n get() {\n const Prototype = Object.create((@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).ReadStream.prototype);\n return Prototype.setRawMode = function(flag) {\n const mode = flag \? 1 : 0, err = ttySetMode(this.fd, mode);\n if (err)\n return this.emit(\"error\", new Error(\"setRawMode failed with errno: \" + err)), this;\n return this.isRaw = flag, this;\n }, Object.defineProperty(ReadStream, \"prototype\", { value: Prototype }), Prototype;\n },\n enumerable: !0,\n configurable: !0\n});\nvar COLORS_2 = 1, COLORS_16 = 4, COLORS_256 = 8, COLORS_16m = 24, TERM_ENVS = {\n eterm: COLORS_16,\n cons25: COLORS_16,\n console: COLORS_16,\n cygwin: COLORS_16,\n dtterm: COLORS_16,\n gnome: COLORS_16,\n hurd: COLORS_16,\n jfbterm: COLORS_16,\n konsole: COLORS_16,\n kterm: COLORS_16,\n mlterm: COLORS_16,\n mosh: COLORS_16m,\n putty: COLORS_16,\n st: COLORS_16,\n \"rxvt-unicode-24bit\": COLORS_16m,\n terminator: COLORS_16m\n}, TERM_ENVS_REG_EXP = [/ansi/, /color/, /linux/, /^con[0-9]*x[0-9]/, /^rxvt/, /^screen/, /^xterm/, /^vt100/], warned = !1;\nObject.defineProperty(WriteStream, \"prototype\", {\n get() {\n const Real = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).WriteStream.prototype;\n Object.defineProperty(WriteStream, \"prototype\", { value: Real }), WriteStream.prototype._refreshSize = function() {\n const oldCols = this.columns, oldRows = this.rows, windowSizeArray = [0, 0];\n if (_getWindowSize(this.fd, windowSizeArray) === !0) {\n if (oldCols !== windowSizeArray[0] || oldRows !== windowSizeArray[1])\n this.columns = windowSizeArray[0], this.rows = windowSizeArray[1], this.emit(\"resize\");\n }\n };\n var readline = @undefined;\n return WriteStream.prototype.clearLine = function(dir, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).clearLine(this, dir, cb);\n }, WriteStream.prototype.clearScreenDown = function(cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).clearScreenDown(this, cb);\n }, WriteStream.prototype.cursorTo = function(x, y, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).cursorTo(this, x, y, cb);\n }, WriteStream.prototype.getColorDepth = function(env = process.env) {\n if (env.FORCE_COLOR !== @undefined)\n switch (env.FORCE_COLOR) {\n case \"\":\n case \"1\":\n case \"true\":\n return warnOnDeactivatedColors(env), COLORS_16;\n case \"2\":\n return warnOnDeactivatedColors(env), COLORS_256;\n case \"3\":\n return warnOnDeactivatedColors(env), COLORS_16m;\n default:\n return COLORS_2;\n }\n if (env.NODE_DISABLE_COLORS !== @undefined || env.NO_COLOR !== @undefined || env.TERM === \"dumb\")\n return COLORS_2;\n if (env.TMUX)\n return COLORS_256;\n if (env.CI) {\n if ([\"APPVEYOR\", \"BUILDKITE\", \"CIRCLECI\", \"DRONE\", \"GITHUB_ACTIONS\", \"GITLAB_CI\", \"TRAVIS\"].some((sign) => (sign in env)) || env.CI_NAME === \"codeship\")\n return COLORS_256;\n return COLORS_2;\n }\n if (\"TEAMCITY_VERSION\" in env)\n return /^(9\\.(0*[1-9]\\d*)\\.|\\d{2,}\\.)/.test(env.TEAMCITY_VERSION) \? COLORS_16 : COLORS_2;\n switch (env.TERM_PROGRAM) {\n case \"iTerm.app\":\n if (!env.TERM_PROGRAM_VERSION || /^[0-2]\\./.test(env.TERM_PROGRAM_VERSION))\n return COLORS_256;\n return COLORS_16m;\n case \"HyperTerm\":\n case \"MacTerm\":\n return COLORS_16m;\n case \"Apple_Terminal\":\n return COLORS_256;\n }\n if (env.COLORTERM === \"truecolor\" || env.COLORTERM === \"24bit\")\n return COLORS_16m;\n if (env.TERM) {\n if (/^xterm-256/.test(env.TERM) !== null)\n return COLORS_256;\n const termEnv = env.TERM.toLowerCase();\n if (TERM_ENVS[termEnv])\n return TERM_ENVS[termEnv];\n if (TERM_ENVS_REG_EXP.some((term) => term.test(termEnv)))\n return COLORS_16;\n }\n if (env.COLORTERM)\n return COLORS_16;\n return COLORS_2;\n }, WriteStream.prototype.getWindowSize = function() {\n return [this.columns, this.rows];\n }, WriteStream.prototype.hasColors = function(count, env) {\n if (env === @undefined && (count === @undefined || typeof count === \"object\" && count !== null))\n env = count, count = 16;\n else\n validateInteger(count, \"count\", 2);\n return count <= 2 ** this.getColorDepth(env);\n }, WriteStream.prototype.moveCursor = function(dx, dy, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).moveCursor(this, dx, dy, cb);\n }, Real;\n },\n enumerable: !0,\n configurable: !0\n});\nvar validateInteger = (value, name, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) => {\n if (typeof value !== \"number\")\n throw new ERR_INVALID_ARG_TYPE(name, \"number\", value);\n if (!NumberIsInteger(value))\n throw new ERR_OUT_OF_RANGE(name, \"an integer\", value);\n if (value < min || value > max)\n throw new ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value);\n};\nreturn { ReadStream, WriteStream, isatty }})\n"_s;
//
//
@@ -295,7 +295,7 @@ static constexpr ASCIILiteral NodeAssertStrictCode = "(function (){\"use strict\
//
//
-static constexpr ASCIILiteral NodeAsyncHooksCode = "(function (){\"use strict\";// src/js/out/tmp/node/async_hooks.ts\nvar get = function() {\n return @getInternalField(@asyncContext, 0);\n}, set = function(contextValue) {\n return @putInternalField(@asyncContext, 0, contextValue);\n}, createWarning = function(message) {\n let warned = !1;\n var wrapped = function() {\n if (warned)\n return;\n if (new Error().stack.includes(\"zx/build/core.js\"))\n return;\n warned = !0, console.warn(\"[bun] Warning:\", message);\n };\n return wrapped;\n}, createHook = function(callbacks) {\n return {\n enable: createHookNotImpl,\n disable: createHookNotImpl\n };\n}, executionAsyncId = function() {\n return executionAsyncIdNotImpl(), 0;\n}, triggerAsyncId = function() {\n return 0;\n}, executionAsyncResource = function() {\n return executionAsyncResourceWarning(), process.stdin;\n}, $, { cleanupLater, setAsyncHooksEnabled } = @lazy(\"async_hooks\");\n\nclass AsyncLocalStorage {\n #disableCalled = !1;\n constructor() {\n setAsyncHooksEnabled(!0);\n }\n static bind(fn, ...args) {\n return this.snapshot().bind(null, fn, ...args);\n }\n static snapshot() {\n var context = get();\n return (fn, ...args) => {\n var prev = get();\n set(context);\n try {\n return fn(...args);\n } catch (error) {\n throw error;\n } finally {\n set(prev);\n }\n };\n }\n enterWith(store) {\n cleanupLater();\n var context = get();\n if (!context) {\n set([this, store]);\n return;\n }\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this) {\n const clone = context.slice();\n clone[i + 1] = store, set(clone);\n return;\n }\n set(context.concat(this, store));\n }\n exit(cb, ...args) {\n return this.run(@undefined, cb, ...args);\n }\n run(store, callback, ...args) {\n var context = get(), hasPrevious = !1, previous, i = 0, contextWasInit = !context;\n if (contextWasInit)\n set(context = [this, store]);\n else {\n if (context = context.slice(), i = context.indexOf(this), i > -1)\n hasPrevious = !0, previous = context[i + 1], context[i + 1] = store;\n else\n context.push(this, store);\n set(context);\n }\n try {\n return callback(...args);\n } catch (e) {\n throw e;\n } finally {\n if (!this.#disableCalled) {\n var context2 = get();\n if (context2 === context && contextWasInit)\n set(@undefined);\n else if (context2 = context2.slice(), hasPrevious)\n context2[i + 1] = previous, set(context2);\n else\n context2.splice(i, 2), set(context2.length \? context2 : @undefined);\n }\n }\n }\n disable() {\n if (!this.#disableCalled) {\n var context = get();\n if (context) {\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this) {\n context.splice(i, 2), set(context.length \? context : @undefined);\n break;\n }\n }\n this.#disableCalled = !0;\n }\n }\n getStore() {\n var context = get();\n if (!context)\n return;\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this)\n return context[i + 1];\n }\n}\n\nclass AsyncResource {\n type;\n #snapshot;\n constructor(type, options) {\n if (typeof type !== \"string\")\n @throwTypeError('The \"type\" argument must be of type string. Received type ' + typeof type);\n setAsyncHooksEnabled(!0), this.type = type, this.#snapshot = get();\n }\n emitBefore() {\n return !0;\n }\n emitAfter() {\n return !0;\n }\n asyncId() {\n return 0;\n }\n triggerAsyncId() {\n return 0;\n }\n emitDestroy() {\n }\n runInAsyncScope(fn, thisArg, ...args) {\n var prev = get();\n set(this.#snapshot);\n try {\n return fn.apply(thisArg, args);\n } catch (error) {\n throw error;\n } finally {\n set(prev);\n }\n }\n}\nvar createHookNotImpl = createWarning(\"async_hooks.createHook is not implemented in Bun. Hooks can still be created but will never be called.\"), executionAsyncIdNotImpl = createWarning(\"async_hooks.executionAsyncId/triggerAsyncId are not implemented in Bun. It will return 0 every time.\"), executionAsyncResourceWarning = createWarning(\"async_hooks.executionAsyncResource is not implemented in Bun. It returns a reference to process.stdin every time.\"), asyncWrapProviders = {\n NONE: 0,\n DIRHANDLE: 1,\n DNSCHANNEL: 2,\n ELDHISTOGRAM: 3,\n FILEHANDLE: 4,\n FILEHANDLECLOSEREQ: 5,\n FIXEDSIZEBLOBCOPY: 6,\n FSEVENTWRAP: 7,\n FSREQCALLBACK: 8,\n FSREQPROMISE: 9,\n GETADDRINFOREQWRAP: 10,\n GETNAMEINFOREQWRAP: 11,\n HEAPSNAPSHOT: 12,\n HTTP2SESSION: 13,\n HTTP2STREAM: 14,\n HTTP2PING: 15,\n HTTP2SETTINGS: 16,\n HTTPINCOMINGMESSAGE: 17,\n HTTPCLIENTREQUEST: 18,\n JSSTREAM: 19,\n JSUDPWRAP: 20,\n MESSAGEPORT: 21,\n PIPECONNECTWRAP: 22,\n PIPESERVERWRAP: 23,\n PIPEWRAP: 24,\n PROCESSWRAP: 25,\n PROMISE: 26,\n QUERYWRAP: 27,\n SHUTDOWNWRAP: 28,\n SIGNALWRAP: 29,\n STATWATCHER: 30,\n STREAMPIPE: 31,\n TCPCONNECTWRAP: 32,\n TCPSERVERWRAP: 33,\n TCPWRAP: 34,\n TTYWRAP: 35,\n UDPSENDWRAP: 36,\n UDPWRAP: 37,\n SIGINTWATCHDOG: 38,\n WORKER: 39,\n WORKERHEAPSNAPSHOT: 40,\n WRITEWRAP: 41,\n ZLIB: 42,\n CHECKPRIMEREQUEST: 43,\n PBKDF2REQUEST: 44,\n KEYPAIRGENREQUEST: 45,\n KEYGENREQUEST: 46,\n KEYEXPORTREQUEST: 47,\n CIPHERREQUEST: 48,\n DERIVEBITSREQUEST: 49,\n HASHREQUEST: 50,\n RANDOMBYTESREQUEST: 51,\n RANDOMPRIMEREQUEST: 52,\n SCRYPTREQUEST: 53,\n SIGNREQUEST: 54,\n TLSWRAP: 55,\n VERIFYREQUEST: 56,\n INSPECTORJSBINDING: 57\n};\n$ = {\n AsyncLocalStorage,\n createHook,\n executionAsyncId,\n triggerAsyncId,\n executionAsyncResource,\n asyncWrapProviders,\n AsyncResource\n};\nreturn $})\n"_s;
+static constexpr ASCIILiteral NodeAsyncHooksCode = "(function (){\"use strict\";// src/js/out/tmp/node/async_hooks.ts\nvar get = function() {\n return @getInternalField(@asyncContext, 0);\n}, set = function(contextValue) {\n return @putInternalField(@asyncContext, 0, contextValue);\n}, createWarning = function(message) {\n let warned = !1;\n var wrapped = function() {\n if (warned)\n return;\n if (new Error().stack.includes(\"zx/build/core.js\"))\n return;\n warned = !0, console.warn(\"[bun] Warning:\", message);\n };\n return wrapped;\n}, createHook = function(callbacks) {\n return {\n enable: createHookNotImpl,\n disable: createHookNotImpl\n };\n}, executionAsyncId = function() {\n return executionAsyncIdNotImpl(), 0;\n}, triggerAsyncId = function() {\n return 0;\n}, executionAsyncResource = function() {\n return executionAsyncResourceWarning(), process.stdin;\n}, $, { cleanupLater, setAsyncHooksEnabled } = @lazy(\"async_hooks\");\n\nclass AsyncLocalStorage {\n #disableCalled = !1;\n constructor() {\n setAsyncHooksEnabled(!0);\n }\n static bind(fn, ...args) {\n return this.snapshot().bind(null, fn, ...args);\n }\n static snapshot() {\n var context = get();\n return (fn, ...args) => {\n var prev = get();\n set(context);\n try {\n return fn(...args);\n } catch (error) {\n throw error;\n } finally {\n set(prev);\n }\n };\n }\n enterWith(store) {\n cleanupLater();\n var context = get();\n if (!context) {\n set([this, store]);\n return;\n }\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this) {\n const clone = context.slice();\n clone[i + 1] = store, set(clone);\n return;\n }\n set(context.concat(this, store));\n }\n exit(cb, ...args) {\n return this.run(@undefined, cb, ...args);\n }\n run(store_value, callback, ...args) {\n var context = get(), hasPrevious = !1, previous_value, i = 0, contextWasAlreadyInit = !context;\n if (contextWasAlreadyInit)\n set(context = [this, store_value]);\n else {\n if (context = context.slice(), i = context.indexOf(this), i > -1)\n hasPrevious = !0, previous_value = context[i + 1], context[i + 1] = store_value;\n else\n i = context.length, context.push(this, store_value);\n set(context);\n }\n try {\n return callback(...args);\n } catch (e) {\n throw e;\n } finally {\n if (!this.#disableCalled) {\n var context2 = get();\n if (context2 === context && contextWasAlreadyInit)\n set(@undefined);\n else if (context2 = context2.slice(), hasPrevious)\n context2[i + 1] = previous_value, set(context2);\n else\n context2.splice(i, 2), set(context2.length \? context2 : @undefined);\n }\n }\n }\n disable() {\n if (!this.#disableCalled) {\n var context = get();\n if (context) {\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this) {\n context.splice(i, 2), set(context.length \? context : @undefined);\n break;\n }\n }\n this.#disableCalled = !0;\n }\n }\n getStore() {\n var context = get();\n if (!context)\n return;\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this)\n return context[i + 1];\n }\n}\n\nclass AsyncResource {\n type;\n #snapshot;\n constructor(type, options) {\n if (typeof type !== \"string\")\n @throwTypeError('The \"type\" argument must be of type string. Received type ' + typeof type);\n setAsyncHooksEnabled(!0), this.type = type, this.#snapshot = get();\n }\n emitBefore() {\n return !0;\n }\n emitAfter() {\n return !0;\n }\n asyncId() {\n return 0;\n }\n triggerAsyncId() {\n return 0;\n }\n emitDestroy() {\n }\n runInAsyncScope(fn, thisArg, ...args) {\n var prev = get();\n set(this.#snapshot);\n try {\n return fn.apply(thisArg, args);\n } catch (error) {\n throw error;\n } finally {\n set(prev);\n }\n }\n bind(fn, thisArg) {\n return this.runInAsyncScope.bind(this, fn, thisArg \?\? this);\n }\n static bind(fn, type, thisArg) {\n return type = type || fn.name, new AsyncResource(type || \"bound-anonymous-fn\").bind(fn, thisArg);\n }\n}\nvar createHookNotImpl = createWarning(\"async_hooks.createHook is not implemented in Bun. Hooks can still be created but will never be called.\"), executionAsyncIdNotImpl = createWarning(\"async_hooks.executionAsyncId/triggerAsyncId are not implemented in Bun. It will return 0 every time.\"), executionAsyncResourceWarning = createWarning(\"async_hooks.executionAsyncResource is not implemented in Bun. It returns a reference to process.stdin every time.\"), asyncWrapProviders = {\n NONE: 0,\n DIRHANDLE: 1,\n DNSCHANNEL: 2,\n ELDHISTOGRAM: 3,\n FILEHANDLE: 4,\n FILEHANDLECLOSEREQ: 5,\n FIXEDSIZEBLOBCOPY: 6,\n FSEVENTWRAP: 7,\n FSREQCALLBACK: 8,\n FSREQPROMISE: 9,\n GETADDRINFOREQWRAP: 10,\n GETNAMEINFOREQWRAP: 11,\n HEAPSNAPSHOT: 12,\n HTTP2SESSION: 13,\n HTTP2STREAM: 14,\n HTTP2PING: 15,\n HTTP2SETTINGS: 16,\n HTTPINCOMINGMESSAGE: 17,\n HTTPCLIENTREQUEST: 18,\n JSSTREAM: 19,\n JSUDPWRAP: 20,\n MESSAGEPORT: 21,\n PIPECONNECTWRAP: 22,\n PIPESERVERWRAP: 23,\n PIPEWRAP: 24,\n PROCESSWRAP: 25,\n PROMISE: 26,\n QUERYWRAP: 27,\n SHUTDOWNWRAP: 28,\n SIGNALWRAP: 29,\n STATWATCHER: 30,\n STREAMPIPE: 31,\n TCPCONNECTWRAP: 32,\n TCPSERVERWRAP: 33,\n TCPWRAP: 34,\n TTYWRAP: 35,\n UDPSENDWRAP: 36,\n UDPWRAP: 37,\n SIGINTWATCHDOG: 38,\n WORKER: 39,\n WORKERHEAPSNAPSHOT: 40,\n WRITEWRAP: 41,\n ZLIB: 42,\n CHECKPRIMEREQUEST: 43,\n PBKDF2REQUEST: 44,\n KEYPAIRGENREQUEST: 45,\n KEYGENREQUEST: 46,\n KEYEXPORTREQUEST: 47,\n CIPHERREQUEST: 48,\n DERIVEBITSREQUEST: 49,\n HASHREQUEST: 50,\n RANDOMBYTESREQUEST: 51,\n RANDOMPRIMEREQUEST: 52,\n SCRYPTREQUEST: 53,\n SIGNREQUEST: 54,\n TLSWRAP: 55,\n VERIFYREQUEST: 56,\n INSPECTORJSBINDING: 57\n};\n$ = {\n AsyncLocalStorage,\n createHook,\n executionAsyncId,\n triggerAsyncId,\n executionAsyncResource,\n asyncWrapProviders,\n AsyncResource\n};\nreturn $})\n"_s;
//
//
@@ -439,7 +439,7 @@ static constexpr ASCIILiteral NodeTraceEventsCode = "(function (){\"use strict\"
//
//
-static constexpr ASCIILiteral NodeTtyCode = "(function (){\"use strict\";// src/js/out/tmp/node/tty.ts\nvar ReadStream = function(fd) {\n if (!(this instanceof ReadStream))\n return new ReadStream(fd);\n if (fd >> 0 !== fd || fd < 0)\n @throwRangeError(\"fd must be a positive integer\");\n const stream = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).ReadStream.call(this, \"\", {\n fd\n });\n return stream.isRaw = !1, stream.isTTY = isatty(stream.fd), stream;\n}, warnOnDeactivatedColors = function(env) {\n if (warned)\n return;\n let name = \"\";\n if (env.NODE_DISABLE_COLORS !== @undefined)\n name = \"NODE_DISABLE_COLORS\";\n if (env.NO_COLOR !== @undefined) {\n if (name !== \"\")\n name += \"' and '\";\n name += \"NO_COLOR\";\n }\n if (name !== \"\")\n process.emitWarning(`The '${name}' env is ignored due to the 'FORCE_COLOR' env being set.`, \"Warning\"), warned = !0;\n}, WriteStream = function(fd) {\n if (!(this instanceof WriteStream))\n return new WriteStream(fd);\n if (fd >> 0 !== fd || fd < 0)\n @throwRangeError(\"fd must be a positive integer\");\n const stream = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).WriteStream.call(this, \"\", {\n fd\n });\n if (stream.columns = @undefined, stream.rows = @undefined, stream.isTTY = isatty(stream.fd), stream.isTTY) {\n const windowSizeArray = [0, 0];\n if (_getWindowSize(fd, windowSizeArray) === !0)\n stream.columns = windowSizeArray[0], stream.rows = windowSizeArray[1];\n }\n return stream;\n}, { ttySetMode, isatty, getWindowSize: _getWindowSize } = @lazy(\"tty\"), StringPrototypeSplit = Function.prototype.call.bind(@String.prototype.split), RegExpPrototypeExec = Function.prototype.call.bind(@RegExp.prototype.exec), StringPrototypeToLowerCase = Function.prototype.call.bind(@String.prototype.toLowerCase), ArrayPrototypeSome = Function.prototype.call.bind(@Array.prototype.some), NumberIsInteger = Number.isInteger;\nObject.defineProperty(ReadStream, \"prototype\", {\n get() {\n const Real = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).ReadStream.prototype;\n return Object.defineProperty(ReadStream, \"prototype\", { value: Real }), ReadStream.prototype.setRawMode = function(flag) {\n const mode = flag \? 1 : 0, err = ttySetMode(this.fd, mode);\n if (err)\n return this.emit(\"error\", new Error(\"setRawMode failed with errno:\", err)), this;\n return this.isRaw = flag, this;\n }, Real;\n },\n enumerable: !0,\n configurable: !0\n});\nvar OSRelease, COLORS_2 = 1, COLORS_16 = 4, COLORS_256 = 8, COLORS_16m = 24, TERM_ENVS = {\n eterm: COLORS_16,\n cons25: COLORS_16,\n console: COLORS_16,\n cygwin: COLORS_16,\n dtterm: COLORS_16,\n gnome: COLORS_16,\n hurd: COLORS_16,\n jfbterm: COLORS_16,\n konsole: COLORS_16,\n kterm: COLORS_16,\n mlterm: COLORS_16,\n mosh: COLORS_16m,\n putty: COLORS_16,\n st: COLORS_16,\n \"rxvt-unicode-24bit\": COLORS_16m,\n terminator: COLORS_16m\n}, TERM_ENVS_REG_EXP = [/ansi/, /color/, /linux/, /^con[0-9]*x[0-9]/, /^rxvt/, /^screen/, /^xterm/, /^vt100/], warned = !1;\nObject.defineProperty(WriteStream, \"prototype\", {\n get() {\n const Real = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).WriteStream.prototype;\n Object.defineProperty(WriteStream, \"prototype\", { value: Real }), WriteStream.prototype._refreshSize = function() {\n const oldCols = this.columns, oldRows = this.rows, windowSizeArray = [0, 0];\n if (_getWindowSize(this.fd, windowSizeArray) === !0) {\n if (oldCols !== windowSizeArray[0] || oldRows !== windowSizeArray[1])\n this.columns = windowSizeArray[0], this.rows = windowSizeArray[1], this.emit(\"resize\");\n }\n };\n var readline = @undefined;\n return WriteStream.prototype.clearLine = function(dir, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).clearLine(this, dir, cb);\n }, WriteStream.prototype.clearScreenDown = function(cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).clearScreenDown(this, cb);\n }, WriteStream.prototype.cursorTo = function(x, y, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).cursorTo(this, x, y, cb);\n }, WriteStream.prototype.getColorDepth = function(env = process.env) {\n if (env.FORCE_COLOR !== @undefined)\n switch (env.FORCE_COLOR) {\n case \"\":\n case \"1\":\n case \"true\":\n return warnOnDeactivatedColors(env), COLORS_16;\n case \"2\":\n return warnOnDeactivatedColors(env), COLORS_256;\n case \"3\":\n return warnOnDeactivatedColors(env), COLORS_16m;\n default:\n return COLORS_2;\n }\n if (env.NODE_DISABLE_COLORS !== @undefined || env.NO_COLOR !== @undefined || env.TERM === \"dumb\")\n return COLORS_2;\n if (OSRelease === @undefined) {\n const { release } = @getInternalField(@internalModuleRegistry, 28) || @createInternalModuleById(28);\n OSRelease = StringPrototypeSplit(release(), \".\");\n }\n if (+OSRelease[0] >= 10) {\n const build = +OSRelease[2];\n if (build >= 14931)\n return COLORS_16m;\n if (build >= 10586)\n return COLORS_256;\n }\n return COLORS_16;\n switch (env.TERM_PROGRAM) {\n case \"iTerm.app\":\n if (!env.TERM_PROGRAM_VERSION || /^[0-2]\\./.test(env.TERM_PROGRAM_VERSION))\n return COLORS_256;\n return COLORS_16m;\n case \"HyperTerm\":\n case \"MacTerm\":\n return COLORS_16m;\n case \"Apple_Terminal\":\n return COLORS_256;\n }\n }, WriteStream.prototype.getWindowSize = function() {\n return [this.columns, this.rows];\n }, WriteStream.prototype.hasColors = function(count, env) {\n if (env === @undefined && (count === @undefined || typeof count === \"object\" && count !== null))\n env = count, count = 16;\n else\n validateInteger(count, \"count\", 2);\n return count <= 2 ** this.getColorDepth(env);\n }, WriteStream.prototype.moveCursor = function(dx, dy, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).moveCursor(this, dx, dy, cb);\n }, Real;\n },\n enumerable: !0,\n configurable: !0\n});\nvar validateInteger = (value, name, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) => {\n if (typeof value !== \"number\")\n throw new ERR_INVALID_ARG_TYPE(name, \"number\", value);\n if (!NumberIsInteger(value))\n throw new ERR_OUT_OF_RANGE(name, \"an integer\", value);\n if (value < min || value > max)\n throw new ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value);\n};\nreturn { ReadStream, WriteStream, isatty }})\n"_s;
+static constexpr ASCIILiteral NodeTtyCode = "(function (){\"use strict\";// src/js/out/tmp/node/tty.ts\nvar ReadStream = function(fd) {\n if (!(this instanceof ReadStream))\n return new ReadStream(fd);\n if (fd >> 0 !== fd || fd < 0)\n @throwRangeError(\"fd must be a positive integer\");\n const stream = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).ReadStream.call(this, \"\", {\n fd\n });\n return Object.setPrototypeOf(stream, ReadStream.prototype), stream.isRaw = !1, stream.isTTY = !0, stream;\n}, warnOnDeactivatedColors = function(env) {\n if (warned)\n return;\n let name = \"\";\n if (env.NODE_DISABLE_COLORS !== @undefined)\n name = \"NODE_DISABLE_COLORS\";\n if (env.NO_COLOR !== @undefined) {\n if (name !== \"\")\n name += \"' and '\";\n name += \"NO_COLOR\";\n }\n if (name !== \"\")\n process.emitWarning(`The '${name}' env is ignored due to the 'FORCE_COLOR' env being set.`, \"Warning\"), warned = !0;\n}, WriteStream = function(fd) {\n if (!(this instanceof WriteStream))\n return new WriteStream(fd);\n if (fd >> 0 !== fd || fd < 0)\n @throwRangeError(\"fd must be a positive integer\");\n const stream = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).WriteStream.call(this, \"\", {\n fd\n });\n if (stream.columns = @undefined, stream.rows = @undefined, stream.isTTY = isatty(stream.fd), stream.isTTY) {\n const windowSizeArray = [0, 0];\n if (_getWindowSize(fd, windowSizeArray) === !0)\n stream.columns = windowSizeArray[0], stream.rows = windowSizeArray[1];\n }\n return stream;\n}, { ttySetMode, isatty, getWindowSize: _getWindowSize } = @lazy(\"tty\"), StringPrototypeSplit = Function.prototype.call.bind(@String.prototype.split), NumberIsInteger = Number.isInteger;\nObject.defineProperty(ReadStream, \"prototype\", {\n get() {\n const Prototype = Object.create((@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).ReadStream.prototype);\n return Prototype.setRawMode = function(flag) {\n const mode = flag \? 1 : 0, err = ttySetMode(this.fd, mode);\n if (err)\n return this.emit(\"error\", new Error(\"setRawMode failed with errno: \" + err)), this;\n return this.isRaw = flag, this;\n }, Object.defineProperty(ReadStream, \"prototype\", { value: Prototype }), Prototype;\n },\n enumerable: !0,\n configurable: !0\n});\nvar OSRelease, COLORS_2 = 1, COLORS_16 = 4, COLORS_256 = 8, COLORS_16m = 24, TERM_ENVS = {\n eterm: COLORS_16,\n cons25: COLORS_16,\n console: COLORS_16,\n cygwin: COLORS_16,\n dtterm: COLORS_16,\n gnome: COLORS_16,\n hurd: COLORS_16,\n jfbterm: COLORS_16,\n konsole: COLORS_16,\n kterm: COLORS_16,\n mlterm: COLORS_16,\n mosh: COLORS_16m,\n putty: COLORS_16,\n st: COLORS_16,\n \"rxvt-unicode-24bit\": COLORS_16m,\n terminator: COLORS_16m\n}, TERM_ENVS_REG_EXP = [/ansi/, /color/, /linux/, /^con[0-9]*x[0-9]/, /^rxvt/, /^screen/, /^xterm/, /^vt100/], warned = !1;\nObject.defineProperty(WriteStream, \"prototype\", {\n get() {\n const Real = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).WriteStream.prototype;\n Object.defineProperty(WriteStream, \"prototype\", { value: Real }), WriteStream.prototype._refreshSize = function() {\n const oldCols = this.columns, oldRows = this.rows, windowSizeArray = [0, 0];\n if (_getWindowSize(this.fd, windowSizeArray) === !0) {\n if (oldCols !== windowSizeArray[0] || oldRows !== windowSizeArray[1])\n this.columns = windowSizeArray[0], this.rows = windowSizeArray[1], this.emit(\"resize\");\n }\n };\n var readline = @undefined;\n return WriteStream.prototype.clearLine = function(dir, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).clearLine(this, dir, cb);\n }, WriteStream.prototype.clearScreenDown = function(cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).clearScreenDown(this, cb);\n }, WriteStream.prototype.cursorTo = function(x, y, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).cursorTo(this, x, y, cb);\n }, WriteStream.prototype.getColorDepth = function(env = process.env) {\n if (env.FORCE_COLOR !== @undefined)\n switch (env.FORCE_COLOR) {\n case \"\":\n case \"1\":\n case \"true\":\n return warnOnDeactivatedColors(env), COLORS_16;\n case \"2\":\n return warnOnDeactivatedColors(env), COLORS_256;\n case \"3\":\n return warnOnDeactivatedColors(env), COLORS_16m;\n default:\n return COLORS_2;\n }\n if (env.NODE_DISABLE_COLORS !== @undefined || env.NO_COLOR !== @undefined || env.TERM === \"dumb\")\n return COLORS_2;\n if (OSRelease === @undefined) {\n const { release } = @getInternalField(@internalModuleRegistry, 28) || @createInternalModuleById(28);\n OSRelease = StringPrototypeSplit(release(), \".\");\n }\n if (+OSRelease[0] >= 10) {\n const build = +OSRelease[2];\n if (build >= 14931)\n return COLORS_16m;\n if (build >= 10586)\n return COLORS_256;\n }\n return COLORS_16;\n switch (env.TERM_PROGRAM) {\n case \"iTerm.app\":\n if (!env.TERM_PROGRAM_VERSION || /^[0-2]\\./.test(env.TERM_PROGRAM_VERSION))\n return COLORS_256;\n return COLORS_16m;\n case \"HyperTerm\":\n case \"MacTerm\":\n return COLORS_16m;\n case \"Apple_Terminal\":\n return COLORS_256;\n }\n }, WriteStream.prototype.getWindowSize = function() {\n return [this.columns, this.rows];\n }, WriteStream.prototype.hasColors = function(count, env) {\n if (env === @undefined && (count === @undefined || typeof count === \"object\" && count !== null))\n env = count, count = 16;\n else\n validateInteger(count, \"count\", 2);\n return count <= 2 ** this.getColorDepth(env);\n }, WriteStream.prototype.moveCursor = function(dx, dy, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).moveCursor(this, dx, dy, cb);\n }, Real;\n },\n enumerable: !0,\n configurable: !0\n});\nvar validateInteger = (value, name, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) => {\n if (typeof value !== \"number\")\n throw new ERR_INVALID_ARG_TYPE(name, \"number\", value);\n if (!NumberIsInteger(value))\n throw new ERR_OUT_OF_RANGE(name, \"an integer\", value);\n if (value < min || value > max)\n throw new ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value);\n};\nreturn { ReadStream, WriteStream, isatty }})\n"_s;
//
//
@@ -545,7 +545,7 @@ static constexpr ASCIILiteral NodeAssertStrictCode = "(function (){\"use strict\
//
//
-static constexpr ASCIILiteral NodeAsyncHooksCode = "(function (){\"use strict\";// src/js/out/tmp/node/async_hooks.ts\nvar get = function() {\n return @getInternalField(@asyncContext, 0);\n}, set = function(contextValue) {\n return @putInternalField(@asyncContext, 0, contextValue);\n}, createWarning = function(message) {\n let warned = !1;\n var wrapped = function() {\n if (warned)\n return;\n if (new Error().stack.includes(\"zx/build/core.js\"))\n return;\n warned = !0, console.warn(\"[bun] Warning:\", message);\n };\n return wrapped;\n}, createHook = function(callbacks) {\n return {\n enable: createHookNotImpl,\n disable: createHookNotImpl\n };\n}, executionAsyncId = function() {\n return executionAsyncIdNotImpl(), 0;\n}, triggerAsyncId = function() {\n return 0;\n}, executionAsyncResource = function() {\n return executionAsyncResourceWarning(), process.stdin;\n}, $, { cleanupLater, setAsyncHooksEnabled } = @lazy(\"async_hooks\");\n\nclass AsyncLocalStorage {\n #disableCalled = !1;\n constructor() {\n setAsyncHooksEnabled(!0);\n }\n static bind(fn, ...args) {\n return this.snapshot().bind(null, fn, ...args);\n }\n static snapshot() {\n var context = get();\n return (fn, ...args) => {\n var prev = get();\n set(context);\n try {\n return fn(...args);\n } catch (error) {\n throw error;\n } finally {\n set(prev);\n }\n };\n }\n enterWith(store) {\n cleanupLater();\n var context = get();\n if (!context) {\n set([this, store]);\n return;\n }\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this) {\n const clone = context.slice();\n clone[i + 1] = store, set(clone);\n return;\n }\n set(context.concat(this, store));\n }\n exit(cb, ...args) {\n return this.run(@undefined, cb, ...args);\n }\n run(store, callback, ...args) {\n var context = get(), hasPrevious = !1, previous, i = 0, contextWasInit = !context;\n if (contextWasInit)\n set(context = [this, store]);\n else {\n if (context = context.slice(), i = context.indexOf(this), i > -1)\n hasPrevious = !0, previous = context[i + 1], context[i + 1] = store;\n else\n context.push(this, store);\n set(context);\n }\n try {\n return callback(...args);\n } catch (e) {\n throw e;\n } finally {\n if (!this.#disableCalled) {\n var context2 = get();\n if (context2 === context && contextWasInit)\n set(@undefined);\n else if (context2 = context2.slice(), hasPrevious)\n context2[i + 1] = previous, set(context2);\n else\n context2.splice(i, 2), set(context2.length \? context2 : @undefined);\n }\n }\n }\n disable() {\n if (!this.#disableCalled) {\n var context = get();\n if (context) {\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this) {\n context.splice(i, 2), set(context.length \? context : @undefined);\n break;\n }\n }\n this.#disableCalled = !0;\n }\n }\n getStore() {\n var context = get();\n if (!context)\n return;\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this)\n return context[i + 1];\n }\n}\n\nclass AsyncResource {\n type;\n #snapshot;\n constructor(type, options) {\n if (typeof type !== \"string\")\n @throwTypeError('The \"type\" argument must be of type string. Received type ' + typeof type);\n setAsyncHooksEnabled(!0), this.type = type, this.#snapshot = get();\n }\n emitBefore() {\n return !0;\n }\n emitAfter() {\n return !0;\n }\n asyncId() {\n return 0;\n }\n triggerAsyncId() {\n return 0;\n }\n emitDestroy() {\n }\n runInAsyncScope(fn, thisArg, ...args) {\n var prev = get();\n set(this.#snapshot);\n try {\n return fn.apply(thisArg, args);\n } catch (error) {\n throw error;\n } finally {\n set(prev);\n }\n }\n}\nvar createHookNotImpl = createWarning(\"async_hooks.createHook is not implemented in Bun. Hooks can still be created but will never be called.\"), executionAsyncIdNotImpl = createWarning(\"async_hooks.executionAsyncId/triggerAsyncId are not implemented in Bun. It will return 0 every time.\"), executionAsyncResourceWarning = createWarning(\"async_hooks.executionAsyncResource is not implemented in Bun. It returns a reference to process.stdin every time.\"), asyncWrapProviders = {\n NONE: 0,\n DIRHANDLE: 1,\n DNSCHANNEL: 2,\n ELDHISTOGRAM: 3,\n FILEHANDLE: 4,\n FILEHANDLECLOSEREQ: 5,\n FIXEDSIZEBLOBCOPY: 6,\n FSEVENTWRAP: 7,\n FSREQCALLBACK: 8,\n FSREQPROMISE: 9,\n GETADDRINFOREQWRAP: 10,\n GETNAMEINFOREQWRAP: 11,\n HEAPSNAPSHOT: 12,\n HTTP2SESSION: 13,\n HTTP2STREAM: 14,\n HTTP2PING: 15,\n HTTP2SETTINGS: 16,\n HTTPINCOMINGMESSAGE: 17,\n HTTPCLIENTREQUEST: 18,\n JSSTREAM: 19,\n JSUDPWRAP: 20,\n MESSAGEPORT: 21,\n PIPECONNECTWRAP: 22,\n PIPESERVERWRAP: 23,\n PIPEWRAP: 24,\n PROCESSWRAP: 25,\n PROMISE: 26,\n QUERYWRAP: 27,\n SHUTDOWNWRAP: 28,\n SIGNALWRAP: 29,\n STATWATCHER: 30,\n STREAMPIPE: 31,\n TCPCONNECTWRAP: 32,\n TCPSERVERWRAP: 33,\n TCPWRAP: 34,\n TTYWRAP: 35,\n UDPSENDWRAP: 36,\n UDPWRAP: 37,\n SIGINTWATCHDOG: 38,\n WORKER: 39,\n WORKERHEAPSNAPSHOT: 40,\n WRITEWRAP: 41,\n ZLIB: 42,\n CHECKPRIMEREQUEST: 43,\n PBKDF2REQUEST: 44,\n KEYPAIRGENREQUEST: 45,\n KEYGENREQUEST: 46,\n KEYEXPORTREQUEST: 47,\n CIPHERREQUEST: 48,\n DERIVEBITSREQUEST: 49,\n HASHREQUEST: 50,\n RANDOMBYTESREQUEST: 51,\n RANDOMPRIMEREQUEST: 52,\n SCRYPTREQUEST: 53,\n SIGNREQUEST: 54,\n TLSWRAP: 55,\n VERIFYREQUEST: 56,\n INSPECTORJSBINDING: 57\n};\n$ = {\n AsyncLocalStorage,\n createHook,\n executionAsyncId,\n triggerAsyncId,\n executionAsyncResource,\n asyncWrapProviders,\n AsyncResource\n};\nreturn $})\n"_s;
+static constexpr ASCIILiteral NodeAsyncHooksCode = "(function (){\"use strict\";// src/js/out/tmp/node/async_hooks.ts\nvar get = function() {\n return @getInternalField(@asyncContext, 0);\n}, set = function(contextValue) {\n return @putInternalField(@asyncContext, 0, contextValue);\n}, createWarning = function(message) {\n let warned = !1;\n var wrapped = function() {\n if (warned)\n return;\n if (new Error().stack.includes(\"zx/build/core.js\"))\n return;\n warned = !0, console.warn(\"[bun] Warning:\", message);\n };\n return wrapped;\n}, createHook = function(callbacks) {\n return {\n enable: createHookNotImpl,\n disable: createHookNotImpl\n };\n}, executionAsyncId = function() {\n return executionAsyncIdNotImpl(), 0;\n}, triggerAsyncId = function() {\n return 0;\n}, executionAsyncResource = function() {\n return executionAsyncResourceWarning(), process.stdin;\n}, $, { cleanupLater, setAsyncHooksEnabled } = @lazy(\"async_hooks\");\n\nclass AsyncLocalStorage {\n #disableCalled = !1;\n constructor() {\n setAsyncHooksEnabled(!0);\n }\n static bind(fn, ...args) {\n return this.snapshot().bind(null, fn, ...args);\n }\n static snapshot() {\n var context = get();\n return (fn, ...args) => {\n var prev = get();\n set(context);\n try {\n return fn(...args);\n } catch (error) {\n throw error;\n } finally {\n set(prev);\n }\n };\n }\n enterWith(store) {\n cleanupLater();\n var context = get();\n if (!context) {\n set([this, store]);\n return;\n }\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this) {\n const clone = context.slice();\n clone[i + 1] = store, set(clone);\n return;\n }\n set(context.concat(this, store));\n }\n exit(cb, ...args) {\n return this.run(@undefined, cb, ...args);\n }\n run(store_value, callback, ...args) {\n var context = get(), hasPrevious = !1, previous_value, i = 0, contextWasAlreadyInit = !context;\n if (contextWasAlreadyInit)\n set(context = [this, store_value]);\n else {\n if (context = context.slice(), i = context.indexOf(this), i > -1)\n hasPrevious = !0, previous_value = context[i + 1], context[i + 1] = store_value;\n else\n i = context.length, context.push(this, store_value);\n set(context);\n }\n try {\n return callback(...args);\n } catch (e) {\n throw e;\n } finally {\n if (!this.#disableCalled) {\n var context2 = get();\n if (context2 === context && contextWasAlreadyInit)\n set(@undefined);\n else if (context2 = context2.slice(), hasPrevious)\n context2[i + 1] = previous_value, set(context2);\n else\n context2.splice(i, 2), set(context2.length \? context2 : @undefined);\n }\n }\n }\n disable() {\n if (!this.#disableCalled) {\n var context = get();\n if (context) {\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this) {\n context.splice(i, 2), set(context.length \? context : @undefined);\n break;\n }\n }\n this.#disableCalled = !0;\n }\n }\n getStore() {\n var context = get();\n if (!context)\n return;\n var { length } = context;\n for (var i = 0;i < length; i += 2)\n if (context[i] === this)\n return context[i + 1];\n }\n}\n\nclass AsyncResource {\n type;\n #snapshot;\n constructor(type, options) {\n if (typeof type !== \"string\")\n @throwTypeError('The \"type\" argument must be of type string. Received type ' + typeof type);\n setAsyncHooksEnabled(!0), this.type = type, this.#snapshot = get();\n }\n emitBefore() {\n return !0;\n }\n emitAfter() {\n return !0;\n }\n asyncId() {\n return 0;\n }\n triggerAsyncId() {\n return 0;\n }\n emitDestroy() {\n }\n runInAsyncScope(fn, thisArg, ...args) {\n var prev = get();\n set(this.#snapshot);\n try {\n return fn.apply(thisArg, args);\n } catch (error) {\n throw error;\n } finally {\n set(prev);\n }\n }\n bind(fn, thisArg) {\n return this.runInAsyncScope.bind(this, fn, thisArg \?\? this);\n }\n static bind(fn, type, thisArg) {\n return type = type || fn.name, new AsyncResource(type || \"bound-anonymous-fn\").bind(fn, thisArg);\n }\n}\nvar createHookNotImpl = createWarning(\"async_hooks.createHook is not implemented in Bun. Hooks can still be created but will never be called.\"), executionAsyncIdNotImpl = createWarning(\"async_hooks.executionAsyncId/triggerAsyncId are not implemented in Bun. It will return 0 every time.\"), executionAsyncResourceWarning = createWarning(\"async_hooks.executionAsyncResource is not implemented in Bun. It returns a reference to process.stdin every time.\"), asyncWrapProviders = {\n NONE: 0,\n DIRHANDLE: 1,\n DNSCHANNEL: 2,\n ELDHISTOGRAM: 3,\n FILEHANDLE: 4,\n FILEHANDLECLOSEREQ: 5,\n FIXEDSIZEBLOBCOPY: 6,\n FSEVENTWRAP: 7,\n FSREQCALLBACK: 8,\n FSREQPROMISE: 9,\n GETADDRINFOREQWRAP: 10,\n GETNAMEINFOREQWRAP: 11,\n HEAPSNAPSHOT: 12,\n HTTP2SESSION: 13,\n HTTP2STREAM: 14,\n HTTP2PING: 15,\n HTTP2SETTINGS: 16,\n HTTPINCOMINGMESSAGE: 17,\n HTTPCLIENTREQUEST: 18,\n JSSTREAM: 19,\n JSUDPWRAP: 20,\n MESSAGEPORT: 21,\n PIPECONNECTWRAP: 22,\n PIPESERVERWRAP: 23,\n PIPEWRAP: 24,\n PROCESSWRAP: 25,\n PROMISE: 26,\n QUERYWRAP: 27,\n SHUTDOWNWRAP: 28,\n SIGNALWRAP: 29,\n STATWATCHER: 30,\n STREAMPIPE: 31,\n TCPCONNECTWRAP: 32,\n TCPSERVERWRAP: 33,\n TCPWRAP: 34,\n TTYWRAP: 35,\n UDPSENDWRAP: 36,\n UDPWRAP: 37,\n SIGINTWATCHDOG: 38,\n WORKER: 39,\n WORKERHEAPSNAPSHOT: 40,\n WRITEWRAP: 41,\n ZLIB: 42,\n CHECKPRIMEREQUEST: 43,\n PBKDF2REQUEST: 44,\n KEYPAIRGENREQUEST: 45,\n KEYGENREQUEST: 46,\n KEYEXPORTREQUEST: 47,\n CIPHERREQUEST: 48,\n DERIVEBITSREQUEST: 49,\n HASHREQUEST: 50,\n RANDOMBYTESREQUEST: 51,\n RANDOMPRIMEREQUEST: 52,\n SCRYPTREQUEST: 53,\n SIGNREQUEST: 54,\n TLSWRAP: 55,\n VERIFYREQUEST: 56,\n INSPECTORJSBINDING: 57\n};\n$ = {\n AsyncLocalStorage,\n createHook,\n executionAsyncId,\n triggerAsyncId,\n executionAsyncResource,\n asyncWrapProviders,\n AsyncResource\n};\nreturn $})\n"_s;
//
//
@@ -689,7 +689,7 @@ static constexpr ASCIILiteral NodeTraceEventsCode = "(function (){\"use strict\"
//
//
-static constexpr ASCIILiteral NodeTtyCode = "(function (){\"use strict\";// src/js/out/tmp/node/tty.ts\nvar ReadStream = function(fd) {\n if (!(this instanceof ReadStream))\n return new ReadStream(fd);\n if (fd >> 0 !== fd || fd < 0)\n @throwRangeError(\"fd must be a positive integer\");\n const stream = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).ReadStream.call(this, \"\", {\n fd\n });\n return stream.isRaw = !1, stream.isTTY = isatty(stream.fd), stream;\n}, warnOnDeactivatedColors = function(env) {\n if (warned)\n return;\n let name = \"\";\n if (env.NODE_DISABLE_COLORS !== @undefined)\n name = \"NODE_DISABLE_COLORS\";\n if (env.NO_COLOR !== @undefined) {\n if (name !== \"\")\n name += \"' and '\";\n name += \"NO_COLOR\";\n }\n if (name !== \"\")\n process.emitWarning(`The '${name}' env is ignored due to the 'FORCE_COLOR' env being set.`, \"Warning\"), warned = !0;\n}, WriteStream = function(fd) {\n if (!(this instanceof WriteStream))\n return new WriteStream(fd);\n if (fd >> 0 !== fd || fd < 0)\n @throwRangeError(\"fd must be a positive integer\");\n const stream = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).WriteStream.call(this, \"\", {\n fd\n });\n if (stream.columns = @undefined, stream.rows = @undefined, stream.isTTY = isatty(stream.fd), stream.isTTY) {\n const windowSizeArray = [0, 0];\n if (_getWindowSize(fd, windowSizeArray) === !0)\n stream.columns = windowSizeArray[0], stream.rows = windowSizeArray[1];\n }\n return stream;\n}, { ttySetMode, isatty, getWindowSize: _getWindowSize } = @lazy(\"tty\"), StringPrototypeSplit = Function.prototype.call.bind(@String.prototype.split), RegExpPrototypeExec = Function.prototype.call.bind(@RegExp.prototype.exec), StringPrototypeToLowerCase = Function.prototype.call.bind(@String.prototype.toLowerCase), ArrayPrototypeSome = Function.prototype.call.bind(@Array.prototype.some), NumberIsInteger = Number.isInteger;\nObject.defineProperty(ReadStream, \"prototype\", {\n get() {\n const Real = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).ReadStream.prototype;\n return Object.defineProperty(ReadStream, \"prototype\", { value: Real }), ReadStream.prototype.setRawMode = function(flag) {\n const mode = flag \? 1 : 0, err = ttySetMode(this.fd, mode);\n if (err)\n return this.emit(\"error\", new Error(\"setRawMode failed with errno:\", err)), this;\n return this.isRaw = flag, this;\n }, Real;\n },\n enumerable: !0,\n configurable: !0\n});\nvar COLORS_2 = 1, COLORS_16 = 4, COLORS_256 = 8, COLORS_16m = 24, TERM_ENVS = {\n eterm: COLORS_16,\n cons25: COLORS_16,\n console: COLORS_16,\n cygwin: COLORS_16,\n dtterm: COLORS_16,\n gnome: COLORS_16,\n hurd: COLORS_16,\n jfbterm: COLORS_16,\n konsole: COLORS_16,\n kterm: COLORS_16,\n mlterm: COLORS_16,\n mosh: COLORS_16m,\n putty: COLORS_16,\n st: COLORS_16,\n \"rxvt-unicode-24bit\": COLORS_16m,\n terminator: COLORS_16m\n}, TERM_ENVS_REG_EXP = [/ansi/, /color/, /linux/, /^con[0-9]*x[0-9]/, /^rxvt/, /^screen/, /^xterm/, /^vt100/], warned = !1;\nObject.defineProperty(WriteStream, \"prototype\", {\n get() {\n const Real = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).WriteStream.prototype;\n Object.defineProperty(WriteStream, \"prototype\", { value: Real }), WriteStream.prototype._refreshSize = function() {\n const oldCols = this.columns, oldRows = this.rows, windowSizeArray = [0, 0];\n if (_getWindowSize(this.fd, windowSizeArray) === !0) {\n if (oldCols !== windowSizeArray[0] || oldRows !== windowSizeArray[1])\n this.columns = windowSizeArray[0], this.rows = windowSizeArray[1], this.emit(\"resize\");\n }\n };\n var readline = @undefined;\n return WriteStream.prototype.clearLine = function(dir, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).clearLine(this, dir, cb);\n }, WriteStream.prototype.clearScreenDown = function(cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).clearScreenDown(this, cb);\n }, WriteStream.prototype.cursorTo = function(x, y, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).cursorTo(this, x, y, cb);\n }, WriteStream.prototype.getColorDepth = function(env = process.env) {\n if (env.FORCE_COLOR !== @undefined)\n switch (env.FORCE_COLOR) {\n case \"\":\n case \"1\":\n case \"true\":\n return warnOnDeactivatedColors(env), COLORS_16;\n case \"2\":\n return warnOnDeactivatedColors(env), COLORS_256;\n case \"3\":\n return warnOnDeactivatedColors(env), COLORS_16m;\n default:\n return COLORS_2;\n }\n if (env.NODE_DISABLE_COLORS !== @undefined || env.NO_COLOR !== @undefined || env.TERM === \"dumb\")\n return COLORS_2;\n if (env.TMUX)\n return COLORS_256;\n if (env.CI) {\n if ([\"APPVEYOR\", \"BUILDKITE\", \"CIRCLECI\", \"DRONE\", \"GITHUB_ACTIONS\", \"GITLAB_CI\", \"TRAVIS\"].some((sign) => (sign in env)) || env.CI_NAME === \"codeship\")\n return COLORS_256;\n return COLORS_2;\n }\n if (\"TEAMCITY_VERSION\" in env)\n return /^(9\\.(0*[1-9]\\d*)\\.|\\d{2,}\\.)/.test(env.TEAMCITY_VERSION) \? COLORS_16 : COLORS_2;\n switch (env.TERM_PROGRAM) {\n case \"iTerm.app\":\n if (!env.TERM_PROGRAM_VERSION || /^[0-2]\\./.test(env.TERM_PROGRAM_VERSION))\n return COLORS_256;\n return COLORS_16m;\n case \"HyperTerm\":\n case \"MacTerm\":\n return COLORS_16m;\n case \"Apple_Terminal\":\n return COLORS_256;\n }\n if (env.COLORTERM === \"truecolor\" || env.COLORTERM === \"24bit\")\n return COLORS_16m;\n if (env.TERM) {\n if (/^xterm-256/.test(env.TERM) !== null)\n return COLORS_256;\n const termEnv = env.TERM.toLowerCase();\n if (TERM_ENVS[termEnv])\n return TERM_ENVS[termEnv];\n if (TERM_ENVS_REG_EXP.some((term) => term.test(termEnv)))\n return COLORS_16;\n }\n if (env.COLORTERM)\n return COLORS_16;\n return COLORS_2;\n }, WriteStream.prototype.getWindowSize = function() {\n return [this.columns, this.rows];\n }, WriteStream.prototype.hasColors = function(count, env) {\n if (env === @undefined && (count === @undefined || typeof count === \"object\" && count !== null))\n env = count, count = 16;\n else\n validateInteger(count, \"count\", 2);\n return count <= 2 ** this.getColorDepth(env);\n }, WriteStream.prototype.moveCursor = function(dx, dy, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).moveCursor(this, dx, dy, cb);\n }, Real;\n },\n enumerable: !0,\n configurable: !0\n});\nvar validateInteger = (value, name, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) => {\n if (typeof value !== \"number\")\n throw new ERR_INVALID_ARG_TYPE(name, \"number\", value);\n if (!NumberIsInteger(value))\n throw new ERR_OUT_OF_RANGE(name, \"an integer\", value);\n if (value < min || value > max)\n throw new ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value);\n};\nreturn { ReadStream, WriteStream, isatty }})\n"_s;
+static constexpr ASCIILiteral NodeTtyCode = "(function (){\"use strict\";// src/js/out/tmp/node/tty.ts\nvar ReadStream = function(fd) {\n if (!(this instanceof ReadStream))\n return new ReadStream(fd);\n if (fd >> 0 !== fd || fd < 0)\n @throwRangeError(\"fd must be a positive integer\");\n const stream = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).ReadStream.call(this, \"\", {\n fd\n });\n return Object.setPrototypeOf(stream, ReadStream.prototype), stream.isRaw = !1, stream.isTTY = !0, stream;\n}, warnOnDeactivatedColors = function(env) {\n if (warned)\n return;\n let name = \"\";\n if (env.NODE_DISABLE_COLORS !== @undefined)\n name = \"NODE_DISABLE_COLORS\";\n if (env.NO_COLOR !== @undefined) {\n if (name !== \"\")\n name += \"' and '\";\n name += \"NO_COLOR\";\n }\n if (name !== \"\")\n process.emitWarning(`The '${name}' env is ignored due to the 'FORCE_COLOR' env being set.`, \"Warning\"), warned = !0;\n}, WriteStream = function(fd) {\n if (!(this instanceof WriteStream))\n return new WriteStream(fd);\n if (fd >> 0 !== fd || fd < 0)\n @throwRangeError(\"fd must be a positive integer\");\n const stream = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).WriteStream.call(this, \"\", {\n fd\n });\n if (stream.columns = @undefined, stream.rows = @undefined, stream.isTTY = isatty(stream.fd), stream.isTTY) {\n const windowSizeArray = [0, 0];\n if (_getWindowSize(fd, windowSizeArray) === !0)\n stream.columns = windowSizeArray[0], stream.rows = windowSizeArray[1];\n }\n return stream;\n}, { ttySetMode, isatty, getWindowSize: _getWindowSize } = @lazy(\"tty\"), StringPrototypeSplit = Function.prototype.call.bind(@String.prototype.split), NumberIsInteger = Number.isInteger;\nObject.defineProperty(ReadStream, \"prototype\", {\n get() {\n const Prototype = Object.create((@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).ReadStream.prototype);\n return Prototype.setRawMode = function(flag) {\n const mode = flag \? 1 : 0, err = ttySetMode(this.fd, mode);\n if (err)\n return this.emit(\"error\", new Error(\"setRawMode failed with errno: \" + err)), this;\n return this.isRaw = flag, this;\n }, Object.defineProperty(ReadStream, \"prototype\", { value: Prototype }), Prototype;\n },\n enumerable: !0,\n configurable: !0\n});\nvar COLORS_2 = 1, COLORS_16 = 4, COLORS_256 = 8, COLORS_16m = 24, TERM_ENVS = {\n eterm: COLORS_16,\n cons25: COLORS_16,\n console: COLORS_16,\n cygwin: COLORS_16,\n dtterm: COLORS_16,\n gnome: COLORS_16,\n hurd: COLORS_16,\n jfbterm: COLORS_16,\n konsole: COLORS_16,\n kterm: COLORS_16,\n mlterm: COLORS_16,\n mosh: COLORS_16m,\n putty: COLORS_16,\n st: COLORS_16,\n \"rxvt-unicode-24bit\": COLORS_16m,\n terminator: COLORS_16m\n}, TERM_ENVS_REG_EXP = [/ansi/, /color/, /linux/, /^con[0-9]*x[0-9]/, /^rxvt/, /^screen/, /^xterm/, /^vt100/], warned = !1;\nObject.defineProperty(WriteStream, \"prototype\", {\n get() {\n const Real = (@getInternalField(@internalModuleRegistry, 21) || @createInternalModuleById(21)).WriteStream.prototype;\n Object.defineProperty(WriteStream, \"prototype\", { value: Real }), WriteStream.prototype._refreshSize = function() {\n const oldCols = this.columns, oldRows = this.rows, windowSizeArray = [0, 0];\n if (_getWindowSize(this.fd, windowSizeArray) === !0) {\n if (oldCols !== windowSizeArray[0] || oldRows !== windowSizeArray[1])\n this.columns = windowSizeArray[0], this.rows = windowSizeArray[1], this.emit(\"resize\");\n }\n };\n var readline = @undefined;\n return WriteStream.prototype.clearLine = function(dir, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).clearLine(this, dir, cb);\n }, WriteStream.prototype.clearScreenDown = function(cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).clearScreenDown(this, cb);\n }, WriteStream.prototype.cursorTo = function(x, y, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).cursorTo(this, x, y, cb);\n }, WriteStream.prototype.getColorDepth = function(env = process.env) {\n if (env.FORCE_COLOR !== @undefined)\n switch (env.FORCE_COLOR) {\n case \"\":\n case \"1\":\n case \"true\":\n return warnOnDeactivatedColors(env), COLORS_16;\n case \"2\":\n return warnOnDeactivatedColors(env), COLORS_256;\n case \"3\":\n return warnOnDeactivatedColors(env), COLORS_16m;\n default:\n return COLORS_2;\n }\n if (env.NODE_DISABLE_COLORS !== @undefined || env.NO_COLOR !== @undefined || env.TERM === \"dumb\")\n return COLORS_2;\n if (env.TMUX)\n return COLORS_256;\n if (env.CI) {\n if ([\"APPVEYOR\", \"BUILDKITE\", \"CIRCLECI\", \"DRONE\", \"GITHUB_ACTIONS\", \"GITLAB_CI\", \"TRAVIS\"].some((sign) => (sign in env)) || env.CI_NAME === \"codeship\")\n return COLORS_256;\n return COLORS_2;\n }\n if (\"TEAMCITY_VERSION\" in env)\n return /^(9\\.(0*[1-9]\\d*)\\.|\\d{2,}\\.)/.test(env.TEAMCITY_VERSION) \? COLORS_16 : COLORS_2;\n switch (env.TERM_PROGRAM) {\n case \"iTerm.app\":\n if (!env.TERM_PROGRAM_VERSION || /^[0-2]\\./.test(env.TERM_PROGRAM_VERSION))\n return COLORS_256;\n return COLORS_16m;\n case \"HyperTerm\":\n case \"MacTerm\":\n return COLORS_16m;\n case \"Apple_Terminal\":\n return COLORS_256;\n }\n if (env.COLORTERM === \"truecolor\" || env.COLORTERM === \"24bit\")\n return COLORS_16m;\n if (env.TERM) {\n if (/^xterm-256/.test(env.TERM) !== null)\n return COLORS_256;\n const termEnv = env.TERM.toLowerCase();\n if (TERM_ENVS[termEnv])\n return TERM_ENVS[termEnv];\n if (TERM_ENVS_REG_EXP.some((term) => term.test(termEnv)))\n return COLORS_16;\n }\n if (env.COLORTERM)\n return COLORS_16;\n return COLORS_2;\n }, WriteStream.prototype.getWindowSize = function() {\n return [this.columns, this.rows];\n }, WriteStream.prototype.hasColors = function(count, env) {\n if (env === @undefined && (count === @undefined || typeof count === \"object\" && count !== null))\n env = count, count = 16;\n else\n validateInteger(count, \"count\", 2);\n return count <= 2 ** this.getColorDepth(env);\n }, WriteStream.prototype.moveCursor = function(dx, dy, cb) {\n return (readline \?\?= @getInternalField(@internalModuleRegistry, 35) || @createInternalModuleById(35)).moveCursor(this, dx, dy, cb);\n }, Real;\n },\n enumerable: !0,\n configurable: !0\n});\nvar validateInteger = (value, name, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) => {\n if (typeof value !== \"number\")\n throw new ERR_INVALID_ARG_TYPE(name, \"number\", value);\n if (!NumberIsInteger(value))\n throw new ERR_OUT_OF_RANGE(name, \"an integer\", value);\n if (value < min || value > max)\n throw new ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value);\n};\nreturn { ReadStream, WriteStream, isatty }})\n"_s;
//
//
diff --git a/src/js/out/WebCoreJSBuiltins.cpp b/src/js/out/WebCoreJSBuiltins.cpp
index 4940ed1f5..a60dfc281 100644
--- a/src/js/out/WebCoreJSBuiltins.cpp
+++ b/src/js/out/WebCoreJSBuiltins.cpp
@@ -786,13 +786,21 @@ const int s_moduleMainCodeLength = 68;
static const JSC::Intrinsic s_moduleMainCodeIntrinsic = JSC::NoIntrinsic;
const char* const s_moduleMainCode = "(function () {\"use strict\";\n return @requireMap.@get(Bun.main);\n})\n";
+// overridableRequire
+const JSC::ConstructAbility s_moduleOverridableRequireCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_moduleOverridableRequireCodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_moduleOverridableRequireCodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_moduleOverridableRequireCodeLength = 888;
+static const JSC::Intrinsic s_moduleOverridableRequireCodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_moduleOverridableRequireCode = "(function (id) {\"use strict\";\n const existing = @requireMap.@get(id) || @requireMap.@get(id = @resolveSync(id, this.path, !1));\n if (existing)\n return @evaluateCommonJSModule(existing), existing.exports;\n if (id.endsWith(\".node\"))\n return @internalRequire(id);\n const mod = @createCommonJSModule(id, {}, !1, this);\n @requireMap.@set(id, mod);\n var out = this.@require(id, mod);\n if (out === -1) {\n try {\n out = @requireESM(id);\n } catch (exception) {\n throw @requireMap.@delete(id), exception;\n }\n const esm = @Loader.registry.@get(id);\n if (esm\?.evaluated && (esm.state \?\? 0) >= @ModuleReady) {\n const namespace = @Loader.getModuleNamespaceObject(esm.module);\n return mod.exports = namespace.__esModule \? namespace : Object.create(namespace, { __esModule: { value: !0 } });\n }\n }\n return @evaluateCommonJSModule(mod), mod.exports;\n})\n";
+
// require
const JSC::ConstructAbility s_moduleRequireCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const JSC::ConstructorKind s_moduleRequireCodeConstructorKind = JSC::ConstructorKind::None;
const JSC::ImplementationVisibility s_moduleRequireCodeImplementationVisibility = JSC::ImplementationVisibility::Public;
-const int s_moduleRequireCodeLength = 888;
+const int s_moduleRequireCodeLength = 79;
static const JSC::Intrinsic s_moduleRequireCodeIntrinsic = JSC::NoIntrinsic;
-const char* const s_moduleRequireCode = "(function (id) {\"use strict\";\n const existing = @requireMap.@get(id) || @requireMap.@get(id = @resolveSync(id, this.path, !1));\n if (existing)\n return @evaluateCommonJSModule(existing), existing.exports;\n if (id.endsWith(\".node\"))\n return @internalRequire(id);\n const mod = @createCommonJSModule(id, {}, !1, this);\n @requireMap.@set(id, mod);\n var out = this.@require(id, mod);\n if (out === -1) {\n try {\n out = @requireESM(id);\n } catch (exception) {\n throw @requireMap.@delete(id), exception;\n }\n const esm = @Loader.registry.@get(id);\n if (esm\?.evaluated && (esm.state \?\? 0) >= @ModuleReady) {\n const namespace = @Loader.getModuleNamespaceObject(esm.module);\n return mod.exports = namespace.__esModule \? namespace : Object.create(namespace, { __esModule: { value: !0 } });\n }\n }\n return @evaluateCommonJSModule(mod), mod.exports;\n})\n";
+const char* const s_moduleRequireCode = "(function (id) {\"use strict\";\n return @overridableRequire.@call(this, id);\n})\n";
// requireNativeModule
const JSC::ConstructAbility s_moduleRequireNativeModuleCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
@@ -824,9 +832,9 @@ WEBCORE_FOREACH_MODULE_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR)
const JSC::ConstructAbility s_processObjectInternalsGetStdinStreamCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const JSC::ConstructorKind s_processObjectInternalsGetStdinStreamCodeConstructorKind = JSC::ConstructorKind::None;
const JSC::ImplementationVisibility s_processObjectInternalsGetStdinStreamCodeImplementationVisibility = JSC::ImplementationVisibility::Public;
-const int s_processObjectInternalsGetStdinStreamCodeLength = 1820;
+const int s_processObjectInternalsGetStdinStreamCodeLength = 1945;
static const JSC::Intrinsic s_processObjectInternalsGetStdinStreamCodeIntrinsic = JSC::NoIntrinsic;
-const char* const s_processObjectInternalsGetStdinStreamCode = "(function (fd) {\"use strict\";\n var reader, readerRef;\n function ref() {\n reader \?\?= Bun.stdin.stream().getReader(), readerRef \?\?= setInterval(() => {\n }, 1 << 30);\n }\n function unref() {\n if (readerRef)\n clearInterval(readerRef), readerRef = @undefined;\n if (reader)\n reader.cancel(), reader = @undefined;\n }\n const stream = new ((@getInternalField(@internalModuleRegistry, 46)) || (@createInternalModuleById(46))).ReadStream(fd), originalOn = stream.on;\n stream.on = function(event, listener) {\n if (event === \"readable\")\n ref();\n return originalOn.call(this, event, listener);\n }, stream.fd = fd;\n const originalPause = stream.pause;\n stream.pause = function() {\n return unref(), originalPause.call(this);\n };\n const originalResume = stream.resume;\n stream.resume = function() {\n return ref(), originalResume.call(this);\n };\n async function internalRead(stream2) {\n try {\n var done, value;\n const read = reader\?.readMany();\n if (@isPromise(read))\n ({ done, value } = await read);\n else\n ({ done, value } = read);\n if (!done) {\n stream2.push(value[0]);\n const length = value.length;\n for (let i = 1;i < length; i++)\n stream2.push(value[i]);\n } else\n stream2.emit(\"end\"), stream2.pause();\n } catch (err) {\n stream2.destroy(err);\n }\n }\n return stream._read = function(size) {\n internalRead(this);\n }, stream.on(\"resume\", () => {\n ref(), stream._undestroy();\n }), stream._readableState.reading = !1, stream.on(\"pause\", () => {\n process.nextTick(() => {\n if (!stream.readableFlowing)\n stream._readableState.reading = !1;\n });\n }), stream.on(\"close\", () => {\n process.nextTick(() => {\n stream.destroy(), unref();\n });\n }), stream;\n})\n";
+const char* const s_processObjectInternalsGetStdinStreamCode = "(function (fd) {\"use strict\";\n var reader, readerRef;\n function ref() {\n reader \?\?= Bun.stdin.stream().getReader(), readerRef \?\?= setInterval(() => {\n }, 1 << 30);\n }\n function unref() {\n if (readerRef)\n clearInterval(readerRef), readerRef = @undefined;\n if (reader)\n reader.cancel(), reader = @undefined;\n }\n const tty = @getInternalField(@internalModuleRegistry, 46) || @createInternalModuleById(46), stream = new ((tty.isatty(fd)) \? tty.ReadStream : ((@getInternalField(@internalModuleRegistry, 21)) || (@createInternalModuleById(21))).ReadStream)(fd), originalOn = stream.on;\n stream.on = function(event, listener) {\n if (event === \"readable\")\n ref();\n return originalOn.call(this, event, listener);\n }, stream.fd = fd;\n const originalPause = stream.pause;\n stream.pause = function() {\n return unref(), originalPause.call(this);\n };\n const originalResume = stream.resume;\n stream.resume = function() {\n return ref(), originalResume.call(this);\n };\n async function internalRead(stream2) {\n try {\n var done, value;\n const read = reader\?.readMany();\n if (@isPromise(read))\n ({ done, value } = await read);\n else\n ({ done, value } = read);\n if (!done) {\n stream2.push(value[0]);\n const length = value.length;\n for (let i = 1;i < length; i++)\n stream2.push(value[i]);\n } else\n stream2.emit(\"end\"), stream2.pause();\n } catch (err) {\n stream2.destroy(err);\n }\n }\n return stream._read = function(size) {\n internalRead(this);\n }, stream.on(\"resume\", () => {\n ref(), stream._undestroy();\n }), stream._readableState.reading = !1, stream.on(\"pause\", () => {\n process.nextTick(() => {\n if (!stream.readableFlowing)\n stream._readableState.reading = !1;\n });\n }), stream.on(\"close\", () => {\n process.nextTick(() => {\n stream.destroy(), unref();\n });\n }), stream;\n})\n";
// getStdioWriteStream
const JSC::ConstructAbility s_processObjectInternalsGetStdioWriteStreamCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
diff --git a/src/js/out/WebCoreJSBuiltins.h b/src/js/out/WebCoreJSBuiltins.h
index 70401c088..3c6ade197 100644
--- a/src/js/out/WebCoreJSBuiltins.h
+++ b/src/js/out/WebCoreJSBuiltins.h
@@ -1506,6 +1506,14 @@ extern const JSC::ConstructAbility s_moduleMainCodeConstructAbility;
extern const JSC::ConstructorKind s_moduleMainCodeConstructorKind;
extern const JSC::ImplementationVisibility s_moduleMainCodeImplementationVisibility;
+// overridableRequire
+#define WEBCORE_BUILTIN_MODULE_OVERRIDABLEREQUIRE 1
+extern const char* const s_moduleOverridableRequireCode;
+extern const int s_moduleOverridableRequireCodeLength;
+extern const JSC::ConstructAbility s_moduleOverridableRequireCodeConstructAbility;
+extern const JSC::ConstructorKind s_moduleOverridableRequireCodeConstructorKind;
+extern const JSC::ImplementationVisibility s_moduleOverridableRequireCodeImplementationVisibility;
+
// require
#define WEBCORE_BUILTIN_MODULE_REQUIRE 1
extern const char* const s_moduleRequireCode;
@@ -1532,18 +1540,21 @@ extern const JSC::ImplementationVisibility s_moduleRequireResolveCodeImplementat
#define WEBCORE_FOREACH_MODULE_BUILTIN_DATA(macro) \
macro(main, moduleMain, 0) \
+ macro(overridableRequire, moduleOverridableRequire, 1) \
macro(require, moduleRequire, 1) \
macro(requireNativeModule, moduleRequireNativeModule, 1) \
macro(requireResolve, moduleRequireResolve, 1) \
#define WEBCORE_FOREACH_MODULE_BUILTIN_CODE(macro) \
macro(moduleMainCode, main, "get main"_s, s_moduleMainCodeLength) \
+ macro(moduleOverridableRequireCode, overridableRequire, ASCIILiteral(), s_moduleOverridableRequireCodeLength) \
macro(moduleRequireCode, require, ASCIILiteral(), s_moduleRequireCodeLength) \
macro(moduleRequireNativeModuleCode, requireNativeModule, ASCIILiteral(), s_moduleRequireNativeModuleCodeLength) \
macro(moduleRequireResolveCode, requireResolve, ASCIILiteral(), s_moduleRequireResolveCodeLength) \
#define WEBCORE_FOREACH_MODULE_BUILTIN_FUNCTION_NAME(macro) \
macro(main) \
+ macro(overridableRequire) \
macro(require) \
macro(requireNativeModule) \
macro(requireResolve) \
diff --git a/src/js_ast.zig b/src/js_ast.zig
index b9e34d279..46c204e69 100644
--- a/src/js_ast.zig
+++ b/src/js_ast.zig
@@ -5994,6 +5994,7 @@ pub const Ast = struct {
/// This is a list of named exports that may exist in a CommonJS module
/// We use this with `commonjs_at_runtime` to re-export CommonJS
commonjs_export_names: []string = &([_]string{}),
+ import_meta_ref: Ref = Ref.None,
pub const CommonJSNamedExport = struct {
loc_ref: LocRef,
diff --git a/src/js_parser.zig b/src/js_parser.zig
index 449d1cbab..fce928a6e 100644
--- a/src/js_parser.zig
+++ b/src/js_parser.zig
@@ -21241,42 +21241,50 @@ fn NewParser_(
parts[parts.len - 1].stmts = new_stmts_list;
},
- // This becomes
+ // This transforms the user's code into.
//
- // (function (module, exports, require) {
+ // (function (exports, require, module, __filename, __dirname) {
+ // ...
+ // }).call(
+ // this.module.exports,
+ // this.module.exports,
+ // this.require,
+ // this.module,
+ // this.__filename,
+ // this.__dirname,
+ // );
//
- // })(module, exports, require);
+ // `this` is a `CommonJSFunctionArgumentsStructure`
+ // which is initialized in `evaluateCommonJSModuleOnce`
.bun_js => {
var args = allocator.alloc(Arg, 5) catch unreachable;
args[0..5].* = .{
- Arg{
- .binding = p.b(B.Identifier{ .ref = p.module_ref }, logger.Loc.Empty),
- },
- Arg{
- .binding = p.b(B.Identifier{ .ref = p.exports_ref }, logger.Loc.Empty),
- },
- Arg{
- .binding = p.b(B.Identifier{ .ref = p.require_ref }, logger.Loc.Empty),
- },
- Arg{
- .binding = p.b(B.Identifier{ .ref = p.dirname_ref }, logger.Loc.Empty),
- },
- Arg{
- .binding = p.b(B.Identifier{ .ref = p.filename_ref }, logger.Loc.Empty),
- },
+ Arg{ .binding = p.b(B.Identifier{ .ref = p.exports_ref }, logger.Loc.Empty) },
+ Arg{ .binding = p.b(B.Identifier{ .ref = p.require_ref }, logger.Loc.Empty) },
+ Arg{ .binding = p.b(B.Identifier{ .ref = p.module_ref }, logger.Loc.Empty) },
+ Arg{ .binding = p.b(B.Identifier{ .ref = p.filename_ref }, logger.Loc.Empty) },
+ Arg{ .binding = p.b(B.Identifier{ .ref = p.dirname_ref }, logger.Loc.Empty) },
+ };
+
+ const cjsArguments = Expr{
+ .data = .{ .e_this = .{} },
+ .loc = logger.Loc.Empty,
};
+
var total_stmts_count: usize = 0;
for (parts) |part| {
total_stmts_count += part.stmts.len;
}
var stmts_to_copy = allocator.alloc(Stmt, total_stmts_count) catch unreachable;
- var remaining_stmts = stmts_to_copy;
- for (parts) |part| {
- for (part.stmts, remaining_stmts[0..part.stmts.len]) |src, *dest| {
- dest.* = src;
+ {
+ var remaining_stmts = stmts_to_copy;
+ for (parts) |part| {
+ for (part.stmts, remaining_stmts[0..part.stmts.len]) |src, *dest| {
+ dest.* = src;
+ }
+ remaining_stmts = remaining_stmts[part.stmts.len..];
}
- remaining_stmts = remaining_stmts[part.stmts.len..];
}
const wrapper = p.newExpr(
@@ -21284,147 +21292,57 @@ fn NewParser_(
.func = G.Fn{
.name = null,
.open_parens_loc = logger.Loc.Empty,
- .args = args,
+ .args = args[0..5],
.body = .{ .loc = logger.Loc.Empty, .stmts = stmts_to_copy },
.flags = Flags.Function.init(.{ .is_export = false }),
},
},
logger.Loc.Empty,
);
- const cjsGlobal = p.newSymbol(.unbound, "$_BunCommonJSModule_$") catch unreachable;
- var all_call_args = allocator.alloc(Expr, 8) catch unreachable;
+
const this_module = p.newExpr(
E.Dot{
.name = "module",
- .target = p.newExpr(E.Identifier{ .ref = cjsGlobal }, logger.Loc.Empty),
+ .target = cjsArguments,
.name_loc = logger.Loc.Empty,
},
logger.Loc.Empty,
);
- var bind_args = all_call_args[0..1];
- bind_args[0] = this_module;
- var bind_resolve_args = all_call_args[1..2];
- var call_args = all_call_args[2..];
-
- const module_id = p.newExpr(E.Dot{
- .name = "id",
- .target = this_module,
- .name_loc = logger.Loc.Empty,
- }, logger.Loc.Empty);
-
- bind_resolve_args[0] = module_id;
- const get_require = p.newExpr(
+ const module_exports = p.newExpr(
E.Dot{
- .name = "require",
+ .name = "exports",
.target = this_module,
.name_loc = logger.Loc.Empty,
},
logger.Loc.Empty,
);
- const create_binding = p.newExpr(
- E.Call{
- .target = p.newExpr(E.Dot{
- .name = "bind",
- .name_loc = logger.Loc.Empty,
- .target = get_require,
- }, logger.Loc.Empty),
- .args = bun.BabyList(Expr).init(bind_args),
- },
- logger.Loc.Empty,
- );
-
- const get_resolve = p.newExpr(E.Dot{
- .name = "resolve",
- .name_loc = logger.Loc.Empty,
- .target = get_require,
- }, logger.Loc.Empty);
-
- const create_resolve_binding = p.newExpr(
- E.Call{
- .target = p.newExpr(E.Dot{
- .name = "bind",
- .name_loc = logger.Loc.Empty,
- .target = get_resolve,
- }, logger.Loc.Empty),
- .args = bun.BabyList(Expr).init(bind_resolve_args),
- },
- logger.Loc.Empty,
- );
-
- const require_path = p.newExpr(
- E.Dot{
- .name = "path",
- .target = get_require,
- .name_loc = logger.Loc.Empty,
- },
- logger.Loc.Empty,
- );
- const assign_binding = p.newExpr(
- E.Binary{
- .left = get_require,
- .right = create_binding,
- .op = .bin_assign,
- },
- logger.Loc.Empty,
- );
-
- const assign_resolve_binding = p.newExpr(
- E.Binary{
- .left = get_resolve,
- .right = create_resolve_binding,
- .op = .bin_assign,
- },
- logger.Loc.Empty,
- );
-
- const assign_id = p.newExpr(E.Binary{
- .left = require_path,
- .right = module_id,
- .op = .bin_assign,
- }, logger.Loc.Empty);
-
- var create_require = [4]Expr{
- assign_binding,
- assign_id,
- assign_resolve_binding,
- get_require,
- };
-
- //
- // (function(module, exports, require, __dirname, __filename) {}).call(this.exports, this.module, this.exports, this.module.require = this.module.require.bind(module), (this.module.require.id = this.module.id, this.module.require), __dirname, __filename)
+ var call_args = allocator.alloc(Expr, 6) catch unreachable;
call_args[0..6].* = .{
+ module_exports, // this.module.exports (this value inside fn)
+ module_exports, // this.module.exports (arg 1)
p.newExpr(
E.Dot{
- .name = "exports",
- .target = this_module,
+ .name = "require",
+ .target = cjsArguments,
.name_loc = logger.Loc.Empty,
},
logger.Loc.Empty,
),
- this_module,
+ this_module, // this.module
p.newExpr(
E.Dot{
- .name = "exports",
- .target = this_module,
+ .name = "__filename",
+ .target = cjsArguments,
.name_loc = logger.Loc.Empty,
},
logger.Loc.Empty,
),
- Expr.joinAllWithComma(&create_require, p.allocator),
p.newExpr(
E.Dot{
.name = "__dirname",
- .target = p.newExpr(E.Identifier{ .ref = cjsGlobal }, logger.Loc.Empty),
- .name_loc = logger.Loc.Empty,
- },
- logger.Loc.Empty,
- ),
- p.newExpr(
- E.Dot{
- .name = "__filename",
- .target = p.newExpr(E.Identifier{ .ref = cjsGlobal }, logger.Loc.Empty),
+ .target = cjsArguments,
.name_loc = logger.Loc.Empty,
},
logger.Loc.Empty,
@@ -21446,14 +21364,50 @@ fn NewParser_(
logger.Loc.Empty,
);
- var only_stmt = try p.allocator.alloc(Stmt, 1);
- only_stmt[0] = p.s(
+ var top_level_stmts = p.allocator.alloc(Stmt, 1 + @as(usize, @intFromBool(p.has_import_meta))) catch unreachable;
+ parts[0].stmts = top_level_stmts;
+
+ // var $Bun_import_meta = this.createImportMeta(this.filename);
+ if (p.has_import_meta) {
+ p.import_meta_ref = p.newSymbol(.other, "$Bun_import_meta") catch unreachable;
+ var decl = allocator.alloc(Decl, 1) catch unreachable;
+ decl[0] = Decl{
+ .binding = Binding.alloc(
+ p.allocator,
+ B.Identifier{
+ .ref = p.import_meta_ref,
+ },
+ logger.Loc.Empty,
+ ),
+ .value = p.newExpr(
+ E.Call{
+ .target = p.newExpr(E.Dot{
+ .target = cjsArguments,
+ .name = "createImportMeta",
+ .name_loc = logger.Loc.Empty,
+ }, logger.Loc.Empty),
+ // reuse the `this.__filename` argument
+ .args = ExprNodeList.init(call_args[5..6]),
+ },
+ logger.Loc.Empty,
+ ),
+ };
+
+ top_level_stmts[0] = p.s(
+ S.Local{
+ .decls = G.Decl.List.init(decl),
+ .kind = .k_var,
+ },
+ logger.Loc.Empty,
+ );
+ top_level_stmts = top_level_stmts[1..];
+ }
+ top_level_stmts[0] = p.s(
S.SExpr{
.value = call,
},
logger.Loc.Empty,
);
- parts[0].stmts = only_stmt;
parts.len = 1;
},
@@ -21984,6 +21938,8 @@ fn NewParser_(
// TODO:
// .const_values = p.const_values,
+
+ .import_meta_ref = p.import_meta_ref,
};
}
diff --git a/src/js_printer.zig b/src/js_printer.zig
index 15f5218ae..8202eac80 100644
--- a/src/js_printer.zig
+++ b/src/js_printer.zig
@@ -482,6 +482,7 @@ pub const Options = struct {
to_commonjs_ref: Ref = Ref.None,
to_esm_ref: Ref = Ref.None,
require_ref: ?Ref = null,
+ import_meta_ref: Ref = Ref.None,
indent: usize = 0,
externals: []u32 = &[_]u32{},
runtime_imports: runtime.Runtime.Imports = runtime.Runtime.Imports{},
@@ -2051,7 +2052,20 @@ fn NewPrinter(
.e_import_meta => {
p.printSpaceBeforeIdentifier();
p.addSourceMapping(expr.loc);
- p.print("import.meta");
+ if (!p.options.import_meta_ref.isValid()) {
+ // Most of the time, leave it in there
+ p.print("import.meta");
+ } else {
+ // Note: The bundler will not hit this code path. The bundler will replace
+ // the ImportMeta AST node with a regular Identifier AST node.
+ //
+ // This is currently only used in Bun's runtime for CommonJS modules
+ // referencing import.meta
+ if (comptime Environment.allow_assert)
+ std.debug.assert(p.options.module_type == .cjs);
+
+ p.printSymbol(p.options.import_meta_ref);
+ }
},
.e_commonjs_export_identifier => |id| {
p.printSpaceBeforeIdentifier();
diff --git a/src/string.zig b/src/string.zig
index 7928ad97b..1305e5884 100644
--- a/src/string.zig
+++ b/src/string.zig
@@ -855,17 +855,17 @@ pub const SliceWithUnderlyingString = struct {
underlying: String,
pub fn toThreadSafe(this: *SliceWithUnderlyingString) void {
- std.debug.assert(this.underlying.tag == .WTFStringImpl);
-
- var orig = this.underlying.value.WTFStringImpl;
- this.underlying.toThreadSafe();
- if (this.underlying.value.WTFStringImpl != orig) {
- orig.deref();
-
- if (this.utf8.allocator.get()) |allocator| {
- if (String.isWTFAllocator(allocator)) {
- this.utf8.deinit();
- this.utf8 = this.underlying.toUTF8(bun.default_allocator);
+ if (this.underlying.tag == .WTFStringImpl) {
+ var orig = this.underlying.value.WTFStringImpl;
+ this.underlying.toThreadSafe();
+ if (this.underlying.value.WTFStringImpl != orig) {
+ orig.deref();
+
+ if (this.utf8.allocator.get()) |allocator| {
+ if (String.isWTFAllocator(allocator)) {
+ this.utf8.deinit();
+ this.utf8 = this.underlying.toUTF8(bun.default_allocator);
+ }
}
}
}
diff --git a/test/.gitignore b/test/.gitignore
deleted file mode 100644
index 60f986255..000000000
--- a/test/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-bun.lockb
diff --git a/test/README.md b/test/README.md
deleted file mode 100644
index 03f9c97af..000000000
--- a/test/README.md
+++ /dev/null
@@ -1,83 +0,0 @@
-# Tests
-
-## Finding tests
-
-Tests are located in the [`test/`](test/) directory and are organized using the following structure:
-
-* `test/`
- * `js/` - tests for JavaScript APIs.
- * `cli/` - tests for commands, configs, and stdout.
- * `bundler/` - tests for the transpiler/bundler.
- * `regression/` - tests that reproduce a specific issue.
- * `harness.ts` - utility functions that can be imported from any test.
-
-The tests in [`test/js/`](test/js/) directory are further categorized by the type of API.
-
-* `test/js/`
- * `bun/` - tests for `Bun`-specific APIs.
- * `node/` - tests for Node.js APIs.
- * `web/` - tests for Web APIs, like `fetch()`.
- * `first_party/` - tests for npm packages that are built-in, like `undici`.
- * `third_party/` - tests for npm packages that are not built-in, but are popular, like `esbuild`.
-
-## Running tests
-
-To run a test, use Bun's built-in test command: `bun test`.
-
-```sh
-bun test # Run all tests
-bun test js/bun # Only run tests in a directory
-bun test sqlite.test.ts # Only run a specific test
-```
-
-If you encounter lots of errors, try running `bun install`, then trying again.
-
-## Writing tests
-
-Tests are written in TypeScript (preferred) or JavaScript using Jest's `describe()`, `test()`, and `expect()` APIs.
-
-```ts
-import { describe, test, expect } from "bun:test";
-import { gcTick } from "harness";
-
-describe("TextEncoder", () => {
- test("can encode a string", async () => {
- const encoder = new TextEncoder();
- const actual = encoder.encode("bun");
- await gcTick();
- expect(actual).toBe(new Uint8Array([0x62, 0x75, 0x6E]));
- });
-});
-```
-
-If you are fixing a bug that was reported from a GitHub issue, remember to add a test in the `test/regression/` directory.
-
-```ts
-// test/regression/issue/02005.test.ts
-
-import { it, expect } from "bun:test";
-
-it("regex literal should work with non-latin1", () => {
- const text = "这是一段要替换的文字";
- expect(text.replace(new RegExp("要替换"), "")).toBe("这是一段的文字");
- expect(text.replace(/要替换/, "")).toBe("这是一段的文字");
-});
-```
-
-In the future, a bot will automatically close or re-open issues when a regression is detected or resolved.
-
-## Zig tests
-
-These tests live in various `.zig` files throughout Bun's codebase, leveraging Zig's builtin `test` keyword.
-
-Currently, they're not run automatically nor is there a simple way to run all of them. We will make this better soon.
-
-## TypeScript
-
-Test files should be written in TypeScript. The types in `packages/bun-types` should be updated to support all new APIs. Changes to the `.d.ts` files in `packages/bun-types` will be immediately reflected in test files; no build step is necessary.
-
-Writing a test will often require using invalid syntax, e.g. when checking for errors when an invalid input is passed to a function. TypeScript provides a number of escape hatches here.
-
-- `// @ts-expect-error` - This should be your first choice. It tells TypeScript that the next line *should* fail typechecking.
-- `// @ts-ignore` - Ignore the next line entirely.
-- `// @ts-nocheck` - Put this at the top of the file to disable typechecking on the entire file. Useful for autogenerated test files, or when ignoring/disabling type checks an a per-line basis is too onerous.
diff --git a/test/bun.lockb b/test/bun.lockb
index b68c3f550..13d6e0866 100755
--- a/test/bun.lockb
+++ b/test/bun.lockb
Binary files differ
diff --git a/test/integration/next/default-pages-dir/.eslintrc.json b/test/integration/next/default-pages-dir/.eslintrc.json
new file mode 100644
index 000000000..bffb357a7
--- /dev/null
+++ b/test/integration/next/default-pages-dir/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": "next/core-web-vitals"
+}
diff --git a/test/integration/next/default-pages-dir/.gitignore b/test/integration/next/default-pages-dir/.gitignore
new file mode 100644
index 000000000..412289e0b
--- /dev/null
+++ b/test/integration/next/default-pages-dir/.gitignore
@@ -0,0 +1,38 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
+
+# fixtures
+src/Counter.tsx \ No newline at end of file
diff --git a/test/integration/next/default-pages-dir/README.md b/test/integration/next/default-pages-dir/README.md
new file mode 100644
index 000000000..a75ac5248
--- /dev/null
+++ b/test/integration/next/default-pages-dir/README.md
@@ -0,0 +1,40 @@
+This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
+
+## Getting Started
+
+First, run the development server:
+
+```bash
+npm run dev
+# or
+yarn dev
+# or
+pnpm dev
+# or
+bun dev
+```
+
+Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+
+You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
+
+[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
+
+The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
+
+This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
+
+## Learn More
+
+To learn more about Next.js, take a look at the following resources:
+
+- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
+- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
+
+You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
+
+## Deploy on Vercel
+
+The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
+
+Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
diff --git a/test/integration/next/default-pages-dir/bun.lockb b/test/integration/next/default-pages-dir/bun.lockb
new file mode 100755
index 000000000..4c97b0398
--- /dev/null
+++ b/test/integration/next/default-pages-dir/bun.lockb
Binary files differ
diff --git a/test/integration/next/default-pages-dir/next.config.js b/test/integration/next/default-pages-dir/next.config.js
new file mode 100644
index 000000000..5a35883f4
--- /dev/null
+++ b/test/integration/next/default-pages-dir/next.config.js
@@ -0,0 +1,10 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+ reactStrictMode: true,
+ generateBuildId: async () => {
+ // You can, for example, get the latest git commit hash here
+ return "bun!";
+ },
+};
+
+module.exports = nextConfig;
diff --git a/test/integration/next/default-pages-dir/package.json b/test/integration/next/default-pages-dir/package.json
new file mode 100644
index 000000000..b3f1d3616
--- /dev/null
+++ b/test/integration/next/default-pages-dir/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "default-create-template",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint",
+ "postinstall": "cd node_modules/puppeteer && bun install.mjs"
+ },
+ "dependencies": {
+ "@types/node": "20.7.0",
+ "@types/react": "18.2.22",
+ "@types/react-dom": "18.2.7",
+ "autoprefixer": "10.4.16",
+ "bun-types": "^1.0.3",
+ "eslint": "8.50.0",
+ "eslint-config-next": "13.5.3",
+ "next": "13.5.3",
+ "postcss": "8.4.30",
+ "puppeteer": "21.3.4",
+ "react": "18.2.0",
+ "react-dom": "18.2.0",
+ "tailwindcss": "3.3.3",
+ "typescript": "5.2.2"
+ }
+}
diff --git a/test/integration/next/default-pages-dir/postcss.config.js b/test/integration/next/default-pages-dir/postcss.config.js
new file mode 100644
index 000000000..12a703d90
--- /dev/null
+++ b/test/integration/next/default-pages-dir/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/test/integration/next/default-pages-dir/public/favicon.ico b/test/integration/next/default-pages-dir/public/favicon.ico
new file mode 100644
index 000000000..718d6fea4
--- /dev/null
+++ b/test/integration/next/default-pages-dir/public/favicon.ico
Binary files differ
diff --git a/test/integration/next/default-pages-dir/public/next.svg b/test/integration/next/default-pages-dir/public/next.svg
new file mode 100644
index 000000000..5174b28c5
--- /dev/null
+++ b/test/integration/next/default-pages-dir/public/next.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg> \ No newline at end of file
diff --git a/test/integration/next/default-pages-dir/public/vercel.svg b/test/integration/next/default-pages-dir/public/vercel.svg
new file mode 100644
index 000000000..d2f842227
--- /dev/null
+++ b/test/integration/next/default-pages-dir/public/vercel.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg> \ No newline at end of file
diff --git a/test/integration/next/default-pages-dir/src/Counter1.txt b/test/integration/next/default-pages-dir/src/Counter1.txt
new file mode 100644
index 000000000..3973e0125
--- /dev/null
+++ b/test/integration/next/default-pages-dir/src/Counter1.txt
@@ -0,0 +1,27 @@
+import { useState } from "react";
+
+export function Counter() {
+ console.log('counter a');
+
+ const [count, setCount] = useState(0);
+
+ function increment() {
+ setCount(count + 1);
+ }
+
+ function decrement() {
+ setCount(count - 1);
+ }
+
+ return (
+ <div id="counter-fixture" className="rounded-bl-full">
+ <p>Count A: {count}</p>
+ <button className="inc" onClick={increment}>
+ +
+ </button>
+ <button className="dec" onClick={decrement}>
+ -
+ </button>
+ </div>
+ );
+}
diff --git a/test/integration/next/default-pages-dir/src/Counter2.txt b/test/integration/next/default-pages-dir/src/Counter2.txt
new file mode 100644
index 000000000..67541a78b
--- /dev/null
+++ b/test/integration/next/default-pages-dir/src/Counter2.txt
@@ -0,0 +1,27 @@
+import { useState } from "react";
+
+export function Counter() {
+ console.log('counter b loaded');
+
+ const [count, setCount] = useState(0);
+
+ function increment() {
+ setCount(count + 2);
+ }
+
+ function decrement() {
+ setCount(count - 2);
+ }
+
+ return (
+ <div id="counter-fixture" className="rounded-br-full">
+ <p>Count B: {count}</p>
+ <button className="inc" onClick={increment}>
+ +
+ </button>
+ <button className="dec" onClick={decrement}>
+ -
+ </button>
+ </div>
+ );
+}
diff --git a/test/integration/next/default-pages-dir/src/pages/_app.tsx b/test/integration/next/default-pages-dir/src/pages/_app.tsx
new file mode 100644
index 000000000..a7a790fba
--- /dev/null
+++ b/test/integration/next/default-pages-dir/src/pages/_app.tsx
@@ -0,0 +1,6 @@
+import "@/styles/globals.css";
+import type { AppProps } from "next/app";
+
+export default function App({ Component, pageProps }: AppProps) {
+ return <Component {...pageProps} />;
+}
diff --git a/test/integration/next/default-pages-dir/src/pages/_document.tsx b/test/integration/next/default-pages-dir/src/pages/_document.tsx
new file mode 100644
index 000000000..b2fff8b42
--- /dev/null
+++ b/test/integration/next/default-pages-dir/src/pages/_document.tsx
@@ -0,0 +1,13 @@
+import { Html, Head, Main, NextScript } from "next/document";
+
+export default function Document() {
+ return (
+ <Html lang="en">
+ <Head />
+ <body>
+ <Main />
+ <NextScript />
+ </body>
+ </Html>
+ );
+}
diff --git a/test/integration/next/default-pages-dir/src/pages/api/hello.ts b/test/integration/next/default-pages-dir/src/pages/api/hello.ts
new file mode 100644
index 000000000..a8d68697c
--- /dev/null
+++ b/test/integration/next/default-pages-dir/src/pages/api/hello.ts
@@ -0,0 +1,10 @@
+// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
+import type { NextApiRequest, NextApiResponse } from "next";
+
+type Data = {
+ name: string;
+};
+
+export default function handler(req: NextApiRequest, res: NextApiResponse<Data>) {
+ res.status(200).json({ name: "John Doe" });
+}
diff --git a/test/integration/next/default-pages-dir/src/pages/index.tsx b/test/integration/next/default-pages-dir/src/pages/index.tsx
new file mode 100644
index 000000000..109f5e5e2
--- /dev/null
+++ b/test/integration/next/default-pages-dir/src/pages/index.tsx
@@ -0,0 +1,128 @@
+import Image from "next/image";
+import { Inter } from "next/font/google";
+import Head from "next/head";
+import { Counter } from "@/Counter";
+
+const inter = Inter({ subsets: ["latin"] });
+
+export default function Home({ bunVersion }: any) {
+ return (
+ <main className={`flex min-h-screen flex-col items-center justify-between p-24 ${inter.className}`}>
+ <Head>
+ <meta name="description" content="HEY YOU" />
+ <title>Create Next App</title>
+ </Head>
+
+ <div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm lg:flex">
+ <p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30">
+ Bun Version:
+ <code className="font-mono font-bold">{bunVersion}</code>
+ </p>
+ <div className="fixed bottom-0 left-0 flex h-48 w-full items-end justify-center bg-gradient-to-t from-white via-white dark:from-black dark:via-black lg:static lg:h-auto lg:w-auto lg:bg-none">
+ <a
+ className="pointer-events-none flex place-items-center gap-2 p-8 lg:pointer-events-auto lg:p-0"
+ href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template-tw&utm_campaign=create-next-app"
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ By <Image src="/vercel.svg" alt="Vercel Logo" className="dark:invert" width={100} height={24} priority />
+ </a>
+ </div>
+ </div>
+
+ <div className="relative flex place-items-center before:absolute before:h-[300px] before:w-[480px] before:-translate-x-1/2 before:rounded-full before:bg-gradient-radial before:from-white before:to-transparent before:blur-2xl before:content-[''] after:absolute after:-z-20 after:h-[180px] after:w-[240px] after:translate-x-1/3 after:bg-gradient-conic after:from-sky-200 after:via-blue-200 after:blur-2xl after:content-[''] before:dark:bg-gradient-to-br before:dark:from-transparent before:dark:to-blue-700/10 after:dark:from-sky-900 after:dark:via-[#0141ff]/40 before:lg:h-[360px]">
+ <Image
+ className="relative dark:drop-shadow-[0_0_0.3rem_#ffffff70] dark:invert"
+ src="/next.svg"
+ alt="Next.js Logo"
+ width={180}
+ height={37}
+ priority
+ />
+ </div>
+
+ <Counter />
+
+ <div className="mb-32 grid text-center lg:max-w-5xl lg:w-full lg:mb-0 lg:grid-cols-4 lg:text-left">
+ <a
+ href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=default-template-tw&utm_campaign=create-next-app"
+ className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ <h2 className={`mb-3 text-2xl font-semibold`}>
+ Docs{" "}
+ <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
+ -&gt;
+ </span>
+ </h2>
+ <p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
+ Find in-depth information about Next.js features and API.
+ </p>
+ </a>
+
+ <a
+ href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=default-template-tw&utm_campaign=create-next-app"
+ className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ <h2 className={`mb-3 text-2xl font-semibold`}>
+ Learn{" "}
+ <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
+ -&gt;
+ </span>
+ </h2>
+ <p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
+ Learn about Next.js in an interactive course with&nbsp;quizzes!
+ </p>
+ </a>
+
+ <a
+ href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=default-template-tw&utm_campaign=create-next-app"
+ className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ <h2 className={`mb-3 text-2xl font-semibold`}>
+ Templates{" "}
+ <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
+ -&gt;
+ </span>
+ </h2>
+ <p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
+ Discover and deploy boilerplate example Next.js&nbsp;projects.
+ </p>
+ </a>
+
+ <a
+ href="https://vercel.com/new?utm_source=create-next-app&utm_medium=default-template-tw&utm_campaign=create-next-app"
+ className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ <h2 className={`mb-3 text-2xl font-semibold`}>
+ Deploy{" "}
+ <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
+ -&gt;
+ </span>
+ </h2>
+ <p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
+ Instantly deploy your Next.js site to a shareable URL with Vercel.
+ </p>
+ </a>
+ </div>
+ </main>
+ );
+}
+
+export async function getStaticProps() {
+ return {
+ props: {
+ bunVersion:
+ process.env.NODE_ENV === "production"
+ ? "[production needs a constant string]"
+ : process.versions.bun ?? "not in bun",
+ },
+ };
+}
diff --git a/test/integration/next/default-pages-dir/src/styles/globals.css b/test/integration/next/default-pages-dir/src/styles/globals.css
new file mode 100644
index 000000000..fd81e8858
--- /dev/null
+++ b/test/integration/next/default-pages-dir/src/styles/globals.css
@@ -0,0 +1,27 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+:root {
+ --foreground-rgb: 0, 0, 0;
+ --background-start-rgb: 214, 219, 220;
+ --background-end-rgb: 255, 255, 255;
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --foreground-rgb: 255, 255, 255;
+ --background-start-rgb: 0, 0, 0;
+ --background-end-rgb: 0, 0, 0;
+ }
+}
+
+body {
+ color: rgb(var(--foreground-rgb));
+ background: linear-gradient(
+ to bottom,
+ transparent,
+ rgb(var(--background-end-rgb))
+ )
+ rgb(var(--background-start-rgb));
+}
diff --git a/test/integration/next/default-pages-dir/tailwind.config.ts b/test/integration/next/default-pages-dir/tailwind.config.ts
new file mode 100644
index 000000000..168556c68
--- /dev/null
+++ b/test/integration/next/default-pages-dir/tailwind.config.ts
@@ -0,0 +1,19 @@
+import type { Config } from "tailwindcss";
+
+const config: Config = {
+ content: [
+ // './src/pages/**/*.{js,ts,jsx,tsx,mdx}',
+ "./src/**/*.{js,ts,jsx,tsx,mdx}",
+ // './src/app/**/*.{js,ts,jsx,tsx,mdx}',
+ ],
+ theme: {
+ extend: {
+ backgroundImage: {
+ "gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
+ "gradient-conic": "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
+ },
+ },
+ },
+ plugins: [],
+};
+export default config;
diff --git a/test/integration/next/default-pages-dir/test/dev-server-puppeteer.ts b/test/integration/next/default-pages-dir/test/dev-server-puppeteer.ts
new file mode 100644
index 000000000..9bebeb614
--- /dev/null
+++ b/test/integration/next/default-pages-dir/test/dev-server-puppeteer.ts
@@ -0,0 +1,101 @@
+import { ConsoleMessage, Page, launch } from "puppeteer";
+import assert from "assert";
+import { copyFileSync } from "fs";
+import { join } from "path";
+
+const root = join(import.meta.dir, "../");
+
+copyFileSync(join(root, "src/Counter1.txt"), join(root, "src/Counter.tsx"));
+
+let url = "http://localhost:3000";
+if (process.argv.length > 2) {
+ url = process.argv[2];
+}
+
+const b = await launch({
+ headless: "new",
+});
+
+const p = await b.newPage();
+// p.on("console", msg => console.log("[browser]", msg.text()));
+
+function waitForConsoleMessage(page: Page, regex: RegExp) {
+ const { resolve, promise } = Promise.withResolvers<void>();
+ function onMessage(msg: ConsoleMessage) {
+ const text = msg.text();
+ if (regex.test(text)) {
+ page.off("console", onMessage);
+ resolve();
+ }
+ }
+ p.on("console", onMessage);
+ return promise;
+}
+
+await p.goto(url);
+await waitForConsoleMessage(p, /counter a/);
+
+assert.strictEqual(await p.$eval("code.font-bold", x => x.innerText), Bun.version);
+
+let counter_root = (await p.$("#counter-fixture"))!;
+
+{
+ const [has_class, style_json_string] = await counter_root.evaluate(
+ x => [(x as HTMLElement).classList.contains("rounded-bl-full"), JSON.stringify(getComputedStyle(x))] as const,
+ );
+ assert.strictEqual(has_class, true);
+ const decoded_style = JSON.parse(style_json_string);
+ assert.strictEqual(decoded_style.borderTopLeftRadius, "0px");
+ assert.strictEqual(decoded_style.borderTopRightRadius, "0px");
+ assert.strictEqual(decoded_style.borderBottomRightRadius, "0px");
+ assert.strictEqual(decoded_style.borderBottomLeftRadius, "9999px");
+}
+
+const getCount = () => counter_root.$eval("p", x => x.innerText);
+
+assert.strictEqual(await getCount(), "Count A: 0");
+await counter_root.$eval(".inc", x => (x as HTMLElement).click());
+assert.strictEqual(await getCount(), "Count A: 1");
+await counter_root.$eval(".inc", x => (x as HTMLElement).click());
+assert.strictEqual(await getCount(), "Count A: 2");
+await counter_root.$eval(".dec", x => (x as HTMLElement).click());
+assert.strictEqual(await getCount(), "Count A: 1");
+
+p.reload({});
+await waitForConsoleMessage(p, /counter a/);
+
+assert.strictEqual(await p.$eval("code.font-bold", x => x.innerText), Bun.version);
+
+counter_root = (await p.$("#counter-fixture"))!;
+
+assert.strictEqual(await getCount(), "Count A: 0");
+await counter_root.$eval(".inc", x => (x as HTMLElement).click());
+assert.strictEqual(await getCount(), "Count A: 1");
+await counter_root.$eval(".inc", x => (x as HTMLElement).click());
+assert.strictEqual(await getCount(), "Count A: 2");
+await counter_root.$eval(".dec", x => (x as HTMLElement).click());
+assert.strictEqual(await getCount(), "Count A: 1");
+
+copyFileSync(join(root, "src/Counter2.txt"), join(root, "src/Counter.tsx"));
+await waitForConsoleMessage(p, /counter b loaded/);
+assert.strictEqual(await getCount(), "Count B: 1");
+await counter_root.$eval(".inc", x => (x as HTMLElement).click());
+assert.strictEqual(await getCount(), "Count B: 3");
+await counter_root.$eval(".inc", x => (x as HTMLElement).click());
+assert.strictEqual(await getCount(), "Count B: 5");
+await counter_root.$eval(".dec", x => (x as HTMLElement).click());
+assert.strictEqual(await getCount(), "Count B: 3");
+
+{
+ const [has_class, style_json_string] = await counter_root.evaluate(
+ x => [(x as HTMLElement).classList.contains("rounded-br-full"), JSON.stringify(getComputedStyle(x))] as const,
+ );
+ assert.strictEqual(has_class, true);
+ const decoded_style = JSON.parse(style_json_string);
+ assert.strictEqual(decoded_style.borderTopLeftRadius, "0px");
+ assert.strictEqual(decoded_style.borderTopRightRadius, "0px");
+ assert.strictEqual(decoded_style.borderBottomRightRadius, "9999px");
+ assert.strictEqual(decoded_style.borderBottomLeftRadius, "0px");
+}
+
+await b.close();
diff --git a/test/integration/next/default-pages-dir/test/dev-server.test.ts b/test/integration/next/default-pages-dir/test/dev-server.test.ts
new file mode 100644
index 000000000..8723a91c2
--- /dev/null
+++ b/test/integration/next/default-pages-dir/test/dev-server.test.ts
@@ -0,0 +1,79 @@
+import { afterAll, beforeAll, describe, expect, test } from "bun:test";
+import { bunEnv, bunExe } from "../../../../harness";
+import { Subprocess } from "bun";
+import { copyFileSync, rmSync } from "fs";
+import { join } from "path";
+
+const root = join(import.meta.dir, "../");
+let dev_server: undefined | Subprocess<"ignore", "pipe", "inherit">;
+let baseUrl: string;
+
+test("the dev server can start", async () => {
+ rmSync(join(root, ".next"), { recursive: true, force: true });
+ copyFileSync(join(root, "src/Counter1.txt"), join(root, "src/Counter.tsx"));
+
+ const install = Bun.spawnSync([bunExe(), "i"], { cwd: root, env: bunEnv });
+ if (install.exitCode !== 0) {
+ throw new Error("Failed to install dependencies");
+ }
+ dev_server = Bun.spawn([bunExe(), "--bun", "node_modules/.bin/next", "dev"], {
+ cwd: root,
+ env: bunEnv,
+ stdio: ["ignore", "pipe", "inherit"],
+ });
+ dev_server.exited.then(() => {
+ dev_server = undefined;
+ });
+ for await (const chunk of dev_server.stdout) {
+ console.error({ chunk });
+ const str = new TextDecoder().decode(chunk);
+ let match = str.match(/http:\/\/localhost:\d+/);
+ if (match) {
+ baseUrl = match[0];
+ }
+ if (str.toLowerCase().includes("ready")) {
+ return;
+ }
+ }
+ console.error("Failed to start dev server :/");
+ dev_server.kill();
+ dev_server = undefined;
+}, 30000);
+
+test("ssr works for 100 requests", async () => {
+ expect(dev_server).not.toBeUndefined();
+ expect(baseUrl).not.toBeUndefined();
+
+ const promises = [];
+ for (let i = 0; i < 100; i++) {
+ promises.push(
+ (async () => {
+ const x = await fetch(`${baseUrl}/`);
+ expect(x.status).toBe(200);
+ const text = await x.text();
+ expect(text).toContain(`>${Bun.version}</code>`);
+ })(),
+ );
+ }
+
+ const x = await Promise.allSettled(promises);
+ for (const y of x) {
+ expect(y.status).toBe("fulfilled");
+ }
+}, 10000);
+
+test("hot reloading works on the client (+ tailwind hmr)", async () => {
+ expect(dev_server).not.toBeUndefined();
+ expect(baseUrl).not.toBeUndefined();
+
+ const result = Bun.spawnSync([bunExe(), "test/dev-server-puppeteer.ts", baseUrl], {
+ cwd: root,
+ env: bunEnv,
+ stdio: ["ignore", "inherit", "inherit"],
+ });
+ expect(result.exitCode).toBe(0);
+}, 30000);
+
+afterAll(() => {
+ Bun.spawnSync(["pkill", "-P", dev_server!.pid.toString()]);
+});
diff --git a/test/integration/next/default-pages-dir/test/next-build.test.ts b/test/integration/next/default-pages-dir/test/next-build.test.ts
new file mode 100644
index 000000000..0a00c158e
--- /dev/null
+++ b/test/integration/next/default-pages-dir/test/next-build.test.ts
@@ -0,0 +1,141 @@
+import { afterAll, beforeAll, describe, expect, test } from "bun:test";
+import { bunEnv, bunExe } from "../../../../harness";
+import { copyFileSync, cpSync, mkdtempSync, readFileSync, readdirSync, rmSync, symlinkSync, writeFileSync } from "fs";
+import { tmpdir } from "os";
+import { join } from "path";
+import { cp } from "fs/promises";
+
+const root = join(import.meta.dir, "../");
+
+let build_passed = false;
+
+async function tempDirToBuildIn() {
+ const dir = mkdtempSync(join(tmpdir(), "bun-next-build-"));
+ const copy = [
+ ".eslintrc.json",
+ "bun.lockb",
+ "next.config.js",
+ "next.config.js",
+ "package.json",
+ "postcss.config.js",
+ "public",
+ "src",
+ "tailwind.config.ts",
+ ];
+ await Promise.all(copy.map(x => cp(join(root, x), join(dir, x), { recursive: true })));
+ cpSync(join(root, "src/Counter1.txt"), join(dir, "src/Counter.tsx"));
+ cpSync(join(root, "tsconfig_for_build.json"), join(dir, "tsconfig.json"));
+ symlinkSync(join(root, "node_modules"), join(dir, "node_modules"));
+ return dir;
+}
+
+function readdirRecursive(dir: string) {
+ let results: string[] = [];
+
+ readdirSync(dir, { withFileTypes: true }).forEach(file => {
+ if (file.isDirectory()) {
+ results = results.concat(readdirRecursive(join(dir, file.name)).map(x => join(file.name, x)));
+ } else {
+ results.push(file.name);
+ }
+ });
+
+ return results;
+}
+
+function hashAllFiles(dir: string) {
+ const files = readdirRecursive(dir).sort();
+ const hashes: Record<string, string> = {};
+ for (const file of files) {
+ const hash = new Bun.CryptoHasher("sha256");
+ hash.update(readFileSync(join(dir, file)));
+ hashes[file] = hash.digest("hex");
+ }
+ return hashes;
+}
+
+test("next build works", async () => {
+ copyFileSync(join(root, "src/Counter1.txt"), join(root, "src/Counter.tsx"));
+
+ const install = Bun.spawnSync([bunExe(), "i"], { cwd: root, env: bunEnv });
+ if (install.exitCode !== 0) {
+ throw new Error("Failed to install dependencies");
+ }
+
+ const bunDir = await tempDirToBuildIn();
+ const nodeDir = await tempDirToBuildIn();
+
+ const bunBuild = await Bun.spawn([bunExe(), "--bun", "node_modules/.bin/next", "build"], {
+ cwd: bunDir,
+ // env: bunEnv,
+ stdio: ["ignore", "pipe", "inherit"],
+ env: {
+ ...bunEnv,
+ NODE_ENV: "production",
+ },
+ });
+ const nodeBuild = await Bun.spawn(["node", "node_modules/.bin/next", "build"], {
+ cwd: nodeDir,
+ env: bunEnv,
+ stdio: ["ignore", "pipe", "inherit"],
+ });
+ await Promise.all([bunBuild.exited, nodeBuild.exited]);
+ expect(nodeBuild.exitCode).toBe(0);
+ expect(bunBuild.exitCode).toBe(0);
+
+ const bunCliOutput = await Bun.readableStreamToText(bunBuild.stdout);
+ const nodeCliOutput = await Bun.readableStreamToText(nodeBuild.stdout);
+
+ expect(bunCliOutput).toBe(nodeCliOutput);
+
+ const bunBuildDir = join(bunDir, ".next");
+ const nodeBuildDir = join(nodeDir, ".next");
+
+ const toRemove = [
+ // these have timestamps and absolute paths in them
+ "trace",
+ "cache",
+ "required-server-files.json",
+ // these have "signing keys", not sure what they are tbh
+ "prerender-manifest.json",
+ "prerender-manifest.js",
+ // these are similar but i feel like there might be something we can fix to make them the same
+ "next-minimal-server.js.nft.json",
+ "next-server.js.nft.json",
+ // not sorted lol
+ "server/pages-manifest.json",
+ ];
+ for (const key of toRemove) {
+ rmSync(join(bunBuildDir, key), { recursive: true });
+ rmSync(join(nodeBuildDir, key), { recursive: true });
+ }
+
+ const bunBuildHash = hashAllFiles(bunBuildDir);
+ const nodeBuildHash = hashAllFiles(nodeBuildDir);
+
+ try {
+ expect(bunBuildHash).toEqual(nodeBuildHash);
+ } catch (error) {
+ console.log("bunBuildDir", bunBuildDir);
+ console.log("nodeBuildDir", nodeBuildDir);
+
+ // print diffs for every file if not the same
+ for (const key in bunBuildHash) {
+ if (bunBuildHash[key] !== nodeBuildHash[key]) {
+ console.log(key + ":");
+ try {
+ expect(readFileSync(join(bunBuildDir, key)).toString()).toBe(
+ readFileSync(join(nodeBuildDir, key)).toString(),
+ );
+ } catch (error) {
+ console.error(error);
+ }
+ }
+ }
+ throw error;
+ }
+
+ build_passed = true;
+}, 300000);
+
+const version_string = "[production needs a constant string]";
diff --git a/test/integration/next/default-pages-dir/tsconfig.json b/test/integration/next/default-pages-dir/tsconfig.json
new file mode 100644
index 000000000..b8629571f
--- /dev/null
+++ b/test/integration/next/default-pages-dir/tsconfig.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "../../../../packages/bun-types/dist/types.d.ts"],
+ "exclude": ["node_modules"]
+}
diff --git a/test/integration/next/default-pages-dir/tsconfig_for_build.json b/test/integration/next/default-pages-dir/tsconfig_for_build.json
new file mode 100644
index 000000000..476ee3ebc
--- /dev/null
+++ b/test/integration/next/default-pages-dir/tsconfig_for_build.json
@@ -0,0 +1,23 @@
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "paths": {
+ "@/*": ["./src/*"]
+ },
+ "types": ["bun-types"]
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
+ "exclude": ["node_modules"]
+}
diff --git a/test/js/node/async_hooks/async_hooks.node.test.ts b/test/js/node/async_hooks/async_hooks.node.test.ts
index 3d6183948..5fc56a39b 100644
--- a/test/js/node/async_hooks/async_hooks.node.test.ts
+++ b/test/js/node/async_hooks/async_hooks.node.test.ts
@@ -1,13 +1,13 @@
-import { AsyncLocalStorage } from "async_hooks";
+import { AsyncLocalStorage, AsyncResource } from "async_hooks";
import assert from "assert";
test("node async_hooks.AsyncLocalStorage enable disable", async done => {
- const asyncLocalStorage = new AsyncLocalStorage();
+ const asyncLocalStorage = new AsyncLocalStorage<Map<string, any>>();
asyncLocalStorage.run(new Map(), () => {
- asyncLocalStorage.getStore().set("foo", "bar");
+ asyncLocalStorage.getStore()!.set("foo", "bar");
process.nextTick(() => {
- assert.strictEqual(asyncLocalStorage.getStore().get("foo"), "bar");
+ assert.strictEqual(asyncLocalStorage.getStore()!.get("foo"), "bar");
process.nextTick(() => {
assert.strictEqual(asyncLocalStorage.getStore(), undefined);
});
@@ -24,7 +24,7 @@ test("node async_hooks.AsyncLocalStorage enable disable", async done => {
process.nextTick(() => {
assert.strictEqual(asyncLocalStorage.getStore(), undefined);
asyncLocalStorage.run(new Map().set("bar", "foo"), () => {
- assert.strictEqual(asyncLocalStorage.getStore().get("bar"), "foo");
+ assert.strictEqual(asyncLocalStorage.getStore()!.get("bar"), "foo");
done();
});
@@ -32,3 +32,21 @@ test("node async_hooks.AsyncLocalStorage enable disable", async done => {
});
});
});
+
+test("AsyncResource.prototype.bind", () => {
+ const localStorage = new AsyncLocalStorage<true>();
+ let ar!: AsyncResource;
+ localStorage.run(true, () => {
+ ar = new AsyncResource("test");
+ });
+ expect(ar.bind(() => localStorage.getStore())()).toBe(true);
+});
+
+test("AsyncResource.bind", () => {
+ const localStorage = new AsyncLocalStorage<true>();
+ let fn!: () => true | undefined;
+ localStorage.run(true, () => {
+ fn = AsyncResource.bind(() => localStorage.getStore());
+ });
+ expect(fn()).toBe(true);
+});
diff --git a/test/js/node/module/modulePrototypeOverwrite-fixture.cjs b/test/js/node/module/modulePrototypeOverwrite-fixture.cjs
new file mode 100644
index 000000000..eecab81c1
--- /dev/null
+++ b/test/js/node/module/modulePrototypeOverwrite-fixture.cjs
@@ -0,0 +1 @@
+module.exports = require("hook");
diff --git a/test/js/node/module/modulePrototypeOverwrite.cjs b/test/js/node/module/modulePrototypeOverwrite.cjs
new file mode 100644
index 000000000..4e84026a6
--- /dev/null
+++ b/test/js/node/module/modulePrototypeOverwrite.cjs
@@ -0,0 +1,17 @@
+// This behavior is required for Next.js to work
+const eql = require("assert").deepStrictEqual;
+const Module = require("module");
+
+const old = Module.prototype.require;
+Module.prototype.require = function (str) {
+ if (str === "hook") return "winner";
+ return {
+ wrap: old.call(this, str),
+ };
+};
+
+// this context has the new require
+const result = require("./modulePrototypeOverwrite-fixture.cjs");
+eql(result, { wrap: "winner" });
+
+console.log("--pass--");
diff --git a/test/js/node/module/node-module-module.test.js b/test/js/node/module/node-module-module.test.js
index 26fbb6fab..5ac48d426 100644
--- a/test/js/node/module/node-module-module.test.js
+++ b/test/js/node/module/node-module-module.test.js
@@ -71,6 +71,17 @@ test("Overwriting _resolveFilename", () => {
expect(exitCode).toBe(0);
});
+test("Overwriting Module.prototype.require", () => {
+ const { stdout, exitCode } = Bun.spawnSync({
+ cmd: [bunExe(), "run", path.join(import.meta.dir, "modulePrototypeOverwrite.cjs")],
+ env: bunEnv,
+ stderr: "inherit",
+ });
+
+ expect(stdout.toString().trim().endsWith("--pass--")).toBe(true);
+ expect(exitCode).toBe(0);
+});
+
test("Module.prototype._compile", () => {
const module = new Module("module id goes here");
const starting_exports = module.exports;
diff --git a/test/js/node/process/process-stdio.test.ts b/test/js/node/process/process-stdio.test.ts
index 463ab5fda..5349587af 100644
--- a/test/js/node/process/process-stdio.test.ts
+++ b/test/js/node/process/process-stdio.test.ts
@@ -5,7 +5,7 @@ import { isatty } from "tty";
test("process.stdin", () => {
expect(process.stdin).toBeDefined();
- expect(process.stdout.isTTY).toBe(isatty(0));
+ expect(process.stdin.isTTY).toBe(isatty(0) ? true : undefined);
expect(process.stdin.on("close", function () {})).toBe(process.stdin);
expect(process.stdin.once("end", function () {})).toBe(process.stdin);
});
diff --git a/test/js/node/stream/node-stream.test.js b/test/js/node/stream/node-stream.test.js
index bc6a4fcfb..ddbd2bc7a 100644
--- a/test/js/node/stream/node-stream.test.js
+++ b/test/js/node/stream/node-stream.test.js
@@ -197,6 +197,7 @@ describe("PassThrough", () => {
const ttyStreamsTest = `
import tty from "tty";
+import fs from "fs";
import { dlopen } from "bun:ffi";
@@ -278,10 +279,11 @@ describe("TTY", () => {
close(child_fd);
});
it("process.stdio tty", () => {
- expect(process.stdin instanceof tty.ReadStream).toBe(true);
+ // this isnt run in a tty, so stdin will not appear to be a tty
+ expect(process.stdin instanceof fs.ReadStream).toBe(true);
expect(process.stdout instanceof tty.WriteStream).toBe(true);
expect(process.stderr instanceof tty.WriteStream).toBe(true);
- expect(process.stdin.isTTY).toBeDefined();
+ expect(process.stdin.isTTY).toBeUndefined();
expect(process.stdout.isTTY).toBeDefined();
expect(process.stderr.isTTY).toBeDefined();
});
@@ -311,7 +313,11 @@ it("TTY streams", () => {
});
expect(stdout.toString()).toBe("");
- expect(stderr.toString()).toContain("0 fail");
+ try {
+ expect(stderr.toString()).toContain("0 fail");
+ } catch (error) {
+ throw new Error(stderr.toString());
+ }
expect(exitCode).toBe(0);
});
diff --git a/test/js/third_party/got/bun.lockb b/test/js/third_party/got/bun.lockb
new file mode 100755
index 000000000..7dbe60317
--- /dev/null
+++ b/test/js/third_party/got/bun.lockb
Binary files differ
diff --git a/test/js/third_party/prisma/bun.lockb b/test/js/third_party/prisma/bun.lockb
new file mode 100755
index 000000000..65d0238e5
--- /dev/null
+++ b/test/js/third_party/prisma/bun.lockb
Binary files differ
diff --git a/test/js/third_party/yargs/bun.lockb b/test/js/third_party/yargs/bun.lockb
new file mode 100755
index 000000000..6b527d00f
--- /dev/null
+++ b/test/js/third_party/yargs/bun.lockb
Binary files differ