aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/bun.js')
-rw-r--r--src/bun.js/api/bun.zig10
-rw-r--r--src/bun.js/api/server.zig3
-rw-r--r--src/bun.js/bindings/BunPlugin.cpp254
-rw-r--r--src/bun.js/bindings/BunPlugin.h22
-rw-r--r--src/bun.js/bindings/BunString.cpp32
-rw-r--r--src/bun.js/bindings/ImportMetaObject.cpp32
-rw-r--r--src/bun.js/bindings/JSBundlerPlugin.cpp2
-rw-r--r--src/bun.js/bindings/JSSocketAddress.cpp8
-rw-r--r--src/bun.js/bindings/JSSocketAddress.h3
-rw-r--r--src/bun.js/bindings/ModuleLoader.cpp4
-rw-r--r--src/bun.js/bindings/Process.cpp2
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.cpp76
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.h5
-rw-r--r--src/bun.js/bindings/bindings.zig7
-rw-r--r--src/bun.js/bindings/headers-handwritten.h23
-rw-r--r--src/bun.js/bindings/isBuiltinModule.cpp98
-rw-r--r--src/bun.js/bindings/isBuiltinModule.h5
-rw-r--r--src/bun.js/javascript.zig1
-rw-r--r--src/bun.js/modules/NodeModuleModule.h17
-rw-r--r--src/bun.js/webcore/request.zig27
20 files changed, 471 insertions, 160 deletions
diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig
index 966c82d38..949ba402c 100644
--- a/src/bun.js/api/bun.zig
+++ b/src/bun.js/api/bun.zig
@@ -782,11 +782,17 @@ fn doResolveWithArgs(
var errorable: ErrorableString = undefined;
var query_string = ZigString.Empty;
+ const specifier_decoded = if (specifier.hasPrefixComptime("file://"))
+ bun.JSC.URL.pathFromFileURL(specifier)
+ else
+ specifier.dupeRef();
+ defer specifier_decoded.deref();
+
if (comptime is_file_path) {
VirtualMachine.resolveFilePathForAPI(
&errorable,
ctx.ptr(),
- specifier,
+ specifier_decoded,
from,
&query_string,
is_esm,
@@ -795,7 +801,7 @@ fn doResolveWithArgs(
VirtualMachine.resolveForAPI(
&errorable,
ctx.ptr(),
- specifier,
+ specifier_decoded,
from,
&query_string,
is_esm,
diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig
index 9d4a8a133..3fe411f39 100644
--- a/src/bun.js/api/server.zig
+++ b/src/bun.js/api/server.zig
@@ -4859,6 +4859,9 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
extern fn JSSocketAddress__create(global: *JSC.JSGlobalObject, ip: JSValue, port: i32, is_ipv6: bool) JSValue;
pub fn requestIP(this: *ThisServer, request: *JSC.WebCore.Request) JSC.JSValue {
+ if (this.config.address == .unix) {
+ return JSValue.jsNull();
+ }
return if (request.request_context.getRemoteSocketInfo()) |info|
JSSocketAddress__create(
this.globalThis,
diff --git a/src/bun.js/bindings/BunPlugin.cpp b/src/bun.js/bindings/BunPlugin.cpp
index 129d7816b..b53fcf313 100644
--- a/src/bun.js/bindings/BunPlugin.cpp
+++ b/src/bun.js/bindings/BunPlugin.cpp
@@ -17,8 +17,10 @@
#include "JavaScriptCore/RegExpObject.h"
#include "JavaScriptCore/JSPromise.h"
#include "BunClientData.h"
-
+#include "isBuiltinModule.h"
#include "JavaScriptCore/RegularExpression.h"
+#include "JavaScriptCore/JSMap.h"
+#include "JavaScriptCore/JSMapInlines.h"
namespace Zig {
@@ -86,6 +88,76 @@ static EncodedJSValue jsFunctionAppendOnLoadPluginBody(JSC::JSGlobalObject* glob
return JSValue::encode(jsUndefined());
}
+static EncodedJSValue jsFunctionAppendVirtualModulePluginBody(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe)
+{
+ JSC::VM& vm = globalObject->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (callframe->argumentCount() < 2) {
+ throwException(globalObject, scope, createError(globalObject, "module() needs 2 arguments: a module ID and a function to call"_s));
+ return JSValue::encode(jsUndefined());
+ }
+
+ JSValue moduleIdValue = callframe->uncheckedArgument(0);
+ JSValue functionValue = callframe->uncheckedArgument(1);
+
+ if (!moduleIdValue.isString()) {
+ throwException(globalObject, scope, createError(globalObject, "module() expects first argument to be a string for the module ID"_s));
+ return JSValue::encode(jsUndefined());
+ }
+
+ if (!functionValue.isCallable()) {
+ throwException(globalObject, scope, createError(globalObject, "module() expects second argument to be a function"_s));
+ return JSValue::encode(jsUndefined());
+ }
+
+ String moduleId = moduleIdValue.toWTFString(globalObject);
+ RETURN_IF_EXCEPTION(scope, encodedJSValue());
+
+ if (moduleId.isEmpty()) {
+ throwException(globalObject, scope, createError(globalObject, "virtual module cannot be blank"_s));
+ return JSValue::encode(jsUndefined());
+ }
+
+ if (Bun::isBuiltinModule(moduleId)) {
+ throwException(globalObject, scope, createError(globalObject, makeString("module() cannot be used to override builtin module \""_s, moduleId, "\""_s)));
+ return JSValue::encode(jsUndefined());
+ }
+
+ if (moduleId.startsWith("."_s)) {
+ throwException(globalObject, scope, createError(globalObject, "virtual module cannot start with \".\""_s));
+ return JSValue::encode(jsUndefined());
+ }
+
+ Zig::GlobalObject* global = Zig::jsCast<Zig::GlobalObject*>(globalObject);
+ if (global->onLoadPlugins.virtualModules == nullptr) {
+ global->onLoadPlugins.virtualModules = new BunPlugin::VirtualModuleMap;
+ }
+ auto* virtualModules = global->onLoadPlugins.virtualModules;
+
+ virtualModules->set(moduleId, JSC::Strong<JSC::JSObject> { vm, jsCast<JSC::JSObject*>(functionValue) });
+
+ JSMap* esmRegistry;
+
+ if (auto loaderValue = global->getIfPropertyExists(global, JSC::Identifier::fromString(vm, "Loader"_s))) {
+ if (auto registryValue = loaderValue.getObject()->getIfPropertyExists(global, JSC::Identifier::fromString(vm, "registry"_s))) {
+ esmRegistry = jsCast<JSC::JSMap*>(registryValue);
+ }
+ }
+
+ global->requireMap()->remove(globalObject, moduleIdValue);
+ esmRegistry && esmRegistry->remove(globalObject, moduleIdValue);
+
+ // bool hasBeenRequired = global->requireMap()->has(globalObject, moduleIdValue);
+ // bool hasBeenImported = esmRegistry && esmRegistry->has(globalObject, moduleIdValue);
+ // if (hasBeenRequired || hasBeenImported) {
+ // // callAndReplaceModule(global, moduleIdValue, functionValue, global->requireMap(), esmRegistry, hasBeenRequired, hasBeenImported);
+ // // RETURN_IF_EXCEPTION(scope, encodedJSValue());
+ // }
+
+ return JSValue::encode(jsUndefined());
+}
+
static EncodedJSValue jsFunctionAppendOnResolvePluginBody(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe, BunPluginTarget target, BunPlugin::Base& plugin, void* ctx, OnAppendPluginCallback callback)
{
JSC::VM& vm = globalObject->vm();
@@ -143,7 +215,7 @@ static EncodedJSValue jsFunctionAppendOnResolvePluginGlobal(JSC::JSGlobalObject*
{
Zig::GlobalObject* global = Zig::jsCast<Zig::GlobalObject*>(globalObject);
- auto& plugins = global->onResolvePlugins[target];
+ auto& plugins = global->onResolvePlugins;
auto callback = Bun__onDidAppendPlugin;
return jsFunctionAppendOnResolvePluginBody(globalObject, callframe, target, plugins, global->bunVM(), callback);
}
@@ -152,7 +224,7 @@ static EncodedJSValue jsFunctionAppendOnLoadPluginGlobal(JSC::JSGlobalObject* gl
{
Zig::GlobalObject* global = Zig::jsCast<Zig::GlobalObject*>(globalObject);
- auto& plugins = global->onLoadPlugins[target];
+ auto& plugins = global->onLoadPlugins;
auto callback = Bun__onDidAppendPlugin;
return jsFunctionAppendOnLoadPluginBody(globalObject, callframe, target, plugins, global->bunVM(), callback);
}
@@ -182,6 +254,11 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionAppendOnResolvePluginBun, (JSC::JSGlobalObjec
return jsFunctionAppendOnResolvePluginGlobal(globalObject, callframe, BunPluginTargetBun);
}
+JSC_DEFINE_HOST_FUNCTION(jsFunctionAppendVirtualModule, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe))
+{
+ return jsFunctionAppendVirtualModulePluginBody(globalObject, callframe);
+}
+
JSC_DEFINE_HOST_FUNCTION(jsFunctionAppendOnResolvePluginBrowser, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe))
{
return jsFunctionAppendOnResolvePluginGlobal(globalObject, callframe, BunPluginTargetBrowser);
@@ -190,12 +267,12 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionAppendOnResolvePluginBrowser, (JSC::JSGlobalO
extern "C" EncodedJSValue jsFunctionBunPluginClear(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe)
{
Zig::GlobalObject* global = reinterpret_cast<Zig::GlobalObject*>(globalObject);
- for (uint8_t i = 0; i < BunPluginTargetMax + 1; i++) {
- global->onLoadPlugins[i].fileNamespace.clear();
- global->onResolvePlugins[i].fileNamespace.clear();
- global->onLoadPlugins[i].groups.clear();
- global->onResolvePlugins[i].namespaces.clear();
- }
+ global->onLoadPlugins.fileNamespace.clear();
+ global->onResolvePlugins.fileNamespace.clear();
+ global->onLoadPlugins.groups.clear();
+ global->onResolvePlugins.namespaces.clear();
+
+ delete global->onLoadPlugins.virtualModules;
return JSValue::encode(jsUndefined());
}
@@ -239,76 +316,37 @@ extern "C" EncodedJSValue setupBunPlugin(JSC::JSGlobalObject* globalObject, JSC:
}
JSFunction* setupFunction = jsCast<JSFunction*>(setupFunctionValue);
- JSObject* builderObject = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 3);
-
- switch (target) {
- case BunPluginTargetNode: {
- builderObject->putDirect(vm, Identifier::fromString(vm, "target"_s), jsString(vm, String("node"_s)), 0);
- builderObject->putDirectNativeFunction(
- vm,
- globalObject,
- JSC::Identifier::fromString(vm, "onLoad"_s),
- 1,
- jsFunctionAppendOnLoadPluginNode,
- ImplementationVisibility::Public,
- NoIntrinsic,
- JSC::PropertyAttribute::DontDelete | 0);
- builderObject->putDirectNativeFunction(
- vm,
- globalObject,
- JSC::Identifier::fromString(vm, "onResolve"_s),
- 1,
- jsFunctionAppendOnResolvePluginNode,
- ImplementationVisibility::Public,
- NoIntrinsic,
- JSC::PropertyAttribute::DontDelete | 0);
- break;
- }
- case BunPluginTargetBun: {
- builderObject->putDirect(vm, Identifier::fromString(vm, "target"_s), jsString(vm, String("bun"_s)), 0);
- builderObject->putDirectNativeFunction(
- vm,
- globalObject,
- JSC::Identifier::fromString(vm, "onLoad"_s),
- 1,
- jsFunctionAppendOnLoadPluginBun,
- ImplementationVisibility::Public,
- NoIntrinsic,
- JSC::PropertyAttribute::DontDelete | 0);
- builderObject->putDirectNativeFunction(
- vm,
- globalObject,
- JSC::Identifier::fromString(vm, "onResolve"_s),
- 1,
- jsFunctionAppendOnResolvePluginBun,
- ImplementationVisibility::Public,
- NoIntrinsic,
- JSC::PropertyAttribute::DontDelete | 0);
- break;
- }
- case BunPluginTargetBrowser: {
- builderObject->putDirect(vm, Identifier::fromString(vm, "target"_s), jsString(vm, String("browser"_s)), 0);
- builderObject->putDirectNativeFunction(
- vm,
- globalObject,
- JSC::Identifier::fromString(vm, "onLoad"_s),
- 1,
- jsFunctionAppendOnLoadPluginBrowser,
- ImplementationVisibility::Public,
- NoIntrinsic,
- JSC::PropertyAttribute::DontDelete | 0);
- builderObject->putDirectNativeFunction(
- vm,
- globalObject,
- JSC::Identifier::fromString(vm, "onResolve"_s),
- 1,
- jsFunctionAppendOnResolvePluginBrowser,
- ImplementationVisibility::Public,
- NoIntrinsic,
- JSC::PropertyAttribute::DontDelete | 0);
- break;
- }
- }
+ JSObject* builderObject = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 4);
+
+ builderObject->putDirect(vm, Identifier::fromString(vm, "target"_s), jsString(vm, String("bun"_s)), 0);
+ builderObject->putDirectNativeFunction(
+ vm,
+ globalObject,
+ JSC::Identifier::fromString(vm, "onLoad"_s),
+ 1,
+ jsFunctionAppendOnLoadPluginBun,
+ ImplementationVisibility::Public,
+ NoIntrinsic,
+ JSC::PropertyAttribute::DontDelete | 0);
+ builderObject->putDirectNativeFunction(
+ vm,
+ globalObject,
+ JSC::Identifier::fromString(vm, "onResolve"_s),
+ 1,
+ jsFunctionAppendOnResolvePluginBun,
+ ImplementationVisibility::Public,
+ NoIntrinsic,
+ JSC::PropertyAttribute::DontDelete | 0);
+
+ builderObject->putDirectNativeFunction(
+ vm,
+ globalObject,
+ JSC::Identifier::fromString(vm, "module"_s),
+ 1,
+ jsFunctionAppendVirtualModule,
+ ImplementationVisibility::Public,
+ NoIntrinsic,
+ JSC::PropertyAttribute::DontDelete | 0);
JSC::MarkedArgumentBuffer args;
args.append(builderObject);
@@ -329,9 +367,7 @@ extern "C" EncodedJSValue setupBunPlugin(JSC::JSGlobalObject* globalObject, JSC:
extern "C" EncodedJSValue jsFunctionBunPlugin(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe)
{
Zig::GlobalObject* global = reinterpret_cast<Zig::GlobalObject*>(globalObject);
- BunPluginTarget target = global->defaultBunPluginTarget;
-
- return setupBunPlugin(globalObject, callframe, target);
+ return setupBunPlugin(globalObject, callframe, BunPluginTargetBun);
}
void BunPlugin::Group::append(JSC::VM& vm, JSC::RegExp* filter, JSC::JSFunction* func)
@@ -513,10 +549,60 @@ EncodedJSValue BunPlugin::OnResolve::run(JSC::JSGlobalObject* globalObject, BunS
extern "C" JSC::EncodedJSValue Bun__runOnResolvePlugins(Zig::GlobalObject* globalObject, BunString* namespaceString, BunString* path, BunString* from, BunPluginTarget target)
{
- return globalObject->onResolvePlugins[target].run(globalObject, namespaceString, path, from);
+ return globalObject->onResolvePlugins.run(globalObject, namespaceString, path, from);
}
extern "C" JSC::EncodedJSValue Bun__runOnLoadPlugins(Zig::GlobalObject* globalObject, BunString* namespaceString, BunString* path, BunPluginTarget target)
{
- return globalObject->onLoadPlugins[target].run(globalObject, namespaceString, path);
+ return globalObject->onLoadPlugins.run(globalObject, namespaceString, path);
+}
+
+namespace Bun {
+JSC::JSValue runVirtualModule(Zig::GlobalObject* globalObject, BunString* specifier)
+{
+ auto fallback = [&]() -> JSC::JSValue {
+ return JSValue::decode(Bun__runVirtualModule(globalObject, specifier));
+ };
+
+ if (!globalObject->onLoadPlugins.virtualModules) {
+ return fallback();
+ }
+ auto& virtualModules = *globalObject->onLoadPlugins.virtualModules;
+ WTF::String specifierString = Bun::toWTFString(*specifier);
+ if (auto virtualModuleFn = virtualModules.get(specifierString)) {
+ auto& vm = globalObject->vm();
+ JSC::JSObject* function = virtualModuleFn.get();
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+
+ JSC::MarkedArgumentBuffer arguments;
+ JSC::CallData callData = JSC::getCallData(function);
+ RELEASE_ASSERT(callData.type != JSC::CallData::Type::None);
+
+ auto result = call(globalObject, function, callData, JSC::jsUndefined(), arguments);
+ RETURN_IF_EXCEPTION(throwScope, JSC::jsUndefined());
+
+ if (auto* promise = JSC::jsDynamicCast<JSPromise*>(result)) {
+ switch (promise->status(vm)) {
+ case JSPromise::Status::Rejected:
+ case JSPromise::Status::Pending: {
+ return promise;
+ }
+ case JSPromise::Status::Fulfilled: {
+ result = promise->result(vm);
+ break;
+ }
+ }
+ }
+
+ if (!result.isObject()) {
+ JSC::throwTypeError(globalObject, throwScope, "virtual module expects an object returned"_s);
+ return JSC::jsUndefined();
+ }
+
+ return result;
+ }
+
+ return fallback();
}
+
+} \ No newline at end of file
diff --git a/src/bun.js/bindings/BunPlugin.h b/src/bun.js/bindings/BunPlugin.h
index cf37b739b..f4d09883d 100644
--- a/src/bun.js/bindings/BunPlugin.h
+++ b/src/bun.js/bindings/BunPlugin.h
@@ -15,6 +15,8 @@ using namespace JSC;
class BunPlugin {
public:
+ using VirtualModuleMap = WTF::HashMap<String, JSC::Strong<JSC::JSObject>>;
+
// This is a list of pairs of regexps and functions to match against
class Group {
@@ -67,7 +69,15 @@ public:
{
}
- EncodedJSValue run(JSC::JSGlobalObject* globalObject, BunString* namespaceString, BunString* path);
+ VirtualModuleMap* virtualModules = nullptr;
+ JSC::EncodedJSValue run(JSC::JSGlobalObject* globalObject, BunString* namespaceString, BunString* path);
+
+ ~OnLoad()
+ {
+ if (virtualModules) {
+ delete virtualModules;
+ }
+ }
};
class OnResolve final : public Base {
@@ -78,8 +88,14 @@ public:
{
}
- EncodedJSValue run(JSC::JSGlobalObject* globalObject, BunString* namespaceString, BunString* path, BunString* importer);
+ JSC::EncodedJSValue run(JSC::JSGlobalObject* globalObject, BunString* namespaceString, BunString* path, BunString* importer);
};
};
-} // namespace Zig \ No newline at end of file
+class GlobalObject;
+
+} // namespace Zig
+
+namespace Bun {
+JSC::JSValue runVirtualModule(Zig::GlobalObject*, BunString* specifier);
+} \ No newline at end of file
diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp
index 416d5d334..31b331111 100644
--- a/src/bun.js/bindings/BunString.cpp
+++ b/src/bun.js/bindings/BunString.cpp
@@ -190,22 +190,6 @@ BunString toStringRef(WTF::StringImpl* wtfString)
return { BunStringTag::WTFStringImpl, { .wtf = wtfString } };
}
-BunString fromString(WTF::String& wtfString)
-{
- if (wtfString.isEmpty())
- return { BunStringTag::Empty };
-
- return { BunStringTag::WTFStringImpl, { .wtf = wtfString.impl() } };
-}
-
-BunString fromString(WTF::StringImpl* wtfString)
-{
- if (wtfString->isEmpty())
- return { BunStringTag::Empty };
-
- return { BunStringTag::WTFStringImpl, { .wtf = wtfString } };
-}
-
}
extern "C" JSC::EncodedJSValue BunString__toJS(JSC::JSGlobalObject* globalObject, BunString* bunString)
@@ -252,7 +236,7 @@ extern "C" BunString BunString__fromUTF8(const char* bytes, size_t length)
auto str = WTF::String::fromUTF8ReplacingInvalidSequences(reinterpret_cast<const LChar*>(bytes), length);
str.impl()->ref();
- return Bun::fromString(str);
+ return Bun::toString(str);
}
extern "C" BunString BunString__fromLatin1(const char* bytes, size_t length)
@@ -381,7 +365,17 @@ extern "C" BunString URL__getHref(BunString* input)
return Bun::toStringRef(url.string());
}
-extern "C" BunString URL__getHrefJoin(BunString* baseStr, BunString *relativeStr)
+extern "C" BunString URL__pathFromFileURL(BunString* input)
+{
+ auto&& str = Bun::toWTFString(*input);
+ auto url = WTF::URL(str);
+ if (!url.isValid() || url.isEmpty())
+ return { BunStringTag::Dead };
+
+ return Bun::toStringRef(url.fileSystemPath());
+}
+
+extern "C" BunString URL__getHrefJoin(BunString* baseStr, BunString* relativeStr)
{
auto base = Bun::toWTFString(*baseStr);
auto relative = Bun::toWTFString(*relativeStr);
@@ -455,4 +449,4 @@ extern "C" uint32_t URL__port(WTF::URL* url)
extern "C" BunString URL__pathname(WTF::URL* url)
{
return Bun::toStringRef(url->path().toStringWithoutCopying());
-} \ No newline at end of file
+}
diff --git a/src/bun.js/bindings/ImportMetaObject.cpp b/src/bun.js/bindings/ImportMetaObject.cpp
index 4160102a5..340c3319b 100644
--- a/src/bun.js/bindings/ImportMetaObject.cpp
+++ b/src/bun.js/bindings/ImportMetaObject.cpp
@@ -64,6 +64,12 @@ static EncodedJSValue functionRequireResolve(JSC::JSGlobalObject* globalObject,
JSC::JSValue moduleName = callFrame->argument(0);
auto doIt = [&](const WTF::String& fromStr) -> JSC::EncodedJSValue {
+ if (auto* virtualModules = jsCast<Zig::GlobalObject*>(globalObject)->onLoadPlugins.virtualModules) {
+ if (virtualModules->contains(fromStr)) {
+ return JSC::JSValue::encode(jsString(vm, fromStr));
+ }
+ }
+
BunString from = Bun::toString(fromStr);
auto result = Bun__resolveSyncWithSource(globalObject, JSC::JSValue::encode(moduleName), &from, false);
@@ -160,6 +166,14 @@ extern "C" EncodedJSValue functionImportMeta__resolveSync(JSC::JSGlobalObject* g
JSC__JSValue from;
bool isESM = true;
+ if (auto* virtualModules = jsCast<Zig::GlobalObject*>(globalObject)->onLoadPlugins.virtualModules) {
+ if (moduleName.isString()) {
+ if (virtualModules->contains(moduleName.toWTFString(globalObject))) {
+ return JSC::JSValue::encode(moduleName);
+ }
+ }
+ }
+
if (callFrame->argumentCount() > 1) {
if (callFrame->argumentCount() > 2) {
@@ -226,6 +240,7 @@ extern "C" EncodedJSValue functionImportMeta__resolveSyncPrivate(JSC::JSGlobalOb
{
JSC::VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+ auto* global = jsDynamicCast<Zig::GlobalObject*>(globalObject);
JSC::JSValue moduleName = callFrame->argument(0);
JSValue from = callFrame->argument(1);
@@ -239,8 +254,15 @@ extern "C" EncodedJSValue functionImportMeta__resolveSyncPrivate(JSC::JSGlobalOb
RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::JSValue {}));
+ if (auto* virtualModules = global->onLoadPlugins.virtualModules) {
+ if (moduleName.isString()) {
+ if (virtualModules->contains(moduleName.toWTFString(globalObject))) {
+ return JSC::JSValue::encode(moduleName);
+ }
+ }
+ }
+
if (!isESM) {
- auto* global = jsDynamicCast<Zig::GlobalObject*>(globalObject);
if (LIKELY(global)) {
auto overrideHandler = global->m_nodeModuleOverriddenResolveFilename.get();
if (UNLIKELY(overrideHandler)) {
@@ -289,6 +311,14 @@ JSC_DEFINE_HOST_FUNCTION(functionImportMeta__resolve,
JSC__JSValue from;
+ if (auto* virtualModules = jsCast<Zig::GlobalObject*>(globalObject)->onLoadPlugins.virtualModules) {
+ if (moduleName.isString()) {
+ if (virtualModules->contains(moduleName.toWTFString(globalObject))) {
+ return JSC::JSValue::encode(moduleName);
+ }
+ }
+ }
+
if (callFrame->argumentCount() > 1 && callFrame->argument(1).isString()) {
from = JSC::JSValue::encode(callFrame->argument(1));
} else {
diff --git a/src/bun.js/bindings/JSBundlerPlugin.cpp b/src/bun.js/bindings/JSBundlerPlugin.cpp
index 6ae266df7..d896d5b3d 100644
--- a/src/bun.js/bindings/JSBundlerPlugin.cpp
+++ b/src/bun.js/bindings/JSBundlerPlugin.cpp
@@ -31,6 +31,7 @@ namespace Bun {
extern "C" void JSBundlerPlugin__addError(void*, void*, JSC::EncodedJSValue, JSC::EncodedJSValue);
extern "C" void JSBundlerPlugin__onLoadAsync(void*, void*, JSC::EncodedJSValue, JSC::EncodedJSValue);
extern "C" void JSBundlerPlugin__onResolveAsync(void*, void*, JSC::EncodedJSValue, JSC::EncodedJSValue, JSC::EncodedJSValue);
+extern "C" void JSBundlerPlugin__onVirtualModulePlugin(void*, void*, JSC::EncodedJSValue, JSC::EncodedJSValue, JSC::EncodedJSValue);
JSC_DECLARE_HOST_FUNCTION(jsBundlerPluginFunction_addFilter);
JSC_DECLARE_HOST_FUNCTION(jsBundlerPluginFunction_addError);
@@ -154,6 +155,7 @@ public:
Bun::BundlerPlugin plugin;
JSC::LazyProperty<JSBundlerPlugin, JSC::JSFunction> onLoadFunction;
JSC::LazyProperty<JSBundlerPlugin, JSC::JSFunction> onResolveFunction;
+ JSC::LazyProperty<JSBundlerPlugin, JSC::JSFunction> moduleFunction;
JSC::LazyProperty<JSBundlerPlugin, JSC::JSFunction> setupFunction;
private:
diff --git a/src/bun.js/bindings/JSSocketAddress.cpp b/src/bun.js/bindings/JSSocketAddress.cpp
index 53084adb6..181507339 100644
--- a/src/bun.js/bindings/JSSocketAddress.cpp
+++ b/src/bun.js/bindings/JSSocketAddress.cpp
@@ -9,8 +9,7 @@ using namespace JSC;
namespace Bun {
namespace JSSocketAddress {
-// Using a structure with inlined offsets will be more lightweight than a class.
-
+// Using a structure with inlined offsets should be more lightweight than a class.
Structure* createStructure(VM& vm, JSGlobalObject* globalObject)
{
JSC::Structure* structure = globalObject->structureCache().emptyObjectStructureForPrototype(
@@ -48,13 +47,16 @@ Structure* createStructure(VM& vm, JSGlobalObject* globalObject)
extern "C" JSObject* JSSocketAddress__create(JSGlobalObject* globalObject, JSString* value, int32_t port, bool isIPv6)
{
+ static const NeverDestroyed<String> IPv4 = MAKE_STATIC_STRING_IMPL("IPv4");
+ static const NeverDestroyed<String> IPv6 = MAKE_STATIC_STRING_IMPL("IPv6");
+
VM& vm = globalObject->vm();
auto* global = jsCast<Zig::GlobalObject*>(globalObject);
JSObject* thisObject = constructEmptyObject(vm, global->JSSocketAddressStructure());
thisObject->putDirectOffset(vm, 0, value);
- thisObject->putDirectOffset(vm, 1, isIPv6 ? jsString(vm, Bun::JSSocketAddress::IPv6) : jsString(vm, Bun::JSSocketAddress::IPv4));
+ thisObject->putDirectOffset(vm, 1, isIPv6 ? jsString(vm, IPv6) : jsString(vm, IPv4));
thisObject->putDirectOffset(vm, 2, jsNumber(port));
return thisObject;
diff --git a/src/bun.js/bindings/JSSocketAddress.h b/src/bun.js/bindings/JSSocketAddress.h
index 5e374dac3..77bdca5d4 100644
--- a/src/bun.js/bindings/JSSocketAddress.h
+++ b/src/bun.js/bindings/JSSocketAddress.h
@@ -8,9 +8,6 @@ using namespace JSC;
namespace Bun {
namespace JSSocketAddress {
-static const NeverDestroyed<String> IPv4 = MAKE_STATIC_STRING_IMPL("IPv4");
-static const NeverDestroyed<String> IPv6 = MAKE_STATIC_STRING_IMPL("IPv6");
-
Structure* createStructure(VM& vm, JSGlobalObject* globalObject);
} // namespace JSSocketAddress
diff --git a/src/bun.js/bindings/ModuleLoader.cpp b/src/bun.js/bindings/ModuleLoader.cpp
index acda70e0a..127fb6965 100644
--- a/src/bun.js/bindings/ModuleLoader.cpp
+++ b/src/bun.js/bindings/ModuleLoader.cpp
@@ -458,7 +458,7 @@ JSValue fetchCommonJSModule(
}
}
- if (JSC::JSValue virtualModuleResult = JSValue::decode(Bun__runVirtualModule(globalObject, specifier))) {
+ if (JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, specifier)) {
JSPromise* promise = jsCast<JSPromise*>(handleVirtualModuleResult<true>(globalObject, virtualModuleResult, res, specifier, referrer));
switch (promise->status(vm)) {
case JSPromise::Status::Rejected: {
@@ -633,7 +633,7 @@ static JSValue fetchESMSourceCode(
}
}
- if (JSC::JSValue virtualModuleResult = JSValue::decode(Bun__runVirtualModule(globalObject, specifier))) {
+ if (JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, specifier)) {
return handleVirtualModuleResult<allowPromise>(globalObject, virtualModuleResult, res, specifier, referrer);
}
diff --git a/src/bun.js/bindings/Process.cpp b/src/bun.js/bindings/Process.cpp
index d82d403d3..1caff9be9 100644
--- a/src/bun.js/bindings/Process.cpp
+++ b/src/bun.js/bindings/Process.cpp
@@ -1835,7 +1835,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionKill,
return JSValue::encode(jsUndefined());
}
- return JSValue::encode(jsUndefined());
+ return JSValue::encode(jsBoolean(true));
}
extern "C" void Process__emitMessageEvent(Zig::GlobalObject* global, EncodedJSValue value)
diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp
index a7d2bb7e5..b9f2e4e46 100644
--- a/src/bun.js/bindings/ZigGlobalObject.cpp
+++ b/src/bun.js/bindings/ZigGlobalObject.cpp
@@ -4036,16 +4036,45 @@ extern "C" void JSC__JSGlobalObject__queueMicrotaskCallback(Zig::GlobalObject* g
globalObject->queueMicrotask(function, JSValue(bitwise_cast<double>(reinterpret_cast<uintptr_t>(ptr))), JSValue(bitwise_cast<double>(reinterpret_cast<uintptr_t>(callback))), jsUndefined(), jsUndefined());
}
-JSC::Identifier GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject,
+JSC::Identifier GlobalObject::moduleLoaderResolve(JSGlobalObject* jsGlobalObject,
JSModuleLoader* loader, JSValue key,
JSValue referrer, JSValue origin)
{
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(jsGlobalObject);
+
ErrorableString res;
res.success = false;
- BunString keyZ = Bun::toString(globalObject, key);
- BunString referrerZ = referrer && !referrer.isUndefinedOrNull() && referrer.isString() ? Bun::toString(globalObject, referrer) : BunStringEmpty;
+
+ if (key.isString()) {
+ if (auto* virtualModules = globalObject->onLoadPlugins.virtualModules) {
+ auto keyString = key.toWTFString(globalObject);
+ if (virtualModules->contains(keyString)) {
+ return JSC::Identifier::fromString(globalObject->vm(), keyString);
+ }
+ }
+ }
+
+ BunString keyZ;
+ if (key.isString()) {
+ auto moduleName = jsCast<JSString*>(key)->value(globalObject);
+ if (moduleName.startsWith("file://"_s)) {
+ auto url = WTF::URL(moduleName);
+ if (url.isValid() && !url.isEmpty()) {
+ keyZ = Bun::toStringRef(url.fileSystemPath());
+ } else {
+ keyZ = Bun::toStringRef(moduleName);
+ }
+ } else {
+ keyZ = Bun::toStringRef(moduleName);
+ }
+ } else {
+ keyZ = Bun::toStringRef(globalObject, key);
+ }
+ BunString referrerZ = referrer && !referrer.isUndefinedOrNull() && referrer.isString() ? Bun::toStringRef(globalObject, referrer) : BunStringEmpty;
ZigString queryString = { 0, 0 };
Zig__GlobalObject__resolve(&res, globalObject, &keyZ, &referrerZ, &queryString);
+ keyZ.deref();
+ referrerZ.deref();
if (res.success) {
if (queryString.len > 0) {
@@ -4060,25 +4089,60 @@ JSC::Identifier GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject,
}
}
-JSC::JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* globalObject,
+JSC::JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* jsGlobalObject,
JSModuleLoader*,
JSString* moduleNameValue,
JSValue parameters,
const SourceOrigin& sourceOrigin)
{
+ auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(jsGlobalObject);
JSC::VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
auto* promise = JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
+ if (auto* virtualModules = globalObject->onLoadPlugins.virtualModules) {
+ auto keyString = moduleNameValue->value(globalObject);
+ if (virtualModules->contains(keyString)) {
+ auto resolvedIdentifier = JSC::Identifier::fromString(vm, keyString);
+
+ auto result = JSC::importModule(globalObject, resolvedIdentifier,
+ JSC::jsUndefined(), parameters, JSC::jsUndefined());
+
+ RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
+ return result;
+ }
+ }
+
auto sourceURL = sourceOrigin.url();
ErrorableString resolved;
- auto moduleNameZ = Bun::toString(globalObject, moduleNameValue);
- auto sourceOriginZ = sourceURL.isEmpty() ? BunStringCwd : Bun::toString(sourceURL.fileSystemPath());
+ BunString moduleNameZ;
+
+ auto moduleName = moduleNameValue->value(globalObject);
+#if BUN_DEBUG
+ auto startRefCount = moduleName.impl()->refCount();
+#endif
+ if (moduleName.startsWith("file://"_s)) {
+ auto url = WTF::URL(moduleName);
+ if (url.isValid() && !url.isEmpty()) {
+ moduleNameZ = Bun::toStringRef(url.fileSystemPath());
+ } else {
+ moduleNameZ = Bun::toStringRef(moduleName);
+ }
+ } else {
+ moduleNameZ = Bun::toStringRef(moduleName);
+ }
+ auto sourceOriginZ = sourceURL.isEmpty() ? BunStringCwd : Bun::toStringRef(sourceURL.fileSystemPath());
ZigString queryString = { 0, 0 };
resolved.success = false;
Zig__GlobalObject__resolve(&resolved, globalObject, &moduleNameZ, &sourceOriginZ, &queryString);
+ moduleNameZ.deref();
+ sourceOriginZ.deref();
+#if BUN_DEBUG
+ // TODO: ASSERT doesnt work right now
+ RELEASE_ASSERT(startRefCount == moduleName.impl()->refCount());
+#endif
if (!resolved.success) {
throwException(scope, resolved.result.err, globalObject);
return promise->rejectWithCaughtException(globalObject, scope);
diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h
index 26111725b..035d18b08 100644
--- a/src/bun.js/bindings/ZigGlobalObject.h
+++ b/src/bun.js/bindings/ZigGlobalObject.h
@@ -382,9 +382,8 @@ public:
return false;
}
- BunPlugin::OnLoad onLoadPlugins[BunPluginTargetMax + 1] {};
- BunPlugin::OnResolve onResolvePlugins[BunPluginTargetMax + 1] {};
- BunPluginTarget defaultBunPluginTarget = BunPluginTargetBun;
+ BunPlugin::OnLoad onLoadPlugins {};
+ BunPlugin::OnResolve onResolvePlugins {};
// This increases the cache hit rate for JSC::VM's SourceProvider cache
// It also avoids an extra allocation for the SourceProvider
diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig
index 60f8f9376..f274f72d7 100644
--- a/src/bun.js/bindings/bindings.zig
+++ b/src/bun.js/bindings/bindings.zig
@@ -5496,6 +5496,7 @@ pub const URL = opaque {
extern fn URL__getHref(*String) String;
extern fn URL__getFileURLString(*String) String;
extern fn URL__getHrefJoin(*String, *String) String;
+ extern fn URL__pathFromFileURL(*String) String;
pub fn hrefFromString(str: bun.String) String {
JSC.markBinding(@src());
@@ -5516,6 +5517,12 @@ pub const URL = opaque {
return URL__getFileURLString(&input);
}
+ pub fn pathFromFileURL(str: bun.String) String {
+ JSC.markBinding(@src());
+ var input = str;
+ return URL__pathFromFileURL(&input);
+ }
+
/// This percent-encodes the URL, punycode-encodes the hostname, and returns the result
/// If it fails, the tag is marked Dead
pub fn hrefFromJS(value: JSValue, globalObject: *JSC.JSGlobalObject) String {
diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h
index e19be7abe..cef5d0804 100644
--- a/src/bun.js/bindings/headers-handwritten.h
+++ b/src/bun.js/bindings/headers-handwritten.h
@@ -17,10 +17,6 @@ typedef union BunStringImpl {
void* wtf;
} BunStringImpl;
-typedef struct BunString {
- BunStringTag tag;
- BunStringImpl impl;
-} BunString;
#else
typedef union BunStringImpl {
ZigString zig;
@@ -34,13 +30,15 @@ enum class BunStringTag : uint8_t {
StaticZigString = 3,
Empty = 4,
};
+#endif
typedef struct BunString {
BunStringTag tag;
BunStringImpl impl;
-} BunString;
-#endif
+ inline void ref();
+ inline void deref();
+} BunString;
typedef struct ZigErrorType {
ZigErrorCode code;
@@ -348,3 +346,16 @@ class ScriptArguments;
using ScriptArguments = Inspector::ScriptArguments;
#endif
+
+ALWAYS_INLINE void BunString::ref()
+{
+ if (this->tag == BunStringTag::WTFStringImpl) {
+ this->impl.wtf->ref();
+ }
+}
+ALWAYS_INLINE void BunString::deref()
+{
+ if (this->tag == BunStringTag::WTFStringImpl) {
+ this->impl.wtf->deref();
+ }
+} \ No newline at end of file
diff --git a/src/bun.js/bindings/isBuiltinModule.cpp b/src/bun.js/bindings/isBuiltinModule.cpp
new file mode 100644
index 000000000..b8e69f479
--- /dev/null
+++ b/src/bun.js/bindings/isBuiltinModule.cpp
@@ -0,0 +1,98 @@
+#include "root.h"
+
+static constexpr ASCIILiteral builtinModuleNamesSortedLength[] = {
+ "fs"_s,
+ "os"_s,
+ "v8"_s,
+ "vm"_s,
+ "ws"_s,
+ "bun"_s,
+ "dns"_s,
+ "net"_s,
+ "sys"_s,
+ "tls"_s,
+ "tty"_s,
+ "url"_s,
+ "http"_s,
+ "path"_s,
+ "repl"_s,
+ "util"_s,
+ "wasi"_s,
+ "zlib"_s,
+ "dgram"_s,
+ "http2"_s,
+ "https"_s,
+ "assert"_s,
+ "buffer"_s,
+ "crypto"_s,
+ "domain"_s,
+ "events"_s,
+ "module"_s,
+ "stream"_s,
+ "timers"_s,
+ "undici"_s,
+ "bun:ffi"_s,
+ "bun:jsc"_s,
+ "cluster"_s,
+ "console"_s,
+ "process"_s,
+ "bun:wrap"_s,
+ "punycode"_s,
+ "bun:test"_s,
+ "bun:main"_s,
+ "readline"_s,
+ "_tls_wrap"_s,
+ "constants"_s,
+ "inspector"_s,
+ "bun:sqlite"_s,
+ "path/posix"_s,
+ "path/win32"_s,
+ "perf_hooks"_s,
+ "stream/web"_s,
+ "util/types"_s,
+ "_http_agent"_s,
+ "_tls_common"_s,
+ "async_hooks"_s,
+ "detect-libc"_s,
+ "fs/promises"_s,
+ "querystring"_s,
+ "_http_client"_s,
+ "_http_common"_s,
+ "_http_server"_s,
+ "_stream_wrap"_s,
+ "dns/promises"_s,
+ "trace_events"_s,
+ "assert/strict"_s,
+ "child_process"_s,
+ "_http_incoming"_s,
+ "_http_outgoing"_s,
+ "_stream_duplex"_s,
+ "string_decoder"_s,
+ "worker_threads"_s,
+ "stream/promises"_s,
+ "timers/promises"_s,
+ "_stream_readable"_s,
+ "_stream_writable"_s,
+ "stream/consumers"_s,
+ "_stream_transform"_s,
+ "readline/promises"_s,
+ "inspector/promises"_s,
+ "_stream_passthrough"_s,
+ "diagnostics_channel"_s,
+};
+
+namespace Bun {
+
+bool isBuiltinModule(const String &namePossiblyWithNodePrefix) {
+ String name = namePossiblyWithNodePrefix;
+ if (name.startsWith("node:"_s))
+ name = name.substringSharingImpl(5);
+
+ for (auto &builtinModule : builtinModuleNamesSortedLength) {
+ if (name == builtinModule)
+ return true;
+ }
+ return false;
+}
+
+} // namespace Bun \ No newline at end of file
diff --git a/src/bun.js/bindings/isBuiltinModule.h b/src/bun.js/bindings/isBuiltinModule.h
new file mode 100644
index 000000000..d66f025d1
--- /dev/null
+++ b/src/bun.js/bindings/isBuiltinModule.h
@@ -0,0 +1,5 @@
+#pragma once
+
+namespace Bun {
+bool isBuiltinModule(const String &namePossiblyWithNodePrefix);
+} // namespace Bun \ No newline at end of file
diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig
index caa7d3cd8..d1b87e34e 100644
--- a/src/bun.js/javascript.zig
+++ b/src/bun.js/javascript.zig
@@ -1523,7 +1523,6 @@ pub const VirtualMachine = struct {
fn normalizeSpecifierForResolution(specifier_: []const u8, query_string: *[]const u8) []const u8 {
var specifier = specifier_;
- if (strings.hasPrefixComptime(specifier, "file://")) specifier = specifier["file://".len..];
if (strings.indexOfChar(specifier, '?')) |i| {
query_string.* = specifier[i..];
diff --git a/src/bun.js/modules/NodeModuleModule.h b/src/bun.js/modules/NodeModuleModule.h
index eb8bb5c00..eeac4c0ea 100644
--- a/src/bun.js/modules/NodeModuleModule.h
+++ b/src/bun.js/modules/NodeModuleModule.h
@@ -1,8 +1,11 @@
+#pragma once
+
#include "CommonJSModuleRecord.h"
#include "ImportMetaObject.h"
#include "JavaScriptCore/JSBoundFunction.h"
#include "JavaScriptCore/ObjectConstructor.h"
#include "_NativeModule.h"
+#include "isBuiltinModule.h"
using namespace Zig;
using namespace JSC;
@@ -88,18 +91,6 @@ static constexpr ASCIILiteral builtinModuleNames[] = {
"zlib"_s,
};
-static bool isBuiltinModule(const String &namePossiblyWithNodePrefix) {
- String name = namePossiblyWithNodePrefix;
- if (name.startsWith("node:"_s))
- name = name.substringSharingImpl(5);
-
- for (auto &builtinModule : builtinModuleNames) {
- if (name == builtinModule)
- return true;
- }
- return false;
-}
-
JSC_DEFINE_HOST_FUNCTION(jsFunctionNodeModuleModuleConstructor,
(JSC::JSGlobalObject * globalObject,
JSC::CallFrame *callFrame)) {
@@ -158,7 +149,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionIsBuiltinModule,
auto moduleStr = moduleName.toWTFString(globalObject);
RETURN_IF_EXCEPTION(scope, JSValue::encode(jsBoolean(false)));
- return JSValue::encode(jsBoolean(isBuiltinModule(moduleStr)));
+ return JSValue::encode(jsBoolean(Bun::isBuiltinModule(moduleStr)));
}
// Might be faster as a JS builtin
diff --git a/src/bun.js/webcore/request.zig b/src/bun.js/webcore/request.zig
index 381ae2750..7f37bea46 100644
--- a/src/bun.js/webcore/request.zig
+++ b/src/bun.js/webcore/request.zig
@@ -507,10 +507,9 @@ pub const Request = struct {
};
const values_to_try = values_to_try_[0 .. @as(usize, @intFromBool(!is_first_argument_a_url)) +
@as(usize, @intFromBool(arguments.len > 1 and arguments[1].isObject()))];
-
for (values_to_try) |value| {
const value_type = value.jsType();
-
+ const explicit_check = values_to_try.len == 2 and value_type == .FinalObject and values_to_try[1].jsType() == .DOMWrapper;
if (value_type == .DOMWrapper) {
if (value.as(Request)) |request| {
if (values_to_try.len == 1) {
@@ -625,23 +624,25 @@ pub const Request = struct {
if (!fields.contains(.method) or !fields.contains(.headers)) {
if (Body.Init.init(globalThis.allocator(), globalThis, value) catch null) |init| {
- if (!fields.contains(.method)) {
- req.method = init.method;
- fields.insert(.method);
+ if (!explicit_check or (explicit_check and value.fastGet(globalThis, .method) != null)) {
+ if (!fields.contains(.method)) {
+ req.method = init.method;
+ fields.insert(.method);
+ }
}
-
- if (init.headers) |headers| {
- if (!fields.contains(.headers)) {
- req.headers = headers;
- fields.insert(.headers);
- } else {
- headers.deref();
+ if (!explicit_check or (explicit_check and value.fastGet(globalThis, .headers) != null)) {
+ if (init.headers) |headers| {
+ if (!fields.contains(.headers)) {
+ req.headers = headers;
+ fields.insert(.headers);
+ } else {
+ headers.deref();
+ }
}
}
}
}
}
-
if (req.url.isEmpty()) {
globalThis.throw("Failed to construct 'Request': url is required.", .{});
req.finalizeWithoutDeinit();