aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-03-17 18:28:24 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-03-17 18:28:24 -0700
commit86a4ab704d026b984fba049c67b2e9594d0ddf65 (patch)
treeb7ad87633953a4e36334ae93270f8dded6c98e0c /src
parentd5613308f9b629e4e28f3625ead38fb052f2db34 (diff)
downloadbun-86a4ab704d026b984fba049c67b2e9594d0ddf65.tar.gz
bun-86a4ab704d026b984fba049c67b2e9594d0ddf65.tar.zst
bun-86a4ab704d026b984fba049c67b2e9594d0ddf65.zip
Move `Bun` to JSC.API
Diffstat (limited to '')
-rw-r--r--src/http.zig4
-rw-r--r--src/javascript/jsc/api/bun.zig1618
-rw-r--r--src/javascript/jsc/api/router.zig4
-rw-r--r--src/javascript/jsc/bindings/exports.zig4
-rw-r--r--src/javascript/jsc/javascript.zig1441
-rw-r--r--src/javascript/jsc/webcore/response.zig9
-rw-r--r--src/javascript/jsc/webcore/url.zig5
-rw-r--r--src/jsc.zig2
8 files changed, 1667 insertions, 1420 deletions
diff --git a/src/http.zig b/src/http.zig
index 601caabf2..585df3756 100644
--- a/src/http.zig
+++ b/src/http.zig
@@ -1401,7 +1401,7 @@ pub const RequestContext = struct {
js_ast.Stmt.Data.Store.reset();
js_ast.Expr.Data.Store.reset();
- JavaScript.Bun.flushCSSImports();
+ JavaScript.API.Bun.flushCSSImports();
vm.flush();
Output.printElapsed(@intToFloat(f64, (handler.start_timer.read())) / std.time.ns_per_ms);
@@ -1530,7 +1530,7 @@ pub const RequestContext = struct {
);
js_ast.Stmt.Data.Store.reset();
js_ast.Expr.Data.Store.reset();
- JavaScript.Bun.flushCSSImports();
+ JavaScript.API.Bun.flushCSSImports();
Output.flush();
JavaScript.VirtualMachine.vm.arena.deinit();
JavaScript.VirtualMachine.vm.has_loaded = false;
diff --git a/src/javascript/jsc/api/bun.zig b/src/javascript/jsc/api/bun.zig
new file mode 100644
index 000000000..e2af7ed95
--- /dev/null
+++ b/src/javascript/jsc/api/bun.zig
@@ -0,0 +1,1618 @@
+const Bun = @This();
+const default_allocator = @import("../../../global.zig").default_allocator;
+const bun = @import("../../../global.zig");
+const Environment = bun.Environment;
+const NetworkThread = @import("http").NetworkThread;
+const Global = bun.Global;
+const strings = bun.strings;
+const string = bun.string;
+const Output = @import("../../../global.zig").Output;
+const MutableString = @import("../../../global.zig").MutableString;
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const IdentityContext = @import("../../../identity_context.zig").IdentityContext;
+const Fs = @import("../../../fs.zig");
+const Resolver = @import("../../../resolver/resolver.zig");
+const ast = @import("../../../import_record.zig");
+const NodeModuleBundle = @import("../../../node_module_bundle.zig").NodeModuleBundle;
+const MacroEntryPoint = @import("../../../bundler.zig").MacroEntryPoint;
+const logger = @import("../../../logger.zig");
+const Api = @import("../../../api/schema.zig").Api;
+const options = @import("../../../options.zig");
+const Bundler = @import("../../../bundler.zig").Bundler;
+const ServerEntryPoint = @import("../../../bundler.zig").ServerEntryPoint;
+const js_printer = @import("../../../js_printer.zig");
+const js_parser = @import("../../../js_parser.zig");
+const js_ast = @import("../../../js_ast.zig");
+const hash_map = @import("../../../hash_map.zig");
+const http = @import("../../../http.zig");
+const NodeFallbackModules = @import("../../../node_fallbacks.zig");
+const ImportKind = ast.ImportKind;
+const Analytics = @import("../../../analytics/analytics_thread.zig");
+const ZigString = @import("../../../jsc.zig").ZigString;
+const Runtime = @import("../../../runtime.zig");
+const Router = @import("./router.zig");
+const ImportRecord = ast.ImportRecord;
+const DotEnv = @import("../../../env_loader.zig");
+const ParseResult = @import("../../../bundler.zig").ParseResult;
+const PackageJSON = @import("../../../resolver/package_json.zig").PackageJSON;
+const MacroRemap = @import("../../../resolver/package_json.zig").MacroMap;
+const WebCore = @import("../../../jsc.zig").WebCore;
+const Request = WebCore.Request;
+const Response = WebCore.Response;
+const Headers = WebCore.Headers;
+const Fetch = WebCore.Fetch;
+const FetchEvent = WebCore.FetchEvent;
+const js = @import("../../../jsc.zig").C;
+const JSC = @import("../../../jsc.zig");
+const JSError = @import("../base.zig").JSError;
+const d = @import("../base.zig").d;
+const MarkedArrayBuffer = @import("../base.zig").MarkedArrayBuffer;
+const getAllocator = @import("../base.zig").getAllocator;
+const JSValue = @import("../../../jsc.zig").JSValue;
+const NewClass = @import("../base.zig").NewClass;
+const Microtask = @import("../../../jsc.zig").Microtask;
+const JSGlobalObject = @import("../../../jsc.zig").JSGlobalObject;
+const ExceptionValueRef = @import("../../../jsc.zig").ExceptionValueRef;
+const JSPrivateDataPtr = @import("../../../jsc.zig").JSPrivateDataPtr;
+const ZigConsoleClient = @import("../../../jsc.zig").ZigConsoleClient;
+const Node = @import("../../../jsc.zig").Node;
+const ZigException = @import("../../../jsc.zig").ZigException;
+const ZigStackTrace = @import("../../../jsc.zig").ZigStackTrace;
+const ErrorableResolvedSource = @import("../../../jsc.zig").ErrorableResolvedSource;
+const ResolvedSource = @import("../../../jsc.zig").ResolvedSource;
+const JSPromise = @import("../../../jsc.zig").JSPromise;
+const JSInternalPromise = @import("../../../jsc.zig").JSInternalPromise;
+const JSModuleLoader = @import("../../../jsc.zig").JSModuleLoader;
+const JSPromiseRejectionOperation = @import("../../../jsc.zig").JSPromiseRejectionOperation;
+const Exception = @import("../../../jsc.zig").Exception;
+const ErrorableZigString = @import("../../../jsc.zig").ErrorableZigString;
+const ZigGlobalObject = @import("../../../jsc.zig").ZigGlobalObject;
+const VM = @import("../../../jsc.zig").VM;
+const JSFunction = @import("../../../jsc.zig").JSFunction;
+const Config = @import("../config.zig");
+const URL = @import("../../../url.zig").URL;
+const Transpiler = @import("./transpiler.zig");
+const VirtualMachine = @import("../javascript.zig").VirtualMachine;
+const IOTask = JSC.IOTask;
+const is_bindgen = JSC.is_bindgen;
+
+threadlocal var css_imports_list_strings: [512]ZigString = undefined;
+threadlocal var css_imports_list: [512]Api.StringPointer = undefined;
+threadlocal var css_imports_list_tail: u16 = 0;
+threadlocal var css_imports_buf: std.ArrayList(u8) = undefined;
+threadlocal var css_imports_buf_loaded: bool = false;
+
+threadlocal var routes_list_strings: [1024]ZigString = undefined;
+
+pub fn onImportCSS(
+ resolve_result: *const Resolver.Result,
+ import_record: *ImportRecord,
+ origin: URL,
+) void {
+ if (!css_imports_buf_loaded) {
+ css_imports_buf = std.ArrayList(u8).initCapacity(
+ VirtualMachine.vm.allocator,
+ import_record.path.text.len,
+ ) catch unreachable;
+ css_imports_buf_loaded = true;
+ }
+
+ var writer = css_imports_buf.writer();
+ const offset = css_imports_buf.items.len;
+ css_imports_list[css_imports_list_tail] = .{
+ .offset = @truncate(u32, offset),
+ .length = 0,
+ };
+ getPublicPath(resolve_result.path_pair.primary.text, origin, @TypeOf(writer), writer);
+ const length = css_imports_buf.items.len - offset;
+ css_imports_list[css_imports_list_tail].length = @truncate(u32, length);
+ css_imports_list_tail += 1;
+}
+
+pub fn flushCSSImports() void {
+ if (css_imports_buf_loaded) {
+ css_imports_buf.clearRetainingCapacity();
+ css_imports_list_tail = 0;
+ }
+}
+
+pub fn getCSSImports() []ZigString {
+ var i: u16 = 0;
+ const tail = css_imports_list_tail;
+ while (i < tail) : (i += 1) {
+ ZigString.fromStringPointer(css_imports_list[i], css_imports_buf.items, &css_imports_list_strings[i]);
+ }
+ return css_imports_list_strings[0..tail];
+}
+
+pub fn inspect(
+ // this
+ _: void,
+ ctx: js.JSContextRef,
+ // function
+ _: js.JSObjectRef,
+ // thisObject
+ _: js.JSObjectRef,
+ arguments: []const js.JSValueRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ if (arguments.len == 0)
+ return ZigString.Empty.toValue(ctx.ptr()).asObjectRef();
+
+ for (arguments) |arg| {
+ JSC.C.JSValueProtect(ctx, arg);
+ }
+ defer {
+ for (arguments) |arg| {
+ JSC.C.JSValueUnprotect(ctx, arg);
+ }
+ }
+
+ // very stable memory address
+ var array = MutableString.init(getAllocator(ctx), 0) catch unreachable;
+ var buffered_writer_ = MutableString.BufferedWriter{ .context = &array };
+ var buffered_writer = &buffered_writer_;
+
+ var writer = buffered_writer.writer();
+ const Writer = @TypeOf(writer);
+ // we buffer this because it'll almost always be < 4096
+ // when it's under 4096, we want to avoid the dynamic allocation
+ ZigConsoleClient.format(
+ .Debug,
+ ctx.ptr(),
+ @ptrCast([*]const JSValue, arguments.ptr),
+ arguments.len,
+ Writer,
+ Writer,
+ writer,
+ false,
+ false,
+ false,
+ );
+
+ // when it's a small thing, rely on GC to manage the memory
+ if (writer.context.pos < 2048 and array.list.items.len == 0) {
+ var slice = writer.context.buffer[0..writer.context.pos];
+ if (slice.len == 0) {
+ return ZigString.Empty.toValue(ctx.ptr()).asObjectRef();
+ }
+
+ var zig_str = ZigString.init(slice).withEncoding();
+ return zig_str.toValueGC(ctx.ptr()).asObjectRef();
+ }
+
+ // when it's a big thing, we will manage it
+ {
+ writer.context.flush() catch {};
+ var slice = writer.context.context.toOwnedSlice();
+
+ var zig_str = ZigString.init(slice).withEncoding();
+ if (!zig_str.isUTF8()) {
+ return zig_str.toExternalValue(ctx.ptr()).asObjectRef();
+ } else {
+ return zig_str.toValueGC(ctx.ptr()).asObjectRef();
+ }
+ }
+}
+
+pub fn registerMacro(
+ // this
+ _: void,
+ ctx: js.JSContextRef,
+ // function
+ _: js.JSObjectRef,
+ // thisObject
+ _: js.JSObjectRef,
+ arguments: []const js.JSValueRef,
+ exception: js.ExceptionRef,
+) js.JSValueRef {
+ if (arguments.len != 2 or !js.JSValueIsNumber(ctx, arguments[0])) {
+ JSError(getAllocator(ctx), "Internal error registering macros: invalid args", .{}, ctx, exception);
+ return js.JSValueMakeUndefined(ctx);
+ }
+ // TODO: make this faster
+ const id = @truncate(i32, @floatToInt(i64, js.JSValueToNumber(ctx, arguments[0], exception)));
+ if (id == -1 or id == 0) {
+ JSError(getAllocator(ctx), "Internal error registering macros: invalid id", .{}, ctx, exception);
+ return js.JSValueMakeUndefined(ctx);
+ }
+
+ if (!js.JSValueIsObject(ctx, arguments[1]) or !js.JSObjectIsFunction(ctx, arguments[1])) {
+ JSError(getAllocator(ctx), "Macro must be a function. Received: {s}", .{@tagName(js.JSValueGetType(ctx, arguments[1]))}, ctx, exception);
+ return js.JSValueMakeUndefined(ctx);
+ }
+
+ var get_or_put_result = VirtualMachine.vm.macros.getOrPut(id) catch unreachable;
+ if (get_or_put_result.found_existing) {
+ js.JSValueUnprotect(ctx, get_or_put_result.value_ptr.*);
+ }
+
+ js.JSValueProtect(ctx, arguments[1]);
+ get_or_put_result.value_ptr.* = arguments[1];
+
+ return js.JSValueMakeUndefined(ctx);
+}
+
+pub fn getCWD(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSValueRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ return ZigString.init(VirtualMachine.vm.bundler.fs.top_level_dir).toValue(ctx.ptr()).asRef();
+}
+
+pub fn getOrigin(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSValueRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ return ZigString.init(VirtualMachine.vm.origin.origin).toValue(ctx.ptr()).asRef();
+}
+
+pub fn enableANSIColors(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSValueRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ return js.JSValueMakeBoolean(ctx, Output.enable_ansi_colors);
+}
+pub fn getMain(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSValueRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ return ZigString.init(VirtualMachine.vm.main).toValue(ctx.ptr()).asRef();
+}
+
+pub fn getAssetPrefix(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSValueRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ return ZigString.init(VirtualMachine.vm.bundler.options.routes.asset_prefix_path).toValue(ctx.ptr()).asRef();
+}
+
+pub fn getArgv(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSValueRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ if (comptime Environment.isWindows) {
+ @compileError("argv not supported on windows");
+ }
+
+ var argv_list = std.heap.stackFallback(128, getAllocator(ctx));
+ var allocator = argv_list.get();
+ var argv = allocator.alloc(ZigString, std.os.argv.len) catch unreachable;
+ defer if (argv.len > 128) allocator.free(argv);
+ for (std.os.argv) |arg, i| {
+ argv[i] = ZigString.init(std.mem.span(arg));
+ }
+
+ return JSValue.createStringArray(ctx.ptr(), argv.ptr, argv.len, true).asObjectRef();
+}
+
+pub fn getRoutesDir(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSValueRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ if (!VirtualMachine.vm.bundler.options.routes.routes_enabled or VirtualMachine.vm.bundler.options.routes.dir.len == 0) {
+ return js.JSValueMakeUndefined(ctx);
+ }
+
+ return ZigString.init(VirtualMachine.vm.bundler.options.routes.dir).toValue(ctx.ptr()).asRef();
+}
+
+pub fn getFilePath(ctx: js.JSContextRef, arguments: []const js.JSValueRef, buf: []u8, exception: js.ExceptionRef) ?string {
+ if (arguments.len != 1) {
+ JSError(getAllocator(ctx), "Expected a file path as a string or an array of strings to be part of a file path.", .{}, ctx, exception);
+ return null;
+ }
+
+ const value = arguments[0];
+ if (js.JSValueIsString(ctx, value)) {
+ var out = ZigString.Empty;
+ JSValue.toZigString(JSValue.fromRef(value), &out, ctx.ptr());
+ var out_slice = out.slice();
+
+ // The dots are kind of unnecessary. They'll be normalized.
+ if (out.len == 0 or @ptrToInt(out.ptr) == 0 or std.mem.eql(u8, out_slice, ".") or std.mem.eql(u8, out_slice, "..") or std.mem.eql(u8, out_slice, "../")) {
+ JSError(getAllocator(ctx), "Expected a file path as a string or an array of strings to be part of a file path.", .{}, ctx, exception);
+ return null;
+ }
+
+ var parts = [_]string{out_slice};
+ // This does the equivalent of Node's path.normalize(path.join(cwd, out_slice))
+ var res = VirtualMachine.vm.bundler.fs.absBuf(&parts, buf);
+
+ return res;
+ } else if (js.JSValueIsArray(ctx, value)) {
+ var temp_strings_list: [32]string = undefined;
+ var temp_strings_list_len: u8 = 0;
+ defer {
+ for (temp_strings_list[0..temp_strings_list_len]) |_, i| {
+ temp_strings_list[i] = "";
+ }
+ }
+
+ var iter = JSValue.fromRef(value).arrayIterator(ctx.ptr());
+ while (iter.next()) |item| {
+ if (temp_strings_list_len >= temp_strings_list.len) {
+ break;
+ }
+
+ if (!item.isString()) {
+ JSError(getAllocator(ctx), "Expected a file path as a string or an array of strings to be part of a file path.", .{}, ctx, exception);
+ return null;
+ }
+
+ var out = ZigString.Empty;
+ JSValue.toZigString(item, &out, ctx.ptr());
+ const out_slice = out.slice();
+
+ temp_strings_list[temp_strings_list_len] = out_slice;
+ // The dots are kind of unnecessary. They'll be normalized.
+ if (out.len == 0 or @ptrToInt(out.ptr) == 0 or std.mem.eql(u8, out_slice, ".") or std.mem.eql(u8, out_slice, "..") or std.mem.eql(u8, out_slice, "../")) {
+ JSError(getAllocator(ctx), "Expected a file path as a string or an array of strings to be part of a file path.", .{}, ctx, exception);
+ return null;
+ }
+ temp_strings_list_len += 1;
+ }
+
+ if (temp_strings_list_len == 0) {
+ JSError(getAllocator(ctx), "Expected a file path as a string or an array of strings to be part of a file path.", .{}, ctx, exception);
+ return null;
+ }
+
+ return VirtualMachine.vm.bundler.fs.absBuf(temp_strings_list[0..temp_strings_list_len], buf);
+ } else {
+ JSError(getAllocator(ctx), "Expected a file path as a string or an array of strings to be part of a file path.", .{}, ctx, exception);
+ return null;
+ }
+}
+
+pub fn getImportedStyles(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ _: []const js.JSValueRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ defer flushCSSImports();
+ const styles = getCSSImports();
+ if (styles.len == 0) {
+ return js.JSObjectMakeArray(ctx, 0, null, null);
+ }
+
+ 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,
+ exception: js.ExceptionRef,
+) js.JSValueRef {
+ const path = buf_z.ptr[0..buf_z.len];
+ var file = std.fs.cwd().openFileZ(buf_z, .{ .mode = .read_only }) catch |err| {
+ JSError(getAllocator(ctx), "Opening file {s} for path: \"{s}\"", .{ @errorName(err), path }, ctx, exception);
+ return js.JSValueMakeUndefined(ctx);
+ };
+
+ defer file.close();
+
+ const stat = file.stat() catch |err| {
+ JSError(getAllocator(ctx), "Getting file size {s} for \"{s}\"", .{ @errorName(err), path }, ctx, exception);
+ return js.JSValueMakeUndefined(ctx);
+ };
+
+ if (stat.kind != .File) {
+ JSError(getAllocator(ctx), "Can't read a {s} as a string (\"{s}\")", .{ @tagName(stat.kind), path }, ctx, exception);
+ return js.JSValueMakeUndefined(ctx);
+ }
+
+ var contents_buf = VirtualMachine.vm.allocator.alloc(u8, stat.size + 2) catch unreachable; // OOM
+ defer VirtualMachine.vm.allocator.free(contents_buf);
+ const contents_len = file.readAll(contents_buf) catch |err| {
+ JSError(getAllocator(ctx), "{s} reading file (\"{s}\")", .{ @errorName(err), path }, ctx, exception);
+ return js.JSValueMakeUndefined(ctx);
+ };
+
+ contents_buf[contents_len] = 0;
+
+ // Very slow to do it this way. We're copying the string twice.
+ // But it's important that this string is garbage collected instead of manually managed.
+ // We can't really recycle this one.
+ // TODO: use external string
+ return js.JSValueMakeString(ctx, js.JSStringCreateWithUTF8CString(contents_buf.ptr));
+}
+
+pub fn readFileAsBytesCallback(
+ ctx: js.JSContextRef,
+ buf_z: [:0]const u8,
+ exception: js.ExceptionRef,
+) js.JSValueRef {
+ const path = buf_z.ptr[0..buf_z.len];
+
+ var file = std.fs.cwd().openFileZ(buf_z, .{ .mode = .read_only }) catch |err| {
+ JSError(getAllocator(ctx), "Opening file {s} for path: \"{s}\"", .{ @errorName(err), path }, ctx, exception);
+ return js.JSValueMakeUndefined(ctx);
+ };
+
+ defer file.close();
+
+ const stat = file.stat() catch |err| {
+ JSError(getAllocator(ctx), "Getting file size {s} for \"{s}\"", .{ @errorName(err), path }, ctx, exception);
+ return js.JSValueMakeUndefined(ctx);
+ };
+
+ if (stat.kind != .File) {
+ JSError(getAllocator(ctx), "Can't read a {s} as a string (\"{s}\")", .{ @tagName(stat.kind), path }, ctx, exception);
+ return js.JSValueMakeUndefined(ctx);
+ }
+
+ var contents_buf = VirtualMachine.vm.allocator.alloc(u8, stat.size + 2) catch unreachable; // OOM
+ errdefer VirtualMachine.vm.allocator.free(contents_buf);
+ const contents_len = file.readAll(contents_buf) catch |err| {
+ JSError(getAllocator(ctx), "{s} reading file (\"{s}\")", .{ @errorName(err), path }, ctx, exception);
+ return js.JSValueMakeUndefined(ctx);
+ };
+
+ contents_buf[contents_len] = 0;
+
+ var marked_array_buffer = VirtualMachine.vm.allocator.create(MarkedArrayBuffer) catch unreachable;
+ marked_array_buffer.* = MarkedArrayBuffer.fromBytes(
+ contents_buf[0..contents_len],
+ VirtualMachine.vm.allocator,
+ .Uint8Array,
+ );
+
+ return marked_array_buffer.toJSObjectRef(ctx, exception);
+}
+
+pub fn getRouteFiles(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ _: []const js.JSValueRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ if (VirtualMachine.vm.bundler.router == null) return js.JSValueMakeNull(ctx);
+
+ const router = &VirtualMachine.vm.bundler.router.?;
+ const list = router.getPublicPaths() catch unreachable;
+
+ for (routes_list_strings[0..@minimum(list.len, routes_list_strings.len)]) |_, i| {
+ routes_list_strings[i] = ZigString.init(list[i]);
+ }
+
+ const ref = JSValue.createStringArray(ctx.ptr(), &routes_list_strings, list.len, true).asRef();
+ return ref;
+}
+
+pub fn getRouteNames(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ _: []const js.JSValueRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ if (VirtualMachine.vm.bundler.router == null) return js.JSValueMakeNull(ctx);
+
+ const router = &VirtualMachine.vm.bundler.router.?;
+ const list = router.getNames() catch unreachable;
+
+ for (routes_list_strings[0..@minimum(list.len, routes_list_strings.len)]) |_, i| {
+ routes_list_strings[i] = ZigString.init(list[i]);
+ }
+
+ const ref = JSValue.createStringArray(ctx.ptr(), &routes_list_strings, list.len, true).asRef();
+ return ref;
+}
+
+pub fn readFileAsBytes(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ arguments: []const js.JSValueRef,
+ exception: js.ExceptionRef,
+) js.JSValueRef {
+ var buf: [bun.MAX_PATH_BYTES]u8 = undefined;
+ const path = getFilePath(ctx, arguments, &buf, exception) orelse return null;
+ buf[path.len] = 0;
+
+ const buf_z: [:0]const u8 = buf[0..path.len :0];
+ const result = readFileAsBytesCallback(ctx, buf_z, exception);
+ return result;
+}
+
+pub fn readFileAsString(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ arguments: []const js.JSValueRef,
+ exception: js.ExceptionRef,
+) js.JSValueRef {
+ var buf: [bun.MAX_PATH_BYTES]u8 = undefined;
+ const path = getFilePath(ctx, arguments, &buf, exception) orelse return null;
+ buf[path.len] = 0;
+
+ const buf_z: [:0]const u8 = buf[0..path.len :0];
+ const result = readFileAsStringCallback(ctx, buf_z, exception);
+ return result;
+}
+
+pub fn getPublicPath(to: string, origin: URL, comptime Writer: type, writer: Writer) void {
+ const relative_path = VirtualMachine.vm.bundler.fs.relativeTo(to);
+ if (origin.isAbsolute()) {
+ if (strings.hasPrefix(relative_path, "..") or strings.hasPrefix(relative_path, "./")) {
+ writer.writeAll(origin.origin) catch return;
+ writer.writeAll("/abs:") catch return;
+ if (std.fs.path.isAbsolute(to)) {
+ writer.writeAll(to) catch return;
+ } else {
+ writer.writeAll(VirtualMachine.vm.bundler.fs.abs(&[_]string{to})) catch return;
+ }
+ } else {
+ origin.joinWrite(
+ Writer,
+ writer,
+ VirtualMachine.vm.bundler.options.routes.asset_prefix_path,
+ "",
+ relative_path,
+ "",
+ ) catch return;
+ }
+ } else {
+ writer.writeAll(std.mem.trimLeft(u8, relative_path, "/")) catch unreachable;
+ }
+}
+
+pub fn sleepSync(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ arguments: []const js.JSValueRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ if (js.JSValueIsNumber(ctx, arguments[0])) {
+ const seconds = JSValue.fromRef(arguments[0]).asNumber();
+ if (seconds > 0 and std.math.isFinite(seconds)) std.time.sleep(@floatToInt(u64, seconds * 1000) * std.time.ns_per_ms);
+ }
+
+ return js.JSValueMakeUndefined(ctx);
+}
+
+pub fn createNodeFS(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ _: []const js.JSValueRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ return Node.NodeFSBindings.make(
+ ctx,
+ VirtualMachine.vm.node_fs orelse brk: {
+ VirtualMachine.vm.node_fs = bun.default_allocator.create(Node.NodeFS) catch unreachable;
+ VirtualMachine.vm.node_fs.?.* = Node.NodeFS{ .async_io = undefined };
+ break :brk VirtualMachine.vm.node_fs.?;
+ },
+ );
+}
+
+pub fn generateHeapSnapshot(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ _: []const js.JSValueRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ return ctx.ptr().generateHeapSnapshot().asObjectRef();
+}
+
+pub fn runGC(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ arguments: []const js.JSValueRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ // it should only force cleanup on thread exit
+
+ Global.mimalloc_cleanup(false);
+
+ return ctx.ptr().vm().runGC(arguments.len > 0 and JSValue.fromRef(arguments[0]).toBoolean()).asRef();
+}
+
+pub fn shrink(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ _: []const js.JSValueRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ ctx.ptr().vm().shrinkFootprint();
+ return JSValue.jsUndefined().asRef();
+}
+
+fn doResolve(
+ ctx: js.JSContextRef,
+ arguments: []const js.JSValueRef,
+ exception: js.ExceptionRef,
+) ?JSC.JSValue {
+ var args = JSC.Node.ArgumentsSlice.from(arguments);
+ const specifier = args.nextEat() orelse {
+ JSC.throwInvalidArguments("Expected a specifier and a from path", .{}, ctx, exception);
+ return null;
+ };
+
+ if (specifier.isUndefinedOrNull()) {
+ JSC.throwInvalidArguments("specifier must be a string", .{}, ctx, exception);
+ return null;
+ }
+
+ const from = args.nextEat() orelse {
+ JSC.throwInvalidArguments("Expected a from path", .{}, ctx, exception);
+ return null;
+ };
+
+ if (from.isUndefinedOrNull()) {
+ JSC.throwInvalidArguments("from must be a string", .{}, ctx, exception);
+ return null;
+ }
+
+ return doResolveWithArgs(ctx, specifier.getZigString(ctx.ptr()), from.getZigString(ctx.ptr()), exception);
+}
+
+fn doResolveWithArgs(
+ ctx: js.JSContextRef,
+ specifier: ZigString,
+ from: ZigString,
+ exception: js.ExceptionRef,
+) ?JSC.JSValue {
+ var errorable: ErrorableZigString = undefined;
+
+ VirtualMachine.resolveForAPI(
+ &errorable,
+ ctx.ptr(),
+ specifier,
+ from,
+ );
+
+ if (!errorable.success) {
+ exception.* = bun.cast(JSC.JSValueRef, errorable.result.err.ptr.?);
+ return null;
+ }
+
+ return errorable.result.value.toValue(ctx.ptr());
+}
+
+pub fn resolveSync(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ arguments: []const js.JSValueRef,
+ exception: js.ExceptionRef,
+) js.JSValueRef {
+ const value = doResolve(ctx, arguments, exception) orelse return null;
+ return value.asObjectRef();
+}
+
+pub fn resolve(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ arguments: []const js.JSValueRef,
+ exception: js.ExceptionRef,
+) js.JSValueRef {
+ const value = doResolve(ctx, arguments, exception) orelse {
+ var exception_value = exception.*.?;
+ exception.* = null;
+ return JSC.JSPromise.rejectedPromiseValue(ctx.ptr(), JSC.JSValue.fromRef(exception_value)).asObjectRef();
+ };
+ return JSC.JSPromise.resolvedPromiseValue(ctx.ptr(), value).asObjectRef();
+}
+
+export fn Bun__resolve(
+ global: *JSGlobalObject,
+ specifier: JSValue,
+ source: JSValue,
+) JSC.JSValue {
+ var exception_ = [1]JSC.JSValueRef{null};
+ var exception = &exception_;
+ const value = doResolveWithArgs(global.ref(), specifier.getZigString(global), source.getZigString(global), exception) orelse {
+ return JSC.JSPromise.rejectedPromiseValue(global, JSC.JSValue.fromRef(exception[0]));
+ };
+ return JSC.JSPromise.resolvedPromiseValue(global, value);
+}
+
+export fn Bun__resolveSync(
+ global: *JSGlobalObject,
+ specifier: JSValue,
+ source: JSValue,
+ exception_: ?*JSValue,
+) JSC.JSValue {
+ var exception_ = [1]JSC.JSValueRef{null};
+ var exception = &exception_;
+ exception_.* = exception[0];
+ const value = doResolveWithArgs(global.ref(), specifier.getZigString(global), source.getZigString(global), exception) orelse {
+ return JSC.JSPromise.rejectedPromiseValue(global, JSC.JSValue.fromRef(exception[0]));
+ };
+ return JSC.JSPromise.resolvedPromiseValue(global, value);
+}
+
+comptime {
+ if (!is_bindgen) {
+ _ = Bun__resolve;
+ _ = Bun__resolveSync;
+ }
+}
+
+pub fn readAllStdinSync(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ _: []const js.JSValueRef,
+ exception: js.ExceptionRef,
+) js.JSValueRef {
+ var stack = std.heap.stackFallback(2048, getAllocator(ctx));
+ var allocator = stack.get();
+
+ var stdin = std.io.getStdIn();
+ var result = stdin.readToEndAlloc(allocator, std.math.maxInt(u32)) catch |err| {
+ JSError(undefined, "{s} reading stdin", .{@errorName(err)}, ctx, exception);
+ return null;
+ };
+ var out = ZigString.init(result);
+ out.detectEncoding();
+ return out.toValueGC(ctx.ptr()).asObjectRef();
+}
+
+var public_path_temp_str: [bun.MAX_PATH_BYTES]u8 = undefined;
+
+pub fn getPublicPathJS(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ arguments: []const js.JSValueRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ var zig_str: ZigString = ZigString.Empty;
+ JSValue.toZigString(JSValue.fromRef(arguments[0]), &zig_str, ctx.ptr());
+
+ const to = zig_str.slice();
+
+ var stream = std.io.fixedBufferStream(&public_path_temp_str);
+ var writer = stream.writer();
+ getPublicPath(to, VirtualMachine.vm.origin, @TypeOf(&writer), &writer);
+ return ZigString.init(stream.buffer[0..stream.pos]).toValueGC(ctx.ptr()).asObjectRef();
+}
+
+// pub fn resolvePath(
+// _: void,
+// ctx: js.JSContextRef,
+// _: js.JSObjectRef,
+// _: js.JSObjectRef,
+// arguments: []const js.JSValueRef,
+// _: js.ExceptionRef,
+// ) js.JSValueRef {
+// if (arguments.len == 0) return ZigString.Empty.toValue(ctx.ptr()).asObjectRef();
+// var zig_str: ZigString = ZigString.Empty;
+// JSValue.toZigString(JSValue.fromRef(arguments[0]), &zig_str, ctx.ptr());
+// var buf: [bun.MAX_PATH_BYTES]u8 = undefined;
+// var stack = std.heap.stackFallback(32 * @sizeOf(string), VirtualMachine.vm.allocator);
+// var allocator = stack.get();
+// var parts = allocator.alloc(string, arguments.len) catch {};
+// defer allocator.free(parts);
+
+// const to = zig_str.slice();
+// var parts = .{to};
+// const value = ZigString.init(VirtualMachine.vm.bundler.fs.absBuf(&parts, &buf)).toValueGC(ctx.ptr());
+// return value.asObjectRef();
+// }
+
+pub const Class = NewClass(
+ void,
+ .{
+ .name = "Bun",
+ .read_only = true,
+ .ts = .{
+ .module = .{
+ .path = "bun.js/router",
+ .tsdoc = "Filesystem Router supporting dynamic routes, exact routes, catch-all routes, and optional catch-all routes. Implemented in native code and only available with Bun.js.",
+ },
+ },
+ },
+ .{
+ .match = .{
+ .rfn = Router.match,
+ .ts = Router.match_type_definition,
+ },
+
+ .sleepSync = .{
+ .rfn = sleepSync,
+ },
+ .fetch = .{
+ .rfn = Fetch.call,
+ .ts = d.ts{},
+ },
+ .getImportedStyles = .{
+ .rfn = Bun.getImportedStyles,
+ .ts = d.ts{
+ .name = "getImportedStyles",
+ .@"return" = "string[]",
+ },
+ },
+ .inspect = .{
+ .rfn = Bun.inspect,
+ .ts = d.ts{
+ .name = "inspect",
+ .@"return" = "string",
+ },
+ },
+ .getRouteFiles = .{
+ .rfn = Bun.getRouteFiles,
+ .ts = d.ts{
+ .name = "getRouteFiles",
+ .@"return" = "string[]",
+ },
+ },
+ ._Path = .{
+ .rfn = Bun.newPath,
+ .ts = d.ts{},
+ },
+ .getRouteNames = .{
+ .rfn = Bun.getRouteNames,
+ .ts = d.ts{
+ .name = "getRouteNames",
+ .@"return" = "string[]",
+ },
+ },
+ .readFile = .{
+ .rfn = Bun.readFileAsString,
+ .ts = d.ts{
+ .name = "readFile",
+ .@"return" = "string",
+ },
+ },
+ .resolveSync = .{
+ .rfn = Bun.resolveSync,
+ .ts = d.ts{
+ .name = "resolveSync",
+ .@"return" = "string",
+ },
+ },
+ .resolve = .{
+ .rfn = Bun.resolve,
+ .ts = d.ts{
+ .name = "resolve",
+ .@"return" = "string",
+ },
+ },
+ .readFileBytes = .{
+ .rfn = Bun.readFileAsBytes,
+ .ts = d.ts{
+ .name = "readFile",
+ .@"return" = "Uint8Array",
+ },
+ },
+ .getPublicPath = .{
+ .rfn = Bun.getPublicPathJS,
+ .ts = d.ts{
+ .name = "getPublicPath",
+ .@"return" = "string",
+ },
+ },
+ .registerMacro = .{
+ .rfn = Bun.registerMacro,
+ .ts = d.ts{
+ .name = "registerMacro",
+ .@"return" = "undefined",
+ },
+ },
+ .fs = .{
+ .rfn = Bun.createNodeFS,
+ .ts = d.ts{},
+ },
+ .jest = .{
+ .rfn = @import("../test/jest.zig").Jest.call,
+ .ts = d.ts{},
+ },
+ .gc = .{
+ .rfn = Bun.runGC,
+ .ts = d.ts{},
+ },
+ .generateHeapSnapshot = .{
+ .rfn = Bun.generateHeapSnapshot,
+ .ts = d.ts{},
+ },
+ .shrink = .{
+ .rfn = Bun.shrink,
+ .ts = d.ts{},
+ },
+ .readAllStdinSync = .{
+ .rfn = Bun.readAllStdinSync,
+ .ts = d.ts{},
+ },
+ },
+ .{
+ .main = .{
+ .get = getMain,
+ .ts = d.ts{ .name = "main", .@"return" = "string" },
+ },
+ .cwd = .{
+ .get = getCWD,
+ .ts = d.ts{ .name = "cwd", .@"return" = "string" },
+ },
+ .origin = .{
+ .get = getOrigin,
+ .ts = d.ts{ .name = "origin", .@"return" = "string" },
+ },
+ .routesDir = .{
+ .get = getRoutesDir,
+ .ts = d.ts{ .name = "routesDir", .@"return" = "string" },
+ },
+ .assetPrefix = .{
+ .get = getAssetPrefix,
+ .ts = d.ts{ .name = "assetPrefix", .@"return" = "string" },
+ },
+ .argv = .{
+ .get = getArgv,
+ .ts = d.ts{ .name = "argv", .@"return" = "string[]" },
+ },
+ .env = .{
+ .get = EnvironmentVariables.getter,
+ },
+ .enableANSIColors = .{
+ .get = enableANSIColors,
+ },
+ .Transpiler = .{
+ .get = getTranspilerConstructor,
+ .ts = d.ts{ .name = "Transpiler", .@"return" = "Transpiler.prototype" },
+ },
+ .TOML = .{
+ .get = getTOMLObject,
+ .ts = d.ts{ .name = "TOML", .@"return" = "TOML.prototype" },
+ },
+ .unsafe = .{
+ .get = getUnsafe,
+ },
+ },
+);
+
+pub fn getTranspilerConstructor(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSValueRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ return js.JSObjectMake(ctx, Transpiler.TranspilerConstructor.get().?[0], null);
+}
+
+pub fn getTOMLObject(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSValueRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ return js.JSObjectMake(ctx, TOML.Class.get().?[0], null);
+}
+
+pub fn getUnsafe(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSValueRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ return js.JSObjectMake(ctx, Unsafe.Class.get().?[0], null);
+}
+
+pub const Unsafe = struct {
+ pub const Class = NewClass(
+ void,
+ .{ .name = "Unsafe", .read_only = true },
+ .{
+ .segfault = .{
+ .rfn = __debug__doSegfault,
+ },
+ .arrayBufferToString = .{
+ .rfn = arrayBufferToString,
+ },
+ },
+ .{},
+ );
+
+ // For testing the segfault handler
+ pub fn __debug__doSegfault(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ _: []const js.JSValueRef,
+ _: js.ExceptionRef,
+ ) js.JSValueRef {
+ _ = ctx;
+ const Reporter = @import("../../../report.zig");
+ Reporter.globalError(error.SegfaultTest);
+ }
+
+ pub fn arrayBufferToString(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ args: []const js.JSValueRef,
+ exception: js.ExceptionRef,
+ ) js.JSValueRef {
+ const array_buffer = JSC.ArrayBuffer.fromTypedArray(ctx, JSC.JSValue.fromRef(args[0]), exception);
+ switch (array_buffer.typed_array_type) {
+ .Uint16Array, .Int16Array => {
+ var zig_str = ZigString.init("");
+ zig_str.ptr = @ptrCast([*]const u8, @alignCast(@alignOf([*]align(1) const u16), array_buffer.ptr));
+ zig_str.len = array_buffer.len;
+ zig_str.markUTF16();
+ return ZigString.toValue(&zig_str, ctx.ptr()).asObjectRef();
+ },
+ else => {
+ return ZigString.init(array_buffer.slice()).toValue(ctx.ptr()).asObjectRef();
+ },
+ }
+ }
+};
+
+// pub const Lockfile = struct {
+// const BunLockfile = @import("../../../install/install.zig").Lockfile;
+// lockfile: *BunLockfile,
+
+// pub const RefCountedLockfile = bun.RefCount(Lockfile, true);
+
+// pub const StaticClass = NewClass(
+// void,
+// .{
+// .name = "Lockfile",
+// .read_only = true,
+// },
+// .{
+// .load = .{
+// .rfn = BunLockfile.load,
+// },
+// },
+// .{},
+// );
+
+// pub const Class = NewClass(
+// RefCountedLockfile,
+// .{
+// .name = "Lockfile",
+// .read_only = true,
+// },
+// .{
+// .findPackagesByName = .{
+// .rfn = BunLockfile.load,
+// },
+// .dependencies = .{
+// .rfn = BunLockfile.load,
+// },
+// },
+// .{},
+// );
+
+// pub fn deinit(this: *Lockfile) void {
+// this.lockfile.deinit();
+// }
+
+// pub fn load(
+// // this
+// _: void,
+// ctx: js.JSContextRef,
+// // function
+// _: js.JSObjectRef,
+// // thisObject
+// _: js.JSObjectRef,
+// arguments: []const js.JSValueRef,
+// exception: js.ExceptionRef,
+// ) js.JSValueRef {
+// if (arguments.len == 0) {
+// JSError(undefined, "Expected file path string or buffer", .{}, ctx, exception);
+// return null;
+// }
+
+// var lockfile: *BunLockfile = getAllocator(ctx).create(BunLockfile) catch return JSValue.jsUndefined().asRef();
+
+// var log = logger.Log.init(default_allocator);
+// var args_slice = @ptrCast([*]const JSValue, arguments.ptr)[0..arguments.len];
+
+// var arguments_slice = Node.ArgumentsSlice.init(args_slice);
+// var path_or_buffer = Node.PathLike.fromJS(ctx, &arguments_slice, exception) orelse {
+// getAllocator(ctx).destroy(lockfile);
+// JSError(undefined, "Expected file path string or buffer", .{}, ctx, exception);
+// return null;
+// };
+
+// const load_from_disk_result = switch (path_or_buffer) {
+// Node.PathLike.Tag.string => lockfile.loadFromDisk(getAllocator(ctx), &log, path_or_buffer.string),
+// Node.PathLike.Tag.buffer => lockfile.loadFromBytes(getAllocator(ctx), path_or_buffer.buffer.slice(), &log),
+// else => {
+// getAllocator(ctx).destroy(lockfile);
+// JSError(undefined, "Expected file path string or buffer", .{}, ctx, exception);
+// return null;
+// },
+// };
+
+// switch (load_from_disk_result) {
+// .err => |cause| {
+// defer getAllocator(ctx).destroy(lockfile);
+// switch (cause.step) {
+// .open_file => {
+// JSError(undefined, "error opening lockfile: {s}", .{
+// @errorName(cause.value),
+// }, ctx, exception);
+// return null;
+// },
+// .parse_file => {
+// JSError(undefined, "error parsing lockfile: {s}", .{
+// @errorName(cause.value),
+// }, ctx, exception);
+// return null;
+// },
+// .read_file => {
+// JSError(undefined, "error reading lockfile: {s}", .{
+// @errorName(cause.value),
+// }, ctx, exception);
+// return null;
+// },
+// }
+// },
+// .ok => {},
+// }
+// }
+// };
+
+pub const TOML = struct {
+ const TOMLParser = @import("../../../toml/toml_parser.zig").TOML;
+ pub const Class = NewClass(
+ void,
+ .{
+ .name = "TOML",
+ .read_only = true,
+ },
+ .{
+ .parse = .{
+ .rfn = TOML.parse,
+ },
+ },
+ .{},
+ );
+
+ pub fn parse(
+ // this
+ _: void,
+ ctx: js.JSContextRef,
+ // function
+ _: js.JSObjectRef,
+ // thisObject
+ _: js.JSObjectRef,
+ arguments: []const js.JSValueRef,
+ exception: js.ExceptionRef,
+ ) js.JSValueRef {
+ var arena = std.heap.ArenaAllocator.init(getAllocator(ctx));
+ var allocator = arena.allocator();
+ defer arena.deinit();
+ var log = logger.Log.init(default_allocator);
+ var input_str = ZigString.init("");
+ JSValue.fromRef(arguments[0]).toZigString(&input_str, ctx.ptr());
+ var needs_deinit = false;
+ var input = input_str.slice();
+ if (input_str.is16Bit()) {
+ input = std.fmt.allocPrint(allocator, "{}", .{input_str}) catch unreachable;
+ needs_deinit = true;
+ }
+ var source = logger.Source.initPathString("input.toml", input);
+ var parse_result = TOMLParser.parse(&source, &log, allocator) catch {
+ exception.* = log.toJS(ctx.ptr(), default_allocator, "Failed to parse toml").asObjectRef();
+ return null;
+ };
+
+ // for now...
+ var buffer_writer = try js_printer.BufferWriter.init(allocator);
+ var writer = js_printer.BufferPrinter.init(buffer_writer);
+ _ = js_printer.printJSON(*js_printer.BufferPrinter, &writer, parse_result, &source) catch {
+ exception.* = log.toJS(ctx.ptr(), default_allocator, "Failed to print toml").asObjectRef();
+ return null;
+ };
+
+ var slice = writer.ctx.buffer.toOwnedSliceLeaky();
+ var out = ZigString.init(slice);
+
+ const out_value = js.JSValueMakeFromJSONString(ctx, out.toJSStringRef());
+ return out_value;
+ }
+};
+
+pub const Timer = struct {
+ last_id: i32 = 0,
+ warned: bool = false,
+ active: u32 = 0,
+ timeouts: TimeoutMap = TimeoutMap{},
+
+ const TimeoutMap = std.AutoArrayHashMapUnmanaged(i32, *Timeout);
+
+ pub fn getNextID() callconv(.C) i32 {
+ VirtualMachine.vm.timer.last_id += 1;
+ return VirtualMachine.vm.timer.last_id;
+ }
+
+ pub const Timeout = struct {
+ id: i32 = 0,
+ callback: JSValue,
+ interval: i32 = 0,
+ completion: NetworkThread.Completion = undefined,
+ repeat: bool = false,
+ io_task: ?*TimeoutTask = null,
+ cancelled: bool = false,
+
+ pub const TimeoutTask = IOTask(Timeout);
+
+ pub fn run(this: *Timeout, _task: *TimeoutTask) void {
+ this.io_task = _task;
+ NetworkThread.global.pool.io.?.timeout(
+ *Timeout,
+ this,
+ onCallback,
+ &this.completion,
+ std.time.ns_per_ms * @intCast(
+ u63,
+ @maximum(
+ this.interval,
+ 1,
+ ),
+ ),
+ );
+ }
+
+ pub fn onCallback(this: *Timeout, _: *NetworkThread.Completion, _: NetworkThread.AsyncIO.TimeoutError!void) void {
+ this.io_task.?.onFinish();
+ }
+
+ pub fn then(this: *Timeout, global: *JSGlobalObject) void {
+ if (!this.cancelled) {
+ if (this.repeat) {
+ this.io_task.?.deinit();
+ var task = Timeout.TimeoutTask.createOnJSThread(VirtualMachine.vm.allocator, global, this) catch unreachable;
+ this.io_task = task;
+ task.schedule();
+ }
+
+ _ = JSC.C.JSObjectCallAsFunction(global.ref(), this.callback.asObjectRef(), null, 0, null, null);
+
+ if (this.repeat)
+ return;
+ }
+
+ this.clear(global);
+ }
+
+ pub fn clear(this: *Timeout, global: *JSGlobalObject) void {
+ this.cancelled = true;
+ JSC.C.JSValueUnprotect(global.ref(), this.callback.asObjectRef());
+ _ = VirtualMachine.vm.timer.timeouts.swapRemove(this.id);
+ if (this.io_task) |task| {
+ task.deinit();
+ }
+ VirtualMachine.vm.allocator.destroy(this);
+ VirtualMachine.vm.timer.active -|= 1;
+ VirtualMachine.vm.active_tasks -|= 1;
+ }
+ };
+
+ fn set(
+ id: i32,
+ globalThis: *JSGlobalObject,
+ callback: JSValue,
+ countdown: JSValue,
+ repeat: bool,
+ ) !void {
+ if (comptime is_bindgen) unreachable;
+ var timeout = try VirtualMachine.vm.allocator.create(Timeout);
+ js.JSValueProtect(globalThis.ref(), callback.asObjectRef());
+ timeout.* = Timeout{ .id = id, .callback = callback, .interval = countdown.toInt32(), .repeat = repeat };
+ var task = try Timeout.TimeoutTask.createOnJSThread(VirtualMachine.vm.allocator, globalThis, timeout);
+ VirtualMachine.vm.timer.timeouts.put(VirtualMachine.vm.allocator, id, timeout) catch unreachable;
+ VirtualMachine.vm.timer.active +|= 1;
+ VirtualMachine.vm.active_tasks +|= 1;
+ task.schedule();
+ }
+
+ pub fn setTimeout(
+ globalThis: *JSGlobalObject,
+ callback: JSValue,
+ countdown: JSValue,
+ ) callconv(.C) JSValue {
+ if (comptime is_bindgen) unreachable;
+ const id = VirtualMachine.vm.timer.last_id;
+ VirtualMachine.vm.timer.last_id +%= 1;
+
+ Timer.set(id, globalThis, callback, countdown, false) catch
+ return JSValue.jsUndefined();
+
+ return JSValue.jsNumberWithType(i32, id);
+ }
+ pub fn setInterval(
+ globalThis: *JSGlobalObject,
+ callback: JSValue,
+ countdown: JSValue,
+ ) callconv(.C) JSValue {
+ if (comptime is_bindgen) unreachable;
+ const id = VirtualMachine.vm.timer.last_id;
+ VirtualMachine.vm.timer.last_id +%= 1;
+
+ Timer.set(id, globalThis, callback, countdown, true) catch
+ return JSValue.jsUndefined();
+
+ return JSValue.jsNumberWithType(i32, id);
+ }
+
+ pub fn clearTimer(id: JSValue, _: *JSGlobalObject) void {
+ if (comptime is_bindgen) unreachable;
+ var timer: *Timeout = VirtualMachine.vm.timer.timeouts.get(id.toInt32()) orelse return;
+ timer.cancelled = true;
+ }
+
+ pub fn clearTimeout(
+ globalThis: *JSGlobalObject,
+ id: JSValue,
+ ) callconv(.C) JSValue {
+ if (comptime is_bindgen) unreachable;
+ Timer.clearTimer(id, globalThis);
+ return JSValue.jsUndefined();
+ }
+ pub fn clearInterval(
+ globalThis: *JSGlobalObject,
+ id: JSValue,
+ ) callconv(.C) JSValue {
+ if (comptime is_bindgen) unreachable;
+ Timer.clearTimer(id, globalThis);
+ return JSValue.jsUndefined();
+ }
+
+ const Shimmer = @import("../bindings/shimmer.zig").Shimmer;
+
+ pub const shim = Shimmer("Bun", "Timer", @This());
+ pub const name = "Bun__Timer";
+ pub const include = "";
+ pub const namespace = shim.namespace;
+
+ pub const Export = shim.exportFunctions(.{
+ .@"setTimeout" = setTimeout,
+ .@"setInterval" = setInterval,
+ .@"clearTimeout" = clearTimeout,
+ .@"clearInterval" = clearInterval,
+ .@"getNextID" = getNextID,
+ });
+
+ comptime {
+ @export(setTimeout, .{ .name = Export[0].symbol_name });
+ @export(setInterval, .{ .name = Export[1].symbol_name });
+ @export(clearTimeout, .{ .name = Export[2].symbol_name });
+ @export(clearInterval, .{ .name = Export[3].symbol_name });
+ @export(getNextID, .{ .name = Export[4].symbol_name });
+ }
+};
+
+/// EnvironmentVariables is runtime defined.
+/// Also, you can't iterate over process.env normally since it only exists at build-time otherwise
+// This is aliased to Bun.env
+pub const EnvironmentVariables = struct {
+ pub const Class = NewClass(
+ void,
+ .{
+ .name = "DotEnv",
+ .read_only = true,
+ },
+ .{
+ .getProperty = .{
+ .rfn = getProperty,
+ },
+ .setProperty = .{
+ .rfn = setProperty,
+ },
+ .deleteProperty = .{
+ .rfn = deleteProperty,
+ },
+ .convertToType = .{ .rfn = convertToType },
+ .hasProperty = .{
+ .rfn = hasProperty,
+ },
+ .getPropertyNames = .{
+ .rfn = getPropertyNames,
+ },
+ .toJSON = .{
+ .rfn = toJSON,
+ .name = "toJSON",
+ },
+ },
+ .{},
+ );
+
+ pub fn getter(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSValueRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+ ) js.JSValueRef {
+ return js.JSObjectMake(ctx, EnvironmentVariables.Class.get().*, null);
+ }
+
+ pub const BooleanString = struct {
+ pub const @"true": string = "true";
+ pub const @"false": string = "false";
+ };
+
+ pub fn getProperty(
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ propertyName: js.JSStringRef,
+ _: js.ExceptionRef,
+ ) callconv(.C) js.JSValueRef {
+ const len = js.JSStringGetLength(propertyName);
+ var ptr = js.JSStringGetCharacters8Ptr(propertyName);
+ var name = ptr[0..len];
+ if (VirtualMachine.vm.bundler.env.map.get(name)) |value| {
+ return ZigString.toRef(value, ctx.ptr());
+ }
+
+ if (Output.enable_ansi_colors) {
+ // https://github.com/chalk/supports-color/blob/main/index.js
+ if (strings.eqlComptime(name, "FORCE_COLOR")) {
+ return ZigString.toRef(BooleanString.@"true", ctx.ptr());
+ }
+ }
+
+ return js.JSValueMakeUndefined(ctx);
+ }
+
+ pub fn toJSON(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ _: []const js.JSValueRef,
+ _: js.ExceptionRef,
+ ) js.JSValueRef {
+ var map = VirtualMachine.vm.bundler.env.map.map;
+ var keys = map.keys();
+ var values = map.values();
+ const StackFallback = std.heap.StackFallbackAllocator(32 * 2 * @sizeOf(ZigString));
+ var stack = StackFallback{
+ .buffer = undefined,
+ .fallback_allocator = bun.default_allocator,
+ .fixed_buffer_allocator = undefined,
+ };
+ var allocator = stack.get();
+ var key_strings_ = allocator.alloc(ZigString, keys.len * 2) catch unreachable;
+ var key_strings = key_strings_[0..keys.len];
+ var value_strings = key_strings_[keys.len..];
+
+ for (keys) |key, i| {
+ key_strings[i] = ZigString.init(key);
+ key_strings[i].detectEncoding();
+ value_strings[i] = ZigString.init(values[i]);
+ value_strings[i].detectEncoding();
+ }
+
+ var result = JSValue.fromEntries(ctx.ptr(), key_strings.ptr, value_strings.ptr, keys.len, false).asObjectRef();
+ allocator.free(key_strings_);
+ return result;
+ // }
+ // ZigConsoleClient.Formatter.format(this: *Formatter, result: Tag.Result, comptime Writer: type, writer: Writer, value: JSValue, globalThis: *JSGlobalObject, comptime enable_ansi_colors: bool)
+ }
+
+ pub fn deleteProperty(
+ _: js.JSContextRef,
+ _: js.JSObjectRef,
+ propertyName: js.JSStringRef,
+ _: js.ExceptionRef,
+ ) callconv(.C) bool {
+ const len = js.JSStringGetLength(propertyName);
+ var ptr = js.JSStringGetCharacters8Ptr(propertyName);
+ var name = ptr[0..len];
+ _ = VirtualMachine.vm.bundler.env.map.map.swapRemove(name);
+ return true;
+ }
+
+ pub fn setProperty(
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ propertyName: js.JSStringRef,
+ value: js.JSValueRef,
+ exception: js.ExceptionRef,
+ ) callconv(.C) bool {
+ const len = js.JSStringGetLength(propertyName);
+ var ptr = js.JSStringGetCharacters8Ptr(propertyName);
+ var name = ptr[0..len];
+ var val = ZigString.init("");
+ JSValue.fromRef(value).toZigString(&val, ctx.ptr());
+ if (exception.* != null) return false;
+ var result = std.fmt.allocPrint(VirtualMachine.vm.allocator, "{}", .{val}) catch unreachable;
+ VirtualMachine.vm.bundler.env.map.put(name, result) catch unreachable;
+
+ return true;
+ }
+
+ pub fn hasProperty(
+ _: js.JSContextRef,
+ _: js.JSObjectRef,
+ propertyName: js.JSStringRef,
+ ) callconv(.C) bool {
+ const len = js.JSStringGetLength(propertyName);
+ const ptr = js.JSStringGetCharacters8Ptr(propertyName);
+ const name = ptr[0..len];
+ return VirtualMachine.vm.bundler.env.map.get(name) != null or (Output.enable_ansi_colors and strings.eqlComptime(name, "FORCE_COLOR"));
+ }
+
+ pub fn convertToType(ctx: js.JSContextRef, obj: js.JSObjectRef, kind: js.JSType, exception: js.ExceptionRef) callconv(.C) js.JSValueRef {
+ _ = ctx;
+ _ = obj;
+ _ = kind;
+ _ = exception;
+ return obj;
+ }
+
+ pub fn getPropertyNames(
+ _: js.JSContextRef,
+ _: js.JSObjectRef,
+ props: js.JSPropertyNameAccumulatorRef,
+ ) callconv(.C) void {
+ var iter = VirtualMachine.vm.bundler.env.map.iter();
+
+ while (iter.next()) |item| {
+ const str = item.key_ptr.*;
+ js.JSPropertyNameAccumulatorAddName(props, js.JSStringCreateStatic(str.ptr, str.len));
+ }
+ }
+};
diff --git a/src/javascript/jsc/api/router.zig b/src/javascript/jsc/api/router.zig
index b6f96b082..da0731efa 100644
--- a/src/javascript/jsc/api/router.zig
+++ b/src/javascript/jsc/api/router.zig
@@ -450,7 +450,7 @@ pub fn getScriptSrcString(
// instead, we just store a boolean saying whether we should generate this whenever the script is requested
// this is kind of bad. we should consider instead a way to inline the contents of the script.
if (client_framework_enabled) {
- JavaScript.Bun.getPublicPath(
+ JSC.API.Bun.getPublicPath(
Bundler.ClientEntryPoint.generateEntryPointPath(
&entry_point_tempbuf,
Fs.PathName.init(file_path),
@@ -460,7 +460,7 @@ pub fn getScriptSrcString(
writer,
);
} else {
- JavaScript.Bun.getPublicPath(file_path, VirtualMachine.vm.origin, Writer, writer);
+ JSC.API.Bun.getPublicPath(file_path, VirtualMachine.vm.origin, Writer, writer);
}
}
diff --git a/src/javascript/jsc/bindings/exports.zig b/src/javascript/jsc/bindings/exports.zig
index ccdded85c..7a4c1eb0a 100644
--- a/src/javascript/jsc/bindings/exports.zig
+++ b/src/javascript/jsc/bindings/exports.zig
@@ -1252,7 +1252,7 @@ pub const ZigConsoleClient = struct {
// Temporary workaround
// console.log(process.env) shows up as [class JSCallbackObject]
// We want to print it like an object
- if (CAPI.JSValueIsObjectOfClass(globalThis.ref(), value.asObjectRef(), JSC.Bun.EnvironmentVariables.Class.get().?[0])) {
+ if (CAPI.JSValueIsObjectOfClass(globalThis.ref(), value.asObjectRef(), JSC.API.Bun.EnvironmentVariables.Class.get().?[0])) {
return .{
.tag = .Object,
.cell = js_type,
@@ -2472,7 +2472,7 @@ comptime {
@export(ErrorCode.JSErrorObject, .{ .name = "Zig_ErrorCodeJSErrorObject" });
}
-const Bun = @import("../javascript.zig").Bun;
+const Bun = @import("../api/bun.zig");
pub const BunTimer = Bun.Timer;
pub const Formatter = ZigConsoleClient.Formatter;
diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig
index 594525cc3..072f685b3 100644
--- a/src/javascript/jsc/javascript.zig
+++ b/src/javascript/jsc/javascript.zig
@@ -83,6 +83,7 @@ const JSFunction = @import("../../jsc.zig").JSFunction;
const Config = @import("./config.zig");
const URL = @import("../../url.zig").URL;
const Transpiler = @import("./api/transpiler.zig");
+const Bun = JSC.API.Bun;
pub const GlobalClasses = [_]type{
Request.Class,
Response.Class,
@@ -111,1410 +112,6 @@ const Blob = @import("../../blob.zig");
pub const Buffer = MarkedArrayBuffer;
const Lock = @import("../../lock.zig").Lock;
-pub const Bun = struct {
- threadlocal var css_imports_list_strings: [512]ZigString = undefined;
- threadlocal var css_imports_list: [512]Api.StringPointer = undefined;
- threadlocal var css_imports_list_tail: u16 = 0;
- threadlocal var css_imports_buf: std.ArrayList(u8) = undefined;
- threadlocal var css_imports_buf_loaded: bool = false;
-
- threadlocal var routes_list_strings: [1024]ZigString = undefined;
-
- pub fn onImportCSS(
- resolve_result: *const Resolver.Result,
- import_record: *ImportRecord,
- origin: URL,
- ) void {
- if (!css_imports_buf_loaded) {
- css_imports_buf = std.ArrayList(u8).initCapacity(
- VirtualMachine.vm.allocator,
- import_record.path.text.len,
- ) catch unreachable;
- css_imports_buf_loaded = true;
- }
-
- var writer = css_imports_buf.writer();
- const offset = css_imports_buf.items.len;
- css_imports_list[css_imports_list_tail] = .{
- .offset = @truncate(u32, offset),
- .length = 0,
- };
- getPublicPath(resolve_result.path_pair.primary.text, origin, @TypeOf(writer), writer);
- const length = css_imports_buf.items.len - offset;
- css_imports_list[css_imports_list_tail].length = @truncate(u32, length);
- css_imports_list_tail += 1;
- }
-
- pub fn flushCSSImports() void {
- if (css_imports_buf_loaded) {
- css_imports_buf.clearRetainingCapacity();
- css_imports_list_tail = 0;
- }
- }
-
- pub fn getCSSImports() []ZigString {
- var i: u16 = 0;
- const tail = css_imports_list_tail;
- while (i < tail) : (i += 1) {
- ZigString.fromStringPointer(css_imports_list[i], css_imports_buf.items, &css_imports_list_strings[i]);
- }
- return css_imports_list_strings[0..tail];
- }
-
- pub fn inspect(
- // this
- _: void,
- ctx: js.JSContextRef,
- // function
- _: js.JSObjectRef,
- // thisObject
- _: js.JSObjectRef,
- arguments: []const js.JSValueRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- if (arguments.len == 0)
- return ZigString.Empty.toValue(ctx.ptr()).asObjectRef();
-
- for (arguments) |arg| {
- JSC.C.JSValueProtect(ctx, arg);
- }
- defer {
- for (arguments) |arg| {
- JSC.C.JSValueUnprotect(ctx, arg);
- }
- }
-
- // very stable memory address
- var array = MutableString.init(getAllocator(ctx), 0) catch unreachable;
- var buffered_writer_ = MutableString.BufferedWriter{ .context = &array };
- var buffered_writer = &buffered_writer_;
-
- var writer = buffered_writer.writer();
- const Writer = @TypeOf(writer);
- // we buffer this because it'll almost always be < 4096
- // when it's under 4096, we want to avoid the dynamic allocation
- ZigConsoleClient.format(
- .Debug,
- ctx.ptr(),
- @ptrCast([*]const JSValue, arguments.ptr),
- arguments.len,
- Writer,
- Writer,
- writer,
- false,
- false,
- false,
- );
-
- // when it's a small thing, rely on GC to manage the memory
- if (writer.context.pos < 2048 and array.list.items.len == 0) {
- var slice = writer.context.buffer[0..writer.context.pos];
- if (slice.len == 0) {
- return ZigString.Empty.toValue(ctx.ptr()).asObjectRef();
- }
-
- var zig_str = ZigString.init(slice).withEncoding();
- return zig_str.toValueGC(ctx.ptr()).asObjectRef();
- }
-
- // when it's a big thing, we will manage it
- {
- writer.context.flush() catch {};
- var slice = writer.context.context.toOwnedSlice();
-
- var zig_str = ZigString.init(slice).withEncoding();
- if (!zig_str.isUTF8()) {
- return zig_str.toExternalValue(ctx.ptr()).asObjectRef();
- } else {
- return zig_str.toValueGC(ctx.ptr()).asObjectRef();
- }
- }
- }
-
- pub fn registerMacro(
- // this
- _: void,
- ctx: js.JSContextRef,
- // function
- _: js.JSObjectRef,
- // thisObject
- _: js.JSObjectRef,
- arguments: []const js.JSValueRef,
- exception: js.ExceptionRef,
- ) js.JSValueRef {
- if (arguments.len != 2 or !js.JSValueIsNumber(ctx, arguments[0])) {
- JSError(getAllocator(ctx), "Internal error registering macros: invalid args", .{}, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- }
- // TODO: make this faster
- const id = @truncate(i32, @floatToInt(i64, js.JSValueToNumber(ctx, arguments[0], exception)));
- if (id == -1 or id == 0) {
- JSError(getAllocator(ctx), "Internal error registering macros: invalid id", .{}, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- }
-
- if (!js.JSValueIsObject(ctx, arguments[1]) or !js.JSObjectIsFunction(ctx, arguments[1])) {
- JSError(getAllocator(ctx), "Macro must be a function. Received: {s}", .{@tagName(js.JSValueGetType(ctx, arguments[1]))}, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- }
-
- var get_or_put_result = VirtualMachine.vm.macros.getOrPut(id) catch unreachable;
- if (get_or_put_result.found_existing) {
- js.JSValueUnprotect(ctx, get_or_put_result.value_ptr.*);
- }
-
- js.JSValueProtect(ctx, arguments[1]);
- get_or_put_result.value_ptr.* = arguments[1];
-
- return js.JSValueMakeUndefined(ctx);
- }
-
- pub fn getCWD(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSValueRef,
- _: js.JSStringRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- return ZigString.init(VirtualMachine.vm.bundler.fs.top_level_dir).toValue(ctx.ptr()).asRef();
- }
-
- pub fn getOrigin(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSValueRef,
- _: js.JSStringRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- return ZigString.init(VirtualMachine.vm.origin.origin).toValue(ctx.ptr()).asRef();
- }
-
- pub fn enableANSIColors(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSValueRef,
- _: js.JSStringRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- return js.JSValueMakeBoolean(ctx, Output.enable_ansi_colors);
- }
- pub fn getMain(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSValueRef,
- _: js.JSStringRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- return ZigString.init(VirtualMachine.vm.main).toValue(ctx.ptr()).asRef();
- }
-
- pub fn getAssetPrefix(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSValueRef,
- _: js.JSStringRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- return ZigString.init(VirtualMachine.vm.bundler.options.routes.asset_prefix_path).toValue(ctx.ptr()).asRef();
- }
-
- pub fn getArgv(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSValueRef,
- _: js.JSStringRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- if (comptime Environment.isWindows) {
- @compileError("argv not supported on windows");
- }
-
- var argv_list = std.heap.stackFallback(128, getAllocator(ctx));
- var allocator = argv_list.get();
- var argv = allocator.alloc(ZigString, std.os.argv.len) catch unreachable;
- defer if (argv.len > 128) allocator.free(argv);
- for (std.os.argv) |arg, i| {
- argv[i] = ZigString.init(std.mem.span(arg));
- }
-
- return JSValue.createStringArray(ctx.ptr(), argv.ptr, argv.len, true).asObjectRef();
- }
-
- pub fn getRoutesDir(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSValueRef,
- _: js.JSStringRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- if (!VirtualMachine.vm.bundler.options.routes.routes_enabled or VirtualMachine.vm.bundler.options.routes.dir.len == 0) {
- return js.JSValueMakeUndefined(ctx);
- }
-
- return ZigString.init(VirtualMachine.vm.bundler.options.routes.dir).toValue(ctx.ptr()).asRef();
- }
-
- pub fn getFilePath(ctx: js.JSContextRef, arguments: []const js.JSValueRef, buf: []u8, exception: js.ExceptionRef) ?string {
- if (arguments.len != 1) {
- JSError(getAllocator(ctx), "Expected a file path as a string or an array of strings to be part of a file path.", .{}, ctx, exception);
- return null;
- }
-
- const value = arguments[0];
- if (js.JSValueIsString(ctx, value)) {
- var out = ZigString.Empty;
- JSValue.toZigString(JSValue.fromRef(value), &out, ctx.ptr());
- var out_slice = out.slice();
-
- // The dots are kind of unnecessary. They'll be normalized.
- if (out.len == 0 or @ptrToInt(out.ptr) == 0 or std.mem.eql(u8, out_slice, ".") or std.mem.eql(u8, out_slice, "..") or std.mem.eql(u8, out_slice, "../")) {
- JSError(getAllocator(ctx), "Expected a file path as a string or an array of strings to be part of a file path.", .{}, ctx, exception);
- return null;
- }
-
- var parts = [_]string{out_slice};
- // This does the equivalent of Node's path.normalize(path.join(cwd, out_slice))
- var res = VirtualMachine.vm.bundler.fs.absBuf(&parts, buf);
-
- return res;
- } else if (js.JSValueIsArray(ctx, value)) {
- var temp_strings_list: [32]string = undefined;
- var temp_strings_list_len: u8 = 0;
- defer {
- for (temp_strings_list[0..temp_strings_list_len]) |_, i| {
- temp_strings_list[i] = "";
- }
- }
-
- var iter = JSValue.fromRef(value).arrayIterator(ctx.ptr());
- while (iter.next()) |item| {
- if (temp_strings_list_len >= temp_strings_list.len) {
- break;
- }
-
- if (!item.isString()) {
- JSError(getAllocator(ctx), "Expected a file path as a string or an array of strings to be part of a file path.", .{}, ctx, exception);
- return null;
- }
-
- var out = ZigString.Empty;
- JSValue.toZigString(item, &out, ctx.ptr());
- const out_slice = out.slice();
-
- temp_strings_list[temp_strings_list_len] = out_slice;
- // The dots are kind of unnecessary. They'll be normalized.
- if (out.len == 0 or @ptrToInt(out.ptr) == 0 or std.mem.eql(u8, out_slice, ".") or std.mem.eql(u8, out_slice, "..") or std.mem.eql(u8, out_slice, "../")) {
- JSError(getAllocator(ctx), "Expected a file path as a string or an array of strings to be part of a file path.", .{}, ctx, exception);
- return null;
- }
- temp_strings_list_len += 1;
- }
-
- if (temp_strings_list_len == 0) {
- JSError(getAllocator(ctx), "Expected a file path as a string or an array of strings to be part of a file path.", .{}, ctx, exception);
- return null;
- }
-
- return VirtualMachine.vm.bundler.fs.absBuf(temp_strings_list[0..temp_strings_list_len], buf);
- } else {
- JSError(getAllocator(ctx), "Expected a file path as a string or an array of strings to be part of a file path.", .{}, ctx, exception);
- return null;
- }
- }
-
- pub fn getImportedStyles(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- _: []const js.JSValueRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- defer flushCSSImports();
- const styles = getCSSImports();
- if (styles.len == 0) {
- return js.JSObjectMakeArray(ctx, 0, null, null);
- }
-
- 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,
- exception: js.ExceptionRef,
- ) js.JSValueRef {
- const path = buf_z.ptr[0..buf_z.len];
- var file = std.fs.cwd().openFileZ(buf_z, .{ .mode = .read_only }) catch |err| {
- JSError(getAllocator(ctx), "Opening file {s} for path: \"{s}\"", .{ @errorName(err), path }, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- };
-
- defer file.close();
-
- const stat = file.stat() catch |err| {
- JSError(getAllocator(ctx), "Getting file size {s} for \"{s}\"", .{ @errorName(err), path }, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- };
-
- if (stat.kind != .File) {
- JSError(getAllocator(ctx), "Can't read a {s} as a string (\"{s}\")", .{ @tagName(stat.kind), path }, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- }
-
- var contents_buf = VirtualMachine.vm.allocator.alloc(u8, stat.size + 2) catch unreachable; // OOM
- defer VirtualMachine.vm.allocator.free(contents_buf);
- const contents_len = file.readAll(contents_buf) catch |err| {
- JSError(getAllocator(ctx), "{s} reading file (\"{s}\")", .{ @errorName(err), path }, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- };
-
- contents_buf[contents_len] = 0;
-
- // Very slow to do it this way. We're copying the string twice.
- // But it's important that this string is garbage collected instead of manually managed.
- // We can't really recycle this one.
- // TODO: use external string
- return js.JSValueMakeString(ctx, js.JSStringCreateWithUTF8CString(contents_buf.ptr));
- }
-
- pub fn readFileAsBytesCallback(
- ctx: js.JSContextRef,
- buf_z: [:0]const u8,
- exception: js.ExceptionRef,
- ) js.JSValueRef {
- const path = buf_z.ptr[0..buf_z.len];
-
- var file = std.fs.cwd().openFileZ(buf_z, .{ .mode = .read_only }) catch |err| {
- JSError(getAllocator(ctx), "Opening file {s} for path: \"{s}\"", .{ @errorName(err), path }, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- };
-
- defer file.close();
-
- const stat = file.stat() catch |err| {
- JSError(getAllocator(ctx), "Getting file size {s} for \"{s}\"", .{ @errorName(err), path }, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- };
-
- if (stat.kind != .File) {
- JSError(getAllocator(ctx), "Can't read a {s} as a string (\"{s}\")", .{ @tagName(stat.kind), path }, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- }
-
- var contents_buf = VirtualMachine.vm.allocator.alloc(u8, stat.size + 2) catch unreachable; // OOM
- errdefer VirtualMachine.vm.allocator.free(contents_buf);
- const contents_len = file.readAll(contents_buf) catch |err| {
- JSError(getAllocator(ctx), "{s} reading file (\"{s}\")", .{ @errorName(err), path }, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- };
-
- contents_buf[contents_len] = 0;
-
- var marked_array_buffer = VirtualMachine.vm.allocator.create(MarkedArrayBuffer) catch unreachable;
- marked_array_buffer.* = MarkedArrayBuffer.fromBytes(
- contents_buf[0..contents_len],
- VirtualMachine.vm.allocator,
- .Uint8Array,
- );
-
- return marked_array_buffer.toJSObjectRef(ctx, exception);
- }
-
- pub fn getRouteFiles(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- _: []const js.JSValueRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- if (VirtualMachine.vm.bundler.router == null) return js.JSValueMakeNull(ctx);
-
- const router = &VirtualMachine.vm.bundler.router.?;
- const list = router.getPublicPaths() catch unreachable;
-
- for (routes_list_strings[0..@minimum(list.len, routes_list_strings.len)]) |_, i| {
- routes_list_strings[i] = ZigString.init(list[i]);
- }
-
- const ref = JSValue.createStringArray(ctx.ptr(), &routes_list_strings, list.len, true).asRef();
- return ref;
- }
-
- pub fn getRouteNames(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- _: []const js.JSValueRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- if (VirtualMachine.vm.bundler.router == null) return js.JSValueMakeNull(ctx);
-
- const router = &VirtualMachine.vm.bundler.router.?;
- const list = router.getNames() catch unreachable;
-
- for (routes_list_strings[0..@minimum(list.len, routes_list_strings.len)]) |_, i| {
- routes_list_strings[i] = ZigString.init(list[i]);
- }
-
- const ref = JSValue.createStringArray(ctx.ptr(), &routes_list_strings, list.len, true).asRef();
- return ref;
- }
-
- pub fn readFileAsBytes(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- arguments: []const js.JSValueRef,
- exception: js.ExceptionRef,
- ) js.JSValueRef {
- var buf: [bun.MAX_PATH_BYTES]u8 = undefined;
- const path = getFilePath(ctx, arguments, &buf, exception) orelse return null;
- buf[path.len] = 0;
-
- const buf_z: [:0]const u8 = buf[0..path.len :0];
- const result = readFileAsBytesCallback(ctx, buf_z, exception);
- return result;
- }
-
- pub fn readFileAsString(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- arguments: []const js.JSValueRef,
- exception: js.ExceptionRef,
- ) js.JSValueRef {
- var buf: [bun.MAX_PATH_BYTES]u8 = undefined;
- const path = getFilePath(ctx, arguments, &buf, exception) orelse return null;
- buf[path.len] = 0;
-
- const buf_z: [:0]const u8 = buf[0..path.len :0];
- const result = readFileAsStringCallback(ctx, buf_z, exception);
- return result;
- }
-
- pub fn getPublicPath(to: string, origin: URL, comptime Writer: type, writer: Writer) void {
- const relative_path = VirtualMachine.vm.bundler.fs.relativeTo(to);
- if (origin.isAbsolute()) {
- if (strings.hasPrefix(relative_path, "..") or strings.hasPrefix(relative_path, "./")) {
- writer.writeAll(origin.origin) catch return;
- writer.writeAll("/abs:") catch return;
- if (std.fs.path.isAbsolute(to)) {
- writer.writeAll(to) catch return;
- } else {
- writer.writeAll(VirtualMachine.vm.bundler.fs.abs(&[_]string{to})) catch return;
- }
- } else {
- origin.joinWrite(
- Writer,
- writer,
- VirtualMachine.vm.bundler.options.routes.asset_prefix_path,
- "",
- relative_path,
- "",
- ) catch return;
- }
- } else {
- writer.writeAll(std.mem.trimLeft(u8, relative_path, "/")) catch unreachable;
- }
- }
-
- pub fn sleepSync(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- arguments: []const js.JSValueRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- if (js.JSValueIsNumber(ctx, arguments[0])) {
- const seconds = JSValue.fromRef(arguments[0]).asNumber();
- if (seconds > 0 and std.math.isFinite(seconds)) std.time.sleep(@floatToInt(u64, seconds * 1000) * std.time.ns_per_ms);
- }
-
- return js.JSValueMakeUndefined(ctx);
- }
-
- pub fn createNodeFS(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- _: []const js.JSValueRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- return Node.NodeFSBindings.make(
- ctx,
- VirtualMachine.vm.node_fs orelse brk: {
- VirtualMachine.vm.node_fs = bun.default_allocator.create(Node.NodeFS) catch unreachable;
- VirtualMachine.vm.node_fs.?.* = Node.NodeFS{ .async_io = undefined };
- break :brk VirtualMachine.vm.node_fs.?;
- },
- );
- }
-
- pub fn generateHeapSnapshot(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- _: []const js.JSValueRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- return ctx.ptr().generateHeapSnapshot().asObjectRef();
- }
-
- pub fn runGC(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- arguments: []const js.JSValueRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- // it should only force cleanup on thread exit
-
- Global.mimalloc_cleanup(false);
-
- return ctx.ptr().vm().runGC(arguments.len > 0 and JSValue.fromRef(arguments[0]).toBoolean()).asRef();
- }
-
- pub fn shrink(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- _: []const js.JSValueRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- ctx.ptr().vm().shrinkFootprint();
- return JSValue.jsUndefined().asRef();
- }
-
- pub fn readAllStdinSync(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- _: []const js.JSValueRef,
- exception: js.ExceptionRef,
- ) js.JSValueRef {
- var stack = std.heap.stackFallback(2048, getAllocator(ctx));
- var allocator = stack.get();
-
- var stdin = std.io.getStdIn();
- var result = stdin.readToEndAlloc(allocator, std.math.maxInt(u32)) catch |err| {
- JSError(undefined, "{s} reading stdin", .{@errorName(err)}, ctx, exception);
- return null;
- };
- var out = ZigString.init(result);
- out.detectEncoding();
- return out.toValueGC(ctx.ptr()).asObjectRef();
- }
-
- var public_path_temp_str: [bun.MAX_PATH_BYTES]u8 = undefined;
-
- pub fn getPublicPathJS(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- arguments: []const js.JSValueRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- var zig_str: ZigString = ZigString.Empty;
- JSValue.toZigString(JSValue.fromRef(arguments[0]), &zig_str, ctx.ptr());
-
- const to = zig_str.slice();
-
- var stream = std.io.fixedBufferStream(&public_path_temp_str);
- var writer = stream.writer();
- getPublicPath(to, VirtualMachine.vm.origin, @TypeOf(&writer), &writer);
- return ZigString.init(stream.buffer[0..stream.pos]).toValueGC(ctx.ptr()).asObjectRef();
- }
-
- // pub fn resolvePath(
- // _: void,
- // ctx: js.JSContextRef,
- // _: js.JSObjectRef,
- // _: js.JSObjectRef,
- // arguments: []const js.JSValueRef,
- // _: js.ExceptionRef,
- // ) js.JSValueRef {
- // if (arguments.len == 0) return ZigString.Empty.toValue(ctx.ptr()).asObjectRef();
- // var zig_str: ZigString = ZigString.Empty;
- // JSValue.toZigString(JSValue.fromRef(arguments[0]), &zig_str, ctx.ptr());
- // var buf: [bun.MAX_PATH_BYTES]u8 = undefined;
- // var stack = std.heap.stackFallback(32 * @sizeOf(string), VirtualMachine.vm.allocator);
- // var allocator = stack.get();
- // var parts = allocator.alloc(string, arguments.len) catch {};
- // defer allocator.free(parts);
-
- // const to = zig_str.slice();
- // var parts = .{to};
- // const value = ZigString.init(VirtualMachine.vm.bundler.fs.absBuf(&parts, &buf)).toValueGC(ctx.ptr());
- // return value.asObjectRef();
- // }
-
- pub const Class = NewClass(
- void,
- .{
- .name = "Bun",
- .read_only = true,
- .ts = .{
- .module = .{
- .path = "bun.js/router",
- .tsdoc = "Filesystem Router supporting dynamic routes, exact routes, catch-all routes, and optional catch-all routes. Implemented in native code and only available with Bun.js.",
- },
- },
- },
- .{
- .match = .{
- .rfn = Router.match,
- .ts = Router.match_type_definition,
- },
-
- .sleepSync = .{
- .rfn = sleepSync,
- },
- .fetch = .{
- .rfn = Fetch.call,
- .ts = d.ts{},
- },
- .getImportedStyles = .{
- .rfn = Bun.getImportedStyles,
- .ts = d.ts{
- .name = "getImportedStyles",
- .@"return" = "string[]",
- },
- },
- .inspect = .{
- .rfn = Bun.inspect,
- .ts = d.ts{
- .name = "inspect",
- .@"return" = "string",
- },
- },
- .getRouteFiles = .{
- .rfn = Bun.getRouteFiles,
- .ts = d.ts{
- .name = "getRouteFiles",
- .@"return" = "string[]",
- },
- },
- ._Path = .{
- .rfn = Bun.newPath,
- .ts = d.ts{},
- },
- .getRouteNames = .{
- .rfn = Bun.getRouteNames,
- .ts = d.ts{
- .name = "getRouteNames",
- .@"return" = "string[]",
- },
- },
- .readFile = .{
- .rfn = Bun.readFileAsString,
- .ts = d.ts{
- .name = "readFile",
- .@"return" = "string",
- },
- },
- .readFileBytes = .{
- .rfn = Bun.readFileAsBytes,
- .ts = d.ts{
- .name = "readFile",
- .@"return" = "Uint8Array",
- },
- },
- .getPublicPath = .{
- .rfn = Bun.getPublicPathJS,
- .ts = d.ts{
- .name = "getPublicPath",
- .@"return" = "string",
- },
- },
- .registerMacro = .{
- .rfn = Bun.registerMacro,
- .ts = d.ts{
- .name = "registerMacro",
- .@"return" = "undefined",
- },
- },
- .fs = .{
- .rfn = Bun.createNodeFS,
- .ts = d.ts{},
- },
- .jest = .{
- .rfn = @import("./test/jest.zig").Jest.call,
- .ts = d.ts{},
- },
- .gc = .{
- .rfn = Bun.runGC,
- .ts = d.ts{},
- },
- .generateHeapSnapshot = .{
- .rfn = Bun.generateHeapSnapshot,
- .ts = d.ts{},
- },
- .shrink = .{
- .rfn = Bun.shrink,
- .ts = d.ts{},
- },
- .readAllStdinSync = .{
- .rfn = Bun.readAllStdinSync,
- .ts = d.ts{},
- },
- },
- .{
- .main = .{
- .get = getMain,
- .ts = d.ts{ .name = "main", .@"return" = "string" },
- },
- .cwd = .{
- .get = getCWD,
- .ts = d.ts{ .name = "cwd", .@"return" = "string" },
- },
- .origin = .{
- .get = getOrigin,
- .ts = d.ts{ .name = "origin", .@"return" = "string" },
- },
- .routesDir = .{
- .get = getRoutesDir,
- .ts = d.ts{ .name = "routesDir", .@"return" = "string" },
- },
- .assetPrefix = .{
- .get = getAssetPrefix,
- .ts = d.ts{ .name = "assetPrefix", .@"return" = "string" },
- },
- .argv = .{
- .get = getArgv,
- .ts = d.ts{ .name = "argv", .@"return" = "string[]" },
- },
- .env = .{
- .get = EnvironmentVariables.getter,
- },
- .enableANSIColors = .{
- .get = enableANSIColors,
- },
- .Transpiler = .{
- .get = getTranspilerConstructor,
- .ts = d.ts{ .name = "Transpiler", .@"return" = "Transpiler.prototype" },
- },
- .TOML = .{
- .get = getTOMLObject,
- .ts = d.ts{ .name = "TOML", .@"return" = "TOML.prototype" },
- },
- .unsafe = .{
- .get = getUnsafe,
- },
- },
- );
-
- pub fn getTranspilerConstructor(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSValueRef,
- _: js.JSStringRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- return js.JSObjectMake(ctx, Transpiler.TranspilerConstructor.get().?[0], null);
- }
-
- pub fn getTOMLObject(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSValueRef,
- _: js.JSStringRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- return js.JSObjectMake(ctx, TOML.Class.get().?[0], null);
- }
-
- pub fn getUnsafe(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSValueRef,
- _: js.JSStringRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- return js.JSObjectMake(ctx, Unsafe.Class.get().?[0], null);
- }
-
- pub const Unsafe = struct {
- pub const Class = NewClass(
- void,
- .{ .name = "Unsafe", .read_only = true },
- .{
- .segfault = .{
- .rfn = __debug__doSegfault,
- },
- .arrayBufferToString = .{
- .rfn = arrayBufferToString,
- },
- },
- .{},
- );
-
- // For testing the segfault handler
- pub fn __debug__doSegfault(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- _: []const js.JSValueRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- _ = ctx;
- const Reporter = @import("../../report.zig");
- Reporter.globalError(error.SegfaultTest);
- }
-
- pub fn arrayBufferToString(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- args: []const js.JSValueRef,
- exception: js.ExceptionRef,
- ) js.JSValueRef {
- const array_buffer = JSC.ArrayBuffer.fromTypedArray(ctx, JSC.JSValue.fromRef(args[0]), exception);
- switch (array_buffer.typed_array_type) {
- .Uint16Array, .Int16Array => {
- var zig_str = ZigString.init("");
- zig_str.ptr = @ptrCast([*]const u8, @alignCast(@alignOf([*]align(1) const u16), array_buffer.ptr));
- zig_str.len = array_buffer.len;
- zig_str.markUTF16();
- return ZigString.toValue(&zig_str, ctx.ptr()).asObjectRef();
- },
- else => {
- return ZigString.init(array_buffer.slice()).toValue(ctx.ptr()).asObjectRef();
- },
- }
- }
- };
-
- // pub const Lockfile = struct {
- // const BunLockfile = @import("../../install/install.zig").Lockfile;
- // pub const Class = NewClass(
- // void,
- // .{
- // .name = "Lockfile",
- // .read_only = true,
- // },
- // .{
- // . = .{
- // .rfn = BunLockfile.load,
- // },
- // },
- // .{},
- // );
-
- // pub const StaticClass = NewClass(
- // void,
- // .{
- // .name = "Lockfile",
- // .read_only = true,
- // },
- // .{
- // .load = .{
- // .rfn = BunLockfile.load,
- // },
- // },
- // .{},
- // );
-
- // pub fn load(
- // // this
- // _: void,
- // ctx: js.JSContextRef,
- // // function
- // _: js.JSObjectRef,
- // // thisObject
- // _: js.JSObjectRef,
- // arguments: []const js.JSValueRef,
- // exception: js.ExceptionRef,
- // ) js.JSValueRef {
- // if (arguments.len == 0) {
- // JSError(undefined, "Expected file path string or buffer", .{}, ctx, exception);
- // return null;
- // }
-
- // var lockfile: *BunLockfile = getAllocator(ctx).create(BunLockfile) catch return JSValue.jsUndefined().asRef();
-
- // var log = logger.Log.init(default_allocator);
- // var args_slice = @ptrCast([*]const JSValue, arguments.ptr)[0..arguments.len];
-
- // var arguments_slice = Node.ArgumentsSlice.init(args_slice);
- // var path_or_buffer = Node.PathLike.fromJS(ctx, &arguments_slice, exception) orelse {
- // getAllocator(ctx).destroy(lockfile);
- // JSError(undefined, "Expected file path string or buffer", .{}, ctx, exception);
- // return null;
- // };
-
- // const load_from_disk_result = switch (path_or_buffer) {
- // Node.PathLike.Tag.string => lockfile.loadFromDisk(getAllocator(ctx), &log, path_or_buffer.string),
- // Node.PathLike.Tag.buffer => lockfile.loadFromBytes(getAllocator(ctx), path_or_buffer.buffer.slice(), &log),
- // else => {
- // getAllocator(ctx).destroy(lockfile);
- // JSError(undefined, "Expected file path string or buffer", .{}, ctx, exception);
- // return null;
- // }
- // };
-
- // switch (load_from_disk_result) {
- // .err => |cause| {
- // defer getAllocator(ctx).destroy(lockfile);
- // switch (cause.step) {
- // .open_file => {
- // JSError(undefined, "error opening lockfile: {s}", .{
- // @errorName(cause.value),
- // }, ctx, exception);
- // return null;
- // },
- // .parse_file => {
- // JSError(undefined, "error parsing lockfile: {s}", .{
- // @errorName(cause.value),
- // }, ctx, exception);
- // return null;
- // },
- // .read_file => {
- // JSError(undefined, "error reading lockfile: {s}", .{
- // @errorName(cause.value),
- // }, ctx, exception);
- // return null;
- // },
- // }
- // },
- // .ok => {
-
- // },
- // }
- // }
- // };
-
- pub const TOML = struct {
- const TOMLParser = @import("../../toml/toml_parser.zig").TOML;
- pub const Class = NewClass(
- void,
- .{
- .name = "TOML",
- .read_only = true,
- },
- .{
- .parse = .{
- .rfn = TOML.parse,
- },
- },
- .{},
- );
-
- pub fn parse(
- // this
- _: void,
- ctx: js.JSContextRef,
- // function
- _: js.JSObjectRef,
- // thisObject
- _: js.JSObjectRef,
- arguments: []const js.JSValueRef,
- exception: js.ExceptionRef,
- ) js.JSValueRef {
- var arena = std.heap.ArenaAllocator.init(getAllocator(ctx));
- var allocator = arena.allocator();
- defer arena.deinit();
- var log = logger.Log.init(default_allocator);
- var input_str = ZigString.init("");
- JSValue.fromRef(arguments[0]).toZigString(&input_str, ctx.ptr());
- var needs_deinit = false;
- var input = input_str.slice();
- if (input_str.is16Bit()) {
- input = std.fmt.allocPrint(allocator, "{}", .{input_str}) catch unreachable;
- needs_deinit = true;
- }
- var source = logger.Source.initPathString("input.toml", input);
- var parse_result = TOMLParser.parse(&source, &log, allocator) catch {
- exception.* = log.toJS(ctx.ptr(), default_allocator, "Failed to parse toml").asObjectRef();
- return null;
- };
-
- // for now...
- var buffer_writer = try js_printer.BufferWriter.init(allocator);
- var writer = js_printer.BufferPrinter.init(buffer_writer);
- _ = js_printer.printJSON(*js_printer.BufferPrinter, &writer, parse_result, &source) catch {
- exception.* = log.toJS(ctx.ptr(), default_allocator, "Failed to print toml").asObjectRef();
- return null;
- };
-
- var slice = writer.ctx.buffer.toOwnedSliceLeaky();
- var out = ZigString.init(slice);
-
- const out_value = js.JSValueMakeFromJSONString(ctx, out.toJSStringRef());
- return out_value;
- }
- };
-
- pub const Timer = struct {
- last_id: i32 = 0,
- warned: bool = false,
- active: u32 = 0,
- timeouts: TimeoutMap = TimeoutMap{},
-
- const TimeoutMap = std.AutoArrayHashMapUnmanaged(i32, *Timeout);
-
- pub fn getNextID() callconv(.C) i32 {
- VirtualMachine.vm.timer.last_id += 1;
- return VirtualMachine.vm.timer.last_id;
- }
-
- pub const Timeout = struct {
- id: i32 = 0,
- callback: JSValue,
- interval: i32 = 0,
- completion: NetworkThread.Completion = undefined,
- repeat: bool = false,
- io_task: ?*TimeoutTask = null,
- cancelled: bool = false,
-
- pub const TimeoutTask = IOTask(Timeout);
-
- pub fn run(this: *Timeout, _task: *TimeoutTask) void {
- this.io_task = _task;
- NetworkThread.global.pool.io.?.timeout(
- *Timeout,
- this,
- onCallback,
- &this.completion,
- std.time.ns_per_ms * @intCast(
- u63,
- @maximum(
- this.interval,
- 1,
- ),
- ),
- );
- }
-
- pub fn onCallback(this: *Timeout, _: *NetworkThread.Completion, _: NetworkThread.AsyncIO.TimeoutError!void) void {
- this.io_task.?.onFinish();
- }
-
- pub fn then(this: *Timeout, global: *JSGlobalObject) void {
- if (!this.cancelled) {
- if (this.repeat) {
- this.io_task.?.deinit();
- var task = Timeout.TimeoutTask.createOnJSThread(VirtualMachine.vm.allocator, global, this) catch unreachable;
- this.io_task = task;
- task.schedule();
- }
-
- _ = JSC.C.JSObjectCallAsFunction(global.ref(), this.callback.asObjectRef(), null, 0, null, null);
-
- if (this.repeat)
- return;
- }
-
- this.clear(global);
- }
-
- pub fn clear(this: *Timeout, global: *JSGlobalObject) void {
- this.cancelled = true;
- JSC.C.JSValueUnprotect(global.ref(), this.callback.asObjectRef());
- _ = VirtualMachine.vm.timer.timeouts.swapRemove(this.id);
- if (this.io_task) |task| {
- task.deinit();
- }
- VirtualMachine.vm.allocator.destroy(this);
- VirtualMachine.vm.timer.active -|= 1;
- VirtualMachine.vm.active_tasks -|= 1;
- }
- };
-
- fn set(
- id: i32,
- globalThis: *JSGlobalObject,
- callback: JSValue,
- countdown: JSValue,
- repeat: bool,
- ) !void {
- if (comptime is_bindgen) unreachable;
- var timeout = try VirtualMachine.vm.allocator.create(Timeout);
- js.JSValueProtect(globalThis.ref(), callback.asObjectRef());
- timeout.* = Timeout{ .id = id, .callback = callback, .interval = countdown.toInt32(), .repeat = repeat };
- var task = try Timeout.TimeoutTask.createOnJSThread(VirtualMachine.vm.allocator, globalThis, timeout);
- VirtualMachine.vm.timer.timeouts.put(VirtualMachine.vm.allocator, id, timeout) catch unreachable;
- VirtualMachine.vm.timer.active +|= 1;
- VirtualMachine.vm.active_tasks +|= 1;
- task.schedule();
- }
-
- pub fn setTimeout(
- globalThis: *JSGlobalObject,
- callback: JSValue,
- countdown: JSValue,
- ) callconv(.C) JSValue {
- if (comptime is_bindgen) unreachable;
- const id = VirtualMachine.vm.timer.last_id;
- VirtualMachine.vm.timer.last_id +%= 1;
-
- Timer.set(id, globalThis, callback, countdown, false) catch
- return JSValue.jsUndefined();
-
- return JSValue.jsNumberWithType(i32, id);
- }
- pub fn setInterval(
- globalThis: *JSGlobalObject,
- callback: JSValue,
- countdown: JSValue,
- ) callconv(.C) JSValue {
- if (comptime is_bindgen) unreachable;
- const id = VirtualMachine.vm.timer.last_id;
- VirtualMachine.vm.timer.last_id +%= 1;
-
- Timer.set(id, globalThis, callback, countdown, true) catch
- return JSValue.jsUndefined();
-
- return JSValue.jsNumberWithType(i32, id);
- }
-
- pub fn clearTimer(id: JSValue, _: *JSGlobalObject) void {
- if (comptime is_bindgen) unreachable;
- var timer: *Timeout = VirtualMachine.vm.timer.timeouts.get(id.toInt32()) orelse return;
- timer.cancelled = true;
- }
-
- pub fn clearTimeout(
- globalThis: *JSGlobalObject,
- id: JSValue,
- ) callconv(.C) JSValue {
- if (comptime is_bindgen) unreachable;
- Timer.clearTimer(id, globalThis);
- return JSValue.jsUndefined();
- }
- pub fn clearInterval(
- globalThis: *JSGlobalObject,
- id: JSValue,
- ) callconv(.C) JSValue {
- if (comptime is_bindgen) unreachable;
- Timer.clearTimer(id, globalThis);
- return JSValue.jsUndefined();
- }
-
- const Shimmer = @import("./bindings/shimmer.zig").Shimmer;
-
- pub const shim = Shimmer("Bun", "Timer", @This());
- pub const name = "Bun__Timer";
- pub const include = "";
- pub const namespace = shim.namespace;
-
- pub const Export = shim.exportFunctions(.{
- .@"setTimeout" = setTimeout,
- .@"setInterval" = setInterval,
- .@"clearTimeout" = clearTimeout,
- .@"clearInterval" = clearInterval,
- .@"getNextID" = getNextID,
- });
-
- comptime {
- @export(setTimeout, .{ .name = Export[0].symbol_name });
- @export(setInterval, .{ .name = Export[1].symbol_name });
- @export(clearTimeout, .{ .name = Export[2].symbol_name });
- @export(clearInterval, .{ .name = Export[3].symbol_name });
- @export(getNextID, .{ .name = Export[4].symbol_name });
- }
- };
-
- /// EnvironmentVariables is runtime defined.
- /// Also, you can't iterate over process.env normally since it only exists at build-time otherwise
- // This is aliased to Bun.env
- pub const EnvironmentVariables = struct {
- pub const Class = NewClass(
- void,
- .{
- .name = "DotEnv",
- .read_only = true,
- },
- .{
- .getProperty = .{
- .rfn = getProperty,
- },
- .setProperty = .{
- .rfn = setProperty,
- },
- .deleteProperty = .{
- .rfn = deleteProperty,
- },
- .convertToType = .{ .rfn = convertToType },
- .hasProperty = .{
- .rfn = hasProperty,
- },
- .getPropertyNames = .{
- .rfn = getPropertyNames,
- },
- .toJSON = .{
- .rfn = toJSON,
- .name = "toJSON",
- },
- },
- .{},
- );
-
- pub fn getter(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSValueRef,
- _: js.JSStringRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- return js.JSObjectMake(ctx, EnvironmentVariables.Class.get().*, null);
- }
-
- pub const BooleanString = struct {
- pub const @"true": string = "true";
- pub const @"false": string = "false";
- };
-
- pub fn getProperty(
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- propertyName: js.JSStringRef,
- _: js.ExceptionRef,
- ) callconv(.C) js.JSValueRef {
- const len = js.JSStringGetLength(propertyName);
- var ptr = js.JSStringGetCharacters8Ptr(propertyName);
- var name = ptr[0..len];
- if (VirtualMachine.vm.bundler.env.map.get(name)) |value| {
- return ZigString.toRef(value, ctx.ptr());
- }
-
- if (Output.enable_ansi_colors) {
- // https://github.com/chalk/supports-color/blob/main/index.js
- if (strings.eqlComptime(name, "FORCE_COLOR")) {
- return ZigString.toRef(BooleanString.@"true", ctx.ptr());
- }
- }
-
- return js.JSValueMakeUndefined(ctx);
- }
-
- pub fn toJSON(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- _: []const js.JSValueRef,
- _: js.ExceptionRef,
- ) js.JSValueRef {
- var map = VirtualMachine.vm.bundler.env.map.map;
- var keys = map.keys();
- var values = map.values();
- const StackFallback = std.heap.StackFallbackAllocator(32 * 2 * @sizeOf(ZigString));
- var stack = StackFallback{
- .buffer = undefined,
- .fallback_allocator = bun.default_allocator,
- .fixed_buffer_allocator = undefined,
- };
- var allocator = stack.get();
- var key_strings_ = allocator.alloc(ZigString, keys.len * 2) catch unreachable;
- var key_strings = key_strings_[0..keys.len];
- var value_strings = key_strings_[keys.len..];
-
- for (keys) |key, i| {
- key_strings[i] = ZigString.init(key);
- key_strings[i].detectEncoding();
- value_strings[i] = ZigString.init(values[i]);
- value_strings[i].detectEncoding();
- }
-
- var result = JSValue.fromEntries(ctx.ptr(), key_strings.ptr, value_strings.ptr, keys.len, false).asObjectRef();
- allocator.free(key_strings_);
- return result;
- // }
- // ZigConsoleClient.Formatter.format(this: *Formatter, result: Tag.Result, comptime Writer: type, writer: Writer, value: JSValue, globalThis: *JSGlobalObject, comptime enable_ansi_colors: bool)
- }
-
- pub fn deleteProperty(
- _: js.JSContextRef,
- _: js.JSObjectRef,
- propertyName: js.JSStringRef,
- _: js.ExceptionRef,
- ) callconv(.C) bool {
- const len = js.JSStringGetLength(propertyName);
- var ptr = js.JSStringGetCharacters8Ptr(propertyName);
- var name = ptr[0..len];
- _ = VirtualMachine.vm.bundler.env.map.map.swapRemove(name);
- return true;
- }
-
- pub fn setProperty(
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- propertyName: js.JSStringRef,
- value: js.JSValueRef,
- exception: js.ExceptionRef,
- ) callconv(.C) bool {
- const len = js.JSStringGetLength(propertyName);
- var ptr = js.JSStringGetCharacters8Ptr(propertyName);
- var name = ptr[0..len];
- var val = ZigString.init("");
- JSValue.fromRef(value).toZigString(&val, ctx.ptr());
- if (exception.* != null) return false;
- var result = std.fmt.allocPrint(VirtualMachine.vm.allocator, "{}", .{val}) catch unreachable;
- VirtualMachine.vm.bundler.env.map.put(name, result) catch unreachable;
-
- return true;
- }
-
- pub fn hasProperty(
- _: js.JSContextRef,
- _: js.JSObjectRef,
- propertyName: js.JSStringRef,
- ) callconv(.C) bool {
- const len = js.JSStringGetLength(propertyName);
- const ptr = js.JSStringGetCharacters8Ptr(propertyName);
- const name = ptr[0..len];
- return VirtualMachine.vm.bundler.env.map.get(name) != null or (Output.enable_ansi_colors and strings.eqlComptime(name, "FORCE_COLOR"));
- }
-
- pub fn convertToType(ctx: js.JSContextRef, obj: js.JSObjectRef, kind: js.JSType, exception: js.ExceptionRef) callconv(.C) js.JSValueRef {
- _ = ctx;
- _ = obj;
- _ = kind;
- _ = exception;
- return obj;
- }
-
- pub fn getPropertyNames(
- _: js.JSContextRef,
- _: js.JSObjectRef,
- props: js.JSPropertyNameAccumulatorRef,
- ) callconv(.C) void {
- var iter = VirtualMachine.vm.bundler.env.map.iter();
-
- while (iter.next()) |item| {
- const str = item.key_ptr.*;
- js.JSPropertyNameAccumulatorAddName(props, js.JSStringCreateStatic(str.ptr, str.len));
- }
- }
- };
-};
-
pub const OpaqueCallback = fn (current: ?*anyopaque) callconv(.C) void;
pub fn OpaqueWrap(comptime Context: type, comptime Function: fn (this: *Context) void) OpaqueCallback {
return struct {
@@ -2166,7 +763,7 @@ pub const VirtualMachine = struct {
};
}
- pub fn refCountedString(this: *VirtualMachine, input_: []const u8, hash_: ?u32, comptime dupe: bool) *JSC.RefString {
+ pub fn refCountedStringWithWasNew(this: *VirtualMachine, new: *bool, input_: []const u8, hash_: ?u32, comptime dupe: bool) *JSC.RefString {
const hash = hash_ orelse JSC.RefString.computeHash(input_);
var entry = this.ref_strings.getOrPut(hash) catch unreachable;
@@ -2187,10 +784,15 @@ pub const VirtualMachine = struct {
};
entry.value_ptr.* = ref;
}
-
+ new.* = !entry.found_existing;
return entry.value_ptr.*;
}
+ pub fn refCountedString(this: *VirtualMachine, input_: []const u8, hash_: ?u32, comptime dupe: bool) *JSC.RefString {
+ var _was_new = false;
+ return this.refCountedStringWithWasNew(&_was_new, input_, hash_, comptime dupe);
+ }
+
pub fn preflush(this: *VirtualMachine) void {
// We flush on the next tick so that if there were any errors you can still see them
this.blobs.?.temporary.reset() catch {};
@@ -2534,7 +1136,13 @@ pub const VirtualMachine = struct {
path: string,
};
- fn _resolve(ret: *ResolveFunctionResult, _: *JSGlobalObject, specifier: string, source: string) !void {
+ fn _resolve(
+ ret: *ResolveFunctionResult,
+ _: *JSGlobalObject,
+ specifier: string,
+ source: string,
+ comptime is_a_file_path: bool,
+ ) !void {
std.debug.assert(VirtualMachine.vm_loaded);
// macOS threadlocal vars are very slow
// we won't change threads in this function
@@ -2573,7 +1181,13 @@ pub const VirtualMachine = struct {
const is_special_source = strings.eqlComptime(source, main_file_name) or js_ast.Macro.isMacroPath(source);
const result = try jsc_vm.bundler.resolver.resolve(
- if (!is_special_source) Fs.PathName.init(source).dirWithTrailingSlash() else jsc_vm.bundler.fs.top_level_dir,
+ if (!is_special_source)
+ if (is_a_file_path)
+ Fs.PathName.init(source).dirWithTrailingSlash()
+ else
+ source
+ else
+ jsc_vm.bundler.fs.top_level_dir,
specifier,
.stmt,
);
@@ -2637,10 +1251,19 @@ pub const VirtualMachine = struct {
vm.enqueueTask(Task.init(microtask));
}
+
+ pub fn resolveForAPI(res: *ErrorableZigString, global: *JSGlobalObject, specifier: ZigString, source: ZigString) void {
+ resolveMaybeNeedsTrailingSlash(res, global, specifier, source, false);
+ }
+
pub fn resolve(res: *ErrorableZigString, global: *JSGlobalObject, specifier: ZigString, source: ZigString) void {
+ resolveMaybeNeedsTrailingSlash(res, global, specifier, source, true);
+ }
+
+ pub fn resolveMaybeNeedsTrailingSlash(res: *ErrorableZigString, global: *JSGlobalObject, specifier: ZigString, source: ZigString, comptime is_a_file_path: bool) void {
var result = ResolveFunctionResult{ .path = "", .result = null };
- _resolve(&result, global, specifier.slice(), source.slice()) catch |err| {
+ _resolve(&result, global, specifier.slice(), source.slice(), is_a_file_path) catch |err| {
// This should almost always just apply to dynamic imports
const printed = ResolveError.fmt(
diff --git a/src/javascript/jsc/webcore/response.zig b/src/javascript/jsc/webcore/response.zig
index d45ed107e..52dce05ef 100644
--- a/src/javascript/jsc/webcore/response.zig
+++ b/src/javascript/jsc/webcore/response.zig
@@ -1670,9 +1670,12 @@ pub const Blob = struct {
return true;
const prev_content_type = this.content_type;
- defer if (this.content_type_allocated) bun.default_allocator.free(prev_content_type);
- var content_type_buf = getAllocator(ctx).alloc(u8, slice.len) catch unreachable;
- this.content_type = strings.copyLowercase(slice, content_type_buf);
+ {
+ defer if (this.content_type_allocated) bun.default_allocator.free(prev_content_type);
+ var content_type_buf = getAllocator(ctx).alloc(u8, slice.len) catch unreachable;
+ this.content_type = strings.copyLowercase(slice, content_type_buf);
+ }
+
this.content_type_allocated = true;
return true;
}
diff --git a/src/javascript/jsc/webcore/url.zig b/src/javascript/jsc/webcore/url.zig
index e3251e65f..0d767fcd3 100644
--- a/src/javascript/jsc/webcore/url.zig
+++ b/src/javascript/jsc/webcore/url.zig
@@ -6,7 +6,7 @@ const MimeType = @import("../../../http.zig").MimeType;
const ZigURL = @import("../../../url.zig").URL;
const HTTPClient = @import("http");
const NetworkThread = HTTPClient.NetworkThread;
-
+const bun = @import("../../global.zig");
const JSC = @import("../../../jsc.zig");
const js = JSC.C;
@@ -131,8 +131,9 @@ pub const DOMURL = struct {
var input = value.toSlice(globalThis, bun.default_allocator);
defer input.deinit();
const buf = input.slice();
- const host_len = copy.parseHost(buf) orelse return false;
+ _ = copy.parseHost(buf) orelse return false;
var temp_clone = std.fmt.allocPrint("{}://{s}/{s}", .{ this.url.displayProtocol(), copy.displayHost(), strings.trimLeadingChar(this.url.pathname, '/') }) catch return false;
+ this.url = URL.parse(temp_clone);
this.m_string = JSC.VirtualMachine.vm.refCountedString(temp_clone, null, false);
if (this.m_string.ptr != temp_clone.ptr) {
bun.default_allocator.free(temp_clone);
diff --git a/src/jsc.zig b/src/jsc.zig
index ff18d5818..cd1744f21 100644
--- a/src/jsc.zig
+++ b/src/jsc.zig
@@ -21,6 +21,8 @@ pub const Cloudflare = struct {
pub const Jest = @import("./javascript/jsc/test/jest.zig");
pub const API = struct {
pub const Transpiler = @import("./javascript/jsc/api/transpiler.zig");
+ pub const Bun = @import("./javascript/jsc/api/bun.zig");
+ pub const Router = @import("./javascript/jsc/api/router.zig");
};
pub const Node = struct {
pub usingnamespace @import("./javascript/jsc/node/types.zig");