diff options
author | 2022-05-19 19:27:23 -0700 | |
---|---|---|
committer | 2022-05-19 19:27:23 -0700 | |
commit | 1d0124093c1e6e3fd8acb102856f07ffdf02ef40 (patch) | |
tree | a1f13e29a2741c8f8a1b8738e1bdde612edb7362 /src | |
parent | 70078f48c05e89c53d38bb5959d431a1c3d134ce (diff) | |
download | bun-1d0124093c1e6e3fd8acb102856f07ffdf02ef40.tar.gz bun-1d0124093c1e6e3fd8acb102856f07ffdf02ef40.tar.zst bun-1d0124093c1e6e3fd8acb102856f07ffdf02ef40.zip |
[solid] Move the post-process JSX step
Diffstat (limited to 'src')
-rw-r--r-- | src/js_ast.zig | 21 | ||||
-rw-r--r-- | src/js_parser.zig | 928 |
2 files changed, 497 insertions, 452 deletions
diff --git a/src/js_ast.zig b/src/js_ast.zig index 7c5603f28..13ba491bf 100644 --- a/src/js_ast.zig +++ b/src/js_ast.zig @@ -557,6 +557,8 @@ pub const Binding = struct { } }; +/// B is for Binding! +/// These are the types of bindings that can be used in the AST. pub const B = union(Binding.Tag) { b_identifier: *B.Identifier, b_array: *B.Array, @@ -1286,6 +1288,9 @@ pub const E = struct { /// If React Fast Refresh ends up using this later, then we can revisit this decision. /// [0]: https://github.com/automerge/automerge/issues/177 pub const JSXElement = struct { + /// JSX tag name + /// <div> => E.String.init("div") + /// <MyComponent> => E.Identifier{.ref = symbolPointingToMyComponent } /// null represents a fragment tag: ?ExprNodeIndex = null, @@ -3566,6 +3571,22 @@ pub const Expr = struct { @"string", bigint, + pub const static = std.enums.EnumSet(PrimitiveType).init(.{ + .@"mixed" = true, + .@"null" = true, + .@"undefined" = true, + .@"boolean" = true, + .@"number" = true, + .@"string" = true, + // for our purposes, bigint is dynamic + // it is technically static though + // .@"bigint" = true, + }); + + pub inline fn isStatic(this: PrimitiveType) bool { + return static.contains(this); + } + pub fn merge(left_known: PrimitiveType, right_known: PrimitiveType) PrimitiveType { if (right_known == .unknown or left_known == .unknown) return .unknown; diff --git a/src/js_parser.zig b/src/js_parser.zig index 9cd910795..0e6d8ecd3 100644 --- a/src/js_parser.zig +++ b/src/js_parser.zig @@ -80,7 +80,7 @@ const NodeFallbackModules = @import("./node_fallbacks.zig"); // Everything in JavaScript is either an Expression, a Binding, or a Statement. // Expression: foo(1) // Statement: let a = 1; -// Binding: 1 +// Binding: a // While the names for Expr, Binding, and Stmt are directly copied from esbuild, those were likely inspired by Go's parser. // which is another example of a very fast parser. @@ -2545,480 +2545,491 @@ pub const Parser = struct { exports_kind = .esm; } - // Auto-import JSX - if (ParserType.jsx_transform_type == .react) { - const jsx_filename_symbol = p.symbols.items[p.jsx_filename.ref.innerIndex()]; + // Auto-import & post-process JSX + switch (comptime ParserType.jsx_transform_type) { + .react => { + const jsx_filename_symbol = p.symbols.items[p.jsx_filename.ref.innerIndex()]; - { - const jsx_symbol = p.symbols.items[p.jsx_runtime.ref.innerIndex()]; - const jsx_static_symbol = p.symbols.items[p.jsxs_runtime.ref.innerIndex()]; - const jsx_fragment_symbol = p.symbols.items[p.jsx_fragment.ref.innerIndex()]; - const jsx_factory_symbol = p.symbols.items[p.jsx_factory.ref.innerIndex()]; - - // 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 - // Given that, we can't directly call import {jsxDEV} from 'react'; - // Instead, we must call require("react").default.jsxDEV - // So a jsx_symbol usage means a jsx_factory_symbol usage - // This is kind of a broken way of doing it because it wouldn't work if it was more than one level deep - if (FeatureFlags.jsx_runtime_is_cjs) { - if (jsx_symbol.use_count_estimate > 0 or jsx_static_symbol.use_count_estimate > 0) { - p.recordUsage(p.jsx_automatic.ref); - } - - if (jsx_fragment_symbol.use_count_estimate > 0) { - p.recordUsage(p.jsx_classic.ref); - } - - if (jsx_factory_symbol.use_count_estimate > 0) { - p.recordUsage(p.jsx_classic.ref); - } - } - } - - p.resolveStaticJSXSymbols(); - - if (p.options.features.auto_import_jsx) { - const jsx_classic_symbol = p.symbols.items[p.jsx_classic.ref.innerIndex()]; - const jsx_automatic_symbol = p.symbols.items[p.jsx_automatic.ref.innerIndex()]; - - // JSX auto-imports - // The classic runtime is a different import than the main import - // There are cases where you can use both JSX runtimes in the same file. - // 1. If you use a spread operator like this: <div foo bar key="foo" {...props} baz /> - // 2. If you use a React.Fragment - // So we have to support both. - if (jsx_classic_symbol.use_count_estimate > 0 or jsx_automatic_symbol.use_count_estimate > 0) { - // These must unfortunately be copied - // p.symbols may grow during this scope - // if it grows, the previous pointers are invalidated + { const jsx_symbol = p.symbols.items[p.jsx_runtime.ref.innerIndex()]; const jsx_static_symbol = p.symbols.items[p.jsxs_runtime.ref.innerIndex()]; const jsx_fragment_symbol = p.symbols.items[p.jsx_fragment.ref.innerIndex()]; const jsx_factory_symbol = p.symbols.items[p.jsx_factory.ref.innerIndex()]; - const classic_namespace_ref = p.jsx_classic.ref; - const automatic_namespace_ref = p.jsx_automatic.ref; - - const decls_count: u32 = - @intCast(u32, @boolToInt(jsx_symbol.use_count_estimate > 0)) * 2 + - @intCast(u32, @boolToInt(jsx_static_symbol.use_count_estimate > 0)) * 2 + - @intCast(u32, @boolToInt(jsx_factory_symbol.use_count_estimate > 0)) + - @intCast(u32, @boolToInt(jsx_fragment_symbol.use_count_estimate > 0)) + - @intCast(u32, @boolToInt(jsx_filename_symbol.use_count_estimate > 0)); - - const imports_count = - @intCast(u32, @boolToInt(jsx_symbol.use_count_estimate > 0)) + - @intCast(u32, @boolToInt(jsx_classic_symbol.use_count_estimate > 0)) + - @intCast(u32, @boolToInt(jsx_fragment_symbol.use_count_estimate > 0)) + - @intCast(u32, @boolToInt(p.options.features.react_fast_refresh)) + - @intCast(u32, @boolToInt(jsx_static_symbol.use_count_estimate > 0)); - const stmts_count = imports_count + 1; - const symbols_count: u32 = imports_count + decls_count; - const loc = logger.Loc{ .start = 0 }; - - // Preallocate everything we'll need here - var declared_symbols = try p.allocator.alloc(js_ast.DeclaredSymbol, symbols_count); - var decls = try p.allocator.alloc(G.Decl, decls_count); - var jsx_part_stmts = try p.allocator.alloc(Stmt, stmts_count); - // Use the same array for storing the require call target of potentially both JSX runtimes - var require_call_args_base = p.allocator.alloc(Expr, if (p.options.can_import_from_bundle) 0 else imports_count) catch unreachable; - var import_records = try p.allocator.alloc(u32, imports_count); - - var decl_i: usize = 0; - var declared_symbols_i: usize = 0; - var import_record_i: usize = 0; - var require_call_args_i: usize = 0; - var stmt_i: usize = 0; - - if (jsx_symbol.use_count_estimate > 0 or jsx_static_symbol.use_count_estimate > 0) { - declared_symbols[declared_symbols_i] = .{ .ref = automatic_namespace_ref, .is_top_level = true }; - declared_symbols_i += 1; - - const automatic_identifier = p.e(E.ImportIdentifier{ .ref = automatic_namespace_ref }, loc); - const dot_call_target = brk: { - if (p.options.can_import_from_bundle or p.options.enable_bundling or !p.options.features.allow_runtime) { - break :brk automatic_identifier; - } else { - require_call_args_base[require_call_args_i] = automatic_identifier; - require_call_args_i += 1; - break :brk p.callUnbundledRequire(require_call_args_base[0..require_call_args_i]); - } - }; + // 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 + // Given that, we can't directly call import {jsxDEV} from 'react'; + // Instead, we must call require("react").default.jsxDEV + // So a jsx_symbol usage means a jsx_factory_symbol usage + // This is kind of a broken way of doing it because it wouldn't work if it was more than one level deep + if (FeatureFlags.jsx_runtime_is_cjs) { + if (jsx_symbol.use_count_estimate > 0 or jsx_static_symbol.use_count_estimate > 0) { + p.recordUsage(p.jsx_automatic.ref); + } - if (jsx_symbol.use_count_estimate > 0) { - declared_symbols[declared_symbols_i] = .{ .ref = p.jsx_runtime.ref, .is_top_level = true }; - declared_symbols_i += 1; + if (jsx_fragment_symbol.use_count_estimate > 0) { + p.recordUsage(p.jsx_classic.ref); + } - decls[decl_i] = G.Decl{ - .binding = p.b( - B.Identifier{ - .ref = p.jsx_runtime.ref, - }, - loc, - ), - .value = p.e( - E.Dot{ - .target = dot_call_target, - .name = p.options.jsx.jsx, - .name_loc = loc, - .can_be_removed_if_unused = true, - }, - loc, - ), - }; - decl_i += 1; + if (jsx_factory_symbol.use_count_estimate > 0) { + p.recordUsage(p.jsx_classic.ref); } + } + } - if (jsx_static_symbol.use_count_estimate > 0) { - declared_symbols[declared_symbols_i] = .{ .ref = p.jsxs_runtime.ref, .is_top_level = true }; + p.resolveStaticJSXSymbols(); + + if (p.options.features.auto_import_jsx) { + const jsx_classic_symbol = p.symbols.items[p.jsx_classic.ref.innerIndex()]; + const jsx_automatic_symbol = p.symbols.items[p.jsx_automatic.ref.innerIndex()]; + + // JSX auto-imports + // The classic runtime is a different import than the main import + // There are cases where you can use both JSX runtimes in the same file. + // 1. If you use a spread operator like this: <div foo bar key="foo" {...props} baz /> + // 2. If you use a React.Fragment + // So we have to support both. + if (jsx_classic_symbol.use_count_estimate > 0 or jsx_automatic_symbol.use_count_estimate > 0) { + // These must unfortunately be copied + // p.symbols may grow during this scope + // if it grows, the previous pointers are invalidated + const jsx_symbol = p.symbols.items[p.jsx_runtime.ref.innerIndex()]; + const jsx_static_symbol = p.symbols.items[p.jsxs_runtime.ref.innerIndex()]; + const jsx_fragment_symbol = p.symbols.items[p.jsx_fragment.ref.innerIndex()]; + const jsx_factory_symbol = p.symbols.items[p.jsx_factory.ref.innerIndex()]; + + const classic_namespace_ref = p.jsx_classic.ref; + const automatic_namespace_ref = p.jsx_automatic.ref; + + const decls_count: u32 = + @intCast(u32, @boolToInt(jsx_symbol.use_count_estimate > 0)) * 2 + + @intCast(u32, @boolToInt(jsx_static_symbol.use_count_estimate > 0)) * 2 + + @intCast(u32, @boolToInt(jsx_factory_symbol.use_count_estimate > 0)) + + @intCast(u32, @boolToInt(jsx_fragment_symbol.use_count_estimate > 0)) + + @intCast(u32, @boolToInt(jsx_filename_symbol.use_count_estimate > 0)); + + const imports_count = + @intCast(u32, @boolToInt(jsx_symbol.use_count_estimate > 0)) + + @intCast(u32, @boolToInt(jsx_classic_symbol.use_count_estimate > 0)) + + @intCast(u32, @boolToInt(jsx_fragment_symbol.use_count_estimate > 0)) + + @intCast(u32, @boolToInt(p.options.features.react_fast_refresh)) + + @intCast(u32, @boolToInt(jsx_static_symbol.use_count_estimate > 0)); + const stmts_count = imports_count + 1; + const symbols_count: u32 = imports_count + decls_count; + const loc = logger.Loc{ .start = 0 }; + + // Preallocate everything we'll need here + var declared_symbols = try p.allocator.alloc(js_ast.DeclaredSymbol, symbols_count); + var decls = try p.allocator.alloc(G.Decl, decls_count); + var jsx_part_stmts = try p.allocator.alloc(Stmt, stmts_count); + // Use the same array for storing the require call target of potentially both JSX runtimes + var require_call_args_base = p.allocator.alloc(Expr, if (p.options.can_import_from_bundle) 0 else imports_count) catch unreachable; + var import_records = try p.allocator.alloc(u32, imports_count); + + var decl_i: usize = 0; + var declared_symbols_i: usize = 0; + var import_record_i: usize = 0; + var require_call_args_i: usize = 0; + var stmt_i: usize = 0; + + if (jsx_symbol.use_count_estimate > 0 or jsx_static_symbol.use_count_estimate > 0) { + declared_symbols[declared_symbols_i] = .{ .ref = automatic_namespace_ref, .is_top_level = true }; declared_symbols_i += 1; - decls[decl_i] = G.Decl{ - .binding = p.b( - B.Identifier{ - .ref = p.jsxs_runtime.ref, - }, - loc, - ), - .value = p.e( - E.Dot{ - .target = dot_call_target, - .name = p.options.jsx.jsx_static, - .name_loc = loc, - .can_be_removed_if_unused = true, - }, - loc, - ), + const automatic_identifier = p.e(E.ImportIdentifier{ .ref = automatic_namespace_ref }, loc); + const dot_call_target = brk: { + if (p.options.can_import_from_bundle or p.options.enable_bundling or !p.options.features.allow_runtime) { + break :brk automatic_identifier; + } else { + require_call_args_base[require_call_args_i] = automatic_identifier; + require_call_args_i += 1; + break :brk p.callUnbundledRequire(require_call_args_base[0..require_call_args_i]); + } }; - decl_i += 1; - } + if (jsx_symbol.use_count_estimate > 0) { + declared_symbols[declared_symbols_i] = .{ .ref = p.jsx_runtime.ref, .is_top_level = true }; + declared_symbols_i += 1; - if (jsx_filename_symbol.use_count_estimate > 0) { - declared_symbols[declared_symbols_i] = .{ .ref = p.jsx_filename.ref, .is_top_level = true }; - declared_symbols_i += 1; - decls[decl_i] = G.Decl{ - .binding = p.b( - B.Identifier{ - .ref = p.jsx_filename.ref, - }, - loc, - ), - .value = p.e(E.String{ .data = p.source.path.pretty }, loc), - }; - decl_i += 1; - } + decls[decl_i] = G.Decl{ + .binding = p.b( + B.Identifier{ + .ref = p.jsx_runtime.ref, + }, + loc, + ), + .value = p.e( + E.Dot{ + .target = dot_call_target, + .name = p.options.jsx.jsx, + .name_loc = loc, + .can_be_removed_if_unused = true, + }, + loc, + ), + }; + decl_i += 1; + } - // We do not mark this as .require becuase we are already wrapping it manually. - const import_record_id = p.addImportRecord(.internal, loc, p.options.jsx.import_source); - p.import_records.items[import_record_id].tag = .jsx_import; - // When everything is CommonJS - // We import JSX like this: - // var {jsxDev} = require("react/jsx-dev") + if (jsx_static_symbol.use_count_estimate > 0) { + declared_symbols[declared_symbols_i] = .{ .ref = p.jsxs_runtime.ref, .is_top_level = true }; + declared_symbols_i += 1; - jsx_part_stmts[stmt_i] = p.s(S.Import{ - .namespace_ref = automatic_namespace_ref, - .star_name_loc = loc, - .is_single_line = true, - .import_record_index = import_record_id, - }, loc); + decls[decl_i] = G.Decl{ + .binding = p.b( + B.Identifier{ + .ref = p.jsxs_runtime.ref, + }, + loc, + ), + .value = p.e( + E.Dot{ + .target = dot_call_target, + .name = p.options.jsx.jsx_static, + .name_loc = loc, + .can_be_removed_if_unused = true, + }, + loc, + ), + }; - stmt_i += 1; - p.named_imports.put( - automatic_namespace_ref, - js_ast.NamedImport{ - .alias = jsx_automatic_symbol.original_name, - .alias_is_star = true, - .alias_loc = loc, - .namespace_ref = automatic_namespace_ref, - .import_record_index = import_record_id, - }, - ) catch unreachable; - p.is_import_item.put(p.allocator, automatic_namespace_ref, .{}) catch unreachable; - import_records[import_record_i] = import_record_id; - import_record_i += 1; - } + decl_i += 1; + } - if (jsx_classic_symbol.use_count_estimate > 0) { - const classic_identifier = p.e(E.ImportIdentifier{ .ref = classic_namespace_ref }, loc); + if (jsx_filename_symbol.use_count_estimate > 0) { + declared_symbols[declared_symbols_i] = .{ .ref = p.jsx_filename.ref, .is_top_level = true }; + declared_symbols_i += 1; + decls[decl_i] = G.Decl{ + .binding = p.b( + B.Identifier{ + .ref = p.jsx_filename.ref, + }, + loc, + ), + .value = p.e(E.String{ .data = p.source.path.pretty }, loc), + }; + decl_i += 1; + } - const dot_call_target = brk: { - // var react = $aopaSD123(); + // We do not mark this as .require becuase we are already wrapping it manually. + const import_record_id = p.addImportRecord(.internal, loc, p.options.jsx.import_source); + p.import_records.items[import_record_id].tag = .jsx_import; + // When everything is CommonJS + // We import JSX like this: + // var {jsxDev} = require("react/jsx-dev") - if (p.options.can_import_from_bundle or p.options.enable_bundling or !p.options.features.allow_runtime) { - break :brk classic_identifier; - } else { - const require_call_args_start = require_call_args_i; - require_call_args_base[require_call_args_i] = classic_identifier; - require_call_args_i += 1; - break :brk p.callUnbundledRequire(require_call_args_base[require_call_args_start..][0..1]); - } - }; + jsx_part_stmts[stmt_i] = p.s(S.Import{ + .namespace_ref = automatic_namespace_ref, + .star_name_loc = loc, + .is_single_line = true, + .import_record_index = import_record_id, + }, loc); - if (jsx_factory_symbol.use_count_estimate > 0) { - declared_symbols[declared_symbols_i] = .{ .ref = p.jsx_factory.ref, .is_top_level = true }; - declared_symbols_i += 1; - decls[decl_i] = G.Decl{ - .binding = p.b( - B.Identifier{ - .ref = p.jsx_factory.ref, - }, - loc, - ), - .value = p.e( - E.Dot{ - .target = dot_call_target, - .name = p.options.jsx.factory[p.options.jsx.factory.len - 1], - .name_loc = loc, - .can_be_removed_if_unused = true, - }, - loc, - ), - }; - decl_i += 1; + stmt_i += 1; + p.named_imports.put( + automatic_namespace_ref, + js_ast.NamedImport{ + .alias = jsx_automatic_symbol.original_name, + .alias_is_star = true, + .alias_loc = loc, + .namespace_ref = automatic_namespace_ref, + .import_record_index = import_record_id, + }, + ) catch unreachable; + p.is_import_item.put(p.allocator, automatic_namespace_ref, .{}) catch unreachable; + import_records[import_record_i] = import_record_id; + import_record_i += 1; } - if (jsx_fragment_symbol.use_count_estimate > 0) { - declared_symbols[declared_symbols_i] = .{ .ref = p.jsx_fragment.ref, .is_top_level = true }; - declared_symbols_i += 1; - decls[decl_i] = G.Decl{ - .binding = p.b( - B.Identifier{ - .ref = p.jsx_fragment.ref, - }, - loc, - ), - .value = p.e( - E.Dot{ - .target = dot_call_target, - .name = p.options.jsx.fragment[p.options.jsx.fragment.len - 1], - .name_loc = loc, - .can_be_removed_if_unused = true, - }, - loc, - ), - }; - decl_i += 1; - } - const import_record_id = p.addImportRecord(.require, loc, p.options.jsx.classic_import_source); - jsx_part_stmts[stmt_i] = p.s(S.Import{ - .namespace_ref = classic_namespace_ref, - .star_name_loc = loc, - .is_single_line = true, - .import_record_index = import_record_id, - }, loc); - p.import_records.items[import_record_id].tag = .jsx_classic; - stmt_i += 1; - p.named_imports.put( - classic_namespace_ref, - js_ast.NamedImport{ - .alias = jsx_classic_symbol.original_name, - .alias_is_star = true, - .alias_loc = loc, - .namespace_ref = classic_namespace_ref, - .import_record_index = import_record_id, - }, - ) catch unreachable; - p.is_import_item.put(p.allocator, classic_namespace_ref, .{}) catch unreachable; - import_records[import_record_i] = import_record_id; - declared_symbols[declared_symbols_i] = .{ .ref = classic_namespace_ref, .is_top_level = true }; - declared_symbols_i += 1; - } + if (jsx_classic_symbol.use_count_estimate > 0) { + const classic_identifier = p.e(E.ImportIdentifier{ .ref = classic_namespace_ref }, loc); - if (p.options.features.react_fast_refresh) { - defer did_import_fast_refresh = true; - p.resolveGeneratedSymbol(&p.jsx_refresh_runtime); - if (!p.options.jsx.use_embedded_refresh_runtime) { - const refresh_runtime_symbol: *const Symbol = &p.symbols.items[p.jsx_refresh_runtime.ref.innerIndex()]; + const dot_call_target = brk: { + // var react = $aopaSD123(); - declared_symbols[declared_symbols_i] = .{ .ref = p.jsx_refresh_runtime.ref, .is_top_level = true }; - declared_symbols_i += 1; + if (p.options.can_import_from_bundle or p.options.enable_bundling or !p.options.features.allow_runtime) { + break :brk classic_identifier; + } else { + const require_call_args_start = require_call_args_i; + require_call_args_base[require_call_args_i] = classic_identifier; + require_call_args_i += 1; + break :brk p.callUnbundledRequire(require_call_args_base[require_call_args_start..][0..1]); + } + }; + + if (jsx_factory_symbol.use_count_estimate > 0) { + declared_symbols[declared_symbols_i] = .{ .ref = p.jsx_factory.ref, .is_top_level = true }; + declared_symbols_i += 1; + decls[decl_i] = G.Decl{ + .binding = p.b( + B.Identifier{ + .ref = p.jsx_factory.ref, + }, + loc, + ), + .value = p.e( + E.Dot{ + .target = dot_call_target, + .name = p.options.jsx.factory[p.options.jsx.factory.len - 1], + .name_loc = loc, + .can_be_removed_if_unused = true, + }, + loc, + ), + }; + decl_i += 1; + } - const import_record_id = p.addImportRecord(.require, loc, p.options.jsx.refresh_runtime); - p.import_records.items[import_record_id].tag = .react_refresh; + if (jsx_fragment_symbol.use_count_estimate > 0) { + declared_symbols[declared_symbols_i] = .{ .ref = p.jsx_fragment.ref, .is_top_level = true }; + declared_symbols_i += 1; + decls[decl_i] = G.Decl{ + .binding = p.b( + B.Identifier{ + .ref = p.jsx_fragment.ref, + }, + loc, + ), + .value = p.e( + E.Dot{ + .target = dot_call_target, + .name = p.options.jsx.fragment[p.options.jsx.fragment.len - 1], + .name_loc = loc, + .can_be_removed_if_unused = true, + }, + loc, + ), + }; + decl_i += 1; + } + const import_record_id = p.addImportRecord(.require, loc, p.options.jsx.classic_import_source); jsx_part_stmts[stmt_i] = p.s(S.Import{ - .namespace_ref = p.jsx_refresh_runtime.ref, + .namespace_ref = classic_namespace_ref, .star_name_loc = loc, .is_single_line = true, .import_record_index = import_record_id, }, loc); - + p.import_records.items[import_record_id].tag = .jsx_classic; stmt_i += 1; p.named_imports.put( - p.jsx_refresh_runtime.ref, + classic_namespace_ref, js_ast.NamedImport{ - .alias = refresh_runtime_symbol.original_name, + .alias = jsx_classic_symbol.original_name, .alias_is_star = true, .alias_loc = loc, - .namespace_ref = p.jsx_refresh_runtime.ref, + .namespace_ref = classic_namespace_ref, .import_record_index = import_record_id, }, ) catch unreachable; - p.is_import_item.put(p.allocator, p.jsx_refresh_runtime.ref, .{}) catch unreachable; + p.is_import_item.put(p.allocator, classic_namespace_ref, .{}) catch unreachable; import_records[import_record_i] = import_record_id; + declared_symbols[declared_symbols_i] = .{ .ref = classic_namespace_ref, .is_top_level = true }; + declared_symbols_i += 1; } - p.recordUsage(p.jsx_refresh_runtime.ref); - } - jsx_part_stmts[stmt_i] = p.s(S.Local{ .kind = .k_var, .decls = decls[0..decl_i] }, loc); - stmt_i += 1; + if (p.options.features.react_fast_refresh) { + defer did_import_fast_refresh = true; + p.resolveGeneratedSymbol(&p.jsx_refresh_runtime); + if (!p.options.jsx.use_embedded_refresh_runtime) { + const refresh_runtime_symbol: *const Symbol = &p.symbols.items[p.jsx_refresh_runtime.ref.innerIndex()]; - before.append(js_ast.Part{ - .stmts = jsx_part_stmts[0..stmt_i], - .declared_symbols = declared_symbols, - .import_record_indices = import_records, - .tag = .jsx_import, - }) catch unreachable; - } - } + declared_symbols[declared_symbols_i] = .{ .ref = p.jsx_refresh_runtime.ref, .is_top_level = true }; + declared_symbols_i += 1; - if (!did_import_fast_refresh and p.options.features.react_fast_refresh) { - p.resolveGeneratedSymbol(&p.jsx_refresh_runtime); - p.recordUsage(p.jsx_refresh_runtime.ref); + const import_record_id = p.addImportRecord(.require, loc, p.options.jsx.refresh_runtime); + p.import_records.items[import_record_id].tag = .react_refresh; + jsx_part_stmts[stmt_i] = p.s(S.Import{ + .namespace_ref = p.jsx_refresh_runtime.ref, + .star_name_loc = loc, + .is_single_line = true, + .import_record_index = import_record_id, + }, loc); + + stmt_i += 1; + p.named_imports.put( + p.jsx_refresh_runtime.ref, + js_ast.NamedImport{ + .alias = refresh_runtime_symbol.original_name, + .alias_is_star = true, + .alias_loc = loc, + .namespace_ref = p.jsx_refresh_runtime.ref, + .import_record_index = import_record_id, + }, + ) catch unreachable; + p.is_import_item.put(p.allocator, p.jsx_refresh_runtime.ref, .{}) catch unreachable; + import_records[import_record_i] = import_record_id; + } + p.recordUsage(p.jsx_refresh_runtime.ref); + } - if (!p.options.jsx.use_embedded_refresh_runtime) { - if (comptime Environment.allow_assert) - assert(!p.options.enable_bundling); - var declared_symbols = try p.allocator.alloc(js_ast.DeclaredSymbol, 1); - const loc = logger.Loc.Empty; - const import_record_id = p.addImportRecord(.require, loc, p.options.jsx.refresh_runtime); - p.import_records.items[import_record_id].tag = .react_refresh; - - var import_stmt = p.s(S.Import{ - .namespace_ref = p.jsx_refresh_runtime.ref, - .star_name_loc = loc, - .is_single_line = true, - .import_record_index = import_record_id, - }, loc); + jsx_part_stmts[stmt_i] = p.s(S.Local{ .kind = .k_var, .decls = decls[0..decl_i] }, loc); + stmt_i += 1; - const refresh_runtime_symbol: *const Symbol = &p.symbols.items[p.jsx_refresh_runtime.ref.innerIndex()]; + before.append(js_ast.Part{ + .stmts = jsx_part_stmts[0..stmt_i], + .declared_symbols = declared_symbols, + .import_record_indices = import_records, + .tag = .jsx_import, + }) catch unreachable; + } + } - p.named_imports.put( - p.jsx_refresh_runtime.ref, - js_ast.NamedImport{ - .alias = refresh_runtime_symbol.original_name, - .alias_is_star = true, - .alias_loc = loc, + if (!did_import_fast_refresh and p.options.features.react_fast_refresh) { + p.resolveGeneratedSymbol(&p.jsx_refresh_runtime); + p.recordUsage(p.jsx_refresh_runtime.ref); + + if (!p.options.jsx.use_embedded_refresh_runtime) { + if (comptime Environment.allow_assert) + assert(!p.options.enable_bundling); + var declared_symbols = try p.allocator.alloc(js_ast.DeclaredSymbol, 1); + const loc = logger.Loc.Empty; + const import_record_id = p.addImportRecord(.require, loc, p.options.jsx.refresh_runtime); + p.import_records.items[import_record_id].tag = .react_refresh; + + var import_stmt = p.s(S.Import{ .namespace_ref = p.jsx_refresh_runtime.ref, + .star_name_loc = loc, + .is_single_line = true, .import_record_index = import_record_id, - }, - ) catch unreachable; - p.is_import_item.put(p.allocator, p.jsx_refresh_runtime.ref, .{}) catch unreachable; - var import_records = try p.allocator.alloc(@TypeOf(import_record_id), 1); - import_records[0] = import_record_id; - declared_symbols[0] = .{ .ref = p.jsx_refresh_runtime.ref, .is_top_level = true }; - var part_stmts = try p.allocator.alloc(Stmt, 1); - part_stmts[0] = import_stmt; + }, loc); - before.append(js_ast.Part{ - .stmts = part_stmts, - .declared_symbols = declared_symbols, - .import_record_indices = import_records, - .tag = .react_fast_refresh, - }) catch unreachable; + const refresh_runtime_symbol: *const Symbol = &p.symbols.items[p.jsx_refresh_runtime.ref.innerIndex()]; + + p.named_imports.put( + p.jsx_refresh_runtime.ref, + js_ast.NamedImport{ + .alias = refresh_runtime_symbol.original_name, + .alias_is_star = true, + .alias_loc = loc, + .namespace_ref = p.jsx_refresh_runtime.ref, + .import_record_index = import_record_id, + }, + ) catch unreachable; + p.is_import_item.put(p.allocator, p.jsx_refresh_runtime.ref, .{}) catch unreachable; + var import_records = try p.allocator.alloc(@TypeOf(import_record_id), 1); + import_records[0] = import_record_id; + declared_symbols[0] = .{ .ref = p.jsx_refresh_runtime.ref, .is_top_level = true }; + var part_stmts = try p.allocator.alloc(Stmt, 1); + part_stmts[0] = import_stmt; + + before.append(js_ast.Part{ + .stmts = part_stmts, + .declared_symbols = declared_symbols, + .import_record_indices = import_records, + .tag = .react_fast_refresh, + }) catch unreachable; + } } - } - } else if (comptime ParserType.jsx_transform_type == .solid) { - p.resolveGeneratedSymbol(&p.solid.wrap); - p.resolveGeneratedSymbol(&p.solid.insert); - p.resolveGeneratedSymbol(&p.solid.template); - p.resolveGeneratedSymbol(&p.solid.delegateEvents); - p.resolveGeneratedSymbol(&p.solid.createComponent); - p.resolveGeneratedSymbol(&p.solid.setAttribute); - p.resolveGeneratedSymbol(&p.solid.effect); - p.resolveGeneratedSymbol(&p.solid.namespace); - - const import_count = - @as(usize, @boolToInt(p.symbols.items[p.solid.wrap.ref.innerIndex()].use_count_estimate > 0)) + - @as(usize, @boolToInt(p.symbols.items[p.solid.insert.ref.innerIndex()].use_count_estimate > 0)) + - @as(usize, @boolToInt(p.symbols.items[p.solid.template.ref.innerIndex()].use_count_estimate > 0)) + - @as(usize, @boolToInt(p.symbols.items[p.solid.delegateEvents.ref.innerIndex()].use_count_estimate > 0)) + - @as(usize, @boolToInt(p.symbols.items[p.solid.createComponent.ref.innerIndex()].use_count_estimate > 0)) + - @as(usize, @boolToInt(p.symbols.items[p.solid.setAttribute.ref.innerIndex()].use_count_estimate > 0)) + - @as(usize, @boolToInt(p.symbols.items[p.solid.effect.ref.innerIndex()].use_count_estimate > 0)); - var import_items = try p.allocator.alloc(js_ast.ClauseItem, import_count); - - // 1. Inject the part containing template declarations and Solid's import statement - var stmts_to_inject = p.allocator.alloc(Stmt, @as(usize, @boolToInt(p.solid.template_decls.items.len > 0)) + @as(usize, @boolToInt(import_count > 0))) catch unreachable; - var j: usize = 0; - const order = .{ - "createComponent", - "delegateEvents", - "effect", - "insert", - "setAttribute", - "template", - "wrap", - }; + }, + .solid => { + p.resolveGeneratedSymbol(&p.solid.wrap); + p.resolveGeneratedSymbol(&p.solid.insert); + p.resolveGeneratedSymbol(&p.solid.template); + p.resolveGeneratedSymbol(&p.solid.delegateEvents); + p.resolveGeneratedSymbol(&p.solid.createComponent); + p.resolveGeneratedSymbol(&p.solid.setAttribute); + p.resolveGeneratedSymbol(&p.solid.effect); + p.resolveGeneratedSymbol(&p.solid.namespace); + + const import_count = + @as(usize, @boolToInt(p.symbols.items[p.solid.wrap.ref.innerIndex()].use_count_estimate > 0)) + + @as(usize, @boolToInt(p.symbols.items[p.solid.insert.ref.innerIndex()].use_count_estimate > 0)) + + @as(usize, @boolToInt(p.symbols.items[p.solid.template.ref.innerIndex()].use_count_estimate > 0)) + + @as(usize, @boolToInt(p.symbols.items[p.solid.delegateEvents.ref.innerIndex()].use_count_estimate > 0)) + + @as(usize, @boolToInt(p.symbols.items[p.solid.createComponent.ref.innerIndex()].use_count_estimate > 0)) + + @as(usize, @boolToInt(p.symbols.items[p.solid.setAttribute.ref.innerIndex()].use_count_estimate > 0)) + + @as(usize, @boolToInt(p.symbols.items[p.solid.effect.ref.innerIndex()].use_count_estimate > 0)); + var import_items = try p.allocator.alloc(js_ast.ClauseItem, import_count); + + // 1. Inject the part containing template declarations and Solid's import statement + var stmts_to_inject = p.allocator.alloc(Stmt, @as(usize, @boolToInt(p.solid.template_decls.items.len > 0)) + @as(usize, @boolToInt(import_count > 0 and p.options.features.auto_import_jsx))) catch unreachable; + var j: usize = 0; + const order = .{ + "createComponent", + "delegateEvents", + "effect", + "insert", + "setAttribute", + "template", + "wrap", + }; - try p.named_imports.ensureUnusedCapacity(import_count); - try p.is_import_item.ensureUnusedCapacity(p.allocator, @intCast(u32, import_count)); - - if (import_count > 0) { - const import_record_id = p.addImportRecord(.stmt, logger.Loc.Empty, p.options.jsx.import_source); - var declared_symbols = p.allocator.alloc(js_ast.DeclaredSymbol, p.solid.template_decls.items.len) catch unreachable; - - inline for (order) |field_name| { - const ref = @field(p.solid, field_name).ref; - if (p.symbols.items[ref.innerIndex()].use_count_estimate > 0) { - import_items[j] = js_ast.ClauseItem{ - .alias = field_name, - .name = .{ .loc = logger.Loc.Empty, .ref = ref }, - .alias_loc = logger.Loc.Empty, - .original_name = "", - }; + var stmts_remain = stmts_to_inject; + + if (stmts_to_inject.len > 0) { + var declared_symbols = p.allocator.alloc(js_ast.DeclaredSymbol, p.solid.template_decls.items.len) catch unreachable; + var import_record_ids: []u32 = &[_]u32{}; + + if (p.options.features.auto_import_jsx) { + try p.named_imports.ensureUnusedCapacity(import_count); + try p.is_import_item.ensureUnusedCapacity(p.allocator, @intCast(u32, import_count)); + const import_record_id = p.addImportRecord(.stmt, logger.Loc.Empty, p.options.jsx.import_source); + + inline for (order) |field_name| { + const ref = @field(p.solid, field_name).ref; + if (p.symbols.items[ref.innerIndex()].use_count_estimate > 0) { + import_items[j] = js_ast.ClauseItem{ + .alias = field_name, + .name = .{ .loc = logger.Loc.Empty, .ref = ref }, + .alias_loc = logger.Loc.Empty, + .original_name = "", + }; - p.named_imports.putAssumeCapacity( - ref, - js_ast.NamedImport{ - .alias = p.symbols.items[ref.innerIndex()].original_name, - .alias_is_star = false, - .alias_loc = logger.Loc.Empty, + p.named_imports.putAssumeCapacity( + ref, + js_ast.NamedImport{ + .alias = p.symbols.items[ref.innerIndex()].original_name, + .alias_is_star = false, + .alias_loc = logger.Loc.Empty, + .namespace_ref = p.solid.namespace.ref, + .import_record_index = import_record_id, + }, + ); + p.is_import_item.putAssumeCapacity(ref, .{}); + j += 1; + } + } + + p.import_records.items[import_record_id].tag = .jsx_import; + stmts_remain[0] = p.s( + S.Import{ .namespace_ref = p.solid.namespace.ref, + .star_name_loc = null, + .is_single_line = true, .import_record_index = import_record_id, + .items = import_items, }, + logger.Loc.Empty, ); - p.is_import_item.putAssumeCapacity(ref, .{}); - j += 1; + stmts_remain = stmts_remain[1..]; + import_record_ids = p.allocator.alloc(u32, 1) catch unreachable; + import_record_ids[0] = import_record_id; } - } - p.import_records.items[import_record_id].tag = .jsx_import; - stmts_to_inject[0] = p.s( - S.Import{ - .namespace_ref = p.solid.namespace.ref, - .star_name_loc = null, - .is_single_line = true, - .import_record_index = import_record_id, - .items = import_items, - }, - logger.Loc.Empty, - ); - if (p.solid.template_decls.items.len > 0) { - for (p.solid.template_decls.items) |_, i| { - declared_symbols[i] = js_ast.DeclaredSymbol{ - .ref = p.solid.template_decls.items[i].binding.data.b_identifier.ref, - .is_top_level = true, - }; + if (p.solid.template_decls.items.len > 0) { + for (p.solid.template_decls.items) |_, i| { + declared_symbols[i] = js_ast.DeclaredSymbol{ + .ref = p.solid.template_decls.items[i].binding.data.b_identifier.ref, + .is_top_level = true, + }; + } + stmts_remain[0] = p.s( + S.Local{ + .decls = p.solid.template_decls.items, + }, + logger.Loc.Empty, + ); } - stmts_to_inject[1] = p.s( - S.Local{ - .decls = p.solid.template_decls.items, - }, - logger.Loc.Empty, - ); + + before.append(js_ast.Part{ + .stmts = stmts_to_inject, + .declared_symbols = declared_symbols, + .import_record_indices = import_record_ids, + .tag = .jsx_import, + }) catch unreachable; } - var import_record_ids = p.allocator.alloc(u32, 1) catch unreachable; - import_record_ids[0] = import_record_id; - - before.append(js_ast.Part{ - .stmts = stmts_to_inject, - .declared_symbols = declared_symbols, - .import_record_indices = import_record_ids, - .tag = .jsx_import, - }) catch unreachable; - } + }, + else => {}, } if (p.options.enable_bundling) p.resolveBundlingSymbols(); @@ -3325,6 +3336,8 @@ const SolidJS = struct { template_decls: std.ArrayListUnmanaged(G.Decl) = .{}, is_in_jsx_component: bool = false, + stack: Stack = .{}, + pub const Stack = struct { component_body: std.ArrayListUnmanaged(Stmt) = .{}, component_body_decls: std.ArrayListUnmanaged(G.Decl) = .{}, @@ -3347,10 +3360,10 @@ const SolidJS = struct { }; pub fn generateElementName(this: *SolidJS, allocator: std.mem.Allocator) string { - if (this.component_body_decls.items.len <= prefilled_element_names.len) { - return prefilled_element_names[this.component_body_decls.items.len]; + if (this.stack.component_body_decls.items.len <= prefilled_element_names.len) { + return prefilled_element_names[this.stack.component_body_decls.items.len]; } - return std.fmt.allocPrint(allocator, "_el${d}", .{this.component_body_decls.items.len}) catch unreachable; + return std.fmt.allocPrint(allocator, "_el${d}", .{this.stack.component_body_decls.items.len}) catch unreachable; } pub fn generateTemplateName(this: *SolidJS, allocator: std.mem.Allocator) string { @@ -3364,12 +3377,14 @@ const SolidJS = struct { var name = solid.generateElementName(p.allocator); var prev_scope = p.current_scope; - p.current_scope = &solid.temporary_scope; + p.current_scope = &solid.stack.temporary_scope; const ref = p.declareSymbolMaybeGenerated(.import, value_loc, name, true) catch unreachable; p.current_scope = prev_scope; const element = .{ .ref = ref }; var decl_value: Expr = undefined; - switch (solid.component_body_decls.items.len) { + var decls = &solid.stack.component_body_decls; + + switch (decls.items.len) { 0 => { decl_value = p.e( E.Call{ @@ -3391,7 +3406,7 @@ const SolidJS = struct { p.recordUsage(template_expression.data.e_identifier.ref); }, 1 => { - const ident = E.Identifier{ .ref = solid.component_body_decls.items[solid.component_body_decls.items.len - 1].binding.data.b_identifier.ref }; + const ident = E.Identifier{ .ref = decls.items[decls.items.len - 1].binding.data.b_identifier.ref }; decl_value = p.e( E.Dot{ .target = .{ @@ -3408,7 +3423,7 @@ const SolidJS = struct { p.recordUsage(ident.ref); }, else => { - const ident = E.Identifier{ .ref = solid.component_body_decls.items[solid.component_body_decls.items.len - 1].binding.data.b_identifier.ref }; + const ident = E.Identifier{ .ref = decls.items[decls.items.len - 1].binding.data.b_identifier.ref }; decl_value = p.e(E.Dot{ .target = .{ .data = .{ .e_identifier = ident }, @@ -3422,7 +3437,7 @@ const SolidJS = struct { p.recordUsage(ident.ref); }, } - try solid.component_body_decls.append( + try decls.append( p.allocator, G.Decl{ .binding = p.b(B.Identifier{ .ref = ref }, template_expression.loc), .value = decl_value }, ); @@ -4782,8 +4797,8 @@ fn NewParser_( p.solid.createComponent = p.declareGeneratedSymbol(.other, "createComponent") catch unreachable; p.solid.setAttribute = p.declareGeneratedSymbol(.other, "setAttribute") catch unreachable; p.solid.effect = p.declareGeneratedSymbol(.other, "effect") catch unreachable; - p.solid.current_template_string = MutableString.initEmpty(p.allocator); - p.solid.buffered_writer = p.solid.current_template_string.bufferedWriter(); + p.solid.stack.current_template_string = MutableString.initEmpty(p.allocator); + p.solid.stack.buffered_writer = p.solid.stack.current_template_string.bufferedWriter(); }, .macro => { p.bun_jsx_ref = p.declareSymbol(.other, logger.Loc.Empty, "bunJSX") catch unreachable; @@ -12635,11 +12650,14 @@ fn NewParser_( // insert(topElement, createComponent(MyComponent, props), markerElement) // 5. Non-statically analyzable attributes are added like this: // setAttribute(topElement, "data-foo", "bar") - // 6. - var solid = &p.solid; - const old_is_in_jsx_component = solid.is_in_jsx_component; - solid.is_in_jsx_component = true; - defer solid.is_in_jsx_component = old_is_in_jsx_component; + var global_solid = &p.solid; + var symbols = global_solid; + + var solid = &global_solid.stack; + + const old_is_in_jsx_component = global_solid.is_in_jsx_component; + global_solid.is_in_jsx_component = true; + defer global_solid.is_in_jsx_component = old_is_in_jsx_component; if (!old_is_in_jsx_component) { solid.current_template_string.reset(); @@ -12751,8 +12769,9 @@ fn NewParser_( } } else { if (template_expression.data.e_identifier.ref.isNull()) { - var new_template_name = solid.generateTemplateName(p.allocator); + var new_template_name = global_solid.generateTemplateName(p.allocator); // declare the template in the module scope + solid.prev_scope = p.current_scope; p.current_scope = p.module_scope; solid.last_template_id = .{ .ref = p.declareSymbolMaybeGenerated(.other, expr.loc, new_template_name, true) catch unreachable, @@ -12763,7 +12782,7 @@ fn NewParser_( template_expression = .{ .loc = expr.loc, .data = .{ .e_identifier = solid.last_template_id } }; } if (element == null) { - element = solid.generateElement( + element = global_solid.generateElement( p, template_expression, property.value.?.loc, @@ -12787,7 +12806,7 @@ fn NewParser_( E.Call{ .target = p.e( E.Identifier{ - .ref = solid.setAttribute.ref, + .ref = symbols.setAttribute.ref, .can_be_removed_if_unused = false, .call_can_be_unwrapped_if_unused = false, }, @@ -12798,7 +12817,7 @@ fn NewParser_( property.key.?.loc, ); - p.recordUsage(solid.setAttribute.ref); + p.recordUsage(symbols.setAttribute.ref); if (args[2].data == .e_identifier or args[2].data == .e_import_identifier) { if (args[2].data == .e_identifier) p.recordUsage(args[2].data.e_identifier.ref); if (args[2].data == .e_import_identifier) p.recordUsage(args[2].data.e_import_identifier.ref); @@ -12822,11 +12841,13 @@ fn NewParser_( E.Call{ .target = p.e( E.Identifier{ - .ref = solid.effect.ref, + .ref = symbols.effect.ref, }, + property.value.?.loc, ), .args = ExprNodeList.init(args[3..4]), }, + property.value.?.loc, ), }, property.value.?.loc); } @@ -12911,7 +12932,7 @@ fn NewParser_( else => { if (template_expression.data.e_identifier.ref.isNull()) { - var new_template_name = solid.generateTemplateName(p.allocator); + var new_template_name = global_solid.generateTemplateName(p.allocator); // declare the template in the module scope p.current_scope = p.module_scope; solid.last_template_id = .{ @@ -12922,15 +12943,17 @@ fn NewParser_( p.current_scope = solid.prev_scope.?; template_expression = .{ .loc = expr.loc, .data = .{ .e_identifier = solid.last_template_id } }; } - p.recordUsage(solid.insert.ref); + p.recordUsage(symbols.insert.ref); p.recordUsage(template_expression.data.e_identifier.ref); var args = p.allocator.alloc(Expr, 3) catch unreachable; - args[0] = template_expression; - args[1] = child; - args[2] = if (k != children.len - 1 and !solid.last_element_id.ref.eql(Ref.None)) - p.e(solid.last_element_id, expr.loc) - else - p.e(E.Null{}, expr.loc); + args[0..3].* = .{ + template_expression, + child, + if (k != children.len - 1 and !solid.last_element_id.ref.eql(Ref.None)) + p.e(solid.last_element_id, expr.loc) + else + p.e(E.Null{}, expr.loc), + }; solid.node_count += 1; solid.component_body.append( p.allocator, @@ -12938,7 +12961,7 @@ fn NewParser_( S.SExpr{ .value = p.e( E.Call{ - .target = p.e(E.ImportIdentifier{ .ref = solid.insert.ref }, child.loc), + .target = p.e(E.ImportIdentifier{ .ref = symbols.insert.ref }, child.loc), .args = ExprNodeList.init(args), }, child.loc, @@ -12967,6 +12990,11 @@ fn NewParser_( // ^ // we are here! if (!old_is_in_jsx_component) { + if (p.is_control_flow_dead) { + solid.node_count = 0; + return p.e(E.Missing{}, expr.loc); + } + var args = p.allocator.alloc(Expr, 2) catch unreachable; // we are done, so it's time to turn our template into a string we can write @@ -12987,7 +13015,7 @@ fn NewParser_( solid.node_count = 0; if (template_expression.data.e_identifier.ref.isNull()) { - var new_template_name = solid.generateTemplateName(p.allocator); + var new_template_name = global_solid.generateTemplateName(p.allocator); // declare the template in the module scope p.current_scope = p.module_scope; solid.last_template_id = .{ @@ -12999,7 +13027,7 @@ fn NewParser_( template_expression = .{ .loc = expr.loc, .data = .{ .e_identifier = solid.last_template_id } }; } - solid.template_decls.append( + global_solid.template_decls.append( p.allocator, G.Decl{ .binding = p.b(B.Identifier{ .ref = template_expression.data.e_identifier.ref }, template_expression.loc), @@ -13008,7 +13036,7 @@ fn NewParser_( .args = ExprNodeList.init(args), .target = p.e( E.ImportIdentifier{ - .ref = solid.template.ref, + .ref = symbols.template.ref, }, expr.loc, ), @@ -13018,11 +13046,7 @@ fn NewParser_( ), }, ) catch unreachable; - p.recordUsage(solid.template.ref); - - if (p.is_control_flow_dead) { - return p.e(E.Missing{}, expr.loc); - } + p.recordUsage(symbols.template.ref); // 1 means it was actually static // that means we can just turn it into a single $template.cloneNode(true) @@ -13141,10 +13165,10 @@ fn NewParser_( args[1] = p.e(E.Object{ .properties = G.Property.List.init(out_props[0..out_props_i]), }, expr.loc); - p.recordUsage(solid.createComponent.ref); + p.recordUsage(symbols.createComponent.ref); return p.e( E.Call{ - .target = p.e(E.ImportIdentifier{ .ref = solid.createComponent.ref }, expr.loc), + .target = p.e(E.ImportIdentifier{ .ref = symbols.createComponent.ref }, expr.loc), .args = ExprNodeList.init(args), .close_paren_loc = e_.close_tag_loc, }, |