aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/javascript.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/bun.js/javascript.zig')
-rw-r--r--src/bun.js/javascript.zig2738
1 files changed, 2738 insertions, 0 deletions
diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig
new file mode 100644
index 000000000..937b40cc6
--- /dev/null
+++ b/src/bun.js/javascript.zig
@@ -0,0 +1,2738 @@
+const std = @import("std");
+const is_bindgen: bool = std.meta.globalOption("bindgen", bool) orelse false;
+const StaticExport = @import("./bindings/static_export.zig");
+const c_char = StaticExport.c_char;
+const bun = @import("../global.zig");
+const string = bun.string;
+const Output = bun.Output;
+const Global = bun.Global;
+const Environment = bun.Environment;
+const strings = bun.strings;
+const MutableString = bun.MutableString;
+const stringZ = bun.stringZ;
+const default_allocator = bun.default_allocator;
+const StoredFileDescriptorType = bun.StoredFileDescriptorType;
+const Arena = @import("../mimalloc_arena.zig").Arena;
+const C = bun.C;
+const NetworkThread = @import("http").NetworkThread;
+const IO = @import("io");
+pub fn zigCast(comptime Destination: type, value: anytype) *Destination {
+ return @ptrCast(*Destination, @alignCast(@alignOf(*Destination), value));
+}
+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("./api/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("./api/transpiler.zig");
+const Bun = JSC.API.Bun;
+const EventLoop = JSC.EventLoop;
+const ThreadSafeFunction = JSC.napi.ThreadSafeFunction;
+pub const GlobalConstructors = [_]type{
+ WebCore.Blob.Constructor,
+ WebCore.TextDecoder.Constructor,
+ // WebCore.TextEncoder.Constructor,
+ Request.Constructor,
+ Response.Constructor,
+ JSC.Cloudflare.HTMLRewriter.Constructor,
+};
+
+pub const GlobalClasses = [_]type{
+ Bun.Class,
+ EventListenerMixin.addEventListener(VirtualMachine),
+ BuildError.Class,
+ ResolveError.Class,
+
+ Fetch.Class,
+ js_ast.Macro.JSNode.BunJSXCallbackFunction,
+ WebCore.Performance.Class,
+
+ WebCore.Crypto.Class,
+ WebCore.Crypto.Prototype,
+
+ // The last item in this array becomes "process.env"
+ Bun.EnvironmentVariables.Class,
+};
+const TaggedPointerUnion = @import("../tagged_pointer.zig").TaggedPointerUnion;
+const Task = JSC.Task;
+const Blob = @import("../blob.zig");
+pub const Buffer = MarkedArrayBuffer;
+const Lock = @import("../lock.zig").Lock;
+
+pub const OpaqueCallback = fn (current: ?*anyopaque) callconv(.C) void;
+pub fn OpaqueWrap(comptime Context: type, comptime Function: fn (this: *Context) void) OpaqueCallback {
+ return struct {
+ pub fn callback(ctx: ?*anyopaque) callconv(.C) void {
+ var context: *Context = @ptrCast(*Context, @alignCast(@alignOf(Context), ctx.?));
+ @call(.{}, Function, .{context});
+ }
+ }.callback;
+}
+
+const bun_file_import_path = "/node_modules.server.bun";
+
+const SourceMap = @import("../sourcemap/sourcemap.zig");
+const MappingList = SourceMap.Mapping.List;
+
+pub const SavedSourceMap = struct {
+ // For bun.js, we store the number of mappings and how many bytes the final list is at the beginning of the array
+ // The first 8 bytes are the length of the array
+ // The second 8 bytes are the number of mappings
+ pub const SavedMappings = struct {
+ data: [*]u8,
+
+ pub fn vlq(this: SavedMappings) []u8 {
+ return this.data[16..this.len()];
+ }
+
+ pub inline fn len(this: SavedMappings) usize {
+ return @bitCast(u64, this.data[0..8].*);
+ }
+
+ pub fn deinit(this: SavedMappings) void {
+ default_allocator.free(this.data[0..this.len()]);
+ }
+
+ pub fn toMapping(this: SavedMappings, allocator: Allocator, path: string) anyerror!MappingList {
+ const result = SourceMap.Mapping.parse(
+ allocator,
+ this.data[16..this.len()],
+ @bitCast(usize, this.data[8..16].*),
+ 1,
+ );
+ switch (result) {
+ .fail => |fail| {
+ if (Output.enable_ansi_colors_stderr) {
+ try fail.toData(path).writeFormat(
+ Output.errorWriter(),
+ logger.Kind.warn,
+ true,
+ false,
+ );
+ } else {
+ try fail.toData(path).writeFormat(
+ Output.errorWriter(),
+ logger.Kind.warn,
+ false,
+ false,
+ );
+ }
+
+ return fail.err;
+ },
+ .success => |success| {
+ return success;
+ },
+ }
+ }
+ };
+
+ pub const Value = TaggedPointerUnion(.{ MappingList, SavedMappings });
+ pub const HashTable = std.HashMap(u64, *anyopaque, IdentityContext(u64), 80);
+
+ map: HashTable,
+
+ pub fn onSourceMapChunk(this: *SavedSourceMap, chunk: SourceMap.Chunk, source: logger.Source) anyerror!void {
+ try this.putMappings(source, chunk.buffer);
+ }
+
+ pub const SourceMapHandler = js_printer.SourceMapHandler.For(SavedSourceMap, onSourceMapChunk);
+
+ pub fn putMappings(this: *SavedSourceMap, source: logger.Source, mappings: MutableString) !void {
+ var entry = try this.map.getOrPut(std.hash.Wyhash.hash(0, source.path.text));
+ if (entry.found_existing) {
+ var value = Value.from(entry.value_ptr.*);
+ if (value.get(MappingList)) |source_map_| {
+ var source_map: *MappingList = source_map_;
+ source_map.deinit(default_allocator);
+ } else if (value.get(SavedMappings)) |saved_mappings| {
+ var saved = SavedMappings{ .data = @ptrCast([*]u8, saved_mappings) };
+
+ saved.deinit();
+ }
+ }
+
+ entry.value_ptr.* = Value.init(bun.cast(*SavedMappings, mappings.list.items.ptr)).ptr();
+ }
+
+ pub fn get(this: *SavedSourceMap, path: string) ?MappingList {
+ var mapping = this.map.getEntry(std.hash.Wyhash.hash(0, path)) orelse return null;
+ switch (Value.from(mapping.value_ptr.*).tag()) {
+ (@field(Value.Tag, @typeName(MappingList))) => {
+ return Value.from(mapping.value_ptr.*).as(MappingList).*;
+ },
+ Value.Tag.SavedMappings => {
+ var saved = SavedMappings{ .data = @ptrCast([*]u8, Value.from(mapping.value_ptr.*).as(MappingList)) };
+ defer saved.deinit();
+ var result = default_allocator.create(MappingList) catch unreachable;
+ result.* = saved.toMapping(default_allocator, path) catch {
+ _ = this.map.remove(mapping.key_ptr.*);
+ return null;
+ };
+ mapping.value_ptr.* = Value.init(result).ptr();
+ return result.*;
+ },
+ else => return null,
+ }
+ }
+
+ pub fn resolveMapping(
+ this: *SavedSourceMap,
+ path: []const u8,
+ line: i32,
+ column: i32,
+ ) ?SourceMap.Mapping {
+ var mappings = this.get(path) orelse return null;
+ return SourceMap.Mapping.find(mappings, line, column);
+ }
+};
+const uws = @import("uws");
+
+pub export fn Bun__getDefaultGlobal() *JSGlobalObject {
+ return JSC.VirtualMachine.vm.global;
+}
+
+pub export fn Bun__getVM() *JSC.VirtualMachine {
+ return JSC.VirtualMachine.vm;
+}
+
+pub export fn Bun__drainMicrotasks() void {
+ JSC.VirtualMachine.vm.eventLoop().tick();
+}
+
+comptime {
+ if (!JSC.is_bindgen) {
+ _ = Bun__getDefaultGlobal;
+ _ = Bun__getVM;
+ _ = Bun__drainMicrotasks;
+ _ = Bun__queueMicrotask;
+ }
+}
+
+pub export fn Bun__queueMicrotask(global: *JSGlobalObject, task: *JSC.CppTask) void {
+ global.bunVM().eventLoop().enqueueTask(Task.init(task));
+}
+
+// If you read JavascriptCore/API/JSVirtualMachine.mm - https://github.com/WebKit/WebKit/blob/acff93fb303baa670c055cb24c2bad08691a01a0/Source/JavaScriptCore/API/JSVirtualMachine.mm#L101
+// We can see that it's sort of like std.mem.Allocator but for JSGlobalContextRef, to support Automatic Reference Counting
+// Its unavailable on Linux
+
+// JavaScriptCore expects 1 VM per thread
+// However, there can be many JSGlobalObject
+// We currently assume a 1:1 correspondence between the two.
+// This is technically innacurate
+pub const VirtualMachine = struct {
+ global: *JSGlobalObject,
+ allocator: std.mem.Allocator,
+ has_loaded_constructors: bool = false,
+ node_modules: ?*NodeModuleBundle = null,
+ bundler: Bundler,
+ watcher: ?*http.Watcher = null,
+ console: *ZigConsoleClient,
+ log: *logger.Log,
+ event_listeners: EventListenerMixin.Map,
+ main: string = "",
+ process: js.JSObjectRef = null,
+ blobs: ?*Blob.Group = null,
+ flush_list: std.ArrayList(string),
+ entry_point: ServerEntryPoint = undefined,
+ origin: URL = URL{},
+ node_fs: ?*Node.NodeFS = null,
+ has_loaded_node_modules: bool = false,
+ timer: Bun.Timer = Bun.Timer{},
+ uws_event_loop: ?*uws.Loop = null,
+
+ arena: *Arena = undefined,
+ has_loaded: bool = false,
+
+ transpiled_count: usize = 0,
+ resolved_count: usize = 0,
+ had_errors: bool = false,
+
+ macros: MacroMap,
+ macro_entry_points: std.AutoArrayHashMap(i32, *MacroEntryPoint),
+ macro_mode: bool = false,
+
+ has_any_macro_remappings: bool = false,
+ is_from_devserver: bool = false,
+ has_enabled_macro_mode: bool = false,
+ argv: []const []const u8 = &[_][]const u8{"bun"},
+ global_api_constructors: [GlobalConstructors.len]JSC.JSValue = undefined,
+
+ origin_timer: std.time.Timer = undefined,
+ active_tasks: usize = 0,
+
+ macro_event_loop: EventLoop = EventLoop{},
+ regular_event_loop: EventLoop = EventLoop{},
+ event_loop: *EventLoop = undefined,
+
+ ref_strings: JSC.RefString.Map = undefined,
+ file_blobs: JSC.WebCore.Blob.Store.Map,
+
+ source_mappings: SavedSourceMap = undefined,
+ response_objects_pool: ?*Response.Pool = null,
+
+ rare_data: ?*JSC.RareData = null,
+ poller: JSC.Poller = JSC.Poller{},
+ us_loop_reference_count: usize = 0,
+ disable_run_us_loop: bool = false,
+ is_us_loop_entered: bool = false,
+
+ pub fn io(this: *VirtualMachine) *IO {
+ if (this.io_ == null) {
+ this.io_ = IO.init(this) catch @panic("Failed to initialize IO");
+ }
+
+ return &this.io_.?;
+ }
+
+ pub inline fn nodeFS(this: *VirtualMachine) *Node.NodeFS {
+ return this.node_fs orelse brk: {
+ this.node_fs = bun.default_allocator.create(Node.NodeFS) catch unreachable;
+ this.node_fs.?.* = Node.NodeFS{ .async_io = undefined };
+ break :brk this.node_fs.?;
+ };
+ }
+
+ pub inline fn rareData(this: *VirtualMachine) *JSC.RareData {
+ return this.rare_data orelse brk: {
+ this.rare_data = this.allocator.create(JSC.RareData) catch unreachable;
+ this.rare_data.?.* = .{};
+ break :brk this.rare_data.?;
+ };
+ }
+
+ pub inline fn eventLoop(this: *VirtualMachine) *EventLoop {
+ return this.event_loop;
+ }
+
+ pub fn prepareLoop(this: *VirtualMachine) void {
+ var loop = this.uws_event_loop.?;
+ _ = loop.addPostHandler(*JSC.EventLoop, this.eventLoop(), JSC.EventLoop.tick);
+ }
+
+ pub fn enterUWSLoop(this: *VirtualMachine) void {
+ var loop = this.uws_event_loop.?;
+ loop.run();
+ }
+
+ pub fn onExit(this: *VirtualMachine) void {
+ var rare_data = this.rare_data orelse return;
+ var hook = rare_data.cleanup_hook orelse return;
+ hook.execute();
+ while (hook.next) |next| {
+ next.execute();
+ hook = next;
+ }
+ }
+
+ pub inline fn enqueueTask(this: *VirtualMachine, task: Task) void {
+ this.eventLoop().enqueueTask(task);
+ }
+
+ pub inline fn enqueueTaskConcurrent(this: *VirtualMachine, task: Task) void {
+ this.eventLoop().enqueueTaskConcurrent(task);
+ }
+
+ pub fn tick(this: *VirtualMachine) void {
+ this.eventLoop().tick();
+ }
+
+ pub fn waitForPromise(this: *VirtualMachine, promise: *JSC.JSInternalPromise) void {
+ this.eventLoop().waitForPromise(promise);
+ }
+
+ pub fn waitForTasks(this: *VirtualMachine) void {
+ this.eventLoop().waitForTasks();
+ }
+
+ pub const MacroMap = std.AutoArrayHashMap(i32, js.JSObjectRef);
+
+ pub threadlocal var vm_loaded = false;
+ pub threadlocal var vm: *VirtualMachine = undefined;
+
+ pub fn enableMacroMode(this: *VirtualMachine) void {
+ if (!this.has_enabled_macro_mode) {
+ this.has_enabled_macro_mode = true;
+ this.macro_event_loop.tasks = EventLoop.Queue.init(default_allocator);
+ this.macro_event_loop.tasks.ensureTotalCapacity(16) catch unreachable;
+ this.macro_event_loop.global = this.global;
+ this.macro_event_loop.virtual_machine = this;
+ this.macro_event_loop.concurrent_tasks = EventLoop.Queue.init(default_allocator);
+ }
+
+ this.bundler.options.platform = .bun_macro;
+ this.bundler.resolver.caches.fs.is_macro_mode = true;
+ this.macro_mode = true;
+ this.event_loop = &this.macro_event_loop;
+ Analytics.Features.macros = true;
+ }
+
+ pub fn disableMacroMode(this: *VirtualMachine) void {
+ this.bundler.options.platform = .bun;
+ this.bundler.resolver.caches.fs.is_macro_mode = false;
+ this.macro_mode = false;
+ this.event_loop = &this.regular_event_loop;
+ }
+
+ pub fn getAPIGlobals() []js.JSClassRef {
+ if (is_bindgen)
+ return &[_]js.JSClassRef{};
+ var classes = default_allocator.alloc(js.JSClassRef, GlobalClasses.len) catch return &[_]js.JSClassRef{};
+ inline for (GlobalClasses) |Class, i| {
+ classes[i] = Class.get().*;
+ }
+
+ return classes;
+ }
+
+ pub fn getAPIConstructors(globalObject: *JSGlobalObject) []const JSC.JSValue {
+ if (is_bindgen)
+ return &[_]JSC.JSValue{};
+ const is_first = !VirtualMachine.vm.has_loaded_constructors;
+ if (is_first) {
+ VirtualMachine.vm.global = globalObject;
+ VirtualMachine.vm.has_loaded_constructors = true;
+ }
+
+ var slice = if (is_first)
+ @as([]JSC.JSValue, &JSC.VirtualMachine.vm.global_api_constructors)
+ else
+ VirtualMachine.vm.allocator.alloc(JSC.JSValue, GlobalConstructors.len) catch unreachable;
+
+ inline for (GlobalConstructors) |Class, i| {
+ var ref = Class.constructor(globalObject.ref()).?;
+ JSC.C.JSValueProtect(globalObject.ref(), ref);
+ slice[i] = JSC.JSValue.fromRef(
+ ref,
+ );
+ }
+
+ return slice;
+ }
+
+ pub fn init(
+ allocator: std.mem.Allocator,
+ _args: Api.TransformOptions,
+ existing_bundle: ?*NodeModuleBundle,
+ _log: ?*logger.Log,
+ env_loader: ?*DotEnv.Loader,
+ ) !*VirtualMachine {
+ var log: *logger.Log = undefined;
+ if (_log) |__log| {
+ log = __log;
+ } else {
+ log = try allocator.create(logger.Log);
+ log.* = logger.Log.init(allocator);
+ }
+
+ VirtualMachine.vm = try allocator.create(VirtualMachine);
+ var console = try allocator.create(ZigConsoleClient);
+ console.* = ZigConsoleClient.init(Output.errorWriter(), Output.writer());
+ const bundler = try Bundler.init(
+ allocator,
+ log,
+ try Config.configureTransformOptionsForBunVM(allocator, _args),
+ existing_bundle,
+ env_loader,
+ );
+
+ VirtualMachine.vm.* = VirtualMachine{
+ .global = undefined,
+ .allocator = allocator,
+ .entry_point = ServerEntryPoint{},
+ .event_listeners = EventListenerMixin.Map.init(allocator),
+ .bundler = bundler,
+ .console = console,
+ .node_modules = bundler.options.node_modules_bundle,
+ .log = log,
+ .flush_list = std.ArrayList(string).init(allocator),
+ .blobs = if (_args.serve orelse false) try Blob.Group.init(allocator) else null,
+ .origin = bundler.options.origin,
+ .source_mappings = SavedSourceMap{ .map = SavedSourceMap.HashTable.init(allocator) },
+ .macros = MacroMap.init(allocator),
+ .macro_entry_points = @TypeOf(VirtualMachine.vm.macro_entry_points).init(allocator),
+ .origin_timer = std.time.Timer.start() catch @panic("Please don't mess with timers."),
+ .ref_strings = JSC.RefString.Map.init(allocator),
+ .file_blobs = JSC.WebCore.Blob.Store.Map.init(allocator),
+ };
+ VirtualMachine.vm.regular_event_loop.tasks = EventLoop.Queue.init(
+ default_allocator,
+ );
+ VirtualMachine.vm.regular_event_loop.tasks.ensureUnusedCapacity(64) catch unreachable;
+ VirtualMachine.vm.regular_event_loop.concurrent_tasks = EventLoop.Queue.init(default_allocator);
+ VirtualMachine.vm.regular_event_loop.concurrent_tasks.ensureUnusedCapacity(8) catch unreachable;
+ VirtualMachine.vm.event_loop = &VirtualMachine.vm.regular_event_loop;
+
+ vm.bundler.macro_context = null;
+
+ VirtualMachine.vm.bundler.configureLinker();
+ try VirtualMachine.vm.bundler.configureFramework(false);
+
+ vm.bundler.macro_context = js_ast.Macro.MacroContext.init(&vm.bundler);
+
+ if (_args.serve orelse false) {
+ VirtualMachine.vm.bundler.linker.onImportCSS = Bun.onImportCSS;
+ }
+
+ var global_classes: [GlobalClasses.len]js.JSClassRef = undefined;
+ inline for (GlobalClasses) |Class, i| {
+ global_classes[i] = Class.get().*;
+ }
+ VirtualMachine.vm.global = ZigGlobalObject.create(
+ &global_classes,
+ @intCast(i32, global_classes.len),
+ vm.console,
+ );
+ VirtualMachine.vm.regular_event_loop.global = VirtualMachine.vm.global;
+ VirtualMachine.vm.regular_event_loop.virtual_machine = VirtualMachine.vm;
+ VirtualMachine.vm_loaded = true;
+
+ if (source_code_printer == null) {
+ var writer = try js_printer.BufferWriter.init(allocator);
+ source_code_printer = allocator.create(js_printer.BufferPrinter) catch unreachable;
+ source_code_printer.?.* = js_printer.BufferPrinter.init(writer);
+ source_code_printer.?.ctx.append_null_byte = false;
+ }
+
+ return VirtualMachine.vm;
+ }
+
+ // dynamic import
+ // pub fn import(global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) ErrorableZigString {
+
+ // }
+
+ threadlocal var source_code_printer: ?*js_printer.BufferPrinter = null;
+
+ pub fn clearRefString(_: *anyopaque, ref_string: *JSC.RefString) void {
+ _ = VirtualMachine.vm.ref_strings.remove(ref_string.hash);
+ }
+
+ pub fn getFileBlob(this: *VirtualMachine, pathlike: JSC.Node.PathOrFileDescriptor) ?*JSC.WebCore.Blob.Store {
+ const hash = pathlike.hash();
+ return this.file_blobs.get(hash);
+ }
+
+ pub fn putFileBlob(this: *VirtualMachine, pathlike: JSC.Node.PathOrFileDescriptor, store: *JSC.WebCore.Blob.Store) !void {
+ const hash = pathlike.hash();
+ try this.file_blobs.put(hash, store);
+ }
+
+ pub fn removeFileBlob(this: *VirtualMachine, pathlike: JSC.Node.PathOrFileDescriptor) void {
+ const hash = pathlike.hash();
+ _ = this.file_blobs.remove(hash);
+ }
+
+ pub fn refCountedResolvedSource(this: *VirtualMachine, code: []const u8, specifier: []const u8, source_url: []const u8, hash_: ?u32) ResolvedSource {
+ var source = this.refCountedString(code, hash_, true);
+
+ return ResolvedSource{
+ .source_code = ZigString.init(source.slice()),
+ .specifier = ZigString.init(specifier),
+ .source_url = ZigString.init(source_url),
+ .hash = source.hash,
+ .allocator = source,
+ };
+ }
+
+ 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;
+ if (!entry.found_existing) {
+ const input = if (comptime dupe)
+ (this.allocator.dupe(u8, input_) catch unreachable)
+ else
+ input_;
+
+ var ref = this.allocator.create(JSC.RefString) catch unreachable;
+ ref.* = JSC.RefString{
+ .allocator = this.allocator,
+ .ptr = input.ptr,
+ .len = input.len,
+ .hash = hash,
+ .ctx = this,
+ .onBeforeDeinit = VirtualMachine.clearRefString,
+ };
+ 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 {};
+ }
+
+ pub fn flush(this: *VirtualMachine) void {
+ this.had_errors = false;
+ for (this.flush_list.items) |item| {
+ this.allocator.free(item);
+ }
+ this.flush_list.shrinkRetainingCapacity(0);
+ this.transpiled_count = 0;
+ this.resolved_count = 0;
+ }
+
+ const shared_library_suffix = if (Environment.isMac) "dylib" else if (Environment.isLinux) "so" else "";
+
+ inline fn _fetch(
+ _: *JSGlobalObject,
+ _specifier: string,
+ _: string,
+ log: *logger.Log,
+ comptime disable_transpilying: bool,
+ ) !ResolvedSource {
+ std.debug.assert(VirtualMachine.vm_loaded);
+ var jsc_vm = vm;
+
+ if (jsc_vm.node_modules != null and strings.eqlComptime(_specifier, bun_file_import_path)) {
+ // We kind of need an abstraction around this.
+ // Basically we should subclass JSC::SourceCode with:
+ // - hash
+ // - file descriptor for source input
+ // - file path + file descriptor for bytecode caching
+ // - separate bundles for server build vs browser build OR at least separate sections
+ const code = try jsc_vm.node_modules.?.readCodeAsStringSlow(jsc_vm.allocator);
+
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(code),
+ .specifier = ZigString.init(bun_file_import_path),
+ .source_url = ZigString.init(bun_file_import_path[1..]),
+ .hash = 0, // TODO
+ };
+ } else if (jsc_vm.node_modules == null and strings.eqlComptime(_specifier, Runtime.Runtime.Imports.Name)) {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(Runtime.Runtime.sourceContentBun()),
+ .specifier = ZigString.init(Runtime.Runtime.Imports.Name),
+ .source_url = ZigString.init(Runtime.Runtime.Imports.Name),
+ .hash = Runtime.Runtime.versionHash(),
+ };
+ } else if (HardcodedModule.Map.get(_specifier)) |hardcoded| {
+ switch (hardcoded) {
+ // This is all complicated because the imports have to be linked and we want to run the printer on it
+ // so it consistently handles bundled imports
+ // we can't take the shortcut of just directly importing the file, sadly.
+ .@"bun:main" => {
+ if (comptime disable_transpilying) {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(jsc_vm.entry_point.source.contents),
+ .specifier = ZigString.init(std.mem.span(main_file_name)),
+ .source_url = ZigString.init(std.mem.span(main_file_name)),
+ .hash = 0,
+ };
+ }
+ defer jsc_vm.transpiled_count += 1;
+
+ var bundler = &jsc_vm.bundler;
+ var old = jsc_vm.bundler.log;
+ jsc_vm.bundler.log = log;
+ jsc_vm.bundler.linker.log = log;
+ jsc_vm.bundler.resolver.log = log;
+ defer {
+ jsc_vm.bundler.log = old;
+ jsc_vm.bundler.linker.log = old;
+ jsc_vm.bundler.resolver.log = old;
+ }
+
+ var jsx = bundler.options.jsx;
+ jsx.parse = false;
+ var opts = js_parser.Parser.Options.init(jsx, .js);
+ opts.enable_bundling = false;
+ opts.transform_require_to_import = true;
+ opts.can_import_from_bundle = bundler.options.node_modules_bundle != null;
+ opts.features.hot_module_reloading = false;
+ opts.features.react_fast_refresh = false;
+ opts.filepath_hash_for_hmr = 0;
+ opts.warn_about_unbundled_modules = false;
+ opts.macro_context = &jsc_vm.bundler.macro_context.?;
+ const main_ast = (bundler.resolver.caches.js.parse(jsc_vm.allocator, opts, bundler.options.define, bundler.log, &jsc_vm.entry_point.source) catch null) orelse {
+ return error.ParseError;
+ };
+ var parse_result = ParseResult{ .source = jsc_vm.entry_point.source, .ast = main_ast, .loader = .js, .input_fd = null };
+ var file_path = Fs.Path.init(bundler.fs.top_level_dir);
+ file_path.name.dir = bundler.fs.top_level_dir;
+ file_path.name.base = "bun:main";
+ try bundler.linker.link(
+ file_path,
+ &parse_result,
+ jsc_vm.origin,
+ .absolute_path,
+ false,
+ true,
+ );
+ var printer = source_code_printer.?.*;
+ var written: usize = undefined;
+ printer.ctx.reset();
+ {
+ defer source_code_printer.?.* = printer;
+ written = try jsc_vm.bundler.printWithSourceMap(
+ parse_result,
+ @TypeOf(&printer),
+ &printer,
+ .esm_ascii,
+ SavedSourceMap.SourceMapHandler.init(&jsc_vm.source_mappings),
+ );
+ }
+
+ if (written == 0) {
+ return error.PrintingErrorWriteFailed;
+ }
+
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(jsc_vm.allocator.dupe(u8, printer.ctx.written) catch unreachable),
+ .specifier = ZigString.init(std.mem.span(main_file_name)),
+ .source_url = ZigString.init(std.mem.span(main_file_name)),
+ .hash = 0,
+ };
+ },
+ .@"bun:jsc" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(@embedFile("bun-jsc.exports.js") ++ JSC.Node.fs.constants_string),
+ .specifier = ZigString.init("bun:jsc"),
+ .source_url = ZigString.init("bun:jsc"),
+ .hash = 0,
+ };
+ },
+ .@"node:fs" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(@embedFile("fs.exports.js") ++ JSC.Node.fs.constants_string),
+ .specifier = ZigString.init("node:fs"),
+ .source_url = ZigString.init("node:fs"),
+ .hash = 0,
+ };
+ },
+ .@"node:fs/promises" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(@embedFile("fs_promises.exports.js") ++ JSC.Node.fs.constants_string),
+ .specifier = ZigString.init("node:fs/promises"),
+ .source_url = ZigString.init("node:fs/promises"),
+ .hash = 0,
+ };
+ },
+ .@"node:path" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(Node.Path.code),
+ .specifier = ZigString.init("node:path"),
+ .source_url = ZigString.init("node:path"),
+ .hash = 0,
+ };
+ },
+ .@"bun:ffi" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ "export const FFIType = " ++
+ JSC.FFI.ABIType.map_to_js_object ++
+ ";\n\n" ++
+ "export const suffix = '" ++ shared_library_suffix ++ "';\n\n" ++
+ @embedFile("ffi.exports.js") ++
+ "\n",
+ ),
+ .specifier = ZigString.init("bun:ffi"),
+ .source_url = ZigString.init("bun:ffi"),
+ .hash = 0,
+ };
+ },
+ .@"detect-libc" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, @embedFile(if (Environment.isLinux) "detect-libc.linux.js" else "detect-libc.js")),
+ ),
+ .specifier = ZigString.init("detect-libc"),
+ .source_url = ZigString.init("detect-libc"),
+ .hash = 0,
+ };
+ },
+ .@"bun:sqlite" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, @embedFile("./bindings/sqlite/sqlite.exports.js")),
+ ),
+ .specifier = ZigString.init("bun:sqlite"),
+ .source_url = ZigString.init("bun:sqlite"),
+ .hash = 0,
+ };
+ },
+ .@"node:module" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, @embedFile("./module.exports.js")),
+ ),
+ .specifier = ZigString.init("node:module"),
+ .source_url = ZigString.init("node:module"),
+ .hash = 0,
+ };
+ },
+ .@"node:perf_hooks" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, @embedFile("./perf_hooks.exports.js")),
+ ),
+ .specifier = ZigString.init("node:perf_hooks"),
+ .source_url = ZigString.init("node:perf_hooks"),
+ .hash = 0,
+ };
+ },
+ .@"ws" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, @embedFile("./ws.exports.js")),
+ ),
+ .specifier = ZigString.init("ws"),
+ .source_url = ZigString.init("ws"),
+ .hash = 0,
+ };
+ },
+ .@"node:timers" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, @embedFile("./node_timers.exports.js")),
+ ),
+ .specifier = ZigString.init("node:timers"),
+ .source_url = ZigString.init("node:timers"),
+ .hash = 0,
+ };
+ },
+ .@"node:timers/promises" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, @embedFile("./node_timers_promises.exports.js")),
+ ),
+ .specifier = ZigString.init("node:timers/promises"),
+ .source_url = ZigString.init("node:timers/promises"),
+ .hash = 0,
+ };
+ },
+ .@"node:streams/web" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, @embedFile("./node_streams_web.exports.js")),
+ ),
+ .specifier = ZigString.init("node:streams/web"),
+ .source_url = ZigString.init("node:streams/web"),
+ .hash = 0,
+ };
+ },
+ .@"node:streams/consumer" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, @embedFile("./node_streams_consumer.exports.js")),
+ ),
+ .specifier = ZigString.init("node:streams/consumer"),
+ .source_url = ZigString.init("node:streams/consumer"),
+ .hash = 0,
+ };
+ },
+ .@"undici" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, @embedFile("./undici.exports.js")),
+ ),
+ .specifier = ZigString.init("undici"),
+ .source_url = ZigString.init("undici"),
+ .hash = 0,
+ };
+ },
+ }
+ } else if (_specifier.len > js_ast.Macro.namespaceWithColon.len and
+ strings.eqlComptimeIgnoreLen(_specifier[0..js_ast.Macro.namespaceWithColon.len], js_ast.Macro.namespaceWithColon))
+ {
+ if (comptime !disable_transpilying) {
+ if (jsc_vm.macro_entry_points.get(MacroEntryPoint.generateIDFromSpecifier(_specifier))) |entry| {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(entry.source.contents),
+ .specifier = ZigString.init(_specifier),
+ .source_url = ZigString.init(_specifier),
+ .hash = 0,
+ };
+ }
+ }
+ }
+
+ const specifier = normalizeSpecifier(_specifier);
+
+ std.debug.assert(std.fs.path.isAbsolute(specifier)); // if this crashes, it means the resolver was skipped.
+
+ const path = Fs.Path.init(specifier);
+ const loader = jsc_vm.bundler.options.loaders.get(path.name.ext) orelse .file;
+
+ switch (loader) {
+ .js, .jsx, .ts, .tsx, .json, .toml => {
+ jsc_vm.transpiled_count += 1;
+ jsc_vm.bundler.resetStore();
+ const hash = http.Watcher.getHash(path.text);
+
+ var allocator = if (jsc_vm.has_loaded) jsc_vm.arena.allocator() else jsc_vm.allocator;
+
+ var fd: ?StoredFileDescriptorType = null;
+ var package_json: ?*PackageJSON = null;
+
+ if (jsc_vm.watcher) |watcher| {
+ if (watcher.indexOf(hash)) |index| {
+ const _fd = watcher.watchlist.items(.fd)[index];
+ fd = if (_fd > 0) _fd else null;
+ package_json = watcher.watchlist.items(.package_json)[index];
+ }
+ }
+
+ var old = jsc_vm.bundler.log;
+ jsc_vm.bundler.log = log;
+ jsc_vm.bundler.linker.log = log;
+ jsc_vm.bundler.resolver.log = log;
+
+ defer {
+ jsc_vm.bundler.log = old;
+ jsc_vm.bundler.linker.log = old;
+ jsc_vm.bundler.resolver.log = old;
+ }
+
+ // this should be a cheap lookup because 24 bytes == 8 * 3 so it's read 3 machine words
+ const is_node_override = specifier.len > "/bun-vfs/node_modules/".len and strings.eqlComptimeIgnoreLen(specifier[0.."/bun-vfs/node_modules/".len], "/bun-vfs/node_modules/");
+
+ const macro_remappings = if (jsc_vm.macro_mode or !jsc_vm.has_any_macro_remappings or is_node_override)
+ MacroRemap{}
+ else
+ jsc_vm.bundler.options.macro_remap;
+
+ var fallback_source: logger.Source = undefined;
+
+ var parse_options = Bundler.ParseOptions{
+ .allocator = allocator,
+ .path = path,
+ .loader = loader,
+ .dirname_fd = 0,
+ .file_descriptor = fd,
+ .file_hash = hash,
+ .macro_remappings = macro_remappings,
+ .jsx = jsc_vm.bundler.options.jsx,
+ };
+
+ if (is_node_override) {
+ if (NodeFallbackModules.contentsFromPath(specifier)) |code| {
+ const fallback_path = Fs.Path.initWithNamespace(specifier, "node");
+ fallback_source = logger.Source{ .path = fallback_path, .contents = code, .key_path = fallback_path };
+ parse_options.virtual_source = &fallback_source;
+ }
+ }
+
+ var parse_result = jsc_vm.bundler.parseMaybeReturnFileOnly(
+ parse_options,
+ null,
+ disable_transpilying,
+ ) orelse {
+ return error.ParseError;
+ };
+
+ if (comptime disable_transpilying) {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(parse_result.source.contents),
+ .specifier = ZigString.init(specifier),
+ .source_url = ZigString.init(path.text),
+ .hash = 0,
+ };
+ }
+
+ const start_count = jsc_vm.bundler.linker.import_counter;
+ // We _must_ link because:
+ // - node_modules bundle won't be properly
+ try jsc_vm.bundler.linker.link(
+ path,
+ &parse_result,
+ jsc_vm.origin,
+ .absolute_path,
+ false,
+ true,
+ );
+
+ if (!jsc_vm.macro_mode)
+ jsc_vm.resolved_count += jsc_vm.bundler.linker.import_counter - start_count;
+ jsc_vm.bundler.linker.import_counter = 0;
+
+ var printer = source_code_printer.?.*;
+ var written: usize = undefined;
+ printer.ctx.reset();
+ {
+ defer source_code_printer.?.* = printer;
+ written = try jsc_vm.bundler.printWithSourceMap(
+ parse_result,
+ @TypeOf(&printer),
+ &printer,
+ .esm_ascii,
+ SavedSourceMap.SourceMapHandler.init(&jsc_vm.source_mappings),
+ );
+ }
+
+ if (written == 0) {
+ return error.PrintingErrorWriteFailed;
+ }
+
+ if (jsc_vm.has_loaded) {
+ return jsc_vm.refCountedResolvedSource(printer.ctx.written, specifier, path.text, null);
+ }
+
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(jsc_vm.allocator.dupe(u8, printer.ctx.written) catch unreachable),
+ .specifier = ZigString.init(specifier),
+ .source_url = ZigString.init(path.text),
+ .hash = 0,
+ };
+ },
+ // provideFetch() should be called
+ .napi => unreachable,
+ // .wasm => {
+ // jsc_vm.transpiled_count += 1;
+ // var fd: ?StoredFileDescriptorType = null;
+
+ // var allocator = if (jsc_vm.has_loaded) jsc_vm.arena.allocator() else jsc_vm.allocator;
+
+ // const hash = http.Watcher.getHash(path.text);
+ // if (jsc_vm.watcher) |watcher| {
+ // if (watcher.indexOf(hash)) |index| {
+ // const _fd = watcher.watchlist.items(.fd)[index];
+ // fd = if (_fd > 0) _fd else null;
+ // }
+ // }
+
+ // var parse_options = Bundler.ParseOptions{
+ // .allocator = allocator,
+ // .path = path,
+ // .loader = loader,
+ // .dirname_fd = 0,
+ // .file_descriptor = fd,
+ // .file_hash = hash,
+ // .macro_remappings = MacroRemap{},
+ // .jsx = jsc_vm.bundler.options.jsx,
+ // };
+
+ // var parse_result = jsc_vm.bundler.parse(
+ // parse_options,
+ // null,
+ // ) orelse {
+ // return error.ParseError;
+ // };
+
+ // return ResolvedSource{
+ // .allocator = if (jsc_vm.has_loaded) &jsc_vm.allocator else null,
+ // .source_code = ZigString.init(jsc_vm.allocator.dupe(u8, parse_result.source.contents) catch unreachable),
+ // .specifier = ZigString.init(specifier),
+ // .source_url = ZigString.init(path.text),
+ // .hash = 0,
+ // .tag = ResolvedSource.Tag.wasm,
+ // };
+ // },
+ else => {
+ return ResolvedSource{
+ .allocator = &vm.allocator,
+ .source_code = ZigString.init(try strings.quotedAlloc(jsc_vm.allocator, path.pretty)),
+ .specifier = ZigString.init(path.text),
+ .source_url = ZigString.init(path.text),
+ .hash = 0,
+ };
+ },
+ }
+ }
+ pub const ResolveFunctionResult = struct {
+ result: ?Resolver.Result,
+ path: string,
+ };
+
+ fn _resolve(
+ ret: *ResolveFunctionResult,
+ _: *JSGlobalObject,
+ specifier: string,
+ source: string,
+ comptime is_a_file_path: bool,
+ comptime realpath: bool,
+ ) !void {
+ std.debug.assert(VirtualMachine.vm_loaded);
+ // macOS threadlocal vars are very slow
+ // we won't change threads in this function
+ // so we can copy it here
+ var jsc_vm = vm;
+
+ if (jsc_vm.node_modules == null and strings.eqlComptime(std.fs.path.basename(specifier), Runtime.Runtime.Imports.alt_name)) {
+ ret.path = Runtime.Runtime.Imports.Name;
+ return;
+ } else if (jsc_vm.node_modules != null and strings.eqlComptime(specifier, bun_file_import_path)) {
+ ret.path = bun_file_import_path;
+ return;
+ } else if (strings.eqlComptime(specifier, main_file_name)) {
+ ret.result = null;
+ ret.path = jsc_vm.entry_point.source.path.text;
+ return;
+ } else if (specifier.len > js_ast.Macro.namespaceWithColon.len and strings.eqlComptimeIgnoreLen(specifier[0..js_ast.Macro.namespaceWithColon.len], js_ast.Macro.namespaceWithColon)) {
+ ret.result = null;
+ ret.path = specifier;
+ return;
+ } else if (specifier.len > "/bun-vfs/node_modules/".len and strings.eqlComptimeIgnoreLen(specifier[0.."/bun-vfs/node_modules/".len], "/bun-vfs/node_modules/")) {
+ ret.result = null;
+ ret.path = specifier;
+ return;
+ } else if (HardcodedModule.Map.get(specifier)) |result| {
+ ret.result = null;
+ ret.path = std.mem.span(@tagName(result));
+ return;
+ }
+
+ 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)
+ if (is_a_file_path)
+ Fs.PathName.init(source).dirWithTrailingSlash()
+ else
+ source
+ else
+ jsc_vm.bundler.fs.top_level_dir,
+ specifier,
+ .stmt,
+ );
+
+ if (!jsc_vm.macro_mode) {
+ jsc_vm.has_any_macro_remappings = jsc_vm.has_any_macro_remappings or jsc_vm.bundler.options.macro_remap.count() > 0;
+ }
+ ret.result = result;
+ const result_path = result.pathConst() orelse return error.ModuleNotFound;
+ jsc_vm.resolved_count += 1;
+ if (comptime !realpath) {
+ if (jsc_vm.node_modules != null and !strings.eqlComptime(result_path.namespace, "node") and result.isLikelyNodeModule()) {
+ const node_modules_bundle = jsc_vm.node_modules.?;
+
+ node_module_checker: {
+ const package_json = result.package_json orelse brk: {
+ if (jsc_vm.bundler.resolver.packageJSONForResolvedNodeModule(&result)) |pkg| {
+ break :brk pkg;
+ } else {
+ break :node_module_checker;
+ }
+ };
+
+ if (node_modules_bundle.getPackageIDByName(package_json.name)) |possible_pkg_ids| {
+ const pkg_id: u32 = brk: {
+ for (possible_pkg_ids) |pkg_id| {
+ const pkg = node_modules_bundle.bundle.packages[pkg_id];
+ if (pkg.hash == package_json.hash) {
+ break :brk pkg_id;
+ }
+ }
+ break :node_module_checker;
+ };
+
+ const package = &node_modules_bundle.bundle.packages[pkg_id];
+
+ if (Environment.isDebug) {
+ std.debug.assert(strings.eql(node_modules_bundle.str(package.name), package_json.name));
+ }
+
+ const package_relative_path = jsc_vm.bundler.fs.relative(
+ package_json.source.path.name.dirWithTrailingSlash(),
+ result_path.text,
+ );
+
+ if (node_modules_bundle.findModuleIDInPackage(package, package_relative_path) == null) break :node_module_checker;
+
+ ret.path = bun_file_import_path;
+ return;
+ }
+ }
+ }
+ }
+
+ ret.path = result_path.text;
+ }
+ pub fn queueMicrotaskToEventLoop(
+ globalObject: *JSGlobalObject,
+ microtask: *Microtask,
+ ) void {
+ std.debug.assert(VirtualMachine.vm_loaded);
+
+ var vm_ = globalObject.bunVM();
+ if (vm_.global == globalObject) {
+ vm_.enqueueTask(Task.init(@ptrCast(*JSC.MicrotaskForDefaultGlobalObject, microtask)));
+ } else {
+ vm_.enqueueTask(Task.init(microtask));
+ }
+ }
+
+ pub fn resolveForAPI(res: *ErrorableZigString, global: *JSGlobalObject, specifier: ZigString, source: ZigString) void {
+ resolveMaybeNeedsTrailingSlash(res, global, specifier, source, false, true);
+ }
+
+ pub fn resolveFilePathForAPI(res: *ErrorableZigString, global: *JSGlobalObject, specifier: ZigString, source: ZigString) void {
+ resolveMaybeNeedsTrailingSlash(res, global, specifier, source, true, true);
+ }
+
+ pub fn resolve(res: *ErrorableZigString, global: *JSGlobalObject, specifier: ZigString, source: ZigString) void {
+ resolveMaybeNeedsTrailingSlash(res, global, specifier, source, true, false);
+ }
+
+ pub fn resolveMaybeNeedsTrailingSlash(res: *ErrorableZigString, global: *JSGlobalObject, specifier: ZigString, source: ZigString, comptime is_a_file_path: bool, comptime realpath: bool) void {
+ var result = ResolveFunctionResult{ .path = "", .result = null };
+
+ _resolve(&result, global, specifier.slice(), source.slice(), is_a_file_path, realpath) catch |err| {
+ // This should almost always just apply to dynamic imports
+
+ const printed = ResolveError.fmt(
+ vm.allocator,
+ specifier.slice(),
+ source.slice(),
+ err,
+ ) catch unreachable;
+ const msg = logger.Msg{
+ .data = logger.rangeData(
+ null,
+ logger.Range.None,
+ printed,
+ ),
+ .metadata = .{
+ // import_kind is wrong probably
+ .resolve = .{ .specifier = logger.BabyString.in(printed, specifier.slice()), .import_kind = .stmt },
+ },
+ };
+
+ {
+ res.* = ErrorableZigString.err(err, @ptrCast(*anyopaque, ResolveError.create(global, vm.allocator, msg, source.slice())));
+ }
+
+ return;
+ };
+
+ res.* = ErrorableZigString.ok(ZigString.init(result.path));
+ }
+ pub fn normalizeSpecifier(slice_: string) string {
+ var vm_ = VirtualMachine.vm;
+
+ var slice = slice_;
+ if (slice.len == 0) return slice;
+ var was_http = false;
+ if (strings.hasPrefix(slice, "https://")) {
+ slice = slice["https://".len..];
+ was_http = true;
+ }
+
+ if (strings.hasPrefix(slice, "http://")) {
+ slice = slice["http://".len..];
+ was_http = true;
+ }
+
+ if (strings.hasPrefix(slice, vm_.origin.host)) {
+ slice = slice[vm_.origin.host.len..];
+ } else if (was_http) {
+ if (strings.indexOfChar(slice, '/')) |i| {
+ slice = slice[i..];
+ }
+ }
+
+ if (vm_.origin.path.len > 1) {
+ if (strings.hasPrefix(slice, vm_.origin.path)) {
+ slice = slice[vm_.origin.path.len..];
+ }
+ }
+
+ if (vm_.bundler.options.routes.asset_prefix_path.len > 0) {
+ if (strings.hasPrefix(slice, vm_.bundler.options.routes.asset_prefix_path)) {
+ slice = slice[vm_.bundler.options.routes.asset_prefix_path.len..];
+ }
+ }
+
+ return slice;
+ }
+
+ // // This double prints
+ // pub fn promiseRejectionTracker(global: *JSGlobalObject, promise: *JSPromise, _: JSPromiseRejectionOperation) callconv(.C) JSValue {
+ // const result = promise.result(global.vm());
+ // if (@enumToInt(VirtualMachine.vm.last_error_jsvalue) != @enumToInt(result)) {
+ // VirtualMachine.vm.defaultErrorHandler(result, null);
+ // }
+
+ // return JSValue.jsUndefined();
+ // }
+
+ const main_file_name: string = "bun:main";
+
+ pub fn fetch(ret: *ErrorableResolvedSource, global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) void {
+ var log = logger.Log.init(vm.bundler.allocator);
+ const spec = specifier.slice();
+ const result = _fetch(global, spec, source.slice(), &log, false) catch |err| {
+ processFetchLog(global, specifier, source, &log, ret, err);
+ return;
+ };
+
+ if (log.errors > 0) {
+ processFetchLog(global, specifier, source, &log, ret, error.LinkError);
+ return;
+ }
+
+ if (log.warnings > 0) {
+ var writer = Output.errorWriter();
+ if (Output.enable_ansi_colors) {
+ for (log.msgs.items) |msg| {
+ if (msg.kind == .warn) {
+ msg.writeFormat(writer, true) catch {};
+ }
+ }
+ } else {
+ for (log.msgs.items) |msg| {
+ if (msg.kind == .warn) {
+ msg.writeFormat(writer, false) catch {};
+ }
+ }
+ }
+ }
+
+ ret.result.value = result;
+
+ if (vm.blobs) |blobs| {
+ const specifier_blob = brk: {
+ if (strings.hasPrefix(spec, VirtualMachine.vm.bundler.fs.top_level_dir)) {
+ break :brk spec[VirtualMachine.vm.bundler.fs.top_level_dir.len..];
+ }
+ break :brk spec;
+ };
+
+ if (vm.has_loaded) {
+ blobs.temporary.put(specifier_blob, .{ .ptr = result.source_code.ptr, .len = result.source_code.len }) catch {};
+ } else {
+ blobs.persistent.put(specifier_blob, .{ .ptr = result.source_code.ptr, .len = result.source_code.len }) catch {};
+ }
+ }
+
+ ret.success = true;
+ }
+
+ fn processFetchLog(globalThis: *JSGlobalObject, specifier: ZigString, referrer: ZigString, log: *logger.Log, ret: *ErrorableResolvedSource, err: anyerror) void {
+ switch (log.msgs.items.len) {
+ 0 => {
+ const msg = logger.Msg{
+ .data = logger.rangeData(null, logger.Range.None, std.fmt.allocPrint(vm.allocator, "{s} while building {s}", .{ @errorName(err), specifier.slice() }) catch unreachable),
+ };
+ {
+ ret.* = ErrorableResolvedSource.err(err, @ptrCast(*anyopaque, BuildError.create(globalThis, vm.bundler.allocator, msg)));
+ }
+ return;
+ },
+
+ 1 => {
+ const msg = log.msgs.items[0];
+ ret.* = ErrorableResolvedSource.err(err, switch (msg.metadata) {
+ .build => BuildError.create(globalThis, vm.bundler.allocator, msg).?,
+ .resolve => ResolveError.create(
+ globalThis,
+ vm.bundler.allocator,
+ msg,
+ referrer.slice(),
+ ).?,
+ });
+ return;
+ },
+ else => {
+ var errors_stack: [256]*anyopaque = undefined;
+
+ var errors = errors_stack[0..@minimum(log.msgs.items.len, errors_stack.len)];
+
+ for (log.msgs.items) |msg, i| {
+ errors[i] = switch (msg.metadata) {
+ .build => BuildError.create(globalThis, vm.bundler.allocator, msg).?,
+ .resolve => ResolveError.create(
+ globalThis,
+ vm.bundler.allocator,
+ msg,
+ referrer.slice(),
+ ).?,
+ };
+ }
+
+ ret.* = ErrorableResolvedSource.err(
+ err,
+ globalThis.createAggregateError(
+ errors.ptr,
+ @intCast(u16, errors.len),
+ &ZigString.init(
+ std.fmt.allocPrint(vm.bundler.allocator, "{d} errors building \"{s}\"", .{
+ errors.len,
+ specifier.slice(),
+ }) catch unreachable,
+ ),
+ ).asVoid(),
+ );
+ },
+ }
+ }
+
+ // TODO:
+ pub fn deinit(_: *VirtualMachine) void {}
+
+ pub const ExceptionList = std.ArrayList(Api.JsException);
+
+ pub fn printException(
+ this: *VirtualMachine,
+ exception: *Exception,
+ exception_list: ?*ExceptionList,
+ comptime Writer: type,
+ writer: Writer,
+ ) void {
+ if (Output.enable_ansi_colors) {
+ this.printErrorlikeObject(exception.value(), exception, exception_list, Writer, writer, true);
+ } else {
+ this.printErrorlikeObject(exception.value(), exception, exception_list, Writer, writer, false);
+ }
+ }
+
+ pub fn defaultErrorHandler(this: *VirtualMachine, result: JSValue, exception_list: ?*ExceptionList) void {
+ if (result.isException(this.global.vm())) {
+ var exception = @ptrCast(*Exception, result.asVoid());
+
+ this.printException(
+ exception,
+ exception_list,
+ @TypeOf(Output.errorWriter()),
+ Output.errorWriter(),
+ );
+ } else if (Output.enable_ansi_colors) {
+ this.printErrorlikeObject(result, null, exception_list, @TypeOf(Output.errorWriter()), Output.errorWriter(), true);
+ } else {
+ this.printErrorlikeObject(result, null, exception_list, @TypeOf(Output.errorWriter()), Output.errorWriter(), false);
+ }
+ }
+
+ pub fn clearEntryPoint(
+ this: *VirtualMachine,
+ ) void {
+ if (this.main.len == 0) {
+ return;
+ }
+
+ var str = ZigString.init(main_file_name);
+ this.global.deleteModuleRegistryEntry(&str);
+ }
+
+ pub fn loadEntryPoint(this: *VirtualMachine, entry_path: string) !*JSInternalPromise {
+ try this.entry_point.generate(@TypeOf(this.bundler), &this.bundler, Fs.PathName.init(entry_path), main_file_name);
+ this.main = entry_path;
+
+ var promise: *JSInternalPromise = undefined;
+ // We first import the node_modules bundle. This prevents any potential TDZ issues.
+ // The contents of the node_modules bundle are lazy, so hopefully this should be pretty quick.
+ if (this.node_modules != null and !this.has_loaded_node_modules) {
+ this.has_loaded_node_modules = true;
+ promise = JSModuleLoader.loadAndEvaluateModule(this.global, &ZigString.init(std.mem.span(bun_file_import_path)));
+
+ this.waitForPromise(promise);
+ if (promise.status(this.global.vm()) == .Rejected)
+ return promise;
+ }
+
+ promise = JSModuleLoader.loadAndEvaluateModule(this.global, &ZigString.init(std.mem.span(main_file_name)));
+
+ this.waitForPromise(promise);
+
+ return promise;
+ }
+
+ pub fn loadMacroEntryPoint(this: *VirtualMachine, entry_path: string, function_name: string, specifier: string, hash: i32) !*JSInternalPromise {
+ var entry_point_entry = try this.macro_entry_points.getOrPut(hash);
+
+ if (!entry_point_entry.found_existing) {
+ var macro_entry_pointer: *MacroEntryPoint = this.allocator.create(MacroEntryPoint) catch unreachable;
+ entry_point_entry.value_ptr.* = macro_entry_pointer;
+ try macro_entry_pointer.generate(&this.bundler, Fs.PathName.init(entry_path), function_name, hash, specifier);
+ }
+ var entry_point = entry_point_entry.value_ptr.*;
+
+ var loader = MacroEntryPointLoader{
+ .path = entry_point.source.path.text,
+ };
+
+ this.runWithAPILock(MacroEntryPointLoader, &loader, MacroEntryPointLoader.load);
+ return loader.promise;
+ }
+
+ /// A subtlelty of JavaScriptCore:
+ /// JavaScriptCore has many release asserts that check an API lock is currently held
+ /// We cannot hold it from Zig code because it relies on C++ ARIA to automatically release the lock
+ /// and it is not safe to copy the lock itself
+ /// So we have to wrap entry points to & from JavaScript with an API lock that calls out to C++
+ pub inline fn runWithAPILock(this: *VirtualMachine, comptime Context: type, ctx: *Context, comptime function: fn (ctx: *Context) void) void {
+ this.global.vm().holdAPILock(ctx, OpaqueWrap(Context, function));
+ }
+
+ const MacroEntryPointLoader = struct {
+ path: string,
+ promise: *JSInternalPromise = undefined,
+ pub fn load(this: *MacroEntryPointLoader) void {
+ this.promise = vm._loadMacroEntryPoint(this.path);
+ }
+ };
+
+ pub inline fn _loadMacroEntryPoint(this: *VirtualMachine, entry_path: string) *JSInternalPromise {
+ var promise: *JSInternalPromise = undefined;
+
+ promise = JSModuleLoader.loadAndEvaluateModule(this.global, &ZigString.init(entry_path));
+ this.waitForPromise(promise);
+
+ return promise;
+ }
+
+ // When the Error-like object is one of our own, it's best to rely on the object directly instead of serializing it to a ZigException.
+ // This is for:
+ // - BuildError
+ // - ResolveError
+ // If there were multiple errors, it could be contained in an AggregateError.
+ // In that case, this function becomes recursive.
+ // In all other cases, we will convert it to a ZigException.
+ const errors_property = ZigString.init("errors");
+ pub fn printErrorlikeObject(
+ this: *VirtualMachine,
+ value: JSValue,
+ exception: ?*Exception,
+ exception_list: ?*ExceptionList,
+ comptime Writer: type,
+ writer: Writer,
+ comptime allow_ansi_color: bool,
+ ) void {
+ if (comptime JSC.is_bindgen) {
+ return;
+ }
+
+ var was_internal = false;
+
+ defer {
+ if (was_internal) {
+ if (exception) |exception_| {
+ var holder = ZigException.Holder.init();
+ var zig_exception: *ZigException = holder.zigException();
+ exception_.getStackTrace(&zig_exception.stack);
+ if (zig_exception.stack.frames_len > 0) {
+ if (allow_ansi_color) {
+ printStackTrace(Writer, writer, zig_exception.stack, true) catch {};
+ } else {
+ printStackTrace(Writer, writer, zig_exception.stack, false) catch {};
+ }
+ }
+
+ if (exception_list) |list| {
+ zig_exception.addToErrorList(list, this.bundler.fs.top_level_dir, &this.origin) catch {};
+ }
+ }
+ }
+ }
+
+ if (value.isAggregateError(this.global)) {
+ const AggregateErrorIterator = struct {
+ writer: Writer,
+ current_exception_list: ?*ExceptionList = null,
+
+ pub fn iteratorWithColor(_vm: [*c]VM, globalObject: [*c]JSGlobalObject, ctx: ?*anyopaque, nextValue: JSValue) callconv(.C) void {
+ iterator(_vm, globalObject, nextValue, ctx.?, true);
+ }
+ pub fn iteratorWithOutColor(_vm: [*c]VM, globalObject: [*c]JSGlobalObject, ctx: ?*anyopaque, nextValue: JSValue) callconv(.C) void {
+ iterator(_vm, globalObject, nextValue, ctx.?, false);
+ }
+ inline fn iterator(_: [*c]VM, _: [*c]JSGlobalObject, nextValue: JSValue, ctx: ?*anyopaque, comptime color: bool) void {
+ var this_ = @intToPtr(*@This(), @ptrToInt(ctx));
+ VirtualMachine.vm.printErrorlikeObject(nextValue, null, this_.current_exception_list, Writer, this_.writer, color);
+ }
+ };
+ var iter = AggregateErrorIterator{ .writer = writer, .current_exception_list = exception_list };
+ if (comptime allow_ansi_color) {
+ value.getErrorsProperty(this.global).forEach(this.global, &iter, AggregateErrorIterator.iteratorWithColor);
+ } else {
+ value.getErrorsProperty(this.global).forEach(this.global, &iter, AggregateErrorIterator.iteratorWithOutColor);
+ }
+ return;
+ }
+
+ if (js.JSValueIsObject(this.global.ref(), value.asRef())) {
+ if (js.JSObjectGetPrivate(value.asRef())) |priv| {
+ was_internal = this.printErrorFromMaybePrivateData(
+ priv,
+ exception_list,
+ Writer,
+ writer,
+ allow_ansi_color,
+ );
+ return;
+ }
+ }
+
+ was_internal = this.printErrorFromMaybePrivateData(
+ value.asRef(),
+ exception_list,
+ Writer,
+ writer,
+ allow_ansi_color,
+ );
+ }
+
+ pub fn printErrorFromMaybePrivateData(
+ this: *VirtualMachine,
+ value: ?*anyopaque,
+ exception_list: ?*ExceptionList,
+ comptime Writer: type,
+ writer: Writer,
+ comptime allow_ansi_color: bool,
+ ) bool {
+ const private_data_ptr = JSPrivateDataPtr.from(value);
+
+ switch (private_data_ptr.tag()) {
+ .BuildError => {
+ defer Output.flush();
+ var build_error = private_data_ptr.as(BuildError);
+ if (!build_error.logged) {
+ build_error.msg.writeFormat(writer, allow_ansi_color) catch {};
+ writer.writeAll("\n") catch {};
+ build_error.logged = true;
+ }
+ this.had_errors = this.had_errors or build_error.msg.kind == .err;
+ if (exception_list != null) {
+ this.log.addMsg(
+ build_error.msg,
+ ) catch {};
+ }
+ return true;
+ },
+ .ResolveError => {
+ defer Output.flush();
+ var resolve_error = private_data_ptr.as(ResolveError);
+ if (!resolve_error.logged) {
+ resolve_error.msg.writeFormat(writer, allow_ansi_color) catch {};
+ resolve_error.logged = true;
+ }
+
+ this.had_errors = this.had_errors or resolve_error.msg.kind == .err;
+
+ if (exception_list != null) {
+ this.log.addMsg(
+ resolve_error.msg,
+ ) catch {};
+ }
+ return true;
+ },
+ else => {
+ this.printErrorInstance(
+ @intToEnum(JSValue, @bitCast(JSValue.Type, (@ptrToInt(value)))),
+ exception_list,
+ Writer,
+ writer,
+ allow_ansi_color,
+ ) catch |err| {
+ if (comptime Environment.isDebug) {
+ // yo dawg
+ Output.printErrorln("Error while printing Error-like object: {s}", .{@errorName(err)});
+ Output.flush();
+ }
+ };
+ return false;
+ },
+ }
+ }
+
+ pub fn reportUncaughtExceptio(_: *JSGlobalObject, exception: *JSC.Exception) JSValue {
+ VirtualMachine.vm.defaultErrorHandler(exception.value(), null);
+ return JSC.JSValue.jsUndefined();
+ }
+
+ pub fn printStackTrace(comptime Writer: type, writer: Writer, trace: ZigStackTrace, comptime allow_ansi_colors: bool) !void {
+ const stack = trace.frames();
+ if (stack.len > 0) {
+ var i: i16 = 0;
+ const origin: ?*const URL = if (vm.is_from_devserver) &vm.origin else null;
+ const dir = vm.bundler.fs.top_level_dir;
+
+ while (i < stack.len) : (i += 1) {
+ const frame = stack[@intCast(usize, i)];
+ const file = frame.source_url.slice();
+ const func = frame.function_name.slice();
+ if (file.len == 0 and func.len == 0) continue;
+
+ const has_name = std.fmt.count("{any}", .{frame.nameFormatter(
+ false,
+ )}) > 0;
+
+ if (has_name) {
+ try writer.print(
+ comptime Output.prettyFmt(
+ "<r> <d>at <r>{any}<d> (<r>{any}<d>)<r>\n",
+ allow_ansi_colors,
+ ),
+ .{
+ frame.nameFormatter(
+ allow_ansi_colors,
+ ),
+ frame.sourceURLFormatter(
+ dir,
+ origin,
+ false,
+ allow_ansi_colors,
+ ),
+ },
+ );
+ } else {
+ try writer.print(
+ comptime Output.prettyFmt(
+ "<r> <d>at <r>{any}\n",
+ allow_ansi_colors,
+ ),
+ .{
+ frame.sourceURLFormatter(
+ dir,
+ origin,
+ false,
+ allow_ansi_colors,
+ ),
+ },
+ );
+ }
+ }
+ }
+ }
+
+ pub fn remapZigException(
+ this: *VirtualMachine,
+ exception: *ZigException,
+ error_instance: JSValue,
+ exception_list: ?*ExceptionList,
+ ) void {
+ error_instance.toZigException(this.global, exception);
+ // defer this so that it copies correctly
+ defer {
+ if (exception_list) |list| {
+ exception.addToErrorList(list, this.bundler.fs.top_level_dir, &this.origin) catch unreachable;
+ }
+ }
+
+ var frames: []JSC.ZigStackFrame = exception.stack.frames_ptr[0..exception.stack.frames_len];
+ if (frames.len == 0) return;
+
+ var top = &frames[0];
+ if (this.source_mappings.resolveMapping(
+ top.source_url.slice(),
+ @maximum(top.position.line, 0),
+ @maximum(top.position.column_start, 0),
+ )) |mapping| {
+ var log = logger.Log.init(default_allocator);
+ var original_source = _fetch(this.global, top.source_url.slice(), "", &log, true) catch return;
+ const code = original_source.source_code.slice();
+ top.position.line = mapping.original.lines;
+ top.position.line_start = mapping.original.lines;
+ top.position.line_stop = mapping.original.lines + 1;
+ top.position.column_start = mapping.original.columns;
+ top.position.column_stop = mapping.original.columns + 1;
+ exception.remapped = true;
+ top.remapped = true;
+ // This expression range is no longer accurate
+ top.position.expression_start = mapping.original.columns;
+ top.position.expression_stop = mapping.original.columns + 1;
+
+ if (strings.getLinesInText(
+ code,
+ @intCast(u32, top.position.line),
+ JSC.ZigException.Holder.source_lines_count,
+ )) |lines| {
+ var source_lines = exception.stack.source_lines_ptr[0..JSC.ZigException.Holder.source_lines_count];
+ var source_line_numbers = exception.stack.source_lines_numbers[0..JSC.ZigException.Holder.source_lines_count];
+ std.mem.set(ZigString, source_lines, ZigString.Empty);
+ std.mem.set(i32, source_line_numbers, 0);
+
+ var lines_ = lines[0..@minimum(lines.len, source_lines.len)];
+ for (lines_) |line, j| {
+ source_lines[(lines_.len - 1) - j] = ZigString.init(line);
+ source_line_numbers[j] = top.position.line - @intCast(i32, j) + 1;
+ }
+
+ exception.stack.source_lines_len = @intCast(u8, lines_.len);
+
+ top.position.column_stop = @intCast(i32, source_lines[lines_.len - 1].len);
+ top.position.line_stop = top.position.column_stop;
+
+ // This expression range is no longer accurate
+ top.position.expression_start = mapping.original.columns;
+ top.position.expression_stop = top.position.column_stop;
+ }
+ }
+
+ if (frames.len > 1) {
+ for (frames[1..]) |*frame| {
+ if (frame.position.isInvalid()) continue;
+ if (this.source_mappings.resolveMapping(
+ frame.source_url.slice(),
+ @maximum(frame.position.line, 0),
+ @maximum(frame.position.column_start, 0),
+ )) |mapping| {
+ frame.position.line = mapping.original.lines;
+ frame.remapped = true;
+ frame.position.column_start = mapping.original.columns;
+ }
+ }
+ }
+ }
+
+ pub fn printErrorInstance(this: *VirtualMachine, error_instance: JSValue, exception_list: ?*ExceptionList, comptime Writer: type, writer: Writer, comptime allow_ansi_color: bool) !void {
+ var exception_holder = ZigException.Holder.init();
+ var exception = exception_holder.zigException();
+ this.remapZigException(exception, error_instance, exception_list);
+ this.had_errors = true;
+
+ var line_numbers = exception.stack.source_lines_numbers[0..exception.stack.source_lines_len];
+ var max_line: i32 = -1;
+ for (line_numbers) |line| max_line = @maximum(max_line, line);
+ const max_line_number_pad = std.fmt.count("{d}", .{max_line});
+
+ var source_lines = exception.stack.sourceLineIterator();
+ var last_pad: u64 = 0;
+ while (source_lines.untilLast()) |source| {
+ const int_size = std.fmt.count("{d}", .{source.line});
+ const pad = max_line_number_pad - int_size;
+ last_pad = pad;
+ writer.writeByteNTimes(' ', pad) catch unreachable;
+ writer.print(
+ comptime Output.prettyFmt("<r><d>{d} | <r>{s}\n", allow_ansi_color),
+ .{
+ source.line,
+ std.mem.trim(u8, source.text, "\n"),
+ },
+ ) catch unreachable;
+ }
+
+ var name = exception.name;
+ if (strings.eqlComptime(exception.name.slice(), "Error")) {
+ name = ZigString.init("error");
+ }
+
+ const message = exception.message;
+ var did_print_name = false;
+ if (source_lines.next()) |source| {
+ if (source.text.len > 0 and exception.stack.frames()[0].position.isInvalid()) {
+ defer did_print_name = true;
+ var text = std.mem.trim(u8, source.text, "\n");
+
+ writer.print(
+ comptime Output.prettyFmt(
+ "<r><d>- |<r> {s}\n",
+ allow_ansi_color,
+ ),
+ .{
+ text,
+ },
+ ) catch unreachable;
+
+ if (name.len > 0 and message.len > 0) {
+ writer.print(comptime Output.prettyFmt(" <r><red>{}<r><d>:<r> <b>{}<r>\n", allow_ansi_color), .{
+ name,
+ message,
+ }) catch unreachable;
+ } else if (name.len > 0) {
+ writer.print(comptime Output.prettyFmt(" <r><b>{}<r>\n", allow_ansi_color), .{name}) catch unreachable;
+ } else if (message.len > 0) {
+ writer.print(comptime Output.prettyFmt(" <r><b>{}<r>\n", allow_ansi_color), .{message}) catch unreachable;
+ }
+ } else if (source.text.len > 0) {
+ defer did_print_name = true;
+ const int_size = std.fmt.count("{d}", .{source.line});
+ const pad = max_line_number_pad - int_size;
+ writer.writeByteNTimes(' ', pad) catch unreachable;
+ const top = exception.stack.frames()[0];
+ var remainder = std.mem.trim(u8, source.text, "\n");
+
+ writer.print(
+ comptime Output.prettyFmt(
+ "<r><d>{d} |<r> {s}\n",
+ allow_ansi_color,
+ ),
+ .{ source.line, remainder },
+ ) catch unreachable;
+
+ if (!top.position.isInvalid()) {
+ var first_non_whitespace = @intCast(u32, top.position.column_start);
+ while (first_non_whitespace < source.text.len and source.text[first_non_whitespace] == ' ') {
+ first_non_whitespace += 1;
+ }
+ const indent = @intCast(usize, pad) + " | ".len + first_non_whitespace;
+
+ writer.writeByteNTimes(' ', indent) catch unreachable;
+ writer.print(comptime Output.prettyFmt(
+ "<red><b>^<r>\n",
+ allow_ansi_color,
+ ), .{}) catch unreachable;
+ }
+
+ if (name.len > 0 and message.len > 0) {
+ writer.print(comptime Output.prettyFmt(" <r><red>{s}<r><d>:<r> <b>{s}<r>\n", allow_ansi_color), .{
+ name,
+ message,
+ }) catch unreachable;
+ } else if (name.len > 0) {
+ writer.print(comptime Output.prettyFmt(" <r><b>{s}<r>\n", allow_ansi_color), .{name}) catch unreachable;
+ } else if (message.len > 0) {
+ writer.print(comptime Output.prettyFmt(" <r><b>{s}<r>\n", allow_ansi_color), .{message}) catch unreachable;
+ }
+ }
+ }
+
+ if (!did_print_name) {
+ if (name.len > 0 and message.len > 0) {
+ writer.print(comptime Output.prettyFmt("<r><red>{s}<r><d>:<r> <b>{s}<r>\n", true), .{
+ name,
+ message,
+ }) catch unreachable;
+ } else if (name.len > 0) {
+ writer.print(comptime Output.prettyFmt("<r>{s}<r>\n", true), .{name}) catch unreachable;
+ } else if (message.len > 0) {
+ writer.print(comptime Output.prettyFmt("<r>{s}<r>\n", true), .{name}) catch unreachable;
+ }
+ }
+
+ var add_extra_line = false;
+
+ const Show = struct {
+ system_code: bool = false,
+ syscall: bool = false,
+ errno: bool = false,
+ path: bool = false,
+ };
+
+ var show = Show{
+ .system_code = exception.system_code.len > 0 and !strings.eql(exception.system_code.slice(), name.slice()),
+ .syscall = exception.syscall.len > 0,
+ .errno = exception.errno < 0,
+ .path = exception.path.len > 0,
+ };
+
+ if (show.path) {
+ if (show.syscall) {
+ writer.writeAll(" ") catch unreachable;
+ } else if (show.errno) {
+ writer.writeAll(" ") catch unreachable;
+ }
+ writer.print(comptime Output.prettyFmt(" path<d>: <r><cyan>\"{s}\"<r>\n", allow_ansi_color), .{exception.path}) catch unreachable;
+ }
+
+ if (show.system_code) {
+ if (show.syscall) {
+ writer.writeAll(" ") catch unreachable;
+ } else if (show.errno) {
+ writer.writeAll(" ") catch unreachable;
+ }
+ writer.print(comptime Output.prettyFmt(" code<d>: <r><cyan>\"{s}\"<r>\n", allow_ansi_color), .{exception.system_code}) catch unreachable;
+ add_extra_line = true;
+ }
+
+ if (show.syscall) {
+ writer.print(comptime Output.prettyFmt("syscall<d>: <r><cyan>\"{s}\"<r>\n", allow_ansi_color), .{exception.syscall}) catch unreachable;
+ add_extra_line = true;
+ }
+
+ if (show.errno) {
+ if (show.syscall) {
+ writer.writeAll(" ") catch unreachable;
+ }
+ writer.print(comptime Output.prettyFmt("errno<d>: <r><yellow>{d}<r>\n", allow_ansi_color), .{exception.errno}) catch unreachable;
+ add_extra_line = true;
+ }
+
+ if (add_extra_line) writer.writeAll("\n") catch unreachable;
+
+ try printStackTrace(@TypeOf(writer), writer, exception.stack, allow_ansi_color);
+ }
+};
+
+const GetterFn = fn (
+ this: anytype,
+ ctx: js.JSContextRef,
+ thisObject: js.JSValueRef,
+ prop: js.JSStringRef,
+ exception: js.ExceptionRef,
+) js.JSValueRef;
+const SetterFn = fn (
+ this: anytype,
+ ctx: js.JSContextRef,
+ thisObject: js.JSValueRef,
+ prop: js.JSStringRef,
+ value: js.JSValueRef,
+ exception: js.ExceptionRef,
+) js.JSValueRef;
+
+const JSProp = struct {
+ get: ?GetterFn = null,
+ set: ?SetterFn = null,
+ ro: bool = false,
+};
+
+pub const EventListenerMixin = struct {
+ threadlocal var event_listener_names_buf: [128]u8 = undefined;
+ pub const List = std.ArrayList(js.JSObjectRef);
+ pub const Map = std.AutoHashMap(EventListenerMixin.EventType, EventListenerMixin.List);
+
+ pub const EventType = enum {
+ fetch,
+ err,
+
+ const SizeMatcher = strings.ExactSizeMatcher(8);
+
+ pub fn match(str: string) ?EventType {
+ return switch (SizeMatcher.match(str)) {
+ SizeMatcher.case("fetch") => EventType.fetch,
+ SizeMatcher.case("error") => EventType.err,
+ else => null,
+ };
+ }
+ };
+
+ pub fn emitFetchEvent(
+ vm: *VirtualMachine,
+ request_context: *http.RequestContext,
+ comptime CtxType: type,
+ ctx: *CtxType,
+ comptime onError: fn (ctx: *CtxType, err: anyerror, value: JSValue, request_ctx: *http.RequestContext) anyerror!void,
+ ) !void {
+ if (comptime JSC.is_bindgen) unreachable;
+
+ var listeners = vm.event_listeners.get(EventType.fetch) orelse (return onError(ctx, error.NoListeners, JSValue.jsUndefined(), request_context) catch {});
+ if (listeners.items.len == 0) return onError(ctx, error.NoListeners, JSValue.jsUndefined(), request_context) catch {};
+ const FetchEventRejectionHandler = struct {
+ pub fn onRejection(_ctx: *anyopaque, err: anyerror, fetch_event: *FetchEvent, value: JSValue) void {
+ onError(
+ @intToPtr(*CtxType, @ptrToInt(_ctx)),
+ err,
+ value,
+ fetch_event.request_context.?,
+ ) catch {};
+ }
+ };
+
+ // Rely on JS finalizer
+ var fetch_event = try vm.allocator.create(FetchEvent);
+
+ fetch_event.* = FetchEvent{
+ .request_context = request_context,
+ .request = try Request.fromRequestContext(request_context, vm.global),
+ .onPromiseRejectionCtx = @as(*anyopaque, ctx),
+ .onPromiseRejectionHandler = FetchEventRejectionHandler.onRejection,
+ };
+
+ var fetch_args: [1]js.JSObjectRef = undefined;
+ fetch_args[0] = FetchEvent.Class.make(vm.global.ref(), fetch_event);
+ JSC.C.JSValueProtect(vm.global.ref(), fetch_args[0]);
+ defer JSC.C.JSValueUnprotect(vm.global.ref(), fetch_args[0]);
+
+ for (listeners.items) |listener_ref| {
+ vm.tick();
+ var result = js.JSObjectCallAsFunctionReturnValue(vm.global.ref(), listener_ref, null, 1, &fetch_args);
+ vm.tick();
+ var promise = JSInternalPromise.resolvedPromise(vm.global, result);
+
+ vm.event_loop.waitForPromise(promise);
+
+ if (fetch_event.rejected) return;
+
+ if (promise.status(vm.global.vm()) == .Rejected) {
+ onError(ctx, error.JSError, promise.result(vm.global.vm()), request_context) catch {};
+ return;
+ }
+
+ _ = promise.result(vm.global.vm());
+
+ vm.waitForTasks();
+
+ if (request_context.has_called_done) {
+ break;
+ }
+ }
+
+ if (!request_context.has_called_done) {
+ onError(ctx, error.FetchHandlerRespondWithNeverCalled, JSValue.jsUndefined(), request_context) catch {};
+ return;
+ }
+ }
+
+ pub fn addEventListener(
+ comptime Struct: type,
+ ) type {
+ const Handler = struct {
+ pub fn addListener(
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ argumentCount: usize,
+ _arguments: [*c]const js.JSValueRef,
+ _: js.ExceptionRef,
+ ) callconv(.C) js.JSValueRef {
+ const arguments = _arguments[0..argumentCount];
+ if (arguments.len == 0 or arguments.len == 1 or !js.JSValueIsString(ctx, arguments[0]) or !js.JSValueIsObject(ctx, arguments[arguments.len - 1]) or !js.JSObjectIsFunction(ctx, arguments[arguments.len - 1])) {
+ return js.JSValueMakeUndefined(ctx);
+ }
+
+ const name_len = js.JSStringGetLength(arguments[0]);
+ if (name_len > event_listener_names_buf.len) {
+ return js.JSValueMakeUndefined(ctx);
+ }
+
+ const name_used_len = js.JSStringGetUTF8CString(arguments[0], &event_listener_names_buf, event_listener_names_buf.len);
+ const name = event_listener_names_buf[0 .. name_used_len - 1];
+ const event = EventType.match(name) orelse return js.JSValueMakeUndefined(ctx);
+ var entry = VirtualMachine.vm.event_listeners.getOrPut(event) catch unreachable;
+
+ if (!entry.found_existing) {
+ entry.value_ptr.* = List.initCapacity(VirtualMachine.vm.allocator, 1) catch unreachable;
+ }
+
+ var callback = arguments[arguments.len - 1];
+ js.JSValueProtect(ctx, callback);
+ entry.value_ptr.append(callback) catch unreachable;
+
+ return js.JSValueMakeUndefined(ctx);
+ }
+ };
+
+ return NewClass(
+ Struct,
+ .{
+ .name = "addEventListener",
+ .read_only = true,
+ },
+ .{
+ .@"callAsFunction" = .{
+ .rfn = Handler.addListener,
+ .ts = d.ts{},
+ },
+ },
+ .{},
+ );
+ }
+};
+
+pub const ResolveError = struct {
+ msg: logger.Msg,
+ allocator: std.mem.Allocator,
+ referrer: ?Fs.Path = null,
+ logged: bool = false,
+
+ pub fn fmt(allocator: std.mem.Allocator, specifier: string, referrer: string, err: anyerror) !string {
+ switch (err) {
+ error.ModuleNotFound => {
+ if (Resolver.isPackagePath(specifier)) {
+ return try std.fmt.allocPrint(allocator, "Cannot find package \"{s}\" from \"{s}\"", .{ specifier, referrer });
+ } else {
+ return try std.fmt.allocPrint(allocator, "Cannot find module \"{s}\" from \"{s}\"", .{ specifier, referrer });
+ }
+ },
+ else => {
+ if (Resolver.isPackagePath(specifier)) {
+ return try std.fmt.allocPrint(allocator, "{s} while resolving package \"{s}\" from \"{s}\"", .{ @errorName(err), specifier, referrer });
+ } else {
+ return try std.fmt.allocPrint(allocator, "{s} while resolving \"{s}\" from \"{s}\"", .{ @errorName(err), specifier, referrer });
+ }
+ },
+ }
+ }
+
+ pub fn toStringFn(this: *ResolveError, ctx: js.JSContextRef) js.JSValueRef {
+ var text = std.fmt.allocPrint(default_allocator, "ResolveError: {s}", .{this.msg.data.text}) catch return null;
+ var str = ZigString.init(text);
+ str.setOutputEncoding();
+ if (str.isUTF8()) {
+ const out = str.toValueGC(ctx.ptr());
+ default_allocator.free(text);
+ return out.asObjectRef();
+ }
+
+ return str.toExternalValue(ctx.ptr()).asObjectRef();
+ }
+
+ pub fn toString(
+ // this
+ this: *ResolveError,
+ ctx: js.JSContextRef,
+ // function
+ _: js.JSObjectRef,
+ // thisObject
+ _: js.JSObjectRef,
+ _: []const js.JSValueRef,
+ _: js.ExceptionRef,
+ ) js.JSValueRef {
+ return this.toStringFn(ctx);
+ }
+
+ pub fn convertToType(ctx: js.JSContextRef, obj: js.JSObjectRef, kind: js.JSType, _: js.ExceptionRef) callconv(.C) js.JSValueRef {
+ switch (kind) {
+ js.JSType.kJSTypeString => {
+ if (js.JSObjectGetPrivate(obj)) |priv| {
+ if (JSPrivateDataPtr.from(priv).is(ResolveError)) {
+ var this = JSPrivateDataPtr.from(priv).as(ResolveError);
+ return this.toStringFn(ctx);
+ }
+ }
+ },
+ else => {},
+ }
+
+ return obj;
+ }
+
+ pub const Class = NewClass(
+ ResolveError,
+ .{
+ .name = "ResolveError",
+ .read_only = true,
+ },
+ .{
+ .toString = .{ .rfn = toString },
+ .convertToType = .{ .rfn = convertToType },
+ },
+ .{
+ .@"referrer" = .{
+ .@"get" = getReferrer,
+ .ro = true,
+ .ts = d.ts{ .@"return" = "string" },
+ },
+ .@"message" = .{
+ .@"get" = getMessage,
+ .ro = true,
+ .ts = d.ts{ .@"return" = "string" },
+ },
+ .@"name" = .{
+ .@"get" = getName,
+ .ro = true,
+ .ts = d.ts{ .@"return" = "string" },
+ },
+ .@"specifier" = .{
+ .@"get" = getSpecifier,
+ .ro = true,
+ .ts = d.ts{ .@"return" = "string" },
+ },
+ .@"importKind" = .{
+ .@"get" = getImportKind,
+ .ro = true,
+ .ts = d.ts{ .@"return" = "string" },
+ },
+ .@"position" = .{
+ .@"get" = getPosition,
+ .ro = true,
+ .ts = d.ts{ .@"return" = "string" },
+ },
+ },
+ );
+
+ pub fn create(
+ globalThis: *JSGlobalObject,
+ allocator: std.mem.Allocator,
+ msg: logger.Msg,
+ referrer: string,
+ ) js.JSObjectRef {
+ var resolve_error = allocator.create(ResolveError) catch unreachable;
+ resolve_error.* = ResolveError{
+ .msg = msg.clone(allocator) catch unreachable,
+ .allocator = allocator,
+ .referrer = Fs.Path.init(referrer),
+ };
+ var ref = Class.make(globalThis.ref(), resolve_error);
+ js.JSValueProtect(globalThis.ref(), ref);
+ return ref;
+ }
+
+ pub fn getPosition(
+ this: *ResolveError,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSStringRef,
+ exception: js.ExceptionRef,
+ ) js.JSValueRef {
+ return BuildError.generatePositionObject(this.msg, ctx, exception);
+ }
+
+ pub fn getMessage(
+ this: *ResolveError,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+ ) js.JSValueRef {
+ return ZigString.init(this.msg.data.text).toValue(ctx.ptr()).asRef();
+ }
+
+ pub fn getSpecifier(
+ this: *ResolveError,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+ ) js.JSValueRef {
+ return ZigString.init(this.msg.metadata.resolve.specifier.slice(this.msg.data.text)).toValue(ctx.ptr()).asRef();
+ }
+
+ pub fn getImportKind(
+ this: *ResolveError,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+ ) js.JSValueRef {
+ return ZigString.init(@tagName(this.msg.metadata.resolve.import_kind)).toValue(ctx.ptr()).asRef();
+ }
+
+ pub fn getReferrer(
+ this: *ResolveError,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+ ) js.JSValueRef {
+ if (this.referrer) |referrer| {
+ return ZigString.init(referrer.text).toValue(ctx.ptr()).asRef();
+ } else {
+ return js.JSValueMakeNull(ctx);
+ }
+ }
+
+ const BuildErrorName = "ResolveError";
+ pub fn getName(
+ _: *ResolveError,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+ ) js.JSValueRef {
+ return ZigString.init(BuildErrorName).toValue(ctx.ptr()).asRef();
+ }
+
+ pub fn finalize(this: *ResolveError) void {
+ this.msg.deinit(bun.default_allocator);
+ }
+};
+
+pub const BuildError = struct {
+ msg: logger.Msg,
+ // resolve_result: Resolver.Result,
+ allocator: std.mem.Allocator,
+ logged: bool = false,
+
+ pub const Class = NewClass(
+ BuildError,
+ .{ .name = "BuildError", .read_only = true, .ts = .{
+ .class = .{
+ .name = "BuildError",
+ },
+ } },
+ .{
+ .convertToType = .{ .rfn = convertToType },
+ .toString = .{ .rfn = toString },
+ },
+ .{
+ .@"message" = .{
+ .@"get" = getMessage,
+ .ro = true,
+ },
+ .@"name" = .{
+ .@"get" = getName,
+ .ro = true,
+ },
+ // This is called "position" instead of "location" because "location" may be confused with Location.
+ .@"position" = .{
+ .@"get" = getPosition,
+ .ro = true,
+ },
+ },
+ );
+
+ pub fn toStringFn(this: *BuildError, ctx: js.JSContextRef) js.JSValueRef {
+ var text = std.fmt.allocPrint(default_allocator, "BuildError: {s}", .{this.msg.data.text}) catch return null;
+ var str = ZigString.init(text);
+ str.setOutputEncoding();
+ if (str.isUTF8()) {
+ const out = str.toValueGC(ctx.ptr());
+ default_allocator.free(text);
+ return out.asObjectRef();
+ }
+
+ return str.toExternalValue(ctx.ptr()).asObjectRef();
+ }
+
+ pub fn toString(
+ // this
+ this: *BuildError,
+ ctx: js.JSContextRef,
+ // function
+ _: js.JSObjectRef,
+ // thisObject
+ _: js.JSObjectRef,
+ _: []const js.JSValueRef,
+ _: js.ExceptionRef,
+ ) js.JSValueRef {
+ return this.toStringFn(ctx);
+ }
+
+ pub fn convertToType(ctx: js.JSContextRef, obj: js.JSObjectRef, kind: js.JSType, _: js.ExceptionRef) callconv(.C) js.JSValueRef {
+ switch (kind) {
+ js.JSType.kJSTypeString => {
+ if (js.JSObjectGetPrivate(obj)) |priv| {
+ if (JSPrivateDataPtr.from(priv).is(BuildError)) {
+ var this = JSPrivateDataPtr.from(priv).as(BuildError);
+ return this.toStringFn(ctx);
+ }
+ }
+ },
+ else => {},
+ }
+
+ return obj;
+ }
+
+ pub fn create(
+ globalThis: *JSGlobalObject,
+ allocator: std.mem.Allocator,
+ msg: logger.Msg,
+ // resolve_result: *const Resolver.Result,
+ ) js.JSObjectRef {
+ var build_error = allocator.create(BuildError) catch unreachable;
+ build_error.* = BuildError{
+ .msg = msg.clone(allocator) catch unreachable,
+ // .resolve_result = resolve_result.*,
+ .allocator = allocator,
+ };
+
+ var ref = Class.make(globalThis.ref(), build_error);
+ js.JSValueProtect(globalThis.ref(), ref);
+ return ref;
+ }
+
+ pub fn getPosition(
+ this: *BuildError,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSStringRef,
+ exception: js.ExceptionRef,
+ ) js.JSValueRef {
+ return generatePositionObject(this.msg, ctx, exception);
+ }
+
+ pub const PositionProperties = struct {
+ const _file = ZigString.init("file");
+ var file_ptr: js.JSStringRef = null;
+ pub fn file() js.JSStringRef {
+ if (file_ptr == null) {
+ file_ptr = _file.toJSStringRef();
+ }
+ return file_ptr.?;
+ }
+ const _namespace = ZigString.init("namespace");
+ var namespace_ptr: js.JSStringRef = null;
+ pub fn namespace() js.JSStringRef {
+ if (namespace_ptr == null) {
+ namespace_ptr = _namespace.toJSStringRef();
+ }
+ return namespace_ptr.?;
+ }
+ const _line = ZigString.init("line");
+ var line_ptr: js.JSStringRef = null;
+ pub fn line() js.JSStringRef {
+ if (line_ptr == null) {
+ line_ptr = _line.toJSStringRef();
+ }
+ return line_ptr.?;
+ }
+ const _column = ZigString.init("column");
+ var column_ptr: js.JSStringRef = null;
+ pub fn column() js.JSStringRef {
+ if (column_ptr == null) {
+ column_ptr = _column.toJSStringRef();
+ }
+ return column_ptr.?;
+ }
+ const _length = ZigString.init("length");
+ var length_ptr: js.JSStringRef = null;
+ pub fn length() js.JSStringRef {
+ if (length_ptr == null) {
+ length_ptr = _length.toJSStringRef();
+ }
+ return length_ptr.?;
+ }
+ const _lineText = ZigString.init("lineText");
+ var lineText_ptr: js.JSStringRef = null;
+ pub fn lineText() js.JSStringRef {
+ if (lineText_ptr == null) {
+ lineText_ptr = _lineText.toJSStringRef();
+ }
+ return lineText_ptr.?;
+ }
+ const _offset = ZigString.init("offset");
+ var offset_ptr: js.JSStringRef = null;
+ pub fn offset() js.JSStringRef {
+ if (offset_ptr == null) {
+ offset_ptr = _offset.toJSStringRef();
+ }
+ return offset_ptr.?;
+ }
+ };
+
+ pub fn generatePositionObject(msg: logger.Msg, ctx: js.JSContextRef, exception: ExceptionValueRef) js.JSValueRef {
+ if (msg.data.location) |location| {
+ const ref = js.JSObjectMake(ctx, null, null);
+ js.JSObjectSetProperty(
+ ctx,
+ ref,
+ PositionProperties.lineText(),
+ ZigString.init(location.line_text orelse "").toJSStringRef(),
+ 0,
+ exception,
+ );
+ js.JSObjectSetProperty(
+ ctx,
+ ref,
+ PositionProperties.file(),
+ ZigString.init(location.file).toJSStringRef(),
+ 0,
+ exception,
+ );
+ js.JSObjectSetProperty(
+ ctx,
+ ref,
+ PositionProperties.namespace(),
+ ZigString.init(location.namespace).toJSStringRef(),
+ 0,
+ exception,
+ );
+ js.JSObjectSetProperty(
+ ctx,
+ ref,
+ PositionProperties.line(),
+ js.JSValueMakeNumber(ctx, @intToFloat(f64, location.line)),
+ 0,
+ exception,
+ );
+ js.JSObjectSetProperty(
+ ctx,
+ ref,
+ PositionProperties.column(),
+ js.JSValueMakeNumber(ctx, @intToFloat(f64, location.column)),
+ 0,
+ exception,
+ );
+ js.JSObjectSetProperty(
+ ctx,
+ ref,
+ PositionProperties.length(),
+ js.JSValueMakeNumber(ctx, @intToFloat(f64, location.length)),
+ 0,
+ exception,
+ );
+ js.JSObjectSetProperty(
+ ctx,
+ ref,
+ PositionProperties.offset(),
+ js.JSValueMakeNumber(ctx, @intToFloat(f64, location.offset)),
+ 0,
+ exception,
+ );
+ return ref;
+ }
+
+ return js.JSValueMakeNull(ctx);
+ }
+
+ pub fn getMessage(
+ this: *BuildError,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+ ) js.JSValueRef {
+ return ZigString.init(this.msg.data.text).toValue(ctx.ptr()).asRef();
+ }
+
+ const BuildErrorName = "BuildError";
+ pub fn getName(
+ _: *BuildError,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+ ) js.JSValueRef {
+ return ZigString.init(BuildErrorName).toValue(ctx.ptr()).asRef();
+ }
+};
+
+pub const JSPrivateDataTag = JSPrivateDataPtr.Tag;
+
+pub const HardcodedModule = enum {
+ @"bun:ffi",
+ @"bun:main",
+ @"node:fs",
+ @"node:path",
+ @"detect-libc",
+ @"bun:sqlite",
+ @"bun:jsc",
+ @"node:module",
+ @"node:perf_hooks",
+ @"ws",
+ @"node:timers",
+ @"node:timers/promises",
+ @"node:streams/web",
+ @"node:streams/consumer",
+ @"node:fs/promises",
+ @"undici",
+
+ pub const Map = bun.ComptimeStringMap(
+ HardcodedModule,
+ .{
+ .{ "bun:ffi", HardcodedModule.@"bun:ffi" },
+ .{ "bun:jsc", HardcodedModule.@"bun:jsc" },
+ .{ "bun:main", HardcodedModule.@"bun:main" },
+ .{ "bun:sqlite", HardcodedModule.@"bun:sqlite" },
+ .{ "detect-libc", HardcodedModule.@"detect-libc" },
+ .{ "ffi", HardcodedModule.@"bun:ffi" },
+ .{ "fs", HardcodedModule.@"node:fs" },
+ .{ "module", HardcodedModule.@"node:module" },
+ .{ "node:fs", HardcodedModule.@"node:fs" },
+ .{ "node:fs/promises", HardcodedModule.@"node:fs/promises" },
+ .{ "node:module", HardcodedModule.@"node:module" },
+ .{ "node:path", HardcodedModule.@"node:path" },
+ .{ "node:path/posix", HardcodedModule.@"node:path" },
+ .{ "node:path/win32", HardcodedModule.@"node:path" },
+ .{ "node:perf_hooks", HardcodedModule.@"node:perf_hooks" },
+ .{ "node:streams/consumer", HardcodedModule.@"node:streams/consumer" },
+ .{ "node:streams/web", HardcodedModule.@"node:streams/web" },
+ .{ "node:timers", HardcodedModule.@"node:timers" },
+ .{ "node:timers/promises", HardcodedModule.@"node:timers/promises" },
+ .{ "path", HardcodedModule.@"node:path" },
+ .{ "undici", HardcodedModule.@"undici" },
+ .{ "ws", HardcodedModule.@"ws" },
+ },
+ );
+ pub const LinkerMap = bun.ComptimeStringMap(
+ string,
+ .{
+ .{ "bun:ffi", "bun:ffi" },
+ .{ "bun:jsc", "bun:jsc" },
+ .{ "bun:sqlite", "bun:sqlite" },
+ .{ "bun:wrap", "bun:wrap" },
+ .{ "detect-libc", "detect-libc" },
+ .{ "detect-libc/lib/detect-libc.js", "detect-libc" },
+ .{ "ffi", "bun:ffi" },
+ .{ "fs", "node:fs" },
+ .{ "fs/promises", "node:fs/promises" },
+ .{ "module", "node:module" },
+ .{ "node:fs", "node:fs" },
+ .{ "node:fs/promises", "node:fs/promises" },
+ .{ "node:module", "node:module" },
+ .{ "node:path", "node:path" },
+ .{ "node:streams/consumer", "node:streams/consumer" },
+ .{ "node:streams/web", "node:streams/web" },
+ .{ "node:timers", "node:timers" },
+ .{ "node:timers/promises", "node:timers/promises" },
+ .{ "path", "node:path" },
+ .{ "perf_hooks", "node:perf_hooks" },
+ .{ "streams/consumer", "node:streams/consumer" },
+ .{ "streams/web", "node:streams/web" },
+ .{ "timers", "node:timers" },
+ .{ "timers/promises", "node:timers/promises" },
+ .{ "undici", "undici" },
+ .{ "ws", "ws" },
+ .{ "ws/lib/websocket", "ws" },
+ },
+ );
+};
+
+pub const DisabledModule = bun.ComptimeStringMap(
+ void,
+ .{
+ .{"child_process"},
+ .{"http"},
+ .{"https"},
+ .{"net"},
+ .{"node:child_process"},
+ .{"node:http"},
+ .{"node:https"},
+ .{"node:net"},
+ .{"node:tls"},
+ .{"node:worker_threads"},
+ .{"tls"},
+ .{"worker_threads"},
+ },
+);