aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/javascript/jsc/bindings/BunBuiltinNames.h14
-rw-r--r--src/javascript/jsc/bindings/Path.cpp182
-rw-r--r--src/javascript/jsc/bindings/Path.h43
-rw-r--r--src/javascript/jsc/bindings/ZigGlobalObject.cpp5
-rw-r--r--src/javascript/jsc/bindings/bindings.zig62
-rw-r--r--src/javascript/jsc/bindings/exports.zig3
-rw-r--r--src/javascript/jsc/bindings/headers-cpp.h16
-rw-r--r--src/javascript/jsc/bindings/headers.h21
-rw-r--r--src/javascript/jsc/bindings/headers.zig1
-rw-r--r--src/javascript/jsc/javascript.zig32
-rw-r--r--src/javascript/jsc/node/types.zig402
-rw-r--r--src/javascript/jsc/path.exports.js56
-rw-r--r--src/linker.zig7
-rw-r--r--src/pool.zig2
-rw-r--r--src/resolver/resolve_path.zig41
15 files changed, 875 insertions, 12 deletions
diff --git a/src/javascript/jsc/bindings/BunBuiltinNames.h b/src/javascript/jsc/bindings/BunBuiltinNames.h
index 7a666df61..86b5a8675 100644
--- a/src/javascript/jsc/bindings/BunBuiltinNames.h
+++ b/src/javascript/jsc/bindings/BunBuiltinNames.h
@@ -56,6 +56,20 @@ using namespace JSC;
macro(unshift) \
macro(resume) \
macro(pause) \
+ macro(basename) \
+ macro(dirname) \
+ macro(file) \
+ macro(extname) \
+ macro(format) \
+ macro(isAbsolute) \
+ macro(join) \
+ macro(normalize) \
+ macro(parse) \
+ macro(relative) \
+ macro(resolve) \
+ macro(sep) \
+ macro(delimiter) \
+ macro(toNamespacedPath) \
BUN_ADDITIONAL_PRIVATE_IDENTIFIERS(macro) \
class BunBuiltinNames {
diff --git a/src/javascript/jsc/bindings/Path.cpp b/src/javascript/jsc/bindings/Path.cpp
new file mode 100644
index 000000000..a158beaa8
--- /dev/null
+++ b/src/javascript/jsc/bindings/Path.cpp
@@ -0,0 +1,182 @@
+#include "Path.h"
+#include <JavaScriptCore/JSMicrotask.h>
+#include <JavaScriptCore/ObjectConstructor.h>
+
+#pragma mark - Node.js Path
+
+extern JSC__JSValue Bun__Path__create(JSC::JSGlobalObject *globalObject, bool isWindows) {
+ JSC::VM &vm = globalObject->vm();
+
+ return JSC::JSValue::encode(JSC::JSValue(Zig::Path::create(
+ vm, isWindows, Zig::Path::createStructure(vm, globalObject, globalObject->objectPrototype()))));
+}
+
+namespace Zig {
+
+using JSGlobalObject = JSC::JSGlobalObject;
+using Exception = JSC::Exception;
+using JSValue = JSC::JSValue;
+using JSString = JSC::JSString;
+using JSModuleLoader = JSC::JSModuleLoader;
+using JSModuleRecord = JSC::JSModuleRecord;
+using Identifier = JSC::Identifier;
+using SourceOrigin = JSC::SourceOrigin;
+using JSObject = JSC::JSObject;
+using JSNonFinalObject = JSC::JSNonFinalObject;
+namespace JSCastingHelpers = JSC::JSCastingHelpers;
+
+// clang-format off
+#define DEFINE_CALLBACK_FUNCTION_BODY(ZigFunction) JSC::VM& vm = globalObject->vm(); \
+ auto* thisObject = JSC::jsDynamicCast<Path*>(vm, callFrame->thisValue()); \
+ auto scope = DECLARE_THROW_SCOPE(vm); \
+ if (!thisObject) \
+ return throwVMTypeError(globalObject, scope); \
+ auto argCount = static_cast<uint16_t>(callFrame->argumentCount()); \
+ WTF::Vector<JSC::EncodedJSValue, 16> arguments; \
+ arguments.reserveInitialCapacity(argCount); \
+ if (argCount) { \
+ for (uint16_t i = 0; i < argCount; ++i) { \
+ arguments.uncheckedAppend(JSC::JSValue::encode(callFrame->uncheckedArgument(i))); \
+ } \
+ } \
+ JSC::JSValue result = JSC::JSValue::decode( \
+ ZigFunction(globalObject, thisObject->isWindows, arguments.data(), argCount) \
+ ); \
+ JSC::JSObject *obj = result.getObject(); \
+ if (UNLIKELY(obj != nullptr && obj->isErrorInstance())) { \
+ scope.throwException(globalObject, obj); \
+ return JSC::JSValue::encode(JSC::jsUndefined()); \
+ } \
+ if (UNLIKELY(scope.exception())) \
+ return JSC::JSValue::encode(JSC::jsUndefined()); \
+ return JSC::JSValue::encode(result);
+
+// clang-format on
+
+static JSC_DECLARE_HOST_FUNCTION(Path_functionBasename);
+static JSC_DEFINE_HOST_FUNCTION(Path_functionBasename,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame *callFrame)) {
+ DEFINE_CALLBACK_FUNCTION_BODY(Bun__Path__basename);
+}
+
+static JSC_DECLARE_HOST_FUNCTION(Path_functionDirname);
+static JSC_DEFINE_HOST_FUNCTION(Path_functionDirname,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame *callFrame)) {
+ DEFINE_CALLBACK_FUNCTION_BODY(Bun__Path__dirname);
+}
+static JSC_DECLARE_HOST_FUNCTION(Path_functionExtname);
+static JSC_DEFINE_HOST_FUNCTION(Path_functionExtname,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame *callFrame)) {
+ DEFINE_CALLBACK_FUNCTION_BODY(Bun__Path__extname);
+}
+static JSC_DECLARE_HOST_FUNCTION(Path_functionFormat);
+static JSC_DEFINE_HOST_FUNCTION(Path_functionFormat,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame *callFrame)) {
+ DEFINE_CALLBACK_FUNCTION_BODY(Bun__Path__format);
+}
+static JSC_DECLARE_HOST_FUNCTION(Path_functionIsAbsolute);
+static JSC_DEFINE_HOST_FUNCTION(Path_functionIsAbsolute,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame *callFrame)) {
+ DEFINE_CALLBACK_FUNCTION_BODY(Bun__Path__isAbsolute);
+}
+static JSC_DECLARE_HOST_FUNCTION(Path_functionJoin);
+static JSC_DEFINE_HOST_FUNCTION(Path_functionJoin,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame *callFrame)) {
+ DEFINE_CALLBACK_FUNCTION_BODY(Bun__Path__join);
+}
+static JSC_DECLARE_HOST_FUNCTION(Path_functionNormalize);
+static JSC_DEFINE_HOST_FUNCTION(Path_functionNormalize,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame *callFrame)) {
+ DEFINE_CALLBACK_FUNCTION_BODY(Bun__Path__normalize);
+}
+static JSC_DECLARE_HOST_FUNCTION(Path_functionParse);
+static JSC_DEFINE_HOST_FUNCTION(Path_functionParse,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame *callFrame)) {
+ DEFINE_CALLBACK_FUNCTION_BODY(Bun__Path__parse);
+}
+static JSC_DECLARE_HOST_FUNCTION(Path_functionRelative);
+static JSC_DEFINE_HOST_FUNCTION(Path_functionRelative,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame *callFrame)) {
+ DEFINE_CALLBACK_FUNCTION_BODY(Bun__Path__relative);
+}
+static JSC_DECLARE_HOST_FUNCTION(Path_functionResolve);
+static JSC_DEFINE_HOST_FUNCTION(Path_functionResolve,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame *callFrame)) {
+ DEFINE_CALLBACK_FUNCTION_BODY(Bun__Path__resolve);
+}
+static JSC_DECLARE_HOST_FUNCTION(Path_functionToNamespacedPath);
+static JSC_DEFINE_HOST_FUNCTION(Path_functionToNamespacedPath,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame *callFrame)) {
+ auto argCount = static_cast<uint16_t>(callFrame->argumentCount());
+ // TODO:
+ return JSC::JSValue::encode(callFrame->argument(0));
+}
+
+void Path::finishCreation(JSC::VM &vm) {
+ Base::finishCreation(vm);
+ auto clientData = Bun::clientData(vm);
+
+ JSC::JSGlobalObject *globalThis = globalObject();
+ this->putDirect(vm, clientData->builtinNames().basenamePublicName(),
+ JSC::JSFunction::create(vm, JSC::jsCast<JSC::JSGlobalObject *>(globalThis), 0,
+ WTF::String("basename"), Path_functionBasename),
+ 0);
+ this->putDirect(vm, clientData->builtinNames().dirnamePublicName(),
+ JSC::JSFunction::create(vm, JSC::jsCast<JSC::JSGlobalObject *>(globalThis), 0,
+ WTF::String("dirname"), Path_functionDirname),
+ 0);
+ this->putDirect(vm, clientData->builtinNames().extnamePublicName(),
+ JSC::JSFunction::create(vm, JSC::jsCast<JSC::JSGlobalObject *>(globalThis), 0,
+ WTF::String("extname"), Path_functionExtname),
+ 0);
+ this->putDirect(vm, clientData->builtinNames().formatPublicName(),
+ JSC::JSFunction::create(vm, JSC::jsCast<JSC::JSGlobalObject *>(globalThis), 0,
+ WTF::String("format"), Path_functionFormat),
+ 0);
+ this->putDirect(vm, clientData->builtinNames().isAbsolutePublicName(),
+ JSC::JSFunction::create(vm, JSC::jsCast<JSC::JSGlobalObject *>(globalThis), 0,
+ WTF::String("isAbsolute"), Path_functionIsAbsolute),
+ 0);
+ this->putDirect(vm, clientData->builtinNames().joinPublicName(),
+ JSC::JSFunction::create(vm, JSC::jsCast<JSC::JSGlobalObject *>(globalThis), 0,
+ WTF::String("join"), Path_functionJoin),
+ 0);
+ this->putDirect(vm, clientData->builtinNames().normalizePublicName(),
+ JSC::JSFunction::create(vm, JSC::jsCast<JSC::JSGlobalObject *>(globalThis), 0,
+ WTF::String("normalize"), Path_functionNormalize),
+ 0);
+ this->putDirect(vm, clientData->builtinNames().parsePublicName(),
+ JSC::JSFunction::create(vm, JSC::jsCast<JSC::JSGlobalObject *>(globalThis), 0,
+ WTF::String("parse"), Path_functionParse),
+ 0);
+ this->putDirect(vm, clientData->builtinNames().relativePublicName(),
+ JSC::JSFunction::create(vm, JSC::jsCast<JSC::JSGlobalObject *>(globalThis), 0,
+ WTF::String("relative"), Path_functionRelative),
+ 0);
+ this->putDirect(vm, clientData->builtinNames().resolvePublicName(),
+ JSC::JSFunction::create(vm, JSC::jsCast<JSC::JSGlobalObject *>(globalThis), 0,
+ WTF::String("resolve"), Path_functionResolve),
+ 0);
+
+ this->putDirect(vm, clientData->builtinNames().toNamespacedPathPublicName(),
+ JSC::JSFunction::create(vm, JSC::jsCast<JSC::JSGlobalObject *>(globalThis), 0,
+ WTF::String("toNamespacedPath"),
+ Path_functionToNamespacedPath),
+ 0);
+
+ if (isWindows) {
+ this->putDirect(vm, clientData->builtinNames().sepPublicName(),
+ JSC::jsString(vm, WTF::String("\\"_s)), 0);
+ this->putDirect(vm, clientData->builtinNames().delimiterPublicName(),
+ JSC::jsString(vm, WTF::String(";"_s)), 0);
+ } else {
+ this->putDirect(vm, clientData->builtinNames().sepPublicName(),
+ JSC::jsString(vm, WTF::String("/"_s)), 0);
+ this->putDirect(vm, clientData->builtinNames().delimiterPublicName(),
+ JSC::jsString(vm, WTF::String(":"_s)), 0);
+ }
+}
+
+const JSC::ClassInfo Path::s_info = {"Path", &Base::s_info, nullptr, nullptr,
+ CREATE_METHOD_TABLE(Path)};
+} // namespace Zig \ No newline at end of file
diff --git a/src/javascript/jsc/bindings/Path.h b/src/javascript/jsc/bindings/Path.h
new file mode 100644
index 000000000..546a542a6
--- /dev/null
+++ b/src/javascript/jsc/bindings/Path.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "BunBuiltinNames.h"
+#include "BunClientData.h"
+#include "root.h"
+
+namespace Zig {
+
+class Path : public JSC::JSNonFinalObject {
+ using Base = JSC::JSNonFinalObject;
+
+ public:
+ Path(JSC::VM &vm, JSC::Structure *structure, bool isWindows_) : Base(vm, structure) {
+ isWindows = isWindows_;
+ }
+
+ DECLARE_INFO;
+
+ static constexpr unsigned StructureFlags = Base::StructureFlags;
+
+ template <typename CellType, JSC::SubspaceAccess>
+ static JSC::CompleteSubspace *subspaceFor(JSC::VM &vm) {
+ return &vm.cellSpace;
+ }
+
+ static JSC::Structure *createStructure(JSC::VM &vm, JSC::JSGlobalObject *globalObject,
+ JSC::JSValue prototype) {
+ return JSC::Structure::create(vm, globalObject, prototype,
+ JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+ }
+
+ static Path *create(JSC::VM &vm, bool isWindows, JSC::Structure *structure) {
+ Path *accessor = new (NotNull, JSC::allocateCell<Path>(vm.heap)) Path(vm, structure, isWindows);
+
+ accessor->finishCreation(vm);
+ return accessor;
+ }
+ bool isWindows = false;
+
+ void finishCreation(JSC::VM &vm);
+};
+
+} // namespace Zig \ No newline at end of file
diff --git a/src/javascript/jsc/bindings/ZigGlobalObject.cpp b/src/javascript/jsc/bindings/ZigGlobalObject.cpp
index 43a106c2d..3bd4eccce 100644
--- a/src/javascript/jsc/bindings/ZigGlobalObject.cpp
+++ b/src/javascript/jsc/bindings/ZigGlobalObject.cpp
@@ -500,8 +500,13 @@ JSC::JSObject *GlobalObject::moduleLoaderCreateImportMetaProperties(JSGlobalObje
if (index != WTF::notFound) {
metaProperties->putDirect(vm, clientData->builtinNames().dirPublicName(),
JSC::jsSubstring(globalObject, keyString, 0, index));
+ metaProperties->putDirect(
+ vm, clientData->builtinNames().filePublicName(),
+ JSC::jsSubstring(globalObject, keyString, index + 1, keyString->length() - index - 1));
}
+
metaProperties->putDirect(vm, clientData->builtinNames().pathPublicName(), key);
+
RETURN_IF_EXCEPTION(scope, nullptr);
// metaProperties->putDirect(vm, Identifier::fromString(vm, "resolve"),
diff --git a/src/javascript/jsc/bindings/bindings.zig b/src/javascript/jsc/bindings/bindings.zig
index c3e2314f5..63f3d36ac 100644
--- a/src/javascript/jsc/bindings/bindings.zig
+++ b/src/javascript/jsc/bindings/bindings.zig
@@ -89,6 +89,27 @@ pub const ZigString = extern struct {
pub const shim = Shimmer("", "ZigString", @This());
+ pub const Slice = struct {
+ allocator: std.mem.Allocator,
+ ptr: [*]const u8,
+ len: u32,
+ allocated: bool = false,
+
+ pub const empty = Slice{ .allocator = _global.default_allocator, .ptr = undefined, .len = 0, .allocated = false };
+
+ pub fn slice(this: Slice) []const u8 {
+ return this.ptr[0..this.len];
+ }
+
+ pub fn deinit(this: *Slice) void {
+ if (!this.allocated) {
+ return;
+ }
+
+ this.allocator.free(this.slice());
+ }
+ };
+
pub const name = "ZigString";
pub const namespace = "";
@@ -100,6 +121,10 @@ pub const ZigString = extern struct {
return @ptrCast([*]align(1) const u16, untagged(this.ptr))[0..this.len];
}
+ pub inline fn isEmpty(this: *const ZigString) bool {
+ return this.len == 0;
+ }
+
pub fn fromStringPointer(ptr: StringPointer, buf: string, to: *ZigString) void {
to.* = ZigString{
.len = ptr.length,
@@ -173,6 +198,25 @@ pub const ZigString = extern struct {
return untagged(this.ptr)[0..@minimum(this.len, std.math.maxInt(u32))];
}
+ pub fn toSlice(this: ZigString, allocator: std.mem.Allocator) Slice {
+ if (is16Bit(&this)) {
+ var buffer = std.fmt.allocPrint(allocator, "{}", .{this}) catch unreachable;
+ return Slice{
+ .ptr = buffer.ptr,
+ .len = @truncate(u32, buffer.len),
+ .allocated = true,
+ .allocator = allocator,
+ };
+ }
+
+ return Slice{
+ .ptr = untagged(this.ptr),
+ .len = @truncate(u32, this.len),
+ .allocated = false,
+ .allocator = allocator,
+ };
+ }
+
pub fn sliceZBuf(this: ZigString, buf: *[std.fs.MAX_PATH_BYTES]u8) ![:0]const u8 {
return try std.fmt.bufPrintZ(buf, "{}", .{this});
}
@@ -1509,6 +1553,20 @@ pub const JSValue = enum(i64) {
return @intToEnum(JSValue, @intCast(i64, @ptrToInt(ptr)));
}
+ pub const Formatter = struct {
+ value: JSValue,
+ global: *JSGlobalObject,
+
+ pub fn format(formatter: Formatter, comptime fmt: []const u8, opts: fmt.FormatOptions, writer: anytype) !void {
+ const self = formatter.value;
+ const kind = jsType(self);
+ if (kind.isStringLike()) {
+ var zig_str = self.getZigString();
+ return try zig_str.format(fmt, opts, writer);
+ }
+ }
+ };
+
pub fn to(this: JSValue, comptime T: type) T {
return switch (comptime T) {
u32 => toU32(this),
@@ -1771,6 +1829,10 @@ pub const JSValue = enum(i64) {
return str;
}
+ pub inline fn toSlice(this: JSValue, global: *JSGlobalObject, allocator: std.mem.Allocator) ZigString.Slice {
+ return getZigString(this, global).toSlice(allocator);
+ }
+
// On exception, this returns the empty string.
pub fn toString(this: JSValue, globalThis: *JSGlobalObject) *JSString {
return cppFn("toString", .{ this, globalThis });
diff --git a/src/javascript/jsc/bindings/exports.zig b/src/javascript/jsc/bindings/exports.zig
index 26ba4cd3c..ebf6ce47f 100644
--- a/src/javascript/jsc/bindings/exports.zig
+++ b/src/javascript/jsc/bindings/exports.zig
@@ -177,6 +177,8 @@ pub const NodeReadableStream = JSC.Node.Readable.State;
/// do not use this reference directly, use JSC.Node.Writable
pub const NodeWritableStream = JSC.Node.Writable.State;
+pub const NodePath = JSC.Node.Path;
+
pub fn Errorable(comptime Type: type) type {
return extern struct {
result: Result,
@@ -1824,5 +1826,6 @@ comptime {
_ = Process.setTitle;
std.testing.refAllDecls(NodeReadableStream);
std.testing.refAllDecls(NodeWritableStream);
+ std.testing.refAllDecls(NodePath);
}
}
diff --git a/src/javascript/jsc/bindings/headers-cpp.h b/src/javascript/jsc/bindings/headers-cpp.h
index 2ba13ed1d..81ff30331 100644
--- a/src/javascript/jsc/bindings/headers-cpp.h
+++ b/src/javascript/jsc/bindings/headers-cpp.h
@@ -1,4 +1,4 @@
-//-- AUTOGENERATED FILE -- 1642736709
+//-- AUTOGENERATED FILE -- 1643849682
// clang-format off
#pragma once
@@ -232,6 +232,14 @@ extern "C" const size_t Bun__Readable_object_align_ = alignof(Bun__Readable);
extern "C" const size_t Bun__Writable_object_size_ = sizeof(Bun__Writable);
extern "C" const size_t Bun__Writable_object_align_ = alignof(Bun__Writable);
+#ifndef INCLUDED_Path_h
+#define INCLUDED_Path_h
+#include Path.h
+#endif
+
+extern "C" const size_t Bun__Path_object_size_ = sizeof(Bun__Path);
+extern "C" const size_t Bun__Path_object_align_ = alignof(Bun__Path);
+
#ifndef INCLUDED__ZigConsoleClient_h_
#define INCLUDED__ZigConsoleClient_h_
#include "ZigConsoleClient.h"
@@ -240,8 +248,8 @@ extern "C" const size_t Bun__Writable_object_align_ = alignof(Bun__Writable);
extern "C" const size_t Zig__ConsoleClient_object_size_ = sizeof(Zig::ConsoleClient);
extern "C" const size_t Zig__ConsoleClient_object_align_ = alignof(Zig::ConsoleClient);
-const size_t sizes[29] = {sizeof(JSC::JSObject), sizeof(SystemError), sizeof(JSC::JSCell), sizeof(JSC::JSString), sizeof(Inspector::ScriptArguments), sizeof(JSC::JSModuleLoader), sizeof(JSC::JSModuleRecord), sizeof(JSC::JSPromise), sizeof(JSC::JSInternalPromise), sizeof(JSC::SourceOrigin), sizeof(JSC::SourceCode), sizeof(JSC::JSFunction), sizeof(JSC::JSGlobalObject), sizeof(WTF::URL), sizeof(WTF::String), sizeof(JSC::JSValue), sizeof(JSC::PropertyName), sizeof(JSC::Exception), sizeof(JSC::VM), sizeof(JSC::ThrowScope), sizeof(JSC::CatchScope), sizeof(JSC::CallFrame), sizeof(JSC::Identifier), sizeof(WTF::StringImpl), sizeof(WTF::ExternalStringImpl), sizeof(WTF::StringView), sizeof(Zig::GlobalObject), sizeof(Bun__Readable), sizeof(Bun__Writable)};
+const size_t sizes[30] = {sizeof(JSC::JSObject), sizeof(SystemError), sizeof(JSC::JSCell), sizeof(JSC::JSString), sizeof(Inspector::ScriptArguments), sizeof(JSC::JSModuleLoader), sizeof(JSC::JSModuleRecord), sizeof(JSC::JSPromise), sizeof(JSC::JSInternalPromise), sizeof(JSC::SourceOrigin), sizeof(JSC::SourceCode), sizeof(JSC::JSFunction), sizeof(JSC::JSGlobalObject), sizeof(WTF::URL), sizeof(WTF::String), sizeof(JSC::JSValue), sizeof(JSC::PropertyName), sizeof(JSC::Exception), sizeof(JSC::VM), sizeof(JSC::ThrowScope), sizeof(JSC::CatchScope), sizeof(JSC::CallFrame), sizeof(JSC::Identifier), sizeof(WTF::StringImpl), sizeof(WTF::ExternalStringImpl), sizeof(WTF::StringView), sizeof(Zig::GlobalObject), sizeof(Bun__Readable), sizeof(Bun__Writable), sizeof(Bun__Path)};
-const char* names[29] = {"JSC__JSObject", "SystemError", "JSC__JSCell", "JSC__JSString", "Inspector__ScriptArguments", "JSC__JSModuleLoader", "JSC__JSModuleRecord", "JSC__JSPromise", "JSC__JSInternalPromise", "JSC__SourceOrigin", "JSC__SourceCode", "JSC__JSFunction", "JSC__JSGlobalObject", "WTF__URL", "WTF__String", "JSC__JSValue", "JSC__PropertyName", "JSC__Exception", "JSC__VM", "JSC__ThrowScope", "JSC__CatchScope", "JSC__CallFrame", "JSC__Identifier", "WTF__StringImpl", "WTF__ExternalStringImpl", "WTF__StringView", "Zig__GlobalObject", "Bun__Readable", "Bun__Writable"};
+const char* names[30] = {"JSC__JSObject", "SystemError", "JSC__JSCell", "JSC__JSString", "Inspector__ScriptArguments", "JSC__JSModuleLoader", "JSC__JSModuleRecord", "JSC__JSPromise", "JSC__JSInternalPromise", "JSC__SourceOrigin", "JSC__SourceCode", "JSC__JSFunction", "JSC__JSGlobalObject", "WTF__URL", "WTF__String", "JSC__JSValue", "JSC__PropertyName", "JSC__Exception", "JSC__VM", "JSC__ThrowScope", "JSC__CatchScope", "JSC__CallFrame", "JSC__Identifier", "WTF__StringImpl", "WTF__ExternalStringImpl", "WTF__StringView", "Zig__GlobalObject", "Bun__Readable", "Bun__Writable", "Bun__Path"};
-const size_t aligns[29] = {alignof(JSC::JSObject), alignof(SystemError), alignof(JSC::JSCell), alignof(JSC::JSString), alignof(Inspector::ScriptArguments), alignof(JSC::JSModuleLoader), alignof(JSC::JSModuleRecord), alignof(JSC::JSPromise), alignof(JSC::JSInternalPromise), alignof(JSC::SourceOrigin), alignof(JSC::SourceCode), alignof(JSC::JSFunction), alignof(JSC::JSGlobalObject), alignof(WTF::URL), alignof(WTF::String), alignof(JSC::JSValue), alignof(JSC::PropertyName), alignof(JSC::Exception), alignof(JSC::VM), alignof(JSC::ThrowScope), alignof(JSC::CatchScope), alignof(JSC::CallFrame), alignof(JSC::Identifier), alignof(WTF::StringImpl), alignof(WTF::ExternalStringImpl), alignof(WTF::StringView), alignof(Zig::GlobalObject), alignof(Bun__Readable), alignof(Bun__Writable)};
+const size_t aligns[30] = {alignof(JSC::JSObject), alignof(SystemError), alignof(JSC::JSCell), alignof(JSC::JSString), alignof(Inspector::ScriptArguments), alignof(JSC::JSModuleLoader), alignof(JSC::JSModuleRecord), alignof(JSC::JSPromise), alignof(JSC::JSInternalPromise), alignof(JSC::SourceOrigin), alignof(JSC::SourceCode), alignof(JSC::JSFunction), alignof(JSC::JSGlobalObject), alignof(WTF::URL), alignof(WTF::String), alignof(JSC::JSValue), alignof(JSC::PropertyName), alignof(JSC::Exception), alignof(JSC::VM), alignof(JSC::ThrowScope), alignof(JSC::CatchScope), alignof(JSC::CallFrame), alignof(JSC::Identifier), alignof(WTF::StringImpl), alignof(WTF::ExternalStringImpl), alignof(WTF::StringView), alignof(Zig::GlobalObject), alignof(Bun__Readable), alignof(Bun__Writable), alignof(Bun__Path)};
diff --git a/src/javascript/jsc/bindings/headers.h b/src/javascript/jsc/bindings/headers.h
index 31ccc29ea..b8934c1a0 100644
--- a/src/javascript/jsc/bindings/headers.h
+++ b/src/javascript/jsc/bindings/headers.h
@@ -1,5 +1,5 @@
// clang-format: off
-//-- AUTOGENERATED FILE -- 1642736709
+//-- AUTOGENERATED FILE -- 1643849682
#pragma once
#include <stddef.h>
@@ -671,6 +671,25 @@ ZIG_DECL JSC__JSValue Bun__Writable__write(Bun__Writable* arg0, JSC__JSGlobalObj
#endif
+#pragma mark - Bun__Path
+
+CPP_DECL JSC__JSValue Bun__Path__create(JSC__JSGlobalObject* arg0, bool arg1);
+
+#ifdef __cplusplus
+
+ZIG_DECL JSC__JSValue Bun__Path__basename(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3);
+ZIG_DECL JSC__JSValue Bun__Path__dirname(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3);
+ZIG_DECL JSC__JSValue Bun__Path__extname(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3);
+ZIG_DECL JSC__JSValue Bun__Path__format(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3);
+ZIG_DECL JSC__JSValue Bun__Path__isAbsolute(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3);
+ZIG_DECL JSC__JSValue Bun__Path__join(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3);
+ZIG_DECL JSC__JSValue Bun__Path__normalize(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3);
+ZIG_DECL JSC__JSValue Bun__Path__parse(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3);
+ZIG_DECL JSC__JSValue Bun__Path__relative(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3);
+ZIG_DECL JSC__JSValue Bun__Path__resolve(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3);
+
+#endif
+
#ifdef __cplusplus
ZIG_DECL JSC__JSValue Bun__Process__getArgv(JSC__JSGlobalObject* arg0);
diff --git a/src/javascript/jsc/bindings/headers.zig b/src/javascript/jsc/bindings/headers.zig
index 9b637f427..c832d8af5 100644
--- a/src/javascript/jsc/bindings/headers.zig
+++ b/src/javascript/jsc/bindings/headers.zig
@@ -425,4 +425,5 @@ pub extern fn Zig__GlobalObject__getModuleRegistryMap(arg0: [*c]JSC__JSGlobalObj
pub extern fn Zig__GlobalObject__resetModuleRegistryMap(arg0: [*c]JSC__JSGlobalObject, arg1: ?*anyopaque) bool;
pub extern fn Bun__Readable__create(arg0: [*c]Bun__Readable, arg1: [*c]JSC__JSGlobalObject) JSC__JSValue;
pub extern fn Bun__Writable__create(arg0: [*c]Bun__Writable, arg1: [*c]JSC__JSGlobalObject) JSC__JSValue;
+pub extern fn Bun__Path__create(arg0: [*c]JSC__JSGlobalObject, arg1: bool) JSC__JSValue;
pub extern fn ZigException__fromException(arg0: [*c]JSC__Exception) ZigException;
diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig
index fcbc532ca..014e5bc75 100644
--- a/src/javascript/jsc/javascript.zig
+++ b/src/javascript/jsc/javascript.zig
@@ -356,6 +356,18 @@ pub const Bun = struct {
return JSValue.createStringArray(ctx.ptr(), styles.ptr, styles.len, true).asRef();
}
+ pub fn newPath(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ args: []const js.JSValueRef,
+ _: js.ExceptionRef,
+ ) js.JSValueRef {
+ const is_windows = args.len == 1 and JSValue.fromRef(args[0]).toBoolean();
+ return Node.Path.create(ctx.ptr(), is_windows).asObjectRef();
+ }
+
pub fn readFileAsStringCallback(
ctx: js.JSContextRef,
buf_z: [:0]const u8,
@@ -705,6 +717,10 @@ pub const Bun = struct {
.@"return" = "string[]",
},
},
+ ._Path = .{
+ .rfn = Bun.newPath,
+ .ts = d.ts{},
+ },
.getRouteNames = .{
.rfn = Bun.getRouteNames,
.ts = d.ts{
@@ -1596,6 +1612,15 @@ pub const VirtualMachine = struct {
.hash = 0,
.bytecodecache_fd = 0,
};
+ } else if (strings.eqlComptime(_specifier, "node:path")) {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(Node.Path.code),
+ .specifier = ZigString.init("node:path"),
+ .source_url = ZigString.init("node:path"),
+ .hash = 0,
+ .bytecodecache_fd = 0,
+ };
}
const specifier = normalizeSpecifier(_specifier);
@@ -1746,11 +1771,16 @@ pub const VirtualMachine = struct {
ret.result = null;
ret.path = specifier;
return;
- } else if (strings.eqlComptime(specifier, "fs") or strings.eqlComptime(specifier, "node:fs")) {
+ } else if (strings.eqlComptime(specifier, "node:fs")) {
ret.result = null;
ret.path = "node:fs";
return;
}
+ if (strings.eqlComptime(specifier, "node:path")) {
+ ret.result = null;
+ ret.path = "node:path";
+ return;
+ }
const is_special_source = strings.eqlComptime(source, main_file_name) or js_ast.Macro.isMacroPath(source);
diff --git a/src/javascript/jsc/node/types.zig b/src/javascript/jsc/node/types.zig
index 922f51b27..9238c3970 100644
--- a/src/javascript/jsc/node/types.zig
+++ b/src/javascript/jsc/node/types.zig
@@ -13,10 +13,10 @@ const os = std.os;
const Buffer = JSC.MarkedArrayBuffer;
const IdentityContext = @import("../../../identity_context.zig").IdentityContext;
const logger = @import("../../../logger.zig");
+const Fs = @import("../../../fs.zig");
const Shimmer = @import("../bindings/shimmer.zig").Shimmer;
const is_bindgen: bool = std.meta.globalOption("bindgen", bool) orelse false;
const meta = _global.meta;
-
/// Time in seconds. Not nanos!
pub const TimeLike = c_int;
pub const Mode = if (Environment.isLinux) u32 else std.os.mode_t;
@@ -1963,6 +1963,405 @@ pub const Readable = struct {
};
};
+pub const Path = struct {
+ pub const shim = Shimmer("Bun", "Path", @This());
+ pub const name = "Bun__Path";
+ pub const include = "Path.h";
+ pub const namespace = shim.namespace;
+ const PathHandler = @import("../../../resolver/resolve_path.zig");
+ const StringBuilder = @import("../../../string_builder.zig");
+ pub const code = @embedFile("../path.exports.js");
+
+ pub fn create(globalObject: *JSC.JSGlobalObject, isWindows: bool) callconv(.C) JSC.JSValue {
+ return shim.cppFn("create", .{ globalObject, isWindows });
+ }
+
+ pub fn basename(globalThis: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue {
+ if (comptime is_bindgen) return JSC.JSValue.jsUndefined();
+ if (args_len == 0) {
+ return JSC.toInvalidArguments("path is required", .{}, globalThis.ref());
+ }
+ var stack_fallback = std.heap.stackFallback(4096, JSC.getAllocator(globalThis.ref()));
+ var allocator = stack_fallback.get();
+
+ var arguments: []JSC.JSValue = args_ptr[0..args_len];
+ var path = arguments[0].toSlice(globalThis, allocator);
+ defer path.deinit();
+ var extname_ = if (args_len > 1) arguments[1].toSlice(globalThis, allocator) else JSC.ZigString.Slice.empty;
+ defer extname_.deinit();
+
+ var base_slice = path.slice();
+ if (extname_.len > 0) {
+ if (strings.endsWith(base_slice, extname_.slice())) {
+ base_slice = base_slice[0 .. base_slice.len - extname_.len];
+ }
+ }
+ var out: []const u8 = undefined;
+
+ if (!isWindows) {
+ out = std.fs.path.basenamePosix(base_slice);
+ } else {
+ out = std.fs.path.basenameWindows(base_slice);
+ }
+
+ return JSC.ZigString.init(out).toValueGC(globalThis);
+ }
+ pub fn dirname(globalThis: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue {
+ if (comptime is_bindgen) return JSC.JSValue.jsUndefined();
+ if (args_len == 0) {
+ return JSC.toInvalidArguments("path is required", .{}, globalThis.ref());
+ }
+ var stack_fallback = std.heap.stackFallback(4096, JSC.getAllocator(globalThis.ref()));
+ var allocator = stack_fallback.get();
+
+ var arguments: []JSC.JSValue = args_ptr[0..args_len];
+ var path = arguments[0].toSlice(globalThis, allocator);
+ defer path.deinit();
+
+ const base_slice = path.slice();
+
+ const out = if (!isWindows)
+ std.fs.path.dirnameWindows(base_slice) orelse "C:\\"
+ else
+ std.fs.path.dirnamePosix(base_slice) orelse "/";
+
+ return JSC.ZigString.init(out).toValueGC(globalThis);
+ }
+ pub fn extname(globalThis: *JSC.JSGlobalObject, _: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue {
+ if (comptime is_bindgen) return JSC.JSValue.jsUndefined();
+ if (args_len == 0) {
+ return JSC.toInvalidArguments("path is required", .{}, globalThis.ref());
+ }
+ var stack_fallback = std.heap.stackFallback(4096, JSC.getAllocator(globalThis.ref()));
+ var allocator = stack_fallback.get();
+ var arguments: []JSC.JSValue = args_ptr[0..args_len];
+
+ var path = arguments[0].toSlice(globalThis, allocator);
+ defer path.deinit();
+
+ const base_slice = path.slice();
+
+ return JSC.ZigString.init(std.fs.path.extension(base_slice)).toValueGC(globalThis);
+ }
+ pub fn format(globalThis: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue {
+ if (comptime is_bindgen) return JSC.JSValue.jsUndefined();
+ if (args_len == 0) {
+ return JSC.toInvalidArguments("pathObject is required", .{}, globalThis.ref());
+ }
+ var path_object: JSC.JSValue = args_ptr[0];
+ const js_type = path_object.jsType();
+ if (!js_type.isObject()) {
+ return JSC.toInvalidArguments("pathObject is required", .{}, globalThis.ref());
+ }
+
+ var stack_fallback = std.heap.stackFallback(4096, JSC.getAllocator(globalThis.ref()));
+ var allocator = stack_fallback.get();
+ var dir = JSC.ZigString.Empty;
+ var name_ = JSC.ZigString.Empty;
+ var ext = JSC.ZigString.Empty;
+ var name_with_ext = JSC.ZigString.Empty;
+
+ var insert_separator = true;
+ if (path_object.get(globalThis, "dir")) |prop| {
+ prop.toZigString(&dir, globalThis);
+ insert_separator = !dir.isEmpty();
+ } else if (path_object.get(globalThis, "root")) |prop| {
+ prop.toZigString(&dir, globalThis);
+ }
+
+ if (path_object.get(globalThis, "base")) |prop| {
+ prop.toZigString(&name_with_ext, globalThis);
+ } else {
+ var had_ext = false;
+ if (path_object.get(globalThis, "ext")) |prop| {
+ prop.toZigString(&ext, globalThis);
+ had_ext = !ext.isEmpty();
+ }
+
+ if (path_object.get(globalThis, "name")) |prop| {
+ if (had_ext) {
+ prop.toZigString(&name_, globalThis);
+ } else {
+ prop.toZigString(&name_with_ext, globalThis);
+ }
+ }
+ }
+
+ if (dir.isEmpty()) {
+ if (!name_with_ext.isEmpty()) {
+ return name_with_ext.toValueAuto(globalThis);
+ }
+
+ if (name_.isEmpty()) {
+ return JSC.ZigString.Empty.toValue(globalThis);
+ }
+ const out = std.fmt.allocPrint(allocator, "{s}{s}", .{ name_, ext }) catch unreachable;
+ defer allocator.free(out);
+ return JSC.ZigString.init(out).toValueGC(globalThis);
+ }
+
+ if (insert_separator) {
+ const separator = if (!isWindows) "/" else "\\";
+ if (name_with_ext.isEmpty()) {
+ const out = std.fmt.allocPrint(allocator, "{}{s}{}{}", .{ dir, separator, name_, ext }) catch unreachable;
+ defer allocator.free(out);
+ return JSC.ZigString.init(out).toValueGC(globalThis);
+ }
+
+ {
+ const out = std.fmt.allocPrint(allocator, "{}{s}{}", .{
+ dir,
+ separator,
+ name_with_ext,
+ }) catch unreachable;
+ defer allocator.free(out);
+ return JSC.ZigString.init(out).toValueGC(globalThis);
+ }
+ }
+
+ if (name_with_ext.isEmpty()) {
+ const out = std.fmt.allocPrint(allocator, "{}{}{}", .{ dir, name_, ext }) catch unreachable;
+ defer allocator.free(out);
+ return JSC.ZigString.init(out).toValueGC(globalThis);
+ }
+
+ {
+ const out = std.fmt.allocPrint(allocator, "{}{}", .{
+ dir,
+ name_with_ext,
+ }) catch unreachable;
+ defer allocator.free(out);
+ return JSC.ZigString.init(out).toValueGC(globalThis);
+ }
+ }
+ pub fn isAbsolute(globalThis: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue {
+ if (comptime is_bindgen) return JSC.JSValue.jsUndefined();
+ if (args_len == 0) return JSC.JSValue.jsBoolean(false);
+ var zig_str: JSC.ZigString = args_ptr[0].getZigString(globalThis);
+ if (zig_str.isEmpty()) return JSC.JSValue.jsBoolean(false);
+
+ if (!isWindows) {
+ return JSC.JSValue.jsBoolean(zig_str.slice()[0] == '/');
+ }
+
+ return JSC.JSValue.jsBoolean(isZigStringAbsoluteWindows(zig_str));
+ }
+ fn isZigStringAbsoluteWindows(zig_str: JSC.ZigString) bool {
+ if (zig_str.is16Bit()) {
+ var buf = [4]u16{ 0, 0, 0, 0 };
+ var u16_slice = zig_str.utf16Slice();
+
+ buf[0] = u16_slice[0];
+ if (u16_slice.len > 1)
+ buf[1] = u16_slice[1];
+
+ if (u16_slice.len > 2)
+ buf[2] = u16_slice[2];
+
+ if (u16_slice.len > 3)
+ buf[3] = u16_slice[3];
+
+ return std.fs.path.isAbsoluteWindowsWTF16(buf[0..@minimum(u16_slice.len, buf.len)]);
+ }
+
+ return std.fs.path.isAbsoluteWindows(zig_str.slice());
+ }
+ pub fn join(globalThis: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue {
+ if (comptime is_bindgen) return JSC.JSValue.jsUndefined();
+
+ var stack_fallback_allocator = std.heap.stackFallback(
+ (32 * @sizeOf(string)),
+ heap_allocator,
+ );
+ var allocator = stack_fallback_allocator.get();
+ var arena = std.heap.ArenaAllocator.init(heap_allocator);
+ var arena_allocator = arena.allocator();
+ defer arena.deinit();
+ var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
+ var to_join = allocator.alloc(string, args_len) catch unreachable;
+ for (args_ptr[0..args_len]) |arg, i| {
+ const zig_str: JSC.ZigString = arg.getZigString(globalThis);
+ if (zig_str.is16Bit()) {
+ // TODO: remove this string conversion
+ to_join[i] = zig_str.toSlice(arena_allocator).slice();
+ } else {
+ to_join[i] = zig_str.slice();
+ }
+ }
+
+ const out = if (!isWindows)
+ PathHandler.joinStringBuf(&buf, to_join, .posix)
+ else
+ PathHandler.joinStringBuf(&buf, to_join, .windows);
+
+ var out_str = JSC.ZigString.init(out);
+ out_str.detectEncoding();
+ return out_str.toValueGC(globalThis);
+ }
+ pub fn normalize(globalThis: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue {
+ if (comptime is_bindgen) return JSC.JSValue.jsUndefined();
+ if (args_len == 0) return JSC.ZigString.init("").toValue(globalThis);
+
+ var zig_str: JSC.ZigString = args_ptr[0].getZigString(globalThis);
+ if (zig_str.len == 0) return JSC.ZigString.init("").toValue(globalThis);
+
+ var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
+ var str_slice = zig_str.toSlice(heap_allocator);
+ defer str_slice.deinit();
+ var str = str_slice.slice();
+
+ const out = if (!isWindows)
+ PathHandler.normalizeBuf(str, &buf, .posix)
+ else
+ PathHandler.normalizeBuf(str, &buf, .windows);
+
+ var out_str = JSC.ZigString.init(out);
+ out_str.detectEncoding();
+ return out_str.toValueGC(globalThis);
+ }
+ pub fn parse(globalThis: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue {
+ if (comptime is_bindgen) return JSC.JSValue.jsUndefined();
+ if (args_len == 0 or !args_ptr[0].jsType().isStringLike()) {
+ return JSC.toInvalidArguments("path string is required", .{}, globalThis.ref());
+ }
+ var path_slice: JSC.ZigString.Slice = args_ptr[0].toSlice(globalThis, heap_allocator);
+ defer path_slice.deinit();
+ var path = path_slice.slice();
+ var path_name = Fs.PathName.init(path);
+ var root = JSC.ZigString.init(path_name.dir);
+ const is_absolute = (isWindows and isZigStringAbsoluteWindows(root)) or (!isWindows and path_name.dir.len > 0 and path_name.dir[0] == '/');
+
+ var dir = JSC.ZigString.init(path_name.dir);
+ if (is_absolute) {
+ root = JSC.ZigString.Empty;
+ if (path_name.dir.len == 0)
+ dir = JSC.ZigString.init(if (isWindows) std.fs.path.sep_str_windows else std.fs.path.sep_str_posix);
+ }
+
+ var base = JSC.ZigString.init(path_name.base);
+ var name_ = JSC.ZigString.init(path_name.filename);
+ var ext = JSC.ZigString.init(path_name.ext);
+ var entries = [10]JSC.ZigString{
+ JSC.ZigString.init("dir"),
+ JSC.ZigString.init("root"),
+ JSC.ZigString.init("base"),
+ JSC.ZigString.init("name"),
+ JSC.ZigString.init("ext"),
+ dir,
+ root,
+ base,
+ name_,
+ ext,
+ };
+
+ var keys: []JSC.ZigString = entries[0..5];
+ var values: []JSC.ZigString = entries[5..10];
+ return JSC.JSValue.fromEntries(globalThis, keys.ptr, values.ptr, 5, true);
+ }
+ pub fn relative(globalThis: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue {
+ if (comptime is_bindgen) return JSC.JSValue.jsUndefined();
+ var arguments = args_ptr[0..args_len];
+
+ if (args_len > 1 and JSC.JSValue.eqlValue(args_ptr[0], args_ptr[1]))
+ return JSC.ZigString.init(".").toValue(globalThis);
+
+ var from_slice: JSC.ZigString.Slice = if (args_len > 0) arguments[0].toSlice(globalThis, heap_allocator) else JSC.ZigString.Slice.empty;
+ defer from_slice.deinit();
+ var to_slice: JSC.ZigString.Slice = if (args_len > 1) arguments[1].toSlice(globalThis, heap_allocator) else JSC.ZigString.Slice.empty;
+ defer to_slice.deinit();
+
+ var from = from_slice.slice();
+ var to = to_slice.slice();
+
+ var out = if (!isWindows)
+ PathHandler.relativeNormalized(from, to, .posix, false)
+ else
+ PathHandler.relativeNormalized(from, to, .windows, false);
+
+ var out_str = JSC.ZigString.init(out);
+ out_str.detectEncoding();
+ return out_str.toValueGC(globalThis);
+ }
+
+ pub fn resolve(globalThis: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue {
+ if (comptime is_bindgen) return JSC.JSValue.jsUndefined();
+ if (args_len < 2) return normalize(globalThis, isWindows, args_ptr, args_len);
+
+ var stack_fallback_allocator = std.heap.stackFallback(
+ (32 * @sizeOf(string)),
+ heap_allocator,
+ );
+ var allocator = stack_fallback_allocator.get();
+ var out_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
+ // TODO:
+ _ = isWindows;
+ var parts = allocator.alloc(string, args_len) catch unreachable;
+ defer allocator.free(parts);
+ var i: u16 = 0;
+ var arena = std.heap.ArenaAllocator.init(heap_allocator);
+ var arena_allocator = arena.allocator();
+ defer arena.deinit();
+
+ while (i < args_len) : (i += 1) {
+ parts[i] = args_ptr[0].toSlice(globalThis, arena_allocator).slice();
+ }
+
+ var out = JSC.ZigString.init(PathHandler.joinStringBuf(&out_buf, parts, .posix));
+ out.detectEncoding();
+ return out.toValueGC(globalThis);
+ }
+
+ pub const Export = shim.exportFunctions(.{
+ .@"basename" = basename,
+ .@"dirname" = dirname,
+ .@"extname" = extname,
+ .@"format" = format,
+ .@"isAbsolute" = isAbsolute,
+ .@"join" = join,
+ .@"normalize" = normalize,
+ .@"parse" = parse,
+ .@"relative" = relative,
+ .@"resolve" = resolve,
+ });
+
+ pub const Extern = [_][]const u8{"create"};
+
+ comptime {
+ if (!is_bindgen) {
+ @export(Path.basename, .{
+ .name = Export[0].symbol_name,
+ });
+ @export(Path.dirname, .{
+ .name = Export[1].symbol_name,
+ });
+ @export(Path.extname, .{
+ .name = Export[2].symbol_name,
+ });
+ @export(Path.format, .{
+ .name = Export[3].symbol_name,
+ });
+ @export(Path.isAbsolute, .{
+ .name = Export[4].symbol_name,
+ });
+ @export(Path.join, .{
+ .name = Export[5].symbol_name,
+ });
+ @export(Path.normalize, .{
+ .name = Export[6].symbol_name,
+ });
+ @export(Path.parse, .{
+ .name = Export[7].symbol_name,
+ });
+ @export(Path.relative, .{
+ .name = Export[8].symbol_name,
+ });
+ @export(Path.resolve, .{
+ .name = Export[9].symbol_name,
+ });
+ }
+ }
+};
+
pub const Process = struct {
pub fn getArgv(globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue {
if (JSC.VirtualMachine.vm.argv.len == 0)
@@ -2068,6 +2467,7 @@ comptime {
std.testing.refAllDecls(Process);
std.testing.refAllDecls(Stream);
std.testing.refAllDecls(Readable);
+ std.testing.refAllDecls(Path);
std.testing.refAllDecls(Writable);
std.testing.refAllDecls(Writable.State);
std.testing.refAllDecls(Readable.State);
diff --git a/src/javascript/jsc/path.exports.js b/src/javascript/jsc/path.exports.js
new file mode 100644
index 000000000..6fa7af88d
--- /dev/null
+++ b/src/javascript/jsc/path.exports.js
@@ -0,0 +1,56 @@
+function bound(obj) {
+ return {
+ basename: obj.basename.bind(obj),
+ dirname: obj.dirname.bind(obj),
+ extname: obj.extname.bind(obj),
+ format: obj.format.bind(obj),
+ isAbsolute: obj.isAbsolute.bind(obj),
+ join: obj.join.bind(obj),
+ normalize: obj.normalize.bind(obj),
+ parse: obj.parse.bind(obj),
+ relative: obj.relative.bind(obj),
+ resolve: obj.resolve.bind(obj),
+ toNamespacedPath: obj.toNamespacedPath.bind(obj),
+ sep: obj.sep,
+ delimiter: obj.delimiter,
+ };
+}
+var path = bound(Bun._Path());
+path.win32 = win32;
+path.posix = posix;
+export var posix = bound(Bun._Path(false));
+export var win32 = bound(Bun._Path(true));
+
+var {
+ basename,
+ dirname,
+ extname,
+ format,
+ isAbsolute,
+ join,
+ normalize,
+ parse,
+ relative,
+ resolve,
+ toNamespacedPath,
+ sep,
+ delimiter,
+} = path;
+
+export {
+ basename,
+ dirname,
+ extname,
+ format,
+ isAbsolute,
+ join,
+ normalize,
+ parse,
+ relative,
+ resolve,
+ toNamespacedPath,
+ sep,
+ delimiter,
+};
+
+export default path;
diff --git a/src/linker.zig b/src/linker.zig
index 04604522a..b108ccce7 100644
--- a/src/linker.zig
+++ b/src/linker.zig
@@ -258,6 +258,13 @@ pub const Linker = struct {
if (linker.options.platform.isBun()) {
if (strings.eqlComptime(import_record.path.text, "fs") or strings.eqlComptime(import_record.path.text, "node:fs")) {
+ import_record.path.text = "node:fs";
+ externals.append(record_index) catch unreachable;
+ continue;
+ }
+
+ if (strings.eqlComptime(import_record.path.text, "path") or strings.eqlComptime(import_record.path.text, "node:path")) {
+ import_record.path.text = "node:path";
externals.append(record_index) catch unreachable;
continue;
}
diff --git a/src/pool.zig b/src/pool.zig
index 084fa9dd4..84fb6acb1 100644
--- a/src/pool.zig
+++ b/src/pool.zig
@@ -107,7 +107,7 @@ fn SinglyLinkedList(comptime T: type, comptime Parent: type) type {
};
}
-const log_allocations = true;
+const log_allocations = false;
pub fn ObjectPool(
comptime Type: type,
diff --git a/src/resolver/resolve_path.zig b/src/resolver/resolve_path.zig
index ca18f1f82..d77825211 100644
--- a/src/resolver/resolve_path.zig
+++ b/src/resolver/resolve_path.zig
@@ -254,7 +254,7 @@ pub fn relativeToCommonPath(
if (normalized_to.len > last_common_separator + 1) {
const tail = normalized_to[last_common_separator..];
- const insert_leading_slash = last_common_separator > 0 and normalized_to[last_common_separator - 1] != separator;
+ const insert_leading_slash = last_common_separator > 0 and normalized_to[last_common_separator - 1] != separator and tail[0] != separator;
if (insert_leading_slash) {
buf[out_slice.len] = separator;
@@ -521,6 +521,32 @@ pub fn normalizeString(str: []const u8, comptime allow_above_root: bool, comptim
return normalizeStringBuf(str, &parser_buffer, allow_above_root, _platform, false);
}
+pub fn normalizeBuf(str: []const u8, buf: []u8, comptime _platform: Platform) []u8 {
+ if (buf.len == 0) {
+ buf[0] = '.';
+ return buf[0..1];
+ }
+
+ const is_absolute = if (_platform == .posix or _platform == .auto)
+ (buf[0] == _platform.separator())
+ else
+ std.fs.path.isAbsoluteWindows(str);
+
+ const trailing_separator =
+ buf[buf.len - 1] == _platform.separator();
+
+ if (is_absolute and trailing_separator)
+ return normalizeStringBuf(str, buf, true, _platform, true);
+
+ if (is_absolute and !trailing_separator)
+ return normalizeStringBuf(str, buf, true, _platform, false);
+
+ if (!is_absolute and !trailing_separator)
+ return normalizeStringBuf(str, buf, false, _platform, false);
+
+ return normalizeStringBuf(str, buf, false, _platform, true);
+}
+
pub fn normalizeStringBuf(str: []const u8, buf: []u8, comptime allow_above_root: bool, comptime _platform: Platform, comptime preserve_trailing_slash: anytype) []u8 {
const platform = comptime _platform.resolve();
@@ -528,7 +554,13 @@ pub fn normalizeStringBuf(str: []const u8, buf: []u8, comptime allow_above_root:
.auto => unreachable,
.windows => {
- @compileError("Not implemented");
+ // @compileError("Not implemented");
+ return normalizeStringLooseBuf(
+ str,
+ buf,
+ allow_above_root,
+ preserve_trailing_slash,
+ );
},
.posix => {
return normalizeStringLooseBuf(
@@ -620,7 +652,7 @@ pub fn joinStringBuf(buf: []u8, _parts: anytype, comptime _platform: Platform) [
if (_parts[0].len > 0 and _parts[0][0] == _platform.separator()) {
const out = switch (comptime platform) {
// .loose =>
- .windows => @compileError("Not implemented yet"),
+ // .windows => @compileError("Not implemented yet"),
else => normalizeStringLooseBuf(parser_join_input_buffer[0..written], buf[1..], false, false),
};
buf[0] = _platform.separator();
@@ -629,7 +661,7 @@ pub fn joinStringBuf(buf: []u8, _parts: anytype, comptime _platform: Platform) [
} else {
return switch (platform) {
else => normalizeStringLooseBuf(parser_join_input_buffer[0..written], buf[0..], false, false),
- .windows => @compileError("Not implemented yet"),
+ // .windows => @compileError("Not implemented yet"),
};
}
}
@@ -956,6 +988,7 @@ test "relative" {
_ = t.expect("index.js", try relativeAlloc(default_allocator, "/app/public/", "/app/public/index.js"), @src());
_ = t.expect("..", try relativeAlloc(default_allocator, "/app/public/index.js", "/app/public/"), @src());
_ = t.expect("../../src/bacon.ts", try relativeAlloc(default_allocator, "/app/public/index.html", "/app/src/bacon.ts"), @src());
+ _ = t.expect("../../../../bacon/foo/baz", try relativeAlloc(default_allocator, "/app/foo/bar/baz.js", "/bacon/foo/baz"), @src());
}
test "longestCommonPath" {