aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bundler.zig5
-rw-r--r--src/js_ast.zig605
-rw-r--r--src/js_parser/js_parser.zig320
-rw-r--r--src/js_printer.zig161
4 files changed, 877 insertions, 214 deletions
diff --git a/src/bundler.zig b/src/bundler.zig
index 96ec6027c..4e68964df 100644
--- a/src/bundler.zig
+++ b/src/bundler.zig
@@ -244,9 +244,11 @@ pub const Bundler = struct {
else => {},
}
- return try bundler.print(
+ const output_file = try bundler.print(
result,
);
+ js_ast.Stmt.Data.Store.reset();
+ return output_file;
}
pub fn print(
@@ -284,6 +286,7 @@ pub const Bundler = struct {
js_printer.Options{ .to_module_ref = Ref.RuntimeRef },
&_linker,
);
+
return options.OutputFile{
.path = out_path,
.contents = print_result.js,
diff --git a/src/js_ast.zig b/src/js_ast.zig
index 4b65d8018..425ff6a83 100644
--- a/src/js_ast.zig
+++ b/src/js_ast.zig
@@ -6,6 +6,7 @@ usingnamespace @import("global.zig");
usingnamespace @import("ast/base.zig");
const ImportRecord = @import("import_record.zig").ImportRecord;
+const allocators = @import("allocators.zig");
// There are three types.
// 1. Expr (expression)
@@ -1071,6 +1072,106 @@ pub const Stmt = struct {
var None = S.Empty{};
+ pub inline fn getBlock(self: *const @This()) *S.Block {
+ return Data.Store.Block.at(self.data.s_block);
+ }
+ pub inline fn getBreak(self: *const @This()) *S.Break {
+ return Data.Store.Break.at(self.data.s_break);
+ }
+ pub inline fn getClass(self: *const @This()) *S.Class {
+ return Data.Store.Class.at(self.data.s_class);
+ }
+ pub inline fn getComment(self: *const @This()) *S.Comment {
+ return Data.Store.Comment.at(self.data.s_comment);
+ }
+ pub inline fn getContinue(self: *const @This()) *S.Continue {
+ return Data.Store.Continue.at(self.data.s_continue);
+ }
+ pub inline fn getDebugger(self: *const @This()) S.Debugger {
+ return S.Debugger{};
+ }
+ pub inline fn getDirective(self: *const @This()) *S.Directive {
+ return Data.Store.Directive.at(self.data.s_directive);
+ }
+ pub inline fn getDoWhile(self: *const @This()) *S.DoWhile {
+ return Data.Store.DoWhile.at(self.data.s_do_while);
+ }
+ pub inline fn getEmpty(self: *const @This()) S.Empty {
+ return S.Empty{};
+ }
+ pub inline fn getEnum(self: *const @This()) *S.Enum {
+ return Data.Store.Enum.at(self.data.s_enum);
+ }
+ pub inline fn getExportClause(self: *const @This()) *S.ExportClause {
+ return Data.Store.ExportClause.at(self.data.s_export_clause);
+ }
+ pub inline fn getExportDefault(self: *const @This()) *S.ExportDefault {
+ return Data.Store.ExportDefault.at(self.data.s_export_default);
+ }
+ pub inline fn getExportEquals(self: *const @This()) *S.ExportEquals {
+ return Data.Store.ExportEquals.at(self.data.s_export_equals);
+ }
+ pub inline fn getExportFrom(self: *const @This()) *S.ExportFrom {
+ return Data.Store.ExportFrom.at(self.data.s_export_from);
+ }
+ pub inline fn getExportStar(self: *const @This()) *S.ExportStar {
+ return Data.Store.ExportStar.at(self.data.s_export_star);
+ }
+ pub inline fn getExpr(self: *const @This()) *S.SExpr {
+ return Data.Store.SExpr.at(self.data.s_expr);
+ }
+ pub inline fn getForIn(self: *const @This()) *S.ForIn {
+ return Data.Store.ForIn.at(self.data.s_for_in);
+ }
+ pub inline fn getForOf(self: *const @This()) *S.ForOf {
+ return Data.Store.ForOf.at(self.data.s_for_of);
+ }
+ pub inline fn getFor(self: *const @This()) *S.For {
+ return Data.Store.For.at(self.data.s_for);
+ }
+ pub inline fn getFunction(self: *const @This()) *S.Function {
+ return Data.Store.Function.at(self.data.s_function);
+ }
+ pub inline fn getIf(self: *const @This()) *S.If {
+ return Data.Store.If.at(self.data.s_if);
+ }
+ pub inline fn getImport(self: *const @This()) *S.Import {
+ return Data.Store.Import.at(self.data.s_import);
+ }
+ pub inline fn getLabel(self: *const @This()) *S.Label {
+ return Data.Store.Label.at(self.data.s_label);
+ }
+ pub inline fn getLazyExport(self: *const @This()) *S.LazyExport {
+ return Data.Store.LazyExport.at(self.data.s_lazy_export);
+ }
+ pub inline fn getLocal(self: *const @This()) *S.Local {
+ return Data.Store.Local.at(self.data.s_local);
+ }
+ pub inline fn getNamespace(self: *const @This()) *S.Namespace {
+ return Data.Store.Namespace.at(self.data.s_namespace);
+ }
+ pub inline fn getReturn(self: *const @This()) *S.Return {
+ return Data.Store.Return.at(self.data.s_return);
+ }
+ pub inline fn getSwitch(self: *const @This()) *S.Switch {
+ return Data.Store.Switch.at(self.data.s_switch);
+ }
+ pub inline fn getThrow(self: *const @This()) *S.Throw {
+ return Data.Store.Throw.at(self.data.s_throw);
+ }
+ pub inline fn getTry(self: *const @This()) *S.Try {
+ return Data.Store.Try.at(self.data.s_try);
+ }
+ pub inline fn getTypeScript(self: *const @This()) S.TypeScript {
+ return S.TypeScript{};
+ }
+ pub inline fn getWhile(self: *const @This()) *S.While {
+ return Data.Store.While.at(self.data.s_while);
+ }
+ pub inline fn getWith(self: *const @This()) *S.With {
+ return Data.Store.With.at(self.data.s_with);
+ }
+
pub fn init(origData: anytype, loc: logger.Loc) Stmt {
if (@typeInfo(@TypeOf(origData)) != .Pointer and @TypeOf(origData) != S.Empty) {
@compileError("Stmt.init needs a pointer.");
@@ -1186,9 +1287,7 @@ pub const Stmt = struct {
}
}
inline fn comptime_alloc(allocator: *std.mem.Allocator, comptime tag_name: string, comptime typename: type, origData: anytype, loc: logger.Loc) Stmt {
- var st = allocator.create(typename) catch unreachable;
- st.* = origData;
- return Stmt{ .loc = loc, .data = @unionInit(Data, tag_name, st) };
+ return Stmt{ .loc = loc, .data = @unionInit(Data, tag_name, Data.Store.append(typename, origData)) };
}
inline fn comptime_init(comptime tag_name: string, comptime typename: type, origData: anytype, loc: logger.Loc) Stmt {
@@ -1213,7 +1312,7 @@ pub const Stmt = struct {
return Stmt.comptime_alloc(allocator, "s_continue", S.Continue, origData, loc);
},
S.Debugger => {
- return Stmt.comptime_alloc(allocator, "s_debugger", S.Debugger, origData, loc);
+ return Stmt{ .loc = loc, .data = .{ .s_debugger = origData } };
},
S.Directive => {
return Stmt.comptime_alloc(allocator, "s_directive", S.Directive, origData, loc);
@@ -1288,7 +1387,7 @@ pub const Stmt = struct {
return Stmt.comptime_alloc(allocator, "s_try", S.Try, origData, loc);
},
S.TypeScript => {
- return Stmt.comptime_alloc(allocator, "s_type_script", S.TypeScript, origData, loc);
+ return Stmt{ .loc = loc, .data = Data{ .s_type_script = S.TypeScript{} } };
},
S.While => {
return Stmt.comptime_alloc(allocator, "s_while", S.While, origData, loc);
@@ -1340,39 +1439,469 @@ pub const Stmt = struct {
};
pub const Data = union(Tag) {
- s_block: *S.Block,
- s_break: *S.Break,
- s_class: *S.Class,
- s_comment: *S.Comment,
- s_continue: *S.Continue,
- s_debugger: *S.Debugger,
- s_directive: *S.Directive,
- s_do_while: *S.DoWhile,
- s_empty: S.Empty,
- s_enum: *S.Enum,
- s_export_clause: *S.ExportClause,
- s_export_default: *S.ExportDefault,
- s_export_equals: *S.ExportEquals,
- s_export_from: *S.ExportFrom,
- s_export_star: *S.ExportStar,
- s_expr: *S.SExpr,
- s_for_in: *S.ForIn,
- s_for_of: *S.ForOf,
- s_for: *S.For,
- s_function: *S.Function,
- s_if: *S.If,
- s_import: *S.Import,
- s_label: *S.Label,
- s_lazy_export: *S.LazyExport,
- s_local: *S.Local,
- s_namespace: *S.Namespace,
- s_return: *S.Return,
- s_switch: *S.Switch,
- s_throw: *S.Throw,
- s_try: *S.Try,
- s_type_script: *S.TypeScript,
- s_while: *S.While,
- s_with: *S.With,
+ s_block: Store.ListIndex,
+ s_break: Store.ListIndex,
+ s_class: Store.ListIndex,
+ s_comment: Store.ListIndex,
+ s_continue: Store.ListIndex,
+ s_debugger: S.Debugger,
+ s_directive: Store.ListIndex,
+ s_do_while: Store.ListIndex,
+ s_empty: S.Empty, // special case, its a zero value type
+ s_enum: Store.ListIndex,
+ s_export_clause: Store.ListIndex,
+ s_export_default: Store.ListIndex,
+ s_export_equals: Store.ListIndex,
+ s_export_from: Store.ListIndex,
+ s_export_star: Store.ListIndex,
+ s_expr: Store.ListIndex,
+ s_for_in: Store.ListIndex,
+ s_for_of: Store.ListIndex,
+ s_for: Store.ListIndex,
+ s_function: Store.ListIndex,
+ s_if: Store.ListIndex,
+ s_import: Store.ListIndex,
+ s_label: Store.ListIndex,
+ s_lazy_export: Store.ListIndex,
+ s_local: Store.ListIndex,
+ s_namespace: Store.ListIndex,
+ s_return: Store.ListIndex,
+ s_switch: Store.ListIndex,
+ s_throw: Store.ListIndex,
+ s_try: Store.ListIndex,
+ s_type_script: S.TypeScript,
+ s_while: Store.ListIndex,
+ s_with: Store.ListIndex,
+
+ pub const Store = struct {
+ pub const ListIndex = packed struct {
+ index: u31,
+ is_overflowing: bool = false,
+ };
+
+ pub const Block = NewStore(S.Block);
+ pub const Break = NewStore(S.Break);
+ pub const Class = NewStore(S.Class);
+ pub const Comment = NewStore(S.Comment);
+ pub const Continue = NewStore(S.Continue);
+ pub const Directive = NewStore(S.Directive);
+ pub const DoWhile = NewStore(S.DoWhile);
+ pub const Enum = NewStore(S.Enum);
+ pub const ExportClause = NewStore(S.ExportClause);
+ pub const ExportDefault = NewStore(S.ExportDefault);
+ pub const ExportEquals = NewStore(S.ExportEquals);
+ pub const ExportFrom = NewStore(S.ExportFrom);
+ pub const ExportStar = NewStore(S.ExportStar);
+ pub const SExpr = NewStore(S.SExpr);
+ pub const ForIn = NewStore(S.ForIn);
+ pub const ForOf = NewStore(S.ForOf);
+ pub const For = NewStore(S.For);
+ pub const Function = NewStore(S.Function);
+ pub const If = NewStore(S.If);
+ pub const Import = NewStore(S.Import);
+ pub const Label = NewStore(S.Label);
+ pub const LazyExport = NewStore(S.LazyExport);
+ pub const Local = NewStore(S.Local);
+ pub const Namespace = NewStore(S.Namespace);
+ pub const Return = NewStore(S.Return);
+ pub const Switch = NewStore(S.Switch);
+ pub const Throw = NewStore(S.Throw);
+ pub const Try = NewStore(S.Try);
+ pub const TypeScript = NewStore(S.TypeScript);
+ pub const While = NewStore(S.While);
+ pub const With = NewStore(S.With);
+
+ threadlocal var has_inited = false;
+ pub fn create(allocator: *std.mem.Allocator) void {
+ if (has_inited) {
+ return;
+ }
+
+ has_inited = true;
+ _ = Block.init(allocator);
+ _ = Break.init(allocator);
+ _ = Class.init(allocator);
+ _ = Comment.init(allocator);
+ _ = Continue.init(allocator);
+ _ = Directive.init(allocator);
+ _ = DoWhile.init(allocator);
+ _ = Enum.init(allocator);
+ _ = ExportClause.init(allocator);
+ _ = ExportDefault.init(allocator);
+ _ = ExportEquals.init(allocator);
+ _ = ExportFrom.init(allocator);
+ _ = ExportStar.init(allocator);
+ _ = SExpr.init(allocator);
+ _ = ForIn.init(allocator);
+ _ = ForOf.init(allocator);
+ _ = For.init(allocator);
+ _ = Function.init(allocator);
+ _ = If.init(allocator);
+ _ = Import.init(allocator);
+ _ = Label.init(allocator);
+ _ = LazyExport.init(allocator);
+ _ = Local.init(allocator);
+ _ = Namespace.init(allocator);
+ _ = Return.init(allocator);
+ _ = Switch.init(allocator);
+ _ = Throw.init(allocator);
+ _ = Try.init(allocator);
+ _ = While.init(allocator);
+ _ = With.init(allocator);
+ }
+
+ pub fn reset() void {
+ Block.reset();
+ Break.reset();
+ Class.reset();
+ Comment.reset();
+ Continue.reset();
+ Directive.reset();
+ DoWhile.reset();
+ Enum.reset();
+ ExportClause.reset();
+ ExportDefault.reset();
+ ExportEquals.reset();
+ ExportFrom.reset();
+ ExportStar.reset();
+ SExpr.reset();
+ ForIn.reset();
+ ForOf.reset();
+ For.reset();
+ Function.reset();
+ If.reset();
+ Import.reset();
+ Label.reset();
+ LazyExport.reset();
+ Local.reset();
+ Namespace.reset();
+ Return.reset();
+ Switch.reset();
+ Throw.reset();
+ Try.reset();
+ While.reset();
+ With.reset();
+ }
+
+ pub fn append(comptime ValueType: type, value: anytype) ListIndex {
+ switch (comptime ValueType) {
+ S.Block => {
+ return Block.append(value);
+ },
+ S.Break => {
+ return Break.append(value);
+ },
+ S.Class => {
+ return Class.append(value);
+ },
+ S.Comment => {
+ return Comment.append(value);
+ },
+ S.Continue => {
+ return Continue.append(value);
+ },
+
+ S.Directive => {
+ return Directive.append(value);
+ },
+ S.DoWhile => {
+ return DoWhile.append(value);
+ },
+ S.Empty => {
+ return Empty.append(value);
+ },
+ S.Enum => {
+ return Enum.append(value);
+ },
+ S.ExportClause => {
+ return ExportClause.append(value);
+ },
+ S.ExportDefault => {
+ return ExportDefault.append(value);
+ },
+ S.ExportEquals => {
+ return ExportEquals.append(value);
+ },
+ S.ExportFrom => {
+ return ExportFrom.append(value);
+ },
+ S.ExportStar => {
+ return ExportStar.append(value);
+ },
+ S.SExpr => {
+ return SExpr.append(value);
+ },
+ S.ForIn => {
+ return ForIn.append(value);
+ },
+ S.ForOf => {
+ return ForOf.append(value);
+ },
+ S.For => {
+ return For.append(value);
+ },
+ S.Function => {
+ return Function.append(value);
+ },
+ S.If => {
+ return If.append(value);
+ },
+ S.Import => {
+ return Import.append(value);
+ },
+ S.Label => {
+ return Label.append(value);
+ },
+ S.LazyExport => {
+ return LazyExport.append(value);
+ },
+ S.Local => {
+ return Local.append(value);
+ },
+ S.Namespace => {
+ return Namespace.append(value);
+ },
+ S.Return => {
+ return Return.append(value);
+ },
+ S.Switch => {
+ return Switch.append(value);
+ },
+ S.Throw => {
+ return Throw.append(value);
+ },
+ S.Try => {
+ return Try.append(value);
+ },
+
+ S.While => {
+ return While.append(value);
+ },
+ S.With => {
+ return With.append(value);
+ },
+ else => {
+ @compileError("Invalid type passed to Stmt.Data.set " ++ @typeName(ValueType));
+ },
+ }
+ }
+
+ pub fn NewStore(comptime ValueType: type) type {
+ const count = 1024;
+ const max_index = count - 1;
+ const list_count = count;
+ return struct {
+ pub threadlocal var backing_buf: [count]ValueType = undefined;
+ pub threadlocal var backing_buf_used: u16 = 0;
+ const Allocator = std.mem.Allocator;
+ const Self = @This();
+ const NotFound = allocators.NotFound;
+ const Unassigned = allocators.Unassigned;
+
+ overflow_list: std.ArrayListUnmanaged(ValueType),
+ allocator: *Allocator,
+
+ pub threadlocal var instance: Self = undefined;
+ pub threadlocal var self: *Self = undefined;
+
+ pub fn reset() void {
+ backing_buf_used = 0;
+ self.overflow_list.shrinkRetainingCapacity(0);
+ }
+
+ pub fn init(allocator: *std.mem.Allocator) *Self {
+ instance = Self{
+ .allocator = allocator,
+ .overflow_list = std.ArrayListUnmanaged(ValueType){},
+ };
+
+ self = &instance;
+ return self;
+ }
+
+ pub fn isOverflowing() bool {
+ return backing_buf_used >= @as(u16, count);
+ }
+
+ pub fn at(index: ListIndex) *ValueType {
+ std.debug.assert(index.index != NotFound.index and index.index != Unassigned.index);
+
+ if (index.is_overflowing) {
+ return &self.overflow_list.items[index.index];
+ } else {
+ return &backing_buf[index.index];
+ }
+ }
+
+ pub fn exists(value: ValueType) bool {
+ return isSliceInBuffer(value, backing_buf);
+ }
+
+ pub fn append(value: ValueType) ListIndex {
+ var result = ListIndex{ .index = std.math.maxInt(u31), .is_overflowing = backing_buf_used > max_index };
+ if (result.is_overflowing) {
+ result.index = @intCast(u31, self.overflow_list.items.len);
+ self.overflow_list.append(self.allocator, value) catch unreachable;
+ } else {
+ result.index = backing_buf_used;
+ backing_buf[result.index] = value;
+ backing_buf_used += 1;
+ if (backing_buf_used >= max_index) {
+ self.overflow_list = @TypeOf(self.overflow_list).initCapacity(self.allocator, count) catch unreachable;
+ }
+ }
+
+ return result;
+ }
+
+ pub fn update(result: *ListIndex, value: ValueType) !*ValueType {
+ if (result.index.index == NotFound.index or result.index.index == Unassigned.index) {
+ result.index.is_overflowing = backing_buf_used > max_index;
+ if (result.index.is_overflowing) {
+ result.index.index = @intCast(u31, self.overflow_list.items.len);
+ } else {
+ result.index.index = backing_buf_used;
+ backing_buf_used += 1;
+ if (backing_buf_used >= max_index) {
+ self.overflow_list = try @TypeOf(self.overflow_list).initCapacity(self.allocator, count);
+ }
+ }
+ }
+
+ if (result.index.is_overflowing) {
+ if (self.overflow_list.items.len == result.index.index) {
+ const real_index = self.overflow_list.items.len;
+ try self.overflow_list.append(self.allocator, value);
+ } else {
+ self.overflow_list.items[result.index.index] = value;
+ }
+
+ return &self.overflow_list.items[result.index.index];
+ } else {
+ backing_buf[result.index.index] = value;
+
+ return &backing_buf[result.index.index];
+ }
+ }
+ };
+ }
+ };
+
+ pub inline fn set(data: *Data, value: anytype) void {
+ const ValueType = @TypeOf(value);
+ if (@typeInfo(ValueType) == .Pointer) {
+ data.setValue(@TypeOf(value.*), value.*);
+ } else {
+ data.setValue(@TypeOf(value), value);
+ }
+ }
+
+ pub inline fn setValue(data: *Data, comptime ValueType: type, value: ValueType) void {
+ switch (comptime ValueType) {
+ S.Block => {
+ data.s_block = Block.append(value);
+ },
+ S.Break => {
+ data.s_break = Break.append(value);
+ },
+ S.Class => {
+ data.s_class = Class.append(value);
+ },
+ S.Comment => {
+ data.s_comment = Comment.append(value);
+ },
+ S.Continue => {
+ data.s_continue = Continue.append(value);
+ },
+ S.Debugger => {
+ data.s_debugger = Debugger.append(value);
+ },
+ S.Directive => {
+ data.s_directive = Directive.append(value);
+ },
+ S.DoWhile => {
+ data.s_do_while = DoWhile.append(value);
+ },
+ S.Empty => {
+ data.s_empty = Empty.append(value);
+ },
+ S.Enum => {
+ data.s_enum = Enum.append(value);
+ },
+ S.ExportClause => {
+ data.s_export_clause = ExportClause.append(value);
+ },
+ S.ExportDefault => {
+ data.s_export_default = ExportDefault.append(value);
+ },
+ S.ExportEquals => {
+ data.s_export_equals = ExportEquals.append(value);
+ },
+ S.ExportFrom => {
+ data.s_export_from = ExportFrom.append(value);
+ },
+ S.ExportStar => {
+ data.s_export_star = ExportStar.append(value);
+ },
+ S.SExpr => {
+ data.s_s_expr = SExpr.append(value);
+ },
+ S.ForIn => {
+ data.s_for_in = ForIn.append(value);
+ },
+ S.ForOf => {
+ data.s_for_of = ForOf.append(value);
+ },
+ S.For => {
+ data.s_for = For.append(value);
+ },
+ S.Function => {
+ data.s_function = Function.append(value);
+ },
+ S.If => {
+ data.s_if = If.append(value);
+ },
+ S.Import => {
+ data.s_import = Import.append(value);
+ },
+ S.Label => {
+ data.s_label = Label.append(value);
+ },
+ S.LazyExport => {
+ data.s_lazy_export = LazyExport.append(value);
+ },
+ S.Local => {
+ data.s_local = Local.append(value);
+ },
+ S.Namespace => {
+ data.s_namespace = Namespace.append(value);
+ },
+ S.Return => {
+ data.s_return = Return.append(value);
+ },
+ S.Switch => {
+ data.s_switch = Switch.append(value);
+ },
+ S.Throw => {
+ data.s_throw = Throw.append(value);
+ },
+ S.Try => {
+ data.s_try = Try.append(value);
+ },
+ S.TypeScript => {
+ data.s_type_script = value;
+ },
+ S.While => {
+ data.s_while = While.append(value);
+ },
+ S.With => {
+ data.s_with = With.append(value);
+ },
+ else => {
+ @compileError("Invalid type passed to Stmt.Data.set " ++ @typeName(ValueType));
+ },
+ }
+ }
};
pub fn caresAboutScope(self: *Stmt) bool {
diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig
index 6776dba7b..63e135295 100644
--- a/src/js_parser/js_parser.zig
+++ b/src/js_parser/js_parser.zig
@@ -53,7 +53,9 @@ pub const ImportScanner = struct {
// zls needs the hint, it seems.
const stmt: Stmt = _stmt;
switch (stmt.data) {
- .s_import => |st| {
+ .s_import => {
+ var st = stmt.getImport();
+
var record: ImportRecord = p.import_records.items[st.import_record_index];
// The official TypeScript compiler always removes unused imported
@@ -364,7 +366,9 @@ pub const ImportScanner = struct {
}
}
},
- .s_function => |st| {
+ .s_function => {
+ var st = stmt.getFunction();
+
if (st.func.flags.is_export) {
if (st.func.name) |name| {
try p.recordExport(name.loc, p.symbols.items[name.ref.?.inner_index].original_name, name.ref.?);
@@ -373,7 +377,9 @@ pub const ImportScanner = struct {
}
}
},
- .s_class => |st| {
+ .s_class => {
+ var st = stmt.getClass();
+
if (st.is_export) {
if (st.class.class_name) |name| {
try p.recordExport(name.loc, p.symbols.items[name.ref.?.inner_index].original_name, name.ref.?);
@@ -382,7 +388,9 @@ pub const ImportScanner = struct {
}
}
},
- .s_local => |st| {
+ .s_local => {
+ var st = stmt.getLocal();
+
if (st.is_export) {
for (st.decls) |decl| {
p.recordExportedBinding(decl.binding);
@@ -422,15 +430,21 @@ pub const ImportScanner = struct {
}
}
},
- .s_export_default => |st| {
+ .s_export_default => {
+ var st = stmt.getExportDefault();
+
try p.recordExport(st.default_name.loc, "default", st.default_name.ref.?);
},
- .s_export_clause => |st| {
+ .s_export_clause => {
+ var st = stmt.getExportClause();
+
for (st.items) |item| {
try p.recordExport(item.alias_loc, item.alias, item.name.ref.?);
}
},
- .s_export_star => |st| {
+ .s_export_star => {
+ var st = stmt.getExportStar();
+
try p.import_records_for_current_part.append(st.import_record_index);
if (st.alias) |alias| {
@@ -449,7 +463,9 @@ pub const ImportScanner = struct {
try p.export_star_import_records.append(st.import_record_index);
}
},
- .s_export_from => |st| {
+ .s_export_from => {
+ var st = stmt.getExportFrom();
+
try p.import_records_for_current_part.append(st.import_record_index);
for (st.items) |item| {
@@ -606,7 +622,9 @@ pub const SideEffects = enum(u2) {
return false;
},
- .s_local => |local| {
+ .s_local => |local__| {
+ var local = stmt.getLocal();
+
return local.kind != .k_var;
// if (local.kind != .k_var) {
// // Omit these statements entirely
@@ -614,8 +632,8 @@ pub const SideEffects = enum(u2) {
// }
},
- .s_block => |block| {
- for (block.stmts) |child| {
+ .s_block => {
+ for (stmt.getBlock().stmts) |child| {
if (shouldKeepStmtInDeadControlFlow(child)) {
return true;
}
@@ -624,7 +642,8 @@ pub const SideEffects = enum(u2) {
return false;
},
- .s_if => |_if_| {
+ .s_if => {
+ const _if_ = stmt.getIf();
if (shouldKeepStmtInDeadControlFlow(_if_.yes)) {
return true;
}
@@ -634,15 +653,16 @@ pub const SideEffects = enum(u2) {
return shouldKeepStmtInDeadControlFlow(no);
},
- .s_while => |__while__| {
- return shouldKeepStmtInDeadControlFlow(__while__.body);
+ .s_while => {
+ return shouldKeepStmtInDeadControlFlow(stmt.getWhile().body);
},
- .s_do_while => |__while__| {
- return shouldKeepStmtInDeadControlFlow(__while__.body);
+ .s_do_while => {
+ return shouldKeepStmtInDeadControlFlow(stmt.getDoWhile().body);
},
- .s_for => |__for__| {
+ .s_for => {
+ const __for__ = stmt.getFor();
if (__for__.init) |init_| {
if (shouldKeepStmtInDeadControlFlow(init_)) {
return true;
@@ -652,15 +672,20 @@ pub const SideEffects = enum(u2) {
return shouldKeepStmtInDeadControlFlow(__for__.body);
},
- .s_for_in => |__for__| {
+ .s_for_in => {
+ const __for__ = stmt.getForIn();
return shouldKeepStmtInDeadControlFlow(__for__.init) or shouldKeepStmtInDeadControlFlow(__for__.body);
},
- .s_for_of => |__for__| {
+ .s_for_of => {
+ const __for__ = stmt.getForOf();
+
return shouldKeepStmtInDeadControlFlow(__for__.init) or shouldKeepStmtInDeadControlFlow(__for__.body);
},
- .s_label => |label| {
+ .s_label => {
+ const label = stmt.getLabel();
+
return shouldKeepStmtInDeadControlFlow(label.stmt);
},
else => {
@@ -1071,8 +1096,8 @@ fn statementCaresAboutScope(stmt: Stmt) bool {
=> {
return false;
},
- .s_local => |s| {
- return s.kind != .k_var;
+ .s_local => {
+ return stmt.getLocal().kind != .k_var;
},
else => {
return true;
@@ -1525,42 +1550,6 @@ pub const Parser = struct {
}
}
- // for (stmts) |stmt| {
- // var _stmts = ([_]Stmt{stmt});
-
- // switch (stmt.data) {
- // // Split up top-level multi-declaration variable statements
-
- // .s_local => |local| {
- // for (local.decls) |decl| {
- // var decls = try p.allocator.alloc(Decl, 1);
- // var clone = S.Local{
- // .kind = local.kind,
- // .decls = decls,
- // .is_export = local.is_export,
- // .was_ts_import_equals = local.was_ts_import_equals,
- // };
- // _stmts[0] = p.s(clone, stmt.loc);
-
- // try p.appendPart(&parts, &_stmts);
- // }
- // },
- // // Move imports (and import-like exports) to the top of the file to
- // // ensure that if they are converted to a require() call, the effects
- // // will take place before any other statements are evaluated.
- // .s_import, .s_export_from, .s_export_star => {
- // try p.appendPart(&before, &_stmts);
- // },
-
- // .s_export_equals => {
- // try p.appendPart(&after, &_stmts);
- // },
- // else => {
- // try p.appendPart(&parts, &_stmts);
- // },
- // }
- // }
- // p.popScope();
var parts_slice: []js_ast.Part = &([_]js_ast.Part{});
if (before.items.len > 0 or after.items.len > 0) {
@@ -3997,7 +3986,7 @@ pub const P = struct {
return stmt;
}
- if (stmt.data.s_function.func.name) |name| {
+ if (stmt.getFunction().func.name) |name| {
defaultName = js_ast.LocRef{ .loc = defaultLoc, .ref = name.ref };
} else {
defaultName = try p.createDefaultName(defaultLoc);
@@ -4033,12 +4022,12 @@ pub const P = struct {
},
.s_function => |func_container| {
- if (func_container.func.name) |name| {
+ if (stmt.getFunction().func.name) |name| {
break :default_name_getter LocRef{ .loc = defaultLoc, .ref = name.ref };
} else {}
},
.s_class => |class| {
- if (class.class.class_name) |name| {
+ if (stmt.getClass().class.class_name) |name| {
break :default_name_getter LocRef{ .loc = defaultLoc, .ref = name.ref };
} else {}
},
@@ -4077,12 +4066,12 @@ pub const P = struct {
},
.s_function => |func_container| {
- if (func_container.func.name) |_name| {
+ if (stmt.getFunction().func.name) |_name| {
break :default_name_getter LocRef{ .loc = defaultLoc, .ref = _name.ref };
} else {}
},
.s_class => |class| {
- if (class.class.class_name) |_name| {
+ if (stmt.getClass().class.class_name) |_name| {
break :default_name_getter LocRef{ .loc = defaultLoc, .ref = _name.ref };
} else {}
},
@@ -4578,8 +4567,8 @@ pub const P = struct {
// Only require "const" statement initializers when we know we're a normal for loop
if (init_) |init_stmt| {
switch (init_stmt.data) {
- .s_local => |local| {
- if (local.kind == .k_const) {
+ .s_local => {
+ if (init_stmt.getLocal().kind == .k_const) {
try p.requireInitializers(decls);
}
},
@@ -5006,7 +4995,8 @@ pub const P = struct {
if (opts.is_namespace_scope and opts.is_export) {
var decls: []G.Decl = &([_]G.Decl{});
switch (stmt.data) {
- .s_local => |local| {
+ .s_local => {
+ const local = stmt.getLocal();
var _decls = try List(G.Decl).initCapacity(p.allocator, local.decls.len);
for (local.decls) |decl| {
try extractDeclsForBinding(decl.binding, &_decls);
@@ -5136,7 +5126,9 @@ pub const P = struct {
const _stmts: []Stmt = stmts.items;
for (_stmts) |stmt| {
switch (stmt.data) {
- .s_local => |local| {
+ .s_local => |local__| {
+ var local = stmt.getLocal();
+
if (local.was_ts_import_equals and !local.is_export) {
import_equal_count += 1;
}
@@ -5978,15 +5970,15 @@ pub const P = struct {
isDirectivePrologue = false;
switch (stmt.data) {
.s_expr => |expr| {
- switch (expr.value.data) {
+ switch (stmt.getExpr().value.data) {
.e_string => |str| {
if (!str.prefer_template) {
- stmt.data = Stmt.Data{
- .s_directive = p.m(S.Directive{
- .value = str.value,
- // .legacy_octal_loc = str.legacy_octal_loc,
- }),
- };
+ // stmt.data = Stmt.Data{
+ // .s_directive = p.m(S.Directive{
+ // .value = str.value,
+ // // .legacy_octal_loc = str.legacy_octal_loc,
+ // }),
+ // };
isDirectivePrologue = true;
if (strings.eqlUtf16("use strict", str.value)) {
@@ -6011,7 +6003,9 @@ pub const P = struct {
if (!p.options.suppress_warnings_about_weird_code) {
var needsCheck = true;
switch (stmt.data) {
- .s_return => |ret| {
+ .s_return => |retu| {
+ const ret = stmt.getReturn();
+
if (ret.value == null and !p.latest_return_had_semicolon) {
returnWithoutSemicolonStart = stmt.loc.start;
needsCheck = false;
@@ -9169,13 +9163,19 @@ pub const P = struct {
// check if the imported file is marked as "sideEffects: false" before we
// can remove a SImport statement. Otherwise the import must be kept for
// its side effects.
- .s_import => |st| {},
- .s_class => |st| {
+ .s_import => {
+ var st = stmt.getImport();
+ },
+ .s_class => {
+ var st = stmt.getClass();
+
if (!p.classCanBeRemovedIfUnused(&st.class)) {
return false;
}
},
- .s_expr => |st| {
+ .s_expr => {
+ var st = stmt.getExpr();
+
if (st.does_not_affect_tree_shaking) {
// Expressions marked with this are automatically generated and have
// no side effects by construction.
@@ -9184,7 +9184,9 @@ pub const P = struct {
return false;
}
},
- .s_local => |st| {
+ .s_local => {
+ var st = stmt.getLocal();
+
for (st.decls) |decl| {
if (!p.bindingCanBeRemovedIfUnused(decl.binding)) {
return false;
@@ -9201,14 +9203,16 @@ pub const P = struct {
// Exports are tracked separately, so this isn't necessary
.s_export_clause, .s_export_from => {},
- .s_export_default => |st| {
+ .s_export_default => {
+ var st = stmt.getExportDefault();
+
switch (st.value) {
.stmt => |s2| {
switch (s2.data) {
// These never have side effects
.s_function => {},
- .s_class => |class| {
- if (!p.classCanBeRemovedIfUnused(&class.class)) {
+ .s_class => {
+ if (!p.classCanBeRemovedIfUnused(&stmt.getClass().class)) {
return false;
}
},
@@ -10393,7 +10397,8 @@ pub const P = struct {
.s_comment => {
continue;
},
- .s_directive => |dir| {
+ .s_directive => {
+ const dir = stmt.getDirective();
if (strings.utf16EqlString(dir.value, "use strict")) {
return stmt.loc;
}
@@ -10704,17 +10709,23 @@ pub const P = struct {
// These don't contain anything to traverse
.s_debugger, .s_empty, .s_comment => {},
- .s_type_script => |data| {
+ .s_type_script => {
+ var data = stmt.getTypeScript();
+
// Erase TypeScript constructs from the output completely
return;
},
- .s_directive => |data| {
+ .s_directive => {
+ var data = stmt.getDirective();
+
// if p.isStrictMode() && s.LegacyOctalLoc.Start > 0 {
// p.markStrictModeFeature(legacyOctalEscape, p.source.RangeOfLegacyOctalEscape(s.LegacyOctalLoc), "")
// }
return;
},
- .s_import => |data| {
+ .s_import => {
+ var data = stmt.getImport();
+
try p.recordDeclaredSymbol(data.namespace_ref);
if (data.default_name) |default_name| {
@@ -10727,7 +10738,9 @@ pub const P = struct {
}
}
},
- .s_export_clause => |data| {
+ .s_export_clause => {
+ var data = stmt.getExportClause();
+
// "export {foo}"
var end: usize = 0;
for (data.items) |*item| {
@@ -10755,7 +10768,9 @@ pub const P = struct {
// jarred: does that mean we can remove them here, since we're not bundling for production?
data.items = data.items[0..end];
},
- .s_export_from => |data| {
+ .s_export_from => {
+ var data = stmt.getExportFrom();
+
// "export {foo} from 'path'"
const name = p.loadNameFromRef(data.namespace_ref);
data.namespace_ref = try p.newSymbol(.other, name);
@@ -10771,7 +10786,9 @@ pub const P = struct {
item.name.ref = ref;
}
},
- .s_export_star => |data| {
+ .s_export_star => {
+ var data = stmt.getExportStar();
+
// "export {foo} from 'path'"
const name = p.loadNameFromRef(data.namespace_ref);
data.namespace_ref = try p.newSymbol(.other, name);
@@ -10795,7 +10812,9 @@ pub const P = struct {
stmts.appendAssumeCapacity(p.s(S.ExportClause{ .items = items.toOwnedSlice(), .is_single_line = true }, stmt.loc));
}
},
- .s_export_default => |data| {
+ .s_export_default => {
+ var data = stmt.getExportDefault();
+
if (data.default_name.ref) |ref| {
try p.recordDeclaredSymbol(ref);
}
@@ -10828,7 +10847,8 @@ pub const P = struct {
.stmt => |s2| {
switch (s2.data) {
- .s_function => |func| {
+ .s_function => {
+ var func = s2.getFunction();
var name: string = "";
if (func.func.name) |func_loc| {
name = p.loadNameFromRef(func_loc.ref.?);
@@ -10846,7 +10866,8 @@ pub const P = struct {
// prevent doubling export default function name
return;
},
- .s_class => |class| {
+ .s_class => {
+ var class = s2.getClass();
var shadow_ref = p.visitClass(s2.loc, &class.class);
stmts.appendSlice(p.lowerClass(js_ast.StmtOrExpr{ .stmt = stmt.* }, shadow_ref)) catch unreachable;
return;
@@ -10856,7 +10877,9 @@ pub const P = struct {
},
}
},
- .s_export_equals => |data| {
+ .s_export_equals => {
+ var data = stmt.getExportEquals();
+
// "module.exports = value"
stmts.append(
Expr.assignStmt(
@@ -10879,7 +10902,9 @@ pub const P = struct {
) catch unreachable;
p.recordUsage(p.module_ref);
},
- .s_break => |data| {
+ .s_break => {
+ var data = stmt.getBreak();
+
if (data.label) |*label| {
const name = p.loadNameFromRef(label.ref orelse p.panic("Expected label to have a ref", .{}));
const res = p.findLabelSymbol(label.loc, name);
@@ -10893,7 +10918,9 @@ pub const P = struct {
p.log.addRangeError(p.source, r, "Cannot use \"break\" here") catch unreachable;
}
},
- .s_continue => |data| {
+ .s_continue => {
+ var data = stmt.getContinue();
+
if (data.label) |*label| {
const name = p.loadNameFromRef(label.ref orelse p.panic("Expected continue label to have a ref", .{}));
const res = p.findLabelSymbol(label.loc, name);
@@ -10907,7 +10934,9 @@ pub const P = struct {
p.log.addRangeError(p.source, r, "Cannot use \"continue\" here") catch unreachable;
}
},
- .s_label => |data| {
+ .s_label => {
+ var data = stmt.getLabel();
+
p.pushScopeForVisitPass(.label, stmt.loc) catch unreachable;
const name = p.loadNameFromRef(data.name.ref orelse unreachable);
const ref = p.newSymbol(.label, name) catch unreachable;
@@ -10923,7 +10952,9 @@ pub const P = struct {
data.stmt = p.visitSingleStmt(data.stmt, StmtsKind.none);
p.popScope();
},
- .s_local => |data| {
+ .s_local => {
+ var data = stmt.getLocal();
+
for (data.decls) |*d| {
p.visitBinding(d.binding, null);
@@ -10968,16 +10999,22 @@ pub const P = struct {
// TODO: do we need to relocate vars? I don't think so.
if (data.kind == .k_var) {}
},
- .s_expr => |data| {
+ .s_expr => {
+ var data = stmt.getExpr();
+
p.stmt_expr_value = data.value.data;
data.value = p.visitExpr(data.value);
// simplify unused
data.value = SideEffects.simpifyUnusedExpr(p, data.value) orelse data.value.toEmpty();
},
- .s_throw => |data| {
+ .s_throw => {
+ var data = stmt.getThrow();
+
data.value = p.visitExpr(data.value);
},
- .s_return => |data| {
+ .s_return => {
+ var data = stmt.getReturn();
+
// Forbid top-level return inside modules with ECMAScript-style exports
if (p.fn_or_arrow_data_visit.is_outside_fn_or_arrow) {
const where = where: {
@@ -11005,7 +11042,9 @@ pub const P = struct {
}
}
},
- .s_block => |data| {
+ .s_block => {
+ var data = stmt.getBlock();
+
{
p.pushScopeForVisitPass(.block, stmt.loc) catch unreachable;
@@ -11031,22 +11070,30 @@ pub const P = struct {
stmts.append(stmt.*) catch unreachable;
return;
},
- .s_with => |data| {
+ .s_with => {
+ var data = stmt.getWith();
+
notimpl();
},
- .s_while => |data| {
+ .s_while => {
+ var data = stmt.getWhile();
+
data.test_ = p.visitExpr(data.test_);
data.body = p.visitLoopBody(data.body);
// TODO: simplify boolean expression
},
- .s_do_while => |data| {
+ .s_do_while => {
+ var data = stmt.getDoWhile();
+
data.test_ = p.visitExpr(data.test_);
data.body = p.visitLoopBody(data.body);
// TODO: simplify boolean expression
},
- .s_if => |data| {
+ .s_if => {
+ var data = stmt.getIf();
+
data.test_ = p.visitExpr(data.test_);
const effects = SideEffects.toBoolean(data.test_.data);
@@ -11076,7 +11123,9 @@ pub const P = struct {
}
}
},
- .s_for => |data| {
+ .s_for => {
+ var data = stmt.getFor();
+
{
p.pushScopeForVisitPass(.block, stmt.loc) catch unreachable;
@@ -11100,7 +11149,9 @@ pub const P = struct {
// TODO: Potentially relocate "var" declarations to the top level
},
- .s_for_in => |data| {
+ .s_for_in => {
+ var data = stmt.getForIn();
+
{
p.pushScopeForVisitPass(.block, stmt.loc) catch unreachable;
defer p.popScope();
@@ -11125,7 +11176,9 @@ pub const P = struct {
// }
}
},
- .s_for_of => |data| {
+ .s_for_of => {
+ var data = stmt.getForOf();
+
p.pushScopeForVisitPass(.block, stmt.loc) catch unreachable;
defer p.popScope();
_ = p.visitForLoopInit(data.init, true);
@@ -11142,7 +11195,9 @@ pub const P = struct {
// p.lowerObjectRestInForLoopInit(s.Init, &s.Body)
},
- .s_try => |data| {
+ .s_try => {
+ var data = stmt.getTry();
+
p.pushScopeForVisitPass(.block, stmt.loc) catch unreachable;
{
var _stmts = List(Stmt).fromOwnedSlice(p.allocator, data.body);
@@ -11176,7 +11231,9 @@ pub const P = struct {
p.popScope();
}
},
- .s_switch => |data| {
+ .s_switch => {
+ var data = stmt.getSwitch();
+
data.test_ = p.visitExpr(data.test_);
{
p.pushScopeForVisitPass(.block, data.body_loc) catch unreachable;
@@ -11201,7 +11258,9 @@ pub const P = struct {
// TODO: duplicate case checker
},
- .s_function => |data| {
+ .s_function => {
+ var data = stmt.getFunction();
+
data.func = p.visitFunc(data.func, data.func.open_parens_loc);
// Handle exporting this function from a namespace
@@ -11232,7 +11291,9 @@ pub const P = struct {
// );
return;
},
- .s_class => |data| {
+ .s_class => {
+ var data = stmt.getClass();
+
const shadow_ref = p.visitClass(stmt.loc, &data.class);
// Remove the export flag inside a namespace
@@ -11255,7 +11316,9 @@ pub const P = struct {
return;
},
- .s_enum => |data| {
+ .s_enum => {
+ var data = stmt.getEnum();
+
p.recordDeclaredSymbol(data.name.ref.?) catch unreachable;
p.pushScopeForVisitPass(.entry, stmt.loc) catch unreachable;
defer p.popScope();
@@ -11372,7 +11435,9 @@ pub const P = struct {
);
return;
},
- .s_namespace => |data| {
+ .s_namespace => {
+ var data = stmt.getNamespace();
+
p.recordDeclaredSymbol(data.name.ref.?) catch unreachable;
// Scan ahead for any variables inside this namespace. This must be done
@@ -11381,7 +11446,9 @@ pub const P = struct {
// We need to convert the uses into property accesses on the namespace.
for (data.stmts) |child_stmt| {
switch (child_stmt.data) {
- .s_local => |local| {
+ .s_local => |local__| {
+ var local = stmt.getLocal();
+
if (local.is_export) {
p.markExportedDeclsInsideNamespace(data.arg, local.decls);
}
@@ -11625,12 +11692,16 @@ pub const P = struct {
pub fn visitForLoopInit(p: *P, stmt: Stmt, is_in_or_of: bool) Stmt {
switch (stmt.data) {
- .s_expr => |st| {
+ .s_expr => {
+ var st = stmt.getExpr();
+
const assign_target = if (is_in_or_of) js_ast.AssignTarget.replace else js_ast.AssignTarget.none;
p.stmt_expr_value = st.value.data;
st.value = p.visitExprInOut(st.value, ExprIn{ .assign_target = assign_target });
},
- .s_local => |st| {
+ .s_local => {
+ var st = stmt.getLocal();
+
for (st.decls) |*dec| {
p.visitBinding(dec.binding, null);
if (dec.value) |val| {
@@ -11843,8 +11914,8 @@ pub const P = struct {
pub fn visitSingleStmt(p: *P, stmt: Stmt, kind: StmtsKind) Stmt {
const has_if_scope = has_if: {
switch (stmt.data) {
- .s_function => |func| {
- break :has_if func.func.flags.has_if_scope;
+ .s_function => {
+ break :has_if stmt.getFunction().func.flags.has_if_scope;
},
else => {
break :has_if false;
@@ -11874,7 +11945,7 @@ pub const P = struct {
return Stmt{ .data = Prefill.Data.SEmpty, .loc = loc };
}
- if (stmts.len == 1 and std.meta.activeTag(stmts[0].data) != .s_local or (std.meta.activeTag(stmts[0].data) == .s_local and stmts[0].data.s_local.kind == S.Local.Kind.k_var)) {
+ if (stmts.len == 1 and std.meta.activeTag(stmts[0].data) != .s_local or (std.meta.activeTag(stmts[0].data) == .s_local and stmts[0].getLocal().kind == S.Local.Kind.k_var)) {
// "let" and "const" must be put in a block when in a single-statement context
return stmts[0];
}
@@ -12080,7 +12151,8 @@ pub const P = struct {
// moves this statement to the end when it generates code.
break :list_getter &after;
},
- .s_function => |data| {
+ .s_function => {
+ var data = stmt.getFunction();
// Manually hoist block-level function declarations to preserve semantics.
// This is only done for function declarations that are not generators
// or async functions, since this is a backwards-compatibility hack from
@@ -12422,8 +12494,8 @@ pub const P = struct {
for (parts) |part| {
for (part.stmts) |stmt| {
switch (stmt.data) {
- .s_export_clause => |clause| {
- for (clause.items) |item| {
+ .s_export_clause => {
+ for (stmt.getExportClause().items) |item| {
if (p.named_imports.getEntry(item.name.ref.?)) |_import| {
_import.value.is_exported = true;
}
@@ -12531,6 +12603,8 @@ pub const P = struct {
}
pub fn init(allocator: *std.mem.Allocator, log: *logger.Log, source: *const logger.Source, define: *Define, lexer: js_lexer.Lexer, opts: Parser.Options) !*P {
+ Stmt.Data.Store.create(allocator);
+
var scope_order = try ScopeOrderList.initCapacity(allocator, 1);
var scope = try allocator.create(Scope);
scope.* = Scope{
diff --git a/src/js_printer.zig b/src/js_printer.zig
index efbb7aa90..a95d3e43a 100644
--- a/src/js_printer.zig
+++ b/src/js_printer.zig
@@ -319,7 +319,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
switch (stmt.data) {
.s_block => |block| {
p.printSpace();
- p.printBlock(stmt.loc, block.stmts);
+ p.printBlock(stmt.loc, stmt.getBlock().stmts);
p.printNewline();
},
else => {
@@ -1144,8 +1144,8 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
var wasPrinted = false;
if (e.body.stmts.len == 1 and e.prefer_expr) {
switch (e.body.stmts[0].data) {
- .s_return => |ret| {
- if (ret.value) |val| {
+ .s_return => {
+ if (e.body.stmts[0].getReturn().value) |val| {
p.arrow_expr_start = p.js.lenI();
p.printExpr(val, .comma, ExprFlag.None());
wasPrinted = true;
@@ -2060,12 +2060,14 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.comptime_flush();
p.addSourceMapping(stmt.loc);
-
switch (stmt.data) {
- .s_comment => |s| {
+ .s_comment => |s_list_index| {
+ const s = stmt.getComment();
p.printIndentedComment(s.text);
},
- .s_function => |s| {
+ .s_function => |s_list_index| {
+ const s = stmt.getFunction();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
if (s.func.flags.is_export) {
@@ -2086,7 +2088,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.printFunc(s.func);
p.printNewline();
},
- .s_class => |s| {
+ .s_class => |s_list_index| {
+ const s = stmt.getClass();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
if (s.is_export) {
@@ -2097,12 +2101,14 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.printClass(s.class);
p.printNewline();
},
- .s_empty => |s| {
+ .s_empty => |s_list_index| {
p.printIndent();
p.print(";");
p.printNewline();
},
- .s_export_default => |s| {
+ .s_export_default => |s_list_index| {
+ const s = stmt.getExportDefault();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
p.print("export default");
@@ -2119,7 +2125,8 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
},
.stmt => |s2| {
switch (s2.data) {
- .s_function => |func| {
+ .s_function => {
+ const func = s2.getFunction();
p.printSpaceBeforeIdentifier();
if (func.func.flags.is_async) {
p.print("async ");
@@ -2138,7 +2145,8 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.printFunc(func.func);
p.printNewline();
},
- .s_class => |class| {
+ .s_class => {
+ const class = s2.getClass();
p.printSpaceBeforeIdentifier();
if (class.class.class_name) |name| {
p.print("class ");
@@ -2156,7 +2164,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
},
}
},
- .s_export_star => |s| {
+ .s_export_star => |s_list_index| {
+ const s = stmt.getExportStar();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
p.print("export");
@@ -2175,7 +2185,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.printQuotedUTF8(p.import_records[s.import_record_index].path.text, false);
p.printSemicolonAfterStatement();
},
- .s_export_clause => |s| {
+ .s_export_clause => |s_list_index| {
+ const s = stmt.getExportClause();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
p.print("export");
@@ -2218,7 +2230,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.print("}");
p.printSemicolonAfterStatement();
},
- .s_export_from => |s| {
+ .s_export_from => |s_list_index| {
+ const s = stmt.getExportFrom();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
p.print("export");
@@ -2266,7 +2280,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.printQuotedUTF8(p.import_records[s.import_record_index].path.text, false);
p.printSemicolonAfterStatement();
},
- .s_local => |s| {
+ .s_local => |s_list_index| {
+ const s = stmt.getLocal();
+
switch (s.kind) {
.k_const => {
p.printDeclStmt(s.is_export, "const", s.decls);
@@ -2279,18 +2295,22 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
},
}
},
- .s_if => |s| {
+ .s_if => |s_list_index| {
+ const s = stmt.getIf();
+
p.printIndent();
p.printIf(s);
},
- .s_do_while => |s| {
+ .s_do_while => |s_list_index| {
+ const s = stmt.getDoWhile();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
p.print("do");
switch (s.body.data) {
- .s_block => |block| {
+ .s_block => {
p.printSpace();
- p.printBlock(s.body.loc, block.stmts);
+ p.printBlock(s.body.loc, s.body.getBlock().stmts);
p.printSpace();
},
else => {
@@ -2310,7 +2330,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.print(")");
p.printSemicolonAfterStatement();
},
- .s_for_in => |s| {
+ .s_for_in => |s_list_index| {
+ const s = stmt.getForIn();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
p.print("for");
@@ -2325,7 +2347,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.print(")");
p.printBody(s.body);
},
- .s_for_of => |s| {
+ .s_for_of => |s_list_index| {
+ const s = stmt.getForOf();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
p.print("for");
@@ -2344,7 +2368,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.print(")");
p.printBody(s.body);
},
- .s_while => |s| {
+ .s_while => |s_list_index| {
+ const s = stmt.getWhile();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
p.print("while");
@@ -2354,7 +2380,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.print(")");
p.printBody(s.body);
},
- .s_with => |s| {
+ .s_with => |s_list_index| {
+ const s = stmt.getWith();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
p.print("with");
@@ -2364,13 +2392,17 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.print(")");
p.printBody(s.body);
},
- .s_label => |s| {
+ .s_label => |s_list_index| {
+ const s = stmt.getLabel();
+
p.printIndent();
p.printSymbol(s.name.ref orelse Global.panic("Internal error: expected label to have a name {s}", .{s}));
p.print(":");
p.printBody(s.stmt);
},
- .s_try => |s| {
+ .s_try => |s_list_index| {
+ const s = stmt.getTry();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
p.print("try");
@@ -2399,7 +2431,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.printNewline();
},
- .s_for => |s| {
+ .s_for => |s_list_index| {
+ const s = stmt.getFor();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
p.print("for");
@@ -2426,7 +2460,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.print(")");
p.printBody(s.body);
},
- .s_switch => |s| {
+ .s_switch => |s_list_index| {
+ const s = stmt.getSwitch();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
p.print("switch");
@@ -2459,7 +2495,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
switch (c.body[0].data) {
.s_block => |block| {
p.printSpace();
- p.printBlock(c.body[0].loc, block.stmts);
+ p.printBlock(c.body[0].loc, c.body[0].getBlock().stmts);
p.printNewline();
continue;
},
@@ -2482,7 +2518,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.printNewline();
p.needs_semicolon = false;
},
- .s_import => |s| {
+ .s_import => |s_list_index| {
+ const s = stmt.getImport();
+
var item_count: usize = 0;
p.printIndent();
p.printSpaceBeforeIdentifier();
@@ -2562,18 +2600,24 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.printQuotedUTF8(p.import_records[s.import_record_index].path.text, false);
p.printSemicolonAfterStatement();
},
- .s_block => |s| {
+ .s_block => |s_list_index| {
+ const s = stmt.getBlock();
+
p.printIndent();
p.printBlock(stmt.loc, s.stmts);
p.printNewline();
},
- .s_debugger => |s| {
+ .s_debugger => |s_list_index| {
+ const s = stmt.getDebugger();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
p.print("debugger");
p.printSemicolonAfterStatement();
},
- .s_directive => |s| {
+ .s_directive => |s_list_index| {
+ const s = stmt.getDirective();
+
const c = p.bestQuoteCharForString(s.value, false);
p.printIndent();
p.printSpaceBeforeIdentifier();
@@ -2582,7 +2626,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.print(c);
p.printSemicolonAfterStatement();
},
- .s_break => |s| {
+ .s_break => |s_list_index| {
+ const s = stmt.getBreak();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
p.print("break");
@@ -2593,7 +2639,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.printSemicolonAfterStatement();
},
- .s_continue => |s| {
+ .s_continue => |s_list_index| {
+ const s = stmt.getContinue();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
p.print("continue");
@@ -2604,7 +2652,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
}
p.printSemicolonAfterStatement();
},
- .s_return => |s| {
+ .s_return => |s_list_index| {
+ const s = stmt.getReturn();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
p.print("return");
@@ -2615,7 +2665,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
}
p.printSemicolonAfterStatement();
},
- .s_throw => |s| {
+ .s_throw => |s_list_index| {
+ const s = stmt.getThrow();
+
p.printIndent();
p.printSpaceBeforeIdentifier();
p.print("throw");
@@ -2623,7 +2675,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.printExpr(s.value, .lowest, ExprFlag.None());
p.printSemicolonAfterStatement();
},
- .s_expr => |s| {
+ .s_expr => |s_list_index| {
+ const s = stmt.getExpr();
+
p.printIndent();
p.stmt_start = p.js.lenI();
p.printExpr(s.value, .lowest, ExprFlag.ExprResultIsUnused());
@@ -2637,14 +2691,18 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
pub fn printForLoopInit(p: *Printer, initSt: Stmt) void {
switch (initSt.data) {
- .s_expr => |s| {
+ .s_expr => |s_list_index| {
+ const s = initSt.getExpr();
+
p.printExpr(
s.value,
.lowest,
ExprFlag{ .forbid_in = true, .expr_result_is_unused = true },
);
},
- .s_local => |s| {
+ .s_local => |s_list_index| {
+ const s = initSt.getLocal();
+
switch (s.kind) {
.k_var => {
p.printDecls("var", s.decls, ExprFlag{ .forbid_in = true });
@@ -2673,7 +2731,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
switch (s.yes.data) {
.s_block => |block| {
p.printSpace();
- p.printBlock(s.yes.loc, block.stmts);
+ p.printBlock(s.yes.loc, s.yes.getBlock().stmts);
if (s.no != null) {
p.printSpace();
@@ -2721,11 +2779,11 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
switch (no_block.data) {
.s_block => |no| {
p.printSpace();
- p.printBlock(no_block.loc, no.stmts);
+ p.printBlock(no_block.loc, no_block.getBlock().stmts);
p.printNewline();
},
.s_if => |no| {
- p.printIf(no);
+ p.printIf(no_block.getIf());
},
else => {
p.printNewline();
@@ -2737,32 +2795,31 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
}
}
- pub fn wrapToAvoidAmbiguousElse(_s: *const Stmt.Data) bool {
- var s = _s;
-
+ pub fn wrapToAvoidAmbiguousElse(s_: *const Stmt.Data) bool {
+ var s = s_;
while (true) {
switch (s.*) {
- .s_if => |*current| {
- if (current.*.no) |*no| {
+ .s_if => |index| {
+ if (Stmt.Data.Store.If.at(index).no) |*no| {
s = &no.data;
} else {
return true;
}
},
.s_for => |current| {
- s = &current.body.data;
+ s = &Stmt.Data.Store.For.at(current).body.data;
},
.s_for_in => |current| {
- s = &current.body.data;
+ s = &Stmt.Data.Store.ForIn.at(current).body.data;
},
.s_for_of => |current| {
- s = &current.body.data;
+ s = &Stmt.Data.Store.ForOf.at(current).body.data;
},
.s_while => |current| {
- s = &current.body.data;
+ s = &Stmt.Data.Store.While.at(current).body.data;
},
.s_with => |current| {
- s = &current.body.data;
+ s = &Stmt.Data.Store.With.at(current).body.data;
},
else => {
return false;