aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/javascript.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/bun.js/javascript.zig')
-rw-r--r--src/bun.js/javascript.zig1387
1 files changed, 133 insertions, 1254 deletions
diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig
index 7a78db237..4068e9cfe 100644
--- a/src/bun.js/javascript.zig
+++ b/src/bun.js/javascript.zig
@@ -16,9 +16,6 @@ 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");
@@ -26,6 +23,7 @@ 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");
@@ -45,7 +43,6 @@ 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;
@@ -86,7 +83,13 @@ 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 ModuleLoader = JSC.ModuleLoader;
+const FetchFlags = JSC.FetchFlags;
+
pub const GlobalConstructors = [_]type{
JSC.Cloudflare.HTMLRewriter.Constructor,
};
@@ -126,7 +129,7 @@ pub fn OpaqueWrap(comptime Context: type, comptime Function: fn (this: *Context)
}.callback;
}
-const bun_file_import_path = "/node_modules.server.bun";
+pub const bun_file_import_path = "/node_modules.server.bun";
const SourceMap = @import("../sourcemap/sourcemap.zig");
const MappingList = SourceMap.Mapping.List;
@@ -346,6 +349,7 @@ pub const VirtualMachine = struct {
is_printing_plugin: bool = false,
plugin_runner: ?PluginRunner = null,
+ is_main_thread: bool = false,
/// Do not access this field directly
/// It exists in the VirtualMachine struct so that
@@ -404,9 +408,17 @@ pub const VirtualMachine = struct {
us_loop_reference_count: usize = 0,
is_us_loop_entered: bool = false,
pending_internal_promise: *JSC.JSInternalPromise = undefined,
-
+ auto_install_dependencies: bool = false,
load_builtins_from_path: []const u8 = "",
+ modules: ModuleLoader.AsyncModule.Queue = .{},
+
+ pub threadlocal var is_main_thread_vm: bool = false;
+
+ pub inline fn packageManager(this: *VirtualMachine) *PackageManager {
+ return this.bundler.getPackageManager();
+ }
+
pub fn reload(this: *VirtualMachine) void {
Output.debug("Reloading...", .{});
this.global.reload();
@@ -462,7 +474,7 @@ pub const VirtualMachine = struct {
this.eventLoop().enqueueTask(task);
}
- pub inline fn enqueueTaskConcurrent(this: *VirtualMachine, task: JSC.ConcurrentTask) void {
+ pub inline fn enqueueTaskConcurrent(this: *VirtualMachine, task: *JSC.ConcurrentTask) void {
this.eventLoop().enqueueTaskConcurrent(task);
}
@@ -627,6 +639,12 @@ pub const VirtualMachine = struct {
vm.bundler.macro_context = null;
+ VirtualMachine.vm.bundler.resolver.onWakePackageManager = .{
+ .context = &VirtualMachine.vm.modules,
+ .handler = ModuleLoader.AsyncModule.Queue.onWakeHandler,
+ .onDependencyError = JSC.ModuleLoader.AsyncModule.Queue.onDependencyError,
+ };
+
VirtualMachine.vm.bundler.configureLinker();
try VirtualMachine.vm.bundler.configureFramework(false);
@@ -742,422 +760,18 @@ pub const VirtualMachine = struct {
this.resolved_count = 0;
}
- 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, 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 = 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 = 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 (comptime Environment.dump_source)
- try dumpSource(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(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(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;
- }
-
pub fn fetchWithoutOnLoadPlugins(
jsc_vm: *VirtualMachine,
+ globalObject: *JSC.JSGlobalObject,
_specifier: string,
+ referrer: string,
log: *logger.Log,
ret: *ErrorableResolvedSource,
comptime flags: FetchFlags,
) !ResolvedSource {
std.debug.assert(VirtualMachine.vm_loaded);
- if (try fetchBuiltinModule(jsc_vm, _specifier, log, comptime flags.disableTranspiling())) |builtin| {
+ if (try ModuleLoader.fetchBuiltinModule(jsc_vm, _specifier, log, comptime flags.disableTranspiling())) |builtin| {
return builtin;
}
@@ -1174,12 +788,15 @@ pub const VirtualMachine = struct {
return try ModuleLoader.transpileSourceCode(
jsc_vm,
specifier,
+ referrer,
path,
loader,
log,
null,
ret,
+ null,
VirtualMachine.source_code_printer.?,
+ globalObject,
flags,
);
}
@@ -1221,7 +838,7 @@ pub const VirtualMachine = struct {
ret.result = null;
ret.path = specifier;
return;
- } else if (HardcodedModule.Map.get(specifier)) |result| {
+ } else if (JSC.HardcodedModule.Map.get(specifier)) |result| {
ret.result = null;
ret.path = @as(string, @tagName(result));
return;
@@ -1229,7 +846,7 @@ pub const VirtualMachine = struct {
const is_special_source = strings.eqlComptime(source, main_file_name) or js_ast.Macro.isMacroPath(source);
- const result = try jsc_vm.bundler.resolver.resolve(
+ const result = try switch (jsc_vm.bundler.resolver.resolveAndAutoInstall(
if (!is_special_source)
if (is_a_file_path)
Fs.PathName.init(source).dirWithTrailingSlash()
@@ -1240,7 +857,13 @@ pub const VirtualMachine = struct {
// TODO: do we need to handle things like query string params?
if (strings.hasPrefixComptime(specifier, "file://")) specifier["file://".len..] else specifier,
.stmt,
- );
+ .read_only,
+ )) {
+ .success => |r| r,
+ .failure => |e| e,
+ .not_found => error.ModuleNotFound,
+ .pending => unreachable,
+ };
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;
@@ -1339,30 +962,50 @@ pub const VirtualMachine = struct {
}
}
- if (HardcodedModule.Aliases.getWithEql(specifier, ZigString.eqlComptime)) |hardcoded| {
+ if (JSC.HardcodedModule.Aliases.getWithEql(specifier, ZigString.eqlComptime)) |hardcoded| {
res.* = ErrorableZigString.ok(ZigString.init(hardcoded));
return;
}
+ var old_log = jsc_vm.log;
+ var log = logger.Log.init(jsc_vm.allocator);
+ defer log.deinit();
+ jsc_vm.log = &log;
+ jsc_vm.bundler.resolver.log = &log;
+ jsc_vm.bundler.linker.log = &log;
+ defer {
+ jsc_vm.log = old_log;
+ jsc_vm.bundler.linker.log = old_log;
+ jsc_vm.bundler.resolver.log = old_log;
+ }
+ _resolve(&result, global, specifier.slice(), source.slice(), is_a_file_path, realpath) catch |err_| {
+ var err = err_;
+ const msg: logger.Msg = brk: {
+ var msgs: []logger.Msg = log.msgs.items;
+
+ for (msgs) |m| {
+ if (m.metadata == .resolve) {
+ err = m.metadata.resolve.err;
+ break :brk m;
+ }
+ }
- _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(
- jsc_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 },
- },
+ const printed = ResolveError.fmt(
+ jsc_vm.allocator,
+ specifier.slice(),
+ source.slice(),
+ err,
+ ) catch unreachable;
+ break :brk 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 },
+ },
+ };
};
{
@@ -1385,24 +1028,27 @@ pub const VirtualMachine = struct {
// return JSValue.jsUndefined();
// }
- const main_file_name: string = "bun:main";
+ pub 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();
- // threadlocal is cheaper in linux
var jsc_vm: *VirtualMachine = if (comptime Environment.isLinux)
vm
else
global.bunVM();
+ var log = logger.Log.init(vm.bundler.allocator);
+ var spec = specifier.toSlice(jsc_vm.allocator);
+ defer spec.deinit();
+ var refer = source.toSlice(jsc_vm.allocator);
+ defer refer.deinit();
+
const result = if (!jsc_vm.bundler.options.disable_transpilation)
- @call(.{ .modifier = .always_inline }, fetchWithoutOnLoadPlugins, .{ jsc_vm, spec, &log, ret, .transpile }) catch |err| {
+ @call(.{ .modifier = .always_inline }, fetchWithoutOnLoadPlugins, .{ jsc_vm, global, spec.slice(), refer.slice(), &log, ret, .transpile }) catch |err| {
processFetchLog(global, specifier, source, &log, ret, err);
return;
}
else
- fetchWithoutOnLoadPlugins(jsc_vm, spec, &log, ret, .print_source_and_clone) catch |err| {
+ fetchWithoutOnLoadPlugins(jsc_vm, global, spec.slice(), refer.slice(), &log, ret, .print_source_and_clone) catch |err| {
processFetchLog(global, specifier, source, &log, ret, err);
return;
};
@@ -1433,10 +1079,10 @@ pub const VirtualMachine = struct {
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..];
+ if (strings.hasPrefix(spec.slice(), VirtualMachine.vm.bundler.fs.top_level_dir)) {
+ break :brk spec.slice()[VirtualMachine.vm.bundler.fs.top_level_dir.len..];
}
- break :brk spec;
+ break :brk spec.slice();
};
if (vm.has_loaded) {
@@ -1893,7 +1539,7 @@ pub const VirtualMachine = struct {
)) |mapping| {
var log = logger.Log.init(default_allocator);
var errorable: ErrorableResolvedSource = undefined;
- var original_source = fetchWithoutOnLoadPlugins(this, top.source_url.slice(), &log, &errorable, .print_source) catch return;
+ var original_source = fetchWithoutOnLoadPlugins(this, this.global, top.source_url.slice(), "", &log, &errorable, .print_source) catch return;
const code = original_source.source_code.slice();
top.position.line = mapping.original.lines;
top.position.line_start = mapping.original.lines;
@@ -2052,6 +1698,35 @@ pub const VirtualMachine = struct {
.fd = exception.fd != -1,
};
+ const extra_fields = .{
+ "url",
+ "info",
+ "pkg",
+ };
+
+ if (error_instance.isCell()) {
+ inline for (extra_fields) |field| {
+ if (error_instance.get(this.global, field)) |value| {
+ if (!value.isEmptyOrUndefinedOrNull()) {
+ const kind = value.jsType();
+ if (kind.isStringLike()) {
+ if (value.toStringOrNull(this.global)) |str| {
+ var zig_str = str.toSlice(this.global, bun.default_allocator);
+ defer zig_str.deinit();
+ try writer.print(comptime Output.prettyFmt(" {s}<d>: <r>\"{s}\"<r>\n", allow_ansi_color), .{ field, zig_str.slice() });
+ add_extra_line = true;
+ }
+ } else if (kind.isObject() or kind.isArray()) {
+ var zig_str = ZigString.init("");
+ value.jsonStringify(this.global, 2, &zig_str);
+ try writer.print(comptime Output.prettyFmt(" {s}<d>: <r>{s}<r>\n", allow_ansi_color), .{ field, zig_str });
+ add_extra_line = true;
+ }
+ }
+ }
+ }
+ }
+
if (show.path) {
if (show.syscall) {
try writer.writeAll(" ");
@@ -2061,6 +1736,16 @@ pub const VirtualMachine = struct {
try writer.print(comptime Output.prettyFmt(" path<d>: <r><cyan>\"{s}\"<r>\n", allow_ansi_color), .{exception.path});
}
+ if (show.fd) {
+ if (show.syscall) {
+ try writer.writeAll(" ");
+ } else if (show.errno) {
+ try writer.writeAll(" ");
+ }
+
+ try writer.print(comptime Output.prettyFmt(" fd<d>: <r><cyan>\"{d}\"<r>\n", allow_ansi_color), .{exception.fd});
+ }
+
if (show.system_code) {
if (show.syscall) {
try writer.writeAll(" ");
@@ -2284,7 +1969,7 @@ pub const ResolveError = struct {
pub fn fmt(allocator: std.mem.Allocator, specifier: string, referrer: string, err: anyerror) !string {
switch (err) {
error.ModuleNotFound => {
- if (Resolver.isPackagePath(specifier)) {
+ if (Resolver.isPackagePath(specifier) and !strings.containsChar(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 });
@@ -2655,812 +2340,6 @@ pub const BuildError = struct {
pub const JSPrivateDataTag = JSPrivateDataPtr.Tag;
-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"},
- },
-);
-
-// 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 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,
- path: Fs.Path,
- loader: options.Loader,
- log: *logger.Log,
- virtual_source: ?*const logger.Source,
- ret: *ErrorableResolvedSource,
- source_code_printer: *js_printer.BufferPrinter,
- 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;
-
- 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,
- .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, source_code_printer, &parse_result, ret);
- }
-
- var printer = source_code_printer.*;
- printer.ctx.reset();
-
- 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;
-
- 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 (jsc_vm.fetchBuiltinModule(specifier.slice(), &log, false) catch |err| {
- 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,
- ) bool {
- JSC.markBinding(@src());
- var log = logger.Log.init(jsc_vm.bundler.allocator);
- defer log.deinit();
- var _specifier = specifier_ptr.toSlice(jsc_vm.allocator);
- defer _specifier.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 brk: {
- if (strings.eqlLong(specifier, jsc_vm.main, true)) {
- break :brk options.Loader.js;
- }
-
- break :brk options.Loader.file;
- };
- ret.* = ErrorableResolvedSource.ok(
- ModuleLoader.transpileSourceCode(
- jsc_vm,
- specifier,
- path,
- loader,
- &log,
- null,
- ret,
- VirtualMachine.source_code_printer.?,
- FetchFlags.transpile,
- ) catch |err| {
- if (err == error.PluginError) {
- return true;
- }
- VirtualMachine.processFetchLog(globalObject, specifier_ptr.*, referrer.*, &log, ret, err);
- return true;
- },
- );
- return true;
- }
-
- 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;
- }
-
- 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 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,
- path,
- options.Loader.fromString(@tagName(loader)).?,
- &log,
- &virtual_source,
- ret,
- VirtualMachine.source_code_printer.?,
- 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;
- }
-};
-
-const FetchFlags = enum {
- transpile,
- print_source,
- print_source_and_clone,
-
- pub fn disableTranspiling(this: FetchFlags) bool {
- return this != .transpile;
- }
-};
-
pub const Watcher = @import("../watcher.zig").NewWatcher(*HotReloader);
pub const HotReloader = struct {