diff options
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | src/api/schema.peechy | 1 | ||||
-rw-r--r-- | src/api/schema.zig | 2925 | ||||
-rw-r--r-- | src/bundler.zig | 573 | ||||
-rw-r--r-- | src/fs.zig | 16 | ||||
-rw-r--r-- | src/hash_map_v2.zig | 6 | ||||
-rw-r--r-- | src/import_record.zig | 2 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/bindings.zig | 2 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/exports.zig | 12 | ||||
-rw-r--r-- | src/javascript/jsc/javascript.zig | 30 | ||||
-rw-r--r-- | src/js_parser/js_parser.zig | 104 | ||||
-rw-r--r-- | src/js_printer.zig | 202 | ||||
-rw-r--r-- | src/linker.zig | 161 | ||||
-rw-r--r-- | src/node_module_bundle.zig | 2 | ||||
-rw-r--r-- | src/options.zig | 102 | ||||
-rw-r--r-- | src/panic_handler.zig | 2 | ||||
-rw-r--r-- | src/query_string_map.zig | 23 | ||||
-rw-r--r-- | src/resolver/package_json.zig | 55 | ||||
-rw-r--r-- | src/resolver/resolver.zig | 89 | ||||
-rw-r--r-- | src/runtime.js | 10 | ||||
-rw-r--r-- | src/runtime.version | 2 | ||||
-rw-r--r-- | src/string_immutable.zig | 16 | ||||
-rw-r--r-- | src/test/fixtures/browsermap-false.ts | 3 | ||||
-rw-r--r-- | src/test/fixtures/main-field.ts | 3 | ||||
-rw-r--r-- | src/test/fixtures/package.json | 7 | ||||
-rw-r--r-- | src/test/fixtures/type-only-import.ts | 33 | ||||
-rw-r--r-- | src/test/project.zig | 139 |
27 files changed, 2556 insertions, 1968 deletions
@@ -102,6 +102,10 @@ bun build ./routes --outdir=./out Unlike many other bundlers, `Bun` only bundles `node_modules`. This is great for development, where most people add/update packages much less frequently than app code (which is also great for caching in browsers). To make that distinction clear, the filename defaults to `node_modules.bun`. We recommend storing `node_modules.bun` in your git repository. Since it's a binary file, it shouldn't clutter your git history and it will make your entire frontend development team move faster if they don't have to re-bundle dependencies. +# Not implemented yet + + + # Building from source Estimated: 30-60 minutes :( diff --git a/src/api/schema.peechy b/src/api/schema.peechy index f296b6452..fd0b81fd2 100644 --- a/src/api/schema.peechy +++ b/src/api/schema.peechy @@ -90,7 +90,6 @@ struct JavascriptBundle { // generated by hashing all ${name}@${version} in sorted order byte[] app_package_json_dependencies_hash; - byte[] import_from_name; // This is what StringPointer refers to diff --git a/src/api/schema.zig b/src/api/schema.zig index 3e542b035..639eeae98 100644 --- a/src/api/schema.zig +++ b/src/api/schema.zig @@ -1,4 +1,3 @@ - const std = @import("std"); pub const Reader = struct { @@ -282,1872 +281,1762 @@ pub fn Writer(comptime WritableStream: type) type { pub const ByteWriter = Writer(*std.io.FixedBufferStream([]u8)); pub const FileWriter = Writer(std.fs.File); +pub const Api = struct { + pub const Loader = enum(u8) { + _none, + /// jsx + jsx, + /// js + js, + /// ts + ts, -pub const Api = struct { - -pub const Loader = enum(u8) { - -_none, - /// jsx - jsx, - - /// js - js, - - /// ts - ts, - - /// tsx - tsx, - - /// css - css, - - /// file - file, - - /// json - json, - -_, - - pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { - return try std.json.stringify(@tagName(self), opts, o); - } - - -}; - -pub const ResolveMode = enum(u8) { - -_none, - /// disable - disable, + /// tsx + tsx, - /// lazy - lazy, + /// css + css, - /// dev - dev, - - /// bundle - bundle, - -_, - - pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { - return try std.json.stringify(@tagName(self), opts, o); - } - - -}; - -pub const Platform = enum(u8) { - -_none, - /// browser - browser, - - /// node - node, - - /// bun - bun, - -_, - - pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { - return try std.json.stringify(@tagName(self), opts, o); - } - - -}; + /// file + file, -pub const CssInJsBehavior = enum(u8) { + /// json + json, -_none, - /// facade - facade, + _, - /// facade_onimportcss - facade_onimportcss, + pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { + return try std.json.stringify(@tagName(self), opts, o); + } + }; - /// auto_onimportcss - auto_onimportcss, + pub const ResolveMode = enum(u8) { + _none, + /// disable + disable, -_, + /// lazy + lazy, - pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { - return try std.json.stringify(@tagName(self), opts, o); - } + /// dev + dev, - -}; + /// bundle + bundle, -pub const JsxRuntime = enum(u8) { + _, -_none, - /// automatic - automatic, + pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { + return try std.json.stringify(@tagName(self), opts, o); + } + }; - /// classic - classic, + pub const Platform = enum(u8) { + _none, + /// browser + browser, -_, + /// node + node, - pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { - return try std.json.stringify(@tagName(self), opts, o); - } + /// bun + bun, - -}; + _, -pub const Jsx = struct { -/// factory -factory: []const u8, + pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { + return try std.json.stringify(@tagName(self), opts, o); + } + }; -/// runtime -runtime: JsxRuntime, + pub const CssInJsBehavior = enum(u8) { + _none, + /// facade + facade, -/// fragment -fragment: []const u8, + /// facade_onimportcss + facade_onimportcss, -/// development -development: bool = false, + /// auto_onimportcss + auto_onimportcss, -/// import_source -import_source: []const u8, + _, -/// react_fast_refresh -react_fast_refresh: bool = false, + pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { + return try std.json.stringify(@tagName(self), opts, o); + } + }; + pub const JsxRuntime = enum(u8) { + _none, + /// automatic + automatic, -pub fn decode(reader: anytype) anyerror!Jsx { - var this = std.mem.zeroes(Jsx); + /// classic + classic, - this.factory = try reader.readValue([]const u8); - this.runtime = try reader.readValue(JsxRuntime); - this.fragment = try reader.readValue([]const u8); - this.development = try reader.readValue(bool); - this.import_source = try reader.readValue([]const u8); - this.react_fast_refresh = try reader.readValue(bool); - return this; -} + _, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeValue(this.factory); - try writer.writeEnum(this.runtime); - try writer.writeValue(this.fragment); - try writer.writeInt(@intCast(u8, @boolToInt(this.development))); - try writer.writeValue(this.import_source); - try writer.writeInt(@intCast(u8, @boolToInt(this.react_fast_refresh))); -} + pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { + return try std.json.stringify(@tagName(self), opts, o); + } + }; -}; + pub const Jsx = struct { + /// factory + factory: []const u8, -pub const StringPointer = packed struct { -/// offset -offset: u32 = 0, + /// runtime + runtime: JsxRuntime, -/// length -length: u32 = 0, + /// fragment + fragment: []const u8, + /// development + development: bool = false, -pub fn decode(reader: anytype) anyerror!StringPointer { - var this = std.mem.zeroes(StringPointer); + /// import_source + import_source: []const u8, - this.offset = try reader.readValue(u32); - this.length = try reader.readValue(u32); - return this; -} + /// react_fast_refresh + react_fast_refresh: bool = false, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeInt(this.offset); - try writer.writeInt(this.length); -} + pub fn decode(reader: anytype) anyerror!Jsx { + var this = std.mem.zeroes(Jsx); -}; + this.factory = try reader.readValue([]const u8); + this.runtime = try reader.readValue(JsxRuntime); + this.fragment = try reader.readValue([]const u8); + this.development = try reader.readValue(bool); + this.import_source = try reader.readValue([]const u8); + this.react_fast_refresh = try reader.readValue(bool); + return this; + } -pub const JavascriptBundledModule = struct { -/// path -path: StringPointer, + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeValue(this.factory); + try writer.writeEnum(this.runtime); + try writer.writeValue(this.fragment); + try writer.writeInt(@intCast(u8, @boolToInt(this.development))); + try writer.writeValue(this.import_source); + try writer.writeInt(@intCast(u8, @boolToInt(this.react_fast_refresh))); + } + }; -/// code -code: StringPointer, + pub const StringPointer = packed struct { + /// offset + offset: u32 = 0, -/// package_id -package_id: u32 = 0, + /// length + length: u32 = 0, -/// id -id: u32 = 0, + pub fn decode(reader: anytype) anyerror!StringPointer { + var this = std.mem.zeroes(StringPointer); -/// path_extname_length -path_extname_length: u8 = 0, + this.offset = try reader.readValue(u32); + this.length = try reader.readValue(u32); + return this; + } + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeInt(this.offset); + try writer.writeInt(this.length); + } + }; -pub fn decode(reader: anytype) anyerror!JavascriptBundledModule { - var this = std.mem.zeroes(JavascriptBundledModule); + pub const JavascriptBundledModule = struct { + /// path + path: StringPointer, - this.path = try reader.readValue(StringPointer); - this.code = try reader.readValue(StringPointer); - this.package_id = try reader.readValue(u32); - this.id = try reader.readValue(u32); - this.path_extname_length = try reader.readValue(u8); - return this; -} + /// code + code: StringPointer, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeValue(this.path); - try writer.writeValue(this.code); - try writer.writeInt(this.package_id); - try writer.writeInt(this.id); - try writer.writeInt(this.path_extname_length); -} + /// package_id + package_id: u32 = 0, -}; + /// id + id: u32 = 0, -pub const JavascriptBundledPackage = struct { -/// name -name: StringPointer, + /// path_extname_length + path_extname_length: u8 = 0, -/// version -version: StringPointer, + pub fn decode(reader: anytype) anyerror!JavascriptBundledModule { + var this = std.mem.zeroes(JavascriptBundledModule); -/// hash -hash: u32 = 0, + this.path = try reader.readValue(StringPointer); + this.code = try reader.readValue(StringPointer); + this.package_id = try reader.readValue(u32); + this.id = try reader.readValue(u32); + this.path_extname_length = try reader.readValue(u8); + return this; + } -/// modules_offset -modules_offset: u32 = 0, + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeValue(this.path); + try writer.writeValue(this.code); + try writer.writeInt(this.package_id); + try writer.writeInt(this.id); + try writer.writeInt(this.path_extname_length); + } + }; -/// modules_length -modules_length: u32 = 0, + pub const JavascriptBundledPackage = struct { + /// name + name: StringPointer, + /// version + version: StringPointer, -pub fn decode(reader: anytype) anyerror!JavascriptBundledPackage { - var this = std.mem.zeroes(JavascriptBundledPackage); + /// hash + hash: u32 = 0, - this.name = try reader.readValue(StringPointer); - this.version = try reader.readValue(StringPointer); - this.hash = try reader.readValue(u32); - this.modules_offset = try reader.readValue(u32); - this.modules_length = try reader.readValue(u32); - return this; -} + /// modules_offset + modules_offset: u32 = 0, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeValue(this.name); - try writer.writeValue(this.version); - try writer.writeInt(this.hash); - try writer.writeInt(this.modules_offset); - try writer.writeInt(this.modules_length); -} + /// modules_length + modules_length: u32 = 0, -}; + pub fn decode(reader: anytype) anyerror!JavascriptBundledPackage { + var this = std.mem.zeroes(JavascriptBundledPackage); -pub const JavascriptBundle = struct { -/// modules -modules: []const JavascriptBundledModule, + this.name = try reader.readValue(StringPointer); + this.version = try reader.readValue(StringPointer); + this.hash = try reader.readValue(u32); + this.modules_offset = try reader.readValue(u32); + this.modules_length = try reader.readValue(u32); + return this; + } -/// packages -packages: []const JavascriptBundledPackage, + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeValue(this.name); + try writer.writeValue(this.version); + try writer.writeInt(this.hash); + try writer.writeInt(this.modules_offset); + try writer.writeInt(this.modules_length); + } + }; -/// etag -etag: []const u8, + pub const JavascriptBundle = struct { + /// modules + modules: []const JavascriptBundledModule, -/// generated_at -generated_at: u32 = 0, + /// packages + packages: []const JavascriptBundledPackage, -/// app_package_json_dependencies_hash -app_package_json_dependencies_hash: []const u8, + /// etag + etag: []const u8, -/// import_from_name -import_from_name: []const u8, + /// generated_at + generated_at: u32 = 0, -/// manifest_string -manifest_string: []const u8, + /// app_package_json_dependencies_hash + app_package_json_dependencies_hash: []const u8, + /// import_from_name + import_from_name: []const u8, -pub fn decode(reader: anytype) anyerror!JavascriptBundle { - var this = std.mem.zeroes(JavascriptBundle); + /// manifest_string + manifest_string: []const u8, - this.modules = try reader.readArray(JavascriptBundledModule); - this.packages = try reader.readArray(JavascriptBundledPackage); - this.etag = try reader.readArray(u8); - this.generated_at = try reader.readValue(u32); - this.app_package_json_dependencies_hash = try reader.readArray(u8); - this.import_from_name = try reader.readArray(u8); - this.manifest_string = try reader.readArray(u8); - return this; -} + pub fn decode(reader: anytype) anyerror!JavascriptBundle { + var this = std.mem.zeroes(JavascriptBundle); -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeArray(JavascriptBundledModule, this.modules); - try writer.writeArray(JavascriptBundledPackage, this.packages); - try writer.writeArray(u8, this.etag); - try writer.writeInt(this.generated_at); - try writer.writeArray(u8, this.app_package_json_dependencies_hash); - try writer.writeArray(u8, this.import_from_name); - try writer.writeArray(u8, this.manifest_string); -} + this.modules = try reader.readArray(JavascriptBundledModule); + this.packages = try reader.readArray(JavascriptBundledPackage); + this.etag = try reader.readArray(u8); + this.generated_at = try reader.readValue(u32); + this.app_package_json_dependencies_hash = try reader.readArray(u8); + this.import_from_name = try reader.readArray(u8); + this.manifest_string = try reader.readArray(u8); + return this; + } -}; + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeArray(JavascriptBundledModule, this.modules); + try writer.writeArray(JavascriptBundledPackage, this.packages); + try writer.writeArray(u8, this.etag); + try writer.writeInt(this.generated_at); + try writer.writeArray(u8, this.app_package_json_dependencies_hash); + try writer.writeArray(u8, this.import_from_name); + try writer.writeArray(u8, this.manifest_string); + } + }; -pub const JavascriptBundleContainer = struct { -/// bundle_format_version -bundle_format_version: ?u32 = null, - -/// routes -routes: ?LoadedRouteConfig = null, - -/// framework -framework: ?LoadedFramework = null, - -/// bundle -bundle: ?JavascriptBundle = null, - -/// code_length -code_length: ?u32 = null, - - -pub fn decode(reader: anytype) anyerror!JavascriptBundleContainer { - var this = std.mem.zeroes(JavascriptBundleContainer); - - while(true) { - switch (try reader.readByte()) { - 0 => { return this; }, - - 1 => { - this.bundle_format_version = try reader.readValue(u32); -}, - 2 => { - this.routes = try reader.readValue(LoadedRouteConfig); -}, - 3 => { - this.framework = try reader.readValue(LoadedFramework); -}, - 4 => { - this.bundle = try reader.readValue(JavascriptBundle); -}, - 5 => { - this.code_length = try reader.readValue(u32); -}, - else => { - return error.InvalidMessage; - }, - } - } -unreachable; -} + pub const JavascriptBundleContainer = struct { + /// bundle_format_version + bundle_format_version: ?u32 = null, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { -if (this.bundle_format_version) |bundle_format_version| { - try writer.writeFieldID(1); - try writer.writeInt(bundle_format_version); -} -if (this.routes) |routes| { - try writer.writeFieldID(2); - try writer.writeValue(routes); -} -if (this.framework) |framework| { - try writer.writeFieldID(3); - try writer.writeValue(framework); -} -if (this.bundle) |bundle| { - try writer.writeFieldID(4); - try writer.writeValue(bundle); -} -if (this.code_length) |code_length| { - try writer.writeFieldID(5); - try writer.writeInt(code_length); -} -try writer.endMessage(); -} + /// routes + routes: ?LoadedRouteConfig = null, -}; + /// framework + framework: ?LoadedFramework = null, -pub const ScanDependencyMode = enum(u8) { + /// bundle + bundle: ?JavascriptBundle = null, -_none, - /// app - app, + /// code_length + code_length: ?u32 = null, - /// all - all, + pub fn decode(reader: anytype) anyerror!JavascriptBundleContainer { + var this = std.mem.zeroes(JavascriptBundleContainer); -_, + while (true) { + switch (try reader.readByte()) { + 0 => { + return this; + }, - pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { - return try std.json.stringify(@tagName(self), opts, o); + 1 => { + this.bundle_format_version = try reader.readValue(u32); + }, + 2 => { + this.routes = try reader.readValue(LoadedRouteConfig); + }, + 3 => { + this.framework = try reader.readValue(LoadedFramework); + }, + 4 => { + this.bundle = try reader.readValue(JavascriptBundle); + }, + 5 => { + this.code_length = try reader.readValue(u32); + }, + else => { + return error.InvalidMessage; + }, } + } + unreachable; + } - -}; - -pub const ModuleImportType = enum(u8) { - -_none, - /// import - import, + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + if (this.bundle_format_version) |bundle_format_version| { + try writer.writeFieldID(1); + try writer.writeInt(bundle_format_version); + } + if (this.routes) |routes| { + try writer.writeFieldID(2); + try writer.writeValue(routes); + } + if (this.framework) |framework| { + try writer.writeFieldID(3); + try writer.writeValue(framework); + } + if (this.bundle) |bundle| { + try writer.writeFieldID(4); + try writer.writeValue(bundle); + } + if (this.code_length) |code_length| { + try writer.writeFieldID(5); + try writer.writeInt(code_length); + } + try writer.endMessage(); + } + }; - /// require - require, + pub const ScanDependencyMode = enum(u8) { + _none, + /// app + app, -_, + /// all + all, - pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { - return try std.json.stringify(@tagName(self), opts, o); - } + _, - -}; + pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { + return try std.json.stringify(@tagName(self), opts, o); + } + }; -pub const ModuleImportRecord = struct { -/// kind -kind: ModuleImportType, + pub const ModuleImportType = enum(u8) { + _none, + /// import + import, -/// path -path: []const u8, + /// require + require, -/// dynamic -dynamic: bool = false, + _, + pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { + return try std.json.stringify(@tagName(self), opts, o); + } + }; -pub fn decode(reader: anytype) anyerror!ModuleImportRecord { - var this = std.mem.zeroes(ModuleImportRecord); + pub const ModuleImportRecord = struct { + /// kind + kind: ModuleImportType, - this.kind = try reader.readValue(ModuleImportType); - this.path = try reader.readValue([]const u8); - this.dynamic = try reader.readValue(bool); - return this; -} + /// path + path: []const u8, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeEnum(this.kind); - try writer.writeValue(this.path); - try writer.writeInt(@intCast(u8, @boolToInt(this.dynamic))); -} + /// dynamic + dynamic: bool = false, -}; + pub fn decode(reader: anytype) anyerror!ModuleImportRecord { + var this = std.mem.zeroes(ModuleImportRecord); -pub const Module = struct { -/// path -path: []const u8, + this.kind = try reader.readValue(ModuleImportType); + this.path = try reader.readValue([]const u8); + this.dynamic = try reader.readValue(bool); + return this; + } -/// imports -imports: []const ModuleImportRecord, + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeEnum(this.kind); + try writer.writeValue(this.path); + try writer.writeInt(@intCast(u8, @boolToInt(this.dynamic))); + } + }; + pub const Module = struct { + /// path + path: []const u8, -pub fn decode(reader: anytype) anyerror!Module { - var this = std.mem.zeroes(Module); + /// imports + imports: []const ModuleImportRecord, - this.path = try reader.readValue([]const u8); - this.imports = try reader.readArray(ModuleImportRecord); - return this; -} + pub fn decode(reader: anytype) anyerror!Module { + var this = std.mem.zeroes(Module); -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeValue(this.path); - try writer.writeArray(ModuleImportRecord, this.imports); -} + this.path = try reader.readValue([]const u8); + this.imports = try reader.readArray(ModuleImportRecord); + return this; + } -}; + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeValue(this.path); + try writer.writeArray(ModuleImportRecord, this.imports); + } + }; -pub const StringMap = struct { -/// keys -keys: []const []const u8, + pub const StringMap = struct { + /// keys + keys: []const []const u8, -/// values -values: []const []const u8, + /// values + values: []const []const u8, + pub fn decode(reader: anytype) anyerror!StringMap { + var this = std.mem.zeroes(StringMap); -pub fn decode(reader: anytype) anyerror!StringMap { - var this = std.mem.zeroes(StringMap); + this.keys = try reader.readArray([]const u8); + this.values = try reader.readArray([]const u8); + return this; + } - this.keys = try reader.readArray([]const u8); - this.values = try reader.readArray([]const u8); - return this; -} + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeArray([]const u8, this.keys); + try writer.writeArray([]const u8, this.values); + } + }; -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeArray([]const u8, this.keys); - try writer.writeArray([]const u8, this.values); -} + pub const LoaderMap = struct { + /// extensions + extensions: []const []const u8, -}; + /// loaders + loaders: []const Loader, -pub const LoaderMap = struct { -/// extensions -extensions: []const []const u8, + pub fn decode(reader: anytype) anyerror!LoaderMap { + var this = std.mem.zeroes(LoaderMap); -/// loaders -loaders: []const Loader, + this.extensions = try reader.readArray([]const u8); + this.loaders = try reader.readArray(Loader); + return this; + } + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeArray([]const u8, this.extensions); + try writer.writeArray(Loader, this.loaders); + } + }; -pub fn decode(reader: anytype) anyerror!LoaderMap { - var this = std.mem.zeroes(LoaderMap); + pub const DotEnvBehavior = enum(u32) { + _none, + /// disable + disable, - this.extensions = try reader.readArray([]const u8); - this.loaders = try reader.readArray(Loader); - return this; -} + /// prefix + prefix, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeArray([]const u8, this.extensions); - try writer.writeArray(Loader, this.loaders); -} + /// load_all + load_all, -}; + _, -pub const DotEnvBehavior = enum(u32) { + pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { + return try std.json.stringify(@tagName(self), opts, o); + } + }; -_none, - /// disable - disable, + pub const EnvConfig = struct { + /// prefix + prefix: ?[]const u8 = null, - /// prefix - prefix, + /// defaults + defaults: ?StringMap = null, - /// load_all - load_all, + pub fn decode(reader: anytype) anyerror!EnvConfig { + var this = std.mem.zeroes(EnvConfig); -_, + while (true) { + switch (try reader.readByte()) { + 0 => { + return this; + }, - pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { - return try std.json.stringify(@tagName(self), opts, o); + 1 => { + this.prefix = try reader.readValue([]const u8); + }, + 2 => { + this.defaults = try reader.readValue(StringMap); + }, + else => { + return error.InvalidMessage; + }, } + } + unreachable; + } - -}; - -pub const EnvConfig = struct { -/// prefix -prefix: ?[]const u8 = null, - -/// defaults -defaults: ?StringMap = null, - - -pub fn decode(reader: anytype) anyerror!EnvConfig { - var this = std.mem.zeroes(EnvConfig); - - while(true) { - switch (try reader.readByte()) { - 0 => { return this; }, - - 1 => { - this.prefix = try reader.readValue([]const u8); -}, - 2 => { - this.defaults = try reader.readValue(StringMap); -}, - else => { - return error.InvalidMessage; - }, - } - } -unreachable; -} - -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { -if (this.prefix) |prefix| { - try writer.writeFieldID(1); - try writer.writeValue(prefix); -} -if (this.defaults) |defaults| { - try writer.writeFieldID(2); - try writer.writeValue(defaults); -} -try writer.endMessage(); -} - -}; - -pub const LoadedEnvConfig = struct { -/// dotenv -dotenv: DotEnvBehavior, - -/// defaults -defaults: StringMap, - -/// prefix -prefix: []const u8, - - -pub fn decode(reader: anytype) anyerror!LoadedEnvConfig { - var this = std.mem.zeroes(LoadedEnvConfig); - - this.dotenv = try reader.readValue(DotEnvBehavior); - this.defaults = try reader.readValue(StringMap); - this.prefix = try reader.readValue([]const u8); - return this; -} - -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeEnum(this.dotenv); - try writer.writeValue(this.defaults); - try writer.writeValue(this.prefix); -} - -}; - -pub const FrameworkConfig = struct { -/// package -package: ?[]const u8 = null, - -/// client -client: ?[]const u8 = null, - -/// server -server: ?[]const u8 = null, - -/// development -development: ?bool = null, - -/// client_env -client_env: ?EnvConfig = null, - -/// server_env -server_env: ?EnvConfig = null, - -/// client_css_in_js -client_css_in_js: ?CssInJsBehavior = null, - - -pub fn decode(reader: anytype) anyerror!FrameworkConfig { - var this = std.mem.zeroes(FrameworkConfig); - - while(true) { - switch (try reader.readByte()) { - 0 => { return this; }, - - 1 => { - this.package = try reader.readValue([]const u8); -}, - 2 => { - this.client = try reader.readValue([]const u8); -}, - 3 => { - this.server = try reader.readValue([]const u8); -}, - 4 => { - this.development = try reader.readValue(bool); -}, - 5 => { - this.client_env = try reader.readValue(EnvConfig); -}, - 6 => { - this.server_env = try reader.readValue(EnvConfig); -}, - 7 => { - this.client_css_in_js = try reader.readValue(CssInJsBehavior); -}, - else => { - return error.InvalidMessage; - }, - } - } -unreachable; -} - -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { -if (this.package) |package| { - try writer.writeFieldID(1); - try writer.writeValue(package); -} -if (this.client) |client| { - try writer.writeFieldID(2); - try writer.writeValue(client); -} -if (this.server) |server| { - try writer.writeFieldID(3); - try writer.writeValue(server); -} -if (this.development) |development| { - try writer.writeFieldID(4); - try writer.writeInt(@intCast(u8, @boolToInt(development))); -} -if (this.client_env) |client_env| { - try writer.writeFieldID(5); - try writer.writeValue(client_env); -} -if (this.server_env) |server_env| { - try writer.writeFieldID(6); - try writer.writeValue(server_env); -} -if (this.client_css_in_js) |client_css_in_js| { - try writer.writeFieldID(7); - try writer.writeEnum(client_css_in_js); -} -try writer.endMessage(); -} - -}; - -pub const LoadedFramework = struct { -/// entry_point -entry_point: []const u8, + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + if (this.prefix) |prefix| { + try writer.writeFieldID(1); + try writer.writeValue(prefix); + } + if (this.defaults) |defaults| { + try writer.writeFieldID(2); + try writer.writeValue(defaults); + } + try writer.endMessage(); + } + }; -/// package -package: []const u8, + pub const LoadedEnvConfig = struct { + /// dotenv + dotenv: DotEnvBehavior, -/// development -development: bool = false, + /// defaults + defaults: StringMap, -/// client -client: bool = false, + /// prefix + prefix: []const u8, -/// env -env: LoadedEnvConfig, + pub fn decode(reader: anytype) anyerror!LoadedEnvConfig { + var this = std.mem.zeroes(LoadedEnvConfig); -/// client_css_in_js -client_css_in_js: CssInJsBehavior, + this.dotenv = try reader.readValue(DotEnvBehavior); + this.defaults = try reader.readValue(StringMap); + this.prefix = try reader.readValue([]const u8); + return this; + } + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeEnum(this.dotenv); + try writer.writeValue(this.defaults); + try writer.writeValue(this.prefix); + } + }; -pub fn decode(reader: anytype) anyerror!LoadedFramework { - var this = std.mem.zeroes(LoadedFramework); + pub const FrameworkConfig = struct { + /// package + package: ?[]const u8 = null, - this.entry_point = try reader.readValue([]const u8); - this.package = try reader.readValue([]const u8); - this.development = try reader.readValue(bool); - this.client = try reader.readValue(bool); - this.env = try reader.readValue(LoadedEnvConfig); - this.client_css_in_js = try reader.readValue(CssInJsBehavior); - return this; -} + /// client + client: ?[]const u8 = null, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeValue(this.entry_point); - try writer.writeValue(this.package); - try writer.writeInt(@intCast(u8, @boolToInt(this.development))); - try writer.writeInt(@intCast(u8, @boolToInt(this.client))); - try writer.writeValue(this.env); - try writer.writeEnum(this.client_css_in_js); -} + /// server + server: ?[]const u8 = null, -}; + /// development + development: ?bool = null, -pub const LoadedRouteConfig = struct { -/// dir -dir: []const u8, + /// client_env + client_env: ?EnvConfig = null, -/// extensions -extensions: []const []const u8, + /// server_env + server_env: ?EnvConfig = null, -/// static_dir -static_dir: []const u8, + /// client_css_in_js + client_css_in_js: ?CssInJsBehavior = null, -/// asset_prefix -asset_prefix: []const u8, + pub fn decode(reader: anytype) anyerror!FrameworkConfig { + var this = std.mem.zeroes(FrameworkConfig); + while (true) { + switch (try reader.readByte()) { + 0 => { + return this; + }, -pub fn decode(reader: anytype) anyerror!LoadedRouteConfig { - var this = std.mem.zeroes(LoadedRouteConfig); + 1 => { + this.package = try reader.readValue([]const u8); + }, + 2 => { + this.client = try reader.readValue([]const u8); + }, + 3 => { + this.server = try reader.readValue([]const u8); + }, + 4 => { + this.development = try reader.readValue(bool); + }, + 5 => { + this.client_env = try reader.readValue(EnvConfig); + }, + 6 => { + this.server_env = try reader.readValue(EnvConfig); + }, + 7 => { + this.client_css_in_js = try reader.readValue(CssInJsBehavior); + }, + else => { + return error.InvalidMessage; + }, + } + } + unreachable; + } - this.dir = try reader.readValue([]const u8); - this.extensions = try reader.readArray([]const u8); - this.static_dir = try reader.readValue([]const u8); - this.asset_prefix = try reader.readValue([]const u8); - return this; -} + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + if (this.package) |package| { + try writer.writeFieldID(1); + try writer.writeValue(package); + } + if (this.client) |client| { + try writer.writeFieldID(2); + try writer.writeValue(client); + } + if (this.server) |server| { + try writer.writeFieldID(3); + try writer.writeValue(server); + } + if (this.development) |development| { + try writer.writeFieldID(4); + try writer.writeInt(@intCast(u8, @boolToInt(development))); + } + if (this.client_env) |client_env| { + try writer.writeFieldID(5); + try writer.writeValue(client_env); + } + if (this.server_env) |server_env| { + try writer.writeFieldID(6); + try writer.writeValue(server_env); + } + if (this.client_css_in_js) |client_css_in_js| { + try writer.writeFieldID(7); + try writer.writeEnum(client_css_in_js); + } + try writer.endMessage(); + } + }; -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeValue(this.dir); - try writer.writeArray([]const u8, this.extensions); - try writer.writeValue(this.static_dir); - try writer.writeValue(this.asset_prefix); -} + pub const LoadedFramework = struct { + /// entry_point + entry_point: []const u8, -}; + /// package + package: []const u8, -pub const RouteConfig = struct { -/// dir -dir: []const []const u8, - -/// extensions -extensions: []const []const u8, - -/// static_dir -static_dir: ?[]const u8 = null, - -/// asset_prefix -asset_prefix: ?[]const u8 = null, - - -pub fn decode(reader: anytype) anyerror!RouteConfig { - var this = std.mem.zeroes(RouteConfig); - - while(true) { - switch (try reader.readByte()) { - 0 => { return this; }, - - 1 => { - this.dir = try reader.readArray([]const u8); -}, - 2 => { - this.extensions = try reader.readArray([]const u8); -}, - 3 => { - this.static_dir = try reader.readValue([]const u8); -}, - 4 => { - this.asset_prefix = try reader.readValue([]const u8); -}, - else => { - return error.InvalidMessage; - }, - } - } -unreachable; -} + /// development + development: bool = false, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { -if (this.dir) |dir| { - try writer.writeFieldID(1); - try writer.writeArray([]const u8, dir); -} -if (this.extensions) |extensions| { - try writer.writeFieldID(2); - try writer.writeArray([]const u8, extensions); -} -if (this.static_dir) |static_dir| { - try writer.writeFieldID(3); - try writer.writeValue(static_dir); -} -if (this.asset_prefix) |asset_prefix| { - try writer.writeFieldID(4); - try writer.writeValue(asset_prefix); -} -try writer.endMessage(); -} + /// client + client: bool = false, -}; + /// env + env: LoadedEnvConfig, -pub const TransformOptions = struct { -/// jsx -jsx: ?Jsx = null, + /// client_css_in_js + client_css_in_js: CssInJsBehavior, -/// tsconfig_override -tsconfig_override: ?[]const u8 = null, + pub fn decode(reader: anytype) anyerror!LoadedFramework { + var this = std.mem.zeroes(LoadedFramework); -/// resolve -resolve: ?ResolveMode = null, + this.entry_point = try reader.readValue([]const u8); + this.package = try reader.readValue([]const u8); + this.development = try reader.readValue(bool); + this.client = try reader.readValue(bool); + this.env = try reader.readValue(LoadedEnvConfig); + this.client_css_in_js = try reader.readValue(CssInJsBehavior); + return this; + } -/// origin -origin: ?[]const u8 = null, - -/// absolute_working_dir -absolute_working_dir: ?[]const u8 = null, - -/// define -define: ?StringMap = null, - -/// preserve_symlinks -preserve_symlinks: ?bool = null, - -/// entry_points -entry_points: []const []const u8, - -/// write -write: ?bool = null, - -/// inject -inject: []const []const u8, - -/// output_dir -output_dir: ?[]const u8 = null, - -/// external -external: []const []const u8, - -/// loaders -loaders: ?LoaderMap = null, - -/// main_fields -main_fields: []const []const u8, - -/// platform -platform: ?Platform = null, - -/// serve -serve: ?bool = null, - -/// extension_order -extension_order: []const []const u8, - -/// generate_node_module_bundle -generate_node_module_bundle: ?bool = null, - -/// node_modules_bundle_path -node_modules_bundle_path: ?[]const u8 = null, - -/// node_modules_bundle_path_server -node_modules_bundle_path_server: ?[]const u8 = null, - -/// framework -framework: ?FrameworkConfig = null, - -/// router -router: ?RouteConfig = null, - -/// no_summary -no_summary: ?bool = null, - - -pub fn decode(reader: anytype) anyerror!TransformOptions { - var this = std.mem.zeroes(TransformOptions); - - while(true) { - switch (try reader.readByte()) { - 0 => { return this; }, - - 1 => { - this.jsx = try reader.readValue(Jsx); -}, - 2 => { - this.tsconfig_override = try reader.readValue([]const u8); -}, - 3 => { - this.resolve = try reader.readValue(ResolveMode); -}, - 4 => { - this.origin = try reader.readValue([]const u8); -}, - 5 => { - this.absolute_working_dir = try reader.readValue([]const u8); -}, - 6 => { - this.define = try reader.readValue(StringMap); -}, - 7 => { - this.preserve_symlinks = try reader.readValue(bool); -}, - 8 => { - this.entry_points = try reader.readArray([]const u8); -}, - 9 => { - this.write = try reader.readValue(bool); -}, - 10 => { - this.inject = try reader.readArray([]const u8); -}, - 11 => { - this.output_dir = try reader.readValue([]const u8); -}, - 12 => { - this.external = try reader.readArray([]const u8); -}, - 13 => { - this.loaders = try reader.readValue(LoaderMap); -}, - 14 => { - this.main_fields = try reader.readArray([]const u8); -}, - 15 => { - this.platform = try reader.readValue(Platform); -}, - 16 => { - this.serve = try reader.readValue(bool); -}, - 17 => { - this.extension_order = try reader.readArray([]const u8); -}, - 18 => { - this.generate_node_module_bundle = try reader.readValue(bool); -}, - 19 => { - this.node_modules_bundle_path = try reader.readValue([]const u8); -}, - 20 => { - this.node_modules_bundle_path_server = try reader.readValue([]const u8); -}, - 21 => { - this.framework = try reader.readValue(FrameworkConfig); -}, - 22 => { - this.router = try reader.readValue(RouteConfig); -}, - 23 => { - this.no_summary = try reader.readValue(bool); -}, - else => { - return error.InvalidMessage; - }, - } - } -unreachable; -} + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeValue(this.entry_point); + try writer.writeValue(this.package); + try writer.writeInt(@intCast(u8, @boolToInt(this.development))); + try writer.writeInt(@intCast(u8, @boolToInt(this.client))); + try writer.writeValue(this.env); + try writer.writeEnum(this.client_css_in_js); + } + }; -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { -if (this.jsx) |jsx| { - try writer.writeFieldID(1); - try writer.writeValue(jsx); -} -if (this.tsconfig_override) |tsconfig_override| { - try writer.writeFieldID(2); - try writer.writeValue(tsconfig_override); -} -if (this.resolve) |resolve| { - try writer.writeFieldID(3); - try writer.writeEnum(resolve); -} -if (this.origin) |origin| { - try writer.writeFieldID(4); - try writer.writeValue(origin); -} -if (this.absolute_working_dir) |absolute_working_dir| { - try writer.writeFieldID(5); - try writer.writeValue(absolute_working_dir); -} -if (this.define) |define| { - try writer.writeFieldID(6); - try writer.writeValue(define); -} -if (this.preserve_symlinks) |preserve_symlinks| { - try writer.writeFieldID(7); - try writer.writeInt(@intCast(u8, @boolToInt(preserve_symlinks))); -} -if (this.entry_points) |entry_points| { - try writer.writeFieldID(8); - try writer.writeArray([]const u8, entry_points); -} -if (this.write) |write| { - try writer.writeFieldID(9); - try writer.writeInt(@intCast(u8, @boolToInt(write))); -} -if (this.inject) |inject| { - try writer.writeFieldID(10); - try writer.writeArray([]const u8, inject); -} -if (this.output_dir) |output_dir| { - try writer.writeFieldID(11); - try writer.writeValue(output_dir); -} -if (this.external) |external| { - try writer.writeFieldID(12); - try writer.writeArray([]const u8, external); -} -if (this.loaders) |loaders| { - try writer.writeFieldID(13); - try writer.writeValue(loaders); -} -if (this.main_fields) |main_fields| { - try writer.writeFieldID(14); - try writer.writeArray([]const u8, main_fields); -} -if (this.platform) |platform| { - try writer.writeFieldID(15); - try writer.writeEnum(platform); -} -if (this.serve) |serve| { - try writer.writeFieldID(16); - try writer.writeInt(@intCast(u8, @boolToInt(serve))); -} -if (this.extension_order) |extension_order| { - try writer.writeFieldID(17); - try writer.writeArray([]const u8, extension_order); -} -if (this.generate_node_module_bundle) |generate_node_module_bundle| { - try writer.writeFieldID(18); - try writer.writeInt(@intCast(u8, @boolToInt(generate_node_module_bundle))); -} -if (this.node_modules_bundle_path) |node_modules_bundle_path| { - try writer.writeFieldID(19); - try writer.writeValue(node_modules_bundle_path); -} -if (this.node_modules_bundle_path_server) |node_modules_bundle_path_server| { - try writer.writeFieldID(20); - try writer.writeValue(node_modules_bundle_path_server); -} -if (this.framework) |framework| { - try writer.writeFieldID(21); - try writer.writeValue(framework); -} -if (this.router) |router| { - try writer.writeFieldID(22); - try writer.writeValue(router); -} -if (this.no_summary) |no_summary| { - try writer.writeFieldID(23); - try writer.writeInt(@intCast(u8, @boolToInt(no_summary))); -} -try writer.endMessage(); -} + pub const LoadedRouteConfig = struct { + /// dir + dir: []const u8, -}; + /// extensions + extensions: []const []const u8, -pub const FileHandle = struct { -/// path -path: []const u8, + /// static_dir + static_dir: []const u8, -/// size -size: u32 = 0, + /// asset_prefix + asset_prefix: []const u8, -/// fd -fd: u32 = 0, + pub fn decode(reader: anytype) anyerror!LoadedRouteConfig { + var this = std.mem.zeroes(LoadedRouteConfig); + this.dir = try reader.readValue([]const u8); + this.extensions = try reader.readArray([]const u8); + this.static_dir = try reader.readValue([]const u8); + this.asset_prefix = try reader.readValue([]const u8); + return this; + } -pub fn decode(reader: anytype) anyerror!FileHandle { - var this = std.mem.zeroes(FileHandle); + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeValue(this.dir); + try writer.writeArray([]const u8, this.extensions); + try writer.writeValue(this.static_dir); + try writer.writeValue(this.asset_prefix); + } + }; - this.path = try reader.readValue([]const u8); - this.size = try reader.readValue(u32); - this.fd = try reader.readValue(u32); - return this; -} + pub const RouteConfig = struct { + /// dir + dir: []const []const u8, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeValue(this.path); - try writer.writeInt(this.size); - try writer.writeInt(this.fd); -} + /// extensions + extensions: []const []const u8, -}; + /// static_dir + static_dir: ?[]const u8 = null, -pub const Transform = struct { -/// handle -handle: ?FileHandle = null, - -/// path -path: ?[]const u8 = null, - -/// contents -contents: []const u8, - -/// loader -loader: ?Loader = null, - -/// options -options: ?TransformOptions = null, - - -pub fn decode(reader: anytype) anyerror!Transform { - var this = std.mem.zeroes(Transform); - - while(true) { - switch (try reader.readByte()) { - 0 => { return this; }, - - 1 => { - this.handle = try reader.readValue(FileHandle); -}, - 2 => { - this.path = try reader.readValue([]const u8); -}, - 3 => { - this.contents = try reader.readArray(u8); -}, - 4 => { - this.loader = try reader.readValue(Loader); -}, - 5 => { - this.options = try reader.readValue(TransformOptions); -}, - else => { - return error.InvalidMessage; - }, - } - } -unreachable; -} + /// asset_prefix + asset_prefix: ?[]const u8 = null, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { -if (this.handle) |handle| { - try writer.writeFieldID(1); - try writer.writeValue(handle); -} -if (this.path) |path| { - try writer.writeFieldID(2); - try writer.writeValue(path); -} -if (this.contents) |contents| { - try writer.writeFieldID(3); - try writer.writeArray(u8, contents); -} -if (this.loader) |loader| { - try writer.writeFieldID(4); - try writer.writeEnum(loader); -} -if (this.options) |options| { - try writer.writeFieldID(5); - try writer.writeValue(options); -} -try writer.endMessage(); -} + pub fn decode(reader: anytype) anyerror!RouteConfig { + var this = std.mem.zeroes(RouteConfig); -}; + while (true) { + switch (try reader.readByte()) { + 0 => { + return this; + }, -pub const TransformResponseStatus = enum(u32) { + 1 => { + this.dir = try reader.readArray([]const u8); + }, + 2 => { + this.extensions = try reader.readArray([]const u8); + }, + 3 => { + this.static_dir = try reader.readValue([]const u8); + }, + 4 => { + this.asset_prefix = try reader.readValue([]const u8); + }, + else => { + return error.InvalidMessage; + }, + } + } + unreachable; + } -_none, - /// success - success, + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + if (this.dir) |dir| { + try writer.writeFieldID(1); + try writer.writeArray([]const u8, dir); + } + if (this.extensions) |extensions| { + try writer.writeFieldID(2); + try writer.writeArray([]const u8, extensions); + } + if (this.static_dir) |static_dir| { + try writer.writeFieldID(3); + try writer.writeValue(static_dir); + } + if (this.asset_prefix) |asset_prefix| { + try writer.writeFieldID(4); + try writer.writeValue(asset_prefix); + } + try writer.endMessage(); + } + }; - /// fail - fail, + pub const TransformOptions = struct { + /// jsx + jsx: ?Jsx = null, -_, + /// tsconfig_override + tsconfig_override: ?[]const u8 = null, - pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { - return try std.json.stringify(@tagName(self), opts, o); - } + /// resolve + resolve: ?ResolveMode = null, - -}; + /// origin + origin: ?[]const u8 = null, -pub const OutputFile = struct { -/// data -data: []const u8, + /// absolute_working_dir + absolute_working_dir: ?[]const u8 = null, -/// path -path: []const u8, + /// define + define: ?StringMap = null, + /// preserve_symlinks + preserve_symlinks: ?bool = null, -pub fn decode(reader: anytype) anyerror!OutputFile { - var this = std.mem.zeroes(OutputFile); + /// entry_points + entry_points: []const []const u8, - this.data = try reader.readArray(u8); - this.path = try reader.readValue([]const u8); - return this; -} + /// write + write: ?bool = null, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeArray(u8, this.data); - try writer.writeValue(this.path); -} + /// inject + inject: []const []const u8, -}; + /// output_dir + output_dir: ?[]const u8 = null, -pub const TransformResponse = struct { -/// status -status: TransformResponseStatus, + /// external + external: []const []const u8, -/// files -files: []const OutputFile, + /// loaders + loaders: ?LoaderMap = null, -/// errors -errors: []const Message, + /// main_fields + main_fields: []const []const u8, + /// platform + platform: ?Platform = null, -pub fn decode(reader: anytype) anyerror!TransformResponse { - var this = std.mem.zeroes(TransformResponse); + /// serve + serve: ?bool = null, - this.status = try reader.readValue(TransformResponseStatus); - this.files = try reader.readArray(OutputFile); - this.errors = try reader.readArray(Message); - return this; -} + /// extension_order + extension_order: []const []const u8, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeEnum(this.status); - try writer.writeArray(OutputFile, this.files); - try writer.writeArray(Message, this.errors); -} + /// generate_node_module_bundle + generate_node_module_bundle: ?bool = null, -}; + /// node_modules_bundle_path + node_modules_bundle_path: ?[]const u8 = null, -pub const MessageKind = enum(u32) { + /// node_modules_bundle_path_server + node_modules_bundle_path_server: ?[]const u8 = null, -_none, - /// err - err, + /// framework + framework: ?FrameworkConfig = null, - /// warn - warn, + /// router + router: ?RouteConfig = null, - /// note - note, + /// no_summary + no_summary: ?bool = null, - /// debug - debug, + pub fn decode(reader: anytype) anyerror!TransformOptions { + var this = std.mem.zeroes(TransformOptions); -_, + while (true) { + switch (try reader.readByte()) { + 0 => { + return this; + }, - pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { - return try std.json.stringify(@tagName(self), opts, o); + 1 => { + this.jsx = try reader.readValue(Jsx); + }, + 2 => { + this.tsconfig_override = try reader.readValue([]const u8); + }, + 3 => { + this.resolve = try reader.readValue(ResolveMode); + }, + 4 => { + this.origin = try reader.readValue([]const u8); + }, + 5 => { + this.absolute_working_dir = try reader.readValue([]const u8); + }, + 6 => { + this.define = try reader.readValue(StringMap); + }, + 7 => { + this.preserve_symlinks = try reader.readValue(bool); + }, + 8 => { + this.entry_points = try reader.readArray([]const u8); + }, + 9 => { + this.write = try reader.readValue(bool); + }, + 10 => { + this.inject = try reader.readArray([]const u8); + }, + 11 => { + this.output_dir = try reader.readValue([]const u8); + }, + 12 => { + this.external = try reader.readArray([]const u8); + }, + 13 => { + this.loaders = try reader.readValue(LoaderMap); + }, + 14 => { + this.main_fields = try reader.readArray([]const u8); + }, + 15 => { + this.platform = try reader.readValue(Platform); + }, + 16 => { + this.serve = try reader.readValue(bool); + }, + 17 => { + this.extension_order = try reader.readArray([]const u8); + }, + 18 => { + this.generate_node_module_bundle = try reader.readValue(bool); + }, + 19 => { + this.node_modules_bundle_path = try reader.readValue([]const u8); + }, + 20 => { + this.node_modules_bundle_path_server = try reader.readValue([]const u8); + }, + 21 => { + this.framework = try reader.readValue(FrameworkConfig); + }, + 22 => { + this.router = try reader.readValue(RouteConfig); + }, + 23 => { + this.no_summary = try reader.readValue(bool); + }, + else => { + return error.InvalidMessage; + }, } + } + unreachable; + } - -}; - -pub const Location = struct { -/// file -file: []const u8, - -/// namespace -namespace: []const u8, + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + if (this.jsx) |jsx| { + try writer.writeFieldID(1); + try writer.writeValue(jsx); + } + if (this.tsconfig_override) |tsconfig_override| { + try writer.writeFieldID(2); + try writer.writeValue(tsconfig_override); + } + if (this.resolve) |resolve| { + try writer.writeFieldID(3); + try writer.writeEnum(resolve); + } + if (this.origin) |origin| { + try writer.writeFieldID(4); + try writer.writeValue(origin); + } + if (this.absolute_working_dir) |absolute_working_dir| { + try writer.writeFieldID(5); + try writer.writeValue(absolute_working_dir); + } + if (this.define) |define| { + try writer.writeFieldID(6); + try writer.writeValue(define); + } + if (this.preserve_symlinks) |preserve_symlinks| { + try writer.writeFieldID(7); + try writer.writeInt(@intCast(u8, @boolToInt(preserve_symlinks))); + } + if (this.entry_points) |entry_points| { + try writer.writeFieldID(8); + try writer.writeArray([]const u8, entry_points); + } + if (this.write) |write| { + try writer.writeFieldID(9); + try writer.writeInt(@intCast(u8, @boolToInt(write))); + } + if (this.inject) |inject| { + try writer.writeFieldID(10); + try writer.writeArray([]const u8, inject); + } + if (this.output_dir) |output_dir| { + try writer.writeFieldID(11); + try writer.writeValue(output_dir); + } + if (this.external) |external| { + try writer.writeFieldID(12); + try writer.writeArray([]const u8, external); + } + if (this.loaders) |loaders| { + try writer.writeFieldID(13); + try writer.writeValue(loaders); + } + if (this.main_fields) |main_fields| { + try writer.writeFieldID(14); + try writer.writeArray([]const u8, main_fields); + } + if (this.platform) |platform| { + try writer.writeFieldID(15); + try writer.writeEnum(platform); + } + if (this.serve) |serve| { + try writer.writeFieldID(16); + try writer.writeInt(@intCast(u8, @boolToInt(serve))); + } + if (this.extension_order) |extension_order| { + try writer.writeFieldID(17); + try writer.writeArray([]const u8, extension_order); + } + if (this.generate_node_module_bundle) |generate_node_module_bundle| { + try writer.writeFieldID(18); + try writer.writeInt(@intCast(u8, @boolToInt(generate_node_module_bundle))); + } + if (this.node_modules_bundle_path) |node_modules_bundle_path| { + try writer.writeFieldID(19); + try writer.writeValue(node_modules_bundle_path); + } + if (this.node_modules_bundle_path_server) |node_modules_bundle_path_server| { + try writer.writeFieldID(20); + try writer.writeValue(node_modules_bundle_path_server); + } + if (this.framework) |framework| { + try writer.writeFieldID(21); + try writer.writeValue(framework); + } + if (this.router) |router| { + try writer.writeFieldID(22); + try writer.writeValue(router); + } + if (this.no_summary) |no_summary| { + try writer.writeFieldID(23); + try writer.writeInt(@intCast(u8, @boolToInt(no_summary))); + } + try writer.endMessage(); + } + }; -/// line -line: i32 = 0, + pub const FileHandle = struct { + /// path + path: []const u8, -/// column -column: i32 = 0, + /// size + size: u32 = 0, -/// line_text -line_text: []const u8, + /// fd + fd: u32 = 0, -/// suggestion -suggestion: []const u8, + pub fn decode(reader: anytype) anyerror!FileHandle { + var this = std.mem.zeroes(FileHandle); -/// offset -offset: u32 = 0, + this.path = try reader.readValue([]const u8); + this.size = try reader.readValue(u32); + this.fd = try reader.readValue(u32); + return this; + } + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeValue(this.path); + try writer.writeInt(this.size); + try writer.writeInt(this.fd); + } + }; -pub fn decode(reader: anytype) anyerror!Location { - var this = std.mem.zeroes(Location); + pub const Transform = struct { + /// handle + handle: ?FileHandle = null, - this.file = try reader.readValue([]const u8); - this.namespace = try reader.readValue([]const u8); - this.line = try reader.readValue(i32); - this.column = try reader.readValue(i32); - this.line_text = try reader.readValue([]const u8); - this.suggestion = try reader.readValue([]const u8); - this.offset = try reader.readValue(u32); - return this; -} + /// path + path: ?[]const u8 = null, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeValue(this.file); - try writer.writeValue(this.namespace); - try writer.writeInt(this.line); - try writer.writeInt(this.column); - try writer.writeValue(this.line_text); - try writer.writeValue(this.suggestion); - try writer.writeInt(this.offset); -} + /// contents + contents: []const u8, -}; + /// loader + loader: ?Loader = null, -pub const MessageData = struct { -/// text -text: ?[]const u8 = null, - -/// location -location: ?Location = null, - - -pub fn decode(reader: anytype) anyerror!MessageData { - var this = std.mem.zeroes(MessageData); - - while(true) { - switch (try reader.readByte()) { - 0 => { return this; }, - - 1 => { - this.text = try reader.readValue([]const u8); -}, - 2 => { - this.location = try reader.readValue(Location); -}, - else => { - return error.InvalidMessage; - }, - } - } -unreachable; -} + /// options + options: ?TransformOptions = null, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { -if (this.text) |text| { - try writer.writeFieldID(1); - try writer.writeValue(text); -} -if (this.location) |location| { - try writer.writeFieldID(2); - try writer.writeValue(location); -} -try writer.endMessage(); -} + pub fn decode(reader: anytype) anyerror!Transform { + var this = std.mem.zeroes(Transform); -}; + while (true) { + switch (try reader.readByte()) { + 0 => { + return this; + }, -pub const Message = struct { -/// kind -kind: MessageKind, + 1 => { + this.handle = try reader.readValue(FileHandle); + }, + 2 => { + this.path = try reader.readValue([]const u8); + }, + 3 => { + this.contents = try reader.readArray(u8); + }, + 4 => { + this.loader = try reader.readValue(Loader); + }, + 5 => { + this.options = try reader.readValue(TransformOptions); + }, + else => { + return error.InvalidMessage; + }, + } + } + unreachable; + } -/// data -data: MessageData, + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + if (this.handle) |handle| { + try writer.writeFieldID(1); + try writer.writeValue(handle); + } + if (this.path) |path| { + try writer.writeFieldID(2); + try writer.writeValue(path); + } + if (this.contents) |contents| { + try writer.writeFieldID(3); + try writer.writeArray(u8, contents); + } + if (this.loader) |loader| { + try writer.writeFieldID(4); + try writer.writeEnum(loader); + } + if (this.options) |options| { + try writer.writeFieldID(5); + try writer.writeValue(options); + } + try writer.endMessage(); + } + }; -/// notes -notes: []const MessageData, + pub const TransformResponseStatus = enum(u32) { + _none, + /// success + success, + /// fail + fail, -pub fn decode(reader: anytype) anyerror!Message { - var this = std.mem.zeroes(Message); + _, - this.kind = try reader.readValue(MessageKind); - this.data = try reader.readValue(MessageData); - this.notes = try reader.readArray(MessageData); - return this; -} + pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { + return try std.json.stringify(@tagName(self), opts, o); + } + }; -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeEnum(this.kind); - try writer.writeValue(this.data); - try writer.writeArray(MessageData, this.notes); -} + pub const OutputFile = struct { + /// data + data: []const u8, -}; + /// path + path: []const u8, -pub const Log = struct { -/// warnings -warnings: u32 = 0, + pub fn decode(reader: anytype) anyerror!OutputFile { + var this = std.mem.zeroes(OutputFile); -/// errors -errors: u32 = 0, + this.data = try reader.readArray(u8); + this.path = try reader.readValue([]const u8); + return this; + } -/// msgs -msgs: []const Message, + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeArray(u8, this.data); + try writer.writeValue(this.path); + } + }; + pub const TransformResponse = struct { + /// status + status: TransformResponseStatus, -pub fn decode(reader: anytype) anyerror!Log { - var this = std.mem.zeroes(Log); + /// files + files: []const OutputFile, - this.warnings = try reader.readValue(u32); - this.errors = try reader.readValue(u32); - this.msgs = try reader.readArray(Message); - return this; -} + /// errors + errors: []const Message, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeInt(this.warnings); - try writer.writeInt(this.errors); - try writer.writeArray(Message, this.msgs); -} + pub fn decode(reader: anytype) anyerror!TransformResponse { + var this = std.mem.zeroes(TransformResponse); -}; + this.status = try reader.readValue(TransformResponseStatus); + this.files = try reader.readArray(OutputFile); + this.errors = try reader.readArray(Message); + return this; + } -pub const Reloader = enum(u8) { + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeEnum(this.status); + try writer.writeArray(OutputFile, this.files); + try writer.writeArray(Message, this.errors); + } + }; -_none, - /// disable - disable, + pub const MessageKind = enum(u32) { + _none, + /// err + err, - /// live - live, + /// warn + warn, - /// fast_refresh - fast_refresh, + /// note + note, -_, + /// debug + debug, - pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { - return try std.json.stringify(@tagName(self), opts, o); - } + _, - -}; + pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { + return try std.json.stringify(@tagName(self), opts, o); + } + }; -pub const WebsocketMessageKind = enum(u8) { + pub const Location = struct { + /// file + file: []const u8, -_none, - /// welcome - welcome, + /// namespace + namespace: []const u8, - /// file_change_notification - file_change_notification, + /// line + line: i32 = 0, - /// build_success - build_success, + /// column + column: i32 = 0, - /// build_fail - build_fail, + /// line_text + line_text: []const u8, - /// manifest_success - manifest_success, + /// suggestion + suggestion: []const u8, - /// manifest_fail - manifest_fail, + /// offset + offset: u32 = 0, -_, + pub fn decode(reader: anytype) anyerror!Location { + var this = std.mem.zeroes(Location); - pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { - return try std.json.stringify(@tagName(self), opts, o); - } + this.file = try reader.readValue([]const u8); + this.namespace = try reader.readValue([]const u8); + this.line = try reader.readValue(i32); + this.column = try reader.readValue(i32); + this.line_text = try reader.readValue([]const u8); + this.suggestion = try reader.readValue([]const u8); + this.offset = try reader.readValue(u32); + return this; + } - -}; + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeValue(this.file); + try writer.writeValue(this.namespace); + try writer.writeInt(this.line); + try writer.writeInt(this.column); + try writer.writeValue(this.line_text); + try writer.writeValue(this.suggestion); + try writer.writeInt(this.offset); + } + }; -pub const WebsocketCommandKind = enum(u8) { + pub const MessageData = struct { + /// text + text: ?[]const u8 = null, -_none, - /// build - build, + /// location + location: ?Location = null, - /// manifest - manifest, + pub fn decode(reader: anytype) anyerror!MessageData { + var this = std.mem.zeroes(MessageData); -_, + while (true) { + switch (try reader.readByte()) { + 0 => { + return this; + }, - pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { - return try std.json.stringify(@tagName(self), opts, o); + 1 => { + this.text = try reader.readValue([]const u8); + }, + 2 => { + this.location = try reader.readValue(Location); + }, + else => { + return error.InvalidMessage; + }, } + } + unreachable; + } - -}; - -pub const WebsocketMessage = struct { -/// timestamp -timestamp: u32 = 0, + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + if (this.text) |text| { + try writer.writeFieldID(1); + try writer.writeValue(text); + } + if (this.location) |location| { + try writer.writeFieldID(2); + try writer.writeValue(location); + } + try writer.endMessage(); + } + }; -/// kind -kind: WebsocketMessageKind, + pub const Message = struct { + /// kind + kind: MessageKind, + /// data + data: MessageData, -pub fn decode(reader: anytype) anyerror!WebsocketMessage { - var this = std.mem.zeroes(WebsocketMessage); + /// notes + notes: []const MessageData, - this.timestamp = try reader.readValue(u32); - this.kind = try reader.readValue(WebsocketMessageKind); - return this; -} + pub fn decode(reader: anytype) anyerror!Message { + var this = std.mem.zeroes(Message); -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeInt(this.timestamp); - try writer.writeEnum(this.kind); -} + this.kind = try reader.readValue(MessageKind); + this.data = try reader.readValue(MessageData); + this.notes = try reader.readArray(MessageData); + return this; + } -}; + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeEnum(this.kind); + try writer.writeValue(this.data); + try writer.writeArray(MessageData, this.notes); + } + }; -pub const WebsocketMessageWelcome = struct { -/// epoch -epoch: u32 = 0, + pub const Log = struct { + /// warnings + warnings: u32 = 0, -/// javascriptReloader -javascript_reloader: Reloader, + /// errors + errors: u32 = 0, + /// msgs + msgs: []const Message, -pub fn decode(reader: anytype) anyerror!WebsocketMessageWelcome { - var this = std.mem.zeroes(WebsocketMessageWelcome); + pub fn decode(reader: anytype) anyerror!Log { + var this = std.mem.zeroes(Log); - this.epoch = try reader.readValue(u32); - this.javascript_reloader = try reader.readValue(Reloader); - return this; -} + this.warnings = try reader.readValue(u32); + this.errors = try reader.readValue(u32); + this.msgs = try reader.readArray(Message); + return this; + } -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeInt(this.epoch); - try writer.writeEnum(this.javascript_reloader); -} + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeInt(this.warnings); + try writer.writeInt(this.errors); + try writer.writeArray(Message, this.msgs); + } + }; -}; + pub const Reloader = enum(u8) { + _none, + /// disable + disable, -pub const WebsocketMessageFileChangeNotification = struct { -/// id -id: u32 = 0, + /// live + live, -/// loader -loader: Loader, + /// fast_refresh + fast_refresh, + _, -pub fn decode(reader: anytype) anyerror!WebsocketMessageFileChangeNotification { - var this = std.mem.zeroes(WebsocketMessageFileChangeNotification); + pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { + return try std.json.stringify(@tagName(self), opts, o); + } + }; - this.id = try reader.readValue(u32); - this.loader = try reader.readValue(Loader); - return this; -} + pub const WebsocketMessageKind = enum(u8) { + _none, + /// welcome + welcome, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeInt(this.id); - try writer.writeEnum(this.loader); -} + /// file_change_notification + file_change_notification, -}; + /// build_success + build_success, -pub const WebsocketCommand = struct { -/// kind -kind: WebsocketCommandKind, + /// build_fail + build_fail, -/// timestamp -timestamp: u32 = 0, + /// manifest_success + manifest_success, + /// manifest_fail + manifest_fail, -pub fn decode(reader: anytype) anyerror!WebsocketCommand { - var this = std.mem.zeroes(WebsocketCommand); + _, - this.kind = try reader.readValue(WebsocketCommandKind); - this.timestamp = try reader.readValue(u32); - return this; -} + pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { + return try std.json.stringify(@tagName(self), opts, o); + } + }; -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeEnum(this.kind); - try writer.writeInt(this.timestamp); -} + pub const WebsocketCommandKind = enum(u8) { + _none, + /// build + build, -}; + /// manifest + manifest, -pub const WebsocketCommandBuild = packed struct { -/// id -id: u32 = 0, + _, + pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void { + return try std.json.stringify(@tagName(self), opts, o); + } + }; -pub fn decode(reader: anytype) anyerror!WebsocketCommandBuild { - var this = std.mem.zeroes(WebsocketCommandBuild); + pub const WebsocketMessage = struct { + /// timestamp + timestamp: u32 = 0, - this.id = try reader.readValue(u32); - return this; -} + /// kind + kind: WebsocketMessageKind, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeInt(this.id); -} + pub fn decode(reader: anytype) anyerror!WebsocketMessage { + var this = std.mem.zeroes(WebsocketMessage); -}; + this.timestamp = try reader.readValue(u32); + this.kind = try reader.readValue(WebsocketMessageKind); + return this; + } -pub const WebsocketCommandManifest = packed struct { -/// id -id: u32 = 0, + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeInt(this.timestamp); + try writer.writeEnum(this.kind); + } + }; + pub const WebsocketMessageWelcome = struct { + /// epoch + epoch: u32 = 0, -pub fn decode(reader: anytype) anyerror!WebsocketCommandManifest { - var this = std.mem.zeroes(WebsocketCommandManifest); + /// javascriptReloader + javascript_reloader: Reloader, - this.id = try reader.readValue(u32); - return this; -} + pub fn decode(reader: anytype) anyerror!WebsocketMessageWelcome { + var this = std.mem.zeroes(WebsocketMessageWelcome); -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeInt(this.id); -} + this.epoch = try reader.readValue(u32); + this.javascript_reloader = try reader.readValue(Reloader); + return this; + } -}; + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeInt(this.epoch); + try writer.writeEnum(this.javascript_reloader); + } + }; -pub const WebsocketMessageBuildSuccess = struct { -/// id -id: u32 = 0, + pub const WebsocketMessageFileChangeNotification = struct { + /// id + id: u32 = 0, -/// from_timestamp -from_timestamp: u32 = 0, + /// loader + loader: Loader, -/// loader -loader: Loader, + pub fn decode(reader: anytype) anyerror!WebsocketMessageFileChangeNotification { + var this = std.mem.zeroes(WebsocketMessageFileChangeNotification); -/// module_path -module_path: []const u8, + this.id = try reader.readValue(u32); + this.loader = try reader.readValue(Loader); + return this; + } -/// blob_length -blob_length: u32 = 0, + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeInt(this.id); + try writer.writeEnum(this.loader); + } + }; + pub const WebsocketCommand = struct { + /// kind + kind: WebsocketCommandKind, -pub fn decode(reader: anytype) anyerror!WebsocketMessageBuildSuccess { - var this = std.mem.zeroes(WebsocketMessageBuildSuccess); + /// timestamp + timestamp: u32 = 0, - this.id = try reader.readValue(u32); - this.from_timestamp = try reader.readValue(u32); - this.loader = try reader.readValue(Loader); - this.module_path = try reader.readValue([]const u8); - this.blob_length = try reader.readValue(u32); - return this; -} + pub fn decode(reader: anytype) anyerror!WebsocketCommand { + var this = std.mem.zeroes(WebsocketCommand); -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeInt(this.id); - try writer.writeInt(this.from_timestamp); - try writer.writeEnum(this.loader); - try writer.writeValue(this.module_path); - try writer.writeInt(this.blob_length); -} + this.kind = try reader.readValue(WebsocketCommandKind); + this.timestamp = try reader.readValue(u32); + return this; + } -}; + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeEnum(this.kind); + try writer.writeInt(this.timestamp); + } + }; -pub const WebsocketMessageBuildFailure = struct { -/// id -id: u32 = 0, + pub const WebsocketCommandBuild = packed struct { + /// id + id: u32 = 0, -/// from_timestamp -from_timestamp: u32 = 0, + pub fn decode(reader: anytype) anyerror!WebsocketCommandBuild { + var this = std.mem.zeroes(WebsocketCommandBuild); -/// loader -loader: Loader, + this.id = try reader.readValue(u32); + return this; + } -/// module_path -module_path: []const u8, + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeInt(this.id); + } + }; -/// log -log: Log, + pub const WebsocketCommandManifest = packed struct { + /// id + id: u32 = 0, + pub fn decode(reader: anytype) anyerror!WebsocketCommandManifest { + var this = std.mem.zeroes(WebsocketCommandManifest); -pub fn decode(reader: anytype) anyerror!WebsocketMessageBuildFailure { - var this = std.mem.zeroes(WebsocketMessageBuildFailure); + this.id = try reader.readValue(u32); + return this; + } - this.id = try reader.readValue(u32); - this.from_timestamp = try reader.readValue(u32); - this.loader = try reader.readValue(Loader); - this.module_path = try reader.readValue([]const u8); - this.log = try reader.readValue(Log); - return this; -} + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeInt(this.id); + } + }; -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeInt(this.id); - try writer.writeInt(this.from_timestamp); - try writer.writeEnum(this.loader); - try writer.writeValue(this.module_path); - try writer.writeValue(this.log); -} + pub const WebsocketMessageBuildSuccess = struct { + /// id + id: u32 = 0, -}; + /// from_timestamp + from_timestamp: u32 = 0, -pub const DependencyManifest = struct { -/// ids -ids: []const u32, + /// loader + loader: Loader, + /// module_path + module_path: []const u8, -pub fn decode(reader: anytype) anyerror!DependencyManifest { - var this = std.mem.zeroes(DependencyManifest); + /// blob_length + blob_length: u32 = 0, - this.ids = try reader.readArray(u32); - return this; -} + pub fn decode(reader: anytype) anyerror!WebsocketMessageBuildSuccess { + var this = std.mem.zeroes(WebsocketMessageBuildSuccess); -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeArray(u32, this.ids); -} + this.id = try reader.readValue(u32); + this.from_timestamp = try reader.readValue(u32); + this.loader = try reader.readValue(Loader); + this.module_path = try reader.readValue([]const u8); + this.blob_length = try reader.readValue(u32); + return this; + } -}; + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeInt(this.id); + try writer.writeInt(this.from_timestamp); + try writer.writeEnum(this.loader); + try writer.writeValue(this.module_path); + try writer.writeInt(this.blob_length); + } + }; -pub const FileList = struct { -/// ptrs -ptrs: []const StringPointer, + pub const WebsocketMessageBuildFailure = struct { + /// id + id: u32 = 0, -/// files -files: []const u8, + /// from_timestamp + from_timestamp: u32 = 0, + /// loader + loader: Loader, -pub fn decode(reader: anytype) anyerror!FileList { - var this = std.mem.zeroes(FileList); + /// module_path + module_path: []const u8, - this.ptrs = try reader.readArray(StringPointer); - this.files = try reader.readValue([]const u8); - return this; -} + /// log + log: Log, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeArray(StringPointer, this.ptrs); - try writer.writeValue(this.files); -} + pub fn decode(reader: anytype) anyerror!WebsocketMessageBuildFailure { + var this = std.mem.zeroes(WebsocketMessageBuildFailure); -}; + this.id = try reader.readValue(u32); + this.from_timestamp = try reader.readValue(u32); + this.loader = try reader.readValue(Loader); + this.module_path = try reader.readValue([]const u8); + this.log = try reader.readValue(Log); + return this; + } -pub const WebsocketMessageResolveIDs = struct { -/// id -id: []const u32, + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeInt(this.id); + try writer.writeInt(this.from_timestamp); + try writer.writeEnum(this.loader); + try writer.writeValue(this.module_path); + try writer.writeValue(this.log); + } + }; -/// list -list: FileList, + pub const DependencyManifest = struct { + /// ids + ids: []const u32, + pub fn decode(reader: anytype) anyerror!DependencyManifest { + var this = std.mem.zeroes(DependencyManifest); -pub fn decode(reader: anytype) anyerror!WebsocketMessageResolveIDs { - var this = std.mem.zeroes(WebsocketMessageResolveIDs); + this.ids = try reader.readArray(u32); + return this; + } - this.id = try reader.readArray(u32); - this.list = try reader.readValue(FileList); - return this; -} + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeArray(u32, this.ids); + } + }; -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeArray(u32, this.id); - try writer.writeValue(this.list); -} + pub const FileList = struct { + /// ptrs + ptrs: []const StringPointer, -}; + /// files + files: []const u8, -pub const WebsocketCommandResolveIDs = struct { -/// ptrs -ptrs: []const StringPointer, + pub fn decode(reader: anytype) anyerror!FileList { + var this = std.mem.zeroes(FileList); -/// files -files: []const u8, + this.ptrs = try reader.readArray(StringPointer); + this.files = try reader.readValue([]const u8); + return this; + } + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeArray(StringPointer, this.ptrs); + try writer.writeValue(this.files); + } + }; -pub fn decode(reader: anytype) anyerror!WebsocketCommandResolveIDs { - var this = std.mem.zeroes(WebsocketCommandResolveIDs); + pub const WebsocketMessageResolveIDs = struct { + /// id + id: []const u32, - this.ptrs = try reader.readArray(StringPointer); - this.files = try reader.readValue([]const u8); - return this; -} + /// list + list: FileList, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeArray(StringPointer, this.ptrs); - try writer.writeValue(this.files); -} + pub fn decode(reader: anytype) anyerror!WebsocketMessageResolveIDs { + var this = std.mem.zeroes(WebsocketMessageResolveIDs); -}; + this.id = try reader.readArray(u32); + this.list = try reader.readValue(FileList); + return this; + } -pub const WebsocketMessageManifestSuccess = struct { -/// id -id: u32 = 0, + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeArray(u32, this.id); + try writer.writeValue(this.list); + } + }; -/// module_path -module_path: []const u8, + pub const WebsocketCommandResolveIDs = struct { + /// ptrs + ptrs: []const StringPointer, -/// loader -loader: Loader, + /// files + files: []const u8, -/// manifest -manifest: DependencyManifest, + pub fn decode(reader: anytype) anyerror!WebsocketCommandResolveIDs { + var this = std.mem.zeroes(WebsocketCommandResolveIDs); + this.ptrs = try reader.readArray(StringPointer); + this.files = try reader.readValue([]const u8); + return this; + } -pub fn decode(reader: anytype) anyerror!WebsocketMessageManifestSuccess { - var this = std.mem.zeroes(WebsocketMessageManifestSuccess); + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeArray(StringPointer, this.ptrs); + try writer.writeValue(this.files); + } + }; - this.id = try reader.readValue(u32); - this.module_path = try reader.readValue([]const u8); - this.loader = try reader.readValue(Loader); - this.manifest = try reader.readValue(DependencyManifest); - return this; -} + pub const WebsocketMessageManifestSuccess = struct { + /// id + id: u32 = 0, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeInt(this.id); - try writer.writeValue(this.module_path); - try writer.writeEnum(this.loader); - try writer.writeValue(this.manifest); -} + /// module_path + module_path: []const u8, -}; + /// loader + loader: Loader, -pub const WebsocketMessageManifestFailure = struct { -/// id -id: u32 = 0, + /// manifest + manifest: DependencyManifest, -/// from_timestamp -from_timestamp: u32 = 0, + pub fn decode(reader: anytype) anyerror!WebsocketMessageManifestSuccess { + var this = std.mem.zeroes(WebsocketMessageManifestSuccess); -/// loader -loader: Loader, + this.id = try reader.readValue(u32); + this.module_path = try reader.readValue([]const u8); + this.loader = try reader.readValue(Loader); + this.manifest = try reader.readValue(DependencyManifest); + return this; + } -/// log -log: Log, + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeInt(this.id); + try writer.writeValue(this.module_path); + try writer.writeEnum(this.loader); + try writer.writeValue(this.manifest); + } + }; + pub const WebsocketMessageManifestFailure = struct { + /// id + id: u32 = 0, -pub fn decode(reader: anytype) anyerror!WebsocketMessageManifestFailure { - var this = std.mem.zeroes(WebsocketMessageManifestFailure); + /// from_timestamp + from_timestamp: u32 = 0, - this.id = try reader.readValue(u32); - this.from_timestamp = try reader.readValue(u32); - this.loader = try reader.readValue(Loader); - this.log = try reader.readValue(Log); - return this; -} + /// loader + loader: Loader, -pub fn encode(this: *const @This(), writer: anytype) anyerror!void { - try writer.writeInt(this.id); - try writer.writeInt(this.from_timestamp); - try writer.writeEnum(this.loader); - try writer.writeValue(this.log); -} + /// log + log: Log, -}; + pub fn decode(reader: anytype) anyerror!WebsocketMessageManifestFailure { + var this = std.mem.zeroes(WebsocketMessageManifestFailure); + this.id = try reader.readValue(u32); + this.from_timestamp = try reader.readValue(u32); + this.loader = try reader.readValue(Loader); + this.log = try reader.readValue(Log); + return this; + } + pub fn encode(this: *const @This(), writer: anytype) anyerror!void { + try writer.writeInt(this.id); + try writer.writeInt(this.from_timestamp); + try writer.writeEnum(this.loader); + try writer.writeValue(this.log); + } + }; }; - const ExamplePackedStruct = packed struct { len: u32 = 0, offset: u32 = 0, diff --git a/src/bundler.zig b/src/bundler.zig index ca4db463f..483b5d09b 100644 --- a/src/bundler.zig +++ b/src/bundler.zig @@ -465,8 +465,6 @@ pub fn NewBundler(cache_files: bool) type { pub const WorkerData = struct { shared_buffer: MutableString = undefined, scan_pass_result: js_parser.ScanPassResult = undefined, - templist: [100]_resolver.Result = undefined, - templist_used: u8 = 0, pub fn deinit(this: *WorkerData, allocator: *std.mem.Allocator) void { this.shared_buffer.deinit(); @@ -544,6 +542,7 @@ pub fn NewBundler(cache_files: bool) type { module_list: std.ArrayList(Api.JavascriptBundledModule), package_list: std.ArrayList(Api.JavascriptBundledPackage), header_string_buffer: MutableString, + // Just need to know if we've already enqueued this one package_list_map: std.AutoHashMap(u64, u32), queue: *BunQueue, @@ -560,15 +559,23 @@ pub fn NewBundler(cache_files: bool) type { list_lock: Lock = Lock.init(), pub const current_version: u32 = 1; + const dist_index_js_string_pointer = Api.StringPointer{ .length = "dist/index.js".len }; + const index_js_string_pointer = Api.StringPointer{ .length = "index.js".len, .offset = "dist/".len }; pub fn enqueueItem(this: *GenerateNodeModuleBundle, resolve: _resolver.Result) !void { - const loader = this.bundler.options.loaders.get(resolve.path_pair.primary.name.ext) orelse .file; - if (!loader.isJavaScriptLike()) return; - var result = resolve; - result.path_pair.primary = Fs.Path.init(std.mem.span(try this.allocator.dupeZ(u8, resolve.path_pair.primary.text))); + var path = result.path() orelse return; + const loader = this.bundler.options.loaders.get(path.name.ext) orelse .file; + if (!loader.isJavaScriptLikeOrJSON()) return; + if (BundledModuleData.get(this, &result)) |mod| { + path.* = Fs.Path.init(std.mem.span(try this.allocator.dupeZ(u8, path.text))); + + try this.queue.upsert(mod.module_id, result); + } else { + path.* = Fs.Path.init(std.mem.span(try this.allocator.dupeZ(u8, path.text))); - try this.queue.upsert(result.hash(loader), result); + try this.queue.upsert(result.hash(this.bundler.fs.top_level_dir, loader), result); + } } // The Bun Bundle Format @@ -612,6 +619,14 @@ pub fn NewBundler(cache_files: bool) type { // The specifics of the metadata is not documented here. You can find it in src/api/schema.peechy. pub fn appendHeaderString(generator: *GenerateNodeModuleBundle, str: string) !Api.StringPointer { + // This is so common we might as well just reuse it + // Plus this is one machine word so it's a quick comparison + if (strings.eqlComptime(str, "index.js")) { + return index_js_string_pointer; + } else if (strings.eqlComptime(str, "dist/index.js")) { + return dist_index_js_string_pointer; + } + var offset = generator.header_string_buffer.list.items.len; try generator.header_string_buffer.append(str); return Api.StringPointer{ @@ -639,13 +654,19 @@ pub fn NewBundler(cache_files: bool) type { ); var tmpfile = try tmpdir.createFileZ(tmpname, .{ .read = isDebug, .exclusive = true }); + + errdefer { + tmpfile.close(); + tmpdir.deleteFile(std.mem.span(tmpname)) catch {}; + } + var generator = try allocator.create(GenerateNodeModuleBundle); var queue = try BunQueue.init(allocator); defer allocator.destroy(generator); generator.* = GenerateNodeModuleBundle{ .module_list = std.ArrayList(Api.JavascriptBundledModule).init(allocator), .package_list = std.ArrayList(Api.JavascriptBundledPackage).init(allocator), - .header_string_buffer = try MutableString.init(allocator, 0), + .header_string_buffer = try MutableString.init(allocator, "dist/index.js".len), .allocator = allocator, .queue = queue, // .resolve_queue = queue, @@ -656,6 +677,9 @@ pub fn NewBundler(cache_files: bool) type { .pool = undefined, .write_lock = Lock.init(), }; + // dist/index.js appears more common than /index.js + // but this means we can store both "dist/index.js" and "index.js" in one. + try generator.header_string_buffer.append("dist/index.js"); try generator.package_list_map.ensureTotalCapacity(128); var pool = try allocator.create(ThreadPool); pool.* = ThreadPool{}; @@ -696,6 +720,7 @@ pub fn NewBundler(cache_files: bool) type { } else {} for (bundler.options.entry_points) |entry_point| { + if (bundler.options.platform == .bun) continue; defer this.bundler.resetStore(); const entry_point_path = bundler.normalizeEntryPointPath(entry_point); @@ -750,9 +775,11 @@ pub fn NewBundler(cache_files: bool) type { this.bundler.resetStore(); try this.pool.start(this); - this.pool.wait(this); + try this.pool.wait(this); if (this.log.errors > 0) { + tmpfile.close(); + tmpdir.deleteFile(std.mem.span(tmpname)) catch {}; // We stop here because if there are errors we don't know if the bundle is valid // This manifests as a crash when sorting through the module list because we may have added files to the bundle which were never actually finished being added. return null; @@ -896,8 +923,38 @@ pub fn NewBundler(cache_files: bool) type { return this.header_string_buffer.list.items[ptr.offset .. ptr.offset + ptr.length]; } - // Since we trim the prefixes, we must also compare the package name + // Since we trim the prefixes, we must also compare the package name and version pub fn sortJavascriptModuleByPath(ctx: *GenerateNodeModuleBundle, a: Api.JavascriptBundledModule, b: Api.JavascriptBundledModule) bool { + if (comptime isDebug) { + const a_pkg: Api.JavascriptBundledPackage = ctx.package_list.items[a.package_id]; + const b_pkg: Api.JavascriptBundledPackage = ctx.package_list.items[b.package_id]; + const a_name = ctx.metadataStringPointer(a_pkg.name); + const b_name = ctx.metadataStringPointer(b_pkg.name); + const a_version = ctx.metadataStringPointer(a_pkg.version); + const b_version = ctx.metadataStringPointer(b_pkg.version); + const a_path = ctx.metadataStringPointer(a.path); + const b_path = ctx.metadataStringPointer(b.path); + + std.debug.assert(a_name.len > 0); + std.debug.assert(b_name.len > 0); + std.debug.assert(a_version.len > 0); + std.debug.assert(b_version.len > 0); + std.debug.assert(a_path.len > 0); + std.debug.assert(b_path.len > 0); + + if (strings.eql(a_name, b_name)) { + if (strings.eql(a_version, b_version)) { + std.debug.assert(a_pkg.hash == b_pkg.hash); // hash collision + std.debug.assert(a.package_id == b.package_id); // duplicate package + std.debug.assert(!strings.eql(a_path, b_path)); // duplicate module + } else { + std.debug.assert(a_pkg.hash != b_pkg.hash); // incorrectly generated hash + } + } else { + std.debug.assert(a_pkg.hash != b_pkg.hash); // incorrectly generated hash + } + } + return switch (std.mem.order( u8, ctx.metadataStringPointer( @@ -907,11 +964,23 @@ pub fn NewBundler(cache_files: bool) type { ctx.package_list.items[b.package_id].name, ), )) { - .eq => std.mem.order( + .eq => switch (std.mem.order( u8, - ctx.metadataStringPointer(a.path), - ctx.metadataStringPointer(b.path), - ) == .lt, + ctx.metadataStringPointer( + ctx.package_list.items[a.package_id].version, + ), + ctx.metadataStringPointer( + ctx.package_list.items[b.package_id].version, + ), + )) { + .eq => std.mem.order( + u8, + ctx.metadataStringPointer(a.path), + ctx.metadataStringPointer(b.path), + ) == .lt, + .lt => true, + else => false, + }, .lt => true, else => false, }; @@ -933,19 +1002,17 @@ pub fn NewBundler(cache_files: bool) type { module_id: u32, pub fn get(this: *GenerateNodeModuleBundle, resolve_result: *const _resolver.Result) ?BundledModuleData { + var path = resolve_result.pathConst() orelse return null; const package_json: *const PackageJSON = this.bundler.resolver.rootNodeModulePackageJSON(resolve_result) orelse return null; const package_base_path = package_json.source.path.name.dirWithTrailingSlash(); - const import_path = resolve_result.path_pair.primary.text[package_base_path.len..]; - const package_path = resolve_result.path_pair.primary.text[package_base_path.len - package_json.name.len - 1 ..]; - var hasher = std.hash.Wyhash.init(0); - hasher.update(import_path); - hasher.update(std.mem.asBytes(&package_json.hash)); + const import_path = path.text[package_base_path.len..]; + const package_path = path.text[package_base_path.len - package_json.name.len - 1 ..]; return BundledModuleData{ .import_path = import_path, .package_path = package_path, .package = package_json, - .module_id = @truncate(u32, hasher.final()), + .module_id = package_json.hashModule(package_path), }; } }; @@ -953,22 +1020,20 @@ pub fn NewBundler(cache_files: bool) type { fn processImportRecord(this: *GenerateNodeModuleBundle, import_record: ImportRecord) !void {} pub fn processFile(this: *GenerateNodeModuleBundle, worker: *ThreadPool.Worker, _resolve: _resolver.Result) !void { - var resolve = _resolve; + const resolve = _resolve; if (resolve.is_external) return; var shared_buffer = &worker.data.shared_buffer; var scan_pass_result = &worker.data.scan_pass_result; const is_from_node_modules = resolve.isLikelyNodeModule(); - const loader = this.bundler.options.loaders.get(resolve.path_pair.primary.name.ext) orelse .file; + var file_path = (resolve.pathConst() orelse unreachable).*; + + const loader = this.bundler.options.loader(file_path.name.ext); var bundler = this.bundler; defer scan_pass_result.reset(); defer shared_buffer.reset(); defer this.bundler.resetStore(); - var file_path = resolve.path_pair.primary; - var hasher = std.hash.Wyhash.init(0); - - var module_data: BundledModuleData = undefined; // If we're in a node_module, build that almost normally if (is_from_node_modules) { @@ -978,6 +1043,9 @@ pub fn NewBundler(cache_files: bool) type { .js, .ts, => { + var written: usize = undefined; + var code_offset: u32 = 0; + const entry = try bundler.resolver.caches.fs.readFileShared( bundler.fs, file_path.text, @@ -985,26 +1053,58 @@ pub fn NewBundler(cache_files: bool) type { null, shared_buffer, ); - const source = logger.Source.initRecycledFile(Fs.File{ .path = file_path, .contents = entry.contents }, bundler.allocator) catch return null; - const source_dir = file_path.name.dirWithTrailingSlash(); - var jsx = bundler.options.jsx; - jsx.parse = loader.isJSX(); - - var opts = js_parser.Parser.Options.init(jsx, loader); - opts.transform_require_to_import = false; - opts.enable_bundling = true; - opts.warn_about_unbundled_modules = false; - - var ast: js_ast.Ast = (try bundler.resolver.caches.js.parse( - bundler.allocator, - opts, - bundler.options.define, - this.log, - &source, - )) orelse return; - if (ast.import_records.len > 0) { - { + const module_data = BundledModuleData.get(this, &resolve) orelse return error.ResolveError; + const module_id = module_data.module_id; + const package = module_data.package; + const package_relative_path = module_data.import_path; + file_path.pretty = module_data.package_path; + + // Handle empty files + // We can't just ignore them. Sometimes code will try to import it. Often because of TypeScript types. + // So we just say it's an empty object. Empty object mimicks what "browser": false does as well. + // TODO: optimize this so that all the exports for these are done in one line instead of writing repeatedly + if (entry.contents.len == 0 or (entry.contents.len < 33 and strings.trim(entry.contents, " \n\r").len == 0)) { + this.write_lock.lock(); + defer this.write_lock.unlock(); + code_offset = @truncate(u32, try this.tmpfile.getPos()); + var writer = this.tmpfile.writer(); + var buffered = std.io.bufferedWriter(writer); + + var bufwriter = buffered.writer(); + try bufwriter.writeAll("// "); + try bufwriter.writeAll(package_relative_path); + try bufwriter.writeAll("\nexport var $"); + std.fmt.formatInt(module_id, 16, .lower, .{}, bufwriter) catch unreachable; + try bufwriter.writeAll(" = () => ({});\n"); + try buffered.flush(); + this.tmpfile_byte_offset = @truncate(u32, try this.tmpfile.getPos()); + } else { + const source = logger.Source.initRecycledFile( + Fs.File{ + .path = file_path, + .contents = entry.contents, + }, + bundler.allocator, + ) catch return null; + const source_dir = file_path.name.dirWithTrailingSlash(); + + var jsx = bundler.options.jsx; + jsx.parse = loader.isJSX(); + + var opts = js_parser.Parser.Options.init(jsx, loader); + opts.transform_require_to_import = false; + opts.enable_bundling = true; + opts.warn_about_unbundled_modules = false; + + var ast: js_ast.Ast = (try bundler.resolver.caches.js.parse( + bundler.allocator, + opts, + bundler.options.define, + this.log, + &source, + )) orelse return; + if (ast.import_records.len > 0) { for (ast.import_records) |*import_record, record_id| { // Don't resolve the runtime @@ -1016,18 +1116,31 @@ pub fn NewBundler(cache_files: bool) type { if (_resolved_import.is_external) { continue; } - _resolved_import.path_pair.primary = Fs.Path.init(std.mem.span(try this.allocator.dupeZ(u8, _resolved_import.path_pair.primary.text))); + var path = _resolved_import.path() orelse { + import_record.path.is_disabled = true; + import_record.is_bundled = true; + continue; + }; - const resolved_import: *const _resolver.Result = _resolved_import; + const loader_ = bundler.options.loader(path.name.ext); - const absolute_path = resolved_import.path_pair.primary.text; + if (!loader_.isJavaScriptLikeOrJSON()) { + import_record.path.is_disabled = true; + import_record.is_bundled = true; + continue; + } - module_data = BundledModuleData.get(this, resolved_import) orelse continue; - import_record.module_id = module_data.module_id; + const resolved_import: *const _resolver.Result = _resolved_import; + + const _module_data = BundledModuleData.get(this, resolved_import) orelse continue; + import_record.module_id = _module_data.module_id; import_record.is_bundled = true; - import_record.path = Fs.Path.init(module_data.import_path); + path.* = Fs.Path.init(this.allocator.dupeZ(u8, path.text) catch unreachable); + + import_record.path = path.*; + try this.queue.upsert( - _resolved_import.hash(this.bundler.options.loaders.get(resolved_import.path_pair.primary.name.ext) orelse .file), + _module_data.module_id, _resolved_import.*, ); } else |err| { @@ -1080,157 +1193,161 @@ pub fn NewBundler(cache_files: bool) type { } } } - } - - module_data = BundledModuleData.get(this, &_resolve) orelse return error.ResolveError; - const module_id = module_data.module_id; - const package = module_data.package; - const package_relative_path = module_data.import_path; - // const load_from_symbol_ref = ast.runtime_imports.$$r.?; - // const reexport_ref = ast.runtime_imports.__reExport.?; - const register_ref = ast.runtime_imports.register.?; - const E = js_ast.E; - const Expr = js_ast.Expr; - const Stmt = js_ast.Stmt; - - var prepend_part: js_ast.Part = undefined; - var needs_prepend_part = false; - if (ast.parts.len > 1) { - for (ast.parts) |part| { - if (part.tag != .none and part.stmts.len > 0) { - prepend_part = part; - needs_prepend_part = true; - break; + // const load_from_symbol_ref = ast.runtime_imports.$$r.?; + // const reexport_ref = ast.runtime_imports.__reExport.?; + const register_ref = ast.runtime_imports.register.?; + const E = js_ast.E; + const Expr = js_ast.Expr; + const Stmt = js_ast.Stmt; + + var prepend_part: js_ast.Part = undefined; + var needs_prepend_part = false; + if (ast.parts.len > 1) { + for (ast.parts) |part| { + if (part.tag != .none and part.stmts.len > 0) { + prepend_part = part; + needs_prepend_part = true; + break; + } } } - } - if (ast.parts.len == 0) { - if (comptime isDebug) { - Output.prettyErrorln("Missing AST for file: {s}", .{file_path.text}); - Output.flush(); + if (ast.parts.len == 0) { + if (comptime isDebug) { + Output.prettyErrorln("Missing AST for file: {s}", .{file_path.text}); + Output.flush(); + } } - } - var part = &ast.parts[ast.parts.len - 1]; - var new_stmts: [1]Stmt = undefined; - var register_args: [3]Expr = undefined; - - var package_json_string = E.String{ .utf8 = package.name }; - var module_path_string = E.String{ .utf8 = module_data.import_path }; - var target_identifier = E.Identifier{ .ref = register_ref }; - var cjs_args: [2]js_ast.G.Arg = undefined; - var module_binding = js_ast.B.Identifier{ .ref = ast.module_ref.? }; - var exports_binding = js_ast.B.Identifier{ .ref = ast.exports_ref.? }; - - // if (!ast.uses_module_ref) { - // var symbol = &ast.symbols[ast.module_ref.?.inner_index]; - // symbol.original_name = "_$$"; - // } - - cjs_args[0] = js_ast.G.Arg{ - .binding = js_ast.Binding{ - .loc = logger.Loc.Empty, - .data = .{ .b_identifier = &module_binding }, - }, - }; - cjs_args[1] = js_ast.G.Arg{ - .binding = js_ast.Binding{ - .loc = logger.Loc.Empty, - .data = .{ .b_identifier = &exports_binding }, - }, - }; + var part = &ast.parts[ast.parts.len - 1]; + var new_stmts: [1]Stmt = undefined; + var register_args: [3]Expr = undefined; + + var package_json_string = E.String{ .utf8 = package.name }; + var module_path_string = E.String{ .utf8 = module_data.import_path }; + var target_identifier = E.Identifier{ .ref = register_ref }; + var cjs_args: [2]js_ast.G.Arg = undefined; + var module_binding = js_ast.B.Identifier{ .ref = ast.module_ref.? }; + var exports_binding = js_ast.B.Identifier{ .ref = ast.exports_ref.? }; + + // if (!ast.uses_module_ref) { + // var symbol = &ast.symbols[ast.module_ref.?.inner_index]; + // symbol.original_name = "_$$"; + // } + + cjs_args[0] = js_ast.G.Arg{ + .binding = js_ast.Binding{ + .loc = logger.Loc.Empty, + .data = .{ .b_identifier = &module_binding }, + }, + }; + cjs_args[1] = js_ast.G.Arg{ + .binding = js_ast.Binding{ + .loc = logger.Loc.Empty, + .data = .{ .b_identifier = &exports_binding }, + }, + }; - var closure = E.Arrow{ - .args = &cjs_args, - .body = .{ - .loc = logger.Loc.Empty, - .stmts = part.stmts, - }, - }; + var closure = E.Arrow{ + .args = &cjs_args, + .body = .{ + .loc = logger.Loc.Empty, + .stmts = part.stmts, + }, + }; - // $$m(12345, "react", "index.js", function(module, exports) { + // $$m(12345, "react", "index.js", function(module, exports) { - // }) - register_args[0] = Expr{ .loc = .{ .start = 0 }, .data = .{ .e_string = &package_json_string } }; - register_args[1] = Expr{ .loc = .{ .start = 0 }, .data = .{ .e_string = &module_path_string } }; - register_args[2] = Expr{ .loc = .{ .start = 0 }, .data = .{ .e_arrow = &closure } }; + // }) + register_args[0] = Expr{ .loc = .{ .start = 0 }, .data = .{ .e_string = &package_json_string } }; + register_args[1] = Expr{ .loc = .{ .start = 0 }, .data = .{ .e_string = &module_path_string } }; + register_args[2] = Expr{ .loc = .{ .start = 0 }, .data = .{ .e_arrow = &closure } }; - var call_register = E.Call{ - .target = Expr{ - .data = .{ .e_identifier = &target_identifier }, - .loc = logger.Loc{ .start = 0 }, - }, - .args = ®ister_args, - }; - var register_expr = Expr{ .loc = call_register.target.loc, .data = .{ .e_call = &call_register } }; - var decls: [1]js_ast.G.Decl = undefined; - var bundle_export_binding = js_ast.B.Identifier{ .ref = ast.bundle_export_ref.? }; - var binding = js_ast.Binding{ - .loc = register_expr.loc, - .data = .{ .b_identifier = &bundle_export_binding }, - }; - decls[0] = js_ast.G.Decl{ - .value = register_expr, - .binding = binding, - }; - var export_var = js_ast.S.Local{ - .decls = &decls, - .is_export = true, - }; - new_stmts[0] = Stmt{ .loc = register_expr.loc, .data = .{ .s_local = &export_var } }; - part.stmts = &new_stmts; + var call_register = E.Call{ + .target = Expr{ + .data = .{ .e_identifier = &target_identifier }, + .loc = logger.Loc{ .start = 0 }, + }, + .args = ®ister_args, + }; + var register_expr = Expr{ .loc = call_register.target.loc, .data = .{ .e_call = &call_register } }; + var decls: [1]js_ast.G.Decl = undefined; + var bundle_export_binding = js_ast.B.Identifier{ .ref = ast.bundle_export_ref.? }; + var binding = js_ast.Binding{ + .loc = register_expr.loc, + .data = .{ .b_identifier = &bundle_export_binding }, + }; + decls[0] = js_ast.G.Decl{ + .value = register_expr, + .binding = binding, + }; + var export_var = js_ast.S.Local{ + .decls = &decls, + .is_export = true, + }; + new_stmts[0] = Stmt{ .loc = register_expr.loc, .data = .{ .s_local = &export_var } }; + part.stmts = &new_stmts; + + var writer = js_printer.NewFileWriter(this.tmpfile); + var symbols: [][]js_ast.Symbol = &([_][]js_ast.Symbol{ast.symbols}); + + // It should only have one part. + ast.parts = ast.parts[ast.parts.len - 1 ..]; + + const write_result = + try js_printer.printCommonJSThreaded( + @TypeOf(writer), + writer, + ast, + js_ast.Symbol.Map.initList(symbols), + &source, + false, + js_printer.Options{ + .to_module_ref = Ref.RuntimeRef, + .bundle_export_ref = ast.bundle_export_ref.?, + .source_path = file_path, + .externals = ast.externals, + .indent = 0, + .module_hash = module_id, + .runtime_imports = ast.runtime_imports, + .prepend_part_value = &prepend_part, + .prepend_part_key = if (needs_prepend_part) closure.body.stmts.ptr else null, + }, + Linker, + &bundler.linker, + &this.write_lock, + std.fs.File, + this.tmpfile, + std.fs.File.getPos, + ); - var writer = js_printer.NewFileWriter(this.tmpfile); - var symbols: [][]js_ast.Symbol = &([_][]js_ast.Symbol{ast.symbols}); + code_offset = write_result.off; + written = write_result.len; - // It should only have one part. - ast.parts = ast.parts[ast.parts.len - 1 ..]; - var written: usize = undefined; - var code_offset: u32 = 0; - const write_result = - try js_printer.printCommonJSThreaded( - @TypeOf(writer), - writer, - ast, - js_ast.Symbol.Map.initList(symbols), - &source, - false, - js_printer.Options{ - .to_module_ref = Ref.RuntimeRef, - .bundle_export_ref = ast.bundle_export_ref.?, - .source_path = file_path, - .externals = ast.externals, - .indent = 0, - .module_hash = module_id, - .runtime_imports = ast.runtime_imports, - .prepend_part_value = &prepend_part, - .prepend_part_key = if (needs_prepend_part) closure.body.stmts.ptr else null, - }, - Linker, - &bundler.linker, - &this.write_lock, - std.fs.File, - this.tmpfile, - std.fs.File.getPos, - ); + // Faster to _not_ do the syscall + // But there's some off-by-one error somewhere and more reliable to just do the lseek + this.tmpfile_byte_offset = write_result.end_off; + } if (comptime isDebug) { - Output.prettyln("{s}/{s} \n", .{ package.name, package_relative_path }); + Output.prettyln("{s}@{s}/{s} - {d}:{d} \n", .{ package.name, package.version, package_relative_path, package.hash, module_id }); Output.flush(); + std.debug.assert(package_relative_path.len > 0); } this.list_lock.lock(); defer this.list_lock.unlock(); - code_offset = write_result.off; - written = write_result.len; - // Faster to _not_ do the syscall - // But there's some off-by-one error somewhere and more reliable to just do the lseek - this.tmpfile_byte_offset = write_result.end_off; const code_length = this.tmpfile_byte_offset - code_offset; - // std.debug.assert(code_length == written); + + if (comptime isDebug) { + std.debug.assert(code_length > 0); + std.debug.assert(package.hash != 0); + std.debug.assert(package.version.len > 0); + std.debug.assert(package.name.len > 0); + std.debug.assert(module_id > 0); + } var package_get_or_put_entry = try this.package_list_map.getOrPut(package.hash); @@ -1279,6 +1396,7 @@ pub fn NewBundler(cache_files: bool) type { null, shared_buffer, ) catch return; + if (entry.contents.len == 0 or (entry.contents.len < 33 and strings.trim(entry.contents, " \n\r").len == 0)) return; const source = logger.Source.initRecycledFile(Fs.File{ .path = file_path, .contents = entry.contents }, bundler.allocator) catch return null; const source_dir = file_path.name.dirWithTrailingSlash(); @@ -1307,13 +1425,26 @@ pub fn NewBundler(cache_files: bool) type { continue; } - _resolved_import.path_pair.primary = Fs.Path.init(std.mem.span(try this.allocator.dupeZ(u8, _resolved_import.path_pair.primary.text))); - try this.queue.upsert( - _resolved_import.hash( - this.bundler.options.loaders.get(_resolved_import.path_pair.primary.name.ext) orelse .file, - ), - _resolved_import.*, - ); + var path = _resolved_import.path() orelse continue; + + const loader_ = this.bundler.options.loader(path.name.ext); + if (!loader_.isJavaScriptLikeOrJSON()) continue; + path.* = Fs.Path.init(std.mem.span(try this.allocator.dupeZ(u8, path.text))); + + if (BundledModuleData.get(this, _resolved_import)) |mod| { + try this.queue.upsert( + mod.module_id, + _resolved_import.*, + ); + } else { + try this.queue.upsert( + _resolved_import.hash( + this.bundler.fs.top_level_dir, + loader_, + ), + _resolved_import.*, + ); + } } else |err| { switch (err) { error.ModuleNotFound => { @@ -1393,7 +1524,12 @@ pub fn NewBundler(cache_files: bool) type { errdefer bundler.resetStore(); - var file_path = resolve_result.path_pair.primary; + var file_path = (resolve_result.pathConst() orelse { + return BuildResolveResultPair{ + .written = 0, + .input_fd = null, + }; + }).*; if (strings.indexOf(file_path.text, bundler.fs.top_level_dir)) |i| { file_path.pretty = file_path.text[i + bundler.fs.top_level_dir.len ..]; @@ -1401,12 +1537,7 @@ pub fn NewBundler(cache_files: bool) type { file_path.pretty = allocator.dupe(u8, bundler.fs.relativeTo(file_path.text)) catch unreachable; } - var old_bundler_allocator = bundler.allocator; - bundler.allocator = allocator; - defer bundler.allocator = old_bundler_allocator; - var old_linker_allocator = bundler.linker.allocator; - defer bundler.linker.allocator = old_linker_allocator; - bundler.linker.allocator = allocator; + bundler.setAllocator(allocator); switch (loader) { .css => { @@ -1432,7 +1563,7 @@ pub fn NewBundler(cache_files: bool) type { .written = brk: { if (bundler.options.hot_module_reloading) { break :brk (try CSSBundlerHMR.bundle( - resolve_result.path_pair.primary.text, + file_path.text, bundler.fs, writer, watcher, @@ -1445,7 +1576,7 @@ pub fn NewBundler(cache_files: bool) type { )).written; } else { break :brk (try CSSBundler.bundle( - resolve_result.path_pair.primary.text, + file_path.text, bundler.fs, writer, watcher, @@ -1462,6 +1593,8 @@ pub fn NewBundler(cache_files: bool) type { }; }, else => { + var old_allocator = bundler.allocator; + bundler.setAllocator(allocator); var result = bundler.parse( allocator, file_path, @@ -1471,12 +1604,14 @@ pub fn NewBundler(cache_files: bool) type { filepath_hash, client_entry_point, ) orelse { + bundler.setAllocator(old_allocator); bundler.resetStore(); return BuildResolveResultPair{ .written = 0, .input_fd = null, }; }; + bundler.setAllocator(old_allocator); try bundler.linker.link(file_path, &result, import_path_format, false); @@ -1505,9 +1640,10 @@ pub fn NewBundler(cache_files: bool) type { return null; } + var file_path = (resolve_result.pathConst() orelse return null).*; + // Step 1. Parse & scan - const loader = bundler.options.loaders.get(resolve_result.path_pair.primary.name.ext) orelse .file; - var file_path = resolve_result.path_pair.primary; + const loader = bundler.options.loader(file_path.name.ext); if (client_entry_point_) |client_entry_point| { file_path = client_entry_point.source.path; @@ -1796,15 +1932,11 @@ pub fn NewBundler(cache_files: bool) type { comptime client_entry_point_enabled: bool, ) !ServeResult { var extension = _extension; - var original_resolver_logger = bundler.resolver.log; - var original_bundler_logger = bundler.log; - - defer bundler.log = original_bundler_logger; - defer bundler.resolver.log = original_resolver_logger; - bundler.log = log; - bundler.linker.allocator = allocator; + var old_log = bundler.log; + var old_allocator = bundler.allocator; - bundler.resolver.log = log; + bundler.setLog(log); + defer bundler.setLog(old_log); if (strings.eqlComptime(relative_path, "__runtime.js")) { return ServeResult{ @@ -1862,8 +1994,10 @@ pub fn NewBundler(cache_files: bool) type { break :brk (try bundler.resolver.resolve(bundler.fs.top_level_dir, absolute_path, .stmt)); }; - const loader = bundler.options.loader(resolved.path_pair.primary.name.ext); - const mime_type_ext = bundler.options.out_extensions.get(resolved.path_pair.primary.name.ext) orelse resolved.path_pair.primary.name.ext; + const path = (resolved.pathConst() orelse return error.ModuleNotFound); + + const loader = bundler.options.loader(path.name.ext); + const mime_type_ext = bundler.options.out_extensions.get(path.name.ext) orelse path.name.ext; switch (loader) { .js, .jsx, .ts, .tsx, .css => { @@ -1882,7 +2016,7 @@ pub fn NewBundler(cache_files: bool) type { }; }, else => { - var abs_path = resolved.path_pair.primary.text; + var abs_path = path.text; const file = try std.fs.openFileAbsolute(abs_path, .{ .read = true }); var stat = try file.stat(); return ServeResult{ @@ -1941,10 +2075,17 @@ pub fn NewBundler(cache_files: bool) type { } const result = bundler.resolver.resolve(bundler.fs.top_level_dir, entry, .entry_point) catch |err| { - Output.printError("Error resolving \"{s}\": {s}\n", .{ entry, @errorName(err) }); + Output.prettyError("Error resolving \"{s}\": {s}\n", .{ entry, @errorName(err) }); continue; }; + if (result.pathConst() == null) { + Output.prettyError("\"{s}\" is disabled due to \"browser\" field in package.json.\n", .{ + entry, + }); + continue; + } + if (bundler.linker.enqueueResolveResult(&result) catch unreachable) { entry_points[entry_point_i] = result; entry_point_i += 1; @@ -2098,12 +2239,13 @@ pub fn NewBundler(cache_files: bool) type { // defer count += 1; if (comptime wrap_entry_point) { - const loader = bundler.options.loaders.get(item.path_pair.primary.name.ext) orelse .file; + var path = item.pathConst() orelse unreachable; + const loader = bundler.options.loader(path.name.ext); if (item.import_kind == .entry_point and loader.supportsClientEntryPoint()) { var client_entry_point = try bundler.allocator.create(ClientEntryPoint); client_entry_point.* = ClientEntryPoint{}; - try client_entry_point.generate(ThisBundler, bundler, item.path_pair.primary.name, bundler.options.framework.?.client); + try client_entry_point.generate(ThisBundler, bundler, path.name, bundler.options.framework.?.client); try bundler.virtual_modules.append(client_entry_point); const entry_point_output_file = bundler.buildWithResolveResultEager( @@ -2602,6 +2744,9 @@ pub const ServerEntryPoint = struct { \\//Auto-generated file \\import * as start from '{s}{s}'; \\export * from '{s}{s}'; + \\if ('default' in start && typeof start.default == 'function') {{ + \\ start.default(); + \\}} , .{ dir_to_use, diff --git a/src/fs.zig b/src/fs.zig index 3936ea933..e59d24b6f 100644 --- a/src/fs.zig +++ b/src/fs.zig @@ -16,7 +16,7 @@ const hash_map = @import("hash_map.zig"); pub const Preallocate = struct { pub const Counts = struct { pub const dir_entry: usize = 512; - pub const files: usize = 1024; + pub const files: usize = 4096; }; }; @@ -810,7 +810,7 @@ pub const FileSystem = struct { ) !File { FileSystem.setMaxFd(file.handle); - if (FeatureFlags.disable_filesystem_cache) { + if (comptime FeatureFlags.disable_filesystem_cache) { _ = std.os.fcntl(file.handle, std.os.F_NOCACHE, 1) catch 0; } @@ -820,6 +820,18 @@ pub const FileSystem = struct { return err; }); + // Skip the pread call for empty files + // Otherwise will get out of bounds errors + // plus it's an unnecessary syscall + if (size == 0) { + if (comptime use_shared_buffer) { + shared_buffer.reset(); + return File{ .path = Path.init(path), .contents = shared_buffer.list.items }; + } else { + return File{ .path = Path.init(path), .contents = "" }; + } + } + var file_contents: []u8 = undefined; // When we're serving a JavaScript-like file over HTTP, we do not want to cache the contents in memory diff --git a/src/hash_map_v2.zig b/src/hash_map_v2.zig index cad4bd36c..e0b84fcd5 100644 --- a/src/hash_map_v2.zig +++ b/src/hash_map_v2.zig @@ -48,6 +48,10 @@ pub fn getAutoHashFn(comptime K: type, comptime Context: type) (fn (Context, K) pub fn getAutoEqlFn(comptime K: type, comptime Context: type) (fn (Context, K, K) bool) { return struct { fn eql(ctx: Context, a: K, b: K) bool { + if (comptime @typeInfo(K) == .Struct and @hasDecl(K, "eql")) { + return a.eql(b); + } + return meta.eql(a, b); } }.eql; @@ -965,7 +969,7 @@ pub fn HashMapUnmanaged( /// fuse the basic blocks after the branch to the basic blocks /// from this function. To encourage that, this function is /// marked as inline. - fn getIndex(self: Self, key: anytype, ctx: anytype) callconv(.Inline) ?usize { + inline fn getIndex(self: Self, key: anytype, ctx: anytype) ?usize { comptime verifyContext(@TypeOf(ctx), @TypeOf(key), K, Hash); if (self.size == 0) { diff --git a/src/import_record.zig b/src/import_record.zig index ae09f8d2f..adb6ea625 100644 --- a/src/import_record.zig +++ b/src/import_record.zig @@ -65,6 +65,8 @@ pub const ImportRecord = struct { is_internal: bool = false, + // This tells the printer that we should print as export var $moduleID = ... + // Instead of using the path. is_bundled: bool = false, // Sometimes the parser creates an import record and decides it isn't needed. diff --git a/src/javascript/jsc/bindings/bindings.zig b/src/javascript/jsc/bindings/bindings.zig index b01690f2a..65a8bef94 100644 --- a/src/javascript/jsc/bindings/bindings.zig +++ b/src/javascript/jsc/bindings/bindings.zig @@ -92,7 +92,7 @@ pub const ZigString = extern struct { pub fn fromStringPointer(ptr: StringPointer, buf: string, to: *ZigString) void { to.* = ZigString{ .len = ptr.length, - .ptr = buf[ptr.offset..ptr.length].ptr, + .ptr = buf[ptr.offset..][0..ptr.length].ptr, }; } diff --git a/src/javascript/jsc/bindings/exports.zig b/src/javascript/jsc/bindings/exports.zig index d58435785..6a8c6328b 100644 --- a/src/javascript/jsc/bindings/exports.zig +++ b/src/javascript/jsc/bindings/exports.zig @@ -4,6 +4,7 @@ const Fs = @import("../../../fs.zig"); const CAPI = @import("../JavaScriptCore.zig"); const JS = @import("../javascript.zig"); const JSBase = @import("../base.zig"); +const ZigURL = @import("../../../query_string_map.zig").URL; const Handler = struct { pub export fn global_signal_handler_fn(sig: i32, info: *const std.os.siginfo_t, ctx_ptr: ?*const c_void) callconv(.C) void { var stdout = std.io.getStdOut(); @@ -347,8 +348,15 @@ pub const ZigStackFrame = extern struct { source_url: ZigString, position: ZigStackFramePosition, enable_color: bool, + origin: *const ZigURL, pub fn format(this: SourceURLFormatter, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { + try writer.writeAll(this.origin.displayProtocol()); + try writer.writeAll("://"); + try writer.writeAll(this.origin.displayHostname()); + try writer.writeAll(":"); + try writer.writeAll(this.origin.port); + try writer.writeAll("/blob:"); try writer.writeAll(this.source_url.slice()); if (this.position.line > -1 and this.position.column_start > -1) { try std.fmt.format(writer, ":{d}:{d}", .{ this.position.line + 1, this.position.column_start }); @@ -416,8 +424,8 @@ pub const ZigStackFrame = extern struct { return NameFormatter{ .function_name = this.function_name, .code_type = this.code_type, .enable_color = enable_color }; } - pub fn sourceURLFormatter(this: *const ZigStackFrame, comptime enable_color: bool) SourceURLFormatter { - return SourceURLFormatter{ .source_url = this.source_url, .position = this.position, .enable_color = enable_color }; + pub fn sourceURLFormatter(this: *const ZigStackFrame, origin: *const ZigURL, comptime enable_color: bool) SourceURLFormatter { + return SourceURLFormatter{ .source_url = this.source_url, .origin = origin, .position = this.position, .enable_color = enable_color }; } }; diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig index 4a3c19964..fa942e4a2 100644 --- a/src/javascript/jsc/javascript.zig +++ b/src/javascript/jsc/javascript.zig @@ -34,6 +34,7 @@ pub const GlobalClasses = [_]type{ ResolveError.Class, Bun.Class, }; +const Blob = @import("../../blob.zig"); pub const Bun = struct { threadlocal var css_imports_list_strings: [512]ZigString = undefined; @@ -345,10 +346,12 @@ pub const VirtualMachine = struct { event_listeners: EventListenerMixin.Map, main: string = "", process: js.JSObjectRef = null, - + blobs: *Blob.Group = undefined, flush_list: std.ArrayList(string), entry_point: ServerEntryPoint = undefined, + has_loaded: bool = false, + pub var vm_loaded = false; pub var vm: *VirtualMachine = undefined; @@ -387,6 +390,7 @@ pub const VirtualMachine = struct { .node_modules = bundler.options.node_modules_bundle, .log = log, .flush_list = std.ArrayList(string).init(allocator), + .blobs = try Blob.Group.init(allocator), }; VirtualMachine.vm.bundler.configureLinker(); @@ -418,6 +422,11 @@ pub const VirtualMachine = struct { threadlocal var source_code_printer: js_printer.BufferPrinter = undefined; threadlocal var source_code_printer_loaded: bool = false; + pub fn preflush(this: *VirtualMachine) void { + // We flush on the next tick so that if there were any errors you can still see them + this.blobs.temporary.reset() catch {}; + } + pub fn flush(this: *VirtualMachine) void { for (this.flush_list.items) |item| { this.allocator.free(item); @@ -650,6 +659,7 @@ pub const VirtualMachine = struct { .stmt, ); ret.result = result; + const result_path = result.pathConst() orelse return error.ModuleNotFound; if (vm.node_modules != null and result.isLikelyNodeModule()) { const node_modules_bundle = vm.node_modules.?; @@ -682,7 +692,7 @@ pub const VirtualMachine = struct { const package_relative_path = vm.bundler.fs.relative( package_json.source.path.name.dirWithTrailingSlash(), - result.path_pair.primary.text, + result_path.text, ); if (node_modules_bundle.findModuleIDInPackage(package, package_relative_path) == null) break :node_module_checker; @@ -693,7 +703,7 @@ pub const VirtualMachine = struct { } } - ret.path = result.path_pair.primary.text; + ret.path = result_path.text; } pub fn resolve(res: *ErrorableZigString, global: *JSGlobalObject, specifier: ZigString, source: ZigString) void { @@ -751,6 +761,11 @@ pub const VirtualMachine = struct { return slice; } + pub fn promiseRejectionTracker(global: *JSGlobalObject, promise: *JSPromise, rejection: JSPromiseRejectionOperation) callconv(.C) JSValue { + VirtualMachine.vm.defaultErrorHandler(promise.result(global.vm())); + return JSValue.jsUndefined(); + } + const main_file_name: string = "bun:main"; threadlocal var errors_stack: [256]*c_void = undefined; pub fn fetch(ret: *ErrorableResolvedSource, global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) void { @@ -775,6 +790,13 @@ pub const VirtualMachine = struct { } ret.result.value = result; + + if (vm.has_loaded) { + vm.blobs.temporary.put(specifier.slice(), .{ .ptr = result.source_code.ptr, .len = result.source_code.len }) catch {}; + } else { + vm.blobs.persistent.put(specifier.slice(), .{ .ptr = result.source_code.ptr, .len = result.source_code.len }) catch {}; + } + ret.success = true; } @@ -977,7 +999,7 @@ pub const VirtualMachine = struct { "<r> <d>at <r>{any} <d>(<r>{any}<d>)<r>\n", allow_ansi_colors, ), - .{ frame.nameFormatter(allow_ansi_colors), frame.sourceURLFormatter(allow_ansi_colors) }, + .{ frame.nameFormatter(allow_ansi_colors), frame.sourceURLFormatter(&vm.bundler.options.origin, allow_ansi_colors) }, ); // if (!frame.position.isInvalid()) { diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig index 760d3ec2b..83a1b0127 100644 --- a/src/js_parser/js_parser.zig +++ b/src/js_parser/js_parser.zig @@ -130,7 +130,7 @@ pub const ImportScanner = struct { // // const keep_unused_imports = !p.options.trim_unused_imports; var did_remove_star_loc = false; - const keep_unused_imports = false; + const keep_unused_imports = !p.options.ts; // TypeScript always trims unused imports. This is important for // correctness since some imports might be fake (only in the type @@ -205,11 +205,7 @@ pub const ImportScanner = struct { } } - if (items_end < st.items.len - 1) { - var list = List(js_ast.ClauseItem).fromOwnedSlice(p.allocator, st.items); - list.shrinkAndFree(items_end); - st.items = list.toOwnedSlice(); - } + st.items = st.items[0..items_end]; } // -- Original Comment -- @@ -285,7 +281,7 @@ pub const ImportScanner = struct { // it's really stupid to import all 1,000 components from that design system // when you just want <Button /> const namespace_ref = st.namespace_ref; - const convert_star_to_clause = !p.options.can_import_from_bundle and p.symbols.items[namespace_ref.inner_index].use_count_estimate == 0; + const convert_star_to_clause = !p.options.enable_bundling and !p.options.can_import_from_bundle and p.symbols.items[namespace_ref.inner_index].use_count_estimate == 0; if (convert_star_to_clause and !keep_unused_imports) { st.star_name_loc = null; @@ -1643,19 +1639,27 @@ const PropertyOpts = struct { }; pub const ScanPassResult = struct { + pub const ParsePassSymbolUse = struct { ref: Ref, used: bool = false, import_record_index: u32 }; + pub const NamespaceCounter = struct { count: u16, import_record_index: u32 }; + pub const ParsePassSymbolUsageMap = std.StringArrayHashMap(ParsePassSymbolUse); import_records: List(ImportRecord), named_imports: js_ast.Ast.NamedImports, + used_symbols: ParsePassSymbolUsageMap, + import_records_to_keep: List(u32), pub fn init(allocator: *std.mem.Allocator) ScanPassResult { return .{ .import_records = List(ImportRecord).init(allocator), .named_imports = js_ast.Ast.NamedImports.init(allocator), + .used_symbols = ParsePassSymbolUsageMap.init(allocator), + .import_records_to_keep = List(u32).init(allocator), }; } pub fn reset(scan_pass: *ScanPassResult) void { scan_pass.named_imports.clearRetainingCapacity(); scan_pass.import_records.shrinkRetainingCapacity(0); + scan_pass.used_symbols.clearRetainingCapacity(); } }; @@ -1714,9 +1718,21 @@ pub const Parser = struct { fn _scanImports(self: *Parser, comptime ParserType: type, scan_pass: *ScanPassResult) !void { var p: ParserType = undefined; + try ParserType.init(self.allocator, self.log, self.source, self.define, self.lexer, self.options, &p); p.import_records = &scan_pass.import_records; p.named_imports = &scan_pass.named_imports; + + // The problem with our scan pass approach is type-only imports. + // We don't have accurate symbol counts. + // So we don't have a good way to distuingish between a type-only import and not. + switch (comptime ParserType) { + TSXImportScanner, TypeScriptImportScanner => { + p.parse_pass_symbol_uses = &scan_pass.used_symbols; + }, + else => {}, + } + // Parse the file in the first pass, but do not bind symbols var opts = ParseStatementOptions{ .is_module_scope = true }; debugl("<p.parseStmtsUpTo>"); @@ -1727,6 +1743,33 @@ pub const Parser = struct { // June 4: "Rest of this took: 8003000" _ = try p.parseStmtsUpTo(js_lexer.T.t_end_of_file, &opts); + // + switch (comptime ParserType) { + TSXImportScanner, TypeScriptImportScanner => { + for (scan_pass.import_records.items) |*import_record| { + // Mark everything as unused + // Except: + // - export * as ns from 'foo'; + // - export * from 'foo'; + // - import 'foo'; + // - import("foo") + // - require("foo") + import_record.is_unused = import_record.kind == .stmt and + !import_record.was_originally_bare_import and + !import_record.calls_run_time_re_export_fn; + } + + var iter = scan_pass.used_symbols.iterator(); + while (iter.next()) |entry| { + const val = entry.value_ptr; + if (val.used) { + scan_pass.import_records.items[val.import_record_index].is_unused = false; + } + } + }, + else => {}, + } + // Symbol use counts are unavailable // So we say "did we parse any JSX?" // if yes, just automatically add the import so that .bun knows to include the file. @@ -2500,7 +2543,7 @@ pub fn NewParser( const ImportRecordList = if (only_scan_imports_and_do_not_visit) *std.ArrayList(ImportRecord) else std.ArrayList(ImportRecord); const NamedImportsType = if (only_scan_imports_and_do_not_visit) *js_ast.Ast.NamedImports else js_ast.Ast.NamedImports; const NeedsJSXType = if (only_scan_imports_and_do_not_visit) bool else void; - + const ParsePassSymbolUsageType = if (only_scan_imports_and_do_not_visit and is_typescript_enabled) *ScanPassResult.ParsePassSymbolUsageMap else void; // P is for Parser! // public only because of Binding.ToExpr return struct { @@ -2552,6 +2595,8 @@ pub fn NewParser( symbol_uses: SymbolUseMap, declared_symbols: List(js_ast.DeclaredSymbol), runtime_imports: RuntimeImports = RuntimeImports{}, + + parse_pass_symbol_uses: ParsePassSymbolUsageType = undefined, // duplicate_case_checker: void, // non_bmp_identifiers: StringBoolMap, // legacy_octal_literals: void, @@ -5186,6 +5231,12 @@ pub fn NewParser( // TODO: import assertions // path.assertions ); + + if (comptime ParsePassSymbolUsageType != void) { + // In the scan pass, we need _some_ way of knowing *not* to mark as unused + p.import_records.items[import_record_index].calls_run_time_re_export_fn = true; + } + try p.lexer.expectOrInsertSemicolon(); return p.s(S.ExportStar{ .namespace_ref = namespace_ref, @@ -5207,6 +5258,12 @@ pub fn NewParser( var path_name = fs.PathName.init(strings.append(p.allocator, "import_", parsedPath.text) catch unreachable); const namespace_ref = p.storeNameInRef(path_name.nonUniqueNameString(p.allocator) catch unreachable) catch unreachable; try p.lexer.expectOrInsertSemicolon(); + + if (comptime ParsePassSymbolUsageType != void) { + // In the scan pass, we need _some_ way of knowing *not* to mark as unused + p.import_records.items[import_record_index].calls_run_time_re_export_fn = true; + } + return p.s(S.ExportFrom{ .items = export_clause.clauses, .is_single_line = export_clause.is_single_line, .namespace_ref = namespace_ref, .import_record_index = import_record_index }, loc); } try p.lexer.expectOrInsertSemicolon(); @@ -5820,6 +5877,12 @@ pub fn NewParser( if (stmt.star_name_loc) |star| { const name = p.loadNameFromRef(stmt.namespace_ref); stmt.namespace_ref = try p.declareSymbol(.import, star, name); + if (comptime ParsePassSymbolUsageType != void) { + p.parse_pass_symbol_uses.put(name, .{ + .ref = stmt.namespace_ref, + .import_record_index = stmt.import_record_index, + }) catch unreachable; + } } else { var path_name = fs.PathName.init(strings.append(p.allocator, "import_", path.text) catch unreachable); const name = try path_name.nonUniqueNameString(p.allocator); @@ -5836,6 +5899,12 @@ pub fn NewParser( const ref = try p.declareSymbol(.import, name_loc.loc, name); try p.is_import_item.put(ref, true); name_loc.ref = ref; + if (comptime ParsePassSymbolUsageType != void) { + p.parse_pass_symbol_uses.put(name, .{ + .ref = ref, + .import_record_index = stmt.import_record_index, + }) catch unreachable; + } } if (stmt.items.len > 0) { @@ -5847,11 +5916,19 @@ pub fn NewParser( try p.is_import_item.put(ref, true); item.name.ref = ref; item_refs.putAssumeCapacity(item.alias, LocRef{ .loc = item.name.loc, .ref = ref }); + + if (comptime ParsePassSymbolUsageType != void) { + p.parse_pass_symbol_uses.put(name, .{ + .ref = ref, + .import_record_index = stmt.import_record_index, + }) catch unreachable; + } } } // Track the items for this namespace try p.import_items_for_namespace.put(stmt.namespace_ref, item_refs); + return p.s(stmt, loc); }, .t_break => { @@ -7293,7 +7370,7 @@ pub fn NewParser( }; const text = p.lexer.identifier; - if (text.len > 0 and !strings.eql(text, "arguments")) { + if (text.len > 0 and !strings.eqlComptime(text, "arguments")) { _name.ref = try p.declareSymbol(.hoisted_function, _name.loc, text); } else { _name.ref = try p.newSymbol(.hoisted_function, text); @@ -7425,6 +7502,12 @@ pub fn NewParser( } pub fn storeNameInRef(p: *P, name: string) !js_ast.Ref { + if (comptime ParsePassSymbolUsageType != void) { + if (p.parse_pass_symbol_uses.getPtr(name)) |res| { + res.used = true; + } + } + if (@ptrToInt(p.source.contents.ptr) <= @ptrToInt(name.ptr) and (@ptrToInt(name.ptr) + name.len) <= (@ptrToInt(p.source.contents.ptr) + p.source.contents.len)) { const start = Ref.toInt(@ptrToInt(name.ptr) - @ptrToInt(p.source.contents.ptr)); const end = Ref.toInt(name.len); @@ -9739,8 +9822,7 @@ pub fn NewParser( // esbuild's version of this function is much more complicated. // I'm not sure why defines is strictly relevant for this case - // and I imagine all the allocations cause some performance - // guessing it's concurrency-related + // do people do <API_URL>? pub fn jsxStringsToMemberExpression(p: *P, loc: logger.Loc, ref: Ref) Expr { p.recordUsage(ref); return p.e(E.Identifier{ .ref = ref }, loc); diff --git a/src/js_printer.zig b/src/js_printer.zig index 82c849df9..42af0cd63 100644 --- a/src/js_printer.zig +++ b/src/js_printer.zig @@ -189,6 +189,8 @@ const ImportVariant = enum { variant = variant.hasDefault(); } } + } else { + variant = variant.hasDefault(); } if (s_import.items.len > 0) { @@ -224,6 +226,8 @@ pub fn NewPrinter( call_target: ?Expr.Data = null, writer: Writer, + has_printed_bundled_import_statement: bool = false, + renamer: rename.Renamer, prev_stmt_tag: Stmt.Tag = .s_empty, @@ -520,6 +524,12 @@ pub fn NewPrinter( backtick_cost += 1; } }, + '\r', '\n' => { + if (comptime isDebug) { + std.debug.assert(allow_backtick); + } + return '`'; + }, else => {}, } i += 1; @@ -1869,11 +1879,13 @@ pub fn NewPrinter( // "=" and ":" are not valid // So we need to check var needs_quoted = !js_lexer.isIdentifierStart(@intCast(js_lexer.CodePoint, key.utf8[0])); - var i: usize = 1; - while (i < key.utf8.len and !needs_quoted) : (i += 1) { - if (!js_lexer.isIdentifierContinue(@intCast(js_lexer.CodePoint, key.utf8[i]))) { - needs_quoted = true; - break; + if (!needs_quoted) { + var i: usize = 1; + while (i < key.utf8.len) : (i += 1) { + if (!js_lexer.isIdentifierContinue(@intCast(js_lexer.CodePoint, key.utf8[i]))) { + needs_quoted = true; + break; + } } } @@ -2118,17 +2130,27 @@ pub fn NewPrinter( if (str.isUTF8()) { p.addSourceMapping(property.key.loc); p.printSpaceBeforeIdentifier(); - p.printIdentifier(str.utf8); - - // Use a shorthand property if the names are the same - switch (property.value.data) { - .b_identifier => |id| { - if (str.eql(string, p.renamer.nameForSymbol(id.ref))) { - p.maybePrintDefaultBindingValue(property); - continue; - } - }, - else => {}, + // Example case: + // const Menu = React.memo(function Menu({ + // aria-label: ariaLabel, + // ^ + // That needs to be: + // "aria-label": ariaLabel, + if (p.canPrintIdentifier(str.utf8)) { + p.printIdentifier(str.utf8); + + // Use a shorthand property if the names are the same + switch (property.value.data) { + .b_identifier => |id| { + if (str.eql(string, p.renamer.nameForSymbol(id.ref))) { + p.maybePrintDefaultBindingValue(property); + continue; + } + }, + else => {}, + } + } else { + p.printQuotedUTF8(str.utf8, false); } } else if (p.canPrintIdentifierUTF16(str.value)) { p.addSourceMapping(property.key.loc); @@ -2245,11 +2267,7 @@ pub fn NewPrinter( if (rewrite_esm_to_cjs and s.func.flags.is_export) { p.printIndent(); - p.printSymbol(p.options.runtime_imports.__export.?); - p.print("."); - p.printSymbol(nameRef); - p.print(" = "); - p.printSymbol(nameRef); + p.printBundledExport(p.renamer.nameForSymbol(nameRef), p.renamer.nameForSymbol(nameRef)); p.printSemicolonAfterStatement(); } }, @@ -2287,11 +2305,7 @@ pub fn NewPrinter( if (rewrite_esm_to_cjs) { if (s.is_export) { p.printIndent(); - p.printSymbol(p.options.runtime_imports.__export.?); - p.print("."); - p.printSymbol(nameRef); - p.print(" = "); - p.printSymbol(nameRef); + p.printBundledExport(p.renamer.nameForSymbol(nameRef), p.renamer.nameForSymbol(nameRef)); p.printSemicolonAfterStatement(); } } @@ -2369,10 +2383,7 @@ pub fn NewPrinter( if (rewrite_esm_to_cjs) { if (func.func.name) |name| { p.printIndent(); - p.printSpaceBeforeIdentifier(); - p.printSymbol(p.options.runtime_imports.__export.?); - p.print(".default = "); - p.printSymbol(name.ref.?); + p.printBundledExport("default", p.renamer.nameForSymbol(name.ref.?)); p.printSemicolonAfterStatement(); } } @@ -2408,10 +2419,7 @@ pub fn NewPrinter( if (class.class.class_name) |name| { p.printIndent(); - p.printSpaceBeforeIdentifier(); - p.printSymbol(p.options.runtime_imports.__export.?); - p.print(".default = "); - p.printSymbol(name.ref.?); + p.printBundledExport("default", p.renamer.nameForSymbol(name.ref.?)); p.printSemicolonAfterStatement(); } } else { @@ -2432,12 +2440,9 @@ pub fn NewPrinter( // module.exports.react = $react(); if (s.alias) |alias| { - p.printSymbol(p.options.runtime_imports.__export.?); - p.print("."); - p.printClauseAlias(alias.original_name); - p.print(" = "); - p.printLoadFromBundle(s.import_record_index); + p.printBundledRexport(alias.original_name, s.import_record_index); p.printSemicolonAfterStatement(); + return; // module.exports = $react(); } else { @@ -2445,7 +2450,9 @@ pub fn NewPrinter( p.print("("); p.printSymbol(p.options.runtime_imports.__export.?); p.print(","); + p.printLoadFromBundle(s.import_record_index); + p.print(")"); p.printSemicolonAfterStatement(); return; @@ -2481,20 +2488,17 @@ pub fn NewPrinter( switch (s.items.len) { 0 => {}, - // __export.prop1 = prop1; + // It unfortunately cannot be so simple as exports.foo = foo; + // If we have a lazy re-export and it's read-only... + // we have to overwrite it via Object.defineProperty 1 => { const item = s.items[0]; - - p.printSymbol(p.options.runtime_imports.__export.?); - p.print("."); - const name = p.renamer.nameForSymbol(item.name.ref.?); - if (!strings.eql(name, item.alias)) { - p.printClauseAlias(item.alias); - } else { - p.printIdentifier(name); - } - p.print(" = "); - p.printIdentifier(name); + const identifier = p.renamer.nameForSymbol(item.name.ref.?); + const name = if (!strings.eql(identifier, item.alias)) + item.alias + else + identifier; + p.printBundledExport(name, identifier); p.printSemicolonAfterStatement(); }, @@ -2978,13 +2982,46 @@ pub fn NewPrinter( return; } } else if (record.is_bundled) { - p.print("import {"); + if (!record.path.is_disabled) { + if (!p.has_printed_bundled_import_statement) { + p.has_printed_bundled_import_statement = true; + p.print("import {"); + + const last = p.import_records.len - 1; + var needs_comma = false; + // This might be a determinsim issue + // But, it's not random + skip: for (p.import_records) |_record, i| { + if (!_record.is_bundled or _record.module_id == 0) continue; - p.printLoadFromBundleWithoutCall(s.import_record_index); + if (i < last) { + // Prevent importing the same module ID twice + // We could use a map but we want to avoid allocating + // and this should be pretty quick since it's just comparing a uint32 + for (p.import_records[i + 1 ..]) |_record2| { + if (_record2.is_bundled and _record2.module_id > 0 and _record2.module_id == _record.module_id) { + continue :skip; + } + } + } - p.print("} from "); - p.printQuotedUTF8(record.path.text, false); - p.printSemicolonAfterStatement(); + if (needs_comma) p.print(", "); + p.printLoadFromBundleWithoutCall(@truncate(u32, i)); + needs_comma = true; + } + + p.print("} from "); + + p.printQuotedUTF8(record.path.text, false); + p.printSemicolonAfterStatement(); + } + } else { + p.print("var "); + + p.printLoadFromBundleWithoutCall(s.import_record_index); + + p.print(" = () => ({default: {}});\n"); + } if (s.items.len > 0) { p.printIndent(); @@ -3248,8 +3285,6 @@ pub fn NewPrinter( .import_items => { p.print("var {"); - var item_count: usize = 0; - for (s.items) |*item, i| { if (i != 0) { p.print(","); @@ -3266,7 +3301,6 @@ pub fn NewPrinter( p.printSpaceBeforeIdentifier(); p.printIdentifier(name); } - item_count += 1; } p.print("}"); @@ -3278,12 +3312,20 @@ pub fn NewPrinter( .import_items_and_default => { p.print("var {"); - const default_name = s.default_name.?.ref.?; - p.print("default: "); - p.printSymbol(default_name); + var need_comma = false; + if (s.default_name) |default_name| { + if (default_name.ref) |ref| { + p.print("default: "); + p.printSymbol(ref); + need_comma = true; + } + } for (s.items) |*item, i| { - p.print(","); + if (need_comma) + p.print(","); + + defer need_comma = true; p.printClauseAlias(item.alias); const name = p.renamer.nameForSymbol(item.name.ref.?); @@ -3392,6 +3434,27 @@ pub fn NewPrinter( p.printLoadFromBundle(require.import_record_index); } + pub fn printBundledRexport(p: *Printer, name: string, import_record_index: u32) void { + p.print("Object.defineProperty("); + p.print("module.exports"); + p.print(","); + p.printQuotedUTF8(name, true); + + p.print(",{get: () => ("); + p.printLoadFromBundle(import_record_index); + p.print("), enumerable: true, configurable: true})"); + } + + pub fn printBundledExport(p: *Printer, name: string, identifier: string) void { + p.print("Object.defineProperty("); + p.print("module.exports"); + p.print(","); + p.printQuotedUTF8(name, true); + p.print(",{get: () => ("); + p.printIdentifier(identifier); + p.print("), enumerable: true, configurable: true})"); + } + pub fn printForLoopInit(p: *Printer, initSt: Stmt) void { switch (initSt.data) { .s_expr => |s| { @@ -3553,16 +3616,21 @@ pub fn NewPrinter( if (rewrite_esm_to_cjs and is_export and decls.len > 0) { p.printIndent(); p.printSpaceBeforeIdentifier(); + p.print("Object.defineProperties("); + p.printSymbol(p.options.runtime_imports.__export.?); + p.print(",{"); for (decls) |decl, i| { - p.printSymbol(p.options.runtime_imports.__export.?); - p.print("."); + p.print("'"); p.printBinding(decl.binding); - p.print(" = "); + p.print("': {get: () => ("); p.printBinding(decl.binding); + p.print("), enumerable: true, configurable: true}"); + if (i < decls.len - 1) { - p.print(","); + p.print(",\n"); } } + p.print("})"); p.printSemicolonAfterStatement(); } } diff --git a/src/linker.zig b/src/linker.zig index 9c0c1d6a1..d6ed3d8fc 100644 --- a/src/linker.zig +++ b/src/linker.zig @@ -190,13 +190,14 @@ pub fn NewLinker(comptime BundlerType: type) type { var externals = std.ArrayList(u32).init(linker.allocator); var needs_bundle = false; const process_import_record_path = file_path.text[0..std.math.min(source_dir.len + 1, file_path.text.len)]; + var first_bundled_index: ?u32 = null; // Step 1. Resolve imports & requires switch (result.loader) { .jsx, .js, .ts, .tsx => { for (result.ast.import_records) |*import_record, _record_index| { if (import_record.is_unused) continue; - + const record_index = @truncate(u32, _record_index); if (comptime !ignore_runtime) { if (strings.eqlComptime(import_record.path.text, Runtime.Imports.Name)) { @@ -224,86 +225,97 @@ pub fn NewLinker(comptime BundlerType: type) type { externals.append(record_index) catch unreachable; continue; } - if (linker.options.node_modules_bundle) |node_modules_bundle| { - const package_json_ = resolved_import.package_json orelse brk: { - if (resolved_import.isLikelyNodeModule()) { - break :brk linker.resolver.packageJSONForResolvedNodeModule(resolved_import); - } - - break :brk null; - }; - if (package_json_) |package_json| { - if (strings.contains(package_json.source.path.name.dirWithTrailingSlash(), "node_modules")) { - if (node_modules_bundle.getPackageIDByName(package_json.name)) |possible_pkg_ids| { - const pkg_id: u32 = brk: { - for (possible_pkg_ids) |pkg_id| { - const pkg = node_modules_bundle.bundle.packages[pkg_id]; - if (pkg.hash == package_json.hash) { - break :brk pkg_id; - } - } - linker.log.addErrorFmt( - null, - logger.Loc.Empty, - linker.allocator, - "\"{s}\" version changed, please regenerate the .bun.\nOld version: \"{s}\"\nNew version: \"{s}\"\nRun this command:\nbun bun", - .{ - package_json.name, - node_modules_bundle.str(node_modules_bundle.bundle.packages[possible_pkg_ids[0]].version), - package_json.version, - }, - ) catch {}; - return error.RebuildJSB; - }; - - const package = &node_modules_bundle.bundle.packages[pkg_id]; - - if (comptime isDebug) { - std.debug.assert(strings.eql(node_modules_bundle.str(package.name), package_json.name)); + const path = resolved_import.pathConst() orelse { + import_record.path.is_disabled = true; + continue; + }; + + const loader = linker.options.loader(path.name.ext); + if (loader.isJavaScriptLikeOrJSON()) { + bundled: { + if (linker.options.node_modules_bundle) |node_modules_bundle| { + const package_json_ = resolved_import.package_json orelse brk: { + if (resolved_import.isLikelyNodeModule()) { + break :brk linker.resolver.packageJSONForResolvedNodeModule(resolved_import); } - const package_relative_path = linker.fs.relative( - package_json.source.path.name.dirWithTrailingSlash(), - resolved_import.path_pair.primary.text, - ); + break :bundled; + }; + if (package_json_) |package_json| { + if (strings.contains(package_json.source.path.name.dirWithTrailingSlash(), "node_modules")) { + if (node_modules_bundle.getPackageIDByName(package_json.name)) |possible_pkg_ids| { + const pkg_id: u32 = brk: { + for (possible_pkg_ids) |pkg_id| { + const pkg = node_modules_bundle.bundle.packages[pkg_id]; + if (pkg.hash == package_json.hash) { + break :brk pkg_id; + } + } + + linker.log.addErrorFmt( + null, + logger.Loc.Empty, + linker.allocator, + "\"{s}\" version changed, please regenerate the .bun.\nOld version: \"{s}\"\nNew version: \"{s}\"\nRun this command:\nbun bun", + .{ + package_json.name, + node_modules_bundle.str(node_modules_bundle.bundle.packages[possible_pkg_ids[0]].version), + package_json.version, + }, + ) catch {}; + return error.RunBunBun; + }; + + const package = &node_modules_bundle.bundle.packages[pkg_id]; + + if (comptime isDebug) { + std.debug.assert(strings.eql(node_modules_bundle.str(package.name), package_json.name)); + } - const found_module = node_modules_bundle.findModuleInPackage(package, package_relative_path) orelse { - linker.log.addErrorFmt( - null, - logger.Loc.Empty, - linker.allocator, - "New dependency import: \"{s}/{s}\"\nPlease run `bun bun` to update the .bun.", - .{ - package_json.name, - package_relative_path, - }, - ) catch {}; - return error.RebuildJSB; - }; - - if (comptime isDebug) { - const module_path = node_modules_bundle.str(found_module.path); - std.debug.assert( - strings.eql( - module_path, - package_relative_path, - ), - ); - } + const package_relative_path = linker.fs.relative( + package_json.source.path.name.dirWithTrailingSlash(), + path.text, + ); + + const found_module = node_modules_bundle.findModuleInPackage(package, package_relative_path) orelse { + linker.log.addErrorFmt( + null, + logger.Loc.Empty, + linker.allocator, + "New dependency import: \"{s}/{s}\"\nPlease run `bun bun` to update the .bun.", + .{ + package_json.name, + package_relative_path, + }, + ) catch {}; + break :bundled; + }; + + if (comptime isDebug) { + const module_path = node_modules_bundle.str(found_module.path); + std.debug.assert( + strings.eql( + module_path, + package_relative_path, + ), + ); + } - import_record.is_bundled = true; - import_record.path.text = linker.nodeModuleBundleImportPath(); - import_record.module_id = found_module.id; - needs_bundle = true; - continue; + import_record.is_bundled = true; + import_record.path.text = linker.nodeModuleBundleImportPath(); + import_record.module_id = found_module.id; + needs_bundle = true; + continue; + } + } } } } } linker.processImportRecord( - linker.options.loader(resolved_import.path_pair.primary.name.ext), + loader, // Include trailing slash process_import_record_path, @@ -564,7 +576,7 @@ pub fn NewLinker(comptime BundlerType: type) type { import_record.path = try linker.generateImportPath( source_dir, - resolve_result.path_pair.primary.text, + resolve_result.pathConst().?.text, if (resolve_result.package_json) |package_json| package_json.version else "", BundlerType.isCacheEnabled and loader == .file, import_path_format, @@ -586,11 +598,12 @@ pub fn NewLinker(comptime BundlerType: type) type { } pub fn resolveResultHashKey(linker: *ThisLinker, resolve_result: *const Resolver.Result) u64 { - var hash_key = resolve_result.path_pair.primary.text; + const path = resolve_result.pathConst() orelse unreachable; + var hash_key = path.text; // Shorter hash key is faster to hash - if (strings.startsWith(resolve_result.path_pair.primary.text, linker.fs.top_level_dir)) { - hash_key = resolve_result.path_pair.primary.text[linker.fs.top_level_dir.len..]; + if (strings.startsWith(path.text, linker.fs.top_level_dir)) { + hash_key = path.text[linker.fs.top_level_dir.len..]; } return std.hash.Wyhash.hash(0, hash_key); diff --git a/src/node_module_bundle.zig b/src/node_module_bundle.zig index 9af0f27de..979c1bba5 100644 --- a/src/node_module_bundle.zig +++ b/src/node_module_bundle.zig @@ -122,7 +122,7 @@ pub const NodeModuleBundle = struct { // Assert we have enough room to add another package std.debug.assert(end < remaining_names.len); entry.value_ptr.* = prev_package_ids_for_name.ptr[0..end]; - entry.value_ptr.*[end] = package_id; + entry.value_ptr.*[end - 1] = package_id; } else { prev_package_ids_for_name = remaining_names[0..1]; prev_package_ids_for_name[0] = package_id; diff --git a/src/options.zig b/src/options.zig index 032d2a38b..05a32cc28 100644 --- a/src/options.zig +++ b/src/options.zig @@ -75,12 +75,23 @@ pub const ExternalModules = struct { .patterns = &([_]WildcardPattern{}), }; - if (platform == .node) { - // TODO: fix this stupid copy - result.node_modules.hash_map.ensureCapacity(NodeBuiltinPatterns.len) catch unreachable; - for (NodeBuiltinPatterns) |pattern| { - result.node_modules.insert(pattern) catch unreachable; - } + switch (platform) { + .node => { + // TODO: fix this stupid copy + result.node_modules.hash_map.ensureCapacity(NodeBuiltinPatterns.len) catch unreachable; + for (NodeBuiltinPatterns) |pattern| { + result.node_modules.insert(pattern) catch unreachable; + } + }, + .bun => { + + // TODO: fix this stupid copy + result.node_modules.hash_map.ensureCapacity(BunNodeBuiltinPatternsCompat.len) catch unreachable; + for (BunNodeBuiltinPatternsCompat) |pattern| { + result.node_modules.insert(pattern) catch unreachable; + } + }, + else => {}, } if (externals.len == 0) { @@ -176,6 +187,65 @@ pub const ExternalModules = struct { "zlib", }; + pub const BunNodeBuiltinPatternsCompat = [_]string{ + "_http_agent", + "_http_client", + "_http_common", + "_http_incoming", + "_http_outgoing", + "_http_server", + "_stream_duplex", + "_stream_passthrough", + "_stream_readable", + "_stream_transform", + "_stream_wrap", + "_stream_writable", + "_tls_common", + "_tls_wrap", + "assert", + "async_hooks", + // "buffer", + "child_process", + "cluster", + "console", + "constants", + "crypto", + "dgram", + "diagnostics_channel", + "dns", + "domain", + "events", + "fs", + "http", + "http2", + "https", + "inspector", + "module", + "net", + "os", + // "path", + "perf_hooks", + // "process", + "punycode", + "querystring", + "readline", + "repl", + "stream", + "string_decoder", + "sys", + "timers", + "tls", + "trace_events", + "tty", + "url", + "util", + "v8", + "vm", + "wasi", + "worker_threads", + "zlib", + }; + pub const NodeBuiltinsMap = std.ComptimeStringMap(bool, .{ .{ "_http_agent", true }, .{ "_http_client", true }, @@ -260,6 +330,13 @@ pub const Platform = enum { }; } + pub inline fn supportsBrowserField(this: Platform) bool { + return switch (this) { + .neutral, .browser, .bun => true, + else => false, + }; + } + const browser_define_value_true = "true"; const browser_define_value_false = "false"; @@ -354,10 +431,12 @@ pub const Platform = enum { array.set(Platform.browser, &listc); array.set(Platform.bun, &listc); + // Original comment: // The neutral platform is for people that don't want esbuild to try to // pick good defaults for their platform. In that case, the list of main // fields is empty by default. You must explicitly configure it yourself. - array.set(Platform.neutral, &([_]string{})); + + array.set(Platform.neutral, &listc); break :brk array; }; @@ -405,6 +484,13 @@ pub const Loader = enum(u3) { }; } + pub fn isJavaScriptLikeOrJSON(loader: Loader) bool { + return switch (loader) { + .jsx, .js, .ts, .tsx, .json => true, + else => false, + }; + } + pub fn forFileName(filename: string, obj: anytype) ?Loader { const ext = std.fs.path.extension(filename); if (ext.len == 0 or (ext.len == 1 and ext[0] == '.')) return null; @@ -1191,7 +1277,7 @@ pub const OutputFile = struct { pub fn initPending(loader: Loader, pending: resolver.Result) OutputFile { return .{ .loader = .file, - .input = pending.path_pair.primary, + .input = pending.pathConst().?.*, .size = 0, .value = .{ .pending = pending }, }; diff --git a/src/panic_handler.zig b/src/panic_handler.zig index 3f49bf6ab..84b66d9be 100644 --- a/src/panic_handler.zig +++ b/src/panic_handler.zig @@ -3,8 +3,6 @@ const logger = @import("logger.zig"); const root = @import("root"); usingnamespace @import("global.zig"); -const USERLAND_PANIC_MESSAGE = "iNtErNaL sErVeR eRrOr"; - /// This function is used by the Zig language code generation and /// therefore must be kept in sync with the compiler implementation. pub fn default_panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) noreturn { diff --git a/src/query_string_map.zig b/src/query_string_map.zig index e9e1f2e6d..1bac8f5ce 100644 --- a/src/query_string_map.zig +++ b/src/query_string_map.zig @@ -18,9 +18,30 @@ pub const URL = struct { search: string = "", searchParams: ?QueryStringMap = null, username: string = "", - port_was_automatically_set: bool = false, + pub fn displayProtocol(this: *const URL) string { + if (this.protocol.len > 0) { + return this.protocol; + } + + if (this.getPort()) |port| { + if (port == 443) { + return "https"; + } + } + + return "http"; + } + + pub fn displayHostname(this: *const URL) string { + if (this.hostname.len > 0) { + return this.hostname; + } + + return "localhost"; + } + pub fn hasHTTPLikeProtocol(this: *const URL) bool { return strings.eqlComptime(this.protocol, "http") or strings.eqlComptime(this.protocol, "https"); } diff --git a/src/resolver/package_json.zig b/src/resolver/package_json.zig index 346b15371..b3b484a84 100644 --- a/src/resolver/package_json.zig +++ b/src/resolver/package_json.zig @@ -9,9 +9,11 @@ const alloc = @import("../alloc.zig"); const fs = @import("../fs.zig"); const resolver = @import("./resolver.zig"); -const MainFieldMap = std.StringHashMap(string); -const BrowserMap = std.StringHashMap(string); -threadlocal var hashed_buf: [2048]u8 = undefined; +// Assume they're not going to have hundreds of main fields or browser map +// so use an array-backed hash table instead of bucketed +const MainFieldMap = std.StringArrayHashMap(string); +const BrowserMap = std.StringArrayHashMap(string); +threadlocal var hashy: [2048]u8 = undefined; pub const PackageJSON = struct { pub const LoadFramework = enum { @@ -50,7 +52,7 @@ pub const PackageJSON = struct { main_fields: MainFieldMap, module_type: options.ModuleType, version: string = "", - hash: u32 = 0, + hash: u32 = 0xDEADBEEF, // Present if the "browser" field is present. This field is intended to be // used by bundlers and lets you redirect the paths of certain 3rd-party @@ -79,6 +81,10 @@ pub const PackageJSON = struct { // browser_map: BrowserMap, + pub inline fn isAppPackage(this: *const PackageJSON) bool { + return this.hash == 0xDEADBEEF; + } + fn loadDefineDefaults( env: *options.Env, json: *const js_ast.E.Object, @@ -400,6 +406,9 @@ pub const PackageJSON = struct { } orelse return null); var package_json = PackageJSON{ + .name = "", + .version = "", + .hash = 0xDEADBEEF, .source = json_source, .module_type = .unknown, .browser_map = BrowserMap.init(r.allocator), @@ -408,13 +417,17 @@ pub const PackageJSON = struct { if (json.asProperty("version")) |version_json| { if (version_json.expr.asString(r.allocator)) |version_str| { - package_json.version = r.allocator.dupe(u8, version_str) catch unreachable; + if (version_str.len > 0) { + package_json.version = r.allocator.dupe(u8, version_str) catch unreachable; + } } } if (json.asProperty("name")) |version_json| { if (version_json.expr.asString(r.allocator)) |version_str| { - package_json.name = r.allocator.dupe(u8, version_str) catch unreachable; + if (version_str.len > 0) { + package_json.name = r.allocator.dupe(u8, version_str) catch unreachable; + } } } @@ -449,14 +462,14 @@ pub const PackageJSON = struct { if ((expr.asString(r.allocator))) |str| { if (str.len > 0) { - package_json.main_fields.put(main, str) catch unreachable; + package_json.main_fields.put(main, r.allocator.dupe(u8, str) catch unreachable) catch unreachable; } } } } // Read the "browser" property, but only when targeting the browser - if (r.opts.platform == .browser) { + if (r.opts.platform.supportsBrowserField()) { // We both want the ability to have the option of CJS vs. ESM and the // option of having node vs. browser. The way to do this is to use the // object literal form of the "browser" field like this: @@ -514,13 +527,29 @@ pub const PackageJSON = struct { // TODO: exports map if (generate_hash) { - std.mem.set(u8, &hashed_buf, 0); - std.mem.copy(u8, &hashed_buf, package_json.name); - hashed_buf[package_json.name.len + 1] = '@'; - std.mem.copy(u8, hashed_buf[package_json.name.len + 1 ..], package_json.version); - package_json.hash = @truncate(u32, std.hash.Wyhash.hash(0, hashed_buf[0 .. package_json.name.len + 1 + package_json.version.len])); + if (package_json.name.len > 0 and package_json.version.len > 0) { + std.mem.set(u8, &hashy, 0); + var used: usize = 0; + std.mem.copy(u8, &hashy, package_json.name); + used = package_json.name.len; + + hashy[used] = '@'; + used += 1; + std.mem.copy(u8, hashy[used..], package_json.version); + used += package_json.version.len; + + package_json.hash = std.hash.Murmur3_32.hash(hashy[0..used]); + } } return package_json; } + + pub fn hashModule(this: *const PackageJSON, module: string) u32 { + var hasher = std.hash.Wyhash.init(0); + hasher.update(std.mem.asBytes(&this.hash)); + hasher.update(module); + + return @truncate(u32, hasher.final()); + } }; diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index 2203ac138..c44608d3b 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -100,6 +100,28 @@ pub const Result = struct { file_fd: StoredFileDescriptorType = 0, import_kind: ast.ImportKind = undefined, + pub fn path(this: *Result) ?*Path { + if (!this.path_pair.primary.is_disabled) + return &this.path_pair.primary; + + if (this.path_pair.secondary) |*second| { + if (!second.is_disabled) return second; + } + + return null; + } + + pub fn pathConst(this: *const Result) ?*const Path { + if (!this.path_pair.primary.is_disabled) + return &this.path_pair.primary; + + if (this.path_pair.secondary) |*second| { + if (!second.is_disabled) return second; + } + + return null; + } + // remember: non-node_modules can have package.json // checking package.json may not be relevant pub fn isLikelyNodeModule(this: *const Result) bool { @@ -147,21 +169,16 @@ pub const Result = struct { } }; - pub fn hash(this: *const Result, loader: options.Loader) u32 { - const HashValue = packed struct { - loader: options.Loader, - len: u8, - path_hash: u21, - }; + pub fn hash(this: *const Result, root_dir: string, loader: options.Loader) u32 { + const module = this.path_pair.primary.text; + const node_module_root = std.fs.path.sep_str ++ "node_modules" ++ std.fs.path.sep_str; + if (strings.lastIndexOf(module, node_module_root)) |end_| { + var end: usize = end_ + node_module_root.len; - return @bitCast( - u32, - HashValue{ - .loader = loader, - .len = @truncate(u8, this.path_pair.primary.text.len), - .path_hash = @truncate(u21, std.hash.Wyhash.hash(0, this.path_pair.primary.text)), - }, - ); + return @truncate(u32, std.hash.Wyhash.hash(0, module[end..])); + } + + return @truncate(u32, std.hash.Wyhash.hash(0, this.path_pair.primary.text)); } }; @@ -882,14 +899,15 @@ pub fn NewResolver(cache_files: bool) type { const base_dir_info = ((r.dirInfoCached(dirname) catch null)) orelse continue; const dir_info = base_dir_info.getEnclosingBrowserScope() orelse continue; const pkg_json = dir_info.package_json orelse continue; - const rel_path = r.fs.relative(pkg_json.source.key_path.text, path.text); + const rel_path = r.fs.relative(pkg_json.source.path.name.dirWithTrailingSlash(), path.text); result.module_type = pkg_json.module_type; result.package_json = result.package_json orelse pkg_json; if (r.checkBrowserMap(pkg_json, rel_path)) |remapped| { if (remapped.len == 0) { path.is_disabled = true; } else if (r.resolveWithoutRemapping(dir_info, remapped, kind)) |remapped_result| { - switch (iter.index) { + // iter.index is the next one, not the prev + switch (iter.index - 1) { 0 => { result.path_pair.primary = remapped_result.path_pair.primary; result.dirname_fd = remapped_result.dirname_fd; @@ -944,7 +962,7 @@ pub fn NewResolver(cache_files: bool) type { r: *ThisResolver, result: *const Result, ) ?*const PackageJSON { - const absolute = result.path_pair.primary.text; + const absolute = (result.pathConst() orelse return null).text; // /foo/node_modules/@babel/standalone/index.js // ^------------^ var end = strings.lastIndexOf(absolute, node_module_root_string) orelse return null; @@ -1361,7 +1379,12 @@ pub fn NewResolver(cache_files: bool) type { } } - const dir_info = try r.dirInfoUncached( + // We must initialize it as empty so that the result index is correct. + // This is important so that browser_scope has a valid index. + var dir_info_ptr = try r.dir_cache.put(&queue_top.result, DirInfo{}); + + try r.dirInfoUncached( + dir_info_ptr, dir_path, dir_entries_option, queue_top.result, @@ -1371,8 +1394,6 @@ pub fn NewResolver(cache_files: bool) type { open_dir.fd, ); - var dir_info_ptr = try r.dir_cache.put(&queue_top.result, dir_info); - if (queue_slice.len == 0) { return dir_info_ptr; @@ -1834,11 +1855,11 @@ pub fn NewResolver(cache_files: bool) type { return MatchResult{ .path_pair = .{ - .primary = auto_main_result.path_pair.primary, - .secondary = _result.path_pair.primary, + .primary = _result.path_pair.primary, + .secondary = auto_main_result.path_pair.primary, }, - .diff_case = auto_main_result.diff_case, - .dirname_fd = auto_main_result.dirname_fd, + .diff_case = _result.diff_case, + .dirname_fd = _result.dirname_fd, .package_json = package_json, }; } else { @@ -2025,6 +2046,7 @@ pub fn NewResolver(cache_files: bool) type { fn dirInfoUncached( r: *ThisResolver, + info: *DirInfo, path: string, _entries: *Fs.FileSystem.RealFS.EntriesOption, _result: allocators.Result, @@ -2032,13 +2054,13 @@ pub fn NewResolver(cache_files: bool) type { parent: ?*DirInfo, parent_index: allocators.IndexType, fd: FileDescriptorType, - ) anyerror!DirInfo { + ) anyerror!void { var result = _result; var rfs: *Fs.FileSystem.RealFS = &r.fs.fs; var entries = _entries.entries; - var info = DirInfo{ + info.* = DirInfo{ .abs_path = path, // .abs_real_path = path, .parent = parent_index, @@ -2054,7 +2076,6 @@ pub fn NewResolver(cache_files: bool) type { // if (entries != null) { if (!strings.eqlComptime(base, "node_modules")) { if (entries.getComptimeQuery("node_modules")) |entry| { - // the catch might be wrong! info.has_node_modules = (entry.entry.kind(rfs)) == .dir; } } @@ -2157,8 +2178,6 @@ pub fn NewResolver(cache_files: bool) type { if (info.tsconfig_json == null and parent != null) { info.tsconfig_json = parent.?.tsconfig_json; } - - return info; } }; } @@ -2197,3 +2216,15 @@ const Dirname = struct { return path[0 .. end_index + 1]; } }; + +test "murmur" { + var str = try std.heap.c_allocator.alloc(u8, "swiper@6.8.2swiper.cjs.js".len); + var str2 = try std.heap.c_allocator.alloc(u8, "swiper@6.8.2swiper.cjs.js".len); + std.mem.copy(u8, str, "swiper@6.8.2swiper.cjs.js"); + std.mem.copy(u8, str2, "swiper@6.8.2swiper.cjs.js"); + + try std.testing.expectEqual( + std.hash.murmur.Murmur3_32.hash(str), + std.hash.murmur.Murmur3_32.hash(str2), + ); +} diff --git a/src/runtime.js b/src/runtime.js index d3416cbe4..96c1c2d6f 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -7,7 +7,7 @@ var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; export var __markAsModule = (target) => - __defProp(target, "__esModule", { value: true }); + __defProp(target, "__esModule", { value: true, configurable: true }); // lazy require to prevent loading one icon from a design system export var $$lzy = (target, module, props) => { @@ -16,6 +16,7 @@ export var $$lzy = (target, module, props) => { __defProp(target, key, { get: () => module()[props[key]], enumerable: true, + configurable: true, }); } return target; @@ -28,8 +29,8 @@ export var __toModule = (module) => { module != null ? __create(__getProtoOf(module)) : {}, "default", module && module.__esModule && "default" in module - ? { get: () => module.default, enumerable: true } - : { value: module, enumerable: true } + ? { get: () => module.default, enumerable: true, configurable: true } + : { value: module, enumerable: true, configurable: true } ) ), module @@ -64,6 +65,7 @@ export var __commonJS = (cb, name) => { return mod.exports; }, enumerable: true, + configurable: true, }); // If it's a namespace export without .default, pretend .default is the same as mod.exports } else if ( @@ -79,6 +81,7 @@ export var __commonJS = (cb, name) => { defaultValue = value; }, enumerable: true, + configurable: true, }); } @@ -175,6 +178,7 @@ export var __reExport = (target, module, desc) => { if (!__hasOwnProp.call(target, key) && key !== "default") __defProp(target, key, { get: () => module[key], + configurable: true, enumerable: !(desc = __getOwnPropDesc(module, key)) || desc.enumerable, }); diff --git a/src/runtime.version b/src/runtime.version index e76ed155e..1d355c2cd 100644 --- a/src/runtime.version +++ b/src/runtime.version @@ -1 +1 @@ -3b71ea301d8e2123
\ No newline at end of file +ffa36d1436d2546f
\ No newline at end of file diff --git a/src/string_immutable.zig b/src/string_immutable.zig index bac00ba45..8706f4053 100644 --- a/src/string_immutable.zig +++ b/src/string_immutable.zig @@ -305,7 +305,7 @@ pub fn eqlComptime(self: string, comptime alt: anytype) bool { second == std.mem.readIntNative(u16, self[4..6]); }, 5, 7 => { - const check = std.mem.readIntNative(u32, alt[0..4]); + const check = comptime std.mem.readIntNative(u32, alt[0..4]); if (self.len != alt.len or std.mem.readIntNative(u32, self[0..4]) != check) { return false; } @@ -316,7 +316,7 @@ pub fn eqlComptime(self: string, comptime alt: anytype) bool { return true; }, 8 => { - const check = std.mem.readIntNative(u64, alt[0..alt.len]); + const check = comptime std.mem.readIntNative(u64, alt[0..alt.len]); return self.len == alt.len and std.mem.readIntNative(u64, self[0..8]) == check; }, 9...11 => { @@ -332,13 +332,13 @@ pub fn eqlComptime(self: string, comptime alt: anytype) bool { return true; }, 12 => { - const first = std.mem.readIntNative(u64, alt[0..8]); - const second = std.mem.readIntNative(u32, alt[8..12]); + const first = comptime std.mem.readIntNative(u64, alt[0..8]); + const second = comptime std.mem.readIntNative(u32, alt[8..12]); return (self.len == alt.len) and first == std.mem.readIntNative(u64, self[0..8]) and second == std.mem.readIntNative(u32, self[8..12]); }, 13...15 => { - const first = std.mem.readIntNative(u64, alt[0..8]); - const second = std.mem.readIntNative(u32, alt[8..12]); + const first = comptime std.mem.readIntNative(u64, alt[0..8]); + const second = comptime std.mem.readIntNative(u32, alt[8..12]); if (self.len != alt.len or first != std.mem.readIntNative(u64, self[0..8]) or second != std.mem.readIntNative(u32, self[8..12])) { return false; @@ -351,8 +351,8 @@ pub fn eqlComptime(self: string, comptime alt: anytype) bool { return true; }, 16 => { - const first = std.mem.readIntNative(u64, alt[0..8]); - const second = std.mem.readIntNative(u64, alt[8..15]); + const first = comptime std.mem.readIntNative(u64, alt[0..8]); + const second = comptime std.mem.readIntNative(u64, alt[8..15]); return (self.len == alt.len) and first == std.mem.readIntNative(u64, self[0..8]) and second == std.mem.readIntNative(u64, self[8..16]); }, else => { diff --git a/src/test/fixtures/browsermap-false.ts b/src/test/fixtures/browsermap-false.ts new file mode 100644 index 000000000..aac72e325 --- /dev/null +++ b/src/test/fixtures/browsermap-false.ts @@ -0,0 +1,3 @@ +import { Foo } from "browsermap"; + +console.log(Foo); diff --git a/src/test/fixtures/main-field.ts b/src/test/fixtures/main-field.ts new file mode 100644 index 000000000..5f69721c8 --- /dev/null +++ b/src/test/fixtures/main-field.ts @@ -0,0 +1,3 @@ +import Algolia from "algoliasearch/lite"; + +console.log(Algolia); diff --git a/src/test/fixtures/package.json b/src/test/fixtures/package.json deleted file mode 100644 index 8555c8500..000000000 --- a/src/test/fixtures/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "repo", - "dependencies": { - "react": "^16.8.4", - "react-dom": "^16.8.4" - } -} diff --git a/src/test/fixtures/type-only-import.ts b/src/test/fixtures/type-only-import.ts new file mode 100644 index 000000000..af7c11a12 --- /dev/null +++ b/src/test/fixtures/type-only-import.ts @@ -0,0 +1,33 @@ +import { Foo } from "bacon"; +import React from "react"; +import * as Boom from "react"; +import { createElement } from "react"; +export const hello: Foo = React.createElement("div"); + +export const bacon: (foo: (what: Foo) => (the: Foo) => Foo) => Foo = ( + foo: Foo +) => { + return createElement(true); +}; + +export function funcBacon(foo: (what: Foo) => (the: Foo) => void) { + this.Foo = foo; + Boom(); +} + +export abstract class Bar implements Foo { + bacon: Foo; + what: Foo; +} + +export class Broke implements Foo { + bacon: Foo; + what: Foo; +} +export interface Baz extends Foo { + foo: Foo; + bar: Foo; + boop: Foo; + Foo: Foo; +} +export interface Baz extends Foo {} diff --git a/src/test/project.zig b/src/test/project.zig index 5715778c1..26dadbc94 100644 --- a/src/test/project.zig +++ b/src/test/project.zig @@ -1464,3 +1464,142 @@ pub const three = [_][]const u8{ "/project/node_modules/three/src/extras/curves/CatmullRomCurve3.js", "/project/node_modules/three/src/extras/curves/SplineCurve.js", }; + +pub const next = [_][]const u8{ + "next@11.1.0/app.js - 3424158524:2890943422", + "next@11.1.0/app.js - 3424158524:2890943422", + "next@11.1.0/dist/client/head-manager.js - 3424158524:2201168507", + "next@11.1.0/dist/client/head-manager.js - 3424158524:2201168507", + "next@11.1.0/dist/client/link.js - 3424158524:3978876338", + "next@11.1.0/dist/client/link.js - 3424158524:3978876338", + "next@11.1.0/dist/client/normalize-trailing-slash.js - 3424158524:3949960510", + "next@11.1.0/dist/client/normalize-trailing-slash.js - 3424158524:3949960510", + "next@11.1.0/dist/client/page-loader.js - 3424158524:3974401562", + "next@11.1.0/dist/client/request-idle-callback.js - 3424158524:2155089364", + "next@11.1.0/dist/client/request-idle-callback.js - 3424158524:2155089364", + "next@11.1.0/dist/client/route-loader.js - 3424158524:868049608", + "next@11.1.0/dist/client/route-loader.js - 3424158524:868049608", + "next@11.1.0/dist/client/route-loader.js - 3424158524:868049608", + "next@11.1.0/dist/client/router.js - 3424158524:60654157", + "next@11.1.0/dist/client/router.js - 3424158524:60654157", + "next@11.1.0/dist/client/router.js - 3424158524:60654157", + "next@11.1.0/dist/client/script.js - 3424158524:2971760940", + "next@11.1.0/dist/client/use-intersection.js - 3424158524:1893142411", + "next@11.1.0/dist/client/use-intersection.js - 3424158524:1893142411", + "next@11.1.0/dist/client/with-router.js - 3424158524:3574523301", + "next@11.1.0/dist/client/with-router.js - 3424158524:3574523301", + "next@11.1.0/dist/compiled/path-to-regexp/index.js - 3424158524:4292453228", + "next@11.1.0/dist/compiled/path-to-regexp/index.js - 3424158524:4292453228", + "next@11.1.0/dist/pages/_app.js - 3424158524:1831562171", + "next@11.1.0/dist/pages/_app.js - 3424158524:1831562171", + "next@11.1.0/dist/pages/_document.js - 3424158524:1843055786", + "next@11.1.0/dist/server/denormalize-page-path.js - 3424158524:2078268279", + "next@11.1.0/dist/server/denormalize-page-path.js - 3424158524:2078268279", + "next@11.1.0/dist/server/get-page-files.js - 3424158524:3103205117", + "next@11.1.0/dist/server/htmlescape.js - 3424158524:3619675719", + "next@11.1.0/dist/server/normalize-page-path.js - 3424158524:79382061", + "next@11.1.0/dist/server/utils.js - 3424158524:3170288217", + "next@11.1.0/dist/shared/lib/amp-context.js - 3424158524:2231212210", + "next@11.1.0/dist/shared/lib/amp-context.js - 3424158524:2231212210", + "next@11.1.0/dist/shared/lib/amp-context.js - 3424158524:2231212210", + "next@11.1.0/dist/shared/lib/amp.js - 3424158524:3972854680", + "next@11.1.0/dist/shared/lib/amp.js - 3424158524:3972854680", + "next@11.1.0/dist/shared/lib/constants.js - 3424158524:3766949957", + "next@11.1.0/dist/shared/lib/document-context.js - 3424158524:3503028665", + "next@11.1.0/dist/shared/lib/head-manager-context.js - 3424158524:99574170", + "next@11.1.0/dist/shared/lib/head-manager-context.js - 3424158524:99574170", + "next@11.1.0/dist/shared/lib/head-manager-context.js - 3424158524:99574170", + "next@11.1.0/dist/shared/lib/head-manager-context.js - 3424158524:99574170", + "next@11.1.0/dist/shared/lib/head.js - 3424158524:1660462722", + "next@11.1.0/dist/shared/lib/head.js - 3424158524:1660462722", + "next@11.1.0/dist/shared/lib/i18n/detect-domain-locale.js - 3424158524:2360522531", + "next@11.1.0/dist/shared/lib/i18n/normalize-locale-path.js - 3424158524:2987178093", + "next@11.1.0/dist/shared/lib/i18n/normalize-locale-path.js - 3424158524:2987178093", + "next@11.1.0/dist/shared/lib/loadable-context.js - 3424158524:3504182001", + "next@11.1.0/dist/shared/lib/loadable-context.js - 3424158524:3504182001", + "next@11.1.0/dist/shared/lib/loadable.js - 3424158524:3055601316", + "next@11.1.0/dist/shared/lib/mitt.js - 3424158524:697603371", + "next@11.1.0/dist/shared/lib/mitt.js - 3424158524:697603371", + "next@11.1.0/dist/shared/lib/mitt.js - 3424158524:697603371", + "next@11.1.0/dist/shared/lib/router-context.js - 3424158524:2677379782", + "next@11.1.0/dist/shared/lib/router-context.js - 3424158524:2677379782", + "next@11.1.0/dist/shared/lib/router-context.js - 3424158524:2677379782", + "next@11.1.0/dist/shared/lib/router-context.js - 3424158524:2677379782", + "next@11.1.0/dist/shared/lib/router/router.js - 3424158524:784078930", + "next@11.1.0/dist/shared/lib/router/router.js - 3424158524:784078930", + "next@11.1.0/dist/shared/lib/router/router.js - 3424158524:784078930", + "next@11.1.0/dist/shared/lib/router/utils/format-url.js - 3424158524:2249819031", + "next@11.1.0/dist/shared/lib/router/utils/format-url.js - 3424158524:2249819031", + "next@11.1.0/dist/shared/lib/router/utils/get-asset-path-from-route.js - 3424158524:1494341198", + "next@11.1.0/dist/shared/lib/router/utils/get-asset-path-from-route.js - 3424158524:1494341198", + "next@11.1.0/dist/shared/lib/router/utils/get-asset-path-from-route.js - 3424158524:1494341198", + "next@11.1.0/dist/shared/lib/router/utils/is-dynamic.js - 3424158524:3652061346", + "next@11.1.0/dist/shared/lib/router/utils/is-dynamic.js - 3424158524:3652061346", + "next@11.1.0/dist/shared/lib/router/utils/is-dynamic.js - 3424158524:3652061346", + "next@11.1.0/dist/shared/lib/router/utils/parse-relative-url.js - 3424158524:84921275", + "next@11.1.0/dist/shared/lib/router/utils/parse-relative-url.js - 3424158524:84921275", + "next@11.1.0/dist/shared/lib/router/utils/parse-url.js - 3424158524:2943870410", + "next@11.1.0/dist/shared/lib/router/utils/parse-url.js - 3424158524:2943870410", + "next@11.1.0/dist/shared/lib/router/utils/path-match.js - 3424158524:1335539408", + "next@11.1.0/dist/shared/lib/router/utils/path-match.js - 3424158524:1335539408", + "next@11.1.0/dist/shared/lib/router/utils/prepare-destination.js - 3424158524:2905198601", + "next@11.1.0/dist/shared/lib/router/utils/prepare-destination.js - 3424158524:2905198601", + "next@11.1.0/dist/shared/lib/router/utils/querystring.js - 3424158524:2585795157", + "next@11.1.0/dist/shared/lib/router/utils/querystring.js - 3424158524:2585795157", + "next@11.1.0/dist/shared/lib/router/utils/querystring.js - 3424158524:2585795157", + "next@11.1.0/dist/shared/lib/router/utils/resolve-rewrites.js - 3424158524:2049321565", + "next@11.1.0/dist/shared/lib/router/utils/resolve-rewrites.js - 3424158524:2049321565", + "next@11.1.0/dist/shared/lib/router/utils/route-matcher.js - 3424158524:3388378419", + "next@11.1.0/dist/shared/lib/router/utils/route-matcher.js - 3424158524:3388378419", + "next@11.1.0/dist/shared/lib/router/utils/route-regex.js - 3424158524:1570670727", + "next@11.1.0/dist/shared/lib/router/utils/route-regex.js - 3424158524:1570670727", + "next@11.1.0/dist/shared/lib/runtime-config.js - 3424158524:4205818429", + "next@11.1.0/dist/shared/lib/side-effect.js - 3424158524:3871282960", + "next@11.1.0/dist/shared/lib/side-effect.js - 3424158524:3871282960", + "next@11.1.0/dist/shared/lib/utils.js - 3424158524:2498823793", + "next@11.1.0/dist/shared/lib/utils.js - 3424158524:2498823793", + "next@11.1.0/dist/shared/lib/utils.js - 3424158524:2498823793", + "next@11.1.0/dist/shared/lib/utils.js - 3424158524:2498823793", + "next@11.1.0/document.js - 3424158524:761357561", + "next@11.1.0/head.js - 3424158524:4027675732", + "next@11.1.0/head.js - 3424158524:4027675732", + "next@11.1.0/link.js - 3424158524:3847679594", + "next@11.1.0/link.js - 3424158524:3847679594", + "next@11.1.0/router.js - 3424158524:2467530242", + "next@11.1.0/router.js - 3424158524:2467530242", + "object-assign@4.1.1/index.js - 1106322050:1257305923", + "object-assign@4.1.1/index.js - 1106322050:1257305923", + "react-dom@17.0.2/cjs/react-dom-server.browser.development.js - 2917057216:4251258747", + "react-dom@17.0.2/cjs/react-dom.development.js - 2917057216:2729826485", + "react-dom@17.0.2/index.js - 2917057216:4152798548", + "react-dom@17.0.2/server.browser.js - 2917057216:2336742101", + "react-is@17.0.2/cjs/react-is.development.js - 1177198225:1925584658", + "react-is@17.0.2/cjs/react-is.development.js - 1177198225:1925584658", + "react-is@17.0.2/index.js - 1177198225:3919220786", + "react-is@17.0.2/index.js - 1177198225:3919220786", + "react-is@17.0.2/index.js - 1177198225:3919220786", + "react-refresh@0.8.3/cjs/react-refresh-runtime.development.js - 1106322050:2742290347", + "react-refresh@0.8.3/runtime.js - 1106322050:1039122438", + "react@17.0.2/cjs/react-jsx-dev-runtime.development.js - 2465707714:1705570593", + "react@17.0.2/cjs/react-jsx-dev-runtime.development.js - 2465707714:1705570593", + "react@17.0.2/cjs/react.development.js - 2465707714:1390143369", + "react@17.0.2/cjs/react.development.js - 2465707714:1390143369", + "react@17.0.2/index.js - 2465707714:1063423392", + "react@17.0.2/index.js - 2465707714:1063423392", + "react@17.0.2/index.js - 2465707714:1063423392", + "react@17.0.2/index.js - 2465707714:1063423392", + "react@17.0.2/jsx-dev-runtime.js - 2465707714:3464951857", + "react@17.0.2/jsx-dev-runtime.js - 2465707714:3464951857", + "scheduler@0.20.2/cjs/scheduler-tracing.development.js - 2917057216:1128698082", + "scheduler@0.20.2/cjs/scheduler.development.js - 2917057216:4082470097", + "scheduler@0.20.2/index.js - 2917057216:3977196876", + "scheduler@0.20.2/tracing.js - 2917057216:2401030364", + "string-hash@1.1.3/index.js - 2958931479:1647663124", + "styled-jsx@4.0.0/dist/lib/stylesheet.js - 2917057216:205078822", + "styled-jsx@4.0.0/dist/server.js - 2917057216:2807236644", + "styled-jsx@4.0.0/dist/style.js - 2917057216:3820693621", + "styled-jsx@4.0.0/dist/stylesheet-registry.js - 2917057216:2283650446", + "styled-jsx@4.0.0/server.js - 2917057216:3921567966", + "use-subscription@1.5.1/cjs/use-subscription.development.js - 1836582978:3015515293", + "use-subscription@1.5.1/index.js - 1836582978:2982917928", +}; |