diff options
author | 2022-06-22 23:21:48 -0700 | |
---|---|---|
committer | 2022-06-22 23:21:48 -0700 | |
commit | 729d445b6885f69dd2c6355f38707bd42851c791 (patch) | |
tree | f87a7c408929ea3f57bbb7ace380cf869da83c0e /src/javascript/jsc/javascript.zig | |
parent | 25f820c6bf1d8ec6d444ef579cc036b8c0607b75 (diff) | |
download | bun-jarred/rename.tar.gz bun-jarred/rename.tar.zst bun-jarred/rename.zip |
change the directory structurejarred/rename
Diffstat (limited to 'src/javascript/jsc/javascript.zig')
-rw-r--r-- | src/javascript/jsc/javascript.zig | 2738 |
1 files changed, 0 insertions, 2738 deletions
diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig deleted file mode 100644 index a5c9f1e01..000000000 --- a/src/javascript/jsc/javascript.zig +++ /dev/null @@ -1,2738 +0,0 @@ -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"}, - }, -); |