aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-02-15 20:08:35 -0800
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-02-15 20:08:35 -0800
commit08e8eabc6f1fdf5a58da0196462cba38b87c18d8 (patch)
tree2bedf1ba9dd8b2ceb34babcf0ef26c8ad2da6609
parent665a3594130d4b48aa009b0a0b38ec742fa921d7 (diff)
downloadbun-08e8eabc6f1fdf5a58da0196462cba38b87c18d8.tar.gz
bun-08e8eabc6f1fdf5a58da0196462cba38b87c18d8.tar.zst
bun-08e8eabc6f1fdf5a58da0196462cba38b87c18d8.zip
Revert "Remove usage of `packed` struct in Ref because packed is buggy in zig"
This reverts commit 2578f426b6d59080b0853164df83fe2b69740a7c.
-rw-r--r--src/ast/base.zig208
-rw-r--r--src/bundler.zig33
-rw-r--r--src/js_ast.zig8
-rw-r--r--src/js_parser/js_parser.zig463
-rw-r--r--src/js_printer.zig2
-rw-r--r--src/renamer.zig4
6 files changed, 284 insertions, 434 deletions
diff --git a/src/ast/base.zig b/src/ast/base.zig
index c283fee8c..ad0d34efd 100644
--- a/src/ast/base.zig
+++ b/src/ast/base.zig
@@ -43,174 +43,28 @@ pub const RefCtx = struct {
}
};
-/// Sets the range of bits starting at `start_bit` upto and excluding `start_bit` + `number_of_bits`
-/// to be specific, if the range is N bits long, the N lower bits of `value` will be used; if any of
-/// the other bits in `value` are set to 1, this function will panic.
-///
-/// ```zig
-/// var val: u8 = 0b10000000;
-/// setBits(&val, 2, 4, 0b00001101);
-/// try testing.expectEqual(@as(u8, 0b10110100), val);
-/// ```
-///
-/// ## Panics
-/// This method will panic if the `value` exceeds the bit range of the type of `target`
-pub fn setBits(
- comptime TargetType: type,
- target: TargetType,
- comptime start_bit: comptime_int,
- comptime number_of_bits: comptime_int,
- value: TargetType,
-) TargetType {
- const end_bit = start_bit + number_of_bits;
-
- comptime {
- if (number_of_bits == 0) @compileError("non-zero number_of_bits must be provided");
-
- if (@typeInfo(TargetType) == .Int) {
- if (@typeInfo(TargetType).Int.signedness != .unsigned) {
- @compileError("requires an unsigned integer, found " ++ @typeName(TargetType));
- }
- if (start_bit >= @bitSizeOf(TargetType)) {
- @compileError("start_bit index is out of bounds of the bit field");
- }
- if (end_bit > @bitSizeOf(TargetType)) {
- @compileError("start_bit + number_of_bits is out of bounds of the bit field");
- }
- } else if (@typeInfo(TargetType) == .ComptimeInt) {
- @compileError("comptime_int is unsupported");
- } else {
- @compileError("requires an unsigned integer, found " ++ @typeName(TargetType));
- }
- }
-
- if (comptime std.debug.runtime_safety) {
- if (getBits(TargetType, value, 0, (end_bit - start_bit)) != value) @panic("value exceeds bit range");
- }
-
- const bitmask: TargetType = comptime blk: {
- var bitmask = ~@as(TargetType, 0);
- bitmask <<= (@bitSizeOf(TargetType) - end_bit);
- bitmask >>= (@bitSizeOf(TargetType) - end_bit);
- bitmask >>= start_bit;
- bitmask <<= start_bit;
- break :blk ~bitmask;
- };
-
- return (target & bitmask) | (value << start_bit);
-}
-
-pub fn getBits(comptime TargetType: type, target: anytype, comptime start_bit: comptime_int, comptime number_of_bits: comptime_int) TargetType {
- comptime {
- if (number_of_bits == 0) @compileError("non-zero number_of_bits must be provided");
-
- if (@typeInfo(TargetType) == .Int) {
- if (@typeInfo(TargetType).Int.signedness != .unsigned) {
- @compileError("requires an unsigned integer, found " ++ @typeName(TargetType));
- }
- if (start_bit >= @bitSizeOf(TargetType)) {
- @compileError("start_bit index is out of bounds of the bit field");
- }
- if (start_bit + number_of_bits > @bitSizeOf(TargetType)) {
- @compileError("start_bit + number_of_bits is out of bounds of the bit field");
- }
- } else if (@typeInfo(TargetType) == .ComptimeInt) {
- if (target < 0) {
- @compileError("requires an unsigned integer, found " ++ @typeName(TargetType));
- }
- } else {
- @compileError("requires an unsigned integer, found " ++ @typeName(TargetType));
- }
- }
-
- return @truncate(TargetType, target >> start_bit);
-}
-
-pub const Ref = enum(TotalSize) {
- default = std.math.maxInt(TotalSize),
- _,
-
- pub const TotalSize = u62;
-
- pub fn format(ref: Ref, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
- try std.fmt.format(
- writer,
- "Ref: sourceIndex = {d}, innerIndex = {d}, is_source_contents_slice = {}",
- .{
- ref.sourceIndex(),
- ref.innerIndex(),
- ref.isSourceContentsSlice(),
- },
- );
- }
-
+pub const Ref = packed struct {
const max_ref_int = std.math.maxInt(Ref.Int);
pub const BitInt = std.meta.Int(.unsigned, @bitSizeOf(Ref));
+ source_index: Int = max_ref_int,
+ inner_index: Int = 0,
+ is_source_contents_slice: bool = false,
+
pub inline fn asBitInt(this: Ref) BitInt {
return @bitCast(BitInt, this);
}
// 2 bits of padding for whatever is the parent
pub const Int = u30;
- pub const None = Ref.init(std.math.maxInt(u30), std.math.maxInt(u30), false);
- pub const RuntimeRef = Ref.init(std.math.maxInt(u30), std.math.maxInt(u30) - 1, false);
-
- const source_index_offset = 1;
- const inner_index_offset = 1 + 30;
-
- pub inline fn sourceIndex(this: Ref) Int {
- return @truncate(Int, getBits(TotalSize, @enumToInt(this), source_index_offset, 30));
- }
-
- pub inline fn innerIndex(this: Ref) Int {
- return @truncate(Int, getBits(TotalSize, @enumToInt(this), inner_index_offset, 30));
- }
-
- pub inline fn isSourceContentsSlice(this: Ref) bool {
- return (getBits(TotalSize, @enumToInt(this), 0, 1) & 1) != 0;
- }
-
- pub fn atIndex(value: anytype) Ref {
- return @intToEnum(Ref, setBits(TotalSize, 0, inner_index_offset, 30, @truncate(Int, value)));
- }
-
- pub fn init(inner_index: Int, source_index: Int, is_source_contents_slice: bool) Ref {
- return @intToEnum(
- Ref,
- setBits(
- TotalSize,
- 0,
- 0,
- 1,
- @as(
- TotalSize,
- @boolToInt(is_source_contents_slice),
- ),
- ) | setBits(
- TotalSize,
- 0,
- source_index_offset,
- 30,
- source_index,
- ) | setBits(
- TotalSize,
- 0,
- inner_index_offset,
- 30,
- inner_index,
- ),
- );
- }
-
- const Old = struct {
- inner_index: Int = 0,
- source_index: Int = std.math.maxInt(Int),
- is_source_contents_slice: bool = false,
+ pub const None = Ref{
+ .inner_index = max_ref_int,
+ .source_index = max_ref_int,
+ };
+ pub const RuntimeRef = Ref{
+ .inner_index = max_ref_int,
+ .source_index = max_ref_int - 1,
};
- pub fn initSourceEnd(old: Old) Ref {
- return init(old.inner_index, old.source_index, old.is_source_contents_slice);
- }
pub fn toInt(int: anytype) Int {
return @intCast(Int, int);
@@ -227,7 +81,7 @@ pub const Ref = enum(TotalSize) {
// but we want to ensure that the value of the unused bits in the u64 are 0
// i have not looked at the assembly to verify that the unused bits default to 0
// so we set it to u64 0 just to be sure
- return @as(u64, @enumToInt(key));
+ return @as(u64, 0) | @as(u64, key.asBitInt());
}
pub inline fn hash64(key: Ref) u64 {
@@ -246,44 +100,10 @@ pub const Ref = enum(TotalSize) {
}
pub fn jsonStringify(self: *const Ref, options: anytype, writer: anytype) !void {
- return try std.json.stringify([2]u32{ self.sourceIndex(), self.innerIndex() }, options, writer);
+ return try std.json.stringify([2]u32{ self.source_index, self.inner_index }, options, writer);
}
};
-test "Ref" {
- {
- const first = .{ .inner_index = 0, .source_index = 1, .is_source_contents_slice = true };
- const ref = Ref.initSourceEnd(.{ .inner_index = 0, .source_index = 1, .is_source_contents_slice = true });
- try std.testing.expectEqual(ref.innerIndex(), first.inner_index);
- try std.testing.expectEqual(ref.sourceIndex(), first.source_index);
- try std.testing.expectEqual(ref.isSourceContentsSlice(), first.is_source_contents_slice);
- }
-
- {
- const first = .{ .inner_index = 100, .source_index = 0, .is_source_contents_slice = true };
- const ref = Ref.initSourceEnd(.{ .inner_index = 100, .source_index = 0, .is_source_contents_slice = true });
- try std.testing.expectEqual(ref.innerIndex(), first.inner_index);
- try std.testing.expectEqual(ref.sourceIndex(), first.source_index);
- try std.testing.expectEqual(ref.isSourceContentsSlice(), first.is_source_contents_slice);
- }
-
- {
- const first = .{ .inner_index = 20, .source_index = 100, .is_source_contents_slice = true };
- const ref = Ref.initSourceEnd(.{ .inner_index = 20, .source_index = 100, .is_source_contents_slice = true });
- try std.testing.expectEqual(ref.innerIndex(), first.inner_index);
- try std.testing.expectEqual(ref.sourceIndex(), first.source_index);
- try std.testing.expectEqual(ref.isSourceContentsSlice(), first.is_source_contents_slice);
- }
-
- {
- const first = .{ .inner_index = 30, .source_index = 100, .is_source_contents_slice = false };
- const ref = Ref.initSourceEnd(.{ .inner_index = 30, .source_index = 100, .is_source_contents_slice = false });
- try std.testing.expectEqual(ref.innerIndex(), first.inner_index);
- try std.testing.expectEqual(ref.sourceIndex(), first.source_index);
- try std.testing.expectEqual(ref.isSourceContentsSlice(), first.is_source_contents_slice);
- }
-}
-
// This is kind of the wrong place, but it's shared between files
pub const RequireOrImportMeta = struct {
// CommonJS files will return the "require_*" wrapper function and an invalid
diff --git a/src/bundler.zig b/src/bundler.zig
index 79068ffff..19102fd98 100644
--- a/src/bundler.zig
+++ b/src/bundler.zig
@@ -1796,7 +1796,7 @@ pub const Bundler = struct {
json_e_string = js_ast.E.String{ .utf8 = source.contents, .prefer_template = true };
var json_string_expr = js_ast.Expr{ .data = .{ .e_string = &json_e_string }, .loc = logger.Loc{ .start = 0 } };
json_call_args[0] = json_string_expr;
- json_e_identifier = js_ast.E.Identifier{ .ref = Ref.atIndex(json_ast_symbols_list.len - 1) };
+ json_e_identifier = js_ast.E.Identifier{ .ref = Ref{ .source_index = 0, .inner_index = @intCast(Ref.Int, json_ast_symbols_list.len - 1) } };
json_e_call = js_ast.E.Call{
.target = js_ast.Expr{ .data = .{ .e_identifier = json_e_identifier }, .loc = logger.Loc{ .start = 0 } },
@@ -1811,10 +1811,7 @@ pub const Bundler = struct {
var stmt = js_ast.Stmt.alloc(js_ast.S.ExportDefault, js_ast.S.ExportDefault{
.value = js_ast.StmtOrExpr{ .expr = expr },
- .default_name = js_ast.LocRef{
- .loc = logger.Loc{},
- .ref = Ref.None,
- },
+ .default_name = js_ast.LocRef{ .loc = logger.Loc{}, .ref = Ref{} },
}, logger.Loc{ .start = 0 });
var stmts = worker.allocator.alloc(js_ast.Stmt, 1) catch unreachable;
stmts[0] = stmt;
@@ -1823,12 +1820,12 @@ pub const Bundler = struct {
ast = js_ast.Ast.initTest(parts);
ast.runtime_imports = runtime.Runtime.Imports{};
- ast.runtime_imports.@"$$m" = .{ .ref = Ref.atIndex(0), .primary = Ref.None, .backup = Ref.None };
- ast.runtime_imports.__export = .{ .ref = Ref.atIndex(1), .primary = Ref.None, .backup = Ref.None };
+ ast.runtime_imports.@"$$m" = .{ .ref = Ref{ .source_index = 0, .inner_index = 0 }, .primary = Ref.None, .backup = Ref.None };
+ ast.runtime_imports.__export = .{ .ref = Ref{ .source_index = 0, .inner_index = 1 }, .primary = Ref.None, .backup = Ref.None };
ast.symbols = json_ast_symbols_list;
- ast.module_ref = Ref.atIndex(2);
+ ast.module_ref = Ref{ .source_index = 0, .inner_index = 2 };
ast.exports_ref = ast.runtime_imports.__export.?.ref;
- ast.bundle_export_ref = Ref.atIndex(3);
+ ast.bundle_export_ref = Ref{ .source_index = 0, .inner_index = 3 };
} else {
var parts = &[_]js_ast.Part{};
ast = js_ast.Ast.initTest(parts);
@@ -1907,7 +1904,7 @@ pub const Bundler = struct {
};
// if (!ast.uses_module_ref) {
- // var symbol = &ast.symbols[ast.module_ref.?.innerIndex()];
+ // var symbol = &ast.symbols[ast.module_ref.?.inner_index];
// symbol.original_name = "_$$";
// }
@@ -2778,10 +2775,7 @@ pub const Bundler = struct {
var expr = json_parser.ParseJSON(&source, bundler.log, allocator) catch return null;
var stmt = js_ast.Stmt.alloc(js_ast.S.ExportDefault, js_ast.S.ExportDefault{
.value = js_ast.StmtOrExpr{ .expr = expr },
- .default_name = js_ast.LocRef{
- .loc = logger.Loc{},
- .ref = Ref.None,
- },
+ .default_name = js_ast.LocRef{ .loc = logger.Loc{}, .ref = Ref{} },
}, logger.Loc{ .start = 0 });
var stmts = allocator.alloc(js_ast.Stmt, 1) catch unreachable;
stmts[0] = stmt;
@@ -2799,10 +2793,7 @@ pub const Bundler = struct {
var expr = TOML.parse(&source, bundler.log, allocator) catch return null;
var stmt = js_ast.Stmt.alloc(js_ast.S.ExportDefault, js_ast.S.ExportDefault{
.value = js_ast.StmtOrExpr{ .expr = expr },
- .default_name = js_ast.LocRef{
- .loc = logger.Loc{},
- .ref = Ref.None,
- },
+ .default_name = js_ast.LocRef{ .loc = logger.Loc{}, .ref = Ref{} },
}, logger.Loc{ .start = 0 });
var stmts = allocator.alloc(js_ast.Stmt, 1) catch unreachable;
stmts[0] = stmt;
@@ -3417,9 +3408,7 @@ pub const Transformer = struct {
var expr = try json_parser.ParseJSON(source, log, allocator);
var stmt = js_ast.Stmt.alloc(js_ast.S.ExportDefault{
.value = js_ast.StmtOrExpr{ .expr = expr },
- .default_name = js_ast.LocRef{
- .loc = logger.Loc{},
- },
+ .default_name = js_ast.LocRef{ .loc = logger.Loc{}, .ref = Ref{} },
}, logger.Loc{ .start = 0 });
var stmts = try allocator.alloc(js_ast.Stmt, 1);
stmts[0] = stmt;
@@ -3453,7 +3442,7 @@ pub const Transformer = struct {
source,
false,
js_printer.Options{
- .to_module_ref = ast.module_ref orelse js_ast.Ref.None,
+ .to_module_ref = ast.module_ref orelse js_ast.Ref{ .inner_index = 0 },
.transform_imports = false,
.runtime_imports = ast.runtime_imports,
},
diff --git a/src/js_ast.zig b/src/js_ast.zig
index de4bf194a..2f7ea1fc2 100644
--- a/src/js_ast.zig
+++ b/src/js_ast.zig
@@ -327,7 +327,7 @@ pub const AssignTarget = enum(u2) {
}
};
-pub const LocRef = struct { loc: logger.Loc, ref: ?Ref = null };
+pub const LocRef = struct { loc: logger.Loc, ref: ?Ref };
pub const Flags = struct {
pub const JSXElement = struct {
@@ -888,11 +888,11 @@ pub const Symbol = struct {
symbols_for_source: [][]Symbol,
pub fn get(self: *Map, ref: Ref) ?*Symbol {
- if (Ref.isSourceIndexNull(ref.sourceIndex()) or ref.isSourceContentsSlice()) {
+ if (Ref.isSourceIndexNull(ref.source_index) or ref.is_source_contents_slice) {
return null;
}
- return &self.symbols_for_source[ref.sourceIndex()][ref.innerIndex()];
+ return &self.symbols_for_source[ref.source_index][ref.inner_index];
}
pub fn init(sourceCount: usize, allocator: std.mem.Allocator) !Map {
@@ -7907,7 +7907,7 @@ pub const Macro = struct {
// test "Binding.init" {
// var binding = Binding.alloc(
// std.heap.page_allocator,
-// B.Identifier{ .ref = Ref{ .source_index = 0, .innerIndex() = 10 } },
+// B.Identifier{ .ref = Ref{ .source_index = 0, .inner_index = 10 } },
// logger.Loc{ .start = 1 },
// );
// std.testing.expect(binding.loc.start == 1);
diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig
index 552d26110..26acadac3 100644
--- a/src/js_parser/js_parser.zig
+++ b/src/js_parser/js_parser.zig
@@ -399,10 +399,10 @@ pub const ImportScanner = struct {
if (st.default_name) |default_name| {
found_imports = true;
- const symbol = p.symbols.items[default_name.ref.?.innerIndex()];
+ const symbol = p.symbols.items[default_name.ref.?.inner_index];
// TypeScript has a separate definition of unused
- if (p.options.ts and p.ts_use_counts.items[default_name.ref.?.innerIndex()] != 0) {
+ if (p.options.ts and p.ts_use_counts.items[default_name.ref.?.inner_index] != 0) {
is_unused_in_typescript = false;
}
@@ -415,10 +415,10 @@ pub const ImportScanner = struct {
// Remove the star import if it's unused
if (st.star_name_loc) |_| {
found_imports = true;
- const symbol = p.symbols.items[st.namespace_ref.innerIndex()];
+ const symbol = p.symbols.items[st.namespace_ref.inner_index];
// TypeScript has a separate definition of unused
- if (p.options.ts and p.ts_use_counts.items[st.namespace_ref.innerIndex()] != 0) {
+ if (p.options.ts and p.ts_use_counts.items[st.namespace_ref.inner_index] != 0) {
is_unused_in_typescript = false;
}
@@ -449,10 +449,10 @@ pub const ImportScanner = struct {
while (i < st.items.len) : (i += 1) {
const item = st.items[i];
const ref = item.name.ref.?;
- const symbol: Symbol = p.symbols.items[ref.innerIndex()];
+ const symbol: Symbol = p.symbols.items[ref.inner_index];
// TypeScript has a separate definition of unused
- if (p.options.ts and p.ts_use_counts.items[ref.innerIndex()] != 0) {
+ if (p.options.ts and p.ts_use_counts.items[ref.inner_index] != 0) {
is_unused_in_typescript = false;
}
@@ -500,7 +500,7 @@ pub const ImportScanner = struct {
}
const namespace_ref = st.namespace_ref;
- const convert_star_to_clause = !p.options.enable_bundling and !p.options.can_import_from_bundle and p.symbols.items[namespace_ref.innerIndex()].use_count_estimate == 0;
+ const convert_star_to_clause = !p.options.enable_bundling and !p.options.can_import_from_bundle and p.symbols.items[namespace_ref.inner_index].use_count_estimate == 0;
if (convert_star_to_clause and !keep_unused_imports) {
st.star_name_loc = null;
@@ -532,7 +532,7 @@ pub const ImportScanner = struct {
});
// Make sure the printer prints this as a property access
- var symbol: *Symbol = &p.symbols.items[name_ref.innerIndex()];
+ var symbol: *Symbol = &p.symbols.items[name_ref.inner_index];
symbol.namespace_alias = G.NamespaceAlias{
.namespace_ref = namespace_ref,
@@ -549,7 +549,7 @@ pub const ImportScanner = struct {
}
if (record.was_originally_require) {
- var symbol = &p.symbols.items[namespace_ref.innerIndex()];
+ var symbol = &p.symbols.items[namespace_ref.inner_index];
symbol.namespace_alias = G.NamespaceAlias{
.namespace_ref = namespace_ref,
.alias = "",
@@ -562,7 +562,7 @@ pub const ImportScanner = struct {
.s_function => |st| {
if (st.func.flags.is_export) {
if (st.func.name) |name| {
- const original_name = p.symbols.items[name.ref.?.innerIndex()].original_name;
+ const original_name = p.symbols.items[name.ref.?.inner_index].original_name;
try p.recordExport(name.loc, original_name, name.ref.?);
if (p.options.features.hot_module_reloading) {
@@ -576,7 +576,7 @@ pub const ImportScanner = struct {
.s_class => |st| {
if (st.is_export) {
if (st.class.class_name) |name| {
- try p.recordExport(name.loc, p.symbols.items[name.ref.?.innerIndex()].original_name, name.ref.?);
+ try p.recordExport(name.loc, p.symbols.items[name.ref.?.inner_index].original_name, name.ref.?);
if (p.options.features.hot_module_reloading) {
st.is_export = false;
@@ -614,7 +614,7 @@ pub const ImportScanner = struct {
if (value) |val| {
if (@as(Expr.Tag, val.data) == .e_identifier) {
// Is this import statement unused?
- if (@as(Binding.Tag, decl.binding.data) == .b_identifier and p.symbols.items[decl.binding.data.b_identifier.ref.innerIndex()].use_count_estimate == 0) {
+ if (@as(Binding.Tag, decl.binding.data) == .b_identifier and p.symbols.items[decl.binding.data.b_identifier.ref.inner_index].use_count_estimate == 0) {
p.ignoreUsage(val.data.e_identifier.ref);
scanner.removed_import_equals = true;
@@ -960,7 +960,7 @@ pub const SideEffects = enum(u1) {
return expr;
}
- if (ident.can_be_removed_if_unused or p.symbols.items[ident.ref.innerIndex()].kind != .unbound) {
+ if (ident.can_be_removed_if_unused or p.symbols.items[ident.ref.inner_index].kind != .unbound) {
return null;
}
},
@@ -2189,8 +2189,8 @@ pub const Parser = struct {
// Analyze cross-part dependencies for tree shaking and code splitting
var exports_kind = js_ast.ExportsKind.none;
- const uses_exports_ref = p.symbols.items[p.exports_ref.innerIndex()].use_count_estimate > 0;
- const uses_module_ref = p.symbols.items[p.module_ref.innerIndex()].use_count_estimate > 0;
+ const uses_exports_ref = p.symbols.items[p.exports_ref.inner_index].use_count_estimate > 0;
+ const uses_module_ref = p.symbols.items[p.module_ref.inner_index].use_count_estimate > 0;
var wrapper_expr: ?Expr = null;
@@ -2225,13 +2225,13 @@ pub const Parser = struct {
// Auto-import JSX
if (ParserType.jsx_transform_type == .react) {
- const jsx_filename_symbol = p.symbols.items[p.jsx_filename.ref.innerIndex()];
+ const jsx_filename_symbol = p.symbols.items[p.jsx_filename.ref.inner_index];
{
- const jsx_symbol = p.symbols.items[p.jsx_runtime.ref.innerIndex()];
- const jsx_static_symbol = p.symbols.items[p.jsxs_runtime.ref.innerIndex()];
- const jsx_fragment_symbol = p.symbols.items[p.jsx_fragment.ref.innerIndex()];
- const jsx_factory_symbol = p.symbols.items[p.jsx_factory.ref.innerIndex()];
+ const jsx_symbol = p.symbols.items[p.jsx_runtime.ref.inner_index];
+ const jsx_static_symbol = p.symbols.items[p.jsxs_runtime.ref.inner_index];
+ const jsx_fragment_symbol = p.symbols.items[p.jsx_fragment.ref.inner_index];
+ const jsx_factory_symbol = p.symbols.items[p.jsx_factory.ref.inner_index];
// Currently, React (and most node_modules) ship a CJS version or a UMD version
// but we should assume that it'll pretty much always be CJS
@@ -2256,8 +2256,8 @@ pub const Parser = struct {
p.resolveStaticJSXSymbols();
- const jsx_classic_symbol = p.symbols.items[p.jsx_classic.ref.innerIndex()];
- const jsx_automatic_symbol = p.symbols.items[p.jsx_automatic.ref.innerIndex()];
+ const jsx_classic_symbol = p.symbols.items[p.jsx_classic.ref.inner_index];
+ const jsx_automatic_symbol = p.symbols.items[p.jsx_automatic.ref.inner_index];
// JSX auto-imports
// The classic runtime is a different import than the main import
@@ -2269,10 +2269,10 @@ pub const Parser = struct {
// These must unfortunately be copied
// p.symbols may grow during this scope
// if it grows, the previous pointers are invalidated
- const jsx_symbol = p.symbols.items[p.jsx_runtime.ref.innerIndex()];
- const jsx_static_symbol = p.symbols.items[p.jsxs_runtime.ref.innerIndex()];
- const jsx_fragment_symbol = p.symbols.items[p.jsx_fragment.ref.innerIndex()];
- const jsx_factory_symbol = p.symbols.items[p.jsx_factory.ref.innerIndex()];
+ const jsx_symbol = p.symbols.items[p.jsx_runtime.ref.inner_index];
+ const jsx_static_symbol = p.symbols.items[p.jsxs_runtime.ref.inner_index];
+ const jsx_fragment_symbol = p.symbols.items[p.jsx_fragment.ref.inner_index];
+ const jsx_factory_symbol = p.symbols.items[p.jsx_factory.ref.inner_index];
const classic_namespace_ref = p.jsx_classic.ref;
const automatic_namespace_ref = p.jsx_automatic.ref;
@@ -2507,7 +2507,7 @@ pub const Parser = struct {
defer did_import_fast_refresh = true;
p.resolveGeneratedSymbol(&p.jsx_refresh_runtime);
if (!p.options.jsx.use_embedded_refresh_runtime) {
- const refresh_runtime_symbol: *const Symbol = &p.symbols.items[p.jsx_refresh_runtime.ref.innerIndex()];
+ const refresh_runtime_symbol: *const Symbol = &p.symbols.items[p.jsx_refresh_runtime.ref.inner_index];
declared_symbols[declared_symbols_i] = .{ .ref = p.jsx_refresh_runtime.ref, .is_top_level = true };
declared_symbols_i += 1;
@@ -2569,7 +2569,7 @@ pub const Parser = struct {
.import_record_index = import_record_id,
}, loc);
- const refresh_runtime_symbol: *const Symbol = &p.symbols.items[p.jsx_refresh_runtime.ref.innerIndex()];
+ const refresh_runtime_symbol: *const Symbol = &p.symbols.items[p.jsx_refresh_runtime.ref.inner_index];
p.named_imports.put(
p.jsx_refresh_runtime.ref,
@@ -2604,7 +2604,7 @@ pub const Parser = struct {
if (FeatureFlags.auto_import_buffer) {
// If they use Buffer...just automatically import it.
// ✨ magic ✨ (i don't like this)
- // if (p.symbols.items[p.buffer_ref.innerIndex()].use_count_estimate > 0) {
+ // if (p.symbols.items[p.buffer_ref.inner_index].use_count_estimate > 0) {
// var named_import = p.named_imports.getOrPut(p.buffer_ref);
// // if Buffer is actually an import, let them use that one instead.
@@ -3238,7 +3238,7 @@ pub fn NewParser(
return p.e(E.Import{
.expr = arg,
- .import_record_index = Ref.None.sourceIndex(),
+ .import_record_index = Ref.None.source_index,
}, state.loc);
}
@@ -3470,7 +3470,7 @@ pub fn NewParser(
// property on the target object of the "with" statement. We must not rename
// it or we risk changing the behavior of the code.
if (is_inside_with_scope) {
- p.symbols.items[ref.innerIndex()].must_not_be_renamed = true;
+ p.symbols.items[ref.inner_index].must_not_be_renamed = true;
}
// Track how many times we've referenced this symbol
@@ -3487,7 +3487,7 @@ pub fn NewParser(
switch (binding.data) {
.b_missing => {},
.b_identifier => |ident| {
- p.recordExport(binding.loc, p.symbols.items[ident.ref.innerIndex()].original_name, ident.ref) catch unreachable;
+ p.recordExport(binding.loc, p.symbols.items[ident.ref.inner_index].original_name, ident.ref) catch unreachable;
},
.b_array => |array| {
for (array.items) |prop| {
@@ -3538,8 +3538,8 @@ pub fn NewParser(
// during minification. These counts shouldn't include references inside dead
// code regions since those will be culled.
if (!p.is_control_flow_dead) {
- std.debug.assert(p.symbols.items.len > ref.innerIndex());
- p.symbols.items[ref.innerIndex()].use_count_estimate += 1;
+ std.debug.assert(p.symbols.items.len > ref.inner_index);
+ p.symbols.items[ref.inner_index].use_count_estimate += 1;
var result = p.symbol_uses.getOrPut(p.allocator, ref) catch unreachable;
if (!result.found_existing) {
result.value_ptr.* = Symbol.Use{ .count_estimate = 1 };
@@ -3552,7 +3552,7 @@ pub fn NewParser(
// symbol use counts for the whole file, including dead code regions. This is
// tracked separately in a parser-only data structure.
if (is_typescript_enabled) {
- p.ts_use_counts.items[ref.innerIndex()] += 1;
+ p.ts_use_counts.items[ref.inner_index] += 1;
}
}
@@ -3586,11 +3586,11 @@ pub fn NewParser(
pub fn handleIdentifier(p: *P, loc: logger.Loc, ident: E.Identifier, _original_name: ?string, opts: IdentifierOpts) Expr {
const ref = ident.ref;
- if ((opts.assign_target != .none or opts.is_delete_target) and p.symbols.items[ref.innerIndex()].kind == .import) {
+ if ((opts.assign_target != .none or opts.is_delete_target) and p.symbols.items[ref.inner_index].kind == .import) {
// Create an error for assigning to an import namespace
const r = js_lexer.rangeOfIdentifier(p.source, loc);
p.log.addRangeErrorFmt(p.source, r, p.allocator, "Cannot assign to import \"{s}\"", .{
- p.symbols.items[ref.innerIndex()].original_name,
+ p.symbols.items[ref.inner_index].original_name,
}) catch unreachable;
}
@@ -3605,7 +3605,7 @@ pub fn NewParser(
// Substitute a namespace export reference now if appropriate
if (is_typescript_enabled) {
if (p.is_exported_inside_namespace.get(ref)) |ns_ref| {
- const name = p.symbols.items[ref.innerIndex()].original_name;
+ const name = p.symbols.items[ref.inner_index].original_name;
// If this is a known enum value, inline the value of the enum
if (p.known_enum_values.get(ns_ref)) |enum_values| {
@@ -3836,17 +3836,17 @@ pub fn NewParser(
pub fn resolveGeneratedSymbol(p: *P, generated_symbol: *GeneratedSymbol) void {
if (generated_symbol.ref.isNull()) return;
- if (p.symbols.items[generated_symbol.primary.innerIndex()].use_count_estimate == 0 and
- p.symbols.items[generated_symbol.primary.innerIndex()].link == null)
+ if (p.symbols.items[generated_symbol.primary.inner_index].use_count_estimate == 0 and
+ p.symbols.items[generated_symbol.primary.inner_index].link == null)
{
- p.symbols.items[generated_symbol.ref.innerIndex()].original_name = p.symbols.items[generated_symbol.primary.innerIndex()].original_name;
+ p.symbols.items[generated_symbol.ref.inner_index].original_name = p.symbols.items[generated_symbol.primary.inner_index].original_name;
return;
}
- if (p.symbols.items[generated_symbol.backup.innerIndex()].use_count_estimate == 0 and
- p.symbols.items[generated_symbol.backup.innerIndex()].link == null)
+ if (p.symbols.items[generated_symbol.backup.inner_index].use_count_estimate == 0 and
+ p.symbols.items[generated_symbol.backup.inner_index].link == null)
{
- p.symbols.items[generated_symbol.ref.innerIndex()].original_name = p.symbols.items[generated_symbol.backup.innerIndex()].original_name;
+ p.symbols.items[generated_symbol.ref.inner_index].original_name = p.symbols.items[generated_symbol.backup.inner_index].original_name;
return;
}
}
@@ -3894,7 +3894,7 @@ pub fn NewParser(
var iter = scope.members.iterator();
const allocator = p.allocator;
nextMember: while (iter.next()) |res| {
- var symbol = &p.symbols.items[res.value.ref.innerIndex()];
+ var symbol = &p.symbols.items[res.value.ref.inner_index];
if (!symbol.isHoisted()) {
continue :nextMember;
}
@@ -3924,7 +3924,7 @@ pub fn NewParser(
if (_scope.members.getEntryWithHash(symbol.original_name, hash)) |existing_member_entry| {
const existing_member = &existing_member_entry.value;
- const existing_symbol: *const Symbol = &p.symbols.items[existing_member.ref.innerIndex()];
+ const existing_symbol: *const Symbol = &p.symbols.items[existing_member.ref.inner_index];
// We can hoist the symbol from the child scope into the symbol in
// this scope if:
@@ -4019,7 +4019,6 @@ pub fn NewParser(
.kind = kind,
.label_ref = null,
.parent = parent,
- .generated = .{},
};
try parent.children.append(allocator, scope);
@@ -4054,8 +4053,8 @@ pub fn NewParser(
while (iter.next()) |entry| {
// // Don't copy down the optional function expression name. Re-declaring
// // the name of a function expression is allowed.
- const adjacent_kind = p.symbols.items[entry.value.ref.innerIndex()].kind;
- if (adjacent_kind != .hoisted_function) {
+ const adjacent_symbols = p.symbols.items[entry.value.ref.inner_index];
+ if (adjacent_symbols.kind != .hoisted_function) {
try scope.members.put(allocator, entry.key, entry.value);
}
}
@@ -4486,8 +4485,8 @@ pub fn NewParser(
// this if it wasn't already declared above because arguments are allowed to
// be called "arguments", in which case the real "arguments" is inaccessible.
if (!p.current_scope.members.contains("arguments")) {
- func.arguments_ref = p.declareSymbolMaybeGenerated(.arguments, func.open_parens_loc, "arguments", true) catch unreachable;
- p.symbols.items[func.arguments_ref.?.innerIndex()].must_not_be_renamed = true;
+ func.arguments_ref = p.declareSymbol(.arguments, func.open_parens_loc, "arguments") catch unreachable;
+ p.symbols.items[func.arguments_ref.?.inner_index].must_not_be_renamed = true;
}
try p.lexer.expect(.t_close_paren);
@@ -5058,91 +5057,42 @@ pub fn NewParser(
fn processImportStatement(p: *P, stmt_: S.Import, path: ParsedPath, loc: logger.Loc, was_originally_bare_import: bool) anyerror!Stmt {
const is_macro = FeatureFlags.is_macro_enabled and js_ast.Macro.isMacroPath(path.text);
- var stmt = stmt_;
- if (is_macro) {
- const id = p.addImportRecord(.stmt, path.loc, path.text);
- p.import_records.items[id].path.namespace = js_ast.Macro.namespace;
- p.import_records.items[id].is_unused = true;
-
- if (stmt.default_name) |name_loc| {
- const name = p.loadNameFromRef(name_loc.ref.?);
- const ref = try p.declareSymbol(.other, name_loc.loc, name);
- try p.is_import_item.put(p.allocator, ref, .{});
- try p.macro.refs.put(ref, id);
- }
-
- for (stmt.items) |item| {
- const name = p.loadNameFromRef(item.name.ref.?);
- const ref = try p.declareSymbol(.other, item.name.loc, name);
- try p.is_import_item.put(p.allocator, ref, .{});
- try p.macro.refs.put(ref, id);
- }
-
- return p.s(S.Empty{}, loc);
- }
-
- if ((comptime allow_macros) and !is_macro) {
- if (p.options.macro_context.getRemap(path.text)) |remap| {
- if (stmt.default_name) |*name_loc| {
- if (remap.get("default")) |remapped_path| {
- const name = p.loadNameFromRef(name_loc.ref.?);
- const ref = try p.declareSymbol(.other, name_loc.loc, name);
- const new_import_id = p.addImportRecord(.stmt, path.loc, remapped_path);
- try p.macro.refs.put(ref, new_import_id);
- try p.is_import_item.put(p.allocator, ref, .{});
-
- stmt.default_name = null;
- p.import_records.items[new_import_id].path.namespace = js_ast.Macro.namespace;
- p.import_records.items[new_import_id].is_unused = true;
- if (comptime only_scan_imports_and_do_not_visit) {
- p.import_records.items[new_import_id].is_internal = true;
- p.import_records.items[new_import_id].path.is_disabled = true;
- }
- }
- }
- var end: u32 = 0;
- for (stmt.items) |item| {
- if (remap.get(item.alias)) |remapped_path| {
- const name = p.loadNameFromRef(item.name.ref.?);
- const ref = try p.declareSymbol(.other, item.alias_loc, name);
- const new_import_id = p.addImportRecord(.stmt, path.loc, remapped_path);
- try p.macro.refs.put(ref, new_import_id);
- try p.is_import_item.put(p.allocator, ref, .{});
-
- p.import_records.items[new_import_id].path.namespace = js_ast.Macro.namespace;
- p.import_records.items[new_import_id].is_unused = true;
-
- if (comptime only_scan_imports_and_do_not_visit) {
- p.import_records.items[new_import_id].is_internal = true;
- p.import_records.items[new_import_id].path.is_disabled = true;
- }
- continue;
- }
+ const macro_remap = if ((comptime allow_macros) and !is_macro)
+ p.options.macro_context.getRemap(path.text)
+ else
+ null;
- stmt.items[end] = item;
- end += 1;
- }
- stmt.items = stmt.items[0..end];
+ var stmt = stmt_;
- if (!was_originally_bare_import and stmt.items.len == 0 and stmt.default_name == null and stmt.star_name_loc == null) {
- return p.s(S.Empty{}, loc);
- }
- }
- }
+ const is_any_macro = is_macro or macro_remap != null;
stmt.import_record_index = p.addImportRecord(.stmt, path.loc, path.text);
p.import_records.items[stmt.import_record_index].was_originally_bare_import = was_originally_bare_import;
+ var remap_count: u16 = 0;
if (stmt.star_name_loc) |star| {
const name = p.loadNameFromRef(stmt.namespace_ref);
stmt.namespace_ref = try p.declareSymbol(.import, star, name);
+ if (is_macro) {
+ p.log.addErrorFmt(
+ p.source,
+ star,
+ p.allocator,
+ "Macro cannot be a * import, must be default or an {{item}}",
+ .{},
+ ) catch unreachable;
+ return error.SyntaxError;
+ }
+
if (comptime ParsePassSymbolUsageType != void) {
- p.parse_pass_symbol_uses.put(name, .{
- .ref = stmt.namespace_ref,
- .import_record_index = stmt.import_record_index,
- }) catch unreachable;
+ if (!is_any_macro) {
+ p.parse_pass_symbol_uses.put(name, .{
+ .ref = stmt.namespace_ref,
+ .import_record_index = stmt.import_record_index,
+ }) catch unreachable;
+ }
}
} else {
var path_name = fs.PathName.init(strings.append(p.allocator, "import_", path.text) catch unreachable);
@@ -5166,25 +5116,86 @@ pub fn NewParser(
// Link the default item to the namespace
if (stmt.default_name) |*name_loc| {
- const name = p.loadNameFromRef(name_loc.ref.?);
- const ref = try p.declareSymbol(.import, name_loc.loc, name);
- name_loc.ref = ref;
- try p.is_import_item.put(p.allocator, ref, .{});
+ outer: {
+ const name = p.loadNameFromRef(name_loc.ref.?);
+ const ref = try p.declareSymbol(.import, name_loc.loc, name);
+ name_loc.ref = ref;
+ try p.is_import_item.put(p.allocator, ref, .{});
- if (comptime ParsePassSymbolUsageType != void) {
- p.parse_pass_symbol_uses.put(name, .{
- .ref = ref,
- .import_record_index = stmt.import_record_index,
- }) catch unreachable;
- }
+ if (comptime ParsePassSymbolUsageType != void) {
+ if (!is_macro) {
+ p.parse_pass_symbol_uses.put(name, .{
+ .ref = ref,
+ .import_record_index = stmt.import_record_index,
+ }) catch unreachable;
+ }
+ }
+
+ if (macro_remap) |remap| {
+ if (remap.get("default")) |remapped_path| {
+ const new_import_id = p.addImportRecord(.stmt, path.loc, remapped_path);
+ try p.macro.refs.put(ref, new_import_id);
+ stmt.default_name = null;
+ p.import_records.items[new_import_id].path.namespace = js_ast.Macro.namespace;
+ if (comptime only_scan_imports_and_do_not_visit) {
+ p.import_records.items[new_import_id].is_internal = true;
+ p.import_records.items[new_import_id].path.is_disabled = true;
+ }
+ remap_count += 1;
+ break :outer;
+ }
+ }
- item_refs.putAssumeCapacity(name, name_loc.*);
+ if (is_macro) {
+ try p.macro.refs.put(ref, stmt.import_record_index);
+ stmt.default_name = null;
+ break :outer;
+ }
+
+ item_refs.putAssumeCapacity(name, name_loc.*);
+ }
}
if (stmt.items.len > 0) {
var i: usize = 0;
var list = std.ArrayListUnmanaged(js_ast.ClauseItem){ .items = stmt.items, .capacity = stmt.items.len };
+ // I do not like two passes here. This works around a bug
+ // where when the final import item of a remapped macro
+ // is _not_ a macro we end up removing the Symbol's
+ // namespace_alias...for some reason The specific issue
+ // might be a pointer aliasing bug, might be a zig bug,
+ // or might be undefined behavior but it's really
+ // difficult to determine it only happens in ReleaseFast
+ // mode – not in ReleaseSafe or Debug. so instead of
+ // fixing it, we do an extra pass over import items
+ // which have a macro remap that contain multiple items
+ // and we just move any macro imports to the end of the
+ // list This shouldn't have a meanigful impact on perf
+ // because the number of imports will typically be small
+ // like 2 it's an edgecase where it would be more than
+ // that nobody uses this feature currently anyway except
+ // for lattice
+ if (macro_remap) |remap| {
+ if (list.items.len > 1) {
+ const Sorter = struct {
+ remap_content: js_ast.Macro.MacroRemapEntry,
+ pub fn isLessThan(this: @This(), lhs: js_ast.ClauseItem, rhs: js_ast.ClauseItem) bool {
+ const has_left = this.remap_content.contains(lhs.alias);
+ const has_right = this.remap_content.contains(rhs.alias);
+
+ // put the macro imports at the end of the list
+ if (has_left != has_right) {
+ return has_right;
+ }
+
+ // we don't care if its asc or desc, just has to be something deterministic
+ return strings.cmpStringsAsc(void{}, lhs.alias, rhs.alias);
+ }
+ };
+ std.sort.insertionSort(js_ast.ClauseItem, list.items, Sorter{ .remap_content = remap }, Sorter.isLessThan);
+ }
+ }
var end: u32 = 0;
while (i < list.items.len) : (i += 1) {
var item: js_ast.ClauseItem = list.items[i];
@@ -5196,15 +5207,32 @@ pub fn NewParser(
p.checkForNonBMPCodePoint(item.alias_loc, item.alias);
item_refs.putAssumeCapacity(item.alias, LocRef{ .loc = item.name.loc, .ref = ref });
- if (comptime ParsePassSymbolUsageType != void) {
- p.parse_pass_symbol_uses.put(name, .{
- .ref = ref,
- .import_record_index = stmt.import_record_index,
- }) catch unreachable;
- }
+ if (is_macro) {
+ try p.macro.refs.put(ref, stmt.import_record_index);
+ continue;
+ } else if (macro_remap) |remap| {
+ if (remap.get(item.alias)) |remapped_path| {
+ const new_import_id = p.addImportRecord(.stmt, path.loc, remapped_path);
+ p.import_records.items[new_import_id].path.namespace = js_ast.Macro.namespace;
+ if (comptime only_scan_imports_and_do_not_visit) {
+ p.import_records.items[new_import_id].is_internal = true;
+ p.import_records.items[new_import_id].path.is_disabled = true;
+ }
+ try p.macro.refs.put(ref, new_import_id);
+ remap_count += 1;
+ continue;
+ }
+ } else {
+ if (comptime ParsePassSymbolUsageType != void) {
+ p.parse_pass_symbol_uses.put(name, .{
+ .ref = ref,
+ .import_record_index = stmt.import_record_index,
+ }) catch unreachable;
+ }
- list.items[end] = item;
- end += 1;
+ list.items[end] = item;
+ end += 1;
+ }
}
stmt.items = list.items[0..end];
}
@@ -5212,6 +5240,17 @@ pub fn NewParser(
// If we remapped the entire import away
// i.e. import {graphql} "react-relay"
+ if (remap_count > 0 and remap_count == total_count) {
+ p.import_records.items[stmt.import_record_index].path.namespace = js_ast.Macro.namespace;
+
+ if (comptime only_scan_imports_and_do_not_visit) {
+ p.import_records.items[stmt.import_record_index].path.is_disabled = true;
+ p.import_records.items[stmt.import_record_index].is_internal = true;
+ }
+
+ return p.s(S.Empty{}, loc);
+ }
+
// Track the items for this namespace
try p.import_items_for_namespace.put(p.allocator, stmt.namespace_ref, item_refs);
return p.s(stmt, loc);
@@ -5272,7 +5311,10 @@ pub fn NewParser(
try p.ts_use_counts.append(p.allocator, 0);
}
- return Ref.init(inner_index, Ref.toInt(p.source.index), false);
+ return Ref{
+ .source_index = Ref.toInt(p.source.index),
+ .inner_index = inner_index,
+ };
}
fn parseLabelName(p: *P) !?js_ast.LocRef {
@@ -5659,9 +5701,7 @@ pub fn NewParser(
break :default_name_getter LocRef{ .loc = defaultLoc, .ref = ident.ref };
},
.e_import_identifier => |ident| {
- if (!allow_macros or (allow_macros and !p.macro.refs.contains(ident.ref))) {
- break :default_name_getter LocRef{ .loc = defaultLoc, .ref = ident.ref };
- }
+ break :default_name_getter LocRef{ .loc = defaultLoc, .ref = ident.ref };
},
.e_class => |class| {
if (class.class_name) |_name| {
@@ -7121,7 +7161,7 @@ pub fn NewParser(
switch (decl.binding.data) {
.b_identifier => |ident| {
const r = js_lexer.rangeOfIdentifier(p.source, decl.binding.loc);
- try p.log.addRangeErrorFmt(p.source, r, p.allocator, "The constant \"{s}\" must be initialized", .{p.symbols.items[ident.ref.innerIndex()].original_name});
+ try p.log.addRangeErrorFmt(p.source, r, p.allocator, "The constant \"{s}\" must be initialized", .{p.symbols.items[ident.ref.inner_index].original_name});
// return;/
},
else => {
@@ -7794,7 +7834,7 @@ pub fn NewParser(
// Both the "exports" argument and "var exports" are hoisted variables, so
// they don't collide.
if (member) |_member| {
- if (p.symbols.items[_member.ref.innerIndex()].kind == .hoisted and kind == .hoisted and !p.has_es_module_syntax) {
+ if (p.symbols.items[_member.ref.inner_index].kind == .hoisted and kind == .hoisted and !p.has_es_module_syntax) {
return _member.ref;
}
}
@@ -7846,7 +7886,7 @@ pub fn NewParser(
var entry = try scope.members.getOrPut(p.allocator, name);
if (entry.found_existing) {
const existing = entry.entry.value;
- var symbol: *Symbol = &p.symbols.items[existing.ref.innerIndex()];
+ var symbol: *Symbol = &p.symbols.items[@intCast(usize, existing.ref.inner_index)];
if (comptime !is_generated) {
switch (scope.canMergeSymbols(symbol.kind, kind, is_typescript_enabled)) {
@@ -7881,7 +7921,7 @@ pub fn NewParser(
try p.is_import_item.put(p.allocator, ref, .{});
}
- p.symbols.items[ref.innerIndex()].link = existing.ref;
+ p.symbols.items[ref.inner_index].link = existing.ref;
}
}
@@ -7894,7 +7934,7 @@ pub fn NewParser(
fn validateFunctionName(p: *P, func: G.Fn, kind: FunctionKind) void {
if (func.name) |name| {
- const original_name = p.symbols.items[name.ref.?.innerIndex()].original_name;
+ const original_name = p.symbols.items[name.ref.?.inner_index].original_name;
if (func.flags.is_async and strings.eqlComptime(original_name, "await")) {
p.log.addRangeError(
@@ -8073,22 +8113,26 @@ pub fn NewParser(
if (@ptrToInt(p.source.contents.ptr) <= @ptrToInt(name.ptr) and (@ptrToInt(name.ptr) + name.len) <= (@ptrToInt(p.source.contents.ptr) + p.source.contents.len)) {
const start = Ref.toInt(@ptrToInt(name.ptr) - @ptrToInt(p.source.contents.ptr));
const end = Ref.toInt(name.len);
- return Ref.initSourceEnd(.{ .source_index = start, .inner_index = end, .is_source_contents_slice = true });
- } else {
+ return Ref{ .source_index = start, .inner_index = end, .is_source_contents_slice = true };
+ } else if (p.allocated_names.capacity > 0) {
const inner_index = Ref.toInt(p.allocated_names.items.len);
try p.allocated_names.append(p.allocator, name);
- return Ref.initSourceEnd(.{ .source_index = std.math.maxInt(Ref.Int), .inner_index = inner_index, .is_source_contents_slice = false });
+ return Ref{ .source_index = std.math.maxInt(Ref.Int), .inner_index = inner_index };
+ } else {
+ p.allocated_names = try @TypeOf(p.allocated_names).initCapacity(p.allocator, 1);
+ p.allocated_names.appendAssumeCapacity(name);
+ return Ref{ .source_index = std.math.maxInt(Ref.Int), .inner_index = 0 };
}
}
pub fn loadNameFromRef(p: *P, ref: Ref) string {
- if (ref.isSourceContentsSlice()) {
- return p.source.contents[ref.sourceIndex() .. ref.sourceIndex() + ref.innerIndex()];
- } else if (ref.sourceIndex() == std.math.maxInt(Ref.Int)) {
- assert(ref.innerIndex() < p.allocated_names.items.len);
- return p.allocated_names.items[ref.innerIndex()];
+ if (ref.is_source_contents_slice) {
+ return p.source.contents[ref.source_index .. ref.source_index + ref.inner_index];
+ } else if (ref.source_index == std.math.maxInt(Ref.Int)) {
+ assert(ref.inner_index < p.allocated_names.items.len);
+ return p.allocated_names.items[ref.inner_index];
} else {
- return p.symbols.items[ref.innerIndex()].original_name;
+ return p.symbols.items[ref.inner_index].original_name;
}
}
@@ -8357,7 +8401,7 @@ pub fn NewParser(
// continue;
// }
- p.symbols.items[member.value.ref.innerIndex()].must_not_be_renamed = true;
+ p.symbols.items[member.value.ref.inner_index].must_not_be_renamed = true;
}
}
@@ -10828,7 +10872,7 @@ pub fn NewParser(
for (p.relocated_top_level_vars.items) |*local| {
// Follow links because "var" declarations may be merged due to hoisting
while (local.ref != null) {
- const link = p.symbols.items[local.ref.?.innerIndex()].link orelse break;
+ const link = p.symbols.items[local.ref.?.inner_index].link orelse break;
if (link.isNull()) {
break;
}
@@ -10851,7 +10895,7 @@ pub fn NewParser(
// Follow links because "var" declarations may be merged due to hoisting
// while (true) {
- // const link = p.symbols.items[local.ref.innerIndex()].link;
+ // const link = p.symbols.items[local.ref.inner_index].link;
// }
}
@@ -11045,8 +11089,8 @@ pub fn NewParser(
}
var func = _func;
- const old_fn_or_arrow_data = p.fn_or_arrow_data_visit;
- const old_fn_only_data = p.fn_only_data_visit;
+ const old_fn_or_arrow_data = std.mem.toBytes(p.fn_or_arrow_data_visit);
+ const old_fn_only_data = std.mem.toBytes(p.fn_only_data_visit);
p.fn_or_arrow_data_visit = FnOrArrowDataVisit{ .is_async = func.flags.is_async };
p.fn_only_data_visit = FnOnlyDataVisit{ .is_this_nested = true, .arguments_ref = func.arguments_ref };
@@ -11081,8 +11125,8 @@ pub fn NewParser(
p.popScope();
p.popScope();
- p.fn_or_arrow_data_visit = old_fn_or_arrow_data;
- p.fn_only_data_visit = old_fn_only_data;
+ p.fn_or_arrow_data_visit = std.mem.bytesToValue(@TypeOf(p.fn_or_arrow_data_visit), &old_fn_or_arrow_data);
+ p.fn_only_data_visit = std.mem.bytesToValue(@TypeOf(p.fn_only_data_visit), &old_fn_only_data);
return func;
}
@@ -11177,10 +11221,10 @@ pub fn NewParser(
e_.ref = result.ref;
// TODO: fix the underyling cause here
- // The problem seems to be that result.ref.innerIndex() is not always set.
+ // The problem seems to be that result.ref.inner_index is not always set.
// Handle assigning to a constant
- // if (in.assign_target != .none and p.symbols.items[result.ref.innerIndex()].kind == .cconst) {
+ // if (in.assign_target != .none and p.symbols.items[result.ref.inner_index].kind == .cconst) {
// const r = js_lexer.rangeOfIdentifier(p.source, expr.loc);
// p.log.addRangeErrorFmt(p.source, r, p.allocator, "Cannot assign to {s} because it is a constant", .{name}) catch unreachable;
// }
@@ -11188,7 +11232,7 @@ pub fn NewParser(
var original_name: ?string = null;
// Substitute user-specified defines for unbound symbols
- if (p.symbols.items[e_.ref.innerIndex()].kind == .unbound and !result.is_inside_with_scope and !is_delete_target) {
+ if (p.symbols.items[e_.ref.inner_index].kind == .unbound and !result.is_inside_with_scope and !is_delete_target) {
if (p.define.identifiers.get(name)) |def| {
if (!def.isUndefined()) {
const newvalue = p.valueForDefine(expr.loc, in.assign_target, is_delete_target, &def);
@@ -11453,8 +11497,7 @@ pub fn NewParser(
if (e_.tag.?.data == .e_import_identifier) {
const ref = e_.tag.?.data.e_import_identifier.ref;
if (p.macro.refs.get(ref)) |import_record_id| {
- const name = p.symbols.items[ref.innerIndex()].original_name;
- p.ignoreUsage(ref);
+ const name = p.symbols.items[ref.inner_index].original_name;
p.macro_call_count += 1;
const record = &p.import_records.items[import_record_id];
// We must visit it to convert inline_identifiers and record usage
@@ -11515,7 +11558,7 @@ pub fn NewParser(
private.ref = result.ref;
// Unlike regular identifiers, there are no unbound private identifiers
- const symbol: Symbol = p.symbols.items[result.ref.innerIndex()];
+ const symbol: Symbol = p.symbols.items[result.ref.inner_index];
if (!Symbol.isKindPrivate(symbol.kind)) {
const r = logger.Range{ .loc = e_.left.loc, .len = @intCast(i32, name.len) };
p.log.addRangeErrorFmt(p.source, r, p.allocator, "Private name \"{s}\" must be declared in an enclosing class", .{name}) catch unreachable;
@@ -11881,7 +11924,7 @@ pub fn NewParser(
// Optionally preserve the name
if (@as(Expr.Tag, e_.left.data) == .e_identifier) {
- e_.right = p.maybeKeepExprSymbolName(e_.right, p.symbols.items[e_.left.data.e_identifier.ref.innerIndex()].original_name, was_anonymous_named_expr);
+ e_.right = p.maybeKeepExprSymbolName(e_.right, p.symbols.items[e_.left.data.e_identifier.ref.inner_index].original_name, was_anonymous_named_expr);
}
},
.bin_add_assign => {
@@ -11986,14 +12029,14 @@ pub fn NewParser(
// though this is a run-time error, we make it a compile-time error when
// bundling because scope hoisting means these will no longer be run-time
// errors.
- if ((in.assign_target != .none or is_delete_target) and @as(Expr.Tag, e_.target.data) == .e_identifier and p.symbols.items[e_.target.data.e_identifier.ref.innerIndex()].kind == .import) {
+ if ((in.assign_target != .none or is_delete_target) and @as(Expr.Tag, e_.target.data) == .e_identifier and p.symbols.items[e_.target.data.e_identifier.ref.inner_index].kind == .import) {
const r = js_lexer.rangeOfIdentifier(p.source, e_.target.loc);
p.log.addRangeErrorFmt(
p.source,
r,
p.allocator,
"Cannot assign to property on import \"{s}\"",
- .{p.symbols.items[e_.target.data.e_identifier.ref.innerIndex()].original_name},
+ .{p.symbols.items[e_.target.data.e_identifier.ref.inner_index].original_name},
) catch unreachable;
}
@@ -12008,7 +12051,7 @@ pub fn NewParser(
// The expression "typeof (0, x)" must not become "typeof x" if "x"
// is unbound because that could suppress a ReferenceError from "x"
- if (!id_before and id_after and p.symbols.items[e_.value.data.e_identifier.ref.innerIndex()].kind == .unbound) {
+ if (!id_before and id_after and p.symbols.items[e_.value.data.e_identifier.ref.inner_index].kind == .unbound) {
e_.value = Expr.joinWithComma(
Expr{ .loc = e_.value.loc, .data = Prefill.Data.Zero },
e_.value,
@@ -12229,7 +12272,7 @@ pub fn NewParser(
if (@as(Expr.Tag, e2.left.data) == .e_identifier) {
e2.right = p.maybeKeepExprSymbolName(
e2.right,
- p.symbols.items[e2.left.data.e_identifier.ref.innerIndex()].original_name,
+ p.symbols.items[e2.left.data.e_identifier.ref.inner_index].original_name,
was_anonymous_named_expr,
);
}
@@ -12298,7 +12341,7 @@ pub fn NewParser(
if (@as(Expr.Tag, val.data) == .e_identifier) {
property.initializer = p.maybeKeepExprSymbolName(
property.initializer orelse unreachable,
- p.symbols.items[val.data.e_identifier.ref.innerIndex()].original_name,
+ p.symbols.items[val.data.e_identifier.ref.inner_index].original_name,
was_anonymous_named_expr,
);
}
@@ -12390,8 +12433,7 @@ pub fn NewParser(
if (is_macro_ref) {
const ref = e_.target.data.e_import_identifier.ref;
const import_record_id = p.macro.refs.get(ref).?;
- p.ignoreUsage(ref);
- const name = p.symbols.items[ref.innerIndex()].original_name;
+ const name = p.symbols.items[ref.inner_index].original_name;
const record = &p.import_records.items[import_record_id];
const copied = Expr{ .loc = expr.loc, .data = .{ .e_call = e_ } };
const start_error_count = p.log.msgs.items.len;
@@ -12473,7 +12515,7 @@ pub fn NewParser(
.e_function => |e_| {
e_.func = p.visitFunc(e_.func, expr.loc);
if (e_.func.name) |name| {
- return p.keepExprSymbolName(expr, p.symbols.items[name.ref.?.innerIndex()].original_name);
+ return p.keepExprSymbolName(expr, p.symbols.items[name.ref.?.inner_index].original_name);
}
},
.e_class => |e_| {
@@ -12664,7 +12706,7 @@ pub fn NewParser(
// incorrect but proper TDZ analysis is very complicated and would have to
// be very conservative, which would inhibit a lot of optimizations of code
// inside closures. This may need to be revisited if it proves problematic.
- if (ex.can_be_removed_if_unused or p.symbols.items[ex.ref.innerIndex()].kind != .unbound) {
+ if (ex.can_be_removed_if_unused or p.symbols.items[ex.ref.inner_index].kind != .unbound) {
return true;
}
},
@@ -12836,7 +12878,7 @@ pub fn NewParser(
fn isSideEffectFreeUnboundIdentifierRef(p: *P, value: Expr, guard_condition: Expr, is_yes_branch: bool) bool {
if (value.data != .e_identifier or
- p.symbols.items[value.data.e_identifier.ref.innerIndex()].kind != .unbound or
+ p.symbols.items[value.data.e_identifier.ref.inner_index].kind != .unbound or
guard_condition.data != .e_binary)
return false;
@@ -12977,9 +13019,9 @@ pub fn NewParser(
pub fn ignoreUsage(p: *P, ref: Ref) void {
if (!p.is_control_flow_dead) {
- p.symbols.items[ref.innerIndex()].use_count_estimate -|= 1;
+ p.symbols.items[ref.inner_index].use_count_estimate = std.math.max(p.symbols.items[ref.inner_index].use_count_estimate, 1) - 1;
var use = p.symbol_uses.get(ref) orelse p.panic("Expected symbol_uses to exist {s}\n{s}", .{ ref, p.symbol_uses });
- use.count_estimate -|= 1;
+ use.count_estimate = std.math.max(use.count_estimate, 1) - 1;
if (use.count_estimate == 0) {
_ = p.symbol_uses.remove(ref);
} else {
@@ -13030,7 +13072,7 @@ pub fn NewParser(
const symbol = try p.findSymbol(item.alias_loc, name);
const ref = symbol.ref;
- if (p.symbols.items[ref.innerIndex()].kind == .unbound) {
+ if (p.symbols.items[ref.inner_index].kind == .unbound) {
// Silently strip exports of non-local symbols in TypeScript, since
// those likely correspond to type-only exports. But report exports of
// non-local symbols as errors in JavaScript.
@@ -13119,10 +13161,10 @@ pub fn NewParser(
// Discard type-only export default statements
if (is_typescript_enabled) {
- switch (data.value.expr.data) {
+ switch (expr.data) {
.e_identifier => |ident| {
- if (!ident.ref.isSourceContentsSlice()) {
- const symbol = p.symbols.items[ident.ref.innerIndex()];
+ if (!ident.ref.is_source_contents_slice) {
+ const symbol = p.symbols.items[ident.ref.inner_index];
if (symbol.kind == .unbound) {
if (p.local_type_names.get(symbol.original_name)) |local_type| {
if (local_type) {
@@ -13645,7 +13687,7 @@ pub fn NewParser(
// p.keepStmtSymbolName(
// data.func.name.?.loc,
// data.func.name.?.ref.?,
- // p.symbols.items[data.func.name.?.ref.?.innerIndex()].original_name,
+ // p.symbols.items[data.func.name.?.ref.?.inner_index].original_name,
// ),
// );
return;
@@ -13666,7 +13708,7 @@ pub fn NewParser(
if (was_export_inside_namespace) {
stmts.appendAssumeCapacity(Expr.assignStmt(p.e(E.Dot{
.target = p.e(E.Identifier{ .ref = p.enclosing_namespace_arg_ref.? }, stmt.loc),
- .name = p.symbols.items[data.class.class_name.?.ref.?.innerIndex()].original_name,
+ .name = p.symbols.items[data.class.class_name.?.ref.?.inner_index].original_name,
.name_loc = data.class.class_name.?.loc,
}, stmt.loc), p.e(E.Identifier{ .ref = data.class.class_name.?.ref.? }, data.class.class_name.?.loc), p.allocator));
}
@@ -13899,7 +13941,7 @@ pub fn NewParser(
.b_identifier => |id| {
decl.value = p.maybeKeepExprSymbolName(
decl.value.?,
- p.symbols.items[id.ref.innerIndex()].original_name,
+ p.symbols.items[id.ref.inner_index].original_name,
was_anonymous_named_expr,
);
},
@@ -13984,11 +14026,11 @@ pub fn NewParser(
) anyerror!void {
var name_ref = _name_ref;
// Follow the link chain in case symbols were merged
- var symbol: Symbol = p.symbols.items[name_ref.innerIndex()];
+ var symbol: Symbol = p.symbols.items[name_ref.inner_index];
while (symbol.link != null) {
const link = symbol.link orelse unreachable;
name_ref = link;
- symbol = p.symbols.items[name_ref.innerIndex()];
+ symbol = p.symbols.items[name_ref.inner_index];
}
const allocator = p.allocator;
@@ -14032,7 +14074,7 @@ pub fn NewParser(
if (is_export and p.enclosing_namespace_arg_ref != null) {
const namespace = p.enclosing_namespace_arg_ref.?;
// "name = enclosing.name || (enclosing.name = {})"
- const name = p.symbols.items[name_ref.innerIndex()].original_name;
+ const name = p.symbols.items[name_ref.inner_index].original_name;
arg_expr = Expr.assign(
Expr.initIdentifier(name_ref, name_loc),
p.e(
@@ -14179,7 +14221,7 @@ pub fn NewParser(
return p.e(E.Dot{
.target = Expr.initIdentifier(enclosing_ref, loc),
- .name = p.symbols.items[ref.innerIndex()].original_name,
+ .name = p.symbols.items[ref.inner_index].original_name,
.name_loc = loc,
}, loc);
}
@@ -14289,7 +14331,7 @@ pub fn NewParser(
}
// The last symbol must be unbound
- return p.symbols.items[result.ref.innerIndex()].kind == .unbound;
+ return p.symbols.items[result.ref.inner_index].kind == .unbound;
}
},
else => {},
@@ -14303,7 +14345,7 @@ pub fn NewParser(
.b_missing => {},
.b_identifier => |bind| {
p.recordDeclaredSymbol(bind.ref) catch unreachable;
- const name = p.symbols.items[bind.ref.innerIndex()].original_name;
+ const name = p.symbols.items[bind.ref.inner_index].original_name;
if (isEvalOrArguments(name)) {
p.markStrictModeFeature(.eval_or_arguments, js_lexer.rangeOfIdentifier(p.source, binding.loc), name) catch unreachable;
}
@@ -14330,7 +14372,7 @@ pub fn NewParser(
.b_identifier => |bind_| {
item.default_value = p.maybeKeepExprSymbolName(
item.default_value orelse unreachable,
- p.symbols.items[bind_.ref.innerIndex()].original_name,
+ p.symbols.items[bind_.ref.inner_index].original_name,
was_anonymous_named_expr,
);
},
@@ -14354,7 +14396,7 @@ pub fn NewParser(
.b_identifier => |bind_| {
property.default_value = p.maybeKeepExprSymbolName(
property.default_value orelse unreachable,
- p.symbols.items[bind_.ref.innerIndex()].original_name,
+ p.symbols.items[bind_.ref.inner_index].original_name,
was_anonymous_named_expr,
);
},
@@ -14422,7 +14464,7 @@ pub fn NewParser(
while (_scope != null and !_scope.?.kindStopsHoisting()) : (_scope = _scope.?.parent.?) {
const scope = _scope orelse unreachable;
const label_ref = scope.label_ref orelse continue;
- if (scope.kind == .label and strings.eql(name, p.symbols.items[label_ref.innerIndex()].original_name)) {
+ if (scope.kind == .label and strings.eql(name, p.symbols.items[label_ref.inner_index].original_name)) {
// Track how many times we've referenced this symbol
p.recordUsage(label_ref);
res.ref = label_ref;
@@ -14468,7 +14510,7 @@ pub fn NewParser(
if (!class_name_ref.eql(Ref.None)) {
// are not allowed to assign to this symbol (it throws a TypeError).
- const name = p.symbols.items[class_name_ref.innerIndex()].original_name;
+ const name = p.symbols.items[class_name_ref.inner_index].original_name;
var identifier = p.allocator.alloc(u8, name.len + 1) catch unreachable;
std.mem.copy(u8, identifier[1..identifier.len], name);
identifier[0] = '_';
@@ -14547,7 +14589,7 @@ pub fn NewParser(
}
if (!shadow_ref.eql(Ref.None)) {
- if (p.symbols.items[shadow_ref.innerIndex()].use_count_estimate == 0) {
+ if (p.symbols.items[shadow_ref.inner_index].use_count_estimate == 0) {
// Don't generate a shadowing name if one isn't needed
shadow_ref = Ref.None;
} else if (class.class_name) |_| {
@@ -14650,7 +14692,7 @@ pub fn NewParser(
// This is only done for function declarations that are not generators
// or async functions, since this is a backwards-compatibility hack from
// Annex B of the JavaScript standard.
- if (!p.current_scope.kindStopsHoisting() and p.symbols.items[data.func.name.?.ref.?.innerIndex()].kind == .hoisted_function) {
+ if (!p.current_scope.kindStopsHoisting() and p.symbols.items[data.func.name.?.ref.?.inner_index].kind == .hoisted_function) {
break :list_getter &before;
}
},
@@ -15296,7 +15338,7 @@ pub fn NewParser(
if (named_import.is_exported) continue;
}
- const named_export_symbol: Symbol = p.symbols.items[named_export_value.ref.innerIndex()];
+ const named_export_symbol: Symbol = p.symbols.items[named_export_value.ref.inner_index];
var export_name_string = export_name_string_remainder[0 .. named_export.key_ptr.len + "$$hmr_".len];
export_name_string_remainder = export_name_string_remainder[export_name_string.len..];
@@ -15576,10 +15618,10 @@ pub fn NewParser(
else
p.require_ref,
- .uses_module_ref = (p.symbols.items[p.module_ref.innerIndex()].use_count_estimate > 0),
- .uses_exports_ref = (p.symbols.items[p.exports_ref.innerIndex()].use_count_estimate > 0),
+ .uses_module_ref = (p.symbols.items[p.module_ref.inner_index].use_count_estimate > 0),
+ .uses_exports_ref = (p.symbols.items[p.exports_ref.inner_index].use_count_estimate > 0),
.uses_require_ref = if (p.runtime_imports.__require != null)
- (p.symbols.items[p.runtime_imports.__require.?.ref.innerIndex()].use_count_estimate > 0)
+ (p.symbols.items[p.runtime_imports.__require.?.ref.inner_index].use_count_estimate > 0)
else
false,
.symbol_pool = p.symbol_pool_node,
@@ -15635,7 +15677,6 @@ pub fn NewParser(
.source = source,
.macro = MacroState.init(allocator),
.current_scope = scope,
- .module_scope = scope,
.scopes_in_order = scope_order,
.needs_jsx_import = if (comptime only_scan_imports_and_do_not_visit) false else NeedsJSXType{},
.lexer = lexer,
diff --git a/src/js_printer.zig b/src/js_printer.zig
index 391450d09..2e90009cb 100644
--- a/src/js_printer.zig
+++ b/src/js_printer.zig
@@ -995,7 +995,7 @@ pub fn NewPrinter(
pub fn isUnboundEvalIdentifier(p: *Printer, value: Expr) bool {
switch (value.data) {
.e_identifier => |ident| {
- if (ident.ref.isSourceContentsSlice()) return false;
+ if (ident.ref.is_source_contents_slice) return false;
const symbol = p.symbols.get(p.symbols.follow(ident.ref)) orelse return false;
return symbol.kind == .unbound and strings.eqlComptime(symbol.original_name, "eval");
diff --git a/src/renamer.zig b/src/renamer.zig
index 1f11e1c15..991d111c1 100644
--- a/src/renamer.zig
+++ b/src/renamer.zig
@@ -25,8 +25,8 @@ pub const Renamer = struct {
}
pub fn nameForSymbol(renamer: *Renamer, ref: Ref) string {
- if (ref.isSourceContentsSlice()) {
- return renamer.source.contents[ref.sourceIndex() .. ref.sourceIndex() + ref.innerIndex()];
+ if (ref.is_source_contents_slice) {
+ return renamer.source.contents[ref.source_index .. ref.source_index + ref.inner_index];
}
const resolved = renamer.symbols.follow(ref);