aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/js_ast.zig21
-rw-r--r--src/js_parser.zig928
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,
},