diff options
author | 2021-09-12 00:37:13 -0700 | |
---|---|---|
committer | 2021-09-12 00:37:13 -0700 | |
commit | 57ca04444b0397c5fd92177382627cf5113282b5 (patch) | |
tree | 30a69d3738d61a829e396eeda876e66abd571c9c | |
parent | 125d88bd6540be5b751404165c69d1c6fdaae322 (diff) | |
download | bun-57ca04444b0397c5fd92177382627cf5113282b5.tar.gz bun-57ca04444b0397c5fd92177382627cf5113282b5.tar.zst bun-57ca04444b0397c5fd92177382627cf5113282b5.zip |
Fix symbol collisions for JSX & React Refresh. Choose a JSX identifier based on the user's JSX import source
-rw-r--r-- | src/js_parser/js_parser.zig | 478 |
1 files changed, 332 insertions, 146 deletions
diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig index 95f2d37c6..cb79e0f77 100644 --- a/src/js_parser/js_parser.zig +++ b/src/js_parser/js_parser.zig @@ -17,6 +17,9 @@ usingnamespace @import("imports.zig"); const TemplatePartTuple = std.meta.Tuple(&[_]type{ []E.TemplatePart, logger.Loc }); const ScopeOrderList = std.ArrayListUnmanaged(?ScopeOrder); +const JSXFactoryName = "JSX"; +const JSXAutomaticName = "jsx_module"; + pub fn ExpressionTransposer( comptime Kontext: type, visitor: fn (ptr: *Kontext, arg: Expr, state: anytype) Expr, @@ -1916,12 +1919,11 @@ pub const Parser = struct { // Auto-import JSX if (p.options.jsx.parse) { - const jsx_symbol: Symbol = p.symbols.items[p.jsx_runtime_ref.inner_index]; - const jsx_static_symbol: Symbol = p.symbols.items[p.jsxs_runtime_ref.inner_index]; - - const jsx_fragment_symbol: Symbol = p.symbols.items[p.jsx_fragment_ref.inner_index]; - const jsx_factory_symbol: Symbol = p.symbols.items[p.jsx_factory_ref.inner_index]; - const jsx_filename_symbol = p.symbols.items[p.jsx_filename_ref.inner_index]; + const jsx_symbol: *const Symbol = &p.symbols.items[p.jsx_runtime_ref.inner_index]; + const jsx_static_symbol: *const Symbol = &p.symbols.items[p.jsxs_runtime_ref.inner_index]; + const jsx_fragment_symbol: *const Symbol = &p.symbols.items[p.jsx_fragment_ref.inner_index]; + const jsx_factory_symbol: *const Symbol = &p.symbols.items[p.jsx_factory_ref.inner_index]; + const jsx_filename_symbol: *const Symbol = &p.symbols.items[p.jsx_filename_ref.inner_index]; // Currently, React (and most node_modules) ship a CJS version or a UMD version // but we should assume that it'll pretty much always be CJS @@ -1983,6 +1985,19 @@ pub const Parser = struct { var stmt_i: usize = 0; if (jsx_symbol.use_count_estimate > 0 or jsx_static_symbol.use_count_estimate > 0) { + if (jsx_automatic_symbol.use_count_estimate > 0) { + if (jsx_automatic_symbol.link != null) { + p.symbols.items[p.jsx_automatic_ref.inner_index].link = null; + p.symbols.items[p.jsx_automatic_ref.inner_index].original_name = try std.fmt.allocPrint( + p.allocator, + "jsxImport{x}", + .{ + @truncate(u16, std.hash.Wyhash.hash(0, p.options.jsx.import_source)), + }, + ); + } + } + declared_symbols[declared_symbols_i] = .{ .ref = automatic_namespace_ref, .is_top_level = true }; declared_symbols_i += 1; @@ -1998,6 +2013,17 @@ pub const Parser = struct { }; if (jsx_symbol.use_count_estimate > 0) { + if (jsx_symbol.link != null) { + p.symbols.items[p.jsx_runtime_ref.inner_index].link = null; + p.symbols.items[p.jsx_runtime_ref.inner_index].original_name = try std.fmt.allocPrint( + p.allocator, + "jsx_{x}", + .{ + @truncate(u16, std.hash.Wyhash.hash(0, p.options.jsx.import_source)), + }, + ); + } + declared_symbols[declared_symbols_i] = .{ .ref = p.jsx_runtime_ref, .is_top_level = true }; declared_symbols_i += 1; @@ -2022,6 +2048,17 @@ pub const Parser = struct { } if (jsx_static_symbol.use_count_estimate > 0) { + if (jsx_static_symbol.link != null) { + p.symbols.items[p.jsxs_runtime_ref.inner_index].link = null; + p.symbols.items[p.jsxs_runtime_ref.inner_index].original_name = try std.fmt.allocPrint( + p.allocator, + "jsxs_{x}", + .{ + @truncate(u16, std.hash.Wyhash.hash(0, p.options.jsx.import_source)), + }, + ); + } + declared_symbols[declared_symbols_i] = .{ .ref = p.jsxs_runtime_ref, .is_top_level = true }; declared_symbols_i += 1; @@ -2047,6 +2084,15 @@ pub const Parser = struct { } if (jsx_filename_symbol.use_count_estimate > 0) { + if (jsx_filename_symbol.link != null) { + p.symbols.items[p.jsx_filename_ref.inner_index].link = null; + p.symbols.items[p.jsx_filename_ref.inner_index].original_name = try std.fmt.allocPrint( + p.allocator, + "jsxFilename_{x}", + .{@truncate(u16, std.hash.Wyhash.hash(0, p.options.jsx.import_source))}, + ); + } + declared_symbols[declared_symbols_i] = .{ .ref = p.jsx_filename_ref, .is_top_level = true }; declared_symbols_i += 1; decls[decl_i] = G.Decl{ @@ -2091,6 +2137,14 @@ pub const Parser = struct { } if (jsx_classic_symbol.use_count_estimate > 0) { + if (jsx_classic_symbol.link != null) { + p.symbols.items[p.jsx_classic_ref.inner_index].link = null; + p.symbols.items[p.jsx_classic_ref.inner_index].original_name = try std.fmt.allocPrint(p.allocator, "{s}${x}", .{ + p.symbols.items[p.jsx_classic_ref.inner_index].original_name, + jsx_classic_symbol.use_count_estimate, + }); + } + const classic_identifier = p.e(E.Identifier{ .ref = classic_namespace_ref }, loc); const dot_call_target = brk: { @@ -2106,6 +2160,14 @@ pub const Parser = struct { }; if (jsx_factory_symbol.use_count_estimate > 0) { + if (jsx_factory_symbol.link != null) { + p.symbols.items[p.jsx_factory_ref.inner_index].link = null; + p.symbols.items[p.jsx_factory_ref.inner_index].original_name = try std.fmt.allocPrint(p.allocator, "{s}${x}", .{ + p.symbols.items[p.jsx_factory_ref.inner_index].original_name, + jsx_factory_symbol.use_count_estimate, + }); + } + declared_symbols[declared_symbols_i] = .{ .ref = p.jsx_factory_ref, .is_top_level = true }; declared_symbols_i += 1; decls[decl_i] = G.Decl{ @@ -2129,6 +2191,14 @@ pub const Parser = struct { } if (jsx_fragment_symbol.use_count_estimate > 0) { + if (jsx_fragment_symbol.link != null) { + p.symbols.items[p.jsx_fragment_ref.inner_index].link = null; + p.symbols.items[p.jsx_fragment_ref.inner_index].original_name = try std.fmt.allocPrint(p.allocator, "{s}${x}", .{ + p.symbols.items[p.jsx_fragment_ref.inner_index].original_name, + jsx_fragment_symbol.use_count_estimate, + }); + } + declared_symbols[declared_symbols_i] = .{ .ref = p.jsx_fragment_ref, .is_top_level = true }; declared_symbols_i += 1; decls[decl_i] = G.Decl{ @@ -2176,7 +2246,14 @@ pub const Parser = struct { if (p.options.features.react_fast_refresh) { defer did_import_fast_refresh = true; - const refresh_runtime_symbol: Symbol = p.symbols.items[p.jsx_refresh_runtime_ref.inner_index]; + const refresh_runtime_symbol: *const Symbol = &p.symbols.items[p.jsx_refresh_runtime_ref.inner_index]; + if (refresh_runtime_symbol.link != null) { + p.symbols.items[p.jsx_refresh_runtime_ref.inner_index].link = null; + p.symbols.items[p.jsx_refresh_runtime_ref.inner_index].original_name = try std.fmt.allocPrint(p.allocator, "{s}${x}", .{ + p.symbols.items[p.jsx_refresh_runtime_ref.inner_index].original_name, + refresh_runtime_symbol.use_count_estimate, + }); + } declared_symbols[declared_symbols_i] = .{ .ref = p.jsx_refresh_runtime_ref, .is_top_level = true }; declared_symbols_i += 1; @@ -2231,7 +2308,15 @@ pub const Parser = struct { }, loc); p.recordUsage(p.jsx_refresh_runtime_ref); - const refresh_runtime_symbol: Symbol = p.symbols.items[p.jsx_refresh_runtime_ref.inner_index]; + const refresh_runtime_symbol: *const Symbol = &p.symbols.items[p.jsx_refresh_runtime_ref.inner_index]; + if (refresh_runtime_symbol.link != null) { + p.symbols.items[p.jsx_refresh_runtime_ref.inner_index].link = null; + p.symbols.items[p.jsx_refresh_runtime_ref.inner_index].original_name = try std.fmt.allocPrint(p.allocator, "{s}${x}", .{ + p.symbols.items[p.jsx_refresh_runtime_ref.inner_index].original_name, + refresh_runtime_symbol.use_count_estimate, + }); + } + p.named_imports.put( p.jsx_refresh_runtime_ref, js_ast.NamedImport{ @@ -2475,6 +2560,7 @@ pub const Prefill = struct { pub var CommonJS = "__commonJS"; pub var ReExport = "__reExport"; pub var ToModule = "__toModule"; + const JSXShortname = "jsx"; }; }; @@ -3154,7 +3240,7 @@ pub fn NewParser( } } - pub fn logArrowArgErrors(p: *P, errors: *DeferredArrowArgErrors) void { + fn logArrowArgErrors(p: *P, errors: *DeferredArrowArgErrors) void { if (errors.invalid_expr_await.len > 0) { var r = errors.invalid_expr_await; p.log.addRangeError(p.source, r, "Cannot use an \"await\" expression here") catch unreachable; @@ -3166,7 +3252,7 @@ pub fn NewParser( } } - pub fn keyNameForError(p: *P, key: js_ast.Expr) string { + fn keyNameForError(p: *P, key: js_ast.Expr) string { switch (key.data) { .e_string => { return p.lexer.raw(); @@ -3181,7 +3267,7 @@ pub fn NewParser( } } - pub fn canMergeSymbols(p: *P, scope: *js_ast.Scope, existing: Symbol.Kind, new: Symbol.Kind) SymbolMergeResult { + fn canMergeSymbols(p: *P, scope: *js_ast.Scope, existing: Symbol.Kind, new: Symbol.Kind) SymbolMergeResult { if (existing == .unbound) { return .replace_with_new; } @@ -3405,32 +3491,54 @@ pub fn NewParser( p.hoistSymbols(p.module_scope); - p.exports_ref = try p.declareSymbol(.hoisted, logger.Loc.Empty, "exports"); - p.module_ref = try p.declareSymbol(.hoisted, logger.Loc.Empty, "module"); + var generated_symbols_count: u32 = 3; + + if (p.options.enable_bundling) { + generated_symbols_count += 4; + } + + if (p.options.features.hot_module_reloading) { + generated_symbols_count += 3; + + if (is_react_fast_refresh_enabled) { + generated_symbols_count += 1; + } + } + + if (is_jsx_enabled) { + generated_symbols_count += 7; + + if (p.options.jsx.development) generated_symbols_count += 1; + } + + try p.module_scope.generated.ensureUnusedCapacity(generated_symbols_count); + + p.exports_ref = try p.declareCommonJSSymbol(.unbound, "exports"); + p.module_ref = try p.declareCommonJSSymbol(.unbound, "module"); p.require_ref = try p.declareCommonJSSymbol(.unbound, "require"); if (p.options.enable_bundling) { - p.bundle_export_ref = try p.declareSymbol(.unbound, logger.Loc.Empty, "IF_YOU_SEE_THIS_ITS_A_BUNDLER_BUG_PLEASE_FILE_AN_ISSUE_THX"); - p.runtime_imports.__reExport = try p.declareSymbol(.unbound, logger.Loc.Empty, "__reExport"); - p.runtime_imports.register = try p.declareSymbol(.unbound, logger.Loc.Empty, "$$m"); - p.runtime_imports.lazy_export = try p.declareSymbol(.unbound, logger.Loc.Empty, "$$lzy"); + p.bundle_export_ref = try p.declareGeneratedSymbol(.other, "IF_YOU_SEE_THIS_ITS_A_BUNDLER_BUG_PLEASE_FILE_AN_ISSUE_THX"); + p.runtime_imports.__reExport = try p.declareGeneratedSymbol(.other, "__reExport"); + p.runtime_imports.register = try p.declareGeneratedSymbol(.other, "$$m"); + p.runtime_imports.lazy_export = try p.declareGeneratedSymbol(.other, "$$lzy"); p.runtime_imports.__export = p.exports_ref; - } else {} + } if (p.options.features.hot_module_reloading) { - p.hmr_module_ref = try p.declareSymbol(.hoisted, logger.Loc.Empty, "__hmrModule"); + p.hmr_module_ref = try p.declareGeneratedSymbol(.other, "__hmrModule"); if (is_react_fast_refresh_enabled) { - p.jsx_refresh_runtime_ref = try p.declareSymbol(.hoisted, logger.Loc.Empty, "__RefreshRuntime"); + p.jsx_refresh_runtime_ref = try p.declareGeneratedSymbol(.other, "__RefreshRuntime"); - p.runtime_imports.__FastRefreshModule = try p.declareSymbol(.hoisted, logger.Loc.Empty, "__FastRefreshModule"); + p.runtime_imports.__FastRefreshModule = try p.declareGeneratedSymbol(.other, "__FastRefreshModule"); p.recordUsage(p.runtime_imports.__FastRefreshModule.?); } else { - p.runtime_imports.__HMRModule = try p.declareSymbol(.hoisted, logger.Loc.Empty, "__HMRModule"); + p.runtime_imports.__HMRModule = try p.declareGeneratedSymbol(.other, "__HMRModule"); p.recordUsage(p.runtime_imports.__HMRModule.?); } - p.runtime_imports.__HMRClient = try p.declareSymbol(.hoisted, logger.Loc.Empty, "__HMRClient"); + p.runtime_imports.__HMRClient = try p.declareGeneratedSymbol(.other, "__HMRClient"); p.recordUsage(p.hmr_module_ref); p.recordUsage(p.runtime_imports.__HMRClient.?); } else { @@ -3440,28 +3548,40 @@ pub fn NewParser( if (is_jsx_enabled) { if (p.options.jsx.development) { - p.jsx_filename_ref = p.newSymbol(.hoisted, Prefill.Runtime.JSXFilename) catch unreachable; + p.jsx_filename_ref = p.declareGeneratedSymbol(.other, Prefill.Runtime.JSXFilename) catch unreachable; } - p.jsx_fragment_ref = p.declareSymbol(.hoisted, logger.Loc.Empty, p.options.jsx.fragment[p.options.jsx.fragment.len - 1]) catch unreachable; - p.jsx_runtime_ref = p.declareSymbol(.hoisted, logger.Loc.Empty, p.options.jsx.jsx) catch unreachable; - p.jsxs_runtime_ref = p.declareSymbol(.hoisted, logger.Loc.Empty, p.options.jsx.jsx_static) catch unreachable; - p.jsx_factory_ref = p.declareSymbol(.hoisted, logger.Loc.Empty, p.options.jsx.factory[p.options.jsx.factory.len - 1]) catch unreachable; + p.jsx_fragment_ref = p.declareGeneratedSymbol(.other, p.options.jsx.fragment[p.options.jsx.fragment.len - 1]) catch unreachable; + p.jsx_runtime_ref = p.declareGeneratedSymbol(.other, Prefill.Runtime.JSXShortname) catch unreachable; + p.jsxs_runtime_ref = p.declareGeneratedSymbol(.other, p.options.jsx.jsx_static) catch unreachable; + p.jsx_factory_ref = p.declareGeneratedSymbol(.other, p.options.jsx.factory[p.options.jsx.factory.len - 1]) catch unreachable; if (p.options.jsx.factory.len > 1 or FeatureFlags.jsx_runtime_is_cjs) { - const source_name_base = fs.PathName.init(p.options.jsx.factory[0]).nonUniqueNameString(p.allocator) catch unreachable; - const namespace_name = strings.cat(p.allocator, source_name_base, if (source_name_base[source_name_base.len - 1] == '_') "dot_jsx" else "_dot_jsx") catch unreachable; - p.jsx_classic_ref = p.declareSymbol(.hoisted, logger.Loc.Empty, namespace_name) catch unreachable; + p.jsx_classic_ref = p.declareGeneratedSymbol(.other, JSXFactoryName) catch unreachable; } if (p.options.jsx.import_source.len > 0) { - const source_name_base = fs.PathName.init(p.options.jsx.import_source).nonUniqueNameString(p.allocator) catch unreachable; - const namespace_name = strings.cat(p.allocator, source_name_base, if (source_name_base[source_name_base.len - 1] == '_') "runtime" else "_runtime") catch unreachable; - p.jsx_automatic_ref = p.declareSymbol(.hoisted, logger.Loc.Empty, namespace_name) catch unreachable; + var jsx_symbol_name: string = JSXAutomaticName; + // try to do: + // var jsx = react.jsxDEV; + // var jsx = emotion.jsxDEV; + if (isPackagePath(p.options.jsx.import_source)) { + var basename = p.options.jsx.import_source; + basename = if (basename[0] == '@') basename[1..] else basename; + if (strings.indexOfChar(basename, '/')) |path_end| { + if (basename[0..path_end].len > 0) { + if (js_lexer.isIdentifier(basename[0..path_end])) { + jsx_symbol_name = basename[0..path_end]; + } + } + } + } + + p.jsx_automatic_ref = p.declareGeneratedSymbol(.other, jsx_symbol_name) catch unreachable; } } } - pub fn hoistSymbols(p: *P, scope: *js_ast.Scope) void { + fn hoistSymbols(p: *P, scope: *js_ast.Scope) void { if (!scope.kindStopsHoisting()) { var iter = scope.members.iterator(); nextMember: while (iter.next()) |res| { @@ -3494,8 +3614,8 @@ pub fn NewParser( } if (_scope.members.getEntryWithHash(symbol.original_name, hash)) |existing_member_entry| { - const existing_member = existing_member_entry.value; - const existing_symbol: Symbol = p.symbols.items[existing_member.ref.inner_index]; + const existing_member = &existing_member_entry.value; + const existing_symbol: *const Symbol = &p.symbols.items[existing_member.ref.inner_index]; // We can hoist the symbol from the child scope into the symbol in // this scope if: @@ -3512,6 +3632,34 @@ pub fn NewParser( symbol.link = existing_member.ref; continue :nextMember; } + + // Otherwise if this isn't a catch identifier, it's a collision + if (existing_symbol.kind != .catch_identifier) { + + // An identifier binding from a catch statement and a function + // declaration can both silently shadow another hoisted symbol + if (symbol.kind != .catch_identifier and symbol.kind != .hoisted_function) { + const r = js_lexer.rangeOfIdentifier(p.source, res.value.loc); + var notes = p.allocator.alloc(logger.Data, 1) catch unreachable; + notes[0] = + logger.rangeData( + p.source, + r, + std.fmt.allocPrint(p.allocator, "{s} has already been declared", .{symbol.original_name}) catch unreachable, + ); + + p.log.addRangeErrorFmtWithNotes( + p.source, + js_lexer.rangeOfIdentifier(p.source, existing_member_entry.value.loc), + p.allocator, + notes, + "{s} was originally declared here", + .{existing_symbol.original_name}, + ) catch unreachable; + } + + continue :nextMember; + } } if (_scope.kindStopsHoisting()) { @@ -3528,13 +3676,13 @@ pub fn NewParser( } } - pub fn nextScopeInOrderForVisitPass(p: *P) ScopeOrder { + fn nextScopeInOrderForVisitPass(p: *P) ScopeOrder { const head = p.scope_order_to_visit[0]; p.scope_order_to_visit = p.scope_order_to_visit[1..p.scope_order_to_visit.len]; return head; } - pub fn pushScopeForVisitPass(p: *P, kind: js_ast.Scope.Kind, loc: logger.Loc) !void { + fn pushScopeForVisitPass(p: *P, kind: js_ast.Scope.Kind, loc: logger.Loc) !void { // Output.print("\n+Loc: {d}\n", .{loc.start}); // for (p.scopes_in_order.items[p.scopes_in_order_visitor_index..p.scopes_in_order.items.len]) |scope_order, i| { // if (scope_order) |ord| { @@ -3553,7 +3701,7 @@ pub fn NewParser( try p.scopes_for_current_part.append(order.scope); } - pub fn pushScopeForParsePass(p: *P, comptime kind: js_ast.Scope.Kind, loc: logger.Loc) !usize { + fn pushScopeForParsePass(p: *P, comptime kind: js_ast.Scope.Kind, loc: logger.Loc) !usize { debugl("<pushScopeForParsePass>"); defer debugl("</pushScopeForParsePass>"); var parent: *Scope = p.current_scope; @@ -3620,7 +3768,7 @@ pub fn NewParser( // from expression to binding should be written to "invalidLog" instead. That // way we can potentially keep this as an expression if it turns out it's not // needed as a binding after all. - pub fn convertExprToBinding(p: *P, expr: ExprNodeIndex, invalid_loc: *LocList) ?Binding { + fn convertExprToBinding(p: *P, expr: ExprNodeIndex, invalid_loc: *LocList) ?Binding { switch (expr.data) { .e_missing => { return null; @@ -3710,7 +3858,7 @@ pub fn NewParser( return null; } - pub fn convertExprToBindingAndInitializer(p: *P, _expr: *ExprNodeIndex, invalid_log: *LocList, is_spread: bool) ExprBindingTuple { + fn convertExprToBindingAndInitializer(p: *P, _expr: *ExprNodeIndex, invalid_log: *LocList, is_spread: bool) ExprBindingTuple { var initializer: ?ExprNodeIndex = null; var expr = _expr; var override: ?ExprNodeIndex = null; @@ -3737,11 +3885,11 @@ pub fn NewParser( return ExprBindingTuple{ .binding = bind, .expr = initializer }; } - pub fn forbidLexicalDecl(p: *P, loc: logger.Loc) !void { + fn forbidLexicalDecl(p: *P, loc: logger.Loc) !void { try p.log.addRangeError(p.source, p.lexer.range(), "Cannot use a declaration in a single-statement context"); } - pub fn logExprErrors(p: *P, errors: *DeferredErrors) void { + fn logExprErrors(p: *P, errors: *DeferredErrors) void { if (errors.invalid_expr_default_value) |r| { p.log.addRangeError( p.source, @@ -3761,7 +3909,7 @@ pub fn NewParser( // This assumes the "function" token has already been parsed - pub fn parseFnStmt(p: *P, loc: logger.Loc, opts: *ParseStatementOptions, asyncRange: ?logger.Range) !Stmt { + fn parseFnStmt(p: *P, loc: logger.Loc, opts: *ParseStatementOptions, asyncRange: ?logger.Range) !Stmt { const is_generator = p.lexer.token == T.t_asterisk; const is_async = asyncRange != null; @@ -3869,7 +4017,7 @@ pub fn NewParser( }, func.open_parens_loc); } - pub fn popAndDiscardScope(p: *P, scope_index: usize) void { + fn popAndDiscardScope(p: *P, scope_index: usize) void { // Move up to the parent scope var to_discard = p.current_scope; var parent = to_discard.parent orelse unreachable; @@ -3889,7 +4037,7 @@ pub fn NewParser( _ = children.popOrNull(); } - pub fn parseFn(p: *P, name: ?js_ast.LocRef, opts: FnOrArrowDataParse) anyerror!G.Fn { + fn parseFn(p: *P, name: ?js_ast.LocRef, opts: FnOrArrowDataParse) anyerror!G.Fn { // if data.allowAwait and data.allowYield { // p.markSyntaxFeature(compat.AsyncGenerator, data.asyncRange) // } @@ -4230,11 +4378,11 @@ pub fn NewParser( }; }; - pub fn skipTypeScriptType(p: *P, level: js_ast.Op.Level) anyerror!void { + fn skipTypeScriptType(p: *P, level: js_ast.Op.Level) anyerror!void { try p.skipTypeScriptTypeWithOpts(level, .{}); } - pub fn skipTypeScriptBinding(p: *P) anyerror!void { + fn skipTypeScriptBinding(p: *P) anyerror!void { switch (p.lexer.token) { .t_identifier, .t_this => { try p.lexer.next(); @@ -4309,7 +4457,7 @@ pub fn NewParser( } } - pub fn skipTypescriptFnArgs(p: *P) anyerror!void { + fn skipTypescriptFnArgs(p: *P) anyerror!void { try p.lexer.expect(.t_open_paren); while (p.lexer.token != .t_close_paren) { @@ -4357,7 +4505,7 @@ pub fn NewParser( // let x = (y: any): (y) => {return 0}; // let x = (y: any): asserts y is (y) => {}; // - pub fn skipTypeScriptParenOrFnType(p: *P) anyerror!void { + fn skipTypeScriptParenOrFnType(p: *P) anyerror!void { if (p.trySkipTypeScriptArrowArgsWithBacktracking()) { try p.skipTypescriptReturnType(); } else { @@ -4367,7 +4515,7 @@ pub fn NewParser( } } - pub fn skipTypeScriptTypeWithOpts(p: *P, level: js_ast.Op.Level, opts: TypeScript.SkipTypeOptions) anyerror!void { + fn skipTypeScriptTypeWithOpts(p: *P, level: js_ast.Op.Level, opts: TypeScript.SkipTypeOptions) anyerror!void { if (!is_typescript_enabled) { unreachable; } @@ -4640,7 +4788,7 @@ pub fn NewParser( } } } - pub fn skipTypeScriptObjectType(p: *P) anyerror!void { + fn skipTypeScriptObjectType(p: *P) anyerror!void { try p.lexer.expect(.t_open_brace); while (p.lexer.token != .t_close_brace) { @@ -4748,7 +4896,7 @@ pub fn NewParser( // This is the type parameter declarations that go with other symbol // declarations (class, function, type, etc.) - pub fn skipTypeScriptTypeParameters(p: *P) anyerror!void { + fn skipTypeScriptTypeParameters(p: *P) anyerror!void { if (p.lexer.token == .t_less_than) { try p.lexer.next(); @@ -4807,7 +4955,7 @@ pub fn NewParser( }; } - pub fn parseLabelName(p: *P) !?js_ast.LocRef { + fn parseLabelName(p: *P) !?js_ast.LocRef { if (p.lexer.token != .t_identifier or p.lexer.has_newline_before) { return null; } @@ -4817,7 +4965,7 @@ pub fn NewParser( return name; } - pub fn parseClassStmt(p: *P, loc: logger.Loc, opts: *ParseStatementOptions) !Stmt { + fn parseClassStmt(p: *P, loc: logger.Loc, opts: *ParseStatementOptions) !Stmt { var name: ?js_ast.LocRef = null; var class_keyword = p.lexer.range(); if (p.lexer.token == .t_class) { @@ -4918,7 +5066,7 @@ pub fn NewParser( // pub fn maybeRewriteExportSymbol(p: *P, ) - pub fn parseStmt(p: *P, opts: *ParseStatementOptions) anyerror!Stmt { + fn parseStmt(p: *P, opts: *ParseStatementOptions) anyerror!Stmt { var loc = p.lexer.loc(); switch (p.lexer.token) { @@ -6184,7 +6332,7 @@ pub fn NewParser( return js_ast.Stmt.empty(); } - pub fn discardScopesUpTo(p: *P, scope_index: usize) void { + fn discardScopesUpTo(p: *P, scope_index: usize) void { // Remove any direct children from their parent var scope = p.current_scope; var children = scope.children; @@ -6208,7 +6356,7 @@ pub fn NewParser( p.scopes_in_order.shrinkRetainingCapacity(scope_index); } - pub fn skipTypeScriptTypeStmt(p: *P, opts: *ParseStatementOptions) anyerror!void { + fn skipTypeScriptTypeStmt(p: *P, opts: *ParseStatementOptions) anyerror!void { if (opts.is_export and p.lexer.token == .t_open_brace) { // "export type {foo}" // "export type {foo} from 'bar'" @@ -6234,7 +6382,7 @@ pub fn NewParser( try p.lexer.expectOrInsertSemicolon(); } - pub fn parseTypeScriptNamespaceStmt(p: *P, loc: logger.Loc, opts: *ParseStatementOptions) anyerror!Stmt { + fn parseTypeScriptNamespaceStmt(p: *P, loc: logger.Loc, opts: *ParseStatementOptions) anyerror!Stmt { // "namespace foo {}"; const name_loc = p.lexer.loc(); const name_text = p.lexer.identifier; @@ -6347,7 +6495,7 @@ pub fn NewParser( ); } - pub fn skipTypeScriptInterfaceStmt(p: *P, opts: *ParseStatementOptions) !void { + fn skipTypeScriptInterfaceStmt(p: *P, opts: *ParseStatementOptions) !void { const name = p.lexer.identifier; try p.lexer.expect(.t_identifier); @@ -6385,7 +6533,7 @@ pub fn NewParser( // This assumes the caller has already parsed the "import" token - pub fn parseTypeScriptImportEqualsStmt(p: *P, loc: logger.Loc, opts: *ParseStatementOptions, default_name_loc: logger.Loc, default_name: string) anyerror!Stmt { + fn parseTypeScriptImportEqualsStmt(p: *P, loc: logger.Loc, opts: *ParseStatementOptions, default_name_loc: logger.Loc, default_name: string) anyerror!Stmt { try p.lexer.expect(.t_equals); const kind = S.Local.Kind.k_const; @@ -6432,7 +6580,7 @@ pub fn NewParser( return p.s(S.Local{ .kind = kind, .decls = decls, .is_export = opts.is_export, .was_ts_import_equals = true }, loc); } - pub fn parseClauseAlias(p: *P, kind: string) !string { + fn parseClauseAlias(p: *P, kind: string) !string { const loc = p.lexer.loc(); // The alias may now be a string (see https://github.com/tc39/ecma262/pull/2154) @@ -6459,7 +6607,7 @@ pub fn NewParser( return alias; } - pub fn parseImportClause( + fn parseImportClause( p: *P, ) !ImportClause { var items = List(js_ast.ClauseItem).init(p.allocator); @@ -6521,7 +6669,7 @@ pub fn NewParser( return ImportClause{ .items = items.toOwnedSlice(), .is_single_line = is_single_line }; } - pub fn forbidInitializers(p: *P, decls: []G.Decl, loop_type: string, is_var: bool) !void { + fn forbidInitializers(p: *P, decls: []G.Decl, loop_type: string, is_var: bool) !void { if (decls.len > 1) { try p.log.addErrorFmt(p.source, decls[0].binding.loc, p.allocator, "for-{s} loops must have a single declaration", .{loop_type}); } else if (decls.len == 1) { @@ -6538,7 +6686,7 @@ pub fn NewParser( } } - pub fn parseExprOrLetStmt(p: *P, opts: *ParseStatementOptions) !ExprOrLetStmt { + fn parseExprOrLetStmt(p: *P, opts: *ParseStatementOptions) !ExprOrLetStmt { var let_range = p.lexer.range(); var raw = p.lexer.raw(); if (p.lexer.token != .t_identifier or !strings.eqlComptime(raw, "let")) { @@ -6577,7 +6725,7 @@ pub fn NewParser( return ExprOrLetStmt{ .stmt_or_expr = js_ast.StmtOrExpr{ .expr = try p.parseSuffix(expr, .lowest, null, Expr.EFlags.none) } }; } - pub fn requireInitializers(p: *P, decls: []G.Decl) !void { + fn requireInitializers(p: *P, decls: []G.Decl) !void { for (decls) |decl| { if (decl.value == null) { switch (decl.binding.data) { @@ -6594,7 +6742,7 @@ pub fn NewParser( } } - pub fn parseBinding(p: *P) anyerror!Binding { + fn parseBinding(p: *P) anyerror!Binding { var loc = p.lexer.loc(); switch (p.lexer.token) { @@ -6825,7 +6973,7 @@ pub fn NewParser( }; } - pub fn parseAndDeclareDecls(p: *P, kind: Symbol.Kind, opts: *ParseStatementOptions) anyerror![]G.Decl { + fn parseAndDeclareDecls(p: *P, kind: Symbol.Kind, opts: *ParseStatementOptions) anyerror![]G.Decl { var decls = List(G.Decl).init(p.allocator); while (true) { @@ -6989,7 +7137,7 @@ pub fn NewParser( }, loc); } - pub fn parseExportClause(p: *P) !ExportClauseResult { + fn parseExportClause(p: *P) !ExportClauseResult { var items = List(js_ast.ClauseItem).initCapacity(p.allocator, 1) catch unreachable; try p.lexer.expect(.t_open_brace); var is_single_line = !p.lexer.has_newline_before; @@ -7085,7 +7233,7 @@ pub fn NewParser( // TODO: pub fn checkForNonBMPCodePoint(p: *P, loc: logger.Loc, name: string) void {} - pub fn parseStmtsUpTo(p: *P, eend: js_lexer.T, _opts: *ParseStatementOptions) ![]Stmt { + fn parseStmtsUpTo(p: *P, eend: js_lexer.T, _opts: *ParseStatementOptions) ![]Stmt { var opts = _opts.*; var stmts = StmtList.init(p.allocator); @@ -7179,7 +7327,7 @@ pub fn NewParser( return stmts.toOwnedSlice(); } - pub fn markStrictModeFeature(p: *P, feature: StrictModeFeature, r: logger.Range, detail: string) !void { + fn markStrictModeFeature(p: *P, feature: StrictModeFeature, r: logger.Range, detail: string) !void { var text: string = undefined; var can_be_transformed = false; switch (feature) { @@ -7248,7 +7396,7 @@ pub fn NewParser( return p.current_scope.strict_mode != .sloppy_mode; } - pub fn isStrictModeOutputFormat(p: *P) bool { + pub inline fn isStrictModeOutputFormat(p: *P) bool { return true; } @@ -7296,12 +7444,23 @@ pub fn NewParser( return ref; } - pub fn declareSymbol(p: *P, kind: Symbol.Kind, loc: logger.Loc, name: string) !Ref { + fn declareGeneratedSymbol(p: *P, kind: Symbol.Kind, name: string) !Ref { + return try declareSymbolMaybeGenerated(p, kind, logger.Loc.Empty, name, true); + } + + fn declareSymbol(p: *P, kind: Symbol.Kind, loc: logger.Loc, name: string) !Ref { + return try declareSymbolMaybeGenerated(p, kind, loc, name, false); + } + + inline fn declareSymbolMaybeGenerated(p: *P, kind: Symbol.Kind, loc: logger.Loc, name: string, comptime is_generated: bool) !Ref { // p.checkForNonBMPCodePoint(loc, name) - // Forbid declaring a symbol with a reserved word in strict mode - if (p.isStrictMode() and js_lexer.StrictModeReservedWords.has(name)) { - try p.markStrictModeFeature(.reserved_word, js_lexer.rangeOfIdentifier(p.source, loc), name); + if (comptime !is_generated) { + + // Forbid declaring a symbol with a reserved word in strict mode + if (p.isStrictMode() and js_lexer.StrictModeReservedWords.has(name)) { + try p.markStrictModeFeature(.reserved_word, js_lexer.rangeOfIdentifier(p.source, loc), name); + } } // Allocate a new symbol @@ -7311,41 +7470,49 @@ pub fn NewParser( var entry = try scope.members.getOrPut(name); if (entry.found_existing) { const existing = entry.entry.value; - var symbol: *Symbol = &p.symbols.items[@intCast(usize, existing.ref.inner_index)]; - switch (p.canMergeSymbols(scope, symbol.kind, kind)) { - .forbidden => { - const r = js_lexer.rangeOfIdentifier(p.source, loc); - var notes: []logger.Data = &[_]logger.Data{}; - notes = &([_]logger.Data{logger.rangeData(p.source, r, try std.fmt.allocPrint(p.allocator, "{s} has already been declared", .{name}))}); - try p.log.addRangeErrorWithNotes(p.source, r, try std.fmt.allocPrint(p.allocator, "{s} was originally declared here", .{name}), notes); - return existing.ref; - }, - .keep_existing => { - ref = existing.ref; - }, - .replace_with_new => { - symbol.link = ref; - }, - .become_private_get_set_pair => { - ref = existing.ref; - symbol.kind = .private_get_set_pair; - }, - .become_private_static_get_set_pair => { - ref = existing.ref; - symbol.kind = .private_static_get_set_pair; - }, + if (comptime !is_generated) { + var symbol: *Symbol = &p.symbols.items[@intCast(usize, existing.ref.inner_index)]; + + switch (p.canMergeSymbols(scope, symbol.kind, kind)) { + .forbidden => { + const r = js_lexer.rangeOfIdentifier(p.source, loc); + var notes = try p.allocator.alloc(logger.Data, 1); + notes[0] = logger.rangeData(p.source, r, try std.fmt.allocPrint(p.allocator, "{s} has already been declared", .{name})); + try p.log.addRangeErrorWithNotes(p.source, r, try std.fmt.allocPrint(p.allocator, "{s} was originally declared here", .{name}), notes); + return existing.ref; + }, + .keep_existing => { + ref = existing.ref; + }, + .replace_with_new => { + symbol.link = ref; + }, + .become_private_get_set_pair => { + ref = existing.ref; + symbol.kind = .private_get_set_pair; + }, + .become_private_static_get_set_pair => { + ref = existing.ref; + symbol.kind = .private_static_get_set_pair; + }, - .overwrite_with_new => {}, - // else => unreachable, + .overwrite_with_new => {}, + // else => unreachable, + } + } else { + p.symbols.items[ref.inner_index].link = existing.ref; } } entry.entry.value = js_ast.Scope.Member{ .ref = ref, .loc = loc }; + if (comptime is_generated) { + try p.module_scope.generated.append(ref); + } return ref; } - pub fn validateFunctionName(p: *P, func: G.Fn, kind: FunctionKind) void { + fn validateFunctionName(p: *P, func: G.Fn, kind: FunctionKind) void { if (func.name) |name| { const original_name = p.symbols.items[name.ref.?.inner_index].original_name; @@ -7365,7 +7532,7 @@ pub fn NewParser( } } - pub fn parseFnExpr(p: *P, loc: logger.Loc, is_async: bool, async_range: logger.Range) !Expr { + fn parseFnExpr(p: *P, loc: logger.Loc, is_async: bool, async_range: logger.Range) !Expr { try p.lexer.next(); const is_generator = p.lexer.token == T.t_asterisk; if (is_generator) { @@ -7417,7 +7584,7 @@ pub fn NewParser( }, loc); } - pub fn parseFnBody(p: *P, data: *FnOrArrowDataParse) !G.FnBody { + fn parseFnBody(p: *P, data: *FnOrArrowDataParse) !G.FnBody { var oldFnOrArrowData = p.fn_or_arrow_data_parse; var oldAllowIn = p.allow_in; p.fn_or_arrow_data_parse = data.*; @@ -7437,7 +7604,7 @@ pub fn NewParser( return G.FnBody{ .loc = loc, .stmts = stmts }; } - pub fn parseArrowBody(p: *P, args: []js_ast.G.Arg, data: *FnOrArrowDataParse) !E.Arrow { + fn parseArrowBody(p: *P, args: []js_ast.G.Arg, data: *FnOrArrowDataParse) !E.Arrow { var arrow_loc = p.lexer.loc(); // Newlines are not allowed before "=>" @@ -7476,7 +7643,7 @@ pub fn NewParser( return E.Arrow{ .args = args, .prefer_expr = true, .body = G.FnBody{ .loc = arrow_loc, .stmts = stmts } }; } - pub fn declareBinding(p: *P, kind: Symbol.Kind, binding: *BindingNodeIndex, opts: *ParseStatementOptions) !void { + fn declareBinding(p: *P, kind: Symbol.Kind, binding: *BindingNodeIndex, opts: *ParseStatementOptions) !void { switch (binding.data) { .b_missing => {}, .b_identifier => |bind| { @@ -9403,8 +9570,10 @@ pub fn NewParser( _ = p.pushScopeForParsePass(.function_args, loc) catch unreachable; defer p.popScope(); - // Output.print("HANDLE START ", .{}); - return p.e(try p.parseArrowBody(args, p.m(FnOrArrowDataParse{})), loc); + + var fn_or_arrow_data = FnOrArrowDataParse{}; + const ret = p.e(try p.parseArrowBody(args, &fn_or_arrow_data), loc); + return ret; } const ref = p.storeNameInRef(name) catch unreachable; @@ -9843,13 +10012,13 @@ pub fn NewParser( // esbuild's version of this function is much more complicated. // I'm not sure why defines is strictly relevant for this case // do people do <API_URL>? - pub fn jsxStringsToMemberExpression(p: *P, loc: logger.Loc, ref: Ref) Expr { + fn jsxStringsToMemberExpression(p: *P, loc: logger.Loc, ref: Ref) Expr { p.recordUsage(ref); return p.e(E.Identifier{ .ref = ref }, loc); } // Note: The caller has already parsed the "import" keyword - pub fn parseImportExpr(p: *P, loc: logger.Loc, level: Level) anyerror!Expr { + fn parseImportExpr(p: *P, loc: logger.Loc, level: Level) anyerror!Expr { // Parse an "import.meta" expression if (p.lexer.token == .t_dot) { p.es6_import_keyword = js_lexer.rangeOfIdentifier(p.source, loc); @@ -9881,6 +10050,19 @@ pub fn NewParser( try p.lexer.expect(.t_close_paren); p.allow_in = old_allow_in; + + if (comptime only_scan_imports_and_do_not_visit) { + if (value.data == .e_string and value.data.e_string.isUTF8() and value.data.e_string.isPresent()) { + const import_record_index = p.addImportRecord(.dynamic, value.loc, value.data.e_string.utf8); + + return p.e(E.Import{ + .expr = value, + .leading_interior_comments = comments, + .import_record_index = import_record_index, + }, loc); + } + } + return p.e(E.Import{ .expr = value, .leading_interior_comments = comments, .import_record_index = 0 }, loc); } @@ -9964,7 +10146,7 @@ pub fn NewParser( } }; - pub fn parseJSXPropValueIdentifier(p: *P, previous_string_with_backslash_loc: *logger.Loc) !Expr { + fn parseJSXPropValueIdentifier(p: *P, previous_string_with_backslash_loc: *logger.Loc) !Expr { // Use NextInsideJSXElement() not Next() so we can parse a JSX-style string literal try p.lexer.nextInsideJSXElement(); if (p.lexer.token == .t_string_literal) { @@ -9982,7 +10164,7 @@ pub fn NewParser( } } - pub fn parseJSXElement(p: *P, loc: logger.Loc) anyerror!Expr { + fn parseJSXElement(p: *P, loc: logger.Loc) anyerror!Expr { if (only_scan_imports_and_do_not_visit) { p.needs_jsx_import = true; } @@ -10183,7 +10365,7 @@ pub fn NewParser( } } - pub fn willNeedBindingPattern(p: *P) bool { + fn willNeedBindingPattern(p: *P) bool { switch (p.lexer.token) { .t_equals => { // "[a] = b;" @@ -10203,11 +10385,11 @@ pub fn NewParser( } } - pub fn parsePrefix(p: *P, level: Level, errors: ?*DeferredErrors, flags: Expr.EFlags) anyerror!Expr { + fn parsePrefix(p: *P, level: Level, errors: ?*DeferredErrors, flags: Expr.EFlags) anyerror!Expr { return try p._parsePrefix(level, errors orelse &DeferredErrors.None, flags); } - pub fn appendPart(p: *P, parts: *List(js_ast.Part), stmts: []Stmt) !void { + fn appendPart(p: *P, parts: *List(js_ast.Part), stmts: []Stmt) !void { p.symbol_uses = SymbolUseMap.init(p.allocator); p.declared_symbols.deinit(); p.declared_symbols = @TypeOf(p.declared_symbols).init(p.allocator); @@ -10267,7 +10449,7 @@ pub fn NewParser( } } - pub fn bindingCanBeRemovedIfUnused(p: *P, binding: Binding) bool { + fn bindingCanBeRemovedIfUnused(p: *P, binding: Binding) bool { switch (binding.data) { .b_array => |bi| { for (bi.items) |*item| { @@ -10305,7 +10487,7 @@ pub fn NewParser( return true; } - pub fn stmtsCanBeRemovedIfUnused(p: *P, stmts: []Stmt) bool { + fn stmtsCanBeRemovedIfUnused(p: *P, stmts: []Stmt) bool { for (stmts) |stmt| { switch (stmt.data) { // These never have side effects @@ -10379,7 +10561,7 @@ pub fn NewParser( return true; } - pub fn visitStmtsAndPrependTempRefs(p: *P, stmts: *List(Stmt), opts: *PrependTempRefsOpts) !void { + fn visitStmtsAndPrependTempRefs(p: *P, stmts: *List(Stmt), opts: *PrependTempRefsOpts) !void { if (only_scan_imports_and_do_not_visit) { @compileError("only_scan_imports_and_do_not_visit must not run this."); } @@ -10404,14 +10586,14 @@ pub fn NewParser( } } - pub fn recordDeclaredSymbol(p: *P, ref: Ref) !void { + fn recordDeclaredSymbol(p: *P, ref: Ref) !void { try p.declared_symbols.append(js_ast.DeclaredSymbol{ .ref = ref, .is_top_level = p.current_scope == p.module_scope, }); } - pub fn visitExpr(p: *P, expr: Expr) Expr { + fn visitExpr(p: *P, expr: Expr) Expr { if (only_scan_imports_and_do_not_visit) { @compileError("only_scan_imports_and_do_not_visit must not run this."); } @@ -10419,7 +10601,7 @@ pub fn NewParser( return @call(.{ .modifier = .always_inline }, P.visitExprInOut, .{ p, expr, ExprIn{} }); } - pub fn visitFunc(p: *P, _func: G.Fn, open_parens_loc: logger.Loc) G.Fn { + fn visitFunc(p: *P, _func: G.Fn, open_parens_loc: logger.Loc) G.Fn { if (only_scan_imports_and_do_not_visit) { @compileError("only_scan_imports_and_do_not_visit must not run this."); } @@ -10466,11 +10648,11 @@ pub fn NewParser( return func; } - pub fn maybeKeepExprSymbolName(p: *P, expr: Expr, original_name: string, was_anonymous_named_expr: bool) Expr { + fn maybeKeepExprSymbolName(p: *P, expr: Expr, original_name: string, was_anonymous_named_expr: bool) Expr { return if (was_anonymous_named_expr) p.keepExprSymbolName(expr, original_name) else expr; } - pub fn valueForThis(p: *P, loc: logger.Loc) ?Expr { + fn valueForThis(p: *P, loc: logger.Loc) ?Expr { // Substitute "this" if we're inside a static class property initializer if (p.fn_only_data_visit.this_class_static_ref) |ref| { p.recordUsage(ref); @@ -10496,7 +10678,7 @@ pub fn NewParser( return null; } - pub fn visitExprInOut(p: *P, expr: Expr, in: ExprIn) Expr { + fn visitExprInOut(p: *P, expr: Expr, in: ExprIn) Expr { // 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 => {}, @@ -11652,7 +11834,7 @@ pub fn NewParser( is_unique_formal_parameters: bool = false, }; - pub fn visitArgs(p: *P, args: []G.Arg, opts: VisitArgsOpts) void { + fn visitArgs(p: *P, args: []G.Arg, opts: VisitArgsOpts) void { const strict_loc = fnBodyContainsUseStrict(opts.body); const has_simple_args = isSimpleParameterList(args, opts.has_rest_arg); var duplicate_args_check: ?StringBoolMap = null; @@ -11929,7 +12111,7 @@ pub fn NewParser( return false; } - pub fn jsxStringsToMemberExpressionAutomatic(p: *P, loc: logger.Loc, is_static: bool) Expr { + fn jsxStringsToMemberExpressionAutomatic(p: *P, loc: logger.Loc, is_static: bool) Expr { return p.jsxStringsToMemberExpression(loc, if (is_static and !p.options.jsx.development) p.jsxs_runtime_ref else p.jsx_runtime_ref); } @@ -11950,7 +12132,7 @@ pub fn NewParser( ok: bool = false, }; - pub fn maybeRelocateVarsToTopLevel(p: *P, decls: []G.Decl, mode: RelocateVars.Mode) RelocateVars { + fn maybeRelocateVarsToTopLevel(p: *P, decls: []G.Decl, mode: RelocateVars.Mode) RelocateVars { // Only do this when the scope is not already top-level and when we're not inside a function. if (p.current_scope == p.module_scope) { return .{ .ok = false }; @@ -11991,7 +12173,7 @@ pub fn NewParser( // EDot nodes represent a property access. This function may return an // expression to replace the property access with. It assumes that the // target of the EDot expression has already been visited. - pub fn maybeRewritePropertyAccess( + fn maybeRewritePropertyAccess( p: *P, loc: logger.Loc, assign_target: js_ast.AssignTarget, @@ -12092,7 +12274,7 @@ pub fn NewParser( // the value is ignored because that's what the TypeScript compiler does. } - pub fn visitAndAppendStmt(p: *P, stmts: *List(Stmt), stmt: *Stmt) !void { + fn visitAndAppendStmt(p: *P, stmts: *List(Stmt), stmt: *Stmt) !void { switch (stmt.data) { // These don't contain anything to traverse @@ -12901,7 +13083,7 @@ pub fn NewParser( return; } - pub fn markExportedBindingInsideNamespace(p: *P, ref: Ref, binding: BindingNodeIndex) void { + fn markExportedBindingInsideNamespace(p: *P, ref: Ref, binding: BindingNodeIndex) void { switch (binding.data) { .b_missing => {}, .b_identifier => |ident| { @@ -12923,7 +13105,7 @@ pub fn NewParser( } } - pub fn generateClosureForTypeScriptNamespaceOrEnum( + fn generateClosureForTypeScriptNamespaceOrEnum( p: *P, stmts: *List(Stmt), stmt_loc: logger.Loc, @@ -13082,7 +13264,7 @@ pub fn NewParser( stmts.append(closure) catch unreachable; } - pub fn lowerClass(p: *P, stmtorexpr: js_ast.StmtOrExpr, ref: Ref) []Stmt { + fn lowerClass(p: *P, stmtorexpr: js_ast.StmtOrExpr, ref: Ref) []Stmt { switch (stmtorexpr) { .stmt => |stmt| { var stmts = p.allocator.alloc(Stmt, 1) catch unreachable; @@ -13097,7 +13279,7 @@ pub fn NewParser( } } - pub fn visitForLoopInit(p: *P, stmt: Stmt, is_in_or_of: bool) Stmt { + fn visitForLoopInit(p: *P, stmt: Stmt, is_in_or_of: bool) Stmt { switch (stmt.data) { .s_expr => |st| { const assign_target = if (is_in_or_of) js_ast.AssignTarget.replace else js_ast.AssignTarget.none; @@ -13123,7 +13305,7 @@ pub fn NewParser( return stmt; } - pub fn wrapIdentifierNamespace( + fn wrapIdentifierNamespace( p: *P, loc: logger.Loc, ref: Ref, @@ -13137,7 +13319,7 @@ pub fn NewParser( }, loc); } - pub fn wrapIdentifierHoisting( + fn wrapIdentifierHoisting( p: *P, loc: logger.Loc, ref: Ref, @@ -13148,7 +13330,7 @@ pub fn NewParser( return p.e(E.Identifier{ .ref = _ref }, loc); } - pub fn isAnonymousNamedExpr(p: *P, expr: ExprNodeIndex) bool { + fn isAnonymousNamedExpr(p: *P, expr: ExprNodeIndex) bool { switch (expr.data) { .e_arrow => { return true; @@ -13165,7 +13347,7 @@ pub fn NewParser( } } - pub fn valueForDefine(p: *P, loc: logger.Loc, assign_target: js_ast.AssignTarget, is_delete_target: bool, define_data: *const DefineData) Expr { + 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 = define_data.value.e_identifier; @@ -13195,7 +13377,7 @@ pub fn NewParser( // This function is recursive // But it shouldn't be that long - pub fn isDotDefineMatch(p: *P, expr: Expr, parts: []const string) bool { + fn isDotDefineMatch(p: *P, expr: Expr, parts: []const string) bool { switch (expr.data) { .e_dot => |ex| { if (parts.len > 1) { @@ -13253,7 +13435,7 @@ pub fn NewParser( return false; } - pub fn visitBinding(p: *P, binding: BindingNodeIndex, duplicate_arg_check: ?*StringBoolMap) void { + fn visitBinding(p: *P, binding: BindingNodeIndex, duplicate_arg_check: ?*StringBoolMap) void { switch (binding.data) { .b_missing => {}, .b_identifier => |bind| { @@ -13327,7 +13509,7 @@ pub fn NewParser( } } - pub fn visitLoopBody(p: *P, stmt: StmtNodeIndex) StmtNodeIndex { + fn visitLoopBody(p: *P, stmt: StmtNodeIndex) StmtNodeIndex { const old_is_inside_loop = p.fn_or_arrow_data_visit.is_inside_loop; p.fn_or_arrow_data_visit.is_inside_loop = true; p.loop_body = stmt.data; @@ -13336,7 +13518,7 @@ pub fn NewParser( return res; } - pub fn visitSingleStmt(p: *P, stmt: Stmt, kind: StmtsKind) Stmt { + fn visitSingleStmt(p: *P, stmt: Stmt, kind: StmtsKind) Stmt { const has_if_scope = has_if: { switch (stmt.data) { .s_function => { @@ -13365,7 +13547,7 @@ pub fn NewParser( } // One statement could potentially expand to several statements - pub fn stmtsToSingleStmt(p: *P, loc: logger.Loc, stmts: []Stmt) Stmt { + fn stmtsToSingleStmt(p: *P, loc: logger.Loc, stmts: []Stmt) Stmt { if (stmts.len == 0) { return Stmt{ .data = Prefill.Data.SEmpty, .loc = loc }; } @@ -13378,7 +13560,7 @@ pub fn NewParser( return p.s(S.Block{ .stmts = stmts }, loc); } - pub fn findLabelSymbol(p: *P, loc: logger.Loc, name: string) FindLabelSymbolResult { + fn findLabelSymbol(p: *P, loc: logger.Loc, name: string) FindLabelSymbolResult { var res = FindLabelSymbolResult{ .ref = Ref.None, .is_loop = false }; var _scope: ?*Scope = p.current_scope; @@ -13408,7 +13590,7 @@ pub fn NewParser( return res; } - pub fn visitClass(p: *P, name_scope_loc: logger.Loc, class: *G.Class) Ref { + fn visitClass(p: *P, name_scope_loc: logger.Loc, class: *G.Class) Ref { if (only_scan_imports_and_do_not_visit) { @compileError("only_scan_imports_and_do_not_visit must not run this."); } @@ -13874,7 +14056,7 @@ pub fn NewParser( } } - pub fn maybeCommaSpreadError(p: *P, _comma_after_spread: ?logger.Loc) void { + fn maybeCommaSpreadError(p: *P, _comma_after_spread: ?logger.Loc) void { const comma_after_spread = _comma_after_spread orelse return; if (comma_after_spread.start == -1) return; @@ -14452,6 +14634,10 @@ pub fn NewParser( .export_keyword = p.es6_export_keyword, .bundle_export_ref = p.bundle_export_ref, .require_ref = p.require_ref, + + .uses_module_ref = (p.symbols.items[p.module_ref.inner_index].use_count_estimate > 0), + .uses_exports_ref = (p.symbols.items[p.exports_ref.inner_index].use_count_estimate > 0), + .uses_require_ref = (p.symbols.items[p.require_ref.inner_index].use_count_estimate > 0), // .top_Level_await_keyword = p.top_level_await_keyword, }; } |