aboutsummaryrefslogtreecommitdiff
path: root/src/js_parser.zig
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-12-09 16:41:38 -0800
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-12-09 16:41:38 -0800
commit88538b7c2c68fe506d0a20a8f5b78e47c6c60299 (patch)
treee27cae0caf7a42ff82177d38911693fcd3720ce8 /src/js_parser.zig
parent79138c4c7cb72a5f84c9a81720a73d283d78b1be (diff)
downloadbun-88538b7c2c68fe506d0a20a8f5b78e47c6c60299.tar.gz
bun-88538b7c2c68fe506d0a20a8f5b78e47c6c60299.tar.zst
bun-88538b7c2c68fe506d0a20a8f5b78e47c6c60299.zip
Deprecate very incomplete Solid.js JSX transform
We don't have time to do a good job of this and Bun.plugin makes it possible to use Solid with Bun
Diffstat (limited to 'src/js_parser.zig')
-rw-r--r--src/js_parser.zig1138
1 files changed, 5 insertions, 1133 deletions
diff --git a/src/js_parser.zig b/src/js_parser.zig
index 5a58ba305..b69951377 100644
--- a/src/js_parser.zig
+++ b/src/js_parser.zig
@@ -1030,7 +1030,6 @@ const StaticSymbolName = struct {
pub const setAttribute = NewStaticSymbol("setAttribute");
pub const effect = NewStaticSymbol("effect");
pub const delegateEvents = NewStaticSymbol("delegateEvents");
- pub const Solid = NewStaticSymbol("Solid");
pub const __merge = NewStaticSymbol("__merge");
};
@@ -2323,11 +2322,11 @@ pub const Parser = struct {
if (!self.options.ts and self.options.features.is_macro_runtime) return try self._parse(JSParserMacro);
if (self.options.ts and self.options.jsx.parse) {
- return if (self.options.jsx.runtime != .solid) try self._parse(TSXParser) else try self._parse(SolidTSXParser);
+ return try self._parse(TSXParser);
} else if (self.options.ts) {
return try self._parse(TypeScriptParser);
} else if (self.options.jsx.parse) {
- return if (self.options.jsx.runtime != .solid) try self._parse(JSXParser) else try self._parse(SolidJSXParser);
+ return try self._parse(JSXParser);
} else {
return try self._parse(JavaScriptParser);
}
@@ -3069,114 +3068,6 @@ pub const Parser = struct {
}
}
},
- .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.count() > 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",
- };
-
- 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.count()) 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,
- .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,
- );
- stmts_remain = stmts_remain[1..];
- import_record_ids = p.allocator.alloc(u32, 1) catch unreachable;
- import_record_ids[0] = import_record_id;
- }
-
- if (p.solid.template_decls.count() > 0) {
- for (p.solid.template_decls.values()) |val, i| {
- declared_symbols[i] = js_ast.DeclaredSymbol{
- .ref = val.binding.data.b_identifier.ref,
- .is_top_level = true,
- };
- }
- stmts_remain[0] = p.s(
- S.Local{
- .decls = p.solid.template_decls.values(),
- },
- 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;
- }
- },
else => {},
}
@@ -3505,340 +3396,8 @@ const JSXTransformType = enum {
none,
react,
macro,
- solid,
-};
-
-const SolidJS = struct {
- namespace: GeneratedSymbol = undefined,
- wrap: GeneratedSymbol = undefined,
- insert: GeneratedSymbol = undefined,
- template: GeneratedSymbol = undefined,
- delegateEvents: GeneratedSymbol = undefined,
- createComponent: GeneratedSymbol = undefined,
- setAttribute: GeneratedSymbol = undefined,
- effect: GeneratedSymbol = undefined,
-
- events_to_delegate: Event.Bitset = .{},
- template_decls: std.ArrayHashMapUnmanaged(u32, G.Decl, bun.ArrayIdentityContext, false) = .{},
- is_in_jsx_component: bool = false,
-
- stack: Stack = .{},
-
- pub const ExpressionTransform = union(enum) {
- class: void,
- nativeEvent: void,
- nativeEventCaptured: void,
- style: void,
- setAttribute: void,
- event: Event,
-
- pub fn which(key: []const u8) ExpressionTransform {
- const len = key.len;
- if (len < 3)
- return .{ .setAttribute = {} };
-
- if (strings.hasPrefixComptime(key, "on:")) {
- return .{ .nativeEvent = {} };
- }
-
- if (strings.hasPrefixComptime(key, "oncapture:")) {
- return .{ .nativeEventCaptured = {} };
- }
-
- if (Event.map.get(key)) |event| {
- return .{ .event = event };
- }
-
- switch (key.len) {
- "class".len => {
- if (strings.eqlComptime(key, "class"))
- return .{ .class = {} };
-
- if (strings.eqlComptime(key, "style"))
- return .{ .style = {} };
-
- return .{ .setAttribute = {} };
- },
- "className".len => {
- if (strings.eqlComptime(key, "className"))
- return .{ .class = {} };
- return .{ .setAttribute = {} };
- },
- else => return .{ .setAttribute = {} },
- }
- }
- };
-
- pub const Stack = struct {
- component_body: std.ArrayListUnmanaged(Stmt) = .{},
- component_body_decls: std.ArrayListUnmanaged(G.Decl) = .{},
- last_template_id: E.Identifier = .{},
- last_element_id: E.Identifier = .{},
- temporary_scope: Scope = Scope{
- .kind = .function_body,
- .parent = null,
- },
- prev_scope: ?*Scope = null,
- node_count: u32 = 0,
-
- current_template_string: MutableString = .{
- .allocator = undefined,
- .list = .{},
- },
- buffered_writer: MutableString.BufferedWriter = undefined,
-
- element_counter: u32 = 0,
- };
-
- pub fn generateElementName(this: *SolidJS, allocator: std.mem.Allocator) string {
- 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.stack.component_body_decls.items.len}) catch unreachable;
- }
-
- pub fn generateTemplateName(this: *SolidJS, allocator: std.mem.Allocator) string {
- if (this.template_decls.count() <= prefilled_template_names.len) {
- return prefilled_template_names[this.template_decls.count()];
- }
- return std.fmt.allocPrint(allocator, "_tmpl${d}", .{this.template_decls.count()}) catch unreachable;
- }
-
- pub fn generateElement(solid: *SolidJS, p: anytype, template_expression: Expr, value_loc: logger.Loc) !E.Identifier {
- var name = solid.generateElementName(p.allocator);
-
- var prev_scope = p.current_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;
- var decls = &solid.stack.component_body_decls;
-
- switch (decls.items.len) {
- 0 => {
- decl_value = p.e(
- E.Call{
- .target = p.e(
- E.Dot{
- .name = "cloneNode",
- .name_loc = value_loc,
- .target = template_expression,
- .can_be_removed_if_unused = true,
- .call_can_be_unwrapped_if_unused = true,
- },
- template_expression.loc,
- ),
- .args = ExprNodeList.init(true_args),
- .can_be_unwrapped_if_unused = true,
- },
- value_loc,
- );
- p.recordUsage(template_expression.data.e_identifier.ref);
- },
- 1 => {
- 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 },
- .loc = value_loc,
- },
- .name = "firstChild",
- .name_loc = template_expression.loc,
- .can_be_removed_if_unused = true,
- .call_can_be_unwrapped_if_unused = true,
- },
- value_loc,
- );
- p.recordUsage(ident.ref);
- },
- else => {
- 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 },
- .loc = value_loc,
- },
- .name_loc = template_expression.loc,
- .name = "nextSibling",
- .can_be_removed_if_unused = true,
- .call_can_be_unwrapped_if_unused = true,
- }, value_loc);
- p.recordUsage(ident.ref);
- },
- }
- try decls.append(
- p.allocator,
- G.Decl{ .binding = p.b(B.Identifier{ .ref = ref }, template_expression.loc), .value = decl_value },
- );
- return element;
- }
-
- pub const Event = enum {
- beforeinput,
- click,
- dblclick,
- contextmenu,
- focusin,
- focusout,
- input,
- keydown,
- keyup,
- mousedown,
- mousemove,
- mouseout,
- mouseover,
- mouseup,
- pointerdown,
- pointermove,
- pointerout,
- pointerover,
- pointerup,
- touchend,
- touchmove,
- touchstart,
-
- pub const setter_names = std.enums.EnumArray(Event, string).init(
- .{
- .beforeinput = "$$beforeinput",
- .click = "$$click",
- .dblclick = "$$dblclick",
- .contextmenu = "$$contextmenu",
- .focusin = "$$focusin",
- .focusout = "$$focusout",
- .input = "$$input",
- .keydown = "$$keydown",
- .keyup = "$$keyup",
- .mousedown = "$$mousedown",
- .mousemove = "$$mousemove",
- .mouseout = "$$mouseout",
- .mouseover = "$$mouseover",
- .mouseup = "$$mouseup",
- .pointerdown = "$$pointerdown",
- .pointermove = "$$pointermove",
- .pointerout = "$$pointerout",
- .pointerover = "$$pointerover",
- .pointerup = "$$pointerup",
- .touchend = "$$touchend",
- .touchmove = "$$touchmove",
- .touchstart = "$$touchstart",
- },
- );
-
- pub inline fn setter(this: Event) string {
- return setter_names.get(this);
- }
-
- pub const map = ComptimeStringMap(
- Event,
- .{
- .{ "onbeforeinput", Event.beforeinput },
- .{ "onclick", Event.click },
- .{ "ondblclick", Event.dblclick },
- .{ "oncontextmenu", Event.contextmenu },
- .{ "onfocusin", Event.focusin },
- .{ "onfocusout", Event.focusout },
- .{ "oninput", Event.input },
- .{ "onkeydown", Event.keydown },
- .{ "onkeyup", Event.keyup },
- .{ "onmousedown", Event.mousedown },
- .{ "onmousemove", Event.mousemove },
- .{ "onmouseout", Event.mouseout },
- .{ "onmouseover", Event.mouseover },
- .{ "onmouseup", Event.mouseup },
- .{ "onpointerdown", Event.pointerdown },
- .{ "onpointermove", Event.pointermove },
- .{ "onpointerout", Event.pointerout },
- .{ "onpointerover", Event.pointerover },
- .{ "onpointerup", Event.pointerup },
- .{ "ontouchend", Event.touchend },
- .{ "ontouchmove", Event.touchmove },
- .{ "ontouchstart", Event.touchstart },
- .{ "onbeforeinput", Event.beforeinput },
- .{ "onClick", Event.click },
- .{ "onDblclick", Event.dblclick },
- .{ "onContextMenu", Event.contextmenu },
- .{ "onFocusIn", Event.focusin },
- .{ "onFocusOut", Event.focusout },
- .{ "onInput", Event.input },
- .{ "onKeydown", Event.keydown },
- .{ "onKeyup", Event.keyup },
- .{ "onMouseDown", Event.mousedown },
- .{ "onMouseMove", Event.mousemove },
- .{ "onMouseOut", Event.mouseout },
- .{ "onMouseOver", Event.mouseover },
- .{ "onMouseUp", Event.mouseup },
- .{ "onPointerDown", Event.pointerdown },
- .{ "onPointerMove", Event.pointermove },
- .{ "onPointerOut", Event.pointerout },
- .{ "onPointerOver", Event.pointerover },
- .{ "onPointerUp", Event.pointerup },
- .{ "onTouchEnd", Event.touchend },
- .{ "onTouchMove", Event.touchmove },
- .{ "onTouchStart", Event.touchstart },
- },
- );
-
- pub const Bitset = std.enums.EnumSet(Event);
- };
-
- const prefilled_element_names = [_]string{
- "_el",
- "_el$1",
- "_el$2",
- "_el$3",
- "_el$4",
- "_el$5",
- "_el$6",
- "_el$7",
- "_el$8",
- "_el$9",
- "_el$10",
- "_el$11",
- "_el$12",
- "_el$13",
- "_el$14",
- "_el$15",
- "_el$16",
- "_el$17",
- "_el$18",
- "_el$19",
- "_el$20",
- "_el$21",
- };
- const prefilled_template_names = [_]string{
- "_tmpl",
- "_tmpl$1",
- "_tmpl$2",
- "_tmpl$3",
- "_tmpl$4",
- "_tmpl$5",
- "_tmpl$6",
- "_tmpl$7",
- "_tmpl$8",
- "_tmpl$9",
- "_tmpl$10",
- "_tmpl$11",
- "_tmpl$12",
- "_tmpl$13",
- "_tmpl$14",
- "_tmpl$15",
- "_tmpl$16",
- "_tmpl$17",
- "_tmpl$18",
- "_tmpl$19",
- "_tmpl$20",
- "_tmpl$21",
- };
};
-fn GetSolidJSSymbols(comptime jsx: JSXTransformType) type {
- if (jsx != .solid)
- return void;
-
- return SolidJS;
-}
const ParserFeatures = struct {
typescript: bool = false,
jsx: JSXTransformType = JSXTransformType.none,
@@ -4052,8 +3611,6 @@ fn NewParser_(
// only applicable when is_react_fast_refresh_enabled
jsx_refresh_runtime: GeneratedSymbol = GeneratedSymbol{ .ref = Ref.None, .primary = Ref.None, .backup = Ref.None },
- solid: GetSolidJSSymbols(jsx_transform_type) = if (jsx_transform_type == JSXTransformType.solid) SolidJS{} else void{},
-
bun_jsx_ref: Ref = Ref.None,
// Imports (both ES6 and CommonJS) are tracked at the top level
@@ -5053,18 +4610,7 @@ fn NewParser_(
p.jsx_automatic = p.declareGeneratedSymbol(.other, "ImportSource") catch unreachable;
}
},
- .solid => {
- p.solid.insert = p.declareGeneratedSymbol(.other, "insert") catch unreachable;
- p.solid.template = p.declareGeneratedSymbol(.other, "template") catch unreachable;
- p.solid.wrap = p.declareGeneratedSymbol(.other, "wrap") catch unreachable;
- p.solid.namespace = p.declareGeneratedSymbol(.other, "Solid") catch unreachable;
- p.solid.delegateEvents = p.declareGeneratedSymbol(.other, "delegateEvents") catch unreachable;
- 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.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;
BunJSX.bun_jsx_identifier = E.Identifier{
@@ -12315,14 +11861,6 @@ fn NewParser_(
value = p.e(E.Boolean{ .value = true }, logger.Loc{ .start = key_range.loc.start + key_range.len });
} else {
value = try p.parseJSXPropValueIdentifier(&previous_string_with_backslash_loc);
- if (comptime jsx_transform_type == .solid) {
- switch (value.knownPrimitive()) {
- .unknown => {
- flags.insert(.has_any_dynamic);
- },
- else => {},
- }
- }
}
try props.append(G.Property{ .key = prop_name, .value = value });
@@ -12374,15 +11912,6 @@ fn NewParser_(
return error.SyntaxError;
};
- if (comptime jsx_transform_type == .solid) {
- switch (expr.knownPrimitive()) {
- .unknown => {
- flags.insert(.has_any_dynamic);
- },
- else => {},
- }
- }
-
try props.append(G.Property{ .value = expr, .key = key, .kind = .normal });
},
// This implements
@@ -12483,18 +12012,7 @@ fn NewParser_(
// The expression is optional, and may be absent
if (p.lexer.token != .t_close_brace) {
- if (comptime jsx_transform_type == .solid) {
- const child = try p.parseExpr(.lowest);
- switch (child.knownPrimitive()) {
- .unknown => {
- flags.insert(.has_any_dynamic);
- },
- else => {},
- }
- try children.append(child);
- } else {
- try children.append(try p.parseExpr(.lowest));
- }
+ try children.append(try p.parseExpr(.lowest));
}
// Use ExpectJSXElementChild() so we parse child strings
@@ -12506,44 +12024,8 @@ fn NewParser_(
if (p.lexer.token != .t_slash) {
// This is a child element
- if (comptime jsx_transform_type == .solid) {
- const child = try p.parseJSXElement(less_than_loc);
-
- // if (!flags.contains(.has_dynamic_children)) {
- // if (@as(Expr.Tag, child.data) == .e_jsx_element) {
- // if (child.data.e_jsx_element.flags.contains(.has_dynamic_children) or child.data.e_jsx_element.flags.contains(.has_dynamic_prop)) {
- // flags.insert(.has_dynamic_children);
-
- // }
- // } else {
- // switch (child.knownPrimitive()) {
- // .unknown => {
- // flags.insert(.has_dynamic_children);
- // },
- // else => {},
- // }
- // }
- // }
-
- if (!flags.contains(.has_any_dynamic)) {
- if (@as(Expr.Tag, child.data) == .e_jsx_element) {
- if (child.data.e_jsx_element.flags.contains(.has_any_dynamic)) {
- flags.insert(.has_any_dynamic);
- }
- } else {
- switch (child.knownPrimitive()) {
- .unknown => {
- flags.insert(.has_any_dynamic);
- },
- else => {},
- }
- }
- }
- children.append(child) catch unreachable;
- } else {
- children.append(try p.parseJSXElement(less_than_loc)) catch unreachable;
- }
+ children.append(try p.parseJSXElement(less_than_loc)) catch unreachable;
// The call to parseJSXElement() above doesn't consume the last
// TGreaterThan because the caller knows what Next() function to call.
@@ -13100,613 +12582,6 @@ fn NewParser_(
var writer = WriterType.initWriter(p, &BunJSX.bun_jsx_identifier);
return writer.writeFunctionCall(e_.*);
},
- .solid => {
- // The rules:
- // 1. HTML string literals of static JSX elements are generated & escaped, injected at the top of the file
- // 1a. Static elements are contiguous in the HTML, but dynamic elements get a marker string during if client-side hydration
- // Each element becomes a declaration in the top-level scope of the JSX expression (i.e. either the anonymous IIFE or an array)
- // Those elements may be markers
- // The final count of the markers is passed to the template function
- // 3. The first element in a a group of elements becomes .cloneNode(true)
- // Subsequent elements call .nextSibling on the previous element.
- // The specific function differs if SSR is enabled and if client-side hydration is enabled.
- // 4. Non-static JSX children are added like this:
- // insert(topElement, createComponent(MyComponent, props), markerElement)
- // 5. Non-statically analyzable attributes are added like this:
- // setAttribute(topElement, "data-foo", "bar")
- 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();
- solid.buffered_writer.pos = 0;
- solid.component_body.clearRetainingCapacity();
- solid.component_body_decls.clearRetainingCapacity();
-
- // prepend an empty statement
- // this will later become an S.Local for the decls
- solid.component_body.append(p.allocator, p.s(S.Empty{}, expr.loc)) catch unreachable;
-
- solid.last_element_id = E.Identifier{};
- solid.prev_scope = p.current_scope;
- solid.temporary_scope.reset();
- solid.node_count = 0;
- solid.temporary_scope.kind = .function_body;
- solid.temporary_scope.parent = p.current_scope;
-
- solid.last_template_id.ref = Ref.None;
- }
-
- var writer = &solid.buffered_writer;
-
- // The JSX tag used
- const tag: Expr = tagger: {
- if (e_.tag) |_tag| {
- break :tagger p.visitExpr(_tag);
- } else {
- break :tagger p.e(E.Array{}, expr.loc);
- }
- };
-
- const jsx_props = e_.properties.slice();
-
- var template_expression = Expr{ .loc = expr.loc, .data = .{ .e_identifier = solid.last_template_id } };
- var element: ?E.Identifier = null;
- var needs_end_bracket = false;
- var children = e_.children.slice();
- defer {
- if (old_is_in_jsx_component) {
- if (element) |el| {
- solid.last_element_id = el;
- }
- }
- }
- switch (tag.data) {
- .e_string => {
- // write the template
- _ = writer.writeAll("<") catch unreachable;
- _ = writer.writeString(tag.data.e_string) catch unreachable;
- needs_end_bracket = true;
-
- for (jsx_props) |*property, i| {
- if (property.kind != .spread) {
- property.key = p.visitExpr(e_.properties.ptr[i].key.?);
- }
-
- if (property.value != null) {
- property.value = p.visitExpr(e_.properties.ptr[i].value.?);
-
- if (property.kind != .spread) {
- var key = property.key.?.data.e_string;
-
- const transform: SolidJS.ExpressionTransform =
- if (key.isUTF8())
- SolidJS.ExpressionTransform.which(key.slice(p.allocator))
- else
- SolidJS.ExpressionTransform{ .setAttribute = {} };
-
- const primitive = @as(Expr.Tag, property.value.?.data);
- const is_dynamic = switch (primitive) {
- .e_string, .e_number, .e_boolean, .e_null, .e_undefined => false,
- else => true,
- };
- do_transform: {
- var out: Expr = p.e(E.Missing{}, expr.loc);
- var needs_wrap = false;
- if (is_dynamic) {
- if (template_expression.data.e_identifier.ref.isNull()) {
- 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,
- .can_be_removed_if_unused = true,
- .call_can_be_unwrapped_if_unused = true,
- };
- p.current_scope = solid.prev_scope.?;
- template_expression = .{ .loc = expr.loc, .data = .{ .e_identifier = solid.last_template_id } };
- }
-
- if (element == null) {
- element = global_solid.generateElement(
- p,
- template_expression,
- property.value.?.loc,
- ) catch unreachable;
- }
- }
-
- if (!is_dynamic and (transform == .class or transform == .style or transform == .setAttribute)) {
- switch (transform) {
- .class => {
- switch (property.value.?.data) {
- .e_string => |str| {
- if (str.len() == 0) break :do_transform;
- _ = writer.writeAll(" class=\"") catch unreachable;
- _ = writer.writeHTMLAttributeValueString(str) catch unreachable;
- _ = writer.writeAll("\"") catch unreachable;
- },
- .e_number => |num| {
- writer.writer().print(" class={d}", .{num.value}) catch unreachable;
- },
- else => {},
- }
- },
- .setAttribute => {
- _ = writer.writeAll(" ") catch unreachable;
- _ = writer.writeString(property.key.?.data.e_string) catch unreachable;
-
- switch (property.value.?.data) {
- .e_string => |str| {
- if (str.len() == 0) break :do_transform;
- _ = writer.writeAll("=\"") catch unreachable;
- _ = writer.writeHTMLAttributeValueString(str) catch unreachable;
- _ = writer.writeAll("\"") catch unreachable;
- },
- .e_number => |num| {
- writer.writer().print("={d}", .{num.value}) catch unreachable;
- },
- else => {},
- }
- },
- .style => {},
- else => unreachable,
- }
- } else {
- switch (transform) {
- .nativeEvent, .nativeEventCaptured => {
- var args = p.allocator.alloc(Expr, 2 + @as(usize, @boolToInt(transform == .nativeEventCaptured))) catch unreachable;
-
- // on:MyEvent => MyEvent
- property.key.?.data.e_string.data = property.key.?.data.e_string.data[3..];
-
- args[0] = property.key.?;
- args[1] = property.value.?;
-
- if (transform == .nativeEventCaptured) {
- args[2] = p.e(E.Boolean{ .value = true }, property.key.?.loc);
- }
- // $element.addEventListener("MyEvent", (e) => { ... });
- out = p.e(
- E.Call{
- .target = p.e(
- E.Dot{
- .target = p.e(
- element.?,
- expr.loc,
- ),
- .name = "addEventListener",
- .name_loc = property.key.?.loc,
- },
- property.key.?.loc,
- ),
- .args = ExprNodeList.init(args),
- },
- property.key.?.loc,
- );
-
- p.recordUsage(element.?.ref);
- },
- .style => {},
- .class, .setAttribute => {
- var args = p.allocator.alloc(Expr, 4) catch unreachable;
- args[0] = p.e(element.?, expr.loc);
- args[1] = property.key.?;
- args[2] = property.value.?;
-
- // setAttribute(template_expression, key, value);
- out = p.e(
- E.Call{
- .target = p.e(
- E.Identifier{
- .ref = symbols.setAttribute.ref,
- .can_be_removed_if_unused = false,
- .call_can_be_unwrapped_if_unused = false,
- },
- property.value.?.loc,
- ),
- .args = ExprNodeList.init(args[0..3]),
- },
- property.key.?.loc,
- );
-
- 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);
- } else {
- needs_wrap = true;
- }
- },
- .event => |event| {
- out = p.e(
- E.Binary{
- .left = p.e(E.Dot{
- .target = p.e(element.?, property.key.?.loc),
- .name = event.setter(),
- .name_loc = property.key.?.loc,
- }, property.key.?.loc),
- .op = js_ast.Op.Code.bin_assign,
- .right = property.value.?,
- },
- property.key.?.loc,
- );
- needs_wrap = switch (property.value.?.data) {
- .e_arrow, .e_function => false,
- else => true,
- };
- global_solid.events_to_delegate.insert(event);
- },
- }
-
- var stmt: Stmt = undefined;
-
- if (needs_wrap) {
- var stmts = p.allocator.alloc(Stmt, 1) catch unreachable;
- stmts[0] = p.s(S.Return{ .value = out }, property.value.?.loc);
- var args = p.allocator.alloc(Expr, 1) catch unreachable;
- args[0] = p.e(
- E.Arrow{
- .args = &[_]G.Arg{},
- .body = G.FnBody{
- .stmts = stmts,
- .loc = out.loc,
- },
- },
- property.value.?.loc,
- );
- stmt = p.s(S.SExpr{
- .value = p.e(
- E.Call{
- .target = p.e(
- E.Identifier{
- .ref = symbols.effect.ref,
- },
- property.value.?.loc,
- ),
- .args = ExprNodeList.init(args),
- },
- property.value.?.loc,
- ),
- }, property.value.?.loc);
- p.recordUsage(symbols.effect.ref);
- } else {
- stmt = p.s(S.SExpr{
- .value = out,
- }, property.value.?.loc);
- }
-
- solid.component_body.append(p.allocator, stmt) catch unreachable;
- }
- }
- }
- }
-
- if (property.initializer != null) {
- property.initializer = p.visitExpr(e_.properties.ptr[i].initializer.?);
- }
- }
-
- const start_node_count = solid.node_count;
- for (children) |*el, k| {
- if (needs_end_bracket and el.data == .e_jsx_element) {
- _ = writer.writeAll(">") catch unreachable;
- solid.node_count += 1;
-
- needs_end_bracket = false;
- }
-
- const child = p.visitExpr(el.*);
- switch (child.data) {
- // skip it
- .e_missing => {},
-
- // we need to serialize it to HTML
- // it's probably a text node
- .e_string => |str| {
- if (str.len() > 0) {
- if (needs_end_bracket) {
- _ = writer.writeAll(">") catch unreachable;
- solid.node_count += 1;
- needs_end_bracket = false;
- }
- writer.writeHTMLAttributeValueString(str) catch unreachable;
- }
- },
- .e_number => |str| {
- if (needs_end_bracket) {
- _ = writer.writeAll(">") catch unreachable;
- needs_end_bracket = false;
- }
- writer.writer().print("{d}", .{str.value}) catch unreachable;
- },
-
- // debug assertion that we don't get here
- .e_jsx_element => unreachable,
-
- else => {
- if (template_expression.data.e_identifier.ref.isNull()) {
- 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 = .{
- .ref = p.declareSymbolMaybeGenerated(.other, expr.loc, new_template_name, true) catch unreachable,
- .can_be_removed_if_unused = true,
- .call_can_be_unwrapped_if_unused = true,
- };
- p.current_scope = solid.prev_scope.?;
- template_expression = .{ .loc = expr.loc, .data = .{ .e_identifier = solid.last_template_id } };
- }
- p.recordUsage(symbols.insert.ref);
- p.recordUsage(template_expression.data.e_identifier.ref);
- var args = p.allocator.alloc(Expr, 3) catch unreachable;
- 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,
- p.s(
- S.SExpr{
- .value = p.e(
- E.Call{
- .target = p.e(E.ImportIdentifier{ .ref = symbols.insert.ref }, child.loc),
- .args = ExprNodeList.init(args),
- },
- child.loc,
- ),
- },
- child.loc,
- ),
- ) catch unreachable;
- },
- }
- }
-
- if (start_node_count != solid.node_count) {
- solid.node_count += 1;
- _ = writer.writeAll("</") catch unreachable;
- _ = writer.writeString(tag.data.e_string) catch unreachable;
- _ = writer.writeAll(">") catch unreachable;
- } else if (needs_end_bracket) {
- _ = writer.writeAll("/>") catch unreachable;
- }
-
- // this is the root of a template tag, we just finished
- // <div>
- // /* some stuff in here */
- // </div>
- // ^
- // 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 hash: u64 = 0;
- // we are done, so it's time to turn our template into a string we can write
- // note that we are writing as UTF-8 but the input may be UTF-16 or UTF-8, depending.
- if (writer.pos == 0 and writer.context.list.items.len == 0) {} else if (writer.pos < writer.buffer.len and writer.context.list.items.len == 0) {
- hash = std.hash.Wyhash.hash(0, writer.buffer[0..writer.pos]);
- } else {
- var hasher = std.hash.Wyhash.init(0);
- hasher.update(writer.context.list.items);
- hasher.update(writer.buffer[0..writer.pos]);
- hash = hasher.final();
- }
-
- var gpe = global_solid.template_decls.getOrPut(p.allocator, @truncate(u32, hash)) catch unreachable;
-
- if (template_expression.data.e_identifier.ref.isNull()) {
- 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 = .{
- .ref = p.declareSymbolMaybeGenerated(.other, expr.loc, new_template_name, true) catch unreachable,
- .can_be_removed_if_unused = true,
- .call_can_be_unwrapped_if_unused = true,
- };
- p.current_scope = solid.prev_scope.?;
- template_expression = .{ .loc = expr.loc, .data = .{ .e_identifier = solid.last_template_id } };
- }
-
- if (!gpe.found_existing) {
- var args = p.allocator.alloc(Expr, 2) catch unreachable;
-
- if (writer.pos == 0 and writer.context.list.items.len == 0) {
- args[0] = p.e(E.String.init(""), expr.loc);
- } else if (writer.pos < writer.buffer.len and writer.context.list.items.len == 0) {
- args[0] = p.e(E.String.init(p.allocator.dupe(u8, writer.buffer[0..writer.pos]) catch unreachable), expr.loc);
- } else {
- const total = writer.context.list.items.len + writer.pos;
- var buffer = p.allocator.alloc(u8, total) catch unreachable;
- @memcpy(buffer.ptr, writer.context.list.items.ptr, writer.context.list.items.len);
- @memcpy(buffer.ptr + writer.context.list.items.len, &writer.buffer, writer.buffer.len);
- args[0] = p.e(E.String.init(buffer), expr.loc);
- }
-
- args[1] = p.e(E.Number{ .value = @intToFloat(f64, solid.node_count) }, expr.loc);
- solid.node_count = 0;
-
- gpe.value_ptr.* = G.Decl{
- .binding = p.b(B.Identifier{ .ref = template_expression.data.e_identifier.ref }, template_expression.loc),
- .value = p.e(
- E.Call{
- .args = ExprNodeList.init(args),
- .target = p.e(
- E.ImportIdentifier{
- .ref = symbols.template.ref,
- },
- expr.loc,
- ),
- .can_be_unwrapped_if_unused = true,
- },
- template_expression.loc,
- ),
- };
- } else {
- // link the template to the existing decl
- // this will cause the printer to use the existing template
- p.symbols.items[template_expression.data.e_identifier.ref.innerIndex()].link = gpe.value_ptr.binding.data.b_identifier.ref;
- }
- p.recordUsage(symbols.template.ref);
-
- // 1 means it was actually static
- // that means we can just turn it into a single $template.cloneNode(true)
- if (solid.component_body.items.len == 1) {
- return p.e(E.Call{
- .target = p.e(
- E.Dot{
- .name = "cloneNode",
- .name_loc = expr.loc,
- .target = template_expression,
- .can_be_removed_if_unused = true,
- .call_can_be_unwrapped_if_unused = true,
- },
- template_expression.loc,
- ),
- .args = ExprNodeList.init(true_args),
- .can_be_unwrapped_if_unused = true,
- }, expr.loc);
- }
- if (solid.component_body_decls.items.len == 0) {
- solid.component_body_decls.ensureTotalCapacityPrecise(p.allocator, 1) catch unreachable;
- solid.component_body_decls.appendAssumeCapacity(G.Decl{
- .binding = p.b(B.Identifier{ .ref = solid.last_template_id.ref }, expr.loc),
- .value = p.e(E.Call{
- .target = p.e(
- E.Dot{
- .name = "cloneNode",
- .name_loc = expr.loc,
- .target = template_expression,
- .can_be_removed_if_unused = true,
- .call_can_be_unwrapped_if_unused = true,
- },
- template_expression.loc,
- ),
- .args = ExprNodeList.init(true_args),
- .can_be_unwrapped_if_unused = true,
- }, expr.loc),
- });
- }
-
- // we need to wrap the template in a function
- const ret = p.e(E.Identifier{ .ref = solid.component_body_decls.items[0].binding.data.b_identifier.ref }, expr.loc);
- solid.component_body.items[0] = p.s(S.Local{ .decls = solid.component_body_decls.toOwnedSlice(p.allocator) }, expr.loc);
- solid.component_body.append(p.allocator, p.s(S.Return{ .value = ret }, expr.loc)) catch unreachable;
- return p.e(
- E.Arrow{ .args = &[_]G.Arg{}, .body = G.FnBody{ .stmts = solid.component_body.toOwnedSlice(p.allocator), .loc = expr.loc } },
- expr.loc,
- );
- // we don't need to return anything because it's a static element that will live in the template
- } else {
- return p.e(E.Missing{}, expr.loc);
- }
- },
- .e_dot, .e_import_identifier, .e_identifier => {
- var out_props = p.allocator.alloc(G.Property, jsx_props.len + @as(usize, @boolToInt(e_.key != null)) + @as(usize, @boolToInt(e_.children.len > 0))) catch unreachable;
- var out_props_i: usize = 0;
- for (jsx_props) |property, i| {
- if (property.kind != .spread) {
- e_.properties.ptr[i].key = p.visitExpr(e_.properties.ptr[i].key.?);
- }
-
- if (property.value != null) {
- e_.properties.ptr[i].value = p.visitExpr(e_.properties.ptr[i].value.?);
- }
-
- if (property.initializer != null) {
- e_.properties.ptr[i].initializer = p.visitExpr(e_.properties.ptr[i].initializer.?);
- }
-
- if (property.kind != .spread) {
- const kind = if (property.value.?.data == .e_arrow or property.value.?.data == .e_function)
- G.Property.Kind.get
- else
- G.Property.Kind.normal;
-
- out_props[out_props_i] = G.Property{
- .key = property.key,
- .value = if (kind != .get)
- property.value.?
- else
- property.value.?.wrapInArrow(p.allocator) catch unreachable,
-
- .kind = kind,
- };
- out_props_i += 1;
- }
- }
-
- if (e_.key) |k| {
- const key = p.visitExpr(k);
- if (key.data != .e_missing) {
- const kind = if (key.data == .e_arrow or key.data == .e_function)
- Property.Kind.get
- else
- Property.Kind.normal;
-
- out_props[out_props_i] = G.Property{
- .key = p.e(Prefill.String.Key, k.loc),
- .value = key,
- .kind = kind,
- };
- out_props_i += 1;
- }
- }
-
- var out_child_i: usize = 0;
- for (children) |child, j| {
- children[j] = p.visitExpr(child);
- if (children[j].data != .e_missing) {
- children[out_child_i] = children[j];
- out_child_i += 1;
- }
- }
-
- if (out_child_i > 0) {
- const kind = Property.Kind.get;
-
- out_props[out_props_i] = G.Property{
- .key = p.e(Prefill.String.Children, expr.loc),
- .value = p.e(E.Array{ .items = ExprNodeList.init(children[0..out_child_i]) }, expr.loc),
- .kind = kind,
- };
- out_props_i += 1;
- }
-
- var args = p.allocator.alloc(Expr, 2) catch unreachable;
- args[0] = tag;
- args[1] = p.e(E.Object{
- .properties = G.Property.List.init(out_props[0..out_props_i]),
- }, expr.loc);
- p.recordUsage(symbols.createComponent.ref);
- return p.e(
- E.Call{
- .target = p.e(E.ImportIdentifier{ .ref = symbols.createComponent.ref }, expr.loc),
- .args = ExprNodeList.init(args),
- .close_paren_loc = e_.close_tag_loc,
- },
- expr.loc,
- );
- },
- .e_array => {},
- else => unreachable,
- }
- },
.react => {
const tag: Expr = tagger: {
if (e_.tag) |_tag| {
@@ -19273,9 +18148,6 @@ const JavaScriptParser = NewParser(.{});
const JSXParser = NewParser(.{ .jsx = .react });
const TSXParser = NewParser(.{ .jsx = .react, .typescript = true });
const TypeScriptParser = NewParser(.{ .typescript = true });
-const SolidJSXParser = NewParser(.{ .jsx = .solid });
-const SolidTSXParser = NewParser(.{ .jsx = .solid, .typescript = true });
-
const JSParserMacro = NewParser(.{
.jsx = .macro,
});