aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-05-30 00:17:17 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-05-30 00:17:17 -0700
commitd1db1fdd79ae34f443c3ab701016790737980458 (patch)
tree43f635d7a7959e578330c43d20b6f52d623acbc0
parent2a54b9f13803a06514c1681464a4a86c0c15f978 (diff)
downloadbun-d1db1fdd79ae34f443c3ab701016790737980458.tar.gz
bun-d1db1fdd79ae34f443c3ab701016790737980458.tar.zst
bun-d1db1fdd79ae34f443c3ab701016790737980458.zip
This blocks approach seems to work
Former-commit-id: 95d5bc78f29e541d299d77e7c521a808f80499b7
-rw-r--r--.vscode/launch.json2
-rw-r--r--src/bundler.zig19
-rw-r--r--src/cli.zig1
-rw-r--r--src/js_ast.zig625
-rw-r--r--src/js_parser/js_parser.zig589
-rw-r--r--src/js_printer.zig14
6 files changed, 469 insertions, 781 deletions
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 932de42ad..bffabe77a 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -35,7 +35,7 @@
"type": "lldb",
"request": "launch",
"name": "DAev Launch",
- "program": "${workspaceFolder}/build/debug/macos-x86_64/esdev",
+ "program": "${workspaceFolder}/build/macos-x86_64/esdev",
"args": ["./simple.jsx", "--resolve=disable"],
"cwd": "${workspaceFolder}/src/test/fixtures",
"console": "internalConsole"
diff --git a/src/bundler.zig b/src/bundler.zig
index 42b515678..e0462e74b 100644
--- a/src/bundler.zig
+++ b/src/bundler.zig
@@ -80,6 +80,8 @@ pub const Bundler = struct {
log: *logger.Log,
opts: Api.TransformOptions,
) !Bundler {
+ js_ast.Expr.Data.Store.create(allocator);
+ js_ast.Stmt.Data.Store.create(allocator);
var fs = try Fs.FileSystem.init1(allocator, opts.absolute_working_dir, opts.serve orelse false);
const bundle_options = try options.BundleOptions.fromApi(allocator, fs, log, opts);
@@ -204,13 +206,19 @@ pub const Bundler = struct {
if (resolve_result.is_external) {
return null;
}
+ errdefer js_ast.Expr.Data.Store.reset();
+ errdefer js_ast.Stmt.Data.Store.reset();
// Step 1. Parse & scan
const loader = bundler.options.loaders.get(resolve_result.path_pair.primary.name.ext) orelse .file;
var file_path = resolve_result.path_pair.primary;
file_path.pretty = relative_paths_list.append(bundler.fs.relativeTo(file_path.text)) catch unreachable;
- var result = bundler.parse(file_path, loader, resolve_result.dirname_fd) orelse return null;
+ var result = bundler.parse(file_path, loader, resolve_result.dirname_fd) orelse {
+ js_ast.Expr.Data.Store.reset();
+ js_ast.Stmt.Data.Store.reset();
+ return null;
+ };
switch (result.loader) {
.jsx, .js, .ts, .tsx => {
@@ -266,10 +274,8 @@ pub const Bundler = struct {
const output_file = try bundler.print(
result,
);
-
- js_ast.Stmt.Data.Store.reset();
js_ast.Expr.Data.Store.reset();
-
+ js_ast.Stmt.Data.Store.reset();
return output_file;
}
@@ -643,6 +649,8 @@ pub const Transformer = struct {
log: *logger.Log,
opts: Api.TransformOptions,
) !options.TransformResult {
+ js_ast.Expr.Data.Store.create(allocator);
+ js_ast.Stmt.Data.Store.create(allocator);
var raw_defines = try options.stringHashMapFromArrays(RawDefines, allocator, opts.define_keys, opts.define_values);
if (opts.define_keys.len == 0) {
try raw_defines.put("process.env.NODE_ENV", "\"development\"");
@@ -687,9 +695,6 @@ pub const Transformer = struct {
var arena: std.heap.ArenaAllocator = undefined;
const use_arenas = opts.entry_points.len > 8;
- js_ast.Expr.Data.Store.create(allocator);
- js_ast.Stmt.Data.Store.create(allocator);
-
var ulimit: usize = Fs.FileSystem.RealFS.adjustUlimit();
var care_about_closing_files = !(FeatureFlags.store_file_descriptors and opts.entry_points.len * 2 < ulimit);
for (opts.entry_points) |entry_point, i| {
diff --git a/src/cli.zig b/src/cli.zig
index 6e44d5e08..fcae111c5 100644
--- a/src/cli.zig
+++ b/src/cli.zig
@@ -380,7 +380,6 @@ pub const Cli = struct {
_ = try writer.write("\n");
for (result.output_files) |file| {
const padding_count = 2 + (max_path_len - file.path.len);
-
try writer.writeByteNTimes(' ', 2);
try writer.writeAll(file.path);
try writer.writeByteNTimes(' ', padding_count);
diff --git a/src/js_ast.zig b/src/js_ast.zig
index 5b3f1a7c1..416a3c752 100644
--- a/src/js_ast.zig
+++ b/src/js_ast.zig
@@ -11,15 +11,88 @@ const allocators = @import("allocators.zig");
const _hash_map = @import("hash_map.zig");
const StringHashMap = _hash_map.StringHashMap;
const AutoHashMap = _hash_map.AutoHashMap;
+pub fn NewStore(comptime ValueType: type, comptime count: usize) type {
+ const max_index = count - 1;
+ const list_count = count;
+ return struct {
+ const Allocator = std.mem.Allocator;
+ const Self = @This();
+ const Block = struct {
+ items: [count]ValueType = undefined,
+ used: usize = 0,
+ allocator: *std.mem.Allocator,
-pub const ListIndex = packed struct {
- index: u31,
- is_overflowing: bool = false,
+ pub fn isFull(block: *const Block) bool {
+ return block.used >= block.items.len;
+ }
- pub fn eql(a: ListIndex, b: ListIndex) bool {
- return @bitCast(u32, a) == @bitCast(u32, b);
- }
-};
+ pub fn append(block: *Block, value: ValueType) *ValueType {
+ std.debug.assert(block.used < count);
+ const index = block.used;
+ block.items[index] = value;
+
+ block.used += 1;
+ return &block.items[index];
+ }
+ };
+
+ block: Block,
+ overflow_ptrs: [500]*Block = undefined,
+ overflow: []*Block = &([_]*Block{}),
+ overflow_used: usize = 0,
+ allocator: *Allocator,
+
+ pub threadlocal var instance: Self = undefined;
+ pub threadlocal var _self: *Self = undefined;
+
+ pub fn reset() void {
+ _self.block.used = 0;
+ for (_self.overflow[0.._self.overflow_used]) |b| {
+ b.used = 0;
+ }
+ _self.overflow_used = 0;
+ }
+
+ pub fn init(allocator: *std.mem.Allocator) *Self {
+ instance = Self{
+ .allocator = allocator,
+ .block = Block{ .allocator = allocator },
+ };
+
+ _self = &instance;
+ return _self;
+ }
+
+ pub fn append(value: ValueType) *ValueType {
+ return _self._append(value);
+ }
+
+ fn _append(self: *Self, value: ValueType) *ValueType {
+ if (!self.block.isFull()) {
+ return self.block.append(value);
+ }
+
+ if (self.overflow_used >= self.overflow.len or self.overflow[self.overflow_used].isFull()) {
+ var slice = self.allocator.alloc(Block, 2) catch unreachable;
+ for (slice) |*block| {
+ block.allocator = self.allocator;
+ block.used = 0;
+ block.items = undefined;
+ self.overflow_ptrs[self.overflow.len] = block;
+ self.overflow = self.overflow_ptrs[0 .. self.overflow.len + 1];
+ }
+ }
+
+ var block = self.overflow[self.overflow_used];
+ var ptr = block.append(value);
+ if (block.isFull()) {
+ self.overflow_used += 1;
+ }
+
+ return ptr;
+ }
+ };
+}
// There are three types.
// 1. Expr (expression)
@@ -709,7 +782,7 @@ pub const E = struct {
pub const Call = struct {
// Node:
target: ExprNodeIndex,
- args: ExprNodeList,
+ args: ExprNodeList = &([_]ExprNodeIndex{}),
optional_chain: ?OptionalChain = null,
is_direct_eval: bool = false,
@@ -1086,103 +1159,103 @@ 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);
+ return self.data.s_block;
}
pub inline fn getBreak(self: *const @This()) *S.Break {
- return Data.Store.Break.at(self.data.s_break);
+ return self.data.s_break;
}
pub inline fn getClass(self: *const @This()) *S.Class {
- return Data.Store.Class.at(self.data.s_class);
+ return self.data.s_class;
}
pub inline fn getComment(self: *const @This()) *S.Comment {
- return Data.Store.Comment.at(self.data.s_comment);
+ return self.data.s_comment;
}
pub inline fn getContinue(self: *const @This()) *S.Continue {
- return Data.Store.Continue.at(self.data.s_continue);
+ return 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);
+ return self.data.s_directive;
}
pub inline fn getDoWhile(self: *const @This()) *S.DoWhile {
- return Data.Store.DoWhile.at(self.data.s_do_while);
+ return 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);
+ return self.data.s_enum;
}
pub inline fn getExportClause(self: *const @This()) *S.ExportClause {
- return Data.Store.ExportClause.at(self.data.s_export_clause);
+ return self.data.s_export_clause;
}
pub inline fn getExportDefault(self: *const @This()) *S.ExportDefault {
- return Data.Store.ExportDefault.at(self.data.s_export_default);
+ return self.data.s_export_default;
}
pub inline fn getExportEquals(self: *const @This()) *S.ExportEquals {
- return Data.Store.ExportEquals.at(self.data.s_export_equals);
+ return self.data.s_export_equals;
}
pub inline fn getExportFrom(self: *const @This()) *S.ExportFrom {
- return Data.Store.ExportFrom.at(self.data.s_export_from);
+ return self.data.s_export_from;
}
pub inline fn getExportStar(self: *const @This()) *S.ExportStar {
- return Data.Store.ExportStar.at(self.data.s_export_star);
+ return self.data.s_export_star;
}
pub inline fn getExpr(self: *const @This()) *S.SExpr {
- return Data.Store.SExpr.at(self.data.s_expr);
+ return self.data.s_expr;
}
pub inline fn getForIn(self: *const @This()) *S.ForIn {
- return Data.Store.ForIn.at(self.data.s_for_in);
+ return self.data.s_for_in;
}
pub inline fn getForOf(self: *const @This()) *S.ForOf {
- return Data.Store.ForOf.at(self.data.s_for_of);
+ return self.data.s_for_of;
}
pub inline fn getFor(self: *const @This()) *S.For {
- return Data.Store.For.at(self.data.s_for);
+ return self.data.s_for;
}
pub inline fn getFunction(self: *const @This()) *S.Function {
- return Data.Store.Function.at(self.data.s_function);
+ return self.data.s_function;
}
pub inline fn getIf(self: *const @This()) *S.If {
- return Data.Store.If.at(self.data.s_if);
+ return self.data.s_if;
}
pub inline fn getImport(self: *const @This()) *S.Import {
- return Data.Store.Import.at(self.data.s_import);
+ return self.data.s_import;
}
pub inline fn getLabel(self: *const @This()) *S.Label {
- return Data.Store.Label.at(self.data.s_label);
+ return self.data.s_label;
}
pub inline fn getLazyExport(self: *const @This()) *S.LazyExport {
- return Data.Store.LazyExport.at(self.data.s_lazy_export);
+ return self.data.s_lazy_export;
}
pub inline fn getLocal(self: *const @This()) *S.Local {
- return Data.Store.Local.at(self.data.s_local);
+ return self.data.s_local;
}
pub inline fn getNamespace(self: *const @This()) *S.Namespace {
- return Data.Store.Namespace.at(self.data.s_namespace);
+ return self.data.s_namespace;
}
pub inline fn getReturn(self: *const @This()) *S.Return {
- return Data.Store.Return.at(self.data.s_return);
+ return self.data.s_return;
}
pub inline fn getSwitch(self: *const @This()) *S.Switch {
- return Data.Store.Switch.at(self.data.s_switch);
+ return self.data.s_switch;
}
pub inline fn getThrow(self: *const @This()) *S.Throw {
- return Data.Store.Throw.at(self.data.s_throw);
+ return self.data.s_throw;
}
pub inline fn getTry(self: *const @This()) *S.Try {
- return Data.Store.Try.at(self.data.s_try);
+ return 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);
+ return self.data.s_while;
}
pub inline fn getWith(self: *const @This()) *S.With {
- return Data.Store.With.at(self.data.s_with);
+ return self.data.s_with;
}
pub var icount: usize = 0;
pub fn init(origData: anytype, loc: logger.Loc) Stmt {
@@ -1454,72 +1527,73 @@ pub const Stmt = struct {
};
pub const Data = union(Tag) {
- s_block: ListIndex,
- s_break: ListIndex,
- s_class: ListIndex,
- s_comment: ListIndex,
- s_continue: ListIndex,
- s_debugger: S.Debugger,
- s_directive: ListIndex,
- s_do_while: ListIndex,
- s_empty: S.Empty, // special case, its a zero value type
- s_enum: ListIndex,
- s_export_clause: ListIndex,
- s_export_default: ListIndex,
- s_export_equals: ListIndex,
- s_export_from: ListIndex,
- s_export_star: ListIndex,
- s_expr: ListIndex,
- s_for_in: ListIndex,
- s_for_of: ListIndex,
- s_for: ListIndex,
- s_function: ListIndex,
- s_if: ListIndex,
- s_import: ListIndex,
- s_label: ListIndex,
- s_lazy_export: ListIndex,
- s_local: ListIndex,
- s_namespace: ListIndex,
- s_return: ListIndex,
- s_switch: ListIndex,
- s_throw: ListIndex,
- s_try: ListIndex,
+ s_block: *S.Block,
+ s_break: *S.Break,
+ s_class: *S.Class,
+ s_comment: *S.Comment,
+ s_continue: *S.Continue,
+ s_directive: *S.Directive,
+ s_do_while: *S.DoWhile,
+ 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_while: *S.While,
+ s_with: *S.With,
+
s_type_script: S.TypeScript,
- s_while: ListIndex,
- s_with: ListIndex,
+ s_empty: S.Empty, // special case, its a zero value type
+ s_debugger: S.Debugger,
pub const Store = struct {
- 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);
+ pub const Block = NewStore(S.Block, 24);
+ pub const Break = NewStore(S.Break, 24);
+ pub const Class = NewStore(S.Class, 24);
+ pub const Comment = NewStore(S.Comment, 24);
+ pub const Continue = NewStore(S.Continue, 24);
+ pub const Directive = NewStore(S.Directive, 24);
+ pub const DoWhile = NewStore(S.DoWhile, 24);
+ pub const Enum = NewStore(S.Enum, 24);
+ pub const ExportClause = NewStore(S.ExportClause, 24);
+ pub const ExportDefault = NewStore(S.ExportDefault, 24);
+ pub const ExportEquals = NewStore(S.ExportEquals, 24);
+ pub const ExportFrom = NewStore(S.ExportFrom, 24);
+ pub const ExportStar = NewStore(S.ExportStar, 24);
+ pub const SExpr = NewStore(S.SExpr, 24);
+ pub const ForIn = NewStore(S.ForIn, 24);
+ pub const ForOf = NewStore(S.ForOf, 24);
+ pub const For = NewStore(S.For, 24);
+ pub const Function = NewStore(S.Function, 24);
+ pub const If = NewStore(S.If, 24);
+ pub const Import = NewStore(S.Import, 24);
+ pub const Label = NewStore(S.Label, 24);
+ pub const LazyExport = NewStore(S.LazyExport, 24);
+ pub const Local = NewStore(S.Local, 24);
+ pub const Namespace = NewStore(S.Namespace, 24);
+ pub const Return = NewStore(S.Return, 24);
+ pub const Switch = NewStore(S.Switch, 24);
+ pub const Throw = NewStore(S.Throw, 24);
+ pub const Try = NewStore(S.Try, 24);
+ pub const TypeScript = NewStore(S.TypeScript, 24);
+ pub const While = NewStore(S.While, 24);
+ pub const With = NewStore(S.With, 24);
threadlocal var has_inited = false;
pub fn create(allocator: *std.mem.Allocator) void {
@@ -1593,7 +1667,7 @@ pub const Stmt = struct {
With.reset();
}
- pub fn append(comptime ValueType: type, value: anytype) ListIndex {
+ pub fn append(comptime ValueType: type, value: anytype) *ValueType {
switch (comptime ValueType) {
S.Block => {
return Block.append(value);
@@ -1695,76 +1769,6 @@ pub const Stmt = struct {
},
}
}
-
- pub fn NewStore(comptime ValueType: type) type {
- const count = 8096;
- 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.items.len = 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 and self.overflow_list.capacity == 0) {
- self.overflow_list = @TypeOf(self.overflow_list).initCapacity(self.allocator, 1) catch unreachable;
- }
- }
-
- return result;
- }
- };
- }
};
pub inline fn set(data: *Data, value: anytype) void {
@@ -1912,110 +1916,110 @@ pub const Expr = struct {
pub const Query = struct { expr: Expr, loc: logger.Loc };
pub fn getArray(exp: *const Expr) *E.Array {
- return Data.Store.Array.at(exp.data.e_array);
+ return exp.data.e_array;
}
pub fn getUnary(exp: *const Expr) *E.Unary {
- return Data.Store.Unary.at(exp.data.e_unary);
+ return exp.data.e_unary;
}
pub fn getBinary(exp: *const Expr) *E.Binary {
- return Data.Store.Binary.at(exp.data.e_binary);
+ return exp.data.e_binary;
}
pub fn getThis(exp: *const Expr) *E.This {
return E.This{};
}
pub fn getClass(exp: *const Expr) *E.Class {
- return Data.Store.Class.at(exp.data.e_class);
+ return exp.data.e_class;
}
pub fn getBoolean(exp: *const Expr) *E.Boolean {
- return Data.Store.Boolean.at(exp.data.e_boolean);
+ return exp.data.e_boolean;
}
pub fn getSuper(exp: *const Expr) *E.Super {
- return Data.Store.Super.at(exp.data.e_super);
+ return exp.data.e_super;
}
pub fn getNull(exp: *const Expr) *E.Null {
- return Data.Store.Null.at(exp.data.e_null);
+ return exp.data.e_null;
}
pub fn getUndefined(exp: *const Expr) *E.Undefined {
- return Data.Store.Undefined.at(exp.data.e_undefined);
+ return exp.data.e_undefined;
}
pub fn getNew(exp: *const Expr) *E.New {
- return Data.Store.New.at(exp.data.e_new);
+ return exp.data.e_new;
}
pub fn getNewTarget(exp: *const Expr) *E.NewTarget {
return &E.NewTarget{};
}
pub fn getFunction(exp: *const Expr) *E.Function {
- return Data.Store.Function.at(exp.data.e_function);
+ return exp.data.e_function;
}
pub fn getCall(exp: *const Expr) *E.Call {
- return Data.Store.Call.at(exp.data.e_call);
+ return exp.data.e_call;
}
pub fn getDot(exp: *const Expr) *E.Dot {
- return Data.Store.Dot.at(exp.data.e_dot);
+ return exp.data.e_dot;
}
pub fn getIndex(exp: *const Expr) *E.Index {
- return Data.Store.Index.at(exp.data.e_index);
+ return exp.data.e_index;
}
pub fn getArrow(exp: *const Expr) *E.Arrow {
- return Data.Store.Arrow.at(exp.data.e_arrow);
+ return exp.data.e_arrow;
}
pub fn getIdentifier(exp: *const Expr) *E.Identifier {
- return Data.Store.Identifier.at(exp.data.e_identifier);
+ return exp.data.e_identifier;
}
pub fn getImportIdentifier(exp: *const Expr) *E.ImportIdentifier {
- return Data.Store.ImportIdentifier.at(exp.data.e_import_identifier);
+ return exp.data.e_import_identifier;
}
pub fn getPrivateIdentifier(exp: *const Expr) *E.PrivateIdentifier {
- return Data.Store.PrivateIdentifier.at(exp.data.e_private_identifier);
+ return exp.data.e_private_identifier;
}
pub fn getJsxElement(exp: *const Expr) *E.JSXElement {
- return Data.Store.JSXElement.at(exp.data.e_jsx_element);
+ return exp.data.e_jsx_element;
}
pub fn getMissing(exp: *const Expr) *E.Missing {
- return Data.Store.Missing.at(exp.data.e_missing);
+ return exp.data.e_missing;
}
pub fn getNumber(exp: *const Expr) *E.Number {
- return Data.Store.Number.at(exp.data.e_number);
+ return exp.data.e_number;
}
pub fn getBigInt(exp: *const Expr) *E.BigInt {
- return Data.Store.BigInt.at(exp.data.e_big_int);
+ return exp.data.e_big_int;
}
pub fn getObject(exp: *const Expr) *E.Object {
- return Data.Store.Object.at(exp.data.e_object);
+ return exp.data.e_object;
}
pub fn getSpread(exp: *const Expr) *E.Spread {
- return Data.Store.Spread.at(exp.data.e_spread);
+ return exp.data.e_spread;
}
pub fn getString(exp: *const Expr) *E.String {
- return Data.Store.String.at(exp.data.e_string);
+ return exp.data.e_string;
}
pub fn getTemplatePart(exp: *const Expr) *E.TemplatePart {
- return Data.Store.TemplatePart.at(exp.data.e_template_part);
+ return exp.data.e_template_part;
}
pub fn getTemplate(exp: *const Expr) *E.Template {
- return Data.Store.Template.at(exp.data.e_template);
+ return exp.data.e_template;
}
pub fn getRegExp(exp: *const Expr) *E.RegExp {
- return Data.Store.RegExp.at(exp.data.e_reg_exp);
+ return exp.data.e_reg_exp;
}
pub fn getAwait(exp: *const Expr) *E.Await {
- return Data.Store.Await.at(exp.data.e_await);
+ return exp.data.e_await;
}
pub fn getYield(exp: *const Expr) *E.Yield {
- return Data.Store.Yield.at(exp.data.e_yield);
+ return exp.data.e_yield;
}
pub fn getIf(exp: *const Expr) *E.If {
- return Data.Store.If.at(exp.data.e_if);
+ return exp.data.e_if;
}
pub fn getRequire(exp: *const Expr) *E.Require {
- return Data.Store.Require.at(exp.data.e_require);
+ return exp.data.e_require;
}
pub fn getRequireOrRequireResolve(exp: *const Expr) *E.RequireOrRequireResolve {
- return Data.Store.RequireOrRequireResolve.at(exp.data.e_require_or_require_resolve);
+ return exp.data.e_require_or_require_resolve;
}
pub fn getImport(exp: *const Expr) *E.Import {
- return Data.Store.Import.at(exp.data.e_import);
+ return exp.data.e_import;
}
pub fn asProperty(expr: *const Expr, name: string) ?Query {
@@ -2108,7 +2112,7 @@ pub const Expr = struct {
return null;
}
- return [2]f64{ Expr.Data.Store.Number.at(left.e_number).value, Expr.Data.Store.Number.at(right.e_number).value };
+ return [2]f64{ left.e_number.value, right.e_number.value };
}
pub fn isAnonymousNamed(e: *Expr) bool {
@@ -3250,12 +3254,35 @@ pub const Expr = struct {
}
pub const Data = union(Tag) {
- e_array: ListIndex,
- e_unary: ListIndex,
- e_binary: ListIndex,
-
- e_class: ListIndex,
- e_boolean: ListIndex,
+ e_array: *E.Array,
+ e_unary: *E.Unary,
+ e_binary: *E.Binary,
+ e_class: *E.Class,
+ e_boolean: *E.Boolean,
+ e_new: *E.New,
+ e_function: *E.Function,
+ e_call: *E.Call,
+ e_dot: *E.Dot,
+ e_index: *E.Index,
+ e_arrow: *E.Arrow,
+ e_identifier: *E.Identifier,
+ e_import_identifier: *E.ImportIdentifier,
+ e_private_identifier: *E.PrivateIdentifier,
+ e_jsx_element: *E.JSXElement,
+ e_number: *E.Number,
+ e_big_int: *E.BigInt,
+ e_object: *E.Object,
+ e_spread: *E.Spread,
+ e_string: *E.String,
+ e_template_part: *E.TemplatePart,
+ e_template: *E.Template,
+ e_reg_exp: *E.RegExp,
+ e_await: *E.Await,
+ e_yield: *E.Yield,
+ e_if: *E.If,
+ e_require: *E.Require,
+ e_require_or_require_resolve: *E.RequireOrRequireResolve,
+ e_import: *E.Import,
e_missing: E.Missing,
e_this: E.This,
@@ -3263,71 +3290,42 @@ pub const Expr = struct {
e_null: E.Null,
e_undefined: E.Undefined,
e_new_target: E.NewTarget,
-
- e_new: ListIndex,
-
- e_function: ListIndex,
e_import_meta: E.ImportMeta,
- e_call: ListIndex,
- e_dot: ListIndex,
- e_index: ListIndex,
- e_arrow: ListIndex,
- e_identifier: ListIndex,
- e_import_identifier: ListIndex,
- e_private_identifier: ListIndex,
- e_jsx_element: ListIndex,
-
- e_number: ListIndex,
- e_big_int: ListIndex,
- e_object: ListIndex,
- e_spread: ListIndex,
- e_string: ListIndex,
- e_template_part: ListIndex,
- e_template: ListIndex,
- e_reg_exp: ListIndex,
- e_await: ListIndex,
- e_yield: ListIndex,
- e_if: ListIndex,
- e_require: ListIndex,
- e_require_or_require_resolve: ListIndex,
- e_import: ListIndex,
pub const Store = struct {
- pub const Array = NewStore(E.Array);
- pub const Unary = NewStore(E.Unary);
- pub const Binary = NewStore(E.Binary);
- pub const This = NewStore(E.This);
- pub const Class = NewStore(E.Class);
- pub const Boolean = NewStore(E.Boolean);
- pub const Super = NewStore(E.Super);
- pub const Null = NewStore(E.Null);
- pub const Undefined = NewStore(E.Undefined);
- pub const New = NewStore(E.New);
- pub const Function = NewStore(E.Function);
- pub const ImportMeta = NewStore(E.ImportMeta);
- pub const Call = NewStore(E.Call);
- pub const Dot = NewStore(E.Dot);
- pub const Index = NewStore(E.Index);
- pub const Arrow = NewStore(E.Arrow);
- pub const Identifier = NewStore(E.Identifier);
- pub const ImportIdentifier = NewStore(E.ImportIdentifier);
- pub const PrivateIdentifier = NewStore(E.PrivateIdentifier);
- pub const JSXElement = NewStore(E.JSXElement);
- pub const Missing = NewStore(E.Missing);
- pub const Number = NewStore(E.Number);
- pub const BigInt = NewStore(E.BigInt);
- pub const Object = NewStore(E.Object);
- pub const Spread = NewStore(E.Spread);
- pub const String = NewStore(E.String);
- pub const TemplatePart = NewStore(E.TemplatePart);
- pub const Template = NewStore(E.Template);
- pub const RegExp = NewStore(E.RegExp);
- pub const Await = NewStore(E.Await);
- pub const Yield = NewStore(E.Yield);
- pub const If = NewStore(E.If);
- pub const Require = NewStore(E.Require);
- pub const RequireOrRequireResolve = NewStore(E.RequireOrRequireResolve);
- pub const Import = NewStore(E.Import);
+ const often = 512;
+ const medium = 256;
+ const rare = 24;
+ pub const Array = NewStore(E.Array, 128);
+ pub const Unary = NewStore(E.Unary, 128);
+ pub const Binary = NewStore(E.Binary, 128);
+ pub const Class = NewStore(E.Class, 24);
+ pub const Boolean = NewStore(E.Boolean, 512);
+ pub const Super = NewStore(E.Super, 128);
+ pub const New = NewStore(E.New, 128);
+ pub const Function = NewStore(E.Function, 24);
+ pub const Call = NewStore(E.Call, often);
+ pub const Dot = NewStore(E.Dot, often);
+ pub const Index = NewStore(E.Index, 24);
+ pub const Arrow = NewStore(E.Arrow, 24);
+ pub const Identifier = NewStore(E.Identifier, 24);
+ pub const ImportIdentifier = NewStore(E.ImportIdentifier, 24);
+ pub const PrivateIdentifier = NewStore(E.PrivateIdentifier, 24);
+ pub const JSXElement = NewStore(E.JSXElement, 24);
+ pub const Number = NewStore(E.Number, 256);
+ pub const BigInt = NewStore(E.BigInt, 256);
+ pub const Object = NewStore(E.Object, 512);
+ pub const Spread = NewStore(E.Spread, 256);
+ pub const String = NewStore(E.String, 512);
+ pub const TemplatePart = NewStore(E.TemplatePart, 128);
+ pub const Template = NewStore(E.Template, 64);
+ pub const RegExp = NewStore(E.RegExp, 24);
+ pub const Await = NewStore(E.Await, 24);
+ pub const Yield = NewStore(E.Yield, 24);
+ pub const If = NewStore(E.If, 24);
+ pub const Require = NewStore(E.Require, 24);
+ pub const RequireOrRequireResolve = NewStore(E.RequireOrRequireResolve, 24);
+ pub const Import = NewStore(E.Import, 24);
threadlocal var has_inited = false;
pub fn create(allocator: *std.mem.Allocator) void {
@@ -3339,12 +3337,10 @@ pub const Expr = struct {
_ = Array.init(allocator);
_ = Unary.init(allocator);
_ = Binary.init(allocator);
- _ = This.init(allocator);
_ = Class.init(allocator);
_ = Boolean.init(allocator);
_ = New.init(allocator);
_ = Function.init(allocator);
- _ = ImportMeta.init(allocator);
_ = Call.init(allocator);
_ = Dot.init(allocator);
_ = Index.init(allocator);
@@ -3353,7 +3349,6 @@ pub const Expr = struct {
_ = ImportIdentifier.init(allocator);
_ = PrivateIdentifier.init(allocator);
_ = JSXElement.init(allocator);
- _ = Missing.init(allocator);
_ = Number.init(allocator);
_ = BigInt.init(allocator);
_ = Object.init(allocator);
@@ -3374,12 +3369,10 @@ pub const Expr = struct {
Array.reset();
Unary.reset();
Binary.reset();
- This.reset();
Class.reset();
Boolean.reset();
New.reset();
Function.reset();
- ImportMeta.reset();
Call.reset();
Dot.reset();
Index.reset();
@@ -3388,7 +3381,6 @@ pub const Expr = struct {
ImportIdentifier.reset();
PrivateIdentifier.reset();
JSXElement.reset();
- Missing.reset();
Number.reset();
BigInt.reset();
Object.reset();
@@ -3405,7 +3397,7 @@ pub const Expr = struct {
Import.reset();
}
- pub fn append(comptime ValueType: type, value: anytype) ListIndex {
+ pub fn append(comptime ValueType: type, value: anytype) *ValueType {
switch (comptime ValueType) {
E.Array => {
return Array.append(value);
@@ -3520,77 +3512,6 @@ pub const Expr = struct {
},
}
}
-
- pub fn NewStore(comptime ValueType: type) type {
- const count = 8096;
- 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 and self.overflow_list.capacity == 0) {
- self.overflow_list = @TypeOf(self.overflow_list).initCapacity(self.allocator, 1) catch unreachable;
- }
- }
-
- return result;
- }
- };
- }
};
pub fn isBooleanValue(self: *Expr) bool {
diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig
index ffa401bb7..ced5f8f25 100644
--- a/src/js_parser/js_parser.zig
+++ b/src/js_parser/js_parser.zig
@@ -18,9 +18,7 @@ pub fn ExpressionTransposer(comptime ctx: type, visitor: fn (ptr: *ctx, arg: Exp
pub fn maybeTransposeIf(self: *@This(), arg: Expr, state: anytype) Expr {
switch (arg.data) {
- .e_if => {
- const ex = arg.getIf();
-
+ .e_if => |ex| {
ex.yes = self.maybeTransposeIf(ex.yes, state);
ex.no = self.maybeTransposeIf(ex.no, state);
return arg;
@@ -55,9 +53,7 @@ pub const ImportScanner = struct {
// zls needs the hint, it seems.
const stmt: Stmt = _stmt;
switch (stmt.data) {
- .s_import => {
- var st = stmt.getImport();
-
+ .s_import => |st| {
var record: ImportRecord = p.import_records.items[st.import_record_index];
// The official TypeScript compiler always removes unused imported
@@ -368,9 +364,7 @@ pub const ImportScanner = struct {
}
}
},
- .s_function => {
- var st = stmt.getFunction();
-
+ .s_function => |st| {
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.?);
@@ -379,9 +373,7 @@ pub const ImportScanner = struct {
}
}
},
- .s_class => {
- var st = stmt.getClass();
-
+ .s_class => |st| {
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.?);
@@ -390,9 +382,7 @@ pub const ImportScanner = struct {
}
}
},
- .s_local => {
- var st = stmt.getLocal();
-
+ .s_local => |st| {
if (st.is_export) {
for (st.decls) |decl| {
p.recordExportedBinding(decl.binding);
@@ -432,21 +422,15 @@ pub const ImportScanner = struct {
}
}
},
- .s_export_default => {
- var st = stmt.getExportDefault();
-
+ .s_export_default => |st| {
try p.recordExport(st.default_name.loc, "default", st.default_name.ref.?);
},
- .s_export_clause => {
- var st = stmt.getExportClause();
-
+ .s_export_clause => |st| {
for (st.items) |item| {
try p.recordExport(item.alias_loc, item.alias, item.name.ref.?);
}
},
- .s_export_star => {
- var st = stmt.getExportStar();
-
+ .s_export_star => |st| {
try p.import_records_for_current_part.append(st.import_record_index);
if (st.alias) |alias| {
@@ -465,9 +449,7 @@ pub const ImportScanner = struct {
try p.export_star_import_records.append(st.import_record_index);
}
},
- .s_export_from => {
- var st = stmt.getExportFrom();
-
+ .s_export_from => |st| {
try p.import_records_for_current_part.append(st.import_record_index);
for (st.items) |item| {
@@ -516,12 +498,12 @@ pub const SideEffects = enum(u2) {
return std.math.nan_f64;
},
.e_boolean => {
- const e = Expr.Data.Store.Boolean.at(data.e_boolean);
+ const e = data.e_boolean;
return if (e.value) 1.0 else 0.0;
},
.e_number => {
- const e = Expr.Data.Store.Number.at(data.e_number);
+ const e = data.e_number;
return e.value;
},
@@ -548,14 +530,12 @@ pub const SideEffects = enum(u2) {
return null;
},
- .e_dot => {
- if (expr.getDot().can_be_removed_if_unused) {
+ .e_dot => |dot| {
+ if (dot.can_be_removed_if_unused) {
return null;
}
},
- .e_identifier => {
- const ident = expr.getIdentifier();
-
+ .e_identifier => |ident| {
if (ident.must_keep_due_to_with_stmt) {
return expr;
}
@@ -564,8 +544,7 @@ pub const SideEffects = enum(u2) {
return null;
}
},
- .e_if => {
- const __if__ = expr.getIf();
+ .e_if => |__if__| {
__if__.yes = simpifyUnusedExpr(p, __if__.yes) orelse __if__.yes.toEmpty();
__if__.no = simpifyUnusedExpr(p, __if__.no) orelse __if__.no.toEmpty();
@@ -575,8 +554,7 @@ pub const SideEffects = enum(u2) {
}
},
- .e_call => {
- const call = expr.getCall();
+ .e_call => |call| {
// A call that has been marked "__PURE__" can be removed if all arguments
// can be removed. The annotation causes us to ignore the target.
@@ -585,8 +563,7 @@ pub const SideEffects = enum(u2) {
}
},
- .e_binary => {
- const bin = expr.getBinary();
+ .e_binary => |bin| {
switch (bin.op) {
// We can simplify "==" and "!=" even though they can call "toString" and/or
// "valueOf" if we can statically determine that the types of both sides are
@@ -601,8 +578,7 @@ pub const SideEffects = enum(u2) {
}
},
- .e_new => {
- const call = expr.getNew();
+ .e_new => |call| {
// A constructor call that has been marked "__PURE__" can be removed if all arguments
// can be removed. The annotation causes us to ignore the target.
if (call.can_be_unwrapped_if_unused) {
@@ -635,9 +611,7 @@ pub const SideEffects = enum(u2) {
return false;
},
- .s_local => |local__| {
- var local = stmt.getLocal();
-
+ .s_local => |local| {
return local.kind != .k_var;
// if (local.kind != .k_var) {
// // Omit these statements entirely
@@ -655,8 +629,7 @@ pub const SideEffects = enum(u2) {
return false;
},
- .s_if => {
- const _if_ = stmt.getIf();
+ .s_if => |_if_| {
if (shouldKeepStmtInDeadControlFlow(_if_.yes)) {
return true;
}
@@ -674,8 +647,7 @@ pub const SideEffects = enum(u2) {
return shouldKeepStmtInDeadControlFlow(stmt.getDoWhile().body);
},
- .s_for => {
- const __for__ = stmt.getFor();
+ .s_for => |__for__| {
if (__for__.init) |init_| {
if (shouldKeepStmtInDeadControlFlow(init_)) {
return true;
@@ -685,20 +657,15 @@ pub const SideEffects = enum(u2) {
return shouldKeepStmtInDeadControlFlow(__for__.body);
},
- .s_for_in => {
- const __for__ = stmt.getForIn();
+ .s_for_in => |__for__| {
return shouldKeepStmtInDeadControlFlow(__for__.init) or shouldKeepStmtInDeadControlFlow(__for__.body);
},
- .s_for_of => {
- const __for__ = stmt.getForOf();
-
+ .s_for_of => |__for__| {
return shouldKeepStmtInDeadControlFlow(__for__.init) or shouldKeepStmtInDeadControlFlow(__for__.body);
},
- .s_label => {
- const label = stmt.getLabel();
-
+ .s_label => |label| {
return shouldKeepStmtInDeadControlFlow(label.stmt);
},
else => {
@@ -724,29 +691,29 @@ pub const SideEffects = enum(u2) {
equality.equal = equality.ok;
},
.e_boolean => {
- const l = Expr.Data.Store.Boolean.at(left.e_boolean);
- const r = Expr.Data.Store.Boolean.at(right.e_boolean);
+ const l = left.e_boolean;
+ const r = right.e_boolean;
equality.ok = @as(Expr.Tag, right) == Expr.Tag.e_boolean;
equality.equal = equality.ok and l.value == r.value;
},
.e_number => {
- const l = Expr.Data.Store.Number.at(left.e_number);
- const r = Expr.Data.Store.Number.at(right.e_number);
+ const l = left.e_number;
+ const r = right.e_number;
equality.ok = @as(Expr.Tag, right) == Expr.Tag.e_number;
equality.equal = equality.ok and l.value == r.value;
},
.e_big_int => {
- const l = Expr.Data.Store.BigInt.at(left.e_big_int);
- const r = Expr.Data.Store.BigInt.at(right.e_big_int);
+ const l = left.e_big_int;
+ const r = right.e_big_int;
equality.ok = @as(Expr.Tag, right) == Expr.Tag.e_big_int;
equality.equal = equality.ok and strings.eql(l.value, r.value);
},
.e_string => {
- const l = Expr.Data.Store.String.at(left.e_string);
- const r = Expr.Data.Store.String.at(right.e_string);
+ const l = left.e_string;
+ const r = right.e_string;
equality.ok = @as(Expr.Tag, right) == Expr.Tag.e_string;
if (equality.ok) {
@@ -768,7 +735,7 @@ pub const SideEffects = enum(u2) {
return true;
},
.e_unary => {
- const e = Expr.Data.Store.Unary.at(data.e_unary);
+ const e = data.e_unary;
switch (e.op) {
// number or bigint
.un_pos,
@@ -792,7 +759,7 @@ pub const SideEffects = enum(u2) {
}
},
.e_binary => {
- const e = Expr.Data.Store.Binary.at(data.e_binary);
+ const e = data.e_binary;
switch (e.op) {
// boolean
.bin_lt,
@@ -846,7 +813,7 @@ pub const SideEffects = enum(u2) {
}
},
.e_if => {
- const e = Expr.Data.Store.If.at(data.e_if);
+ const e = data.e_if;
return isPrimitiveWithSideEffects(e.yes.data) and isPrimitiveWithSideEffects(e.no.data);
},
else => {},
@@ -902,8 +869,7 @@ pub const SideEffects = enum(u2) {
return Result{ .value = true, .side_effects = .could_have_side_effects, .ok = true };
},
- .e_unary => {
- const e = Expr.Data.Store.Unary.at(exp.e_unary);
+ .e_unary => |e| {
switch (e.op) {
// Always number or bigint
.un_pos, .un_neg, .un_cpl, .un_pre_dec, .un_pre_inc, .un_post_dec, .un_post_inc => {
@@ -922,8 +888,7 @@ pub const SideEffects = enum(u2) {
}
},
- .e_binary => {
- const e = Expr.Data.Store.Binary.at(exp.e_binary);
+ .e_binary => |e| {
switch (e.op) {
// always string or number or bigint
.bin_add,
@@ -986,20 +951,16 @@ pub const SideEffects = enum(u2) {
.e_null, .e_undefined => {
return Result{ .ok = true, .value = false, .side_effects = .no_side_effects };
},
- .e_boolean => {
- const e = Expr.Data.Store.Boolean.at(exp.e_boolean);
+ .e_boolean => |e| {
return Result{ .ok = true, .value = e.value, .side_effects = .no_side_effects };
},
- .e_number => {
- const e = Expr.Data.Store.Number.at(exp.e_number);
+ .e_number => |e| {
return Result{ .ok = true, .value = e.value != 0.0 and !std.math.isNan(e.value), .side_effects = .no_side_effects };
},
- .e_big_int => {
- const e = Expr.Data.Store.BigInt.at(exp.e_big_int);
+ .e_big_int => |e| {
return Result{ .ok = true, .value = !strings.eqlComptime(e.value, "0"), .side_effects = .no_side_effects };
},
- .e_string => {
- const e = Expr.Data.Store.String.at(exp.e_string);
+ .e_string => |e| {
return Result{ .ok = true, .value = std.math.max(e.value.len, e.utf8.len) > 0, .side_effects = .no_side_effects };
},
.e_function, .e_arrow, .e_reg_exp => {
@@ -1009,7 +970,7 @@ pub const SideEffects = enum(u2) {
return Result{ .ok = true, .value = true, .side_effects = .could_have_side_effects };
},
.e_unary => {
- const e_ = Expr.Data.Store.Unary.at(exp.e_unary);
+ const e_ = exp.e_unary;
switch (e_.op) {
.un_void => {
return Result{ .ok = true, .value = false, .side_effects = .could_have_side_effects };
@@ -1030,7 +991,7 @@ pub const SideEffects = enum(u2) {
}
},
.e_binary => {
- const e_ = Expr.Data.Store.Binary.at(exp.e_binary);
+ const e_ = exp.e_binary;
switch (e_.op) {
.bin_logical_or => {
// "anything || truthy" is truthy
@@ -2008,8 +1969,7 @@ pub const P = struct {
pub fn transposeRequire(p: *P, arg: Expr, transpose_state: anytype) Expr {
switch (arg.data) {
- .e_string => {
- const str = arg.getString();
+ .e_string => |str| {
// Ignore calls to require() if the control flow is provably dead here.
// We don't want to spend time scanning the required files if they will
@@ -2636,14 +2596,10 @@ pub const P = struct {
.e_missing => {
return null;
},
- .e_identifier => {
- const ex = expr.getIdentifier();
-
+ .e_identifier => |ex| {
return p.b(B.Identifier{ .ref = ex.ref }, expr.loc);
},
- .e_array => {
- const ex = expr.getArray();
-
+ .e_array => |ex| {
if (ex.comma_after_spread) |spread| {
invalid_loc.append(spread) catch unreachable;
}
@@ -2672,9 +2628,7 @@ pub const P = struct {
.is_single_line = ex.is_single_line,
}, expr.loc);
},
- .e_object => {
- const ex = expr.getObject();
-
+ .e_object => |ex| {
if (ex.comma_after_spread) |sp| {
invalid_loc.append(sp) catch unreachable;
}
@@ -2726,9 +2680,7 @@ pub const P = struct {
var override: ?ExprNodeIndex = null;
// zig syntax is sometimes painful
switch (expr.*.data) {
- .e_binary => {
- const bin = expr.getBinary();
-
+ .e_binary => |bin| {
if (bin.op == .bin_assign) {
initializer = bin.right;
expr = &bin.left;
@@ -4103,9 +4055,7 @@ pub const P = struct {
// Handle the default export of an abstract class in TypeScript
if (p.options.ts and is_identifier and (p.lexer.token == .t_class or opts.ts_decorators != null) and strings.eqlComptime(name, "abstract")) {
switch (expr.data) {
- .e_identifier => {
- var ident = expr.getIdentifier();
-
+ .e_identifier => |ident| {
var stmtOpts = ParseStatementOptions{
.ts_decorators = opts.ts_decorators,
.is_name_optional = true,
@@ -4933,9 +4883,7 @@ pub const P = struct {
}
if (is_identifier) {
switch (expr.data) {
- .e_identifier => {
- var ident = expr.getIdentifier();
-
+ .e_identifier => |ident| {
if (p.lexer.token == .t_colon and !opts.hasDecorators()) {
_ = try p.pushScopeForParsePass(.label, loc);
defer p.popScope();
@@ -5050,8 +4998,7 @@ pub const P = struct {
if (opts.is_namespace_scope and opts.is_export) {
var decls: []G.Decl = &([_]G.Decl{});
switch (stmt.data) {
- .s_local => {
- const local = stmt.getLocal();
+ .s_local => |local| {
var _decls = try List(G.Decl).initCapacity(p.allocator, local.decls.len);
for (local.decls) |decl| {
try extractDeclsForBinding(decl.binding, &_decls);
@@ -5181,9 +5128,7 @@ pub const P = struct {
const _stmts: []Stmt = stmts.items;
for (_stmts) |stmt| {
switch (stmt.data) {
- .s_local => |local__| {
- var local = stmt.getLocal();
-
+ .s_local => |local| {
if (local.was_ts_import_equals and !local.is_export) {
import_equal_count += 1;
}
@@ -6022,8 +5967,7 @@ pub const P = struct {
if (isDirectivePrologue) {
isDirectivePrologue = false;
switch (stmt.data) {
- .s_expr => {
- const expr = stmt.getExpr();
+ .s_expr => |expr| {
switch (expr.value.data) {
.e_string => {
const str = expr.value.getString();
@@ -6052,9 +5996,7 @@ pub const P = struct {
if (!p.options.suppress_warnings_about_weird_code) {
var needsCheck = true;
switch (stmt.data) {
- .s_return => |retu| {
- const ret = stmt.getReturn();
-
+ .s_return => |ret| {
if (ret.value == null and !p.latest_return_had_semicolon) {
returnWithoutSemicolonStart = stmt.loc.start;
needsCheck = false;
@@ -6635,14 +6577,10 @@ pub const P = struct {
if (had_pure_comment_before and level.lt(.call)) {
expr = try p.parseSuffix(expr, @intToEnum(Level, @enumToInt(Level.call) - 1), errors, flags);
switch (expr.data) {
- .e_call => {
- const ex = expr.getCall();
-
+ .e_call => |ex| {
ex.can_be_unwrapped_if_unused = true;
},
- .e_new => {
- const ex = expr.getNew();
-
+ .e_new => |ex| {
ex.can_be_unwrapped_if_unused = true;
},
else => {},
@@ -6728,14 +6666,10 @@ pub const P = struct {
pub fn markExprAsParenthesized(p: *P, expr: *Expr) void {
switch (expr.data) {
- .e_array => {
- const ex = expr.getArray();
-
+ .e_array => |ex| {
ex.is_parenthesized = true;
},
- .e_object => {
- const ex = expr.getObject();
-
+ .e_object => |ex| {
ex.is_parenthesized = true;
},
else => {
@@ -6811,9 +6745,7 @@ pub const P = struct {
// Handle index signatures
if (p.options.ts and p.lexer.token == .t_colon and wasIdentifier and opts.is_class) {
switch (expr.data) {
- .e_identifier => {
- var ident = expr.getIdentifier();
-
+ .e_identifier => |ident| {
try p.lexer.next();
try p.skipTypeScriptType(.lowest);
try p.lexer.expect(.t_close_bracket);
@@ -6962,9 +6894,7 @@ pub const P = struct {
// Forbid the names "constructor" and "prototype" in some cases
if (!is_computed) {
switch (key.data) {
- .e_string => {
- const str = key.getString();
-
+ .e_string => |str| {
if (str.eql(string, "constructor") or (opts.is_static and str.eql(string, "prototype"))) {
// TODO: fmt error message to include string value.
p.log.addRangeError(p.source, key_range, "Invalid field name") catch unreachable;
@@ -6987,9 +6917,7 @@ pub const P = struct {
// Special-case private identifiers
switch (key.data) {
- .e_private_identifier => {
- const private = key.getPrivateIdentifier();
-
+ .e_private_identifier => |private| {
const name = p.loadNameFromRef(private.ref);
if (strings.eqlComptime(name, "#constructor")) {
p.log.addRangeError(p.source, key_range, "Invalid field name \"#constructor\"") catch unreachable;
@@ -7033,9 +6961,7 @@ pub const P = struct {
// Forbid the names "constructor" and "prototype" in some cases
if (opts.is_class and !is_computed) {
switch (key.data) {
- .e_string => {
- const str = key.getString();
-
+ .e_string => |str| {
if (!opts.is_static and str.eql(string, "constructor")) {
if (kind == .get) {
p.log.addRangeError(p.source, key_range, "Class constructor cannot be a getter") catch unreachable;
@@ -7102,9 +7028,7 @@ pub const P = struct {
// Special-case private identifiers
switch (key.data) {
- .e_private_identifier => {
- const private = key.getPrivateIdentifier();
-
+ .e_private_identifier => |private| {
var declare: Symbol.Kind = undefined;
var suffix: string = "";
switch (kind) {
@@ -8061,9 +7985,7 @@ pub const P = struct {
// Warn about "!a in b" instead of "!(a in b)"
switch (left.data) {
- .e_unary => {
- const unary = expr.getUnary();
-
+ .e_unary => |unary| {
if (unary.op == .un_not) {
// TODO:
// p.log.addRangeWarning(source: ?Source, r: Range, text: string)
@@ -8084,9 +8006,7 @@ pub const P = struct {
// example of code with this problem: https://github.com/mrdoob/three.js/pull/11182.
if (!p.options.suppress_warnings_about_weird_code) {
switch (left.data) {
- .e_unary => {
- const unary = expr.getUnary();
-
+ .e_unary => |unary| {
if (unary.op == .un_not) {
// TODO:
// p.log.addRangeWarning(source: ?Source, r: Range, text: string)
@@ -9223,19 +9143,13 @@ 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 => {
- var st = stmt.getImport();
- },
- .s_class => {
- var st = stmt.getClass();
-
+ .s_import => |st| {},
+ .s_class => |st| {
if (!p.classCanBeRemovedIfUnused(&st.class)) {
return false;
}
},
- .s_expr => {
- var st = stmt.getExpr();
-
+ .s_expr => |st| {
if (st.does_not_affect_tree_shaking) {
// Expressions marked with this are automatically generated and have
// no side effects by construction.
@@ -9244,9 +9158,7 @@ pub const P = struct {
return false;
}
},
- .s_local => {
- var st = stmt.getLocal();
-
+ .s_local => |st| {
for (st.decls) |decl| {
if (!p.bindingCanBeRemovedIfUnused(decl.binding)) {
return false;
@@ -9263,9 +9175,7 @@ pub const P = struct {
// Exports are tracked separately, so this isn't necessary
.s_export_clause, .s_export_from => {},
- .s_export_default => {
- var st = stmt.getExportDefault();
-
+ .s_export_default => |st| {
switch (st.value) {
.stmt => |s2| {
switch (s2.data) {
@@ -9406,14 +9316,12 @@ pub const P = struct {
// Output.print("\nVisit: {s} - {d}\n", .{ @tagName(expr.data), expr.loc.start });
switch (expr.data) {
.e_null, .e_super, .e_boolean, .e_big_int, .e_reg_exp, .e_new_target, .e_undefined => {},
- .e_string => {
- const e_ = expr.getString();
+ .e_string => |e_| {
// If you're using this, you're probably not using 0-prefixed legacy octal notation
// if e.LegacyOctalLoc.Start > 0 {
},
- .e_number => {
- const e_ = expr.getNumber();
+ .e_number => |e_| {
// idc about legacy octal loc
},
@@ -9430,7 +9338,8 @@ pub const P = struct {
},
.e_import_meta => {
- const is_delete_target = std.meta.activeTag(p.delete_target) == .e_import_meta and &expr.data.e_import_meta == &p.delete_target.e_import_meta;
+ // TODO: delete import.meta might not work
+ const is_delete_target = std.meta.activeTag(p.delete_target) == .e_import_meta;
if (p.define.dots.get("meta")) |meta| {
for (meta) |define| {
@@ -9446,15 +9355,11 @@ pub const P = struct {
return p.e(E.Identifier{ .ref = p.import_meta_ref }, expr.loc);
}
},
- .e_spread => {
- const exp = expr.getSpread();
-
+ .e_spread => |exp| {
exp.value = p.visitExpr(exp.value);
},
- .e_identifier => {
- const e_ = expr.getIdentifier();
-
- const is_delete_target = @as(Expr.Tag, p.delete_target) == .e_identifier and expr.data.e_identifier.eql(p.delete_target.e_identifier);
+ .e_identifier => |e_| {
+ const is_delete_target = @as(Expr.Tag, p.delete_target) == .e_identifier and expr.data.e_identifier == p.delete_target.e_identifier;
const name = p.loadNameFromRef(e_.ref);
if (p.isStrictMode() and js_lexer.StrictModeReservedWords.has(name)) {
@@ -9506,13 +9411,9 @@ pub const P = struct {
});
},
.e_private_identifier => {
- const e_ = expr.getPrivateIdentifier();
-
p.panic("Unexpected private identifier. This is an internal error - not your fault.", .{});
},
- .e_jsx_element => {
- const e_ = expr.getJsxElement();
-
+ .e_jsx_element => |e_| {
const tag = tagger: {
if (e_.tag) |_tag| {
break :tagger p.visitExpr(_tag);
@@ -9649,9 +9550,7 @@ pub const P = struct {
}
},
- .e_template => {
- const e_ = expr.getTemplate();
-
+ .e_template => |e_| {
if (e_.tag) |tag| {
e_.tag = p.visitExpr(tag);
}
@@ -9662,14 +9561,10 @@ pub const P = struct {
}
},
- .e_binary => {
- const e_ = expr.getBinary();
-
+ .e_binary => |e_| {
switch (e_.left.data) {
// Special-case private identifiers
- .e_private_identifier => {
- const private = expr.getPrivateIdentifier();
-
+ .e_private_identifier => |private| {
if (e_.op == .bin_in) {
const name = p.loadNameFromRef(private.ref);
const result = p.findSymbol(e_.left.loc, name) catch unreachable;
@@ -9690,8 +9585,8 @@ pub const P = struct {
else => {},
}
- const is_call_target = @as(Expr.Tag, p.call_target) == .e_binary and expr.data.e_binary.eql(p.call_target.e_binary);
- const is_stmt_expr = @as(Expr.Tag, p.stmt_expr_value) == .e_binary and expr.data.e_binary.eql(p.stmt_expr_value.e_binary);
+ const is_call_target = @as(Expr.Tag, p.call_target) == .e_binary and expr.data.e_binary == p.call_target.e_binary;
+ const is_stmt_expr = @as(Expr.Tag, p.stmt_expr_value) == .e_binary and expr.data.e_binary == p.stmt_expr_value.e_binary;
const was_anonymous_named_expr = p.isAnonymousNamedExpr(e_.right);
e_.left = p.visitExprInOut(e_.left, ExprIn{
@@ -9990,11 +9885,9 @@ pub const P = struct {
else => {},
}
},
- .e_index => {
- const e_ = expr.getIndex();
-
- const is_call_target = std.meta.activeTag(p.call_target) == .e_index and expr.data.e_index.eql(p.call_target.e_index);
- const is_delete_target = std.meta.activeTag(p.delete_target) == .e_index and expr.data.e_index.eql(p.delete_target.e_index);
+ .e_index => |e_| {
+ const is_call_target = std.meta.activeTag(p.call_target) == .e_index and expr.data.e_index == p.call_target.e_index;
+ const is_delete_target = std.meta.activeTag(p.delete_target) == .e_index and expr.data.e_index == p.delete_target.e_index;
const target = p.visitExprInOut(e_.target, ExprIn{
// this is awkward due to a zig compiler bug
@@ -10033,9 +9926,7 @@ pub const P = struct {
return p.e(e_, expr.loc);
},
- .e_unary => {
- const e_ = expr.getUnary();
-
+ .e_unary => |e_| {
switch (e_.op) {
.un_typeof => {
e_.value = p.visitExprInOut(e_.value, ExprIn{ .assign_target = e_.op.unaryAssignTarget() });
@@ -10099,11 +9990,9 @@ pub const P = struct {
},
}
},
- .e_dot => {
- const e_ = expr.getDot();
-
- const is_delete_target = @as(Expr.Tag, p.delete_target) == .e_dot and expr.data.e_dot.eql(p.delete_target.e_dot);
- const is_call_target = @as(Expr.Tag, p.call_target) == .e_dot and expr.data.e_dot.eql(p.call_target.e_dot);
+ .e_dot => |e_| {
+ const is_delete_target = @as(Expr.Tag, p.delete_target) == .e_dot and expr.data.e_dot == p.delete_target.e_dot;
+ const is_call_target = @as(Expr.Tag, p.call_target) == .e_dot and expr.data.e_dot == p.call_target.e_dot;
if (p.define.dots.get(e_.name)) |parts| {
for (parts) |define| {
@@ -10129,7 +10018,7 @@ pub const P = struct {
}
// Track ".then().catch()" chains
- if (is_call_target and @as(Expr.Tag, p.then_catch_chain.next_target) == .e_dot and p.then_catch_chain.next_target.e_dot.eql(expr.data.e_dot)) {
+ if (is_call_target and @as(Expr.Tag, p.then_catch_chain.next_target) == .e_dot and p.then_catch_chain.next_target.e_dot == expr.data.e_dot) {
if (strings.eqlComptime(e_.name, "catch")) {
p.then_catch_chain = ThenCatchChain{
.next_target = e_.target.data,
@@ -10158,10 +10047,8 @@ pub const P = struct {
}
}
},
- .e_if => {
- const e_ = expr.getIf();
-
- const is_call_target = @as(Expr.Data, p.call_target) == .e_if and expr.data.e_if.eql(p.call_target.e_if);
+ .e_if => |e_| {
+ const is_call_target = @as(Expr.Data, p.call_target) == .e_if and expr.data.e_if == p.call_target.e_if;
e_.test_ = p.visitExpr(e_.test_);
@@ -10189,22 +10076,16 @@ pub const P = struct {
}
}
},
- .e_await => {
- const e_ = expr.getAwait();
-
+ .e_await => |e_| {
p.await_target = e_.value.data;
e_.value = p.visitExpr(e_.value);
},
- .e_yield => {
- const e_ = expr.getYield();
-
+ .e_yield => |e_| {
if (e_.value) |val| {
e_.value = p.visitExpr(val);
}
},
- .e_array => {
- const e_ = expr.getArray();
-
+ .e_array => |e_| {
if (in.assign_target != .none) {
if (e_.comma_after_spread) |spread| {
p.log.addRangeError(p.source, logger.Range{ .loc = spread, .len = 1 }, "Unexpected \",\" after rest pattern") catch unreachable;
@@ -10212,20 +10093,13 @@ pub const P = struct {
}
var has_spread = false;
- var i: usize = 0;
- while (i < e_.items.len) : (i += 1) {
- var item = e_.items[i];
- const data = item.data;
- switch (data) {
+ for (e_.items) |*item| {
+ switch (item.data) {
.e_missing => {},
- .e_spread => {
- const spread = item.getSpread();
-
+ .e_spread => |spread| {
spread.value = p.visitExprInOut(spread.value, ExprIn{ .assign_target = in.assign_target });
},
- .e_binary => {
- const e2 = item.getBinary();
-
+ .e_binary => |e2| {
if (in.assign_target != .none and e2.op == .bin_assign) {
const was_anonymous_named_expr = p.isAnonymousNamedExpr(e2.right);
e2.left = p.visitExprInOut(e2.left, ExprIn{ .assign_target = .replace });
@@ -10234,24 +10108,21 @@ pub const P = struct {
if (@as(Expr.Tag, e2.left.data) == .e_identifier) {
e2.right = p.maybeKeepExprSymbolName(
e2.right,
- p.symbols.items[e2.left.getIdentifier().ref.inner_index].original_name,
+ p.symbols.items[e2.left.data.e_identifier.ref.inner_index].original_name,
was_anonymous_named_expr,
);
}
} else {
- item = p.visitExprInOut(item, ExprIn{ .assign_target = in.assign_target });
+ item.* = p.visitExprInOut(item.*, ExprIn{ .assign_target = in.assign_target });
}
},
else => {
- item = p.visitExprInOut(item, ExprIn{ .assign_target = in.assign_target });
+ item.* = p.visitExprInOut(item.*, ExprIn{ .assign_target = in.assign_target });
},
}
- e_.items[i] = item;
}
},
- .e_object => {
- const e_ = expr.getObject();
-
+ .e_object => |e_| {
if (in.assign_target != .none) {
p.maybeCommaSpreadError(e_.comma_after_spread);
}
@@ -10305,7 +10176,7 @@ pub const P = struct {
if (@as(Expr.Tag, val.data) == .e_identifier) {
property.initializer = p.maybeKeepExprSymbolName(
property.initializer orelse unreachable,
- p.symbols.items[val.getIdentifier().ref.inner_index].original_name,
+ p.symbols.items[val.data.e_identifier.ref.inner_index].original_name,
was_anonymous_named_expr,
);
}
@@ -10313,27 +10184,23 @@ pub const P = struct {
}
}
},
- .e_import => {
- const e_ = expr.getImport();
-
+ .e_import => |e_| {
const state = TransposeState{
- .is_await_target = if (p.await_target != null) p.await_target.?.e_import.eql(expr.data.e_index) else false,
- .is_then_catch_target = expr.data.e_import.eql(p.then_catch_chain.next_target.e_import) and p.then_catch_chain.has_catch,
+ .is_await_target = if (p.await_target != null) p.await_target.?.e_import == e_ else false,
+ .is_then_catch_target = expr.data.e_import == p.then_catch_chain.next_target.e_import and p.then_catch_chain.has_catch,
.loc = e_.expr.loc,
};
e_.expr = p.visitExpr(e_.expr);
return p.import_transposer.maybeTransposeIf(e_.expr, state);
},
- .e_call => {
- const e_ = expr.getCall();
-
+ .e_call => |e_| {
p.call_target = e_.target.data;
p.then_catch_chain = ThenCatchChain{
.next_target = e_.target.data,
.has_multiple_args = e_.args.len >= 2,
- .has_catch = @as(Expr.Tag, p.then_catch_chain.next_target) == .e_call and p.then_catch_chain.next_target.e_call.eql(expr.data.e_call) and p.then_catch_chain.has_catch,
+ .has_catch = @as(Expr.Tag, p.then_catch_chain.next_target) == .e_call and p.then_catch_chain.next_target.e_call == expr.data.e_call and p.then_catch_chain.has_catch,
};
// Prepare to recognize "require.resolve()" calls
@@ -10350,10 +10217,9 @@ pub const P = struct {
});
// TODO: wan about import namespace call
var has_spread = false;
- var i: usize = 0;
- while (i < e_.args.len) : (i += 1) {
- e_.args[i] = p.visitExpr(e_.args[i]);
- has_spread = has_spread or @as(Expr.Tag, e_.args[i].data) == .e_spread;
+ for (e_.args) |*arg| {
+ arg.* = p.visitExpr(arg.*);
+ has_spread = has_spread or @as(Expr.Tag, arg.data) == .e_spread;
}
if (e_.optional_chain == null and @as(Expr.Tag, e_.target.data) == .e_identifier and e_.target.getIdentifier().ref.eql(p.require_ref)) {
@@ -10370,20 +10236,15 @@ pub const P = struct {
return expr;
},
- .e_new => {
- const e_ = expr.getNew();
-
+ .e_new => |e_| {
e_.target = p.visitExpr(e_.target);
// p.warnA
- var i: usize = 0;
- while (i < e_.args.len) : (i += 1) {
- e_.args[i] = p.visitExpr(e_.args[i]);
+ for (e_.args) |*arg| {
+ arg.* = p.visitExpr(arg.*);
}
},
- .e_arrow => {
- const e_ = expr.getArrow();
-
+ .e_arrow => |e_| {
const old_fn_or_arrow_data = std.mem.toBytes(p.fn_or_arrow_data_visit);
p.fn_or_arrow_data_visit = FnOrArrowDataVisit{
.is_arrow = true,
@@ -10418,16 +10279,13 @@ pub const P = struct {
p.fn_only_data_visit.is_inside_async_arrow_fn = old_inside_async_arrow_fn;
p.fn_or_arrow_data_visit = std.mem.bytesToValue(@TypeOf(p.fn_or_arrow_data_visit), &old_fn_or_arrow_data);
},
- .e_function => {
- const e_ = expr.getFunction();
-
+ .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.?.inner_index].original_name);
}
},
- .e_class => {
- const e_ = expr.getClass();
+ .e_class => |e_| {
// This might be wrong.
_ = p.visitClass(expr.loc, e_);
@@ -10509,8 +10367,7 @@ pub const P = struct {
.s_comment => {
continue;
},
- .s_directive => {
- const dir = stmt.getDirective();
+ .s_directive => |dir| {
if (strings.utf16EqlString(dir.value, "use strict")) {
return stmt.loc;
}
@@ -10585,19 +10442,13 @@ pub const P = struct {
return true;
},
- .e_dot => {
- const ex = expr.getDot();
-
+ .e_dot => |ex| {
return ex.can_be_removed_if_unused;
},
- .e_class => {
- const ex = expr.getClass();
-
+ .e_class => |ex| {
return p.classCanBeRemovedIfUnused(ex);
},
- .e_identifier => {
- const ex = expr.getIdentifier();
-
+ .e_identifier => |ex| {
if (ex.must_keep_due_to_with_stmt) {
return false;
}
@@ -10625,8 +10476,7 @@ pub const P = struct {
return true;
}
},
- .e_import_identifier => {
- const ex = expr.getImportIdentifier();
+ .e_import_identifier => |ex| {
// References to an ES6 import item are always side-effect free in an
// ECMAScript environment.
@@ -10646,14 +10496,10 @@ pub const P = struct {
// references as being side-effect free.
return true;
},
- .e_if => {
- const ex = expr.getIf();
-
+ .e_if => |ex| {
return p.exprCanBeRemovedIfUnused(ex.test_) and p.exprCanBeRemovedIfUnused(ex.yes) and p.exprCanBeRemovedIfUnused(ex.no);
},
- .e_array => {
- const ex = expr.getArray();
-
+ .e_array => |ex| {
for (ex.items) |item| {
if (!p.exprCanBeRemovedIfUnused(item)) {
return false;
@@ -10662,9 +10508,7 @@ pub const P = struct {
return true;
},
- .e_object => {
- const ex = expr.getObject();
-
+ .e_object => |ex| {
for (ex.properties) |property| {
// The key must still be evaluated if it's computed or a spread
@@ -10680,8 +10524,7 @@ pub const P = struct {
}
return true;
},
- .e_call => {
- const ex = expr.getCall();
+ .e_call => |ex| {
// A call that has been marked "__PURE__" can be removed if all arguments
// can be removed. The annotation causes us to ignore the target.
@@ -10695,8 +10538,7 @@ pub const P = struct {
return true;
},
- .e_new => {
- const ex = expr.getNew();
+ .e_new => |ex| {
// A call that has been marked "__PURE__" can be removed if all arguments
// can be removed. The annotation causes us to ignore the target.
@@ -10710,9 +10552,7 @@ pub const P = struct {
return true;
},
- .e_unary => {
- const ex = expr.getUnary();
-
+ .e_unary => |ex| {
switch (ex.op) {
.un_typeof, .un_void, .un_not => {
return p.exprCanBeRemovedIfUnused(ex.value);
@@ -10720,9 +10560,7 @@ pub const P = struct {
else => {},
}
},
- .e_binary => {
- const ex = expr.getBinary();
-
+ .e_binary => |ex| {
switch (ex.op) {
.bin_strict_eq, .bin_strict_ne, .bin_comma, .bin_logical_or, .bin_logical_and, .bin_nullish_coalescing => {
return p.exprCanBeRemovedIfUnused(ex.left) and p.exprCanBeRemovedIfUnused(ex.right);
@@ -10754,7 +10592,7 @@ pub const P = struct {
is_call_target: bool,
) ?Expr {
if (@as(Expr.Tag, target.data) == .e_identifier) {
- const id = target.getIdentifier();
+ const id = target.data.e_identifier;
// Rewrite property accesses on explicit namespace imports as an identifier.
// This lets us replace them easily in the printer to rebind them to
@@ -10843,23 +10681,19 @@ pub const P = struct {
// These don't contain anything to traverse
.s_debugger, .s_empty, .s_comment => {},
- .s_type_script => {
- var data = stmt.getTypeScript();
+ .s_type_script => |data| {
// Erase TypeScript constructs from the output completely
return;
},
- .s_directive => {
- var data = stmt.getDirective();
+ .s_directive => |data| {
// if p.isStrictMode() && s.LegacyOctalLoc.Start > 0 {
// p.markStrictModeFeature(legacyOctalEscape, p.source.RangeOfLegacyOctalEscape(s.LegacyOctalLoc), "")
// }
return;
},
- .s_import => {
- var data = stmt.getImport();
-
+ .s_import => |data| {
try p.recordDeclaredSymbol(data.namespace_ref);
if (data.default_name) |default_name| {
@@ -10872,8 +10706,7 @@ pub const P = struct {
}
}
},
- .s_export_clause => {
- var data = stmt.getExportClause();
+ .s_export_clause => |data| {
// "export {foo}"
var end: usize = 0;
@@ -10902,8 +10735,7 @@ 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 => {
- var data = stmt.getExportFrom();
+ .s_export_from => |data| {
// "export {foo} from 'path'"
const name = p.loadNameFromRef(data.namespace_ref);
@@ -10920,8 +10752,7 @@ pub const P = struct {
item.name.ref = ref;
}
},
- .s_export_star => {
- var data = stmt.getExportStar();
+ .s_export_star => |data| {
// "export {foo} from 'path'"
const name = p.loadNameFromRef(data.namespace_ref);
@@ -10946,9 +10777,7 @@ pub const P = struct {
stmts.appendAssumeCapacity(p.s(S.ExportClause{ .items = items.toOwnedSlice(), .is_single_line = true }, stmt.loc));
}
},
- .s_export_default => {
- var data = stmt.getExportDefault();
-
+ .s_export_default => |data| {
if (data.default_name.ref) |ref| {
try p.recordDeclaredSymbol(ref);
}
@@ -10964,9 +10793,7 @@ pub const P = struct {
// Discard type-only export default statements
if (p.options.ts) {
switch (expr.data) {
- .e_identifier => {
- var ident = expr.getIdentifier();
-
+ .e_identifier => |ident| {
const symbol = p.symbols.items[ident.ref.inner_index];
if (symbol.kind == .unbound) {
if (p.local_type_names.get(symbol.original_name)) |local_type| {
@@ -10983,8 +10810,7 @@ pub const P = struct {
.stmt => |s2| {
switch (s2.data) {
- .s_function => {
- var func = s2.getFunction();
+ .s_function => |func| {
var name: string = "";
if (func.func.name) |func_loc| {
name = p.loadNameFromRef(func_loc.ref.?);
@@ -11002,8 +10828,7 @@ pub const P = struct {
// prevent doubling export default function name
return;
},
- .s_class => {
- var class = s2.getClass();
+ .s_class => |class| {
var shadow_ref = p.visitClass(s2.loc, &class.class);
stmts.appendSlice(p.lowerClass(js_ast.StmtOrExpr{ .stmt = stmt.* }, shadow_ref)) catch unreachable;
return;
@@ -11013,8 +10838,7 @@ pub const P = struct {
},
}
},
- .s_export_equals => {
- var data = stmt.getExportEquals();
+ .s_export_equals => |data| {
// "module.exports = value"
stmts.append(
@@ -11038,9 +10862,7 @@ pub const P = struct {
) catch unreachable;
p.recordUsage(p.module_ref);
},
- .s_break => {
- var data = stmt.getBreak();
-
+ .s_break => |data| {
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);
@@ -11054,9 +10876,7 @@ pub const P = struct {
p.log.addRangeError(p.source, r, "Cannot use \"break\" here") catch unreachable;
}
},
- .s_continue => {
- var data = stmt.getContinue();
-
+ .s_continue => |data| {
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);
@@ -11070,9 +10890,7 @@ pub const P = struct {
p.log.addRangeError(p.source, r, "Cannot use \"continue\" here") catch unreachable;
}
},
- .s_label => {
- var data = stmt.getLabel();
-
+ .s_label => |data| {
p.pushScopeForVisitPass(.label, stmt.loc) catch unreachable;
const name = p.loadNameFromRef(data.name.ref orelse unreachable);
const ref = p.newSymbol(.label, name) catch unreachable;
@@ -11088,9 +10906,7 @@ pub const P = struct {
data.stmt = p.visitSingleStmt(data.stmt, StmtsKind.none);
p.popScope();
},
- .s_local => {
- var data = stmt.getLocal();
-
+ .s_local => |data| {
for (data.decls) |*d| {
p.visitBinding(d.binding, null);
@@ -11135,21 +10951,16 @@ pub const P = struct {
// TODO: do we need to relocate vars? I don't think so.
if (data.kind == .k_var) {}
},
- .s_expr => {
- var data = stmt.getExpr();
-
+ .s_expr => |data| {
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 => {
- var data = stmt.getThrow();
-
+ .s_throw => |data| {
data.value = p.visitExpr(data.value);
},
- .s_return => {
- var data = stmt.getReturn();
+ .s_return => |data| {
// Forbid top-level return inside modules with ECMAScript-style exports
if (p.fn_or_arrow_data_visit.is_outside_fn_or_arrow) {
@@ -11178,9 +10989,7 @@ pub const P = struct {
}
}
},
- .s_block => {
- var data = stmt.getBlock();
-
+ .s_block => |data| {
{
p.pushScopeForVisitPass(.block, stmt.loc) catch unreachable;
@@ -11206,30 +11015,22 @@ pub const P = struct {
stmts.append(stmt.*) catch unreachable;
return;
},
- .s_with => {
- var data = stmt.getWith();
-
+ .s_with => |data| {
notimpl();
},
- .s_while => {
- var data = stmt.getWhile();
-
+ .s_while => |data| {
data.test_ = p.visitExpr(data.test_);
data.body = p.visitLoopBody(data.body);
// TODO: simplify boolean expression
},
- .s_do_while => {
- var data = stmt.getDoWhile();
-
+ .s_do_while => |data| {
data.test_ = p.visitExpr(data.test_);
data.body = p.visitLoopBody(data.body);
// TODO: simplify boolean expression
},
- .s_if => {
- var data = stmt.getIf();
-
+ .s_if => |data| {
data.test_ = p.visitExpr(data.test_);
const effects = SideEffects.toBoolean(data.test_.data);
@@ -11259,9 +11060,7 @@ pub const P = struct {
}
}
},
- .s_for => {
- var data = stmt.getFor();
-
+ .s_for => |data| {
{
p.pushScopeForVisitPass(.block, stmt.loc) catch unreachable;
@@ -11285,9 +11084,7 @@ pub const P = struct {
// TODO: Potentially relocate "var" declarations to the top level
},
- .s_for_in => {
- var data = stmt.getForIn();
-
+ .s_for_in => |data| {
{
p.pushScopeForVisitPass(.block, stmt.loc) catch unreachable;
defer p.popScope();
@@ -11312,9 +11109,7 @@ pub const P = struct {
// }
}
},
- .s_for_of => {
- var data = stmt.getForOf();
-
+ .s_for_of => |data| {
p.pushScopeForVisitPass(.block, stmt.loc) catch unreachable;
defer p.popScope();
_ = p.visitForLoopInit(data.init, true);
@@ -11331,9 +11126,7 @@ pub const P = struct {
// p.lowerObjectRestInForLoopInit(s.Init, &s.Body)
},
- .s_try => {
- var data = stmt.getTry();
-
+ .s_try => |data| {
p.pushScopeForVisitPass(.block, stmt.loc) catch unreachable;
{
var _stmts = List(Stmt).fromOwnedSlice(p.allocator, data.body);
@@ -11367,9 +11160,7 @@ pub const P = struct {
p.popScope();
}
},
- .s_switch => {
- var data = stmt.getSwitch();
-
+ .s_switch => |data| {
data.test_ = p.visitExpr(data.test_);
{
p.pushScopeForVisitPass(.block, data.body_loc) catch unreachable;
@@ -11394,9 +11185,7 @@ pub const P = struct {
// TODO: duplicate case checker
},
- .s_function => {
- var data = stmt.getFunction();
-
+ .s_function => |data| {
data.func = p.visitFunc(data.func, data.func.open_parens_loc);
// Handle exporting this function from a namespace
@@ -11427,9 +11216,7 @@ pub const P = struct {
// );
return;
},
- .s_class => {
- var data = stmt.getClass();
-
+ .s_class => |data| {
const shadow_ref = p.visitClass(stmt.loc, &data.class);
// Remove the export flag inside a namespace
@@ -11452,9 +11239,7 @@ pub const P = struct {
return;
},
- .s_enum => {
- var data = stmt.getEnum();
-
+ .s_enum => |data| {
p.recordDeclaredSymbol(data.name.ref.?) catch unreachable;
p.pushScopeForVisitPass(.entry, stmt.loc) catch unreachable;
defer p.popScope();
@@ -11498,17 +11283,14 @@ pub const P = struct {
if (enum_value.value != null) {
enum_value.value = p.visitExpr(enum_value.value.?);
switch (enum_value.value.?.data) {
- .e_number => {
- const num = assign_target.getNumber();
+ .e_number => |num| {
// prob never allocates in practice
values_so_far.put(name.string(p.allocator) catch unreachable, num.value) catch unreachable;
has_numeric_value = true;
next_numeric_value = num.value + 1.0;
},
- .e_string => {
- const str = assign_target.getString();
-
+ .e_string => |str| {
has_string_value = true;
},
else => {},
@@ -11575,9 +11357,7 @@ pub const P = struct {
);
return;
},
- .s_namespace => {
- var data = stmt.getNamespace();
-
+ .s_namespace => |data| {
p.recordDeclaredSymbol(data.name.ref.?) catch unreachable;
// Scan ahead for any variables inside this namespace. This must be done
@@ -11586,9 +11366,7 @@ 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__| {
- var local = stmt.getLocal();
-
+ .s_local => |local| {
if (local.is_export) {
p.markExportedDeclsInsideNamespace(data.arg, local.decls);
}
@@ -11832,16 +11610,12 @@ pub const P = struct {
pub fn visitForLoopInit(p: *P, stmt: Stmt, is_in_or_of: bool) Stmt {
switch (stmt.data) {
- .s_expr => {
- var st = stmt.getExpr();
-
+ .s_expr => |st| {
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 => {
- var st = stmt.getLocal();
-
+ .s_local => |st| {
for (st.decls) |*dec| {
p.visitBinding(dec.binding, null);
if (dec.value) |val| {
@@ -11891,14 +11665,10 @@ pub const P = struct {
.e_arrow => {
return true;
},
- .e_function => {
- const func = expr.getFunction();
-
+ .e_function => |func| {
return func.func.name == null;
},
- .e_class => {
- const class = expr.getClass();
-
+ .e_class => |class| {
return class.class_name == null;
},
else => {
@@ -11910,7 +11680,7 @@ pub const P = struct {
pub fn valueForDefine(p: *P, loc: logger.Loc, assign_target: js_ast.AssignTarget, is_delete_target: bool, define_data: *const DefineData) Expr {
switch (define_data.value) {
.e_identifier => {
- var ident = Expr.Data.Store.Identifier.at(define_data.value.e_identifier);
+ var ident = define_data.value.e_identifier;
return p.handleIdentifier(
loc,
@@ -11934,9 +11704,7 @@ pub const P = struct {
pub fn isDotDefineMatch(p: *P, expr: Expr, parts: []const string) bool {
switch (expr.data) {
- .e_dot => {
- const ex = expr.getDot();
-
+ .e_dot => |ex| {
if (parts.len > 1) {
if (ex.optional_chain != null) {
return false;
@@ -11951,8 +11719,7 @@ pub const P = struct {
.e_import_meta => {
return parts.len == 2 and strings.eqlComptime(parts[0], "import") and strings.eqlComptime(parts[1], "meta");
},
- .e_identifier => {
- const ex = expr.getIdentifier();
+ .e_identifier => |ex| {
// The last expression must be an identifier
if (parts.len == 1) {
@@ -12301,8 +12068,7 @@ pub const P = struct {
// moves this statement to the end when it generates code.
break :list_getter &after;
},
- .s_function => {
- var data = stmt.getFunction();
+ .s_function => |data| {
// 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
@@ -12446,7 +12212,7 @@ pub const P = struct {
// Eat the comma token
try p.lexer.next();
}
- var items = items_list.toOwnedSlice();
+ var items = if (items_list.capacity > 0) items_list.toOwnedSlice() else &([_]Expr{});
// The parenthetical construct must end with a close parenthesis
try p.lexer.expect(.t_close_paren);
@@ -12755,9 +12521,6 @@ 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);
- Expr.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 de467a105..698eb3227 100644
--- a/src/js_printer.zig
+++ b/src/js_printer.zig
@@ -1473,7 +1473,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
var wrap = false;
if (p.call_target) |target| {
- wrap = e.was_originally_identifier and target.e_import_identifier.index == expr.data.e_import_identifier.index;
+ wrap = e.was_originally_identifier and target.e_import_identifier == expr.data.e_import_identifier;
}
if (wrap) {
@@ -2870,26 +2870,26 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
while (true) {
switch (s.*) {
.s_if => |index| {
- if (Stmt.Data.Store.If.at(index).no) |*no| {
+ if (index.no) |*no| {
s = &no.data;
} else {
return true;
}
},
.s_for => |current| {
- s = &Stmt.Data.Store.For.at(current).body.data;
+ s = &current.body.data;
},
.s_for_in => |current| {
- s = &Stmt.Data.Store.ForIn.at(current).body.data;
+ s = &current.body.data;
},
.s_for_of => |current| {
- s = &Stmt.Data.Store.ForOf.at(current).body.data;
+ s = &current.body.data;
},
.s_while => |current| {
- s = &Stmt.Data.Store.While.at(current).body.data;
+ s = &current.body.data;
},
.s_with => |current| {
- s = &Stmt.Data.Store.With.at(current).body.data;
+ s = &current.body.data;
},
else => {
return false;