diff options
author | 2021-05-30 00:17:17 -0700 | |
---|---|---|
committer | 2021-05-30 00:17:17 -0700 | |
commit | d1db1fdd79ae34f443c3ab701016790737980458 (patch) | |
tree | 43f635d7a7959e578330c43d20b6f52d623acbc0 | |
parent | 2a54b9f13803a06514c1681464a4a86c0c15f978 (diff) | |
download | bun-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.json | 2 | ||||
-rw-r--r-- | src/bundler.zig | 19 | ||||
-rw-r--r-- | src/cli.zig | 1 | ||||
-rw-r--r-- | src/js_ast.zig | 625 | ||||
-rw-r--r-- | src/js_parser/js_parser.zig | 589 | ||||
-rw-r--r-- | src/js_printer.zig | 14 |
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 = ¤t.body.data; }, .s_for_in => |current| { - s = &Stmt.Data.Store.ForIn.at(current).body.data; + s = ¤t.body.data; }, .s_for_of => |current| { - s = &Stmt.Data.Store.ForOf.at(current).body.data; + s = ¤t.body.data; }, .s_while => |current| { - s = &Stmt.Data.Store.While.at(current).body.data; + s = ¤t.body.data; }, .s_with => |current| { - s = &Stmt.Data.Store.With.at(current).body.data; + s = ¤t.body.data; }, else => { return false; |