diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2aa1a1b113cece..03a2b4d663fc78 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -207,7 +207,7 @@ $ git clone https://github.com/oven-sh/WebKit vendor/WebKit # Make a debug build of JSC. This will output build artifacts in ./vendor/WebKit/WebKitBuild/Debug # Optionally, you can use `make jsc` for a release build -$ make jsc-debug && rm vendor/WebKit/WebKitBuild/Debug/JavaScriptCore/DerivedSources/inspector/InspectorProtocolObjects.h +$ make jsc-debug # Build bun with the local JSC build $ bun run build:local diff --git a/build.zig b/build.zig index 3d5c0b659fa089..abcefc752bd6d5 100644 --- a/build.zig +++ b/build.zig @@ -473,11 +473,6 @@ pub fn addInstallObjectFile( name: []const u8, out_mode: ObjectFormat, ) *Step { - if (@import("builtin").os.tag != .windows and std.posix.getenvZ("COMPILE_ERRORS_ONLY") != null) { - const failstep = b.addSystemCommand(&.{"COMPILE_ERRORS_ONLY set but there were no compile errors"}); - failstep.step.dependOn(&compile.step); - return &failstep.step; - } // bin always needed to be computed or else the compilation will do nothing. zig build system bug? const bin = compile.getEmittedBin(); return &b.addInstallFile(switch (out_mode) { diff --git a/cmake/tools/SetupWebKit.cmake b/cmake/tools/SetupWebKit.cmake index 4422e25376825b..57ce5f1eb9b0c6 100644 --- a/cmake/tools/SetupWebKit.cmake +++ b/cmake/tools/SetupWebKit.cmake @@ -30,8 +30,6 @@ if(WEBKIT_LOCAL) ${WEBKIT_PATH} ${WEBKIT_PATH}/JavaScriptCore/Headers/JavaScriptCore ${WEBKIT_PATH}/JavaScriptCore/PrivateHeaders - ${WEBKIT_PATH}/JavaScriptCore/DerivedSources/inspector - ${WEBKIT_PATH}/JavaScriptCore/PrivateHeaders/JavaScriptCore ${WEBKIT_PATH}/bmalloc/Headers ${WEBKIT_PATH}/WTF/Headers ) diff --git a/src/analyze_transpiled_module.zig b/src/analyze_transpiled_module.zig deleted file mode 100644 index 72e241bd9f6b65..00000000000000 --- a/src/analyze_transpiled_module.zig +++ /dev/null @@ -1,477 +0,0 @@ -const std = @import("std"); -const bun = @import("bun.zig"); -const js_ast = bun.JSAst; -const Ast = js_ast.Ast; - -pub const RecordKind = enum(u8) { - /// var_name - declared_variable, - /// let_name - lexical_variable, - /// module_name, import_name, local_name - import_info_single, - /// module_name, import_name = '*', local_name - import_info_namespace, - /// export_name, import_name, module_name - export_info_indirect, - /// export_name, local_name, padding (for local => indirect conversion) - export_info_local, - /// export_name, module_name - export_info_namespace, - /// module_name - export_info_star, - _, - - pub fn len(record: RecordKind) !usize { - return switch (record) { - .declared_variable, .lexical_variable => 1, - .import_info_single => 3, - .import_info_namespace => 3, - .export_info_indirect => 3, - .export_info_local => 3, - .export_info_namespace => 2, - .export_info_star => 1, - else => return error.InvalidRecordKind, - }; - } -}; - -pub const ModuleInfoDeserialized = struct { - strings_buf: []const u8, - strings_lens: []align(1) const u32, - requested_modules_keys: []align(1) const StringID, - requested_modules_values: []align(1) const ModuleInfo.FetchParameters, - buffer: []align(1) const StringID, - record_kinds: []align(1) const RecordKind, - contains_import_meta: bool, - owner: union(enum) { - module_info, - allocated_slice: struct { - slice: []const u8, - allocator: std.mem.Allocator, - }, - }, - dead: bool = false, - - pub fn deinit(self: *ModuleInfoDeserialized) void { - switch (self.owner) { - .module_info => { - const mi: *ModuleInfo = @fieldParentPtr("_deserialized", self); - mi.destroy(); - }, - .allocated_slice => |as| { - as.allocator.free(as.slice); - as.allocator.destroy(self); - }, - } - } - - inline fn eat(rem: *[]const u8, len: usize) ![]const u8 { - if (rem.*.len < len) return error.BadModuleInfo; - const res = rem.*[0..len]; - rem.* = rem.*[len..]; - return res; - } - inline fn eatC(rem: *[]const u8, comptime len: usize) !*const [len]u8 { - if (rem.*.len < len) return error.BadModuleInfo; - const res = rem.*[0..len]; - rem.* = rem.*[len..]; - return res; - } - pub fn create(source: []const u8, gpa: std.mem.Allocator) !*ModuleInfoDeserialized { - std.log.info("ModuleInfoDeserialized.create", .{}); - var rem = try gpa.dupe(u8, source); - errdefer gpa.free(rem); - var res = try gpa.create(ModuleInfoDeserialized); - errdefer res.deinit(); - - const record_kinds_len = std.mem.readInt(u32, try eatC(&rem, 4), .little); - const record_kinds = std.mem.bytesAsSlice(RecordKind, try eat(&rem, record_kinds_len * @sizeOf(RecordKind))); - const buffer_len = std.mem.readInt(u32, try eatC(&rem, 4), .little); - const buffer = std.mem.bytesAsSlice(StringID, try eat(&rem, buffer_len * @sizeOf(StringID))); - const requested_modules_len = std.mem.readInt(u32, try eatC(&rem, 4), .little); - const requested_modules_keys = std.mem.bytesAsSlice(StringID, try eat(&rem, requested_modules_len * @sizeOf(StringID))); - const requested_modules_values = std.mem.bytesAsSlice(ModuleInfo.FetchParameters, try eat(&rem, requested_modules_len * @sizeOf(ModuleInfo.FetchParameters))); - const contains_import_meta = (try eatC(&rem, 1))[0] != 0; - const strings_len = std.mem.readInt(u32, try eatC(&rem, 4), .little); - const strings_lens = std.mem.bytesAsSlice(u32, try eat(&rem, strings_len * @sizeOf(u32))); - const strings_buf = rem; - - res.* = .{ - .strings_buf = strings_buf, - .strings_lens = strings_lens, - .requested_modules_keys = requested_modules_keys, - .requested_modules_values = requested_modules_values, - .buffer = buffer, - .record_kinds = record_kinds, - .contains_import_meta = contains_import_meta, - .owner = .{ .allocated_slice = .{ - .slice = source, - .allocator = gpa, - } }, - }; - return res; - } - pub fn serialize(self: *const ModuleInfoDeserialized, writer: anytype) !void { - try writer.writeInt(u32, @truncate(self.record_kinds.len), .little); - try writer.writeAll(std.mem.sliceAsBytes(self.record_kinds)); - try writer.writeInt(u32, @truncate(self.buffer.len), .little); - try writer.writeAll(std.mem.sliceAsBytes(self.buffer)); - - try writer.writeInt(u32, @truncate(self.requested_modules_keys.len), .little); - try writer.writeAll(std.mem.sliceAsBytes(self.requested_modules_keys)); - try writer.writeAll(std.mem.sliceAsBytes(self.requested_modules_values)); - - try writer.writeInt(u8, @intFromBool(self.contains_import_meta), .little); - - try writer.writeInt(u32, @truncate(self.strings_lens.len), .little); - try writer.writeAll(std.mem.sliceAsBytes(self.strings_lens)); - try writer.writeAll(self.strings_buf); - } -}; - -const StringMapKey = enum(u32) { - get_or_put = std.math.maxInt(u32), - _, -}; -pub const StringContext = struct { - get_or_put_key: []const u8, - strings_buf: []const u8, - strings_lens: []const u32, - - pub fn hash(self: @This(), s: StringMapKey) u32 { - bun.assert(s == .get_or_put); - return @as(u32, @truncate(std.hash.Wyhash.hash(0, self.get_or_put_key))); - } - pub fn eql(self: @This(), fetch_key: StringMapKey, item_key: StringMapKey, item_i: usize) bool { - bun.assert(item_key != .get_or_put); - bun.assert(fetch_key == .get_or_put); - return bun.strings.eqlLong(self.get_or_put_key, self.strings_buf[@intFromEnum(item_key)..][0..self.strings_lens[item_i]], true); - } -}; - -pub const ModuleInfo = struct { - /// all strings in wtf-8. index in hashmap = StringID - gpa: std.mem.Allocator, - strings_map: std.ArrayHashMapUnmanaged(StringMapKey, void, StringContext, true), - strings_buf: std.ArrayListUnmanaged(u8), - strings_lens: std.ArrayListUnmanaged(u32), - requested_modules: std.AutoArrayHashMap(StringID, FetchParameters), - buffer: std.ArrayList(StringID), - record_kinds: std.ArrayList(RecordKind), - exported_names: std.AutoArrayHashMapUnmanaged(StringID, void), - contains_import_meta: bool, - finalized: bool = false, - - _deserialized: ModuleInfoDeserialized = undefined, - - pub fn asDeserialized(self: *ModuleInfo) *ModuleInfoDeserialized { - bun.assert(self.finalized); - return &self._deserialized; - } - - pub const FetchParameters = enum(u32) { - none = std.math.maxInt(u32), - javascript = std.math.maxInt(u32) - 1, - webassembly = std.math.maxInt(u32) - 2, - json = std.math.maxInt(u32) - 3, - _, // host_defined: cast to StringID - pub fn hostDefined(value: StringID) FetchParameters { - return @enumFromInt(@intFromEnum(value)); - } - }; - - pub const VarKind = enum { declared, lexical }; - pub fn addVar(self: *ModuleInfo, name: []const u8, kind: VarKind) !void { - switch (kind) { - .declared => try self.addDeclaredVariable(name), - .lexical => try self.addLexicalVariable(name), - } - } - - fn _addRecord(self: *ModuleInfo, kind: RecordKind, data: []const StringID) !void { - bun.assert(!self.finalized); - bun.assert(data.len == kind.len() catch unreachable); - try self.record_kinds.append(kind); - try self.buffer.appendSlice(data); - } - pub fn addDeclaredVariable(self: *ModuleInfo, id: []const u8) !void { - try self._addRecord(.declared_variable, &.{try self.str(id)}); - } - pub fn addLexicalVariable(self: *ModuleInfo, id: []const u8) !void { - try self._addRecord(.lexical_variable, &.{try self.str(id)}); - } - pub fn addImportInfoSingle(self: *ModuleInfo, module_name: []const u8, import_name: []const u8, local_name: []const u8) !void { - try self._addRecord(.import_info_single, &.{ try self.str(module_name), try self.str(import_name), try self.str(local_name) }); - } - pub fn addImportInfoNamespace(self: *ModuleInfo, module_name: []const u8, local_name: []const u8) !void { - try self._addRecord(.import_info_namespace, &.{ try self.str(module_name), try self.str("*"), try self.str(local_name) }); - } - pub fn addExportInfoIndirect(self: *ModuleInfo, export_name: []const u8, import_name: []const u8, module_name: []const u8) !void { - const export_name_id = try self.str(export_name); - if (try self._hasOrAddExportedName(export_name_id)) return; // a syntax error will be emitted later in this case - try self._addRecord(.export_info_indirect, &.{ export_name_id, try self.str(import_name), try self.str(module_name) }); - } - pub fn addExportInfoLocal(self: *ModuleInfo, export_name: []const u8, local_name: []const u8) !void { - const export_name_id = try self.str(export_name); - if (try self._hasOrAddExportedName(export_name_id)) return; // a syntax error will be emitted later in this case - try self._addRecord(.export_info_local, &.{ export_name_id, try self.str(local_name), @enumFromInt(std.math.maxInt(u32)) }); - } - pub fn addExportInfoNamespace(self: *ModuleInfo, export_name: []const u8, module_name: []const u8) !void { - const export_name_id = try self.str(export_name); - if (try self._hasOrAddExportedName(export_name_id)) return; // a syntax error will be emitted later in this case - try self._addRecord(.export_info_namespace, &.{ export_name_id, try self.str(module_name) }); - } - pub fn addExportInfoStar(self: *ModuleInfo, module_name: []const u8) !void { - try self._addRecord(.export_info_star, &.{try self.str(module_name)}); - } - - pub fn _hasOrAddExportedName(self: *ModuleInfo, name: StringID) !bool { - if (try self.exported_names.fetchPut(self.gpa, name, {}) != null) return true; - return false; - } - - pub fn create(gpa: std.mem.Allocator) !*ModuleInfo { - const res = try gpa.create(ModuleInfo); - res.* = ModuleInfo.init(gpa); - return res; - } - fn init(allocator: std.mem.Allocator) ModuleInfo { - return .{ - .gpa = allocator, - .strings_map = .{}, - .strings_buf = .{}, - .strings_lens = .{}, - .exported_names = .{}, - .requested_modules = std.AutoArrayHashMap(StringID, FetchParameters).init(allocator), - .buffer = std.ArrayList(StringID).init(allocator), - .record_kinds = std.ArrayList(RecordKind).init(allocator), - .contains_import_meta = false, - }; - } - fn deinit(self: *ModuleInfo) void { - self.strings_map.deinit(self.gpa); - self.strings_buf.deinit(self.gpa); - self.strings_lens.deinit(self.gpa); - self.exported_names.deinit(self.gpa); - self.requested_modules.deinit(); - self.buffer.deinit(); - self.record_kinds.deinit(); - } - pub fn destroy(self: *ModuleInfo) void { - const alloc = self.gpa; - self.deinit(); - alloc.destroy(self); - } - pub fn str(self: *ModuleInfo, value: []const u8) !StringID { - const gpres = try self.strings_map.getOrPutContext(self.gpa, .get_or_put, .{ - .get_or_put_key = value, - .strings_buf = self.strings_buf.items, - .strings_lens = self.strings_lens.items, - }); - if (gpres.found_existing) return @enumFromInt(@as(u32, @intCast(gpres.index))); - - gpres.key_ptr.* = @enumFromInt(@as(u32, @truncate(self.strings_buf.items.len))); - gpres.value_ptr.* = {}; - try self.strings_buf.ensureUnusedCapacity(self.gpa, value.len); - try self.strings_lens.ensureUnusedCapacity(self.gpa, 1); - self.strings_buf.appendSliceAssumeCapacity(value); - self.strings_lens.appendAssumeCapacity(@as(u32, @truncate(value.len))); - return @enumFromInt(@as(u32, @intCast(gpres.index))); - } - pub const star_default = "*default*"; - pub fn requestModule(self: *ModuleInfo, import_record_path: []const u8, fetch_parameters: FetchParameters) !void { - // jsc only records the attributes of the first import with the given import_record_path. so only put if not exists. - const gpres = try self.requested_modules.getOrPut(try self.str(import_record_path)); - if (!gpres.found_existing) gpres.value_ptr.* = fetch_parameters; - } - - /// find any exports marked as 'local' that are actually 'indirect' and fix them - pub fn finalize(self: *ModuleInfo) !void { - bun.assert(!self.finalized); - var local_name_to_module_name = std.AutoArrayHashMap(StringID, struct { module_name: StringID, import_name: StringID }).init(bun.default_allocator); - defer local_name_to_module_name.deinit(); - { - var i: usize = 0; - for (self.record_kinds.items) |k| { - if (k == .import_info_single) { - try local_name_to_module_name.put(self.buffer.items[i + 2], .{ .module_name = self.buffer.items[i], .import_name = self.buffer.items[i + 1] }); - } - i += k.len() catch unreachable; - } - } - - { - var i: usize = 0; - for (self.record_kinds.items) |*k| { - if (k.* == .export_info_local) { - if (local_name_to_module_name.get(self.buffer.items[i + 1])) |ip| { - k.* = .export_info_indirect; - self.buffer.items[i + 1] = ip.import_name; - self.buffer.items[i + 2] = ip.module_name; - } - } - i += k.len() catch unreachable; - } - } - - self._deserialized = .{ - .strings_buf = self.strings_buf.items, - .strings_lens = self.strings_lens.items, - .requested_modules_keys = self.requested_modules.keys(), - .requested_modules_values = self.requested_modules.values(), - .buffer = self.buffer.items, - .record_kinds = self.record_kinds.items, - .contains_import_meta = self.contains_import_meta, - .owner = .module_info, - }; - - self.finalized = true; - } -}; -pub const StringID = enum(u32) { - _, -}; - -export fn zig__renderDiff(expected_ptr: [*:0]const u8, expected_len: usize, received_ptr: [*:0]const u8, received_len: usize, globalThis: *bun.JSC.JSGlobalObject) void { - const DiffFormatter = @import("bun.js/test/diff_format.zig").DiffFormatter; - const formatter = DiffFormatter{ - .received_string = received_ptr[0..received_len], - .expected_string = expected_ptr[0..expected_len], - .globalThis = globalThis, - }; - const stderr = std.io.getStdErr().writer(); - stderr.print("DIFF:\n{}\n", .{formatter}) catch {}; -} - -export fn zig__ModuleInfoDeserialized__toJSModuleRecord( - globalObject: *bun.JSC.JSGlobalObject, - vm: *bun.JSC.VM, - module_key: *const IdentifierArray, - source_code: *const SourceCode, - declared_variables: *VariableEnvironment, - lexical_variables: *VariableEnvironment, - res: *ModuleInfoDeserialized, -) ?*JSModuleRecord { - if (res.dead) @panic("ModuleInfoDeserialized already deinit()ed"); - defer res.deinit(); - - var identifiers = IdentifierArray.create(res.strings_lens.len); - defer identifiers.destroy(); - var offset: usize = 0; - for (0.., res.strings_lens) |index, len| { - if (res.strings_buf.len < offset + len) return null; // error! - const sub = res.strings_buf[offset..][0..len]; - if (bun.strings.eqlComptime(sub, ModuleInfo.star_default)) { - identifiers.setFromStarDefault(index, vm); - } else { - identifiers.setFromUtf8(index, vm, sub); - } - offset += len; - } - - { - var i: usize = 0; - for (res.record_kinds) |k| { - if (i + (k.len() catch 0) > res.buffer.len) return null; - switch (k) { - .declared_variable => declared_variables.add(identifiers, res.buffer[i]), - .lexical_variable => lexical_variables.add(identifiers, res.buffer[i]), - .import_info_single, .import_info_namespace, .export_info_indirect, .export_info_local, .export_info_namespace, .export_info_star => {}, - else => return null, - } - i += k.len() catch unreachable; // handled above - } - } - - const module_record = JSModuleRecord.create(globalObject, vm, module_key, source_code, declared_variables, lexical_variables, res.contains_import_meta); - - for (res.requested_modules_keys, res.requested_modules_values) |reqk, reqv| { - switch (reqv) { - .none => module_record.addRequestedModuleNullAttributesPtr(identifiers, reqk), - .javascript => module_record.addRequestedModuleJavaScript(identifiers, reqk), - .webassembly => module_record.addRequestedModuleWebAssembly(identifiers, reqk), - .json => module_record.addRequestedModuleJSON(identifiers, reqk), - else => |uv| module_record.addRequestedModuleHostDefined(identifiers, reqk, @enumFromInt(@intFromEnum(uv))), - } - } - - { - var i: usize = 0; - for (res.record_kinds) |k| { - if (i + (k.len() catch unreachable) > res.buffer.len) unreachable; // handled above - switch (k) { - .declared_variable, .lexical_variable => {}, - .import_info_single => module_record.addImportEntrySingle(identifiers, res.buffer[i + 1], res.buffer[i + 2], res.buffer[i]), - .import_info_namespace => module_record.addImportEntryNamespace(identifiers, res.buffer[i + 1], res.buffer[i + 2], res.buffer[i]), - .export_info_indirect => module_record.addIndirectExport(identifiers, res.buffer[i + 0], res.buffer[i + 1], res.buffer[i + 2]), - .export_info_local => module_record.addLocalExport(identifiers, res.buffer[i], res.buffer[i + 1]), - .export_info_namespace => module_record.addNamespaceExport(identifiers, res.buffer[i], res.buffer[i + 1]), - .export_info_star => module_record.addStarExport(identifiers, res.buffer[i]), - else => unreachable, // handled above - } - i += k.len() catch unreachable; // handled above - } - } - - return module_record; -} -export fn zig__ModuleInfo__destroy(info: *ModuleInfo) void { - info.deinit(); - bun.default_allocator.destroy(info); -} - -const VariableEnvironment = opaque { - extern fn JSC__VariableEnvironment__add(environment: *VariableEnvironment, identifier_array: *IdentifierArray, identifier_index: StringID) void; - pub const add = JSC__VariableEnvironment__add; -}; -const IdentifierArray = opaque { - extern fn JSC__IdentifierArray__create(len: usize) *IdentifierArray; - pub const create = JSC__IdentifierArray__create; - - extern fn JSC__IdentifierArray__destroy(identifier_array: *IdentifierArray) void; - pub const destroy = JSC__IdentifierArray__destroy; - - extern fn JSC__IdentifierArray__setFromUtf8(identifier_array: *IdentifierArray, n: usize, vm: *bun.JSC.VM, str: [*]const u8, len: usize) void; - pub fn setFromUtf8(self: *IdentifierArray, n: usize, vm: *bun.JSC.VM, str: []const u8) void { - JSC__IdentifierArray__setFromUtf8(self, n, vm, str.ptr, str.len); - } - - extern fn JSC__IdentifierArray__setFromStarDefault(identifier_array: *IdentifierArray, n: usize, vm: *bun.JSC.VM) void; - pub const setFromStarDefault = JSC__IdentifierArray__setFromStarDefault; -}; -const SourceCode = opaque {}; -const JSModuleRecord = opaque { - extern fn JSC_JSModuleRecord__create(global_object: *bun.JSC.JSGlobalObject, vm: *bun.JSC.VM, module_key: *const IdentifierArray, source_code: *const SourceCode, declared_variables: *VariableEnvironment, lexical_variables: *VariableEnvironment, has_import_meta: bool) *JSModuleRecord; - pub const create = JSC_JSModuleRecord__create; - - extern fn JSC_JSModuleRecord__declaredVariables(module_record: *JSModuleRecord) *VariableEnvironment; - pub const declaredVariables = JSC_JSModuleRecord__declaredVariables; - extern fn JSC_JSModuleRecord__lexicalVariables(module_record: *JSModuleRecord) *VariableEnvironment; - pub const lexicalVariables = JSC_JSModuleRecord__lexicalVariables; - - extern fn JSC_JSModuleRecord__addIndirectExport(module_record: *JSModuleRecord, identifier_array: *IdentifierArray, export_name: StringID, import_name: StringID, module_name: StringID) void; - pub const addIndirectExport = JSC_JSModuleRecord__addIndirectExport; - extern fn JSC_JSModuleRecord__addLocalExport(module_record: *JSModuleRecord, identifier_array: *IdentifierArray, export_name: StringID, local_name: StringID) void; - pub const addLocalExport = JSC_JSModuleRecord__addLocalExport; - extern fn JSC_JSModuleRecord__addNamespaceExport(module_record: *JSModuleRecord, identifier_array: *IdentifierArray, export_name: StringID, module_name: StringID) void; - pub const addNamespaceExport = JSC_JSModuleRecord__addNamespaceExport; - extern fn JSC_JSModuleRecord__addStarExport(module_record: *JSModuleRecord, identifier_array: *IdentifierArray, module_name: StringID) void; - pub const addStarExport = JSC_JSModuleRecord__addStarExport; - - extern fn JSC_JSModuleRecord__addRequestedModuleNullAttributesPtr(module_record: *JSModuleRecord, identifier_array: *IdentifierArray, module_name: StringID) void; - pub const addRequestedModuleNullAttributesPtr = JSC_JSModuleRecord__addRequestedModuleNullAttributesPtr; - extern fn JSC_JSModuleRecord__addRequestedModuleJavaScript(module_record: *JSModuleRecord, identifier_array: *IdentifierArray, module_name: StringID) void; - pub const addRequestedModuleJavaScript = JSC_JSModuleRecord__addRequestedModuleJavaScript; - extern fn JSC_JSModuleRecord__addRequestedModuleWebAssembly(module_record: *JSModuleRecord, identifier_array: *IdentifierArray, module_name: StringID) void; - pub const addRequestedModuleWebAssembly = JSC_JSModuleRecord__addRequestedModuleWebAssembly; - extern fn JSC_JSModuleRecord__addRequestedModuleJSON(module_record: *JSModuleRecord, identifier_array: *IdentifierArray, module_name: StringID) void; - pub const addRequestedModuleJSON = JSC_JSModuleRecord__addRequestedModuleJSON; - extern fn JSC_JSModuleRecord__addRequestedModuleHostDefined(module_record: *JSModuleRecord, identifier_array: *IdentifierArray, module_name: StringID, host_defined_import_type: StringID) void; - pub const addRequestedModuleHostDefined = JSC_JSModuleRecord__addRequestedModuleHostDefined; - - extern fn JSC_JSModuleRecord__addImportEntrySingle(module_record: *JSModuleRecord, identifier_array: *IdentifierArray, import_name: StringID, local_name: StringID, module_name: StringID) void; - pub const addImportEntrySingle = JSC_JSModuleRecord__addImportEntrySingle; - extern fn JSC_JSModuleRecord__addImportEntryNamespace(module_record: *JSModuleRecord, identifier_array: *IdentifierArray, import_name: StringID, local_name: StringID, module_name: StringID) void; - pub const addImportEntryNamespace = JSC_JSModuleRecord__addImportEntryNamespace; -}; diff --git a/src/bun.js/RuntimeTranspilerCache.zig b/src/bun.js/RuntimeTranspilerCache.zig index 0d8235d417fbd0..3eac90cbf6aeae 100644 --- a/src/bun.js/RuntimeTranspilerCache.zig +++ b/src/bun.js/RuntimeTranspilerCache.zig @@ -10,8 +10,7 @@ /// Version 11: Fix \uFFFF printing regression /// Version 12: "use strict"; makes it CommonJS if we otherwise don't know which one to pick. /// Version 13: Hoist `import.meta.require` definition, see #15738 -/// Version 14: Include module info with an ES Module, see #15758 -const expected_version = 14; +const expected_version = 13; const bun = @import("root").bun; const std = @import("std"); @@ -34,7 +33,6 @@ pub const RuntimeTranspilerCache = struct { sourcemap_allocator: std.mem.Allocator, output_code_allocator: std.mem.Allocator, - esm_record_allocator: std.mem.Allocator, const seed = 42; pub const Metadata = struct { @@ -55,10 +53,6 @@ pub const RuntimeTranspilerCache = struct { sourcemap_byte_length: u64 = 0, sourcemap_hash: u64 = 0, - esm_record_byte_offset: u64 = 0, - esm_record_byte_length: u64 = 0, - esm_record_hash: u64 = 0, - pub const size = brk: { var count: usize = 0; const meta: Metadata = .{}; @@ -85,10 +79,6 @@ pub const RuntimeTranspilerCache = struct { try writer.writeInt(u64, this.sourcemap_byte_offset, .little); try writer.writeInt(u64, this.sourcemap_byte_length, .little); try writer.writeInt(u64, this.sourcemap_hash, .little); - - try writer.writeInt(u64, this.esm_record_byte_offset, .little); - try writer.writeInt(u64, this.esm_record_byte_length, .little); - try writer.writeInt(u64, this.esm_record_hash, .little); } pub fn decode(this: *Metadata, reader: anytype) !void { @@ -113,10 +103,6 @@ pub const RuntimeTranspilerCache = struct { this.sourcemap_byte_length = try reader.readInt(u64, .little); this.sourcemap_hash = try reader.readInt(u64, .little); - this.esm_record_byte_offset = try reader.readInt(u64, .little); - this.esm_record_byte_length = try reader.readInt(u64, .little); - this.esm_record_hash = try reader.readInt(u64, .little); - switch (this.module_type) { .esm, .cjs => {}, // Invalid module type @@ -135,7 +121,7 @@ pub const RuntimeTranspilerCache = struct { metadata: Metadata, output_code: OutputCode = .{ .utf8 = "" }, sourcemap: []const u8 = "", - esm_record: []const u8 = "", + pub const OutputCode = union(enum) { utf8: []const u8, string: bun.String, @@ -157,14 +143,11 @@ pub const RuntimeTranspilerCache = struct { } }; - pub fn deinit(this: *Entry, sourcemap_allocator: std.mem.Allocator, output_code_allocator: std.mem.Allocator, esm_record_allocator: std.mem.Allocator) void { + pub fn deinit(this: *Entry, sourcemap_allocator: std.mem.Allocator, output_code_allocator: std.mem.Allocator) void { this.output_code.deinit(output_code_allocator); if (this.sourcemap.len > 0) { sourcemap_allocator.free(this.sourcemap); } - if (this.esm_record.len > 0) { - esm_record_allocator.free(this.esm_record); - } } pub fn save( @@ -174,7 +157,6 @@ pub const RuntimeTranspilerCache = struct { input_hash: u64, features_hash: u64, sourcemap: []const u8, - esm_record: []const u8, output_code: OutputCode, exports_kind: bun.JSAst.ExportsKind, ) !void { @@ -220,8 +202,6 @@ pub const RuntimeTranspilerCache = struct { .output_byte_offset = Metadata.size, .output_byte_length = output_bytes.len, .sourcemap_byte_offset = Metadata.size + output_bytes.len, - .esm_record_byte_offset = Metadata.size + output_bytes.len + sourcemap.len, - .esm_record_byte_length = esm_record.len, }; metadata.output_hash = hash(output_bytes); @@ -240,26 +220,20 @@ pub const RuntimeTranspilerCache = struct { break :brk metadata_buf[0..metadata_stream.pos]; }; - var vecs_buf: [4]bun.PlatformIOVecConst = undefined; - var vecs_i: usize = 0; - vecs_buf[vecs_i] = bun.platformIOVecConstCreate(metadata_bytes); - vecs_i += 1; - if (output_bytes.len > 0) { - vecs_buf[vecs_i] = bun.platformIOVecConstCreate(output_bytes); - vecs_i += 1; - } - if (sourcemap.len > 0) { - vecs_buf[vecs_i] = bun.platformIOVecConstCreate(sourcemap); - vecs_i += 1; - } - if (esm_record.len > 0) { - vecs_buf[vecs_i] = bun.platformIOVecConstCreate(esm_record); - vecs_i += 1; - } - const vecs: []const bun.PlatformIOVecConst = vecs_buf[0..vecs_i]; + const vecs: []const bun.PlatformIOVecConst = if (output_bytes.len > 0) + &.{ + bun.platformIOVecConstCreate(metadata_bytes), + bun.platformIOVecConstCreate(output_bytes), + bun.platformIOVecConstCreate(sourcemap), + } + else + &.{ + bun.platformIOVecConstCreate(metadata_bytes), + bun.platformIOVecConstCreate(sourcemap), + }; var position: isize = 0; - const end_position = Metadata.size + output_bytes.len + sourcemap.len + esm_record.len; + const end_position = Metadata.size + output_bytes.len + sourcemap.len; if (bun.Environment.allow_assert) { var total: usize = 0; @@ -269,7 +243,7 @@ pub const RuntimeTranspilerCache = struct { } bun.assert(end_position == total); } - bun.assert(end_position == @as(i64, @intCast(sourcemap.len + output_bytes.len + Metadata.size + esm_record.len))); + bun.assert(end_position == @as(i64, @intCast(sourcemap.len + output_bytes.len + Metadata.size))); bun.C.preallocate_file(tmpfile.fd.cast(), 0, @intCast(end_position)) catch {}; while (position < end_position) { @@ -290,7 +264,6 @@ pub const RuntimeTranspilerCache = struct { file: std.fs.File, sourcemap_allocator: std.mem.Allocator, output_code_allocator: std.mem.Allocator, - esm_record_allocator: std.mem.Allocator, ) !void { const stat_size = try file.getEndPos(); if (stat_size < Metadata.size + this.metadata.output_byte_length + this.metadata.sourcemap_byte_length) { @@ -366,17 +339,6 @@ pub const RuntimeTranspilerCache = struct { this.sourcemap = sourcemap; } - - if (this.metadata.esm_record_byte_length > 0) { - const esm_record = try esm_record_allocator.alloc(u8, this.metadata.esm_record_byte_length); - errdefer esm_record_allocator.free(esm_record); - const read_bytes = try file.preadAll(esm_record, this.metadata.esm_record_byte_offset); - if (read_bytes != this.metadata.esm_record_byte_length) { - return error.MissingData; - } - - this.esm_record = esm_record; - } } }; @@ -494,7 +456,6 @@ pub const RuntimeTranspilerCache = struct { input_stat_size: u64, sourcemap_allocator: std.mem.Allocator, output_code_allocator: std.mem.Allocator, - esm_record_allocator: std.mem.Allocator, ) !Entry { var tracer = bun.tracy.traceNamed(@src(), "RuntimeTranspilerCache.fromFile"); defer tracer.end(); @@ -509,7 +470,6 @@ pub const RuntimeTranspilerCache = struct { input_stat_size, sourcemap_allocator, output_code_allocator, - esm_record_allocator, ); } @@ -520,7 +480,6 @@ pub const RuntimeTranspilerCache = struct { input_stat_size: u64, sourcemap_allocator: std.mem.Allocator, output_code_allocator: std.mem.Allocator, - esm_record_allocator: std.mem.Allocator, ) !Entry { var metadata_bytes_buf: [Metadata.size * 2]u8 = undefined; const cache_fd = try bun.sys.open(cache_file_path.sliceAssumeZ(), bun.O.RDONLY, 0).unwrap(); @@ -552,7 +511,7 @@ pub const RuntimeTranspilerCache = struct { return error.MismatchedFeatureHash; } - try entry.load(file, sourcemap_allocator, output_code_allocator, esm_record_allocator); + try entry.load(file, sourcemap_allocator, output_code_allocator); return entry; } @@ -569,7 +528,6 @@ pub const RuntimeTranspilerCache = struct { input_hash: u64, features_hash: u64, sourcemap: []const u8, - esm_record: []const u8, source_code: bun.String, exports_kind: bun.JSAst.ExportsKind, ) !void { @@ -609,7 +567,6 @@ pub const RuntimeTranspilerCache = struct { input_hash, features_hash, sourcemap, - esm_record, output_code, exports_kind, ); @@ -643,7 +600,7 @@ pub const RuntimeTranspilerCache = struct { parser_options.hashForRuntimeTranspiler(&features_hasher, used_jsx); this.features_hash = features_hasher.final(); - this.entry = fromFile(input_hash, this.features_hash.?, source.contents.len, this.sourcemap_allocator, this.output_code_allocator, this.esm_record_allocator) catch |err| { + this.entry = fromFile(input_hash, this.features_hash.?, source.contents.len, this.sourcemap_allocator, this.output_code_allocator) catch |err| { debug("get(\"{s}\") = {s}", .{ source.path.text, @errorName(err) }); return false; }; @@ -659,7 +616,7 @@ pub const RuntimeTranspilerCache = struct { if (comptime bun.Environment.isDebug) { if (!bun_debug_restore_from_cache) { if (this.entry) |*entry| { - entry.deinit(this.sourcemap_allocator, this.output_code_allocator, this.esm_record_allocator); + entry.deinit(this.sourcemap_allocator, this.output_code_allocator); this.entry = null; } } @@ -668,7 +625,7 @@ pub const RuntimeTranspilerCache = struct { return this.entry != null; } - pub fn put(this: *RuntimeTranspilerCache, output_code_bytes: []const u8, sourcemap: []const u8, esm_record: []const u8) void { + pub fn put(this: *RuntimeTranspilerCache, output_code_bytes: []const u8, sourcemap: []const u8) void { if (comptime !bun.FeatureFlags.runtime_transpiler_cache) @compileError("RuntimeTranspilerCache is disabled"); @@ -679,7 +636,7 @@ pub const RuntimeTranspilerCache = struct { const output_code = bun.String.createLatin1(output_code_bytes); this.output_code = output_code; - toFile(this.input_byte_length.?, this.input_hash.?, this.features_hash.?, sourcemap, esm_record, output_code, this.exports_kind) catch |err| { + toFile(this.input_byte_length.?, this.input_hash.?, this.features_hash.?, sourcemap, output_code, this.exports_kind) catch |err| { debug("put() = {s}", .{@errorName(err)}); return; }; diff --git a/src/bun.js/bindings/BunAnalyzeTranspiledModule.cpp b/src/bun.js/bindings/BunAnalyzeTranspiledModule.cpp deleted file mode 100644 index 4268358a650f78..00000000000000 --- a/src/bun.js/bindings/BunAnalyzeTranspiledModule.cpp +++ /dev/null @@ -1,313 +0,0 @@ -#include "root.h" - -#include "JavaScriptCore/JSInternalPromise.h" -#include "JavaScriptCore/JSModuleRecord.h" -#include "JavaScriptCore/GlobalObjectMethodTable.h" -#include "JavaScriptCore/JSModuleRecord.h" -#include "JavaScriptCore/Nodes.h" -#include "JavaScriptCore/Parser.h" -#include "JavaScriptCore/ParserError.h" -#include "JavaScriptCore/SyntheticModuleRecord.h" -#include -#include "JavaScriptCore/JSGlobalObject.h" -#include "JavaScriptCore/JSModuleRecord.h" -#include "JavaScriptCore/ExceptionScope.h" -#include "ZigSourceProvider.h" -#include "BunAnalyzeTranspiledModule.h" - -// ref: JSModuleLoader.cpp -// ref: ModuleAnalyzer.cpp -// ref: JSModuleRecord.cpp -// ref: NodesAnalyzeModule.cpp, search ::analyzeModule - -// TODO: #include "JavaScriptCore/parser/ModuleAnalyzer.h" -#include "JavaScriptCore/ErrorType.h" -#include "JavaScriptCore/Nodes.h" - -namespace JSC { - -class JSModuleRecord; -class SourceCode; -class ScriptFetchParameters; - -class ModuleAnalyzer { - WTF_MAKE_NONCOPYABLE(ModuleAnalyzer); - WTF_FORBID_HEAP_ALLOCATION; - -public: - ModuleAnalyzer(JSGlobalObject*, const Identifier& moduleKey, const SourceCode&, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables, CodeFeatures); - - Expected> analyze(ModuleProgramNode&); - - VM& vm() { return m_vm; } - - JSModuleRecord* moduleRecord() { return m_moduleRecord; } - - void appendRequestedModule(const Identifier&, RefPtr&&); - - void fail(std::tuple&& errorMessage) { m_errorMessage = errorMessage; } - -private: - void exportVariable(ModuleProgramNode&, const RefPtr&, const VariableEnvironmentEntry&); - - VM& m_vm; - JSModuleRecord* m_moduleRecord; - IdentifierSet m_requestedModules; - std::tuple m_errorMessage; -}; - -} - -namespace JSC { - -String dumpRecordInfo(JSModuleRecord* moduleRecord); - -extern "C" JSModuleRecord* zig__ModuleInfoDeserialized__toJSModuleRecord(JSGlobalObject* globalObject, VM& vm, const Identifier& module_key, const SourceCode& source_code, VariableEnvironment& declared_variables, VariableEnvironment& lexical_variables, bun_ModuleInfoDeserialized* module_info); -extern "C" void zig__renderDiff(const char* expected_ptr, size_t expected_len, const char* received_ptr, size_t received_len, JSGlobalObject* globalObject); - -extern "C" Identifier* JSC__IdentifierArray__create(size_t len) -{ - return new Identifier[len]; -} -extern "C" void JSC__IdentifierArray__destroy(Identifier* identifier) -{ - delete[] identifier; -} -extern "C" void JSC__IdentifierArray__setFromUtf8(Identifier* identifierArray, size_t n, VM& vm, char* str, size_t len) -{ - identifierArray[n] = Identifier::fromString(vm, AtomString::fromUTF8(std::span(str, len))); -} -extern "C" void JSC__IdentifierArray__setFromStarDefault(Identifier* identifierArray, size_t n, VM& vm) -{ - identifierArray[n] = vm.propertyNames->starDefaultPrivateName; -} - -extern "C" void JSC__VariableEnvironment__add(VariableEnvironment& environment, Identifier* identifierArray, uint32_t index) -{ - environment.add(identifierArray[index]); -} - -extern "C" VariableEnvironment* JSC_JSModuleRecord__declaredVariables(JSModuleRecord* moduleRecord) -{ - return &moduleRecord->m_declaredVariables; -} -extern "C" VariableEnvironment* JSC_JSModuleRecord__lexicalVariables(JSModuleRecord* moduleRecord) -{ - return &moduleRecord->m_lexicalVariables; -} - -extern "C" JSModuleRecord* JSC_JSModuleRecord__create(JSGlobalObject* globalObject, VM& vm, const Identifier* moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables, bool hasImportMeta) -{ - return JSModuleRecord::create(globalObject, vm, globalObject->moduleRecordStructure(), moduleKey[0], sourceCode, declaredVariables, lexicalVariables, hasImportMeta ? ImportMetaFeature : 0); -} - -extern "C" void JSC_JSModuleRecord__addIndirectExport(JSModuleRecord* moduleRecord, Identifier* identifierArray, uint32_t exportName, uint32_t importName, uint32_t moduleName) -{ - moduleRecord->addExportEntry(JSModuleRecord::ExportEntry::createIndirect(identifierArray[exportName], identifierArray[importName], identifierArray[moduleName])); -} -extern "C" void JSC_JSModuleRecord__addLocalExport(JSModuleRecord* moduleRecord, Identifier* identifierArray, uint32_t exportName, uint32_t localName) -{ - moduleRecord->addExportEntry(JSModuleRecord::ExportEntry::createLocal(identifierArray[exportName], identifierArray[localName])); -} -extern "C" void JSC_JSModuleRecord__addNamespaceExport(JSModuleRecord* moduleRecord, Identifier* identifierArray, uint32_t exportName, uint32_t moduleName) -{ - moduleRecord->addExportEntry(JSModuleRecord::ExportEntry::createNamespace(identifierArray[exportName], identifierArray[moduleName])); -} -extern "C" void JSC_JSModuleRecord__addStarExport(JSModuleRecord* moduleRecord, Identifier* identifierArray, uint32_t moduleName) -{ - moduleRecord->addStarExportEntry(identifierArray[moduleName]); -} -extern "C" void JSC_JSModuleRecord__addRequestedModuleNullAttributesPtr(JSModuleRecord* moduleRecord, Identifier* identifierArray, uint32_t moduleName) -{ - RefPtr attributes = RefPtr {}; - moduleRecord->appendRequestedModule(identifierArray[moduleName], WTFMove(attributes)); -} -extern "C" void JSC_JSModuleRecord__addRequestedModuleJavaScript(JSModuleRecord* moduleRecord, Identifier* identifierArray, uint32_t moduleName) -{ - Ref attributes = ScriptFetchParameters::create(ScriptFetchParameters::Type::JavaScript); - moduleRecord->appendRequestedModule(identifierArray[moduleName], WTFMove(attributes)); -} -extern "C" void JSC_JSModuleRecord__addRequestedModuleWebAssembly(JSModuleRecord* moduleRecord, Identifier* identifierArray, uint32_t moduleName) -{ - Ref attributes = ScriptFetchParameters::create(ScriptFetchParameters::Type::WebAssembly); - moduleRecord->appendRequestedModule(identifierArray[moduleName], WTFMove(attributes)); -} -extern "C" void JSC_JSModuleRecord__addRequestedModuleJSON(JSModuleRecord* moduleRecord, Identifier* identifierArray, uint32_t moduleName) -{ - Ref attributes = ScriptFetchParameters::create(ScriptFetchParameters::Type::JSON); - moduleRecord->appendRequestedModule(identifierArray[moduleName], WTFMove(attributes)); -} -extern "C" void JSC_JSModuleRecord__addRequestedModuleHostDefined(JSModuleRecord* moduleRecord, Identifier* identifierArray, uint32_t moduleName, uint32_t hostDefinedImportType) -{ - Ref attributes = ScriptFetchParameters::create(identifierArray[hostDefinedImportType].string()); - moduleRecord->appendRequestedModule(identifierArray[moduleName], WTFMove(attributes)); -} - -extern "C" void JSC_JSModuleRecord__addImportEntrySingle(JSModuleRecord* moduleRecord, Identifier* identifierArray, uint32_t importName, uint32_t localName, uint32_t moduleName) -{ - moduleRecord->addImportEntry(JSModuleRecord::ImportEntry { - .type = JSModuleRecord::ImportEntryType::Single, - .moduleRequest = identifierArray[moduleName], - .importName = identifierArray[importName], - .localName = identifierArray[localName], - }); -} -extern "C" void JSC_JSModuleRecord__addImportEntryNamespace(JSModuleRecord* moduleRecord, Identifier* identifierArray, uint32_t importName, uint32_t localName, uint32_t moduleName) -{ - moduleRecord->addImportEntry(JSModuleRecord::ImportEntry { - .type = JSModuleRecord::ImportEntryType::Namespace, - .moduleRequest = identifierArray[moduleName], - .importName = identifierArray[importName], - .localName = identifierArray[localName], - }); -} - -static EncodedJSValue fallbackParse(JSGlobalObject* globalObject, const Identifier& moduleKey, const SourceCode& sourceCode, JSInternalPromise* promise, JSModuleRecord* resultValue = nullptr); -extern "C" EncodedJSValue Bun__analyzeTranspiledModule(JSGlobalObject* globalObject, const Identifier& moduleKey, const SourceCode& sourceCode, JSInternalPromise* promise) -{ - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - auto rejectWithError = [&](JSValue error) { - promise->reject(globalObject, error); - return promise; - }; - - VariableEnvironment declaredVariables = VariableEnvironment(); - VariableEnvironment lexicalVariables = VariableEnvironment(); - - auto provider = static_cast(sourceCode.provider()); - - if (provider->m_resolvedSource.module_info == nullptr) { - dataLog("[note] module_info is null for module: ", moduleKey.utf8(), "\n"); - RELEASE_AND_RETURN(scope, JSValue::encode(rejectWithError(createError(globalObject, WTF::String::fromLatin1("module_info is null"))))); - } - - auto moduleRecord = zig__ModuleInfoDeserialized__toJSModuleRecord(globalObject, vm, moduleKey, sourceCode, declaredVariables, lexicalVariables, provider->m_resolvedSource.module_info); - if (moduleRecord == nullptr) { - RELEASE_AND_RETURN(scope, JSValue::encode(rejectWithError(createError(globalObject, WTF::String::fromLatin1("parseFromSourceCode failed"))))); - } - -#ifdef DEBUG - RELEASE_AND_RETURN(scope, fallbackParse(globalObject, moduleKey, sourceCode, promise, moduleRecord)); -#else - promise->fulfillWithNonPromise(globalObject, moduleRecord); - RELEASE_AND_RETURN(scope, JSValue::encode(promise)); -#endif -} -static EncodedJSValue fallbackParse(JSGlobalObject* globalObject, const Identifier& moduleKey, const SourceCode& sourceCode, JSInternalPromise* promise, JSModuleRecord* resultValue) -{ - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - auto rejectWithError = [&](JSValue error) { - promise->reject(globalObject, error); - return promise; - }; - - ParserError error; - std::unique_ptr moduleProgramNode = parseRootNode( - vm, sourceCode, ImplementationVisibility::Public, JSParserBuiltinMode::NotBuiltin, - StrictModeLexicallyScopedFeature, JSParserScriptMode::Module, SourceParseMode::ModuleAnalyzeMode, error); - if (error.isValid()) - RELEASE_AND_RETURN(scope, JSValue::encode(rejectWithError(error.toErrorObject(globalObject, sourceCode)))); - ASSERT(moduleProgramNode); - - ModuleAnalyzer ModuleAnalyzer(globalObject, moduleKey, sourceCode, moduleProgramNode->varDeclarations(), moduleProgramNode->lexicalVariables(), moduleProgramNode->features()); - RETURN_IF_EXCEPTION(scope, JSValue::encode(promise->rejectWithCaughtException(globalObject, scope))); - - auto result = ModuleAnalyzer.analyze(*moduleProgramNode); - if (!result) { - auto [errorType, message] = WTFMove(result.error()); - RELEASE_AND_RETURN(scope, JSValue::encode(rejectWithError(createError(globalObject, errorType, message)))); - } - - JSModuleRecord* moduleRecord = result.value(); - - if (resultValue != nullptr) { - auto actual = dumpRecordInfo(resultValue); - auto expected = dumpRecordInfo(moduleRecord); - if (actual != expected) { - dataLog("\n\n\n\n\n\n\x1b[95mBEGIN analyzeTranspiledModule\x1b(B\x1b[m\n ---code---\n\n", sourceCode.toUTF8().data(), "\n"); - dataLog(" ------", "\n"); - dataLog(" BunAnalyzeTranspiledModule:", "\n"); - - zig__renderDiff(expected.utf8().data(), expected.utf8().length(), actual.utf8().data(), actual.utf8().length(), globalObject); - - RELEASE_AND_RETURN(scope, JSValue::encode(rejectWithError(createError(globalObject, WTF::String::fromLatin1("Imports different between parseFromSourceCode and fallbackParse"))))); - } - } - - scope.release(); - promise->fulfillWithNonPromise(globalObject, resultValue == nullptr ? moduleRecord : resultValue); - return JSValue::encode(promise); -} - -String dumpRecordInfo(JSModuleRecord* moduleRecord) -{ - WTF::StringPrintStream stream; - - stream.print(" varDeclarations:\n"); - for (const auto& pair : moduleRecord->m_declaredVariables) { - stream.print(" - ", pair.key, "\n"); - } - - stream.print(" lexicalVariables:\n"); - for (const auto& pair : moduleRecord->m_lexicalVariables) { - stream.print(" - ", pair.key, "\n"); - } - - stream.print(" features: "); - stream.print(moduleRecord->m_features & ImportMetaFeature); - stream.print("\n"); - - stream.print("\nAnalyzing ModuleRecord key(", moduleRecord->moduleKey().impl(), ")\n"); - - stream.print(" Dependencies: ", moduleRecord->requestedModules().size(), " modules\n"); - for (const auto& request : moduleRecord->requestedModules()) - if (request.m_attributes == nullptr) { - stream.print(" module(", request.m_specifier, ")\n"); - } else { - stream.print(" module(", request.m_specifier, "),attributes(", (uint8_t)request.m_attributes->type(), ", ", request.m_attributes->hostDefinedImportType(), ")\n"); - } - - stream.print(" Import: ", moduleRecord->importEntries().size(), " entries\n"); - for (const auto& pair : moduleRecord->importEntries()) { - auto& importEntry = pair.value; - stream.print(" import(", importEntry.importName, "), local(", importEntry.localName, "), module(", importEntry.moduleRequest, ")\n"); - } - - stream.print(" Export: ", moduleRecord->exportEntries().size(), " entries\n"); - Vector sortedEntries; - for (const auto& pair : moduleRecord->exportEntries()) { - WTF::StringPrintStream line; - auto& exportEntry = pair.value; - switch (exportEntry.type) { - case AbstractModuleRecord::ExportEntry::Type::Local: - line.print(" [Local] ", "export(", exportEntry.exportName, "), local(", exportEntry.localName, ")\n"); - break; - - case AbstractModuleRecord::ExportEntry::Type::Indirect: - line.print(" [Indirect] ", "export(", exportEntry.exportName, "), import(", exportEntry.importName, "), module(", exportEntry.moduleName, ")\n"); - break; - - case AbstractModuleRecord::ExportEntry::Type::Namespace: - line.print(" [Namespace] ", "export(", exportEntry.exportName, "), module(", exportEntry.moduleName, ")\n"); - break; - } - sortedEntries.append(line.toString()); - } - std::sort(sortedEntries.begin(), sortedEntries.end(), [](const String& a, const String& b) { - return a.utf8().toStdString() < b.utf8().toStdString(); - }); - for (const auto& entry : sortedEntries) - stream.print(entry); - - for (const auto& moduleName : moduleRecord->starExportEntries()) - stream.print(" [Star] module(", moduleName.get(), ")\n"); - - stream.print(" -> done\n"); - - return stream.toString(); -} - -} diff --git a/src/bun.js/bindings/BunAnalyzeTranspiledModule.h b/src/bun.js/bindings/BunAnalyzeTranspiledModule.h deleted file mode 100644 index 9a4e055d0d0ace..00000000000000 --- a/src/bun.js/bindings/BunAnalyzeTranspiledModule.h +++ /dev/null @@ -1 +0,0 @@ -struct bun_ModuleInfoDeserialized; diff --git a/src/bun.js/bindings/CommonJSModuleRecord.cpp b/src/bun.js/bindings/CommonJSModuleRecord.cpp index bac55fc1dccd20..5fb4cdb9d2d275 100644 --- a/src/bun.js/bindings/CommonJSModuleRecord.cpp +++ b/src/bun.js/bindings/CommonJSModuleRecord.cpp @@ -1145,7 +1145,7 @@ bool JSCommonJSModule::evaluate( bool isBuiltIn) { auto& vm = globalObject->vm(); - auto sourceProvider = Zig::SourceProvider::create(jsCast(globalObject), source, isBuiltIn); + auto sourceProvider = Zig::SourceProvider::create(jsCast(globalObject), source, JSC::SourceProviderSourceType::Program, isBuiltIn); this->ignoreESModuleAnnotation = source.tag == ResolvedSourceTagPackageJSONTypeModule; if (this->hasEvaluated) return true; @@ -1199,7 +1199,7 @@ std::optional createCommonJSModule( dirname = jsEmptyString(vm); } - auto sourceProvider = Zig::SourceProvider::create(jsCast(globalObject), source, isBuiltIn); + auto sourceProvider = Zig::SourceProvider::create(jsCast(globalObject), source, JSC::SourceProviderSourceType::Program, isBuiltIn); sourceOrigin = sourceProvider->sourceOrigin(); moduleObject = JSCommonJSModule::create( vm, diff --git a/src/bun.js/bindings/ModuleLoader.cpp b/src/bun.js/bindings/ModuleLoader.cpp index bb116b0662afcf..bb0653d1e8052f 100644 --- a/src/bun.js/bindings/ModuleLoader.cpp +++ b/src/bun.js/bindings/ModuleLoader.cpp @@ -745,7 +745,7 @@ static JSValue fetchESMSourceCode( auto tag = res->result.value.tag; switch (tag) { case SyntheticModuleType::ESM: { - auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value, true); + auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value, JSC::SourceProviderSourceType::Module, true); return rejectOrResolve(JSSourceCode::create(vm, JSC::SourceCode(provider))); } @@ -764,7 +764,7 @@ static JSValue fetchESMSourceCode( auto source = JSC::SourceCode(JSC::SyntheticSourceProvider::create(generateInternalModuleSourceCode(globalObject, static_cast(tag & mask)), JSC::SourceOrigin(URL(makeString("builtins://"_s, moduleKey))), moduleKey)); return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source))); } else { - auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value, true); + auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value, JSC::SourceProviderSourceType::Module, true); return rejectOrResolve(JSC::JSSourceCode::create(vm, JSC::SourceCode(provider))); } } diff --git a/src/bun.js/bindings/ZigSourceProvider.cpp b/src/bun.js/bindings/ZigSourceProvider.cpp index e6914bcd88e5fb..acb4f530f1001c 100644 --- a/src/bun.js/bindings/ZigSourceProvider.cpp +++ b/src/bun.js/bindings/ZigSourceProvider.cpp @@ -75,17 +75,9 @@ extern "C" void Bun__removeSourceProviderSourceMap(void* bun_vm, SourceProvider* Ref SourceProvider::create( Zig::GlobalObject* globalObject, ResolvedSource& resolvedSource, + JSC::SourceProviderSourceType sourceType, bool isBuiltin) { - - JSC::SourceProviderSourceType sourceType = JSC::SourceProviderSourceType::BunTranspiledModule; - if (resolvedSource.isCommonJSModule) { - ASSERT(resolvedSource.module_info == nullptr, "isCommonJSModule should not have module_info"); - sourceType = JSC::SourceProviderSourceType::Program; - } else if (resolvedSource.module_info == nullptr) { - sourceType = JSC::SourceProviderSourceType::Module; - } - auto string = resolvedSource.source_code.toWTFString(BunString::ZeroCopy); auto sourceURLString = resolvedSource.source_url.toWTFString(BunString::ZeroCopy); diff --git a/src/bun.js/bindings/ZigSourceProvider.h b/src/bun.js/bindings/ZigSourceProvider.h index 73e0fbb88cd0e6..eddb638665775d 100644 --- a/src/bun.js/bindings/ZigSourceProvider.h +++ b/src/bun.js/bindings/ZigSourceProvider.h @@ -39,6 +39,7 @@ class SourceProvider final : public JSC::SourceProvider { static Ref create( Zig::GlobalObject*, ResolvedSource& resolvedSource, + JSC::SourceProviderSourceType sourceType = JSC::SourceProviderSourceType::Module, bool isBuiltIn = false); ~SourceProvider(); unsigned hash() const override; diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index e804c0c8d31921..1d88a6d235db0b 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -7062,7 +7062,3 @@ pub const DeferredError = struct { return err; } }; - -comptime { - _ = @import("../../analyze_transpiled_module.zig"); -} diff --git a/src/bun.js/bindings/exports.zig b/src/bun.js/bindings/exports.zig index 5bcb682cb33075..a6b716c523232e 100644 --- a/src/bun.js/bindings/exports.zig +++ b/src/bun.js/bindings/exports.zig @@ -205,7 +205,6 @@ pub fn Errorable(comptime Type: type) type { }; } -/// must be kept in sync with `ResolvedSource` in `headers-handwritten.h` pub const ResolvedSource = extern struct { pub const shim = Shimmer("Zig", "ResolvedSource", @This()); pub const name = "ResolvedSource"; @@ -235,14 +234,6 @@ pub const ResolvedSource = extern struct { bytecode_cache: ?[*]u8 = null, bytecode_cache_size: usize = 0, - /// - for esm: null means to use jsc's regular parsing step. more info: https://github.com/oven-sh/bun/pull/15758 - /// - for cjs: must be null - module_info: ?*@import("../../analyze_transpiled_module.zig").ModuleInfoDeserialized, - - pub const unfilled = ResolvedSource{ - .module_info = null, - }; - pub const Tag = @import("ResolvedSourceTag").ResolvedSourceTag; }; diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h index 72c96c46aa9d7c..01c5c1a9788ce9 100644 --- a/src/bun.js/bindings/headers-handwritten.h +++ b/src/bun.js/bindings/headers-handwritten.h @@ -3,7 +3,6 @@ #include "wtf/text/OrdinalNumber.h" #include "JavaScriptCore/JSCJSValue.h" #include "JavaScriptCore/ArgList.h" -#include "BunAnalyzeTranspiledModule.h" #include #ifndef HEADERS_HANDWRITTEN @@ -108,7 +107,6 @@ typedef struct ResolvedSource { bool already_bundled; uint8_t* bytecode_cache; size_t bytecode_cache_size; - bun_ModuleInfoDeserialized* module_info; } ResolvedSource; static const uint32_t ResolvedSourceTagPackageJSONTypeModule = 1; typedef union ErrorableResolvedSourceResult { diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index bb03ba2415d17a..41d5c1ba2fff69 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -2336,7 +2336,6 @@ pub const VirtualMachine = struct { .hash = 0, .allocator = null, .source_code_needs_deref = false, - .module_info = null, }; } var source = this.refCountedString(code, hash_, !add_double_ref); @@ -2352,7 +2351,6 @@ pub const VirtualMachine = struct { .hash = source.hash, .allocator = source, .source_code_needs_deref = false, - .module_info = null, }; } diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig index b6141e518cfd56..cfc603014746cb 100644 --- a/src/bun.js/module_loader.zig +++ b/src/bun.js/module_loader.zig @@ -13,8 +13,6 @@ const default_allocator = bun.default_allocator; const StoredFileDescriptorType = bun.StoredFileDescriptorType; const Arena = @import("../allocators/mimalloc_arena.zig").Arena; const C = bun.C; -const analyze_transpiled_module = @import("../analyze_transpiled_module.zig"); -const ModuleInfo = analyze_transpiled_module.ModuleInfo; const Allocator = std.mem.Allocator; const IdentityContext = @import("../identity_context.zig").IdentityContext; @@ -99,7 +97,6 @@ inline fn jsSyntheticModule(comptime name: ResolvedSource.Tag, specifier: String .hash = 0, .tag = name, .source_code_needs_deref = false, - .module_info = null, }; } @@ -289,7 +286,7 @@ pub const RuntimeTranspilerStore = struct { generation_number: u32 = 0, log: logger.Log, parse_error: ?anyerror = null, - resolved_source: ResolvedSource = ResolvedSource.unfilled, + resolved_source: ResolvedSource = ResolvedSource{}, work_task: JSC.WorkPoolTask = .{ .callback = runFromWorkerThread }, next: ?*TranspilerJob = null, @@ -412,7 +409,6 @@ pub const RuntimeTranspilerStore = struct { var cache = JSC.RuntimeTranspilerCache{ .output_code_allocator = allocator, .sourcemap_allocator = bun.default_allocator, - .esm_record_allocator = bun.default_allocator, }; var vm = this.vm; @@ -558,19 +554,6 @@ pub const RuntimeTranspilerStore = struct { dumpSourceString(vm, specifier, entry.output_code.byteSlice()); } - var module_info: ?*analyze_transpiled_module.ModuleInfoDeserialized = null; - if (entry.esm_record.len > 0) { - if (entry.metadata.module_type == .cjs) { - @panic("TranspilerCache contained cjs module with module info"); - } - module_info = analyze_transpiled_module.ModuleInfoDeserialized.create(entry.esm_record, bun.default_allocator) catch |e| switch (e) { - error.OutOfMemory => bun.outOfMemory(), - // uh oh! invalid module info in cache - // (not sure what to do here) - error.BadModuleInfo => @panic("TranspilerCache contained invalid module info"), - }; - } - this.resolved_source = ResolvedSource{ .allocator = null, .source_code = switch (entry.output_code) { @@ -586,7 +569,6 @@ pub const RuntimeTranspilerStore = struct { .source_url = duped.createIfDifferent(path.text), .hash = 0, .is_commonjs_module = entry.metadata.module_type == .cjs, - .module_info = module_info, }; return; @@ -605,7 +587,6 @@ pub const RuntimeTranspilerStore = struct { .bytecode_cache = if (bytecode_slice.len > 0) bytecode_slice.ptr else null, .bytecode_cache_size = bytecode_slice.len, .is_commonjs_module = parse_result.already_bundled.isCommonJS(), - .module_info = null, }; this.resolved_source.source_code.ensureHash(); return; @@ -658,10 +639,6 @@ pub const RuntimeTranspilerStore = struct { var printer = source_code_printer.?.*; printer.ctx.reset(); - const is_commonjs_module = parse_result.ast.has_commonjs_export_names or parse_result.ast.exports_kind == .cjs; - const module_info: ?*ModuleInfo = if (is_commonjs_module) null else ModuleInfo.create(bun.default_allocator) catch bun.outOfMemory(); - // defer module_info.destroy(); // TODO: do not leak module_info - { var mapper = vm.sourceMapHandler(&printer); defer source_code_printer.?.* = printer; @@ -671,7 +648,6 @@ pub const RuntimeTranspilerStore = struct { &printer, .esm_ascii, mapper.get(), - module_info, ) catch |err| { this.parse_error = err; return; @@ -705,15 +681,13 @@ pub const RuntimeTranspilerStore = struct { break :brk result; }; - this.resolved_source = ResolvedSource{ .allocator = null, .source_code = source_code, .specifier = duped, .source_url = duped.createIfDifferent(path.text), - .is_commonjs_module = is_commonjs_module, + .is_commonjs_module = parse_result.ast.has_commonjs_export_names or parse_result.ast.exports_kind == .cjs, .hash = 0, - .module_info = if (module_info) |mi| mi.asDeserialized() else null, }; } }; @@ -1432,10 +1406,6 @@ pub const ModuleLoader = struct { var printer = VirtualMachine.source_code_printer.?.*; printer.ctx.reset(); - const is_commonjs_module = parse_result.ast.has_commonjs_export_names or parse_result.ast.exports_kind == .cjs; - const module_info: ?*ModuleInfo = if (is_commonjs_module) null else ModuleInfo.create(bun.default_allocator) catch bun.outOfMemory(); - // defer module_info.destroy(); // TODO: do not leak module_info - { var mapper = jsc_vm.sourceMapHandler(&printer); defer VirtualMachine.source_code_printer.?.* = printer; @@ -1445,7 +1415,6 @@ pub const ModuleLoader = struct { &printer, .esm_ascii, mapper.get(), - module_info, ); } @@ -1470,7 +1439,7 @@ pub const ModuleLoader = struct { } } - resolved_source.is_commonjs_module = is_commonjs_module; + resolved_source.is_commonjs_module = parse_result.ast.has_commonjs_export_names or parse_result.ast.exports_kind == .cjs; return resolved_source; } @@ -1480,10 +1449,9 @@ pub const ModuleLoader = struct { .source_code = bun.String.createLatin1(printer.ctx.getWritten()), .specifier = String.init(specifier), .source_url = String.init(path.text), - .is_commonjs_module = is_commonjs_module, + .is_commonjs_module = parse_result.ast.has_commonjs_export_names or parse_result.ast.exports_kind == .cjs, .hash = 0, - .module_info = if (module_info) |mi| mi.asDeserialized() else null, }; } @@ -1545,7 +1513,6 @@ pub const ModuleLoader = struct { .specifier = input_specifier, .source_url = input_specifier.createIfDifferent(path.text), .hash = 0, - .module_info = null, }; } } @@ -1613,7 +1580,6 @@ pub const ModuleLoader = struct { var cache = JSC.RuntimeTranspilerCache{ .output_code_allocator = allocator, .sourcemap_allocator = bun.default_allocator, - .esm_record_allocator = bun.default_allocator, }; const old = jsc_vm.transpiler.log; @@ -1780,7 +1746,6 @@ pub const ModuleLoader = struct { .hash = 0, .tag = ResolvedSource.Tag.json_for_object_loader, - .module_info = null, }; } @@ -1795,7 +1760,6 @@ pub const ModuleLoader = struct { .specifier = input_specifier, .source_url = input_specifier.createIfDifferent(path.text), .hash = 0, - .module_info = null, }; } @@ -1808,7 +1772,6 @@ pub const ModuleLoader = struct { .hash = 0, .jsvalue_for_export = JSC.JSValue.createEmptyObject(jsc_vm.global, 0), .tag = .exports_object, - .module_info = null, }; } @@ -1819,7 +1782,6 @@ pub const ModuleLoader = struct { .hash = 0, .jsvalue_for_export = parse_result.ast.parts.@"[0]"().stmts[0].data.s_expr.value.toJS(allocator, globalObject orelse jsc_vm.global) catch |e| panic("Unexpected JS error: {s}", .{@errorName(e)}), .tag = .exports_object, - .module_info = null, }; } @@ -1835,7 +1797,6 @@ pub const ModuleLoader = struct { .bytecode_cache = if (bytecode_slice.len > 0) bytecode_slice.ptr else null, .bytecode_cache_size = if (bytecode_slice.len > 0) bytecode_slice.len else 0, .is_commonjs_module = parse_result.already_bundled.isCommonJS(), - .module_info = null, }; } @@ -1849,19 +1810,6 @@ pub const ModuleLoader = struct { dumpSourceString(jsc_vm, specifier, entry.output_code.byteSlice()); } - var module_info: ?*analyze_transpiled_module.ModuleInfoDeserialized = null; - if (entry.esm_record.len > 0) { - if (entry.metadata.module_type == .cjs) { - @panic("TranspilerCache contained cjs module with module info"); - } - module_info = analyze_transpiled_module.ModuleInfoDeserialized.create(entry.esm_record, bun.default_allocator) catch |e| switch (e) { - error.OutOfMemory => bun.outOfMemory(), - // uh oh! invalid module info in cache - // (not sure what to do here) - error.BadModuleInfo => @panic("TranspilerCache contained invalid module info"), - }; - } - return ResolvedSource{ .allocator = null, .source_code = switch (entry.output_code) { @@ -1894,7 +1842,6 @@ pub const ModuleLoader = struct { break :brk ResolvedSource.Tag.javascript; }, - .module_info = module_info, }; } @@ -1949,11 +1896,6 @@ pub const ModuleLoader = struct { var printer = source_code_printer.*; printer.ctx.reset(); defer source_code_printer.* = printer; - - const is_commonjs_module = parse_result.ast.has_commonjs_export_names or parse_result.ast.exports_kind == .cjs; - const module_info: ?*ModuleInfo = if (is_commonjs_module) null else ModuleInfo.create(bun.default_allocator) catch bun.outOfMemory(); - // defer module_info.destroy(); // TODO: do not leak module_info - _ = brk: { var mapper = jsc_vm.sourceMapHandler(&printer); @@ -1963,7 +1905,6 @@ pub const ModuleLoader = struct { &printer, .esm_ascii, mapper.get(), - module_info, ); }; @@ -2016,10 +1957,9 @@ pub const ModuleLoader = struct { }, .specifier = input_specifier, .source_url = input_specifier.createIfDifferent(path.text), - .is_commonjs_module = is_commonjs_module, + .is_commonjs_module = parse_result.ast.has_commonjs_export_names or parse_result.ast.exports_kind == .cjs, .hash = 0, .tag = tag, - .module_info = if (module_info) |mi| mi.asDeserialized() else null, }; }, // provideFetch() should be called @@ -2088,7 +2028,6 @@ pub const ModuleLoader = struct { .source_url = input_specifier.createIfDifferent(path.text), .tag = .esm, .hash = 0, - .module_info = null, }; } @@ -2149,7 +2088,6 @@ pub const ModuleLoader = struct { .source_url = input_specifier.createIfDifferent(path.text), .tag = .esm, .hash = 0, - .module_info = null, }; }, @@ -2231,7 +2169,6 @@ pub const ModuleLoader = struct { .specifier = input_specifier, .source_url = input_specifier.createIfDifferent(path.text), .hash = 0, - .module_info = null, }; }, } @@ -2504,7 +2441,6 @@ pub const ModuleLoader = struct { .specifier = specifier, .source_url = specifier, .hash = Runtime.Runtime.versionHash(), - .module_info = null, }; } else if (HardcodedModule.Map.getWithEql(specifier, bun.String.eqlComptime)) |hardcoded| { Analytics.Features.builtin_modules.insert(hardcoded); @@ -2519,7 +2455,6 @@ pub const ModuleLoader = struct { .hash = 0, .tag = .esm, .source_code_needs_deref = true, - .module_info = null, }; }, @@ -2629,7 +2564,6 @@ pub const ModuleLoader = struct { .specifier = specifier, .source_url = specifier.dupeRef(), .hash = 0, - .module_info = null, }; } } else if (jsc_vm.standalone_module_graph) |graph| { @@ -2653,7 +2587,6 @@ pub const ModuleLoader = struct { .source_url = specifier.dupeRef(), .hash = 0, .source_code_needs_deref = false, - .module_info = null, }; } @@ -2667,7 +2600,6 @@ pub const ModuleLoader = struct { .bytecode_cache = if (file.bytecode.len > 0) file.bytecode.ptr else null, .bytecode_cache_size = file.bytecode.len, .is_commonjs_module = file.module_format == .cjs, - .module_info = null, }; } } diff --git a/src/js_ast.zig b/src/js_ast.zig index f78d7dbe8ced2f..6b4fd31d3283d4 100644 --- a/src/js_ast.zig +++ b/src/js_ast.zig @@ -322,6 +322,10 @@ pub const Binding = struct { loc: logger.Loc, }; + pub fn jsonStringify(self: *const @This(), writer: anytype) !void { + return try writer.write(Serializable{ .type = std.meta.activeTag(self.data), .object = "binding", .value = self.data, .loc = self.loc }); + } + pub fn ToExpr(comptime expr_type: type, comptime func_type: anytype) type { const ExprType = expr_type; return struct { @@ -2850,89 +2854,6 @@ pub const Stmt = struct { loc: logger.Loc, }; - pub fn print(self: *const Stmt, tree: Ast, writer: std.io.AnyWriter) !void { - _ = tree; - switch (self.data) { - .s_import => |simport| { - // const record = &tree.import_records.slice()[simport.import_record_index]; - try writer.print(".s_import{{\n", .{}); - try writer.print(" import_records[import_record_index = {d}] = ,\n", .{simport.import_record_index}); - // simport.default_name - // simport.is_single_line - // simport.items - // simport.namespace_ref - - // === record: === - // range: logger.Range, - // path: fs.Path, - // kind: ImportKind, - // tag: Tag = .none, - // source_index: Index = Index.invalid, - // print_mode: PrintMode = .normal, - // handles_import_errors: bool = false, - // is_internal: bool = false, - // is_unused: bool = false, - // contains_import_star: bool = false, - // contains_default_alias: bool = false, - // contains_es_module_alias: bool = false, - // calls_runtime_re_export_fn: bool = false, - // is_inside_try_body: bool = false, - // was_originally_bare_import: bool = false, - // was_originally_require: bool = false, - // was_injected_by_macro: bool = false, - // is_external_without_side_effects: bool = false, - // print_namespace_in_path: bool = false, - // wrap_with_to_esm: bool = false, - // wrap_with_to_commonjs: bool = false, - - try writer.print(" ", .{}); - try writer.print("}}", .{}); - }, - .s_expr => |expr| { - try writer.print(".s_expr{{ .does_not_affect_tree_shaking = {}, .value = ", .{expr.does_not_affect_tree_shaking}); - try expr.value.print(writer, 0); - try writer.print("}}", .{}); - }, - .s_local => |local| { - try writer.print(".s_local{{ .kind = .{s}, .is_export = {}, .was_ts_import_equals = {}, .was_commonjs_export = {}, .decls = .{{\n", .{ @tagName(local.kind), local.is_export, local.was_ts_import_equals, local.was_commonjs_export }); - for (local.decls.slice()) |m| { - try writer.print(" .{{\n .binding = ", .{}); - switch (m.binding.data) { - .b_array => |v| { - try writer.print(".b_array{{ .has_spread = {}, .is_single_line = {}, .items = .{{", .{ v.has_spread, v.is_single_line }); - for (v.items, 0..) |item, i| { - if (i != 0) try writer.print(", ", .{}); - try writer.print("(TODO)", .{}); - _ = item; - } - try writer.print("}}}}", .{}); - }, - .b_identifier => |v| { - try writer.print(".b_identifier{{ .ref = {} }}", .{v.ref}); - }, - .b_object => { - try writer.print(".b_object", .{}); - }, - .b_missing => { - try writer.print(".b_missing", .{}); - }, - } - try writer.print(",\n .value = ", .{}); - if (m.value == null) { - try writer.print("null", .{}); - } else { - try m.value.?.print(writer, 2); - } - try writer.print(",\n }},\n", .{}); - } - try writer.print("}} }}", .{}); - }, - else => { - try writer.print(".{s}._todo_print_stmt", .{@tagName(self.data)}); - }, - } - } - pub fn jsonStringify(self: *const Stmt, writer: anytype) !void { return try writer.write(Serializable{ .type = std.meta.activeTag(self.data), .object = "stmt", .value = self.data, .loc = self.loc }); } @@ -3312,18 +3233,6 @@ pub const Expr = struct { loc: logger.Loc, data: Data, - pub fn print(self: *const Expr, writer: std.io.AnyWriter, depth: u32) !void { - _ = depth; - switch (self.data) { - .e_string => |str| { - try writer.print("(string: \"{s}\")", .{bun.strings.formatEscapes(str.data, .{ .str_encoding = .utf8, .quote_char = '"' })}); - }, - else => { - try writer.print("(expr: {s})", .{@tagName(self.data)}); - }, - } - } - pub const empty = Expr{ .data = .{ .e_missing = E.Missing{} }, .loc = logger.Loc.Empty }; pub fn isAnonymousNamed(expr: Expr) bool { diff --git a/src/js_printer.zig b/src/js_printer.zig index be9dd807f10ff4..8cb2b6327de6c5 100644 --- a/src/js_printer.zig +++ b/src/js_printer.zig @@ -23,8 +23,6 @@ const Ref = @import("ast/base.zig").Ref; const StoredFileDescriptorType = bun.StoredFileDescriptorType; const FeatureFlags = bun.FeatureFlags; const FileDescriptorType = bun.FileDescriptor; -const analyze_transpiled_module = @import("analyze_transpiled_module.zig"); -const ModuleInfo = analyze_transpiled_module.ModuleInfo; const expect = std.testing.expect; const ImportKind = importRecord.ImportKind; @@ -692,38 +690,8 @@ fn NewPrinter( binary_expression_stack: std.ArrayList(BinaryExpressionVisitor) = undefined, - module_info: if (!may_have_module_info) void else ?*ModuleInfo = if (!may_have_module_info) {} else null, - const Printer = @This(); - const may_have_module_info = is_bun_platform and !rewrite_esm_to_cjs; - const TopLevelAndIsExport = if (!may_have_module_info) struct {} else struct { - is_export: bool = false, - is_top_level: ?ModuleInfo.VarKind = null, - }; - const TopLevel = if (!may_have_module_info) struct { - pub inline fn init(_: IsTopLevel) @This() { - return .{}; - } - pub inline fn subVar(_: @This()) @This() { - return .{}; - } - } else struct { - is_top_level: IsTopLevel = .no, - pub inline fn init(is_top_level: IsTopLevel) @This() { - return .{ .is_top_level = is_top_level }; - } - pub fn subVar(self: @This()) @This() { - if (self.is_top_level == .no) return @This().init(.no); - return @This().init(.var_only); - } - }; - const IsTopLevel = enum { yes, var_only, no }; - inline fn moduleInfo(self: *const @This()) ?*ModuleInfo { - if (!may_have_module_info) return null; - return self.module_info; - } - /// When Printer is used as a io.Writer, this represents it's error type, aka nothing. pub const Error = error{}; @@ -1020,7 +988,6 @@ fn NewPrinter( printInternalBunImport(p, import, @TypeOf("globalThis.Bun.jest(__filename)"), "globalThis.Bun.jest(__filename)"); }, else => { - if (p.moduleInfo()) |mi| mi.contains_import_meta = true; printInternalBunImport(p, import, @TypeOf("globalThis.Bun.jest(import.meta.path)"), "globalThis.Bun.jest(import.meta.path)"); }, } @@ -1036,9 +1003,7 @@ fn NewPrinter( if (import.star_name_loc != null) { p.print("var "); - const name = p.renamer.nameForSymbol(import.namespace_ref); - p.printIdentifier(name); - if (p.moduleInfo()) |mi| mi.addVar(name, .declared) catch bun.outOfMemory(); + p.printSymbol(import.namespace_ref); p.printSpace(); p.print("="); p.printSpaceBeforeIdentifier(); @@ -1061,9 +1026,7 @@ fn NewPrinter( if (import.default_name) |default| { p.print("var "); - const default_name = p.renamer.nameForSymbol(default.ref.?); - p.printIdentifier(default_name); - if (p.moduleInfo()) |mi| mi.addVar(default_name, .declared) catch bun.outOfMemory(); + p.printSymbol(default.ref.?); if (comptime Statement == void) { p.@"print = "(); p.printRequireOrImportExpr( @@ -1101,11 +1064,7 @@ fn NewPrinter( } } - p.printVarClauseItem(item); - if (p.moduleInfo()) |mi| { - const varname = p.renamer.nameForSymbol(item.name.ref.?); - mi.addVar(varname, .declared) catch bun.outOfMemory(); - } + p.printClauseItemAs(item, .@"var"); } if (!import.is_single_line) { @@ -1177,32 +1136,32 @@ fn NewPrinter( switch (stmt.data) { .s_block => |block| { p.printSpace(); - p.printBlock(stmt.loc, block.stmts, block.close_brace_loc, .{}); + p.printBlock(stmt.loc, block.stmts, block.close_brace_loc); p.printNewline(); }, else => { p.printNewline(); p.indent(); - p.printStmt(stmt, .{}) catch bun.outOfMemory(); + p.printStmt(stmt) catch unreachable; p.unindent(); }, } } - pub fn printBlockBody(p: *Printer, stmts: []const Stmt, tlmtlo: TopLevel) void { + pub fn printBlockBody(p: *Printer, stmts: []const Stmt) void { for (stmts) |stmt| { p.printSemicolonIfNeeded(); - p.printStmt(stmt, tlmtlo) catch bun.outOfMemory(); + p.printStmt(stmt) catch unreachable; } } - pub fn printBlock(p: *Printer, loc: logger.Loc, stmts: []const Stmt, close_brace_loc: ?logger.Loc, tlmtlo: TopLevel) void { + pub fn printBlock(p: *Printer, loc: logger.Loc, stmts: []const Stmt, close_brace_loc: ?logger.Loc) void { p.addSourceMapping(loc); p.print("{"); p.printNewline(); p.indent(); - p.printBlockBody(stmts, tlmtlo); + p.printBlockBody(stmts); p.unindent(); p.needs_semicolon = false; @@ -1219,8 +1178,8 @@ fn NewPrinter( p.printNewline(); p.indent(); - p.printBlockBody(prepend, .{}); - p.printBlockBody(stmts, .{}); + p.printBlockBody(prepend); + p.printBlockBody(stmts); p.unindent(); p.needs_semicolon = false; @@ -1228,7 +1187,7 @@ fn NewPrinter( p.print("}"); } - pub fn printDecls(p: *Printer, comptime keyword: string, decls_: []G.Decl, flags: ExprFlag.Set, tlm: TopLevelAndIsExport) void { + pub fn printDecls(p: *Printer, comptime keyword: string, decls_: []G.Decl, flags: ExprFlag.Set) void { p.print(keyword); p.printSpace(); var decls = decls_; @@ -1336,7 +1295,7 @@ fn NewPrinter( .is_single_line = true, }; const binding = Binding.init(&b_object, target_e_dot.target.loc); - p.printBinding(binding, tlm); + p.printBinding(binding); } p.printWhitespacer(ws(" = ")); @@ -1352,7 +1311,7 @@ fn NewPrinter( } { - p.printBinding(decls[0].binding, tlm); + p.printBinding(decls[0].binding); if (decls[0].value) |value| { p.printWhitespacer(ws(" = ")); @@ -1364,7 +1323,7 @@ fn NewPrinter( p.print(","); p.printSpace(); - p.printBinding(decl.binding, tlm); + p.printBinding(decl.binding); if (decl.value) |value| { p.printWhitespacer(ws(" = ")); @@ -1431,7 +1390,7 @@ fn NewPrinter( p.print("..."); } - p.printBinding(arg.binding, .{}); + p.printBinding(arg.binding); if (arg.default) |default| { p.printWhitespacer(ws(" = ")); @@ -1447,7 +1406,7 @@ fn NewPrinter( pub fn printFunc(p: *Printer, func: G.Fn) void { p.printFnArgs(func.open_parens_loc, func.args, func.flags.contains(.has_rest_arg), false); p.printSpace(); - p.printBlock(func.body.loc, func.body.stmts, null, .{}); + p.printBlock(func.body.loc, func.body.stmts, null); } pub fn printClass(p: *Printer, class: G.Class) void { if (class.extends) |extends| { @@ -1470,7 +1429,7 @@ fn NewPrinter( if (item.kind == .class_static_block) { p.print("static"); p.printSpace(); - p.printBlock(item.class_static_block.?.loc, item.class_static_block.?.stmts.slice(), null, .{}); + p.printBlock(item.class_static_block.?.loc, item.class_static_block.?.stmts.slice(), null); p.printNewline(); continue; } @@ -1711,14 +1670,12 @@ fn NewPrinter( if (module_type == .cjs) { p.print("Promise.resolve(globalThis.Bun.jest(__filename))"); } else { - if (p.moduleInfo()) |mi| mi.contains_import_meta = true; p.print("Promise.resolve(globalThis.Bun.jest(import.meta.path))"); } } else if (record.kind == .require) { if (module_type == .cjs) { p.print("globalThis.Bun.jest(__filename)"); } else { - if (p.moduleInfo()) |mi| mi.contains_import_meta = true; p.print("globalThis.Bun.jest(import.meta.path)"); } } @@ -1941,28 +1898,45 @@ fn NewPrinter( p.print(quote); } - fn printExportClauseItem(p: *Printer, item: js_ast.ClauseItem) void { - const name = p.renamer.nameForSymbol(item.name.ref.?); - - p.printIdentifier(name); + fn printClauseItem(p: *Printer, item: js_ast.ClauseItem) void { + return printClauseItemAs(p, item, .import); + } - if (!strings.eql(name, item.alias)) { - p.print(" as "); - p.addSourceMapping(item.alias_loc); - p.printClauseAlias(item.alias); - } + fn printExportClauseItem(p: *Printer, item: js_ast.ClauseItem) void { + return printClauseItemAs(p, item, .@"export"); } - fn printVarClauseItem(p: *Printer, item: js_ast.ClauseItem) void { + fn printClauseItemAs(p: *Printer, item: js_ast.ClauseItem, comptime as: @Type(.EnumLiteral)) void { const name = p.renamer.nameForSymbol(item.name.ref.?); - p.printClauseAlias(item.alias); + if (comptime as == .import) { + if (strings.eql(name, item.alias)) { + p.printIdentifier(name); + } else { + p.printClauseAlias(item.alias); + p.print(" as "); + p.addSourceMapping(item.alias_loc); + p.printIdentifier(name); + } + } else if (comptime as == .@"var") { + p.printClauseAlias(item.alias); - if (!strings.eql(name, item.alias)) { - p.print(":"); - p.printSpace(); + if (!strings.eql(name, item.alias)) { + p.print(":"); + p.printSpace(); + p.printIdentifier(name); + } + } else if (comptime as == .@"export") { p.printIdentifier(name); + + if (!strings.eql(name, item.alias)) { + p.print(" as "); + p.addSourceMapping(item.alias_loc); + p.printClauseAlias(item.alias); + } + } else { + @compileError("Unknown as"); } } @@ -2074,7 +2048,6 @@ fn NewPrinter( p.print(".importMeta()"); } else if (!p.options.import_meta_ref.isValid()) { // Most of the time, leave it in there - if (p.moduleInfo()) |mi| mi.contains_import_meta = true; p.print("import.meta"); } else { // Note: The bundler will not hit this code path. The bundler will replace @@ -2101,7 +2074,6 @@ fn NewPrinter( p.printSpaceBeforeIdentifier(); p.addSourceMapping(expr.loc); } - if (p.moduleInfo()) |mi| mi.contains_import_meta = true; p.print("import.meta.main"); } else { bun.assert(p.options.module_type != .internal_bake_dev); @@ -2569,7 +2541,7 @@ fn NewPrinter( } if (!wasPrinted) { - p.printBlock(e.body.loc, e.body.stmts, null, .{}); + p.printBlock(e.body.loc, e.body.stmts, null); } if (wrap) { @@ -3477,19 +3449,13 @@ fn NewPrinter( p.printExpr(initial, .comma, ExprFlag.None()); } - pub fn printBinding(p: *Printer, binding: Binding, tlm: TopLevelAndIsExport) void { + pub fn printBinding(p: *Printer, binding: Binding) void { switch (binding.data) { .b_missing => {}, .b_identifier => |b| { p.printSpaceBeforeIdentifier(); p.addSourceMapping(binding.loc); - const local_name = p.renamer.nameForSymbol(b.ref); - p.printIdentifier(local_name); - - if (p.moduleInfo()) |mi| { - if (tlm.is_top_level) |vk| mi.addVar(local_name, vk) catch bun.outOfMemory(); - if (tlm.is_export) mi.addExportInfoLocal(local_name, local_name) catch bun.outOfMemory(); - } + p.printSymbol(b.ref); }, .b_array => |b| { p.print("["); @@ -3516,7 +3482,7 @@ fn NewPrinter( p.print("..."); } - p.printBinding(item.binding, tlm); + p.printBinding(item.binding); p.maybePrintDefaultBindingValue(item); @@ -3563,7 +3529,7 @@ fn NewPrinter( p.print("]:"); p.printSpace(); - p.printBinding(property.value, tlm); + p.printBinding(property.value); p.maybePrintDefaultBindingValue(property); continue; } @@ -3588,10 +3554,6 @@ fn NewPrinter( switch (property.value.data) { .b_identifier => |id| { if (str.eql(string, p.renamer.nameForSymbol(id.ref))) { - if (p.moduleInfo()) |mi| { - if (tlm.is_top_level) |vk| mi.addVar(str.data, vk) catch bun.outOfMemory(); - if (tlm.is_export) mi.addExportInfoLocal(str.data, str.data) catch bun.outOfMemory(); - } p.maybePrintDefaultBindingValue(property); continue; } @@ -3609,11 +3571,6 @@ fn NewPrinter( switch (property.value.data) { .b_identifier => |id| { if (strings.utf16EqlString(str.slice16(), p.renamer.nameForSymbol(id.ref))) { - if (p.moduleInfo()) |mi| { - const str8 = str.slice(p.options.allocator); - if (tlm.is_top_level) |vk| mi.addVar(str8, vk) catch bun.outOfMemory(); - if (tlm.is_export) mi.addExportInfoLocal(str8, str8) catch bun.outOfMemory(); - } p.maybePrintDefaultBindingValue(property); continue; } @@ -3633,7 +3590,7 @@ fn NewPrinter( p.printSpace(); } - p.printBinding(property.value, tlm); + p.printBinding(property.value); p.maybePrintDefaultBindingValue(property); } @@ -3659,7 +3616,7 @@ fn NewPrinter( } } - pub fn printStmt(p: *Printer, stmt: Stmt, tlmtlo: TopLevel) !void { + pub fn printStmt(p: *Printer, stmt: Stmt) !void { const prev_stmt_tag = p.prev_stmt_tag; defer { @@ -3693,15 +3650,9 @@ fn NewPrinter( p.printSpaceBeforeIdentifier(); p.addSourceMapping(name.loc); - const local_name = p.renamer.nameForSymbol(nameRef); - p.printIdentifier(local_name); + p.printSymbol(nameRef); p.printFunc(s.func); - if (p.moduleInfo()) |mi| { - if (tlmtlo.is_top_level == .yes) try mi.addVar(local_name, .lexical); - if (s.func.flags.contains(.is_export)) try mi.addExportInfoLocal(local_name, local_name); - } - // if (rewrite_esm_to_cjs and s.func.flags.contains(.is_export)) { // p.printSemicolonAfterStatement(); // p.print("var "); @@ -3728,7 +3679,6 @@ fn NewPrinter( p.printIndent(); p.printSpaceBeforeIdentifier(); const nameRef = s.class.class_name.?.ref.?; - const nameStr = p.renamer.nameForSymbol(nameRef); if (s.is_export) { if (!rewrite_esm_to_cjs) { p.print("export "); @@ -3737,14 +3687,9 @@ fn NewPrinter( p.print("class "); p.addSourceMapping(s.class.class_name.?.loc); - p.printIdentifier(nameStr); + p.printSymbol(nameRef); p.printClass(s.class); - if (p.moduleInfo()) |mi| { - if (s.is_export) try mi.addExportInfoLocal(nameStr, nameStr); - if (tlmtlo.is_top_level == .yes) try mi.addVar(nameStr, .lexical); - } - if (rewrite_esm_to_cjs and s.is_export) { p.printSemicolonAfterStatement(); } else { @@ -3778,10 +3723,6 @@ fn NewPrinter( p.export_default_start = p.writer.written; p.printExpr(expr, .comma, ExprFlag.None()); p.printSemicolonAfterStatement(); - if (p.moduleInfo()) |mi| { - try mi.addExportInfoLocal("default", ModuleInfo.star_default); - try mi.addVar(ModuleInfo.star_default, .lexical); - } return; }, @@ -3802,26 +3743,20 @@ fn NewPrinter( p.maybePrintSpace(); } - const func_name: ?[]const u8 = if (func.func.name) |f| p.renamer.nameForSymbol(f.ref.?) else null; - if (func_name) |f| p.printIdentifier(f); + if (func.func.name) |name| { + p.printSymbol(name.ref.?); + } p.printFunc(func.func); p.printNewline(); - - if (p.moduleInfo()) |mi| { - const local_name = func_name orelse ModuleInfo.star_default; - try mi.addExportInfoLocal("default", local_name); - try mi.addVar(local_name, .lexical); - } }, .s_class => |class| { p.printSpaceBeforeIdentifier(); - const class_name: ?[]const u8 = if (class.class.class_name) |f| p.renamer.nameForSymbol(f.ref.?) else null; - if (class_name) |name| { + if (class.class.class_name) |name| { p.print("class "); - p.printIdentifier(name); + p.printSymbol(name.ref orelse Output.panic("Internal error: Expected class to have a name ref\n{any}", .{class})); } else { p.print("class"); } @@ -3829,12 +3764,6 @@ fn NewPrinter( p.printClass(class.class); p.printNewline(); - - if (p.moduleInfo()) |mi| { - const local_name = class_name orelse ModuleInfo.star_default; - try mi.addExportInfoLocal("default", local_name); - try mi.addVar(local_name, .lexical); - } }, else => { Output.panic("Internal error: unexpected export default stmt data {any}", .{s}); @@ -3852,27 +3781,19 @@ fn NewPrinter( p.printIndent(); p.printSpaceBeforeIdentifier(); + if (s.alias != null) + p.printWhitespacer(comptime ws("export *").append(" as ")) + else + p.printWhitespacer(comptime ws("export * from ")); + if (s.alias) |alias| { - p.printWhitespacer(comptime ws("export *").append(" as ")); p.printClauseAlias(alias.original_name); p.print(" "); p.printWhitespacer(ws("from ")); - } else { - p.printWhitespacer(comptime ws("export * from ")); } - const irp = try p.fmtImportRecordPath(p.importRecord(s.import_record_index)); - p.printStringLiteralUTF8(irp, false); + p.printImportRecordPath(p.importRecord(s.import_record_index)); p.printSemicolonAfterStatement(); - - if (p.moduleInfo()) |mi| { - try mi.requestModule(irp, .none); - if (s.alias) |alias| { - try mi.addExportInfoNamespace(alias.original_name, irp); - } else { - try mi.addExportInfoStar(irp); - } - } }, .s_export_clause => |s| { if (rewrite_esm_to_cjs) { @@ -4020,12 +3941,7 @@ fn NewPrinter( p.printIndent(); } - const name = p.renamer.nameForSymbol(item.name.ref.?); p.printExportClauseItem(item); - - if (p.moduleInfo()) |mi| { - try mi.addExportInfoLocal(item.alias, name); - } } if (!s.is_single_line) { @@ -4077,26 +3993,26 @@ fn NewPrinter( } p.printWhitespacer(ws("} from ")); - const irp = try p.fmtImportRecordPath(import_record); - p.printStringLiteralUTF8(irp, false); + p.printImportRecordPath(import_record); p.printSemicolonAfterStatement(); - - if (p.moduleInfo()) |mi| { - try mi.requestModule(irp, .none); - for (s.items) |item| { - // how could this be renamed, it's in `export from`? - const name = p.renamer.nameForSymbol(item.name.ref.?); - try mi.addExportInfoIndirect(item.alias, name, irp); - } - } }, .s_local => |s| { switch (s.kind) { - .k_const => p.printDeclStmt(s.is_export, "const", s.decls.slice(), tlmtlo), - .k_let => p.printDeclStmt(s.is_export, "let", s.decls.slice(), tlmtlo), - .k_var => p.printDeclStmt(s.is_export, "var", s.decls.slice(), tlmtlo), - .k_using => p.printDeclStmt(s.is_export, "using", s.decls.slice(), tlmtlo), - .k_await_using => p.printDeclStmt(s.is_export, "await using", s.decls.slice(), tlmtlo), + .k_const => { + p.printDeclStmt(s.is_export, "const", s.decls.slice()); + }, + .k_let => { + p.printDeclStmt(s.is_export, "let", s.decls.slice()); + }, + .k_var => { + p.printDeclStmt(s.is_export, "var", s.decls.slice()); + }, + .k_using => { + p.printDeclStmt(s.is_export, "using", s.decls.slice()); + }, + .k_await_using => { + p.printDeclStmt(s.is_export, "await using", s.decls.slice()); + }, } }, .s_if => |s| { @@ -4110,13 +4026,13 @@ fn NewPrinter( switch (s.body.data) { .s_block => { p.printSpace(); - p.printBlock(s.body.loc, s.body.data.s_block.stmts, s.body.data.s_block.close_brace_loc, .{}); + p.printBlock(s.body.loc, s.body.data.s_block.stmts, s.body.data.s_block.close_brace_loc); p.printSpace(); }, else => { p.printNewline(); p.indent(); - p.printStmt(s.body, .{}) catch unreachable; + p.printStmt(s.body) catch unreachable; p.printSemicolonIfNeeded(); p.unindent(); p.printIndent(); @@ -4199,7 +4115,7 @@ fn NewPrinter( p.printSpaceBeforeIdentifier(); p.print("try"); p.printSpace(); - p.printBlock(s.body_loc, s.body, null, tlmtlo.subVar()); + p.printBlock(s.body_loc, s.body, null); if (s.catch_) |catch_| { p.printSpace(); @@ -4207,18 +4123,18 @@ fn NewPrinter( if (catch_.binding) |binding| { p.printSpace(); p.print("("); - p.printBinding(binding, .{}); + p.printBinding(binding); p.print(")"); } p.printSpace(); - p.printBlock(catch_.loc, catch_.body, null, tlmtlo.subVar()); + p.printBlock(catch_.loc, catch_.body, null); } if (s.finally) |finally| { p.printSpace(); p.print("finally"); p.printSpace(); - p.printBlock(finally.loc, finally.stmts, null, tlmtlo.subVar()); + p.printBlock(finally.loc, finally.stmts, null); } p.printNewline(); @@ -4283,7 +4199,7 @@ fn NewPrinter( switch (c.body[0].data) { .s_block => { p.printSpace(); - p.printBlock(c.body[0].loc, c.body[0].data.s_block.stmts, c.body[0].data.s_block.close_brace_loc, .{}); + p.printBlock(c.body[0].loc, c.body[0].data.s_block.stmts, c.body[0].data.s_block.close_brace_loc); p.printNewline(); continue; }, @@ -4295,7 +4211,7 @@ fn NewPrinter( p.indent(); for (c.body) |st| { p.printSemicolonIfNeeded(); - p.printStmt(st, .{}) catch unreachable; + p.printStmt(st) catch unreachable; } p.unindent(); } @@ -4376,7 +4292,6 @@ fn NewPrinter( p.printSymbol(s.namespace_ref); p.@"print = "(); - if (p.moduleInfo()) |mi| mi.contains_import_meta = true; p.print("import.meta.require("); p.printImportRecordPath(record); p.print(")"); @@ -4429,7 +4344,7 @@ fn NewPrinter( p.print(","); p.printSpace(); for (s.items, 0..) |item, i| { - p.printVarClauseItem(item); + p.printClauseItemAs(item, .@"var"); if (i < s.items.len - 1) { p.print(","); @@ -4439,7 +4354,7 @@ fn NewPrinter( } } else { for (s.items, 0..) |item, i| { - p.printVarClauseItem(item); + p.printClauseItemAs(item, .@"var"); if (i < s.items.len - 1) { p.print(","); @@ -4471,18 +4386,10 @@ fn NewPrinter( var item_count: usize = 0; - const import_record_path = try p.fmtImportRecordPath(record); - if (s.default_name) |name| { p.print(" "); - const local_name = p.renamer.nameForSymbol(name.ref.?); - p.printIdentifier(local_name); + p.printSymbol(name.ref.?); item_count += 1; - - if (p.moduleInfo()) |mi| { - try mi.addVar(local_name, .lexical); - try mi.addImportInfoSingle(import_record_path, "default", local_name); - } } if (s.items.len > 0) { @@ -4511,20 +4418,7 @@ fn NewPrinter( p.printIndent(); } - const local_name = p.renamer.nameForSymbol(item.name.ref.?); - if (strings.eql(local_name, item.alias)) { - p.printIdentifier(local_name); - } else { - p.printClauseAlias(item.alias); - p.print(" as "); - p.addSourceMapping(item.alias_loc); - p.printIdentifier(local_name); - } - - if (p.moduleInfo()) |mi| { - try mi.addVar(local_name, .lexical); - try mi.addImportInfoSingle(import_record_path, item.alias, local_name); - } + p.printClauseItem(item); } if (!s.is_single_line) { @@ -4544,17 +4438,10 @@ fn NewPrinter( } p.printSpace(); - const local_name = p.renamer.nameForSymbol(s.namespace_ref); - p.printWhitespacer(ws("* as")); p.print(" "); - p.printIdentifier(local_name); + p.printSymbol(s.namespace_ref); item_count += 1; - - if (p.moduleInfo()) |mi| { - try mi.addVar(local_name, .lexical); - try mi.addImportInfoNamespace(import_record_path, local_name); - } } if (item_count > 0) { @@ -4566,54 +4453,43 @@ fn NewPrinter( p.printWhitespacer(ws("from ")); } - p.printStringLiteralUTF8(import_record_path, false); + p.printImportRecordPath(record); - var fetch_parameters: ModuleInfo.FetchParameters = if (p.moduleInfo() != null) .none else undefined; switch (record.tag) { .with_type_sqlite, .with_type_sqlite_embedded => { // we do not preserve "embed": "true" since it is not necessary p.printWhitespacer(ws(" with { type: \"sqlite\" }")); - if (p.moduleInfo()) |mi| fetch_parameters = ModuleInfo.FetchParameters.hostDefined(try mi.str("sqlite")); }, .with_type_text => { if (comptime is_bun_platform) { p.printWhitespacer(ws(" with { type: \"text\" }")); - if (p.moduleInfo()) |mi| fetch_parameters = ModuleInfo.FetchParameters.hostDefined(try mi.str("text")); } }, .with_type_json => { // backwards compatibility: previously, we always stripped type json if (comptime is_bun_platform) { p.printWhitespacer(ws(" with { type: \"json\" }")); - if (p.moduleInfo() != null) fetch_parameters = .json; } }, .with_type_toml => { // backwards compatibility: previously, we always stripped type if (comptime is_bun_platform) { p.printWhitespacer(ws(" with { type: \"toml\" }")); - if (p.moduleInfo()) |mi| fetch_parameters = ModuleInfo.FetchParameters.hostDefined(try mi.str("toml")); } }, .with_type_file => { // backwards compatibility: previously, we always stripped type if (comptime is_bun_platform) { p.printWhitespacer(ws(" with { type: \"file\" }")); - if (p.moduleInfo()) |mi| fetch_parameters = ModuleInfo.FetchParameters.hostDefined(try mi.str("file")); } }, else => {}, } - - if (p.moduleInfo()) |mi| { - try mi.requestModule(import_record_path, fetch_parameters); - } - p.printSemicolonAfterStatement(); }, .s_block => |s| { p.printIndent(); - p.printBlock(stmt.loc, s.stmts, s.close_brace_loc, .{}); + p.printBlock(stmt.loc, s.stmts, s.close_brace_loc); p.printNewline(); }, .s_debugger => { @@ -4692,16 +4568,22 @@ fn NewPrinter( p.print("module.exports"); } - pub fn fmtImportRecordPath(p: *Printer, import_record: *const ImportRecord) ![]const u8 { - if (comptime is_json) unreachable; + pub fn printImportRecordPath(p: *Printer, import_record: *const ImportRecord) void { + if (comptime is_json) + unreachable; + const quote = bestQuoteCharForString(u8, import_record.path.text, false); if (import_record.print_namespace_in_path and !import_record.path.isFile()) { - return try std.fmt.allocPrint(p.options.allocator, "{s}:{s}", .{ import_record.path.namespace, import_record.path.text }); + p.print(quote); + p.printStringCharactersUTF8(import_record.path.namespace, quote); + p.print(":"); + p.printStringCharactersUTF8(import_record.path.text, quote); + p.print(quote); + } else { + p.print(quote); + p.printStringCharactersUTF8(import_record.path.text, quote); + p.print(quote); } - return import_record.path.text; - } - pub fn printImportRecordPath(p: *Printer, import_record: *const ImportRecord) void { - p.printStringLiteralUTF8(p.fmtImportRecordPath(import_record) catch bun.outOfMemory(), false); } pub fn printBundledImport(p: *Printer, record: ImportRecord, s: *S.Import) void { @@ -4877,11 +4759,21 @@ fn NewPrinter( }, .s_local => |s| { switch (s.kind) { - .k_var => p.printDecls("var", s.decls.slice(), ExprFlag.Set.init(.{ .forbid_in = true }), .{}), - .k_let => p.printDecls("let", s.decls.slice(), ExprFlag.Set.init(.{ .forbid_in = true }), .{}), - .k_const => p.printDecls("const", s.decls.slice(), ExprFlag.Set.init(.{ .forbid_in = true }), .{}), - .k_using => p.printDecls("using", s.decls.slice(), ExprFlag.Set.init(.{ .forbid_in = true }), .{}), - .k_await_using => p.printDecls("await using", s.decls.slice(), ExprFlag.Set.init(.{ .forbid_in = true }), .{}), + .k_var => { + p.printDecls("var", s.decls.slice(), ExprFlag.Set.init(.{ .forbid_in = true })); + }, + .k_let => { + p.printDecls("let", s.decls.slice(), ExprFlag.Set.init(.{ .forbid_in = true })); + }, + .k_const => { + p.printDecls("const", s.decls.slice(), ExprFlag.Set.init(.{ .forbid_in = true })); + }, + .k_using => { + p.printDecls("using", s.decls.slice(), ExprFlag.Set.init(.{ .forbid_in = true })); + }, + .k_await_using => { + p.printDecls("await using", s.decls.slice(), ExprFlag.Set.init(.{ .forbid_in = true })); + }, } }, // for(;) @@ -4902,7 +4794,7 @@ fn NewPrinter( switch (s.yes.data) { .s_block => |block| { p.printSpace(); - p.printBlock(s.yes.loc, block.stmts, block.close_brace_loc, .{}); + p.printBlock(s.yes.loc, block.stmts, block.close_brace_loc); if (s.no != null) { p.printSpace(); @@ -4917,7 +4809,7 @@ fn NewPrinter( p.printNewline(); p.indent(); - p.printStmt(s.yes, .{}) catch bun.outOfMemory(); + p.printStmt(s.yes) catch unreachable; p.unindent(); p.needs_semicolon = false; @@ -4932,7 +4824,7 @@ fn NewPrinter( } else { p.printNewline(); p.indent(); - p.printStmt(s.yes, .{}) catch bun.outOfMemory(); + p.printStmt(s.yes) catch unreachable; p.unindent(); if (s.no != null) { @@ -4950,7 +4842,7 @@ fn NewPrinter( switch (no_block.data) { .s_block => { p.printSpace(); - p.printBlock(no_block.loc, no_block.data.s_block.stmts, null, .{}); + p.printBlock(no_block.loc, no_block.data.s_block.stmts, null); p.printNewline(); }, .s_if => { @@ -4959,7 +4851,7 @@ fn NewPrinter( else => { p.printNewline(); p.indent(); - p.printStmt(no_block, .{}) catch bun.outOfMemory(); + p.printStmt(no_block) catch unreachable; p.unindent(); }, } @@ -5040,17 +4932,14 @@ fn NewPrinter( } } - pub fn printDeclStmt(p: *Printer, is_export: bool, comptime keyword: string, decls: []G.Decl, tlmtlo: TopLevel) void { + pub fn printDeclStmt(p: *Printer, is_export: bool, comptime keyword: string, decls: []G.Decl) void { p.printIndent(); p.printSpaceBeforeIdentifier(); if (!rewrite_esm_to_cjs and is_export) { p.print("export "); } - p.printDecls(keyword, decls, ExprFlag.None(), if (may_have_module_info) .{ - .is_export = is_export and !rewrite_esm_to_cjs, - .is_top_level = if (comptime std.mem.eql(u8, keyword, "var")) if (tlmtlo.is_top_level == .no) null else .declared else if (tlmtlo.is_top_level == .yes) .lexical else null, - } else .{}); + p.printDecls(keyword, decls, ExprFlag.None()); p.printSemicolonAfterStatement(); if (rewrite_esm_to_cjs and is_export and decls.len > 0) { for (decls) |decl| { @@ -5095,7 +4984,7 @@ fn NewPrinter( p.print("}"); }, else => { - p.printBinding(decl.binding, .{}); + p.printBinding(decl.binding); }, } p.print(")"); @@ -5778,7 +5667,6 @@ pub fn printAst( comptime ascii_only: bool, opts: Options, comptime generate_source_map: bool, - module_info: ?*@import("analyze_transpiled_module.zig").ModuleInfo, ) !usize { var renamer: rename.Renamer = undefined; var no_op_renamer: rename.NoOpRenamer = undefined; @@ -5877,11 +5765,6 @@ pub fn printAst( printer.source_map_builder.line_offset_tables.deinit(opts.allocator); } } - if (module_info != null) bun.assert(PrinterType.may_have_module_info); - const have_module_info = PrinterType.may_have_module_info and module_info != null; - - if (have_module_info) printer.module_info = module_info; - var bin_stack_heap = std.heap.stackFallback(1024, bun.default_allocator); printer.binary_expression_stack = std.ArrayList(PrinterType.BinaryExpressionVisitor).init(bin_stack_heap.get()); defer printer.binary_expression_stack.clearAndFree(); @@ -5905,13 +5788,12 @@ pub fn printAst( // // This is never a symbol collision because `uses_require_ref` means // `require` must be an unbound variable. - if (printer.moduleInfo()) |mi| mi.contains_import_meta = true; printer.print("var {require}=import.meta;"); } for (tree.parts.slice()) |part| { for (part.stmts) |stmt| { - try printer.printStmt(stmt, PrinterType.TopLevel.init(.yes)); + try printer.printStmt(stmt); if (printer.writer.getError()) {} else |err| { return err; } @@ -5919,24 +5801,23 @@ pub fn printAst( } } - if (have_module_info) { - try module_info.?.finalize(); - } - - var sourcemap: []const u8 = ""; - if (comptime generate_source_map) { + if (comptime FeatureFlags.runtime_transpiler_cache and generate_source_map) { if (opts.source_map_handler) |handler| { const source_maps_chunk = printer.source_map_builder.generateChunk(printer.writer.ctx.getWritten()); - sourcemap = source_maps_chunk.buffer.list.items; + if (opts.runtime_transpiler_cache) |cache| { + cache.put(printer.writer.ctx.getWritten(), source_maps_chunk.buffer.list.items); + } try handler.onSourceMapChunk(source_maps_chunk, source.*); + } else { + if (opts.runtime_transpiler_cache) |cache| { + cache.put(printer.writer.ctx.getWritten(), ""); + } + } + } else if (comptime generate_source_map) { + if (opts.source_map_handler) |handler| { + try handler.onSourceMapChunk(printer.source_map_builder.generateChunk(printer.writer.ctx.getWritten()), source.*); } - } - if (opts.runtime_transpiler_cache) |cache| { - var srlz_res = std.ArrayList(u8).init(bun.default_allocator); - defer srlz_res.deinit(); - if (have_module_info) try module_info.?.asDeserialized().serialize(srlz_res.writer()); - cache.put(printer.writer.ctx.getWritten(), sourcemap, srlz_res.items); } try printer.writer.done(); @@ -6125,7 +6006,7 @@ pub fn printWithWriterAndPlatform( for (parts) |part| { for (part.stmts) |stmt| { - printer.printStmt(stmt, PrinterType.TopLevel.init(.yes)) catch |err| { + printer.printStmt(stmt) catch |err| { return .{ .err = err }; }; if (printer.writer.getError()) {} else |err| { @@ -6188,7 +6069,7 @@ pub fn printCommonJS( for (tree.parts.slice()) |part| { for (part.stmts) |stmt| { - try printer.printStmt(stmt, PrinterType.TopLevel.init(.yes)); + try printer.printStmt(stmt); if (printer.writer.getError()) {} else |err| { return err; } diff --git a/src/string_immutable.zig b/src/string_immutable.zig index db9db240b6160a..ab1d7964908809 100644 --- a/src/string_immutable.zig +++ b/src/string_immutable.zig @@ -6473,7 +6473,7 @@ fn QuoteEscapeFormat(comptime flags: QuoteEscapeFormatFlags) type { data: []const u8, pub fn format(self: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { - try bun.js_printer.writePreQuotedString(self.data, @TypeOf(writer), writer, flags.quote_char, flags.ascii_only, flags.json, flags.str_encoding); + try bun.js_printer.writePreQuotedString(self.data, @TypeOf(writer), writer, flags.quote_char, false, flags.json, flags.str_encoding); } }; } diff --git a/src/transpiler.zig b/src/transpiler.zig index 54ec22dff3fb7d..5836e0e20c1447 100644 --- a/src/transpiler.zig +++ b/src/transpiler.zig @@ -1068,15 +1068,12 @@ pub const Transpiler = struct { comptime enable_source_map: bool, source_map_context: ?js_printer.SourceMapHandler, runtime_transpiler_cache: ?*bun.JSC.RuntimeTranspilerCache, - module_info: ?*@import("analyze_transpiled_module.zig").ModuleInfo, ) !usize { const tracer = bun.tracy.traceNamed(@src(), if (enable_source_map) "JSPrinter.printWithSourceMap" else "JSPrinter.print"); defer tracer.end(); const symbols = js_ast.Symbol.NestedList.init(&[_]js_ast.Symbol.List{ast.symbols}); - if (module_info != null) bun.assert(format == .esm or format == .esm_ascii); - return switch (format) { .cjs => try js_printer.printCommonJS( Writer, @@ -1123,7 +1120,6 @@ pub const Transpiler = struct { .print_dce_annotations = transpiler.options.emit_dce_annotations, }, enable_source_map, - module_info, ), .esm_ascii => switch (transpiler.options.target.isBun()) { inline else => |is_bun| try js_printer.printAst( @@ -1158,7 +1154,6 @@ pub const Transpiler = struct { .print_dce_annotations = transpiler.options.emit_dce_annotations, }, enable_source_map, - module_info, ), }, else => unreachable, @@ -1181,7 +1176,6 @@ pub const Transpiler = struct { false, null, null, - null, ); } @@ -1192,7 +1186,6 @@ pub const Transpiler = struct { writer: Writer, comptime format: js_printer.Format, handler: js_printer.SourceMapHandler, - module_info: ?*@import("analyze_transpiled_module.zig").ModuleInfo, ) !usize { if (bun.getRuntimeFeatureFlag("BUN_FEATURE_FLAG_DISABLE_SOURCE_MAPS")) { return transpiler.printWithSourceMapMaybe( @@ -1204,7 +1197,6 @@ pub const Transpiler = struct { false, handler, result.runtime_transpiler_cache, - module_info, ); } return transpiler.printWithSourceMapMaybe( @@ -1216,7 +1208,6 @@ pub const Transpiler = struct { true, handler, result.runtime_transpiler_cache, - module_info, ); } diff --git a/test/js/bun/typescript/type-export.test.ts b/test/js/bun/typescript/type-export.test.ts deleted file mode 100644 index 2f44ac4577196e..00000000000000 --- a/test/js/bun/typescript/type-export.test.ts +++ /dev/null @@ -1,174 +0,0 @@ -import { describe, test, expect } from "bun:test" with { todo: "true" }; -import { bunEnv, bunExe, tempDirWithFiles } from "harness"; - -/* -Potential solutions: -- Option 1: Make a fake export `export const my_string = undefined;` and make sure it is not enumerable -- Option 2: In b.ts, make javascriptcore skip re-exporting something if it is not found rather than SyntaxErroring - - this won't work because in the import {} export {} case, the error will be on the import -*/ - -const a_file = ` - export type my_string = "1"; - - export type my_value = "2"; - export const my_value = "2"; - - export const my_only = "3"; -`; -const a_no_value = ` - export type my_string = "1"; - export type my_value = "2"; - export const my_only = "3"; -`; -const a_with_value = ` - export type my_string = "1"; - export const my_value = "2"; -`; -const b_files = [ - { - name: "export from", - value: `export { my_string, my_value, my_only } from "./a.ts";`, - }, - { - name: "import then export", - value: ` - import { my_string, my_value, my_only } from "./a.ts"; - export { my_string, my_value, my_only }; - `, - }, - { - name: "export star", - value: `export * from "./a.ts";`, - }, - { - name: "export merge", - value: `export * from "./a_no_value.ts"; export * from "./a_with_value.ts"`, - }, -]; -const c_files = [ - { name: "require", value: `console.log(JSON.stringify(require("./b")));` }, - { name: "import star", value: `import * as b from "./b"; console.log(JSON.stringify(b));` }, - { name: "await import", value: `console.log(JSON.stringify(await import("./b")));` }, - { - name: "import individual", - value: ` - import { my_string, my_value, my_only } from "./b"; - console.log(JSON.stringify({ my_only, my_value })); - `, - }, -]; -for (const b_file of b_files) { - describe(`re-export with ${b_file.name}`, () => { - for (const c_file of c_files) { - describe(`import with ${c_file.name}`, () => { - const dir = tempDirWithFiles("type-export", { - "a.ts": a_file, - "b.ts": b_file.value, - "c.ts": c_file.value, - - "a_no_value.ts": a_no_value, - "a_with_value.ts": a_with_value, - }); - - const runAndVerify = (filename: string) => { - const result = Bun.spawnSync({ - cmd: [bunExe(), "run", filename], - cwd: dir, - env: bunEnv, - stdio: ["inherit", "pipe", "inherit"], - }); - - expect(result.exitCode).toBe(0); - expect(JSON.parse(result.stdout.toString().trim())).toEqual({ my_value: "2", my_only: "3" }); - }; - - test.todoIf(b_file.name !== "export star" && b_file.name !== "export merge")("run", () => { - runAndVerify("c.ts"); - }); - - test("build", async () => { - const result = Bun.spawnSync({ - cmd: [bunExe(), "build", "--target=bun", "--outfile", "bundle.js", "c.ts"], - cwd: dir, - env: bunEnv, - stdio: ["inherit", "inherit", "inherit"], - }); - - expect(result.exitCode).toBe(0); - runAndVerify("bundle.js"); - }); - }); - } - }); -} - -test("import not found", () => { - const dir = tempDirWithFiles("type-export", { - "a.ts": `export const a = 25; export const c = "hello";`, - "b.ts": /*js*/ ` - import { a, b, c } from "./a"; - console.log(a, b, c); - `, - }); - - const result = Bun.spawnSync({ - cmd: [bunExe(), "run", "b.ts"], - cwd: dir, - env: bunEnv, - stdio: ["inherit", "pipe", "pipe"], - }); - - expect(result.stderr?.toString().trim()).toContain("SyntaxError: Export named 'b' not found in module"); - expect({ - exitCode: result.exitCode, - stdout: result.stdout?.toString().trim(), - }).toEqual({ - exitCode: 1, - stdout: "", - }); -}); - -describe("through export merge", () => { - // this isn't allowed, even in typescript (tsc emits "Duplicate identifier 'value'.") - for (const fmt of ["js", "ts"]) { - describe(fmt, () => { - for (const [name, mode] of [ - ["through", "export {value} from './b'; export {value} from './c';"], - ["direct", "export {value} from './b'; export const value = 'abc';"], - ["direct2", "export const value = 'abc'; export {value};"], - ["ns", "export * as value from './c'; export * as value from './c';"], - ]) { - describe(name, () => { - const dir = tempDirWithFiles("type-import", { - ["main." + fmt]: "import {value} from './a'; console.log(value);", - ["a." + fmt]: mode, - ["b." + fmt]: fmt === "ts" ? "export type value = 'b';" : "", - ["c." + fmt]: "export const value = 'c';", - }); - for (const file of ["main." + fmt, "a." + fmt]) { - test(file, () => { - const result = Bun.spawnSync({ - cmd: [bunExe(), file], - cwd: dir, - env: bunEnv, - stdio: ["inherit", "pipe", "pipe"], - }); - expect(result.stderr?.toString().trim()).toInclude( - file === "a." + fmt - ? 'error: Multiple exports with the same name "value"\n' // bun's syntax error - : "SyntaxError: Cannot export a duplicate name 'value'.\n", // jsc's syntax error - ); - expect(result.exitCode).toBe(1); - }); - } - }); - } - }); - } -}); - -// TODO: -// - check ownkeys from a star import -// - check commonjs cases -// - what happens with `export * from ./a; export * from ./b` where a and b have different definitions of the same name?