aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/module_loader.zig
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-11-06 21:42:05 -0800
committerGravatar GitHub <noreply@github.com> 2022-11-06 21:42:05 -0800
commite45f72e8e422191adeb4fd1bad896dc6a47c76b3 (patch)
tree3a76da8b343c081dba84e0ac95f3c2cc2423106a /src/bun.js/module_loader.zig
parent645cf903350a7fe5f5076100b7c4a6bc8cd1b431 (diff)
downloadbun-e45f72e8e422191adeb4fd1bad896dc6a47c76b3.tar.gz
bun-e45f72e8e422191adeb4fd1bad896dc6a47c76b3.tar.zst
bun-e45f72e8e422191adeb4fd1bad896dc6a47c76b3.zip
Automatically install npm packages when running a script in Bun's runtime (#1459)
* Update bundler.zig * WIP * Update README.md * Update README.md * wip * Support running scripts without package.json * Add `--no-auto-install` and `--prefer-offline` flags * WIP * wip * Update headers-handwritten.h * WIP * Build fixes * Fix UAF * Update install.zig * Must call .allocate() * Micro-optimization: only call .timestamp() once per tick when installing packages * Support progress bar * Extend the timestamp for package staleness checks to 1 day * Add `--prefer-latest`, `-i` CLI Flags * Fix crash * Support line text manually being set on an Error instance * Add a few more fields for error messages * Fix bug when counting 8 character strings in string builder * Implement error handling for automatic package installs! * Fix crash * Make it say module when there's a slash * Update module_loader.zig * Ban dependency versions in import specifiers when a package.json is present * Remove unused field * Update README.md * Update README.md * Update README.md * Update README.md Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'src/bun.js/module_loader.zig')
-rw-r--r--src/bun.js/module_loader.zig2052
1 files changed, 2052 insertions, 0 deletions
diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig
new file mode 100644
index 000000000..bee5fa1a1
--- /dev/null
+++ b/src/bun.js/module_loader.zig
@@ -0,0 +1,2052 @@
+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");
+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 ParseResult = @import("../bundler.zig").ParseResult;
+const logger = @import("../logger.zig");
+const Api = @import("../api/schema.zig").Api;
+const options = @import("../options.zig");
+const Bundler = @import("../bundler.zig").Bundler;
+const PluginRunner = @import("../bundler.zig").PluginRunner;
+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 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 PendingResolution = @import("../resolver/resolver.zig").PendingResolution;
+const ThreadSafeFunction = JSC.napi.ThreadSafeFunction;
+const PackageManager = @import("../install/install.zig").PackageManager;
+const Install = @import("../install/install.zig");
+const VirtualMachine = JSC.VirtualMachine;
+const Dependency = @import("../install/dependency.zig");
+
+// This exists to make it so we can reload these quicker in development
+fn jsModuleFromFile(from_path: string, comptime input: string) string {
+ const absolute_path = comptime std.fs.path.dirname(@src().file).? ++ "/" ++ input;
+ const Holder = struct {
+ pub const file = @embedFile(absolute_path);
+ };
+
+ if (comptime !Environment.allow_assert) {
+ if (from_path.len == 0) {
+ return Holder.file;
+ }
+ }
+
+ var file: std.fs.File = undefined;
+
+ if (comptime Environment.allow_assert) {
+ file = std.fs.openFileAbsoluteZ(absolute_path, .{ .mode = .read_only }) catch {
+ const WarnOnce = struct {
+ pub var warned = false;
+ };
+ if (!WarnOnce.warned) {
+ WarnOnce.warned = true;
+ Output.prettyErrorln("Could not find file: " ++ absolute_path ++ " - using embedded version", .{});
+ }
+ return Holder.file;
+ };
+ } else {
+ var parts = [_]string{ from_path, input };
+ var buf: [bun.MAX_PATH_BYTES]u8 = undefined;
+ var absolute_path_to_use = Fs.FileSystem.instance.absBuf(&parts, &buf);
+ buf[absolute_path_to_use.len] = 0;
+ file = std.fs.openFileAbsoluteZ(std.meta.assumeSentinel(absolute_path_to_use.ptr, 0), .{ .mode = .read_only }) catch {
+ const WarnOnce = struct {
+ pub var warned = false;
+ };
+ if (!WarnOnce.warned) {
+ WarnOnce.warned = true;
+ Output.prettyErrorln("Could not find file: {s}, so using embedded version", .{absolute_path_to_use});
+ }
+ return Holder.file;
+ };
+ }
+
+ var contents = file.readToEndAlloc(bun.default_allocator, std.math.maxInt(usize)) catch @panic("Cannot read file: " ++ absolute_path);
+ if (comptime !Environment.allow_assert) {
+ file.close();
+ }
+ return contents;
+}
+
+inline fn jsSyntheticModule(comptime name: ResolvedSource.Tag) ResolvedSource {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(""),
+ .specifier = ZigString.init(@tagName(name)),
+ .source_url = ZigString.init(@tagName(name)),
+ .hash = 0,
+ .tag = name,
+ };
+}
+
+fn dumpSource(specifier: string, printer: anytype) !void {
+ const BunDebugHolder = struct {
+ pub var dir: ?std.fs.Dir = null;
+ };
+ if (BunDebugHolder.dir == null) {
+ BunDebugHolder.dir = try std.fs.cwd().makeOpenPath("/tmp/bun-debug-src/", .{ .iterate = true });
+ }
+
+ if (std.fs.path.dirname(specifier)) |dir_path| {
+ var parent = try BunDebugHolder.dir.?.makeOpenPath(dir_path[1..], .{ .iterate = true });
+ defer parent.close();
+ try parent.writeFile(std.fs.path.basename(specifier), printer.ctx.getWritten());
+ } else {
+ try BunDebugHolder.dir.?.writeFile(std.fs.path.basename(specifier), printer.ctx.getWritten());
+ }
+}
+
+pub const ModuleLoader = struct {
+ pub const AsyncModule = struct {
+
+ // This is all the state used by the printer to print the module
+ parse_result: ParseResult,
+ stmt_blocks: []*js_ast.Stmt.Data.Store.All.Block = &[_]*js_ast.Stmt.Data.Store.All.Block{},
+ expr_blocks: []*js_ast.Expr.Data.Store.All.Block = &[_]*js_ast.Expr.Data.Store.All.Block{},
+ promise: JSC.Strong = .{},
+ path: Fs.Path,
+ specifier: string = "",
+ referrer: string = "",
+ string_buf: []u8 = &[_]u8{},
+ fd: ?StoredFileDescriptorType = null,
+ package_json: ?*PackageJSON = null,
+ loader: Api.Loader,
+ hash: u32 = std.math.maxInt(u32),
+ globalThis: *JSC.JSGlobalObject = undefined,
+
+ // This is the specific state for making it async
+ poll_ref: JSC.PollRef = .{},
+
+ pub const Id = u32;
+ const debug = Output.scoped(.ModuleLoader, false);
+
+ const PackageDownloadError = struct {
+ name: []const u8,
+ resolution: Install.Resolution,
+ err: anyerror,
+ url: []const u8,
+ };
+
+ const PackageResolveError = struct {
+ name: []const u8,
+ err: anyerror,
+ url: []const u8,
+ version: Dependency.Version,
+ };
+
+ pub const Queue = struct {
+ map: Map = .{},
+ concurrent_task_count: std.atomic.Atomic(u32) = std.atomic.Atomic(u32).init(0),
+
+ const DeferredDependencyError = struct {
+ dependency: Dependency,
+ root_dependency_id: Install.PackageID,
+ err: anyerror,
+ };
+
+ pub const Map = std.ArrayListUnmanaged(AsyncModule);
+
+ pub fn enqueue(this: *Queue, globalObject: *JSC.JSGlobalObject, opts: anytype) void {
+ debug("enqueue: {s}", .{opts.specifier});
+ var module = AsyncModule.init(opts, globalObject) catch unreachable;
+ module.poll_ref.ref(this.vm());
+
+ this.map.append(this.vm().allocator, module) catch unreachable;
+ this.vm().packageManager().flushDependencyQueue();
+ _ = this.vm().packageManager().scheduleNetworkTasks();
+ }
+
+ pub fn onDependencyError(ctx: *anyopaque, dependency: Dependency, root_dependency_id: Install.PackageID, err: anyerror) void {
+ var this = bun.cast(*Queue, ctx);
+ debug("onDependencyError: {s}", .{this.vm().packageManager().lockfile.str(dependency.name)});
+
+ var modules: []AsyncModule = this.map.items;
+ var i: usize = 0;
+ outer: for (modules) |module_| {
+ var module = module_;
+ var root_dependency_ids = module.parse_result.pending_imports.items(.root_dependency_id);
+ for (root_dependency_ids) |dep, dep_i| {
+ if (dep != root_dependency_id) continue;
+ module.resolveError(
+ this.vm(),
+ module.parse_result.pending_imports.items(.import_record_id)[dep_i],
+ .{
+ .name = this.vm().packageManager().lockfile.str(dependency.name),
+ .err = err,
+ .url = "",
+ .version = dependency.version,
+ },
+ ) catch unreachable;
+ continue :outer;
+ }
+
+ modules[i] = module;
+ i += 1;
+ }
+ this.map.items.len = i;
+ }
+ pub fn onWakeHandler(ctx: *anyopaque, _: *PackageManager) void {
+ debug("onWake", .{});
+ var this = bun.cast(*Queue, ctx);
+ var concurrent_task = bun.default_allocator.create(JSC.ConcurrentTask) catch @panic("OOM");
+ concurrent_task.* = .{
+ .task = JSC.Task.init(this),
+ .auto_delete = true,
+ };
+ this.vm().enqueueTaskConcurrent(concurrent_task);
+ }
+
+ pub fn onPoll(this: *Queue) void {
+ debug("onPoll", .{});
+ var pm = this.vm().packageManager();
+
+ this.runTasks();
+ this.pollModules();
+ _ = pm.flushDependencyQueue();
+ _ = pm.scheduleNetworkTasks();
+ }
+
+ pub fn runTasks(this: *Queue) void {
+ var pm = this.vm().packageManager();
+
+ if (Output.enable_ansi_colors_stderr) {
+ pm.startProgressBarIfNone();
+ pm.runTasks(
+ *Queue,
+ this,
+ .{
+ .onExtract = onExtract,
+ .onResolve = onResolve,
+ .onPackageManifestError = onPackageManifestError,
+ .onPackageDownloadError = onPackageDownloadError,
+ .progress_bar = true,
+ },
+ PackageManager.Options.LogLevel.default,
+ ) catch unreachable;
+ } else {
+ pm.runTasks(
+ *Queue,
+ this,
+ .{
+ .onExtract = onExtract,
+ .onResolve = onResolve,
+ .onPackageManifestError = onPackageManifestError,
+ .onPackageDownloadError = onPackageDownloadError,
+ },
+ PackageManager.Options.LogLevel.default_no_progress,
+ ) catch unreachable;
+ }
+ }
+
+ pub fn onResolve(_: *Queue) void {
+ debug("onResolve", .{});
+ }
+
+ pub fn onPackageManifestError(
+ this: *Queue,
+ name: []const u8,
+ err: anyerror,
+ url: []const u8,
+ ) void {
+ debug("onPackageManifestError: {s}", .{name});
+
+ var modules: []AsyncModule = this.map.items;
+ var i: usize = 0;
+ outer: for (modules) |module_| {
+ var module = module_;
+ var tags = module.parse_result.pending_imports.items(.tag);
+ for (tags) |tag, tag_i| {
+ if (tag == .resolve) {
+ var esms = module.parse_result.pending_imports.items(.esm);
+ const esm = esms[tag_i];
+ var string_bufs = module.parse_result.pending_imports.items(.string_buf);
+
+ if (!strings.eql(esm.name.slice(string_bufs[tag_i]), name)) continue;
+
+ var versions = module.parse_result.pending_imports.items(.dependency);
+
+ module.resolveError(
+ this.vm(),
+ module.parse_result.pending_imports.items(.import_record_id)[tag_i],
+ .{
+ .name = name,
+ .err = err,
+ .url = url,
+ .version = versions[tag_i],
+ },
+ ) catch unreachable;
+ continue :outer;
+ }
+ }
+
+ modules[i] = module;
+ i += 1;
+ }
+ this.map.items.len = i;
+ }
+
+ pub fn onPackageDownloadError(
+ this: *Queue,
+ package_id: Install.PackageID,
+ name: []const u8,
+ resolution: Install.Resolution,
+ err: anyerror,
+ url: []const u8,
+ ) void {
+ debug("onPackageDownloadError: {s}", .{name});
+
+ var modules: []AsyncModule = this.map.items;
+ var i: usize = 0;
+ outer: for (modules) |module_| {
+ var module = module_;
+ var root_dependency_ids = module.parse_result.pending_imports.items(.root_dependency_id);
+ for (root_dependency_ids) |dep, dep_i| {
+ if (this.vm().packageManager().dynamicRootDependencies().items[dep].resolution_id != package_id) continue;
+ module.downloadError(
+ this.vm(),
+ module.parse_result.pending_imports.items(.import_record_id)[dep_i],
+ .{
+ .name = name,
+ .resolution = resolution,
+ .err = err,
+ .url = url,
+ },
+ ) catch unreachable;
+ continue :outer;
+ }
+
+ modules[i] = module;
+ i += 1;
+ }
+ this.map.items.len = i;
+ }
+
+ pub fn onExtract(this: *Queue, package_id: u32, comptime _: PackageManager.Options.LogLevel) void {
+ if (comptime Environment.allow_assert)
+ debug("onExtract: {s} ({d})", .{
+ this.vm().packageManager().lockfile.str(this.vm().packageManager().lockfile.packages.get(package_id).name),
+ package_id,
+ });
+ this.onPackageID(package_id);
+ }
+
+ pub fn onPackageID(this: *Queue, package_id: u32) void {
+ var values = this.map.items;
+ for (values) |value| {
+ var package_ids = value.parse_result.pending_imports.items(.resolution_id);
+
+ _ = package_id;
+ _ = package_ids;
+ }
+ }
+
+ pub fn pollModules(this: *Queue) void {
+ var pm = this.vm().packageManager();
+ var modules = this.map.items;
+ var i: usize = 0;
+ for (modules) |mod| {
+ var module = mod;
+ var tags = module.parse_result.pending_imports.items(.tag);
+ var root_dependency_ids = module.parse_result.pending_imports.items(.root_dependency_id);
+ // var esms = module.parse_result.pending_imports.items(.esm);
+ // var versions = module.parse_result.pending_imports.items(.dependency);
+ var done_count: usize = 0;
+ for (tags) |tag, tag_i| {
+ const root_id = root_dependency_ids[tag_i];
+ if (root_id == Install.invalid_package_id) continue;
+ const root_items = pm.dynamicRootDependencies().items;
+ if (root_items.len <= root_id) continue;
+ const package_id = root_items[root_id].resolution_id;
+
+ switch (tag) {
+ .resolve => {
+ if (package_id == Install.invalid_package_id) {
+ continue;
+ }
+
+ // if we get here, the package has already been resolved.
+ tags[tag_i] = .download;
+ },
+ .download => {
+ if (package_id == Install.invalid_package_id) {
+ unreachable;
+ }
+ },
+ .done => {
+ done_count += 1;
+ continue;
+ },
+ }
+
+ if (package_id == Install.invalid_package_id) {
+ continue;
+ }
+
+ const package = pm.lockfile.packages.get(package_id);
+ std.debug.assert(package.resolution.tag != .root);
+
+ switch (pm.determinePreinstallState(package, pm.lockfile)) {
+ .done => {
+ done_count += 1;
+ tags[tag_i] = .done;
+ },
+ .extracting => {
+ // we are extracting the package
+ // we need to wait for the next poll
+ continue;
+ },
+ .extract => {},
+ else => {},
+ }
+ }
+
+ if (done_count == tags.len) {
+ if (i + 1 >= modules.len) {
+ this.vm().packageManager().endProgressBar();
+ }
+ module.done(this.vm());
+ } else {
+ modules[i] = module;
+ i += 1;
+ }
+ }
+ this.map.items.len = i;
+ if (i == 0) {
+ // ensure we always end the progress bar
+ this.vm().packageManager().endProgressBar();
+ }
+ }
+
+ pub fn vm(this: *Queue) *VirtualMachine {
+ return @fieldParentPtr(VirtualMachine, "modules", this);
+ }
+ };
+
+ pub fn init(opts: anytype, globalObject: *JSC.JSGlobalObject) !AsyncModule {
+ var promise = JSC.Strong{};
+ var stmt_blocks = js_ast.Stmt.Data.Store.toOwnedSlice();
+ var expr_blocks = js_ast.Expr.Data.Store.toOwnedSlice();
+ const this_promise = JSValue.createInternalPromise(globalObject);
+ promise.set(globalObject, this_promise);
+
+ var buf = bun.StringBuilder{};
+ buf.count(opts.referrer);
+ buf.count(opts.specifier);
+ buf.count(opts.path.text);
+
+ try buf.allocate(bun.default_allocator);
+ opts.promise_ptr.?.* = this_promise.asInternalPromise().?;
+ const referrer = buf.append(opts.referrer);
+ const specifier = buf.append(opts.specifier);
+ const path = Fs.Path.init(buf.append(opts.path.text));
+
+ return AsyncModule{
+ .parse_result = opts.parse_result,
+ .promise = promise,
+ .path = path,
+ .specifier = specifier,
+ .referrer = referrer,
+ .fd = opts.fd,
+ .package_json = opts.package_json,
+ .loader = opts.loader.toAPI(),
+ .string_buf = buf.allocatedSlice(),
+ .stmt_blocks = stmt_blocks,
+ .globalThis = globalObject,
+ .expr_blocks = expr_blocks,
+ };
+ }
+
+ pub fn done(this: *AsyncModule, jsc_vm: *JSC.VirtualMachine) void {
+ var log = logger.Log.init(jsc_vm.allocator);
+ defer log.deinit();
+ var errorable: ErrorableResolvedSource = undefined;
+ this.poll_ref.unref(jsc_vm);
+ outer: {
+ errorable = ErrorableResolvedSource.ok(this.resumeLoadingModule(&log) catch |err| {
+ JSC.VirtualMachine.processFetchLog(
+ this.globalThis,
+ ZigString.init(this.specifier),
+ ZigString.init(this.referrer),
+ &log,
+ &errorable,
+ err,
+ );
+ break :outer;
+ });
+ }
+
+ var spec = ZigString.init(this.specifier).withEncoding();
+ var ref = ZigString.init(this.referrer).withEncoding();
+ Bun__onFulfillAsyncModule(
+ this.promise.get().?,
+ &errorable,
+ &spec,
+ &ref,
+ );
+ this.deinit();
+ }
+
+ pub fn resolveError(this: *AsyncModule, vm: *JSC.VirtualMachine, import_record_id: u32, result: PackageResolveError) !void {
+ var globalThis = this.globalThis;
+
+ var msg: []u8 = try switch (result.err) {
+ error.PackageManifestHTTP400 => std.fmt.allocPrint(
+ bun.default_allocator,
+ "HTTP 400 while resolving package '{s}' at '{s}'",
+ .{ result.name, result.url },
+ ),
+ error.PackageManifestHTTP401 => std.fmt.allocPrint(
+ bun.default_allocator,
+ "HTTP 401 while resolving package '{s}' at '{s}'",
+ .{ result.name, result.url },
+ ),
+ error.PackageManifestHTTP402 => std.fmt.allocPrint(
+ bun.default_allocator,
+ "HTTP 402 while resolving package '{s}' at '{s}'",
+ .{ result.name, result.url },
+ ),
+ error.PackageManifestHTTP403 => std.fmt.allocPrint(
+ bun.default_allocator,
+ "HTTP 403 while resolving package '{s}' at '{s}'",
+ .{ result.name, result.url },
+ ),
+ error.PackageManifestHTTP404 => std.fmt.allocPrint(
+ bun.default_allocator,
+ "Package '{s}' was not found",
+ .{result.name},
+ ),
+ error.PackageManifestHTTP4xx => std.fmt.allocPrint(
+ bun.default_allocator,
+ "HTTP 4xx while resolving package '{s}' at '{s}'",
+ .{ result.name, result.url },
+ ),
+ error.PackageManifestHTTP5xx => std.fmt.allocPrint(
+ bun.default_allocator,
+ "HTTP 5xx while resolving package '{s}' at '{s}'",
+ .{ result.name, result.url },
+ ),
+ error.DistTagNotFound, error.NoMatchingVersion => brk: {
+ const prefix: []const u8 = if (result.err == error.NoMatchingVersion and result.version.tag == .npm and result.version.value.npm.isExact())
+ "Version not found"
+ else if (result.version.tag == .npm and !result.version.value.npm.isExact())
+ "No matching version found"
+ else
+ "No match found";
+
+ break :brk std.fmt.allocPrint(
+ bun.default_allocator,
+ "{s} '{s}' for package '{s}' (but package exists)",
+ .{ prefix, vm.packageManager().lockfile.str(result.version.literal), result.name },
+ );
+ },
+ else => |err| std.fmt.allocPrint(
+ bun.default_allocator,
+ "{s} resolving package '{s}' at '{s}'",
+ .{ std.mem.span(@errorName(err)), result.name, result.url },
+ ),
+ };
+
+ const name: []const u8 = switch (result.err) {
+ error.NoMatchingVersion => "PackageVersionNotFound",
+ error.DistTagNotFound => "PackageTagNotFound",
+ error.PackageManifestHTTP403 => "PackageForbidden",
+ error.PackageManifestHTTP404 => "PackageNotFound",
+ else => "PackageResolveError",
+ };
+
+ var error_instance = ZigString.init(msg).withEncoding().toErrorInstance(globalThis);
+ if (result.url.len > 0)
+ error_instance.put(globalThis, ZigString.static("url"), ZigString.init(result.url).withEncoding().toValueGC(globalThis));
+ error_instance.put(globalThis, ZigString.static("name"), ZigString.init(name).withEncoding().toValueGC(globalThis));
+ error_instance.put(globalThis, ZigString.static("pkg"), ZigString.init(result.name).withEncoding().toValueGC(globalThis));
+ error_instance.put(globalThis, ZigString.static("specifier"), ZigString.init(this.specifier).withEncoding().toValueGC(globalThis));
+ const location = logger.rangeData(&this.parse_result.source, this.parse_result.ast.import_records[import_record_id].range, "").location.?;
+ error_instance.put(globalThis, ZigString.static("sourceURL"), ZigString.init(this.parse_result.source.path.text).withEncoding().toValueGC(globalThis));
+ error_instance.put(globalThis, ZigString.static("line"), JSValue.jsNumber(location.line));
+ if (location.line_text) |line_text| {
+ error_instance.put(globalThis, ZigString.static("lineText"), ZigString.init(line_text).withEncoding().toValueGC(globalThis));
+ }
+ error_instance.put(globalThis, ZigString.static("column"), JSValue.jsNumber(location.column));
+ if (this.referrer.len > 0 and !strings.eqlComptime(this.referrer, "undefined")) {
+ error_instance.put(globalThis, ZigString.static("referrer"), ZigString.init(this.referrer).withEncoding().toValueGC(globalThis));
+ }
+
+ const promise_value = this.promise.swap();
+ var promise = promise_value.asInternalPromise().?;
+ promise_value.ensureStillAlive();
+ this.poll_ref.unref(vm);
+ this.deinit();
+ promise.rejectAsHandled(globalThis, error_instance);
+ }
+ pub fn downloadError(this: *AsyncModule, vm: *JSC.VirtualMachine, import_record_id: u32, result: PackageDownloadError) !void {
+ var globalThis = this.globalThis;
+
+ const msg_args = .{
+ result.name,
+ result.resolution.fmt(vm.packageManager().lockfile.buffers.string_bytes.items),
+ };
+
+ var msg: []u8 = try switch (result.err) {
+ error.TarballHTTP400 => std.fmt.allocPrint(
+ bun.default_allocator,
+ "HTTP 400 downloading package '{s}@{any}'",
+ msg_args,
+ ),
+ error.TarballHTTP401 => std.fmt.allocPrint(
+ bun.default_allocator,
+ "HTTP 401 downloading package '{s}@{any}'",
+ msg_args,
+ ),
+ error.TarballHTTP402 => std.fmt.allocPrint(
+ bun.default_allocator,
+ "HTTP 402 downloading package '{s}@{any}'",
+ msg_args,
+ ),
+ error.TarballHTTP403 => std.fmt.allocPrint(
+ bun.default_allocator,
+ "HTTP 403 downloading package '{s}@{any}'",
+ msg_args,
+ ),
+ error.TarballHTTP404 => std.fmt.allocPrint(
+ bun.default_allocator,
+ "HTTP 404 downloading package '{s}@{any}'",
+ msg_args,
+ ),
+ error.TarballHTTP4xx => std.fmt.allocPrint(
+ bun.default_allocator,
+ "HTTP 4xx downloading package '{s}@{any}'",
+ msg_args,
+ ),
+ error.TarballHTTP5xx => std.fmt.allocPrint(
+ bun.default_allocator,
+ "HTTP 5xx downloading package '{s}@{any}'",
+ msg_args,
+ ),
+ error.TarballFailedToExtract => std.fmt.allocPrint(
+ bun.default_allocator,
+ "Failed to extract tarball for package '{s}@{any}'",
+ msg_args,
+ ),
+ else => |err| std.fmt.allocPrint(
+ bun.default_allocator,
+ "{s} downloading package '{s}@{any}'",
+ .{
+ std.mem.span(@errorName(err)), result.name,
+ result.resolution.fmt(vm.packageManager().lockfile.buffers.string_bytes.items),
+ },
+ ),
+ };
+
+ const name: []const u8 = switch (result.err) {
+ error.TarballFailedToExtract => "PackageExtractionError",
+ error.TarballHTTP403 => "TarballForbiddenError",
+ error.TarballHTTP404 => "TarballNotFoundError",
+ else => "TarballDownloadError",
+ };
+
+ var error_instance = ZigString.init(msg).withEncoding().toErrorInstance(globalThis);
+ if (result.url.len > 0)
+ error_instance.put(globalThis, ZigString.static("url"), ZigString.init(result.url).withEncoding().toValueGC(globalThis));
+ error_instance.put(globalThis, ZigString.static("name"), ZigString.init(name).withEncoding().toValueGC(globalThis));
+ error_instance.put(globalThis, ZigString.static("pkg"), ZigString.init(result.name).withEncoding().toValueGC(globalThis));
+ if (this.specifier.len > 0 and !strings.eqlComptime(this.specifier, "undefined")) {
+ error_instance.put(globalThis, ZigString.static("referrer"), ZigString.init(this.specifier).withEncoding().toValueGC(globalThis));
+ }
+
+ const location = logger.rangeData(&this.parse_result.source, this.parse_result.ast.import_records[import_record_id].range, "").location.?;
+ error_instance.put(globalThis, ZigString.static("specifier"), ZigString.init(
+ this.parse_result.ast.import_records[import_record_id].path.text,
+ ).withEncoding().toValueGC(globalThis));
+ error_instance.put(globalThis, ZigString.static("sourceURL"), ZigString.init(this.parse_result.source.path.text).withEncoding().toValueGC(globalThis));
+ error_instance.put(globalThis, ZigString.static("line"), JSValue.jsNumber(location.line));
+ if (location.line_text) |line_text| {
+ error_instance.put(globalThis, ZigString.static("lineText"), ZigString.init(line_text).withEncoding().toValueGC(globalThis));
+ }
+ error_instance.put(globalThis, ZigString.static("column"), JSValue.jsNumber(location.column));
+
+ const promise_value = this.promise.swap();
+ var promise = promise_value.asInternalPromise().?;
+ promise_value.ensureStillAlive();
+ this.poll_ref.unref(vm);
+ this.deinit();
+ promise.rejectAsHandled(globalThis, error_instance);
+ }
+
+ pub fn resumeLoadingModule(this: *AsyncModule, log: *logger.Log) !ResolvedSource {
+ debug("resumeLoadingModule: {s}", .{this.specifier});
+ var parse_result = this.parse_result;
+ var path = this.path;
+ var jsc_vm = JSC.VirtualMachine.vm;
+ var specifier = this.specifier;
+ var old_log = jsc_vm.log;
+
+ jsc_vm.bundler.linker.log = log;
+ jsc_vm.bundler.log = log;
+ jsc_vm.bundler.resolver.log = log;
+ jsc_vm.packageManager().log = log;
+ defer {
+ jsc_vm.bundler.linker.log = old_log;
+ jsc_vm.bundler.log = old_log;
+ jsc_vm.bundler.resolver.log = old_log;
+ jsc_vm.packageManager().log = old_log;
+ }
+
+ // 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,
+ );
+ this.parse_result = parse_result;
+
+ var printer = VirtualMachine.source_code_printer.?.*;
+ printer.ctx.reset();
+
+ const written = brk: {
+ defer VirtualMachine.source_code_printer.?.* = printer;
+ break :brk 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 (comptime Environment.dump_source) {
+ try dumpSource(specifier, &printer);
+ }
+
+ if (jsc_vm.isWatcherEnabled()) {
+ const resolved_source = jsc_vm.refCountedResolvedSource(printer.ctx.written, specifier, path.text, null);
+
+ if (parse_result.input_fd) |fd_| {
+ if (jsc_vm.bun_watcher != null and std.fs.path.isAbsolute(path.text) and !strings.contains(path.text, "node_modules")) {
+ jsc_vm.bun_watcher.?.addFile(
+ fd_,
+ path.text,
+ this.hash,
+ options.Loader.fromAPI(this.loader),
+ 0,
+ this.package_json,
+ true,
+ ) catch {};
+ }
+ }
+
+ return resolved_source;
+ }
+
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(try default_allocator.dupe(u8, printer.ctx.getWritten())),
+ .specifier = ZigString.init(specifier),
+ .source_url = ZigString.init(path.text),
+ // // TODO: change hash to a bitfield
+ // .hash = 1,
+
+ // having JSC own the memory causes crashes
+ .hash = 0,
+ };
+ }
+
+ pub fn deinit(this: *AsyncModule) void {
+ this.parse_result.deinit();
+ bun.default_allocator.free(this.stmt_blocks);
+ bun.default_allocator.free(this.expr_blocks);
+ this.promise.deinit();
+ bun.default_allocator.free(this.string_buf);
+ }
+
+ extern "C" fn Bun__onFulfillAsyncModule(
+ promiseValue: JSC.JSValue,
+ res: *JSC.ErrorableResolvedSource,
+ specifier: *ZigString,
+ referrer: *ZigString,
+ ) void;
+ };
+
+ pub export fn Bun__getDefaultLoader(global: *JSC.JSGlobalObject, str: *ZigString) Api.Loader {
+ var jsc_vm = global.bunVM();
+ const filename = str.toSlice(jsc_vm.allocator);
+ defer filename.deinit();
+ const loader = jsc_vm.bundler.options.loader(Fs.PathName.init(filename.slice()).ext).toAPI();
+ if (loader == .file) {
+ return Api.Loader.js;
+ }
+
+ return loader;
+ }
+
+ pub fn transpileSourceCode(
+ jsc_vm: *VirtualMachine,
+ specifier: string,
+ referrer: string,
+ path: Fs.Path,
+ loader: options.Loader,
+ log: *logger.Log,
+ virtual_source: ?*const logger.Source,
+ ret: *ErrorableResolvedSource,
+ promise_ptr: ?*?*JSC.JSInternalPromise,
+ source_code_printer: *js_printer.BufferPrinter,
+ globalObject: ?*JSC.JSGlobalObject,
+ comptime flags: FetchFlags,
+ ) !ResolvedSource {
+ const disable_transpilying = comptime flags.disableTranspiling();
+
+ 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.bun_dev_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];
+ }
+ } else if (jsc_vm.bun_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;
+ if (jsc_vm.bundler.resolver.package_manager) |pm| {
+ pm.log = log;
+ }
+
+ defer {
+ jsc_vm.bundler.log = old;
+ jsc_vm.bundler.linker.log = old;
+ jsc_vm.bundler.resolver.log = old;
+ if (jsc_vm.bundler.resolver.package_manager) |pm| {
+ pm.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,
+ .virtual_source = virtual_source,
+ .hoist_bun_plugin = true,
+ };
+
+ 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 (jsc_vm.bundler.log.errors > 0) {
+ return error.ParseError;
+ }
+
+ if (comptime disable_transpilying) {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = switch (comptime flags) {
+ .print_source_and_clone => ZigString.init(jsc_vm.allocator.dupe(u8, parse_result.source.contents) catch unreachable),
+ .print_source => ZigString.init(parse_result.source.contents),
+ else => unreachable,
+ },
+ .specifier = ZigString.init(specifier),
+ .source_url = ZigString.init(path.text),
+ .hash = 0,
+ };
+ }
+
+ const has_bun_plugin = parse_result.ast.bun_plugin.hoisted_stmts.items.len > 0;
+
+ if (has_bun_plugin) {
+ try ModuleLoader.runBunPlugin(jsc_vm, JSC.VirtualMachine.source_code_printer.?, &parse_result, ret);
+ }
+
+ 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 (parse_result.pending_imports.len > 0) {
+ if (promise_ptr == null) {
+ return error.UnexpectedPendingResolution;
+ }
+
+ if (jsc_vm.isWatcherEnabled()) {
+ if (parse_result.input_fd) |fd_| {
+ if (jsc_vm.bun_watcher != null and !is_node_override and std.fs.path.isAbsolute(path.text) and !strings.contains(path.text, "node_modules")) {
+ jsc_vm.bun_watcher.?.addFile(
+ fd_,
+ path.text,
+ hash,
+ loader,
+ 0,
+ package_json,
+ true,
+ ) catch {};
+ }
+ }
+ }
+
+ if (parse_result.source.contents_is_recycled) {
+ // this shared buffer is about to become owned by the AsyncModule struct
+ jsc_vm.bundler.resolver.caches.fs.resetSharedBuffer(
+ jsc_vm.bundler.resolver.caches.fs.sharedBuffer(),
+ );
+ }
+
+ jsc_vm.modules.enqueue(
+ globalObject.?,
+ .{
+ .parse_result = parse_result,
+ .path = path,
+ .loader = loader,
+ .fd = fd,
+ .package_json = package_json,
+ .hash = hash,
+ .promise_ptr = promise_ptr,
+ .specifier = specifier,
+ .referrer = referrer,
+ },
+ );
+ return error.AsyncModule;
+ }
+
+ 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.*;
+ printer.ctx.reset();
+
+ const written = brk: {
+ defer source_code_printer.* = printer;
+ break :brk try jsc_vm.bundler.printWithSourceMap(
+ parse_result,
+ @TypeOf(&printer),
+ &printer,
+ .esm_ascii,
+ SavedSourceMap.SourceMapHandler.init(&jsc_vm.source_mappings),
+ );
+ };
+
+ if (written == 0) {
+ // if it's an empty file but there were plugins
+ // we don't want it to break if you try to import from it
+ if (has_bun_plugin) {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init("// auto-generated plugin stub\nexport default undefined\n"),
+ .specifier = ZigString.init(specifier),
+ .source_url = ZigString.init(path.text),
+ // // TODO: change hash to a bitfield
+ // .hash = 1,
+
+ // having JSC own the memory causes crashes
+ .hash = 0,
+ };
+ }
+ return error.PrintingErrorWriteFailed;
+ }
+
+ if (comptime Environment.dump_source) {
+ try dumpSource(specifier, &printer);
+ }
+
+ if (jsc_vm.isWatcherEnabled()) {
+ const resolved_source = jsc_vm.refCountedResolvedSource(printer.ctx.written, specifier, path.text, null);
+
+ if (parse_result.input_fd) |fd_| {
+ if (jsc_vm.bun_watcher != null and !is_node_override and std.fs.path.isAbsolute(path.text) and !strings.contains(path.text, "node_modules")) {
+ jsc_vm.bun_watcher.?.addFile(
+ fd_,
+ path.text,
+ hash,
+ loader,
+ 0,
+ package_json,
+ true,
+ ) catch {};
+ }
+ }
+
+ return resolved_source;
+ }
+
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(try default_allocator.dupe(u8, printer.ctx.getWritten())),
+ .specifier = ZigString.init(specifier),
+ .source_url = ZigString.init(path.text),
+ // // TODO: change hash to a bitfield
+ // .hash = 1,
+
+ // having JSC own the memory causes crashes
+ .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 = &jsc_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 fn runBunPlugin(
+ jsc_vm: *VirtualMachine,
+ source_code_printer: *js_printer.BufferPrinter,
+ parse_result: *ParseResult,
+ ret: *ErrorableResolvedSource,
+ ) !void {
+ var printer = source_code_printer.*;
+ printer.ctx.reset();
+
+ defer printer.ctx.reset();
+ // If we start transpiling in the middle of an existing transpilation session
+ // we will hit undefined memory bugs
+ // unless we disable resetting the store until we are done transpiling
+ const prev_disable_reset = js_ast.Stmt.Data.Store.disable_reset;
+ js_ast.Stmt.Data.Store.disable_reset = true;
+ js_ast.Expr.Data.Store.disable_reset = true;
+
+ // flip the source code we use
+ // unless we're already transpiling a plugin
+ // that case could happen when
+ const was_printing_plugin = jsc_vm.is_printing_plugin;
+ const prev = jsc_vm.bundler.resolver.caches.fs.use_alternate_source_cache;
+ jsc_vm.is_printing_plugin = true;
+ defer {
+ js_ast.Stmt.Data.Store.disable_reset = prev_disable_reset;
+ js_ast.Expr.Data.Store.disable_reset = prev_disable_reset;
+ if (!was_printing_plugin) jsc_vm.bundler.resolver.caches.fs.use_alternate_source_cache = prev;
+ jsc_vm.is_printing_plugin = was_printing_plugin;
+ }
+ // we flip use_alternate_source_cache
+ if (!was_printing_plugin) jsc_vm.bundler.resolver.caches.fs.use_alternate_source_cache = !prev;
+
+ // this is a bad idea, but it should work for now.
+ const original_name = parse_result.ast.symbols[parse_result.ast.bun_plugin.ref.innerIndex()].original_name;
+ parse_result.ast.symbols[parse_result.ast.bun_plugin.ref.innerIndex()].original_name = "globalThis.Bun.plugin";
+ defer {
+ parse_result.ast.symbols[parse_result.ast.bun_plugin.ref.innerIndex()].original_name = original_name;
+ }
+ const hoisted_stmts = parse_result.ast.bun_plugin.hoisted_stmts.items;
+
+ var parts = [1]js_ast.Part{
+ js_ast.Part{
+ .stmts = hoisted_stmts,
+ },
+ };
+ var ast_copy = parse_result.ast;
+ ast_copy.import_records = try jsc_vm.allocator.dupe(ImportRecord, ast_copy.import_records);
+ defer jsc_vm.allocator.free(ast_copy.import_records);
+ ast_copy.parts = &parts;
+ ast_copy.prepend_part = null;
+ var temporary_source = parse_result.source;
+ var source_name = try std.fmt.allocPrint(jsc_vm.allocator, "{s}.plugin.{s}", .{ temporary_source.path.text, temporary_source.path.name.ext[1..] });
+ temporary_source.path = Fs.Path.init(source_name);
+
+ var temp_parse_result = parse_result.*;
+ temp_parse_result.ast = ast_copy;
+
+ try jsc_vm.bundler.linker.link(
+ temporary_source.path,
+ &temp_parse_result,
+ jsc_vm.origin,
+ .absolute_path,
+ false,
+ true,
+ );
+
+ _ = brk: {
+ defer source_code_printer.* = printer;
+ break :brk try jsc_vm.bundler.printWithSourceMapMaybe(
+ temp_parse_result.ast,
+ &temporary_source,
+ @TypeOf(&printer),
+ &printer,
+ .esm_ascii,
+ true,
+ SavedSourceMap.SourceMapHandler.init(&jsc_vm.source_mappings),
+ );
+ };
+ const wrote = printer.ctx.getWritten();
+
+ if (wrote.len > 0) {
+ if (comptime Environment.dump_source)
+ try dumpSource(temporary_source.path.text, &printer);
+
+ var exception = [1]JSC.JSValue{JSC.JSValue.zero};
+ const promise = JSC.JSModuleLoader.evaluate(
+ jsc_vm.global,
+ wrote.ptr,
+ wrote.len,
+ temporary_source.path.text.ptr,
+ temporary_source.path.text.len,
+ parse_result.source.path.text.ptr,
+ parse_result.source.path.text.len,
+ JSC.JSValue.jsUndefined(),
+ &exception,
+ );
+ if (!exception[0].isEmpty()) {
+ ret.* = JSC.ErrorableResolvedSource.err(
+ error.JSErrorObject,
+ exception[0].asVoid(),
+ );
+ return error.PluginError;
+ }
+
+ if (!promise.isEmptyOrUndefinedOrNull()) {
+ if (promise.asInternalPromise()) |promise_value| {
+ jsc_vm.waitForPromise(promise_value);
+
+ if (promise_value.status(jsc_vm.global.vm()) == .Rejected) {
+ ret.* = JSC.ErrorableResolvedSource.err(
+ error.JSErrorObject,
+ promise_value.result(jsc_vm.global.vm()).asVoid(),
+ );
+ return error.PluginError;
+ }
+ }
+ }
+ }
+ }
+ pub fn normalizeSpecifier(jsc_vm: *VirtualMachine, slice_: string) string {
+ var slice = slice_;
+ if (slice.len == 0) return slice;
+ var was_http = false;
+ if (strings.hasPrefixComptime(slice, "https://")) {
+ slice = slice["https://".len..];
+ was_http = true;
+ } else if (strings.hasPrefixComptime(slice, "http://")) {
+ slice = slice["http://".len..];
+ was_http = true;
+ }
+
+ if (strings.hasPrefix(slice, jsc_vm.origin.host)) {
+ slice = slice[jsc_vm.origin.host.len..];
+ } else if (was_http) {
+ if (strings.indexOfChar(slice, '/')) |i| {
+ slice = slice[i..];
+ }
+ }
+
+ if (jsc_vm.origin.path.len > 1) {
+ if (strings.hasPrefix(slice, jsc_vm.origin.path)) {
+ slice = slice[jsc_vm.origin.path.len..];
+ }
+ }
+
+ if (jsc_vm.bundler.options.routes.asset_prefix_path.len > 0) {
+ if (strings.hasPrefix(slice, jsc_vm.bundler.options.routes.asset_prefix_path)) {
+ slice = slice[jsc_vm.bundler.options.routes.asset_prefix_path.len..];
+ }
+ }
+
+ return slice;
+ }
+
+ pub export fn Bun__fetchBuiltinModule(
+ jsc_vm: *VirtualMachine,
+ globalObject: *JSC.JSGlobalObject,
+ specifier: *ZigString,
+ referrer: *ZigString,
+ ret: *ErrorableResolvedSource,
+ ) bool {
+ JSC.markBinding(@src());
+ var log = logger.Log.init(jsc_vm.bundler.allocator);
+ defer log.deinit();
+ if (ModuleLoader.fetchBuiltinModule(jsc_vm, specifier.slice(), &log, false) catch |err| {
+ if (err == error.AsyncModule) {
+ unreachable;
+ }
+ VirtualMachine.processFetchLog(globalObject, specifier.*, referrer.*, &log, ret, err);
+ return true;
+ }) |builtin| {
+ ret.* = ErrorableResolvedSource.ok(builtin);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ pub export fn Bun__transpileFile(
+ jsc_vm: *VirtualMachine,
+ globalObject: *JSC.JSGlobalObject,
+ specifier_ptr: *ZigString,
+ referrer: *ZigString,
+ ret: *ErrorableResolvedSource,
+ allow_promise: bool,
+ ) ?*anyopaque {
+ JSC.markBinding(@src());
+ var log = logger.Log.init(jsc_vm.bundler.allocator);
+ defer log.deinit();
+ var _specifier = specifier_ptr.toSlice(jsc_vm.allocator);
+ var referrer_slice = referrer.toSlice(jsc_vm.allocator);
+ defer _specifier.deinit();
+ defer referrer_slice.deinit();
+ var specifier = normalizeSpecifier(jsc_vm, _specifier.slice());
+ const path = Fs.Path.init(specifier);
+ const loader = jsc_vm.bundler.options.loaders.get(path.name.ext) orelse options.Loader.js;
+ var promise: ?*JSC.JSInternalPromise = null;
+ ret.* = ErrorableResolvedSource.ok(
+ ModuleLoader.transpileSourceCode(
+ jsc_vm,
+ specifier,
+ referrer_slice.slice(),
+ path,
+ loader,
+ &log,
+ null,
+ ret,
+ if (allow_promise) &promise else null,
+ VirtualMachine.source_code_printer.?,
+ globalObject,
+ FetchFlags.transpile,
+ ) catch |err| {
+ if (err == error.AsyncModule) {
+ std.debug.assert(promise != null);
+ return promise;
+ }
+
+ if (err == error.PluginError) {
+ return null;
+ }
+ VirtualMachine.processFetchLog(globalObject, specifier_ptr.*, referrer.*, &log, ret, err);
+ return null;
+ },
+ );
+ return promise;
+ }
+
+ export fn Bun__runVirtualModule(globalObject: *JSC.JSGlobalObject, specifier_ptr: *ZigString) JSValue {
+ JSC.markBinding(@src());
+ if (globalObject.bunVM().plugin_runner == null) return JSValue.zero;
+
+ const specifier = specifier_ptr.slice();
+
+ if (!PluginRunner.couldBePlugin(specifier)) {
+ return JSValue.zero;
+ }
+
+ const namespace = PluginRunner.extractNamespace(specifier);
+ const after_namespace = if (namespace.len == 0)
+ specifier
+ else
+ specifier[@minimum(namespace.len + 1, specifier.len)..];
+
+ return globalObject.runOnLoadPlugins(ZigString.init(namespace), ZigString.init(after_namespace), .bun) orelse return JSValue.zero;
+ }
+
+ const shared_library_suffix = if (Environment.isMac) "dylib" else if (Environment.isLinux) "so" else "";
+
+ pub fn fetchBuiltinModule(jsc_vm: *VirtualMachine, specifier: string, log: *logger.Log, comptime disable_transpilying: bool) !?ResolvedSource {
+ if (jsc_vm.node_modules != null and strings.eqlComptime(specifier, JSC.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(JSC.bun_file_import_path),
+ .source_url = ZigString.init(JSC.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(JSC.VirtualMachine.main_file_name)),
+ .source_url = ZigString.init(std.mem.span(JSC.VirtualMachine.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 = false;
+ opts.features.dynamic_require = 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 = JSC.VirtualMachine.source_code_printer.?.*;
+ var written: usize = undefined;
+ printer.ctx.reset();
+ {
+ defer JSC.VirtualMachine.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 (comptime Environment.dump_source)
+ try dumpSource(JSC.VirtualMachine.main_file_name, &printer);
+
+ 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(JSC.VirtualMachine.main_file_name)),
+ .source_url = ZigString.init(std.mem.span(JSC.VirtualMachine.main_file_name)),
+ .hash = 0,
+ };
+ },
+ .@"bun:jsc" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(jsModuleFromFile(jsc_vm.load_builtins_from_path, "bun-jsc.exports.js")),
+ .specifier = ZigString.init("bun:jsc"),
+ .source_url = ZigString.init("bun:jsc"),
+ .hash = 0,
+ };
+ },
+ .@"node:child_process" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(jsModuleFromFile(jsc_vm.load_builtins_from_path, "child_process.exports.js")),
+ .specifier = ZigString.init("node:child_process"),
+ .source_url = ZigString.init("node:child_process"),
+ .hash = 0,
+ };
+ },
+ .@"node:net" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(jsModuleFromFile(jsc_vm.load_builtins_from_path, "net.exports.js")),
+ .specifier = ZigString.init("node:net"),
+ .source_url = ZigString.init("node:net"),
+ .hash = 0,
+ };
+ },
+ .@"node:fs" => {
+ if (comptime Environment.isDebug) {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(strings.append(bun.default_allocator, jsModuleFromFile(jsc_vm.load_builtins_from_path, "fs.exports.js"), JSC.Node.fs.constants_string) catch unreachable),
+ .specifier = ZigString.init("node:fs"),
+ .source_url = ZigString.init("node:fs"),
+ .hash = 0,
+ };
+ }
+ 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:buffer" => return jsSyntheticModule(.@"node:buffer"),
+ .@"node:string_decoder" => return jsSyntheticModule(.@"node:string_decoder"),
+ .@"node:module" => return jsSyntheticModule(.@"node:module"),
+ .@"node:events" => return jsSyntheticModule(.@"node:events"),
+ .@"node:process" => return jsSyntheticModule(.@"node:process"),
+ .@"node:tty" => return jsSyntheticModule(.@"node:tty"),
+ .@"node:stream" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(jsModuleFromFile(jsc_vm.load_builtins_from_path, "streams.exports.js")),
+ .specifier = ZigString.init("node:stream"),
+ .source_url = ZigString.init("node:stream"),
+ .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(jsModuleFromFile(jsc_vm.load_builtins_from_path, "path.exports.js")),
+ .specifier = ZigString.init("node:path"),
+ .source_url = ZigString.init("node:path"),
+ .hash = 0,
+ };
+ },
+ .@"node:path/win32" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(jsModuleFromFile(jsc_vm.load_builtins_from_path, "path-win32.exports.js")),
+ .specifier = ZigString.init("node:path/win32"),
+ .source_url = ZigString.init("node:path/win32"),
+ .hash = 0,
+ };
+ },
+ .@"node:path/posix" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(jsModuleFromFile(jsc_vm.load_builtins_from_path, "path-posix.exports.js")),
+ .specifier = ZigString.init("node:path/posix"),
+ .source_url = ZigString.init("node:path/posix"),
+ .hash = 0,
+ };
+ },
+
+ .@"node:os" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(jsModuleFromFile(jsc_vm.load_builtins_from_path, "os.exports.js")),
+ .specifier = ZigString.init("node:os"),
+ .source_url = ZigString.init("node:os"),
+ .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,
+ };
+ },
+ .@"node:url" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, jsModuleFromFile(jsc_vm.load_builtins_from_path, "url.exports.js")),
+ ),
+ .specifier = ZigString.init("node:url"),
+ .source_url = ZigString.init("node:url"),
+ .hash = 0,
+ };
+ },
+ .@"node:assert" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, jsModuleFromFile(jsc_vm.load_builtins_from_path, "assert.exports.js")),
+ ),
+ .specifier = ZigString.init("node:assert"),
+ .source_url = ZigString.init("node:assert"),
+ .hash = 0,
+ };
+ },
+ .@"bun:sqlite" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, jsModuleFromFile(jsc_vm.load_builtins_from_path, "./bindings/sqlite/sqlite.exports.js")),
+ ),
+ .specifier = ZigString.init("bun:sqlite"),
+ .source_url = ZigString.init("bun:sqlite"),
+ .hash = 0,
+ };
+ },
+ .@"node:perf_hooks" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, jsModuleFromFile(jsc_vm.load_builtins_from_path, "./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, jsModuleFromFile(jsc_vm.load_builtins_from_path, "./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, jsModuleFromFile(jsc_vm.load_builtins_from_path, "./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, jsModuleFromFile(jsc_vm.load_builtins_from_path, "./node_timers_promises.exports.js")),
+ ),
+ .specifier = ZigString.init("node:timers/promises"),
+ .source_url = ZigString.init("node:timers/promises"),
+ .hash = 0,
+ };
+ },
+ .@"node:stream/web" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, jsModuleFromFile(jsc_vm.load_builtins_from_path, "./node_streams_web.exports.js")),
+ ),
+ .specifier = ZigString.init("node:stream/web"),
+ .source_url = ZigString.init("node:stream/web"),
+ .hash = 0,
+ };
+ },
+ .@"node:stream/consumer" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, jsModuleFromFile(jsc_vm.load_builtins_from_path, "./node_streams_consumer.exports.js")),
+ ),
+ .specifier = ZigString.init("node:stream/consumer"),
+ .source_url = ZigString.init("node:stream/consumer"),
+ .hash = 0,
+ };
+ },
+ .@"undici" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, jsModuleFromFile(jsc_vm.load_builtins_from_path, "./undici.exports.js")),
+ ),
+ .specifier = ZigString.init("undici"),
+ .source_url = ZigString.init("undici"),
+ .hash = 0,
+ };
+ },
+ .@"node:http" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, jsModuleFromFile(jsc_vm.load_builtins_from_path, "./http.exports.js")),
+ ),
+ .specifier = ZigString.init("node:http"),
+ .source_url = ZigString.init("node:http"),
+ .hash = 0,
+ };
+ },
+ .@"node:https" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, jsModuleFromFile(jsc_vm.load_builtins_from_path, "./https.exports.js")),
+ ),
+ .specifier = ZigString.init("node:https"),
+ .source_url = ZigString.init("node:https"),
+ .hash = 0,
+ };
+ },
+ .@"depd" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ @as(string, jsModuleFromFile(jsc_vm.load_builtins_from_path, "./depd.exports.js")),
+ ),
+ .specifier = ZigString.init("depd"),
+ .source_url = ZigString.init("depd"),
+ .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 (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,
+ };
+ }
+ }
+
+ return null;
+ }
+
+ export fn Bun__transpileVirtualModule(
+ globalObject: *JSC.JSGlobalObject,
+ specifier_ptr: *ZigString,
+ referrer_ptr: *ZigString,
+ source_code: *ZigString,
+ loader_: Api.Loader,
+ ret: *ErrorableResolvedSource,
+ ) bool {
+ JSC.markBinding(@src());
+ const jsc_vm = globalObject.bunVM();
+ std.debug.assert(jsc_vm.plugin_runner != null);
+
+ var specifier_slice = specifier_ptr.toSlice(jsc_vm.allocator);
+ const specifier = specifier_slice.slice();
+ defer specifier_slice.deinit();
+ var source_code_slice = source_code.toSlice(jsc_vm.allocator);
+ defer source_code_slice.deinit();
+ var referrer_slice = referrer_ptr.toSlice(jsc_vm.allocator);
+ defer referrer_slice.deinit();
+
+ var virtual_source = logger.Source.initPathString(specifier, source_code_slice.slice());
+ var log = logger.Log.init(jsc_vm.allocator);
+ const path = Fs.Path.init(specifier);
+
+ const loader = if (loader_ != ._none)
+ options.Loader.fromString(@tagName(loader_)).?
+ else
+ jsc_vm.bundler.options.loaders.get(path.name.ext) orelse brk: {
+ if (strings.eqlLong(specifier, jsc_vm.main, true)) {
+ break :brk options.Loader.js;
+ }
+
+ break :brk options.Loader.file;
+ };
+
+ defer log.deinit();
+ ret.* = ErrorableResolvedSource.ok(
+ ModuleLoader.transpileSourceCode(
+ jsc_vm,
+ specifier,
+ referrer_slice.slice(),
+ path,
+ options.Loader.fromString(@tagName(loader)).?,
+ &log,
+ &virtual_source,
+ ret,
+ null,
+ VirtualMachine.source_code_printer.?,
+ globalObject,
+ FetchFlags.transpile,
+ ) catch |err| {
+ if (err == error.PluginError) {
+ return true;
+ }
+ VirtualMachine.processFetchLog(globalObject, specifier_ptr.*, referrer_ptr.*, &log, ret, err);
+ return true;
+ },
+ );
+ return true;
+ }
+
+ comptime {
+ _ = Bun__transpileVirtualModule;
+ _ = Bun__runVirtualModule;
+ _ = Bun__transpileFile;
+ _ = Bun__fetchBuiltinModule;
+ _ = Bun__getDefaultLoader;
+ }
+};
+
+pub const FetchFlags = enum {
+ transpile,
+ print_source,
+ print_source_and_clone,
+
+ pub fn disableTranspiling(this: FetchFlags) bool {
+ return this != .transpile;
+ }
+};
+
+const SavedSourceMap = JSC.SavedSourceMap;
+
+pub const HardcodedModule = enum {
+ @"bun:ffi",
+ @"bun:jsc",
+ @"bun:main",
+ @"bun:sqlite",
+ @"depd",
+ @"detect-libc",
+ @"node:assert",
+ @"node:buffer",
+ @"node:child_process",
+ @"node:events",
+ @"node:fs",
+ @"node:fs/promises",
+ @"node:http",
+ @"node:https",
+ @"node:module",
+ @"node:net",
+ @"node:os",
+ @"node:path",
+ @"node:path/posix",
+ @"node:path/win32",
+ @"node:perf_hooks",
+ @"node:process",
+ @"node:stream",
+ @"node:stream/consumer",
+ @"node:stream/web",
+ @"node:string_decoder",
+ @"node:timers",
+ @"node:timers/promises",
+ @"node:tty",
+ @"node:url",
+ @"undici",
+ @"ws",
+ /// Already resolved modules go in here.
+ /// This does not remap the module name, it is just a hash table.
+ /// Do not put modules that have aliases in here
+ /// Put those in Aliases
+ pub const Map = bun.ComptimeStringMap(
+ HardcodedModule,
+ .{
+ .{ "buffer", HardcodedModule.@"node:buffer" },
+ .{ "bun:ffi", HardcodedModule.@"bun:ffi" },
+ .{ "bun:jsc", HardcodedModule.@"bun:jsc" },
+ .{ "bun:main", HardcodedModule.@"bun:main" },
+ .{ "bun:sqlite", HardcodedModule.@"bun:sqlite" },
+ .{ "depd", HardcodedModule.@"depd" },
+ .{ "detect-libc", HardcodedModule.@"detect-libc" },
+ .{ "node:assert", HardcodedModule.@"node:assert" },
+ .{ "node:buffer", HardcodedModule.@"node:buffer" },
+ .{ "node:child_process", HardcodedModule.@"node:child_process" },
+ .{ "node:events", HardcodedModule.@"node:events" },
+ .{ "node:fs", HardcodedModule.@"node:fs" },
+ .{ "node:fs/promises", HardcodedModule.@"node:fs/promises" },
+ .{ "node:http", HardcodedModule.@"node:http" },
+ .{ "node:https", HardcodedModule.@"node:https" },
+ .{ "node:module", HardcodedModule.@"node:module" },
+ .{ "node:net", HardcodedModule.@"node:net" },
+ .{ "node:os", HardcodedModule.@"node:os" },
+ .{ "node:path", HardcodedModule.@"node:path" },
+ .{ "node:path/posix", HardcodedModule.@"node:path/posix" },
+ .{ "node:path/win32", HardcodedModule.@"node:path/win32" },
+ .{ "node:perf_hooks", HardcodedModule.@"node:perf_hooks" },
+ .{ "node:process", HardcodedModule.@"node:process" },
+ .{ "node:stream", HardcodedModule.@"node:stream" },
+ .{ "node:stream/consumer", HardcodedModule.@"node:stream/consumer" },
+ .{ "node:stream/web", HardcodedModule.@"node:stream/web" },
+ .{ "node:string_decoder", HardcodedModule.@"node:string_decoder" },
+ .{ "node:timers", HardcodedModule.@"node:timers" },
+ .{ "node:timers/promises", HardcodedModule.@"node:timers/promises" },
+ .{ "node:tty", HardcodedModule.@"node:tty" },
+ .{ "node:url", HardcodedModule.@"node:url" },
+ .{ "undici", HardcodedModule.@"undici" },
+ .{ "ws", HardcodedModule.@"ws" },
+ },
+ );
+ pub const Aliases = bun.ComptimeStringMap(
+ string,
+ .{
+ .{ "assert", "node:assert" },
+ .{ "buffer", "node:buffer" },
+ .{ "bun", "bun" },
+ .{ "bun:ffi", "bun:ffi" },
+ .{ "bun:jsc", "bun:jsc" },
+ .{ "bun:sqlite", "bun:sqlite" },
+ .{ "bun:wrap", "bun:wrap" },
+ .{ "child_process", "node:child_process" },
+ .{ "depd", "depd" },
+ .{ "detect-libc", "detect-libc" },
+ .{ "detect-libc/lib/detect-libc.js", "detect-libc" },
+ .{ "events", "node:events" },
+ .{ "ffi", "bun:ffi" },
+ .{ "fs", "node:fs" },
+ .{ "fs/promises", "node:fs/promises" },
+ .{ "http", "node:http" },
+ .{ "https", "node:https" },
+ .{ "module", "node:module" },
+ .{ "net", "node:net" },
+ .{ "node:assert", "node:assert" },
+ .{ "node:buffer", "node:buffer" },
+ .{ "node:child_process", "node:child_process" },
+ .{ "node:events", "node:events" },
+ .{ "node:fs", "node:fs" },
+ .{ "node:fs/promises", "node:fs/promises" },
+ .{ "node:http", "node:http" },
+ .{ "node:https", "node:https" },
+ .{ "node:module", "node:module" },
+ .{ "node:net", "node:net" },
+ .{ "node:os", "node:os" },
+ .{ "node:path", "node:path" },
+ .{ "node:path/posix", "node:path/posix" },
+ .{ "node:path/win32", "node:path/win32" },
+ .{ "node:perf_hooks", "node:perf_hooks" },
+ .{ "node:process", "node:process" },
+ .{ "node:stream", "node:stream" },
+ .{ "node:stream/consumer", "node:stream/consumer" },
+ .{ "node:stream/web", "node:stream/web" },
+ .{ "node:string_decoder", "node:string_decoder" },
+ .{ "node:timers", "node:timers" },
+ .{ "node:timers/promises", "node:timers/promises" },
+ .{ "node:tty", "node:tty" },
+ .{ "node:url", "node:url" },
+ .{ "os", "node:os" },
+ .{ "path", "node:path" },
+ .{ "path/posix", "node:path/posix" },
+ .{ "path/win32", "node:path/win32" },
+ .{ "perf_hooks", "node:perf_hooks" },
+ .{ "process", "node:process" },
+ .{ "stream", "node:stream" },
+ .{ "stream/consumer", "node:stream/consumer" },
+ .{ "stream/web", "node:stream/web" },
+ .{ "string_decoder", "node:string_decoder" },
+ .{ "timers", "node:timers" },
+ .{ "timers/promises", "node:timers/promises" },
+ .{ "tty", "node:tty" },
+ .{ "undici", "undici" },
+ .{ "url", "node:url" },
+ .{ "ws", "ws" },
+ .{ "ws/lib/websocket", "ws" },
+ },
+ );
+};
+
+pub const DisabledModule = bun.ComptimeStringMap(
+ void,
+ .{
+ .{"node:tls"},
+ .{"node:worker_threads"},
+ .{"tls"},
+ .{"worker_threads"},
+ },
+);