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.zig162
1 files changed, 61 insertions, 101 deletions
diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig
index 6bb003e89..33b999e4f 100644
--- a/src/js_parser/js_parser.zig
+++ b/src/js_parser/js_parser.zig
@@ -439,78 +439,47 @@ pub const ImportScanner = struct {
}
}
- if (st.star_name_loc != null or did_remove_star_loc) {
- // -- Original Comment --
- // If we're bundling a star import and the namespace is only ever
- // used for property accesses, then convert each unique property to
- // a clause item in the import statement and remove the star import.
- // That will cause the bundler to bundle them more efficiently when
- // both this module and the imported module are in the same group.
- //
- // Before:
- //
- // import * as ns from 'foo'
- // console.log(ns.a, ns.b)
- //
- // After:
- //
- // import {a, b} from 'foo'
- // console.log(a, b)
- //
- // This is not done if the namespace itself is used, because in that
- // case the code for the namespace will have to be generated. This is
- // determined by the symbol count because the parser only counts the
- // star import as used if it was used for something other than a
- // property access:
- //
- // import * as ns from 'foo'
- // console.log(ns, ns.a, ns.b)
- //
- // -- Original Comment --
+ const namespace_ref = st.namespace_ref;
+ const convert_star_to_clause = !p.options.enable_bundling and !p.options.can_import_from_bundle and p.symbols.items[namespace_ref.inner_index].use_count_estimate == 0;
- // jarred: we don't use the same grouping mechanism as esbuild
- // but, we do this anyway.
- // The reasons why are:
- // * It makes static analysis for other tools simpler.
- // * I imagine browsers may someday do some optimizations
- // when it's "easier" to know only certain modules are used
- // For example, if you're importing a component from a design system
- // it's really stupid to import all 1,000 components from that design system
- // when you just want <Button />
- const namespace_ref = st.namespace_ref;
- const convert_star_to_clause = !p.options.enable_bundling and !p.options.can_import_from_bundle and p.symbols.items[namespace_ref.inner_index].use_count_estimate == 0;
+ if (convert_star_to_clause and !keep_unused_imports) {
+ st.star_name_loc = null;
+ }
- if (convert_star_to_clause and !keep_unused_imports) {
- st.star_name_loc = null;
- }
+ record.contains_default_alias = record.contains_default_alias or st.default_name != null;
- const default_name: string = if (st.default_name != null)
- p.loadNameFromRef(st.default_name.?.ref.?)
- else
- "";
+ const existing_items: ImportItemForNamespaceMap = p.import_items_for_namespace.get(namespace_ref) orelse
+ ImportItemForNamespaceMap.init(p.allocator);
- for (st.items) |item| {
- const is_default = strings.eqlComptime(item.alias, "default");
- record.contains_default_alias = record.contains_default_alias or is_default;
+ // ESM requires live bindings
+ // CommonJS does not require live bindings
+ // We load ESM in browsers & in Bun.js
+ // We have to simulate live bindings for cases where the code is bundled
+ // We do not know at this stage whether or not the import statement is bundled
+ // This keeps track of the `namespace_alias` incase, at printing time, we determine that we should print it with the namespace
+ for (st.items) |item| {
+ const is_default = strings.eqlComptime(item.alias, "default");
+ record.contains_default_alias = record.contains_default_alias or is_default;
- const name: LocRef = item.name;
- const name_ref = name.ref.?;
+ const name: LocRef = item.name;
+ const name_ref = name.ref.?;
- try p.named_imports.put(name_ref, js_ast.NamedImport{
- .alias = item.alias,
- .alias_loc = name.loc,
- .namespace_ref = st.namespace_ref,
- .import_record_index = st.import_record_index,
- });
+ try p.named_imports.put(name_ref, js_ast.NamedImport{
+ .alias = item.alias,
+ .alias_loc = name.loc,
+ .namespace_ref = st.namespace_ref,
+ .import_record_index = st.import_record_index,
+ });
- // Make sure the printer prints this as a property access
- var symbol: *Symbol = &p.symbols.items[name_ref.inner_index];
- symbol.namespace_alias = G.NamespaceAlias{
- .namespace_ref = st.namespace_ref,
- .alias = item.original_name,
- .import_record_index = st.import_record_index,
- };
- }
+ // Make sure the printer prints this as a property access
+ var symbol: *Symbol = &p.symbols.items[name_ref.inner_index];
+
+ symbol.namespace_alias = G.NamespaceAlias{
+ .namespace_ref = st.namespace_ref,
+ .alias = item.alias,
+ .import_record_index = st.import_record_index,
+ .was_originally_property_access = st.star_name_loc != null and existing_items.contains(symbol.original_name),
+ };
}
try p.import_records_for_current_part.append(st.import_record_index);
@@ -518,18 +487,8 @@ pub const ImportScanner = struct {
if (st.star_name_loc != null) {
record.contains_import_star = true;
}
-
- if (st.default_name != null) {
- record.contains_default_alias = true;
- } else {
- for (st.items) |item| {
- if (strings.eqlComptime(item.alias, "default")) {
- record.contains_default_alias = true;
- break;
- }
- }
- }
},
+
.s_function => |st| {
if (st.func.flags.is_export) {
if (st.func.name) |name| {
@@ -3626,7 +3585,6 @@ pub fn NewParser(
const namespace_ref = try p.newSymbol(.other, namespace_identifier);
try p.module_scope.generated.append(namespace_ref);
-
for (imports) |alias, i| {
const ref = symbols.get(alias) orelse unreachable;
const alias_name = if (@TypeOf(symbols) == RuntimeImports) RuntimeImports.all[alias] else alias;
@@ -6182,6 +6140,7 @@ pub fn NewParser(
var remap_count: u16 = 0;
if (stmt.star_name_loc) |star| {
const name = p.loadNameFromRef(stmt.namespace_ref);
+
stmt.namespace_ref = try p.declareSymbol(.import, star, name);
if (comptime ParsePassSymbolUsageType != void) {
if (!is_macro) {
@@ -6257,9 +6216,11 @@ pub fn NewParser(
if (stmt.items.len > 0) {
for (stmt.items) |*item| {
const name = p.loadNameFromRef(item.name.ref orelse unreachable);
+
const ref = try p.declareSymbol(.import, item.name.loc, name);
p.checkForNonBMPCodePoint(item.alias_loc, item.alias);
try p.is_import_item.put(ref, true);
+
item.name.ref = ref;
item_refs.putAssumeCapacity(item.alias, LocRef{ .loc = item.name.loc, .ref = ref });
@@ -7692,10 +7653,9 @@ 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)];
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);
@@ -7723,6 +7683,11 @@ pub fn NewParser(
// else => unreachable,
}
} else {
+ // Ensure that EImportIdentifier is created for the symbol in handleIdentifier
+ if (symbol.kind == .import and kind != .import) {
+ try p.is_import_item.put(ref, true);
+ }
+
p.symbols.items[ref.inner_index].link = existing.ref;
}
}
@@ -9635,9 +9600,10 @@ pub fn NewParser(
for (import.items) |*clause| {
const import_hash_name = clause.original_name;
- if (strings.eqlComptime(clause.alias, "default") and strings.eqlComptime(clause.original_name, "default")) {
+ if (strings.eqlComptime(clause.alias, "default")) {
var non_unique_name = record.path.name.nonUniqueNameString(p.allocator) catch unreachable;
clause.original_name = std.fmt.allocPrint(p.allocator, "{s}_default", .{non_unique_name}) catch unreachable;
+ record.contains_default_alias = true;
}
const name_ref = p.declareSymbol(.import, this.loc, clause.original_name) catch unreachable;
clause.name = LocRef{ .loc = this.loc, .ref = name_ref };
@@ -9649,7 +9615,7 @@ pub fn NewParser(
// Ensure we don't accidentally think this is an export from
}
- p.macro.prepend_stmts.append(p.visitSingleStmt(p.s(import, this.loc), StmtsKind.none)) catch unreachable;
+ p.macro.prepend_stmts.append(p.s(import, this.loc)) catch unreachable;
}
};
@@ -11325,7 +11291,6 @@ pub fn NewParser(
return p.e(
E.ImportIdentifier{
.was_originally_identifier = false,
- .was_from_macro = true,
.ref = ref,
},
expr.loc,
@@ -12571,7 +12536,10 @@ pub fn NewParser(
}
fn jsxStringsToMemberExpressionAutomatic(p: *P, loc: logger.Loc, is_static: bool) Expr {
- return p.jsxStringsToMemberExpression(loc, if (is_static) p.jsxs_runtime.ref else p.jsx_runtime.ref);
+ return p.jsxStringsToMemberExpression(loc, if (is_static and !p.options.jsx.development)
+ p.jsxs_runtime.ref
+ else
+ p.jsx_runtime.ref);
}
fn maybeRelocateVarsToTopLevel(p: *P, decls: []G.Decl, mode: RelocateVars.Mode) RelocateVars {
@@ -12790,17 +12758,19 @@ pub fn NewParser(
data.value.expr = p.visitExpr(expr);
// // Optionally preserve the name
- data.value.expr = p.maybeKeepExprSymbolName(data.value.expr, "default", was_anonymous_named_expr);
+ data.value.expr = p.maybeKeepExprSymbolName(data.value.expr, js_ast.ClauseItem.default_alias, was_anonymous_named_expr);
// Discard type-only export default statements
if (is_typescript_enabled) {
switch (expr.data) {
.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| {
- if (local_type) {
- return;
+ if (!ident.ref.is_source_contents_slice) {
+ const symbol = p.symbols.items[ident.ref.inner_index];
+ if (symbol.kind == .unbound) {
+ if (p.local_type_names.get(symbol.original_name)) |local_type| {
+ if (local_type) {
+ return;
+ }
}
}
}
@@ -12828,7 +12798,7 @@ pub fn NewParser(
name = p.loadNameFromRef(func_loc.ref.?);
} else {
func.func.name = data.default_name;
- name = "default";
+ name = js_ast.ClauseItem.default_alias;
}
func.func = p.visitFunc(func.func, func.func.open_parens_loc);
@@ -12906,17 +12876,7 @@ pub fn NewParser(
// "module.exports = value"
stmts.append(
Expr.assignStmt(
- p.e(
- E.Dot{
- .target = p.e(
- E.Identifier{
- .ref = p.module_ref,
- },
- stmt.loc,
- ),
- .name = "exports",
- .name_loc = stmt.loc,
- },
+ p.@"module.exports"(
stmt.loc,
),
p.visitExpr(data.value),