aboutsummaryrefslogtreecommitdiff
path: root/src/js_parser/js_parser.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/js_parser/js_parser.zig')
-rw-r--r--src/js_parser/js_parser.zig308
1 files changed, 229 insertions, 79 deletions
diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig
index 2d3989b12..546ac3f58 100644
--- a/src/js_parser/js_parser.zig
+++ b/src/js_parser/js_parser.zig
@@ -408,7 +408,7 @@ pub const ImportScanner = struct {
if (@as(Expr.Tag, val.data) == .e_identifier) {
// Is this import statement unused?
if (@as(Binding.Tag, decl.binding.data) == .b_identifier and p.symbols.items[decl.binding.data.b_identifier.ref.inner_index].use_count_estimate == 0) {
- p.ignoreUsage(val.getIdentifier().ref);
+ p.ignoreUsage(val.data.e_identifier.ref);
scanner.removed_import_equals = true;
continue;
@@ -734,33 +734,22 @@ pub const SideEffects = enum(u2) {
equality.ok = @as(Expr.Tag, right) == Expr.Tag.e_undefined;
equality.equal = equality.ok;
},
- .e_boolean => {
- const l = left.e_boolean;
- const r = right.e_boolean;
-
+ .e_boolean => |l| {
equality.ok = @as(Expr.Tag, right) == Expr.Tag.e_boolean;
- equality.equal = equality.ok and l.value == r.value;
+ equality.equal = equality.ok and l.value == right.e_boolean.value;
},
- .e_number => {
- const l = left.e_number;
- const r = right.e_number;
-
+ .e_number => |l| {
equality.ok = @as(Expr.Tag, right) == Expr.Tag.e_number;
- equality.equal = equality.ok and l.value == r.value;
+ equality.equal = equality.ok and l.value == right.e_number.value;
},
- .e_big_int => {
- const l = left.e_big_int;
- const r = right.e_big_int;
-
+ .e_big_int => |l| {
equality.ok = @as(Expr.Tag, right) == Expr.Tag.e_big_int;
- equality.equal = equality.ok and strings.eql(l.value, r.value);
+ equality.equal = equality.ok and strings.eql(l.value, right.e_big_int.value);
},
- .e_string => {
- const l = left.e_string;
- const r = right.e_string;
-
+ .e_string => |l| {
equality.ok = @as(Expr.Tag, right) == Expr.Tag.e_string;
if (equality.ok) {
+ const r = right.e_string;
equality.equal = r.eql(E.String, l);
}
},
@@ -1455,6 +1444,23 @@ const PropertyOpts = struct {
ts_decorators: []Expr = &[_]Expr{},
};
+pub const ScanPassResult = struct {
+ import_records: List(ImportRecord),
+ named_imports: js_ast.Ast.NamedImports,
+
+ pub fn init(allocator: *std.mem.Allocator) ScanPassResult {
+ return .{
+ .import_records = List(ImportRecord).init(allocator),
+ .named_imports = js_ast.Ast.NamedImports.init(allocator),
+ };
+ }
+
+ pub fn reset(scan_pass: *ScanPassResult) void {
+ scan_pass.named_imports.clearRetainingCapacity();
+ scan_pass.import_records.shrinkRetainingCapacity(0);
+ }
+};
+
pub const Parser = struct {
options: Options,
lexer: js_lexer.Lexer,
@@ -1474,6 +1480,9 @@ pub const Parser = struct {
use_define_for_class_fields: bool = false,
suppress_warnings_about_weird_code: bool = true,
+ // Used when bundling node_modules
+ output_commonjs: bool = false,
+
moduleType: ModuleType = ModuleType.esm,
trim_unused_imports: bool = true,
@@ -1488,6 +1497,34 @@ pub const Parser = struct {
}
};
+ pub fn scanImports(self: *Parser, scan_pass: *ScanPassResult) !void {
+ if (self.options.ts and self.options.jsx.parse) {
+ return try self._scanImports(TSXImportScanner, scan_pass);
+ } else if (self.options.ts) {
+ return try self._scanImports(TypeScriptImportScanner, scan_pass);
+ } else if (self.options.jsx.parse) {
+ return try self._scanImports(JSXImportScanner, scan_pass);
+ } else {
+ return try self._scanImports(JavaScriptImportScanner, scan_pass);
+ }
+ }
+
+ fn _scanImports(self: *Parser, comptime ParserType: type, scan_pass: *ScanPassResult) !void {
+ var p: ParserType = undefined;
+ try ParserType.init(self.allocator, self.log, self.source, self.define, self.lexer, self.options, &p);
+ p.import_records = &scan_pass.import_records;
+ p.named_imports = &scan_pass.named_imports;
+ // Parse the file in the first pass, but do not bind symbols
+ var opts = ParseStatementOptions{ .is_module_scope = true };
+ debugl("<p.parseStmtsUpTo>");
+
+ // Parsing seems to take around 2x as much time as visiting.
+ // Which makes sense.
+ // June 4: "Parsing took: 18028000"
+ // June 4: "Rest of this took: 8003000"
+ _ = try p.parseStmtsUpTo(js_lexer.T.t_end_of_file, &opts);
+ }
+
pub fn parse(self: *Parser) !js_ast.Result {
if (self.options.ts and self.options.jsx.parse) {
return try self._parse(TSXParser);
@@ -1501,7 +1538,8 @@ pub const Parser = struct {
}
fn _parse(self: *Parser, comptime ParserType: type) !js_ast.Result {
- var p = try ParserType.init(self.allocator, self.log, self.source, self.define, self.lexer, self.options);
+ var p: ParserType = undefined;
+ try ParserType.init(self.allocator, self.log, self.source, self.define, self.lexer, self.options, &p);
var result: js_ast.Result = undefined;
@@ -1515,6 +1553,11 @@ pub const Parser = struct {
// Parse the file in the first pass, but do not bind symbols
var opts = ParseStatementOptions{ .is_module_scope = true };
debugl("<p.parseStmtsUpTo>");
+
+ // Parsing seems to take around 2x as much time as visiting.
+ // Which makes sense.
+ // June 4: "Parsing took: 18028000"
+ // June 4: "Rest of this took: 8003000"
const stmts = try p.parseStmtsUpTo(js_lexer.T.t_end_of_file, &opts);
debugl("</p.parseStmtsUpTo>");
try p.prepareForVisitPass();
@@ -1787,7 +1830,7 @@ pub const Parser = struct {
p.generateImportStmt(RuntimeImports.Name, &imports, &before, p.runtime_imports, null, "import_") catch unreachable;
}
- if (p.cjs_import_stmts.items.len > 0) {
+ if (p.cjs_import_stmts.items.len > 0 and !p.options.output_commonjs) {
var import_records = try p.allocator.alloc(u32, p.cjs_import_stmts.items.len);
var declared_symbols = try p.allocator.alloc(js_ast.DeclaredSymbol, p.cjs_import_stmts.items.len);
@@ -1956,7 +1999,18 @@ var falseExprValueData = E.Boolean{ .value = false };
var nullValueExpr = Expr.Data{ .e_null = nullExprValueData };
var falseValueExpr = Expr.Data{ .e_boolean = E.Boolean{ .value = false } };
-pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled: bool) type {
+pub const ImportOrRequireScanResults = struct {
+ import_records: List(ImportRecord),
+};
+
+pub fn NewParser(
+ comptime is_typescript_enabled: bool,
+ comptime is_jsx_enabled: bool,
+ comptime only_scan_imports_and_do_not_visit: bool,
+) type {
+ const ImportRecordList = if (only_scan_imports_and_do_not_visit) *std.ArrayList(ImportRecord) else std.ArrayList(ImportRecord);
+ const NamedImportsType = if (only_scan_imports_and_do_not_visit) *js_ast.Ast.NamedImports else js_ast.Ast.NamedImports;
+
// P is for Parser!
// public only because of Binding.ToExpr
return struct {
@@ -2042,7 +2096,7 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
jsx_source_list_ref: js_ast.Ref = Ref.None,
// Imports (both ES6 and CommonJS) are tracked at the top level
- import_records: List(ImportRecord),
+ import_records: ImportRecordList,
import_records_for_current_part: List(u32),
export_star_import_records: List(u32),
@@ -2052,7 +2106,7 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
enclosing_class_keyword: logger.Range = logger.Range.None,
import_items_for_namespace: Map(js_ast.Ref, StringHashMap(js_ast.LocRef)),
is_import_item: RefBoolMap,
- named_imports: js_ast.Ast.NamedImports,
+ named_imports: NamedImportsType,
named_exports: js_ast.Ast.NamedExports,
top_level_symbol_to_parts: Map(js_ast.Ref, List(u32)),
import_namespace_cc_map: Map(ImportNamespaceCallOrConstruct, bool),
@@ -2300,6 +2354,23 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
pub fn s(p: *P, t: anytype, loc: logger.Loc) Stmt {
// Output.print("\nStmt: {s} - {d}\n", .{ @typeName(@TypeOf(t)), loc.start });
if (@typeInfo(@TypeOf(t)) == .Pointer) {
+ // ExportFrom normally becomes import records during the visiting pass
+ // However, we skip the visiting pass in this mode
+ // So we must generate a minimum version of it here.
+ if (comptime only_scan_imports_and_do_not_visit) {
+ // if (@TypeOf(t) == *S.ExportFrom) {
+ // switch (call.target.data) {
+ // .e_identifier => |ident| {
+ // // is this a require("something")
+ // if (strings.eqlComptime(p.loadNameFromRef(ident.ref), "require") and call.args.len == 1 and std.meta.activeTag(call.args[0].data) == .e_string) {
+ // _ = p.addImportRecord(.require, loc, call.args[0].data.e_string.string(p.allocator) catch unreachable);
+ // }
+ // },
+ // else => {},
+ // }
+ // }
+ }
+
return Stmt.init(t, loc);
} else {
return Stmt.alloc(p.allocator, t, loc);
@@ -2310,8 +2381,36 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
// Output.print("\nExpr: {s} - {d}\n", .{ @typeName(@TypeOf(t)), loc.start });
if (@typeInfo(@TypeOf(t)) == .Pointer) {
+ if (comptime only_scan_imports_and_do_not_visit) {
+ if (@TypeOf(t) == *E.Call) {
+ const call: *E.Call = t;
+ switch (call.target.data) {
+ .e_identifier => |ident| {
+ // is this a require("something")
+ if (strings.eqlComptime(p.loadNameFromRef(ident.ref), "require") and call.args.len == 1 and std.meta.activeTag(call.args[0].data) == .e_string) {
+ _ = p.addImportRecord(.require, loc, call.args[0].data.e_string.string(p.allocator) catch unreachable);
+ }
+ },
+ else => {},
+ }
+ }
+ }
return Expr.init(t, loc);
} else {
+ if (comptime only_scan_imports_and_do_not_visit) {
+ if (@TypeOf(t) == E.Call) {
+ const call: E.Call = t;
+ switch (call.target.data) {
+ .e_identifier => |ident| {
+ // is this a require("something")
+ if (strings.eqlComptime(p.loadNameFromRef(ident.ref), "require") and call.args.len == 1 and std.meta.activeTag(call.args[0].data) == .e_string) {
+ _ = p.addImportRecord(.require, loc, call.args[0].data.e_string.string(p.allocator) catch unreachable);
+ }
+ },
+ else => {},
+ }
+ }
+ }
return Expr.alloc(p.allocator, t, loc);
}
}
@@ -2640,7 +2739,9 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
comptime suffix: string,
) !void {
const import_record_i = p.addImportRecordByRange(.stmt, logger.Range.None, import_path);
- var import_record = p.import_records.items[import_record_i];
+ var import_record: *ImportRecord = &p.import_records.items[import_record_i];
+
+ import_record.is_internal = true;
var import_path_identifier = try import_record.path.name.nonUniqueNameString(p.allocator);
var namespace_identifier = try p.allocator.alloc(u8, import_path_identifier.len + suffix.len);
var clause_items = try p.allocator.alloc(js_ast.ClauseItem, imports.len);
@@ -2733,8 +2834,14 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
p.hoistSymbols(p.module_scope);
p.require_ref = try p.declareCommonJSSymbol(.unbound, "require");
- p.exports_ref = try p.declareSymbol(.hoisted, logger.Loc.Empty, "exports");
- p.module_ref = try p.declareSymbol(.hoisted, logger.Loc.Empty, "module");
+
+ if (p.options.output_commonjs) {
+ p.exports_ref = try p.declareCommonJSSymbol(.hoisted, "exports");
+ p.module_ref = try p.declareCommonJSSymbol(.hoisted, "module");
+ } else {
+ p.exports_ref = try p.declareSymbol(.hoisted, logger.Loc.Empty, "exports");
+ p.module_ref = try p.declareSymbol(.hoisted, logger.Loc.Empty, "module");
+ }
p.runtime_imports.__require = p.require_ref;
@@ -6429,8 +6536,9 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
return true;
}
- pub fn declareCommonJSSymbol(p: *P, kind: Symbol.Kind, name: string) !Ref {
- const member = p.module_scope.members.get(name);
+ pub fn declareCommonJSSymbol(p: *P, comptime kind: Symbol.Kind, comptime name: string) !Ref {
+ const name_hash = comptime @TypeOf(p.module_scope.members).getHash(name);
+ const member = p.module_scope.members.getWithHash(name, name_hash);
// If the code declared this symbol using "var name", then this is actually
// not a collision. For example, node will let you do this:
@@ -6460,7 +6568,7 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
const ref = try p.newSymbol(kind, name);
if (member == null) {
- try p.module_scope.members.put(name, Scope.Member{ .ref = ref, .loc = logger.Loc.Empty });
+ try p.module_scope.members.putWithHash(name, name_hash, Scope.Member{ .ref = ref, .loc = logger.Loc.Empty });
return ref;
}
@@ -9540,6 +9648,10 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
}
pub 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.");
+ }
+
var old_temp_refs = p.temp_refs_to_declare;
var old_temp_ref_count = p.temp_ref_count;
p.temp_refs_to_declare.deinit();
@@ -9568,10 +9680,18 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
}
pub fn visitExpr(p: *P, expr: Expr) Expr {
- return p.visitExprInOut(expr, ExprIn{});
+ if (only_scan_imports_and_do_not_visit) {
+ @compileError("only_scan_imports_and_do_not_visit must not run this.");
+ }
+ // Inline to avoid the extra unnecessary function call in the stack
+ 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 {
+ if (only_scan_imports_and_do_not_visit) {
+ @compileError("only_scan_imports_and_do_not_visit must not run this.");
+ }
+
var func = _func;
const old_fn_or_arrow_data = std.mem.toBytes(p.fn_or_arrow_data_visit);
const old_fn_only_data = std.mem.toBytes(p.fn_only_data_visit);
@@ -10170,7 +10290,7 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
// Optionally preserve the name
if (@as(Expr.Tag, e_.left.data) == .e_identifier) {
- e_.right = p.maybeKeepExprSymbolName(e_.right, p.symbols.items[e_.left.getIdentifier().ref.inner_index].original_name, was_anonymous_named_expr);
+ e_.right = p.maybeKeepExprSymbolName(e_.right, p.symbols.items[e_.left.data.e_identifier.ref.inner_index].original_name, was_anonymous_named_expr);
}
},
.bin_add_assign => {
@@ -10249,14 +10369,14 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
// though this is a run-time error, we make it a compile-time error when
// bundling because scope hoisting means these will no longer be run-time
// errors.
- if ((in.assign_target != .none or is_delete_target) and @as(Expr.Tag, e_.target.data) == .e_identifier and p.symbols.items[e_.target.getIdentifier().ref.inner_index].kind == .import) {
+ if ((in.assign_target != .none or is_delete_target) and @as(Expr.Tag, e_.target.data) == .e_identifier and p.symbols.items[e_.target.data.e_identifier.ref.inner_index].kind == .import) {
const r = js_lexer.rangeOfIdentifier(p.source, e_.target.loc);
p.log.addRangeErrorFmt(
p.source,
r,
p.allocator,
"Cannot assign to property on import \"{s}\"",
- .{p.symbols.items[e_.target.getIdentifier().ref.inner_index].original_name},
+ .{p.symbols.items[e_.target.data.e_identifier.ref.inner_index].original_name},
) catch unreachable;
}
@@ -11334,16 +11454,13 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
var val = d.value orelse unreachable;
const was_anonymous_named_expr = p.isAnonymousNamedExpr(val);
- val = p.visitExpr(val);
- // go version of defer would cause this to reset the variable
- // zig version of defer causes this to set it to the last value of val, at the end of the scope.
- d.value = val;
+ d.value = p.visitExpr(val);
// Optionally preserve the name
switch (d.binding.data) {
.b_identifier => |id| {
- val = p.maybeKeepExprSymbolName(
- val,
+ d.value = p.maybeKeepExprSymbolName(
+ d.value.?,
p.symbols.items[id.ref.inner_index].original_name,
was_anonymous_named_expr,
);
@@ -11460,7 +11577,8 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
// TODO: simplify boolean expression
},
.s_if => |data| {
- data.test_ = SideEffects.simplifyBoolean(p, p.visitExpr(data.test_));
+ var test__ = p.visitExpr(data.test_);
+ data.test_ = SideEffects.simplifyBoolean(p, test__);
const effects = SideEffects.toBoolean(data.test_.data);
if (effects.ok and !effects.value) {
@@ -12186,6 +12304,9 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
},
);
},
+ .e_string => |str| {
+ return p.e(str, loc);
+ },
else => {},
}
@@ -12394,6 +12515,10 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
}
pub 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.");
+ }
+
class.ts_decorators = p.visitTSDecorators(class.ts_decorators);
if (class.class_name) |name| {
@@ -12540,6 +12665,10 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
// Try separating the list for appending, so that it's not a pointer.
fn visitStmts(p: *P, stmts: *List(Stmt), kind: StmtsKind) !void {
+ if (only_scan_imports_and_do_not_visit) {
+ @compileError("only_scan_imports_and_do_not_visit must not run this.");
+ }
+
// Save the current control-flow liveness. This represents if we are
// currently inside an "if (false) { ... }" block.
var old_is_control_flow_dead = p.is_control_flow_dead;
@@ -13025,6 +13154,7 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
.symbols = p.symbols.items,
.exports_ref = p.exports_ref,
.wrapper_ref = null,
+ .module_ref = p.module_ref,
.import_records = p.import_records.items,
.export_star_import_records = p.export_star_import_records.items,
.top_level_symbol_to_parts = p.top_level_symbol_to_parts,
@@ -13038,7 +13168,15 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
};
}
- pub fn init(allocator: *std.mem.Allocator, log: *logger.Log, source: *const logger.Source, define: *Define, lexer: js_lexer.Lexer, opts: Parser.Options) !*P {
+ pub fn init(
+ allocator: *std.mem.Allocator,
+ log: *logger.Log,
+ source: *const logger.Source,
+ define: *Define,
+ lexer: js_lexer.Lexer,
+ opts: Parser.Options,
+ this: *P,
+ ) !void {
var scope_order = try ScopeOrderList.initCapacity(allocator, 1);
var scope = try allocator.create(Scope);
scope.* = Scope{
@@ -13053,11 +13191,8 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
};
scope_order.appendAssumeCapacity(ScopeOrder{ .loc = locModuleScope, .scope = scope });
-
- var _parser = try allocator.create(P);
-
- _parser.* = P{
- .cjs_import_stmts = @TypeOf(_parser.cjs_import_stmts).init(allocator),
+ this.* = P{
+ .cjs_import_stmts = @TypeOf(this.cjs_import_stmts).init(allocator),
// This must default to true or else parsing "in" won't work right.
// It will fail for the case in the "in-keyword.js" file
.allow_in = true,
@@ -13068,44 +13203,54 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
.stmt_expr_value = nullExprData,
.expr_list = List(Expr).init(allocator),
.loop_body = nullStmtData,
- .injected_define_symbols = @TypeOf(_parser.injected_define_symbols).init(allocator),
- .emitted_namespace_vars = @TypeOf(_parser.emitted_namespace_vars).init(allocator),
- .is_exported_inside_namespace = @TypeOf(_parser.is_exported_inside_namespace).init(allocator),
- .known_enum_values = @TypeOf(_parser.known_enum_values).init(allocator),
- .local_type_names = @TypeOf(_parser.local_type_names).init(allocator),
- .allocated_names = @TypeOf(_parser.allocated_names).init(allocator),
+ .injected_define_symbols = @TypeOf(this.injected_define_symbols).init(allocator),
+ .emitted_namespace_vars = @TypeOf(this.emitted_namespace_vars).init(allocator),
+ .is_exported_inside_namespace = @TypeOf(this.is_exported_inside_namespace).init(allocator),
+ .known_enum_values = @TypeOf(this.known_enum_values).init(allocator),
+ .local_type_names = @TypeOf(this.local_type_names).init(allocator),
+ .allocated_names = @TypeOf(this.allocated_names).init(allocator),
.define = define,
- .scopes_for_current_part = @TypeOf(_parser.scopes_for_current_part).init(allocator),
- .symbols = @TypeOf(_parser.symbols).init(allocator),
- .ts_use_counts = @TypeOf(_parser.ts_use_counts).init(allocator),
- .declared_symbols = @TypeOf(_parser.declared_symbols).init(allocator),
- .import_records = @TypeOf(_parser.import_records).init(allocator),
- .import_records_for_current_part = @TypeOf(_parser.import_records_for_current_part).init(allocator),
- .export_star_import_records = @TypeOf(_parser.export_star_import_records).init(allocator),
- .import_items_for_namespace = @TypeOf(_parser.import_items_for_namespace).init(allocator),
- .named_imports = @TypeOf(_parser.named_imports).init(allocator),
- .named_exports = @TypeOf(_parser.named_exports).init(allocator),
- .top_level_symbol_to_parts = @TypeOf(_parser.top_level_symbol_to_parts).init(allocator),
- .import_namespace_cc_map = @TypeOf(_parser.import_namespace_cc_map).init(allocator),
+ .scopes_for_current_part = @TypeOf(this.scopes_for_current_part).init(allocator),
+ .symbols = @TypeOf(this.symbols).init(allocator),
+ .ts_use_counts = @TypeOf(this.ts_use_counts).init(allocator),
+ .declared_symbols = @TypeOf(this.declared_symbols).init(allocator),
+ .import_records = undefined,
+ .import_records_for_current_part = @TypeOf(this.import_records_for_current_part).init(allocator),
+ .export_star_import_records = @TypeOf(this.export_star_import_records).init(allocator),
+ .import_items_for_namespace = @TypeOf(this.import_items_for_namespace).init(allocator),
+ .named_imports = undefined,
+ .named_exports = @TypeOf(this.named_exports).init(allocator),
+ .top_level_symbol_to_parts = @TypeOf(this.top_level_symbol_to_parts).init(allocator),
+ .import_namespace_cc_map = @TypeOf(this.import_namespace_cc_map).init(allocator),
.scopes_in_order = scope_order,
.current_scope = scope,
- .temp_refs_to_declare = @TypeOf(_parser.temp_refs_to_declare).init(allocator),
- .relocated_top_level_vars = @TypeOf(_parser.relocated_top_level_vars).init(allocator),
+ .temp_refs_to_declare = @TypeOf(this.temp_refs_to_declare).init(allocator),
+ .relocated_top_level_vars = @TypeOf(this.relocated_top_level_vars).init(allocator),
.log = log,
- .is_import_item = @TypeOf(_parser.is_import_item).init(allocator),
+ .is_import_item = @TypeOf(this.is_import_item).init(allocator),
.allocator = allocator,
.options = opts,
.then_catch_chain = ThenCatchChain{ .next_target = nullExprData },
- .to_expr_wrapper_namespace = Binding2ExprWrapper.Namespace.init(_parser),
- .to_expr_wrapper_hoisted = Binding2ExprWrapper.Hoisted.init(_parser),
+ .to_expr_wrapper_namespace = undefined,
+ .to_expr_wrapper_hoisted = undefined,
+ .import_transposer = undefined,
+ .require_transposer = undefined,
+ .require_resolve_transposer = undefined,
.source = source,
- .import_transposer = @TypeOf(_parser.import_transposer).init(_parser),
- .require_transposer = @TypeOf(_parser.require_transposer).init(_parser),
- .require_resolve_transposer = @TypeOf(_parser.require_resolve_transposer).init(_parser),
+
.lexer = lexer,
};
- return _parser;
+ if (!only_scan_imports_and_do_not_visit) {
+ this.import_records = @TypeOf(this.import_records).init(allocator);
+ this.named_imports = NamedImportsType.init(allocator);
+ }
+
+ this.to_expr_wrapper_namespace = Binding2ExprWrapper.Namespace.init(this);
+ this.to_expr_wrapper_hoisted = Binding2ExprWrapper.Hoisted.init(this);
+ this.import_transposer = @TypeOf(this.import_transposer).init(this);
+ this.require_transposer = @TypeOf(this.require_transposer).init(this);
+ this.require_resolve_transposer = @TypeOf(this.require_resolve_transposer).init(this);
}
};
}
@@ -13121,10 +13266,15 @@ pub fn NewParser(comptime is_typescript_enabled: bool, comptime is_jsx_enabled:
// Range (min … max): 24.1 ms … 39.7 ms 500 runs
// '../../build/macos-x86_64/esdev node_modules/react-dom/cjs/react-dom.development.js --resolve=disable' ran
// 1.02 ± 0.07 times faster than '../../esdev.before-comptime-js-parser node_modules/react-dom/cjs/react-dom.development.js --resolve=disable'
-const JavaScriptParser = NewParser(false, false);
-const JSXParser = NewParser(false, true);
-const TSXParser = NewParser(true, true);
-const TypeScriptParser = NewParser(true, false);
+const JavaScriptParser = NewParser(false, false, false);
+const JSXParser = NewParser(false, true, false);
+const TSXParser = NewParser(true, true, false);
+const TypeScriptParser = NewParser(true, false, false);
+
+const JavaScriptImportScanner = NewParser(false, false, true);
+const JSXImportScanner = NewParser(false, true, true);
+const TSXImportScanner = NewParser(true, true, true);
+const TypeScriptImportScanner = NewParser(true, false, true);
// The "await" and "yield" expressions are never allowed in argument lists but
// may or may not be allowed otherwise depending on the details of the enclosing