diff --git a/src/analyze_transpiled_module.zig b/src/analyze_transpiled_module.zig
index 7ca4cb9a63..72a9467722 100644
--- a/src/analyze_transpiled_module.zig
+++ b/src/analyze_transpiled_module.zig
@@ -11,44 +11,179 @@ const Ast = js_ast.Ast;
// @panic("TODO analyzeTranspiledModule");
// }
+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_len: u32,
+ strings: []const u8, // null-terminated
+ 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,
+
+ 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;
+ }
+ 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 parse(source: []const u8) !ModuleInfoDeserialized {
+ var rem = source[0..];
+ 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 = rem;
+
+ return .{
+ .strings_len = strings_len,
+ .strings = strings,
+ .requested_modules_keys = requested_modules_keys,
+ .requested_modules_values = requested_modules_values,
+ .buffer = buffer,
+ .record_kinds = record_kinds,
+ .contains_import_meta = contains_import_meta,
+ };
+ }
+};
+
pub const ModuleInfo = struct {
/// all strings in wtf-8. index in hashmap = StringID
strings: bun.StringArrayHashMap(void),
requested_modules: std.AutoArrayHashMap(StringID, FetchParameters),
- imports: std.ArrayList(ImportInfo),
- exports: std.ArrayList(ExportInfo),
- declared_variables: std.ArrayList(StringID),
- lexical_variables: std.ArrayList(StringID),
+ buffer: std.ArrayList(StringID),
+ record_kinds: std.ArrayList(RecordKind),
contains_import_meta: bool,
- pub const FetchParameters = union(enum) {
- none,
- javascript,
- webassembly,
- json,
- host_defined: StringID,
+ pub fn serialize(self: *ModuleInfo, final_writer: anytype) !void {
+ var res = std.ArrayList(u8).init(bun.default_allocator);
+ defer res.deinit();
+ const writer = res.writer();
+
+ try writer.writeInt(u32, @truncate(self.record_kinds.items.len), .little);
+ try writer.writeAll(std.mem.sliceAsBytes(self.record_kinds.items));
+ try writer.writeInt(u32, @truncate(self.buffer.items.len), .little);
+ try writer.writeAll(std.mem.sliceAsBytes(self.buffer.items));
+
+ try writer.writeInt(u32, @truncate(self.requested_modules.count()), .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.count()), .little);
+ for (self.strings.keys()) |s| {
+ try writer.writeAll(s);
+ try writer.writeByte(0);
+ }
+
+ const enc_buf = try bun.default_allocator.alloc(u8, std.base64.standard.Encoder.calcSize(res.items.len));
+ defer bun.default_allocator.free(enc_buf);
+ const enc_res = std.base64.standard.Encoder.encode(enc_buf, res.items);
+
+ try final_writer.writeAll("\n// \n// ");
+ try final_writer.writeAll(enc_res);
+ try final_writer.writeAll("\n// \n");
+ }
+
+ 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 {
- const id = try self.str(name);
- try self.addVarStrID(id, kind);
- }
- pub fn addVarStrID(self: *ModuleInfo, id: StringID, kind: VarKind) !void {
switch (kind) {
- .declared => try self.declared_variables.append(id),
- .lexical => try self.lexical_variables.append(id),
+ .declared => try self.addDeclaredVariable(name),
+ .lexical => try self.addLexicalVariable(name),
}
}
+ fn _addRecord(self: *ModuleInfo, kind: RecordKind, data: []const StringID) !void {
+ 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 {
+ try self._addRecord(.export_info_indirect, &.{ try self.str(export_name), try self.str(import_name), try self.str(module_name) });
+ }
+ pub fn addExportInfoLocal(self: *ModuleInfo, export_name: []const u8, local_name: []const u8) !void {
+ try self._addRecord(.export_info_local, &.{ try self.str(export_name), try self.str(local_name), @enumFromInt(0) });
+ }
+ pub fn addExportInfoNamespace(self: *ModuleInfo, export_name: []const u8, module_name: []const u8) !void {
+ try self._addRecord(.export_info_namespace, &.{ try self.str(export_name), 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 init(allocator: std.mem.Allocator) ModuleInfo {
return .{
.strings = bun.StringArrayHashMap(void).init(allocator),
.requested_modules = std.AutoArrayHashMap(StringID, FetchParameters).init(allocator),
- .imports = std.ArrayList(ImportInfo).init(allocator),
- .exports = std.ArrayList(ExportInfo).init(allocator),
- .declared_variables = std.ArrayList(StringID).init(allocator),
- .lexical_variables = std.ArrayList(StringID).init(allocator),
+ .buffer = std.ArrayList(StringID).init(allocator),
+ .record_kinds = std.ArrayList(RecordKind).init(allocator),
.contains_import_meta = false,
};
}
@@ -56,10 +191,8 @@ pub const ModuleInfo = struct {
for (self.strings.keys()) |string| self.strings.allocator.free(string);
self.strings.deinit();
self.requested_modules.deinit();
- self.imports.deinit();
- self.exports.deinit();
- self.declared_variables.deinit();
- self.lexical_variables.deinit();
+ self.buffer.deinit();
+ self.record_kinds.deinit();
}
pub fn str(self: *ModuleInfo, value: []const u8) !StringID {
const gpres = try self.strings.getOrPut(value);
@@ -68,9 +201,7 @@ pub const ModuleInfo = struct {
gpres.value_ptr.* = {};
return @enumFromInt(@as(u32, @intCast(gpres.index)));
}
- pub fn starDefault(self: *ModuleInfo) !StringID {
- return try self.str("*default*");
- }
+ 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));
@@ -79,127 +210,34 @@ pub const ModuleInfo = struct {
/// find any exports marked as 'local' that are actually 'indirect' and fix them
pub fn fixupIndirectExports(self: *ModuleInfo) !void {
- var local_name_to_module_name = std.AutoArrayHashMap(StringID, *ImportInfo).init(self.strings.allocator);
+ var local_name_to_module_name = std.AutoArrayHashMap(StringID, [2]StringID).init(self.strings.allocator);
defer local_name_to_module_name.deinit();
- for (self.imports.items) |*ip| {
- try local_name_to_module_name.put(ip.local_name, ip);
+ {
+ 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], [2]StringID{ self.buffer.items[i], self.buffer.items[i + 1] });
+ i += k.len() catch unreachable;
+ }
}
- for (self.exports.items) |*xp| {
- if (xp.* == .local) {
- if (local_name_to_module_name.get(xp.local.local_name)) |ip| {
- if (ip.kind == .single) {
- xp.* = .{ .indirect = .{ .export_name = xp.local.export_name, .import_name = ip.import_name, .module_name = ip.module_name } };
+ {
+ 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[0];
+ self.buffer.items[i + 2] = ip[1];
+ continue;
}
}
+ i += k.len() catch unreachable;
}
}
}
-
- const JsonStringifyableModuleInfo = struct {
- strings: []const struct {
- comptime {
- if (@sizeOf(@This()) != @sizeOf([]const u8) or @alignOf(@This()) != @alignOf([]const u8)) unreachable;
- }
- value: []const u8,
- pub fn jsonStringify(self: @This(), jw: anytype) !void {
- if (jw.next_punctuation == .comma) try jw.stream.writeByte(',');
- if (jw.next_punctuation == .colon) try jw.stream.writeByte(':');
- try jw.stream.print("\"{}\"", .{bun.strings.formatEscapes(self.value, .{ .quote_char = '"', .ascii_only = true, .json = true })});
- jw.next_punctuation = .comma;
- }
- pub fn jsonParse(alloc: std.mem.Allocator, source: anytype, options: anytype) !@This() {
- const token = try source.nextAllocMax(alloc, .alloc_if_needed, options.max_value_len.?);
- if (token == .string) return .{ .value = token.string };
- if (token != .allocated_string) return error.UnexpectedToken;
- return .{ .value = token.allocated_string };
- }
- },
- requested_modules_keys: []const StringID,
- requested_modules_values: []const FetchParameters,
- imports: []const ImportInfo,
- exports: []const ExportInfo,
- declared_variables: []const StringID,
- lexical_variables: []const StringID,
- contains_import_meta: bool,
- };
-
- pub fn jsonStringify(self: *ModuleInfo, writer: anytype) !void {
- try std.json.stringify(JsonStringifyableModuleInfo{
- .strings = @ptrCast(self.strings.keys()),
- .requested_modules_keys = self.requested_modules.keys(),
- .requested_modules_values = self.requested_modules.values(),
- .imports = self.imports.items,
- .exports = self.exports.items,
- .declared_variables = self.declared_variables.items,
- .lexical_variables = self.lexical_variables.items,
- .contains_import_meta = self.contains_import_meta,
- }, .{}, writer);
- }
- pub fn jsonParse(allocator: std.mem.Allocator, source: []const u8) !ModuleInfo {
- const parsed = try std.json.parseFromSlice(JsonStringifyableModuleInfo, allocator, source, .{ .allocate = .alloc_always });
- defer parsed.deinit();
- var result = init(allocator);
- for (parsed.value.strings) |string| if (try result.strings.fetchPut(try allocator.dupe(u8, string.value), {}) != null) return error.ParseError;
- for (parsed.value.requested_modules_keys, parsed.value.requested_modules_values) |reqk, reqv| if (try result.requested_modules.fetchPut(reqk, reqv) != null) return error.ParseError;
- try result.imports.appendSlice(parsed.value.imports);
- try result.exports.appendSlice(parsed.value.exports);
- try result.declared_variables.appendSlice(parsed.value.declared_variables);
- try result.lexical_variables.appendSlice(parsed.value.lexical_variables);
- result.contains_import_meta = parsed.value.contains_import_meta;
- return result;
- }
};
pub const StringID = enum(u32) {
_,
- pub fn jsonStringify(self: @This(), jw: anytype) !void {
- try jw.write(@intFromEnum(self));
- }
- pub fn jsonParse(alloc: std.mem.Allocator, source: anytype, options: anytype) !@This() {
- const token = try source.nextAllocMax(alloc, .alloc_if_needed, options.max_value_len.?);
- defer switch (token) {
- .allocated_number, .allocated_string => |slice| {
- alloc.free(slice);
- },
- else => {},
- };
- const slice = switch (token) {
- inline .number, .allocated_number, .string, .allocated_string => |slice| slice,
- else => return error.UnexpectedToken,
- };
- return @enumFromInt(try std.fmt.parseInt(u32, slice, 10));
- }
-};
-
-const ImportInfo = struct {
- kind: enum { single, namespace },
- /// eg "./a.ts" or "./q". must be in requested_modules.
- module_name: StringID,
- /// eg "a". if kind is namespace, this should be "*".
- import_name: StringID,
- /// the name of the local variable this will be bound to
- local_name: StringID,
-};
-
-const ExportInfo = union(enum) {
- indirect: struct {
- export_name: StringID,
- import_name: StringID,
- module_name: StringID,
- },
- local: struct {
- export_name: StringID,
- local_name: StringID,
- },
-
- /// not sure. `import * as mod; export {mod}` didn't do it. but it seems right?
- namespace: struct {
- export_name: StringID,
- module_name: StringID,
- },
- star: struct {
- module_name: StringID,
- },
};
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 {
@@ -240,49 +278,70 @@ export fn zig__ModuleInfo__parseFromSourceCode(
if (!std.mem.startsWith(u8, source[l1..l2], "\n// ")) return fail(failure_reason, 1);
if (!std.mem.eql(u8, source[l2..l3], "\n// ")) return fail(failure_reason, 1);
const json_part = source[l1 + "\n// ".len .. l2];
- var res = ModuleInfo.jsonParse(bun.default_allocator, json_part) catch return fail(failure_reason, 2);
- defer res.deinit();
- var identifiers = IdentifierArray.create(res.strings.keys().len);
+ const dec_res = bun.default_allocator.alloc(u8, std.base64.standard.Decoder.calcSizeForSlice(json_part) catch return fail(failure_reason, 2)) catch bun.outOfMemory();
+ defer bun.default_allocator.free(dec_res);
+ std.base64.standard.Decoder.decode(dec_res, json_part) catch return fail(failure_reason, 2);
+
+ const res = ModuleInfoDeserialized.parse(dec_res) catch return fail(failure_reason, 2);
+
+ var identifiers = IdentifierArray.create(res.strings_len);
defer identifiers.destroy();
- for (res.strings.keys(), 0..) |key, i| {
- if (bun.strings.eqlComptime(key, "*default*")) {
- identifiers.setFromStarDefault(i, vm);
- } else {
- identifiers.setFromUtf8(i, vm, key);
+ {
+ var strs_rem = res.strings;
+ var i: usize = 0;
+ while (std.mem.indexOfScalar(u8, strs_rem, 0)) |next_zero| : (i += 1) {
+ const sub = strs_rem[0..next_zero];
+ strs_rem = strs_rem[next_zero + 1 ..];
+ if (bun.strings.eqlComptime(sub, ModuleInfo.star_default)) {
+ identifiers.setFromStarDefault(i, vm);
+ } else {
+ identifiers.setFromUtf8(i, vm, sub);
+ }
}
}
- for (res.declared_variables.items) |id| declared_variables.add(identifiers, id);
- for (res.lexical_variables.items) |id| lexical_variables.add(identifiers, id);
+ {
+ var i: usize = 0;
+ for (res.record_kinds) |k| {
+ 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 fail(failure_reason, 2),
+ }
+ i += k.len() catch return fail(failure_reason, 2);
+ }
+ }
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| {
+ 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),
- .host_defined => |v| {
- const tmp_str = bun.default_allocator.dupeZ(u8, res.strings.keys()[@intFromEnum(v)]) catch return fail(failure_reason, 2);
- defer bun.default_allocator.free(tmp_str);
- if (std.mem.indexOfScalar(u8, tmp_str, 0) != null) return fail(failure_reason, 2);
- if (!bun.strings.isAllASCII(tmp_str)) return fail(failure_reason, 2);
- module_record.addRequestedModuleHostDefined(identifiers, reqk, tmp_str.ptr);
- },
+ else => |uv| module_record.addRequestedModuleHostDefined(identifiers, reqk, @enumFromInt(@intFromEnum(uv))),
+ }
+ }
+
+ {
+ var i: usize = 0;
+ for (res.record_kinds) |k| {
+ 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 + 1], res.buffer[i + 2], res.buffer[i]),
+ .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 => return fail(failure_reason, 2),
+ }
+ i += k.len() catch return fail(failure_reason, 2);
}
}
- for (res.imports.items) |import_info| switch (import_info.kind) {
- .single => module_record.addImportEntrySingle(identifiers, import_info.import_name, import_info.local_name, import_info.module_name),
- .namespace => module_record.addImportEntryNamespace(identifiers, import_info.import_name, import_info.local_name, import_info.module_name),
- };
- for (res.exports.items) |export_info| switch (export_info) {
- .indirect => module_record.addIndirectExport(identifiers, export_info.indirect.export_name, export_info.indirect.import_name, export_info.indirect.module_name),
- .local => module_record.addLocalExport(identifiers, export_info.local.export_name, export_info.local.local_name),
- .namespace => module_record.addNamespaceExport(identifiers, export_info.namespace.export_name, export_info.namespace.module_name),
- .star => module_record.addStarExport(identifiers, export_info.star.module_name),
- };
return module_record;
}
@@ -337,7 +396,7 @@ const JSModuleRecord = opaque {
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: [*:0]const u8) void;
+ 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;
diff --git a/src/bun.js/bindings/BunAnalyzeTranspiledModule.cpp b/src/bun.js/bindings/BunAnalyzeTranspiledModule.cpp
index ede7e5247d..41788deb83 100644
--- a/src/bun.js/bindings/BunAnalyzeTranspiledModule.cpp
+++ b/src/bun.js/bindings/BunAnalyzeTranspiledModule.cpp
@@ -149,9 +149,9 @@ extern "C" void JSC_JSModuleRecord__addRequestedModuleJSON(JSModuleRecord* modul
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, const char* hostDefinedImportType)
+extern "C" void JSC_JSModuleRecord__addRequestedModuleHostDefined(JSModuleRecord* moduleRecord, Identifier* identifierArray, uint32_t moduleName, uint32_t hostDefinedImportType)
{
- Ref attributes = ScriptFetchParameters::create(makeString(ASCIILiteral::fromLiteralUnsafe(hostDefinedImportType)));
+ Ref attributes = ScriptFetchParameters::create(identifierArray[hostDefinedImportType].string());
moduleRecord->appendRequestedModule(identifierArray[moduleName], WTFMove(attributes));
}
diff --git a/src/js_printer.zig b/src/js_printer.zig
index fab18bbf0d..d02646e952 100644
--- a/src/js_printer.zig
+++ b/src/js_printer.zig
@@ -3525,7 +3525,7 @@ fn NewPrinter(
if (p.moduleInfo()) |mi| {
if (tlm.is_top_level) |vk| mi.addVar(local_name, vk) catch bun.outOfMemory();
- if (tlm.is_export) mi.exports.append(.{ .local = .{ .export_name = mi.str(local_name) catch bun.outOfMemory(), .local_name = mi.str(local_name) catch bun.outOfMemory() } }) catch bun.outOfMemory();
+ if (tlm.is_export) mi.addExportInfoLocal(local_name, local_name) catch bun.outOfMemory();
}
},
.b_array => |b| {
@@ -3627,7 +3627,7 @@ fn NewPrinter(
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.exports.append(.{ .local = .{ .export_name = mi.str(str.data) catch bun.outOfMemory(), .local_name = mi.str(str.data) catch bun.outOfMemory() } }) catch bun.outOfMemory();
+ if (tlm.is_export) mi.addExportInfoLocal(str.data, str.data) catch bun.outOfMemory();
}
p.maybePrintDefaultBindingValue(property);
continue;
@@ -3649,7 +3649,7 @@ fn NewPrinter(
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.exports.append(.{ .local = .{ .export_name = mi.str(str8) catch bun.outOfMemory(), .local_name = mi.str(str8) catch bun.outOfMemory() } }) catch bun.outOfMemory();
+ if (tlm.is_export) mi.addExportInfoLocal(str8, str8) catch bun.outOfMemory();
}
p.maybePrintDefaultBindingValue(property);
continue;
@@ -3736,7 +3736,7 @@ fn NewPrinter(
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.exports.append(.{ .local = .{ .export_name = try mi.str(local_name), .local_name = try mi.str(local_name) } });
+ 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)) {
@@ -3778,7 +3778,7 @@ fn NewPrinter(
p.printClass(s.class);
if (p.moduleInfo()) |mi| {
- if (s.is_export) try mi.exports.append(.{ .local = .{ .export_name = try mi.str(nameStr), .local_name = try mi.str(nameStr) } });
+ if (s.is_export) try mi.addExportInfoLocal(nameStr, nameStr);
if (tlmtlo.is_top_level == .yes) try mi.addVar(nameStr, .lexical);
}
@@ -3816,8 +3816,8 @@ fn NewPrinter(
p.printExpr(expr, .comma, ExprFlag.None());
p.printSemicolonAfterStatement();
if (p.moduleInfo()) |mi| {
- try mi.exports.append(.{ .local = .{ .export_name = try mi.str("default"), .local_name = try mi.starDefault() } });
- try mi.addVarStrID(try mi.starDefault(), .lexical);
+ try mi.addExportInfoLocal("default", ModuleInfo.star_default);
+ try mi.addVar(ModuleInfo.star_default, .lexical);
}
return;
},
@@ -3847,9 +3847,9 @@ fn NewPrinter(
p.printNewline();
if (p.moduleInfo()) |mi| {
- const local_name = if (func_name) |f| try mi.str(f) else try mi.starDefault();
- try mi.exports.append(.{ .local = .{ .export_name = try mi.str("default"), .local_name = local_name } });
- try mi.addVarStrID(local_name, .lexical);
+ const local_name = func_name orelse ModuleInfo.star_default;
+ try mi.addExportInfoLocal("default", local_name);
+ try mi.addVar(local_name, .lexical);
}
},
.s_class => |class| {
@@ -3868,9 +3868,9 @@ fn NewPrinter(
p.printNewline();
if (p.moduleInfo()) |mi| {
- const local_name = if (class_name) |f| try mi.str(f) else try mi.starDefault();
- try mi.exports.append(.{ .local = .{ .export_name = try mi.str("default"), .local_name = local_name } });
- try mi.addVarStrID(local_name, .lexical);
+ const local_name = class_name orelse ModuleInfo.star_default;
+ try mi.addExportInfoLocal("default", local_name);
+ try mi.addVar(local_name, .lexical);
}
},
else => {
@@ -3905,9 +3905,9 @@ fn NewPrinter(
if (p.moduleInfo()) |mi| {
try mi.requestModule(irp, .none);
if (s.alias) |alias| {
- try mi.exports.append(.{ .namespace = .{ .module_name = try mi.str(irp), .export_name = try mi.str(alias.original_name) } });
+ try mi.addExportInfoNamespace(irp, alias.original_name);
} else {
- try mi.exports.append(.{ .star = .{ .module_name = try mi.str(irp) } });
+ try mi.addExportInfoStar(irp);
}
}
},
@@ -4061,7 +4061,7 @@ fn NewPrinter(
p.printExportClauseItem(item);
if (p.moduleInfo()) |mi| {
- try mi.exports.append(.{ .local = .{ .export_name = try mi.str(item.alias), .local_name = try mi.str(name) } });
+ try mi.addExportInfoLocal(item.alias, name);
}
}
@@ -4123,7 +4123,7 @@ fn NewPrinter(
for (s.items) |item| {
// how could this be renamed, it's in `export from`?
const name = p.renamer.nameForSymbol(item.name.ref.?);
- try mi.exports.append(.{ .indirect = .{ .export_name = try mi.str(item.alias), .import_name = try mi.str(name), .module_name = try mi.str(irp) } });
+ try mi.addExportInfoIndirect(item.alias, name, irp);
}
}
},
@@ -4518,12 +4518,7 @@ fn NewPrinter(
if (p.moduleInfo()) |mi| {
try mi.addVar(local_name, .lexical);
- try mi.imports.append(.{
- .kind = .single,
- .module_name = try mi.str(import_record_path),
- .import_name = try mi.str("default"),
- .local_name = try mi.str(local_name),
- });
+ try mi.addImportInfoSingle(import_record_path, "default", local_name);
}
}
@@ -4565,12 +4560,7 @@ fn NewPrinter(
if (p.moduleInfo()) |mi| {
try mi.addVar(local_name, .lexical);
- try mi.imports.append(.{
- .kind = .single,
- .module_name = try mi.str(import_record_path),
- .import_name = try mi.str(item.alias),
- .local_name = try mi.str(local_name),
- });
+ try mi.addImportInfoSingle(import_record_path, item.alias, local_name);
}
}
@@ -4600,12 +4590,7 @@ fn NewPrinter(
if (p.moduleInfo()) |mi| {
try mi.addVar(local_name, .lexical);
- try mi.imports.append(.{
- .kind = .namespace,
- .module_name = try mi.str(import_record_path),
- .import_name = try mi.str("*"),
- .local_name = try mi.str(local_name),
- });
+ try mi.addImportInfoNamespace(import_record_path, local_name);
}
}
@@ -4625,12 +4610,12 @@ fn NewPrinter(
.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 = .{ .host_defined = try mi.str("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 = .{ .host_defined = try mi.str("text") };
+ if (p.moduleInfo()) |mi| fetch_parameters = ModuleInfo.FetchParameters.hostDefined(try mi.str("text"));
}
},
.with_type_json => {
@@ -4644,14 +4629,14 @@ fn NewPrinter(
// backwards compatibility: previously, we always stripped type
if (comptime is_bun_platform) {
p.printWhitespacer(ws(" with { type: \"toml\" }"));
- if (p.moduleInfo()) |mi| fetch_parameters = .{ .host_defined = try mi.str("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 = .{ .host_defined = try mi.str("file") };
+ if (p.moduleInfo()) |mi| fetch_parameters = ModuleInfo.FetchParameters.hostDefined(try mi.str("file"));
}
},
else => {},
@@ -5980,9 +5965,7 @@ pub fn printAst(
if (PrinterType.may_have_module_info) {
try mi.fixupIndirectExports();
- printer.print("\n// \n// ");
- try mi.jsonStringify(printer.writer.stdWriter());
- printer.print("\n// \n");
+ try mi.serialize(printer.writer.stdWriter());
}
try printer.writer.done();