aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/SVG/code.js74
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/SVG/output.bun.js33
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/SVG/output.js108
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/attributeExpressions/code.js115
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/attributeExpressions/output.bun.js155
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/attributeExpressions/output.js241
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/components/code.js161
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/components/output.bun.js205
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/components/output.js443
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/conditionalExpressions/code.js71
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/conditionalExpressions/output.bun.js144
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/conditionalExpressions/output.js319
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/customElements/code.js29
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/customElements/output.bun.js27
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/customElements/output.js66
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/eventExpressions/code.js32
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/eventExpressions/output.bun.js57
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/eventExpressions/output.js63
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/fragments/code.js83
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/fragments/output.bun.js13
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/fragments/output.js66
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/insertChildren/code.js36
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/insertChildren/output.js185
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/namespaceElements/code.js6
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/namespaceElements/output.js16
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/simpleElements/code.js9
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/simpleElements/output.bun.js5
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/simpleElements/output.js8
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/textInterpolation/code.js72
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/textInterpolation/output.bun.js71
-rw-r--r--integration/bunjs-only-snippets/solid-dom-fixtures/textInterpolation/output.js144
-rw-r--r--src/global.zig3
-rw-r--r--src/javascript/jsc/node/node_fs.zig5
-rw-r--r--src/js_ast.zig13
-rw-r--r--src/js_parser.zig600
-rw-r--r--src/string_immutable.zig4
37 files changed, 3469 insertions, 217 deletions
diff --git a/Makefile b/Makefile
index 85164d53d..c4c9f9565 100644
--- a/Makefile
+++ b/Makefile
@@ -409,6 +409,10 @@ prepare-types:
release-types:
cd packages/bun-types && npm publish
+format:
+ $(PRETTIER) --write integration/bunjs-only-snippets/*.js
+ $(PRETTIER) --write integration/bunjs-only-snippets/solid-dom-fixtures/**/*.js
+
lolhtml:
cd $(BUN_DEPS_DIR)/lol-html/ && cd $(BUN_DEPS_DIR)/lol-html/c-api && cargo build --release && cp target/release/liblolhtml.a $(BUN_DEPS_OUT_DIR)
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/SVG/code.js b/integration/bunjs-only-snippets/solid-dom-fixtures/SVG/code.js
new file mode 100644
index 000000000..0ffded054
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/SVG/code.js
@@ -0,0 +1,74 @@
+const template = (
+ <svg width="400" height="180">
+ <rect
+ stroke-width="2"
+ x="50"
+ y="20"
+ rx="20"
+ ry="20"
+ width="150"
+ height="150"
+ style="fill:red;stroke:black;stroke-width:5;opacity:0.5"
+ />
+ <linearGradient gradientTransform="rotate(25)">
+ <stop offset="0%"></stop>
+ </linearGradient>
+ </svg>
+);
+
+const template2 = (
+ <svg width="400" height="180">
+ <rect
+ className={state.name}
+ stroke-width={state.width}
+ x={state.x}
+ y={state.y}
+ rx="20"
+ ry="20"
+ width="150"
+ height="150"
+ style={{
+ fill: "red",
+ stroke: "black",
+ "stroke-width": props.stroke,
+ opacity: 0.5,
+ }}
+ />
+ </svg>
+);
+
+const template3 = (
+ <svg width="400" height="180">
+ <rect {...props} />
+ </svg>
+);
+
+const template4 = <rect x="50" y="20" width="150" height="150" />;
+
+const template5 = (
+ <>
+ <rect x="50" y="20" width="150" height="150" />
+ </>
+);
+
+const template6 = (
+ <Component>
+ <rect x="50" y="20" width="150" height="150" />
+ </Component>
+);
+
+const template7 = (
+ <svg viewBox={"0 0 160 40"} xmlns="http://www.w3.org/2000/svg">
+ <a xlink:href={url}>
+ <text x="10" y="25">
+ MDN Web Docs
+ </text>
+ </a>
+ </svg>
+);
+
+const template8 = (
+ <svg viewBox={"0 0 160 40"} xmlns="http://www.w3.org/2000/svg">
+ <text x="10" y="25" textContent={text} />
+ </svg>
+);
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/SVG/output.bun.js b/integration/bunjs-only-snippets/solid-dom-fixtures/SVG/output.bun.js
new file mode 100644
index 000000000..44d092f15
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/SVG/output.bun.js
@@ -0,0 +1,33 @@
+var _tmpl$1 = _template$('<svg width="400" height="180"><rect stroke-width="2" x="50" y="20" rx="20" ry="20" width="150" height="150"/><linearGradient gradientTransform="rotate(25)"><stop offset="0%"/></linearGradient></svg>', 4), _tmpl$2 = _template$('<svg width="400" height="180"><rect rx="20" ry="20" width="150" height="150"/></svg>', 2), _tmpl$3 = _template$('<svg width="400" height="180"><rect/></svg>', 2), _tmpl$4 = _template$('<rect x="50" y="20" width="150" height="150"/>', 0), _tmpl$5 = _template$('<svg viewBox="0 0 160 40" xmlns="http://www.w3.org/2000/svg"><a><text x="10" y="25">MDN Web Docs</text></a></svg>', 6), _tmpl$6 = _template$('<svg viewBox="0 0 160 40" xmlns="http://www.w3.org/2000/svg"><text x="10" y="25"/></svg>', 2);
+const template = _tmpl$1.cloneNode(true);
+const template2 = () => {
+ var _el = _tmpl$1.cloneNode(true);
+ effect(() => {
+ return setAttribute(_el, "className", state.name);
+ });
+ effect(() => {
+ return setAttribute(_el, "stroke-width", state.width);
+ });
+ effect(() => {
+ return setAttribute(_el, "x", state.x);
+ });
+ effect(() => {
+ return setAttribute(_el, "y", state.y);
+ });
+ ;
+ return _el;
+};
+const template3 = _tmpl$3.cloneNode(true);
+const template4 = _tmpl$4.cloneNode(true);
+const template5 = ;
+const template6 = createComponent(Component, {});
+const template7 = () => {
+ var _el = _tmpl$4.cloneNode(true);
+ setAttribute(_el, "xlink:href", url);
+ return _el;
+};
+const template8 = () => {
+ var _el = _tmpl$5.cloneNode(true);
+ setAttribute(_el, "textContent", text);
+ return _el;
+};
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/SVG/output.js b/integration/bunjs-only-snippets/solid-dom-fixtures/SVG/output.js
new file mode 100644
index 000000000..edac460af
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/SVG/output.js
@@ -0,0 +1,108 @@
+import { template as _$template } from "r-dom";
+import { setAttributeNS as _$setAttributeNS } from "r-dom";
+import { createComponent as _$createComponent } from "r-dom";
+import { spread as _$spread } from "r-dom";
+import { setAttribute as _$setAttribute } from "r-dom";
+import { effect as _$effect } from "r-dom";
+
+const _tmpl$ = /*#__PURE__*/ _$template(
+ `<svg width="400" height="180"><rect stroke-width="2" x="50" y="20" rx="20" ry="20" width="150" height="150" style="fill:red;stroke:black;stroke-width:5;opacity:0.5"></rect><linearGradient gradientTransform="rotate(25)"><stop offset="0%"></stop></linearGradient></svg>`,
+ 8
+ ),
+ _tmpl$2 = /*#__PURE__*/ _$template(
+ `<svg width="400" height="180"><rect rx="20" ry="20" width="150" height="150"></rect></svg>`,
+ 4
+ ),
+ _tmpl$3 = /*#__PURE__*/ _$template(
+ `<svg width="400" height="180"><rect></rect></svg>`,
+ 4
+ ),
+ _tmpl$4 = /*#__PURE__*/ _$template(
+ `<svg><rect x="50" y="20" width="150" height="150"></rect></svg>`,
+ 4,
+ true
+ ),
+ _tmpl$5 = /*#__PURE__*/ _$template(
+ `<svg viewBox="0 0 160 40" xmlns="http://www.w3.org/2000/svg"><a><text x="10" y="25">MDN Web Docs</text></a></svg>`,
+ 6
+ ),
+ _tmpl$6 = /*#__PURE__*/ _$template(
+ `<svg viewBox="0 0 160 40" xmlns="http://www.w3.org/2000/svg"><text x="10" y="25"></text></svg>`,
+ 4
+ );
+
+const template = _tmpl$.cloneNode(true);
+
+const template2 = (() => {
+ const _el$2 = _tmpl$2.cloneNode(true),
+ _el$3 = _el$2.firstChild;
+
+ _el$3.style.setProperty("fill", "red");
+
+ _el$3.style.setProperty("stroke", "black");
+
+ _el$3.style.setProperty("opacity", "0.5");
+
+ _$effect(
+ (_p$) => {
+ const _v$ = state.name,
+ _v$2 = state.width,
+ _v$3 = state.x,
+ _v$4 = state.y,
+ _v$5 = props.stroke;
+ _v$ !== _p$._v$ && _$setAttribute(_el$3, "class", (_p$._v$ = _v$));
+ _v$2 !== _p$._v$2 &&
+ _$setAttribute(_el$3, "stroke-width", (_p$._v$2 = _v$2));
+ _v$3 !== _p$._v$3 && _$setAttribute(_el$3, "x", (_p$._v$3 = _v$3));
+ _v$4 !== _p$._v$4 && _$setAttribute(_el$3, "y", (_p$._v$4 = _v$4));
+ _v$5 !== _p$._v$5 &&
+ _el$3.style.setProperty("stroke-width", (_p$._v$5 = _v$5));
+ return _p$;
+ },
+ {
+ _v$: undefined,
+ _v$2: undefined,
+ _v$3: undefined,
+ _v$4: undefined,
+ _v$5: undefined,
+ }
+ );
+
+ return _el$2;
+})();
+
+const template3 = (() => {
+ const _el$4 = _tmpl$3.cloneNode(true),
+ _el$5 = _el$4.firstChild;
+
+ _$spread(_el$5, props, true, false);
+
+ return _el$4;
+})();
+
+const template4 = _tmpl$4.cloneNode(true);
+
+const template5 = _tmpl$4.cloneNode(true);
+
+const template6 = _$createComponent(Component, {
+ get children() {
+ return _tmpl$4.cloneNode(true);
+ },
+});
+
+const template7 = (() => {
+ const _el$9 = _tmpl$5.cloneNode(true),
+ _el$10 = _el$9.firstChild;
+
+ _$setAttributeNS(_el$10, "http://www.w3.org/1999/xlink", "xlink:href", url);
+
+ return _el$9;
+})();
+
+const template8 = (() => {
+ const _el$11 = _tmpl$6.cloneNode(true),
+ _el$12 = _el$11.firstChild;
+
+ _el$12.textContent = text;
+ return _el$11;
+})();
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/attributeExpressions/code.js b/integration/bunjs-only-snippets/solid-dom-fixtures/attributeExpressions/code.js
new file mode 100644
index 000000000..b64949434
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/attributeExpressions/code.js
@@ -0,0 +1,115 @@
+const selected = true;
+let id = "my-h1";
+let link;
+const template = (
+ <div
+ id="main"
+ {...results}
+ classList={{ selected: unknown }}
+ style={{ color }}
+ >
+ <h1
+ class="base"
+ id={id}
+ {...results()}
+ disabled
+ readonly=""
+ title={welcoming()}
+ style={{ "background-color": color(), "margin-right": "40px" }}
+ classList={{ dynamic: dynamic(), selected }}
+ >
+ <a href={"/"} ref={link} classList={{ "ccc ddd": true }} readonly={value}>
+ Welcome
+ </a>
+ </h1>
+ </div>
+);
+
+const template2 = (
+ <div {...getProps("test")}>
+ <div textContent={rowId} />
+ <div textContent={row.label} />
+ <div innerHTML={"<div/>"} />
+ </div>
+);
+
+const template3 = (
+ <div
+ id={/*@once*/ state.id}
+ style={/*@once*/ { "background-color": state.color }}
+ name={state.name}
+ textContent={/*@once*/ state.content}
+ />
+);
+
+const template4 = (
+ <div class="hi" className={state.class} classList={{ "ccc:ddd": true }} />
+);
+
+const template5 = <div class="a" className="b"></div>;
+
+const template6 = <div style={someStyle()} textContent="Hi" />;
+
+const template7 = (
+ <div
+ style={{
+ "background-color": color(),
+ "margin-right": "40px",
+ ...props.style,
+ }}
+ style:padding-top={props.top}
+ class:my-class={props.active}
+ />
+);
+
+let refTarget;
+const template8 = <div ref={refTarget} />;
+
+const template9 = <div ref={(e) => console.log(e)} />;
+
+const template10 = <div ref={refFactory()} />;
+
+const template11 = <div use:something use:another={thing} use:zero={0} />;
+
+const template12 = <div prop:htmlFor={thing} />;
+
+const template13 = <input type="checkbox" checked={true} />;
+
+const template14 = <input type="checkbox" checked={state.visible} />;
+
+const template15 = <div class="`a">`$`</div>;
+
+const template16 = (
+ <button
+ class="static"
+ classList={{
+ hi: "k",
+ }}
+ type="button"
+ >
+ Write
+ </button>
+);
+
+const template17 = (
+ <button
+ classList={{
+ a: true,
+ b: true,
+ c: true,
+ }}
+ onClick={increment}
+ >
+ Hi
+ </button>
+);
+
+const template18 = (
+ <div
+ {...{
+ get [key()]() {
+ return props.value;
+ },
+ }}
+ />
+);
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/attributeExpressions/output.bun.js b/integration/bunjs-only-snippets/solid-dom-fixtures/attributeExpressions/output.bun.js
new file mode 100644
index 000000000..4bb3e1b39
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/attributeExpressions/output.bun.js
@@ -0,0 +1,155 @@
+var _tmpl = _template$(
+ '<div id="main"><h1 class="base" disabled readonly><a href="/">Welcome</a></h1></div>',
+ 6
+ ),
+ _tmpl$2 = _template$(
+ '<div><div/><div/><div innerHTML="&lt;div/&gt;"/></div>',
+ 2
+ ),
+ _tmpl$2 = _template$("<div/>", 0),
+ _tmpl$3 = _template$('<div class="hi"/>', 0),
+ _tmpl$5 = _template$('<div class="a" class="b"/>', 0),
+ _tmpl$5 = _template$('<div textContent="Hi"/>', 0),
+ _tmpl$6 = _template$("<div use:something use:zero=0/>", 0),
+ _tmpl$8 = _template$('<input type="checkbox" checked/>', 0),
+ _tmpl$8 = _template$('<input type="checkbox"/>', 0),
+ _tmpl$10 = _template$('<div class="`a">`$`</div>', 2),
+ _tmpl$10 = _template$(
+ '<button class="static" type="button">Write</button>',
+ 2
+ ),
+ _tmpl$11 = _template$("<button>Hi</button>", 2);
+const selected = true;
+let id = "my-h1";
+let link;
+const template = () => {
+ var _el = _tmpl.cloneNode(true),
+ _el$1 = _el.firstChild,
+ _el$2 = _el$1.nextSibling;
+ effect(() => {
+ return setAttribute(_el, "classList", { selected: unknown });
+ });
+ setAttribute(_el$1, "id", id);
+ effect(() => {
+ return setAttribute(_el$1, "title", welcoming());
+ });
+ effect(() => {
+ return setAttribute(_el$1, "classList", { dynamic: dynamic(), selected });
+ });
+ setAttribute(_el$2, "ref", link);
+ effect(() => {
+ return setAttribute(_el$2, "classList", { "ccc ddd": true });
+ });
+ setAttribute(_el$2, "readonly", value);
+ return _el;
+};
+const template2 = () => {
+ var _el = _tmpl$1.cloneNode(true),
+ _el$1 = _el.firstChild;
+ setAttribute(_el, "textContent", rowId);
+ effect(() => {
+ return setAttribute(_el$1, "textContent", row.label);
+ });
+ return _el;
+};
+const template3 = () => {
+ var _el = _tmpl$2.cloneNode(true);
+ effect(() => {
+ return setAttribute(_el, "id", state.id);
+ });
+ effect(() => {
+ return setAttribute(_el, "name", state.name);
+ });
+ effect(() => {
+ return setAttribute(_el, "textContent", state.content);
+ });
+ return _el;
+};
+const template4 = () => {
+ var _el = _tmpl$3.cloneNode(true);
+ effect(() => {
+ return setAttribute(_el, "className", state.class);
+ });
+ effect(() => {
+ return setAttribute(_el, "classList", { "ccc:ddd": true });
+ });
+ return _el;
+};
+const template5 = _tmpl$5.cloneNode(true);
+const template6 = () => {
+ var _el = _tmpl$5.cloneNode(true);
+ return _el;
+};
+const template7 = () => {
+ var _el = _tmpl$2.cloneNode(true);
+ effect(() => {
+ return setAttribute(_el, "style:padding-top", props.top);
+ });
+ effect(() => {
+ return setAttribute(_el, "class:my-class", props.active);
+ });
+ return _el;
+};
+let refTarget;
+const template8 = () => {
+ var _el = _tmpl$2.cloneNode(true);
+ setAttribute(_el, "ref", refTarget);
+ return _el;
+};
+const template9 = () => {
+ var _el = _tmpl$2.cloneNode(true);
+ effect(() => {
+ return setAttribute(_el, "ref", (e) => console.log(e));
+ });
+ return _el;
+};
+const template10 = () => {
+ var _el = _tmpl$2.cloneNode(true);
+ effect(() => {
+ return setAttribute(_el, "ref", refFactory());
+ });
+ return _el;
+};
+const template11 = () => {
+ var _el = _tmpl$6.cloneNode(true);
+ setAttribute(_el, "use:another", thing);
+ return _el;
+};
+const template12 = () => {
+ var _el = _tmpl$2.cloneNode(true);
+ setAttribute(_el, "prop:htmlFor", thing);
+ return _el;
+};
+const template13 = _tmpl$8.cloneNode(true);
+const template14 = () => {
+ var _el = _tmpl$8.cloneNode(true);
+ effect(() => {
+ return setAttribute(_el, "checked", state.visible);
+ });
+ return _el;
+};
+const template15 = _tmpl$10.cloneNode(true);
+const template16 = () => {
+ var _el = _tmpl$10.cloneNode(true);
+ effect(() => {
+ return setAttribute(_el, "classList", {
+ hi: "k",
+ });
+ });
+ return _el;
+};
+const template17 = () => {
+ var _el = _tmpl$11.cloneNode(true);
+ effect(() => {
+ return setAttribute(_el, "classList", {
+ a: true,
+ b: true,
+ c: true,
+ });
+ });
+ effect(() => {
+ return (_el.$$click = increment);
+ });
+ return _el;
+};
+const template18 = _tmpl$2.cloneNode(true);
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/attributeExpressions/output.js b/integration/bunjs-only-snippets/solid-dom-fixtures/attributeExpressions/output.js
new file mode 100644
index 000000000..14f700218
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/attributeExpressions/output.js
@@ -0,0 +1,241 @@
+const _tmpl$ = /*#__PURE__*/ _$template(
+ `<div id="main"><h1 class="base selected" id="my-h1" disabled readonly=""><a href="/">Welcome</a></h1></div>`,
+ 6
+ ),
+ _tmpl$2 = /*#__PURE__*/ _$template(
+ `<div><div></div><div> </div><div></div></div>`,
+ 8
+ ),
+ _tmpl$3 = /*#__PURE__*/ _$template(`<div></div>`, 2),
+ _tmpl$4 = /*#__PURE__*/ _$template(`<div class="a b"></div>`, 2),
+ _tmpl$5 = /*#__PURE__*/ _$template(`<input type="checkbox">`, 1),
+ _tmpl$6 = /*#__PURE__*/ _$template(`<div class="\`a">\`$\`</div>`, 2),
+ _tmpl$7 = /*#__PURE__*/ _$template(
+ `<button class="static hi" type="button">Write</button>`,
+ 2
+ ),
+ _tmpl$8 = /*#__PURE__*/ _$template(`<button class="a b c">Hi</button>`, 2);
+
+const selected = true;
+let id = "my-h1";
+let link;
+
+const template = (() => {
+ const _el$ = _tmpl$.cloneNode(true),
+ _el$2 = _el$.firstChild,
+ _el$3 = _el$2.firstChild;
+
+ _$spread(_el$, results, false, true);
+
+ _el$.classList.toggle("selected", unknown);
+
+ _el$.style.setProperty("color", color);
+
+ _$spread(_el$2, results, false, true);
+
+ _el$2.style.setProperty("margin-right", "40px");
+
+ const _ref$ = link;
+ typeof _ref$ === "function" ? _ref$(_el$3) : (link = _el$3);
+
+ _$classList(_el$3, {
+ "ccc ddd": true,
+ });
+
+ _el$3.readOnly = value;
+
+ _$effect(
+ (_p$) => {
+ const _v$ = welcoming(),
+ _v$2 = color(),
+ _v$3 = !!dynamic();
+
+ _v$ !== _p$._v$ && _$setAttribute(_el$2, "title", (_p$._v$ = _v$));
+ _v$2 !== _p$._v$2 &&
+ _el$2.style.setProperty("background-color", (_p$._v$2 = _v$2));
+ _v$3 !== _p$._v$3 && _el$2.classList.toggle("dynamic", (_p$._v$3 = _v$3));
+ return _p$;
+ },
+ {
+ _v$: undefined,
+ _v$2: undefined,
+ _v$3: undefined,
+ }
+ );
+
+ return _el$;
+})();
+
+const template2 = (() => {
+ const _el$4 = _tmpl$2.cloneNode(true),
+ _el$5 = _el$4.firstChild,
+ _el$6 = _el$5.nextSibling,
+ _el$7 = _el$6.firstChild,
+ _el$8 = _el$6.nextSibling;
+
+ _$spread(_el$4, () => getProps("test"), false, true);
+
+ _el$5.textContent = rowId;
+ _el$8.innerHTML = "<div/>";
+
+ _$effect(() => (_el$7.data = row.label));
+
+ return _el$4;
+})();
+
+const template3 = (() => {
+ const _el$9 = _tmpl$3.cloneNode(true);
+
+ _$setAttribute(_el$9, "id", state.id);
+
+ _el$9.style.setProperty("background-color", state.color);
+
+ _el$9.textContent = state.content;
+
+ _$effect(() => _$setAttribute(_el$9, "name", state.name));
+
+ return _el$9;
+})();
+
+const template4 = (() => {
+ const _el$10 = _tmpl$3.cloneNode(true);
+
+ _$classList(_el$10, {
+ "ccc:ddd": true,
+ });
+
+ _$effect(() => _$className(_el$10, `hi ${state.class || ""}`));
+
+ return _el$10;
+})();
+
+const template5 = _tmpl$4.cloneNode(true);
+
+const template6 = (() => {
+ const _el$12 = _tmpl$3.cloneNode(true);
+
+ _el$12.textContent = "Hi";
+
+ _$effect((_$p) => _$style(_el$12, someStyle(), _$p));
+
+ return _el$12;
+})();
+
+const template7 = (() => {
+ const _el$13 = _tmpl$3.cloneNode(true);
+
+ _$effect(
+ (_p$) => {
+ const _v$4 = {
+ "background-color": color(),
+ "margin-right": "40px",
+ ...props.style,
+ },
+ _v$5 = props.top,
+ _v$6 = !!props.active;
+
+ _p$._v$4 = _$style(_el$13, _v$4, _p$._v$4);
+ _v$5 !== _p$._v$5 &&
+ _el$13.style.setProperty("padding-top", (_p$._v$5 = _v$5));
+ _v$6 !== _p$._v$6 &&
+ _el$13.classList.toggle("my-class", (_p$._v$6 = _v$6));
+ return _p$;
+ },
+ {
+ _v$4: undefined,
+ _v$5: undefined,
+ _v$6: undefined,
+ }
+ );
+
+ return _el$13;
+})();
+
+let refTarget;
+
+const template8 = (() => {
+ const _el$14 = _tmpl$3.cloneNode(true);
+
+ const _ref$2 = refTarget;
+ typeof _ref$2 === "function" ? _ref$2(_el$14) : (refTarget = _el$14);
+ return _el$14;
+})();
+
+const template9 = (() => {
+ const _el$15 = _tmpl$3.cloneNode(true);
+
+ ((e) => console.log(e))(_el$15);
+
+ return _el$15;
+})();
+
+const template10 = (() => {
+ const _el$16 = _tmpl$3.cloneNode(true);
+
+ const _ref$3 = refFactory();
+
+ typeof _ref$3 === "function" && _ref$3(_el$16);
+ return _el$16;
+})();
+
+const template11 = (() => {
+ const _el$17 = _tmpl$3.cloneNode(true);
+
+ zero(_el$17, () => 0);
+ another(_el$17, () => thing);
+ something(_el$17, () => true);
+ return _el$17;
+})();
+
+const template12 = (() => {
+ const _el$18 = _tmpl$3.cloneNode(true);
+
+ _el$18.htmlFor = thing;
+ return _el$18;
+})();
+
+const template13 = (() => {
+ const _el$19 = _tmpl$5.cloneNode(true);
+
+ _el$19.checked = true;
+ return _el$19;
+})();
+
+const template14 = (() => {
+ const _el$20 = _tmpl$5.cloneNode(true);
+
+ _$effect(() => (_el$20.checked = state.visible));
+
+ return _el$20;
+})();
+
+const template15 = _tmpl$6.cloneNode(true);
+
+const template16 = _tmpl$7.cloneNode(true);
+
+const template17 = (() => {
+ const _el$23 = _tmpl$8.cloneNode(true);
+
+ _$addEventListener(_el$23, "click", increment, true);
+
+ return _el$23;
+})();
+
+const template18 = (() => {
+ const _el$24 = _tmpl$3.cloneNode(true);
+
+ _$spread(
+ _el$24,
+ () => ({
+ get [key()]() {
+ return props.value;
+ },
+ }),
+ false,
+ false
+ );
+
+ return _el$24;
+})();
+
+_$delegateEvents(["click"]);
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/components/code.js b/integration/bunjs-only-snippets/solid-dom-fixtures/components/code.js
new file mode 100644
index 000000000..f3bd159d6
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/components/code.js
@@ -0,0 +1,161 @@
+import { Show } from "somewhere";
+
+const Child = (props) => {
+ const [s, set] = createSignal();
+ return (
+ <>
+ <div ref={props.ref}>Hello {props.name}</div>
+ <div ref={set}>{props.children}</div>
+ </>
+ );
+};
+
+const template = (props) => {
+ let childRef;
+ const { content } = props;
+ return (
+ <div>
+ <Child name="John" {...props} ref={childRef} booleanProperty>
+ <div>From Parent</div>
+ </Child>
+ <Child name="Jason" {...dynamicSpread()} ref={props.ref}>
+ {/* Comment Node */}
+ <div>{content}</div>
+ </Child>
+ <Context.Consumer ref={props.consumerRef()}>
+ {(context) => context}
+ </Context.Consumer>
+ </div>
+ );
+};
+
+const template2 = (
+ <Child
+ name="Jake"
+ dynamic={state.data}
+ stale={/*@once*/ state.data}
+ handleClick={clickHandler}
+ hyphen-ated={state.data}
+ ref={(el) => (e = el)}
+ />
+);
+
+const template3 = (
+ <Child>
+ <div />
+ <div />
+ <div />
+ After
+ </Child>
+);
+
+const [s, set] = createSignal();
+const template4 = <Child ref={set}>{<div />}</Child>;
+
+const template5 = <Child dynamic={state.dynamic}>{state.dynamic}</Child>;
+
+// builtIns
+const template6 = (
+ <For each={state.list} fallback={<Loading />}>
+ {(item) => <Show when={state.condition}>{item}</Show>}
+ </For>
+);
+
+const template7 = (
+ <Child>
+ <div />
+ {state.dynamic}
+ </Child>
+);
+
+const template8 = (
+ <Child>
+ {(item) => item}
+ {(item) => item}
+ </Child>
+);
+
+const template9 = <_garbage>Hi</_garbage>;
+
+const template10 = (
+ <div>
+ <Link>new</Link>
+ {" | "}
+ <Link>comments</Link>
+ {" | "}
+ <Link>show</Link>
+ {" | "}
+ <Link>ask</Link>
+ {" | "}
+ <Link>jobs</Link>
+ {" | "}
+ <Link>submit</Link>
+ </div>
+);
+
+const template11 = (
+ <div>
+ <Link>new</Link>
+ {" | "}
+ <Link>comments</Link>
+ <Link>show</Link>
+ {" | "}
+ <Link>ask</Link>
+ <Link>jobs</Link>
+ {" | "}
+ <Link>submit</Link>
+ </div>
+);
+
+const template12 = (
+ <div>
+ {" | "}
+ <Link>comments</Link>
+ {" | "}
+ {" | "}
+ {" | "}
+ <Link>show</Link>
+ {" | "}
+ </div>
+);
+
+class Template13 {
+ render() {
+ <Component prop={this.something} onClick={() => this.shouldStay}>
+ <Nested prop={this.data}>{this.content}</Nested>
+ </Component>;
+ }
+}
+
+const Template14 = <Component>{data()}</Component>;
+
+const Template15 = <Component {...props} />;
+
+const Template16 = <Component something={something} {...props} />;
+
+const Template17 = (
+ <Pre>
+ <span>1</span> <span>2</span> <span>3</span>
+ </Pre>
+);
+const Template18 = (
+ <Pre>
+ <span>1</span>
+ <span>2</span>
+ <span>3</span>
+ </Pre>
+);
+
+const Template19 = <Component {...s.dynamic()} />;
+
+const Template20 = <Component class={prop.red ? "red" : "green"} />;
+
+const template21 = (
+ <Component
+ {...{
+ get [key()]() {
+ return props.value;
+ },
+ }}
+ />
+);
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/components/output.bun.js b/integration/bunjs-only-snippets/solid-dom-fixtures/components/output.bun.js
new file mode 100644
index 000000000..5ab4d5614
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/components/output.bun.js
@@ -0,0 +1,205 @@
+var _tmpl = _template$("<div><div>From Parent</div><div</div></div>", 9), _tmpl$1 = _template$("<div> | | | | | </div>", 8), _tmpl$2 = _template$("<div> | | | </div>", 8);
+import {Show} from "somewhere";
+const Child = (props) => {
+ const [s, set] = createSignal();
+ return ;
+};
+const template = (props) => {
+ let childRef;
+ const { content } = props;
+ return () => {
+ var _tmpl = _tmpl.cloneNode(true);
+ insert(_tmpl, createComponent(Child, {
+ name: "John",
+ ref: childRef,
+ booleanProperty: true
+ }), null);
+ insert(_tmpl, content, null);
+ insert(_tmpl, createComponent(Child, {
+ name: "Jason",
+ ref: props.ref
+ }), null);
+ insert(_tmpl, createComponent(Context.Consumer, {
+ ref: props.consumerRef(),
+ get children: [
+ (context) => context
+ ]
+ }), null);
+ return _tmpl;
+ };
+};
+const template2 = createComponent(Child, {
+ name: "Jake",
+ dynamic: state.data,
+ stale: state.data,
+ handleClick: clickHandler,
+ "hyphen-ated": state.data,
+ get ref: () => {
+ return (el) => e = el;
+ }
+});
+const template3 = createComponent(Child, {
+ get children: [
+ "After"
+ ]
+});
+const [s, set] = createSignal();
+const template4 = createComponent(Child, {
+ ref: set
+});
+const template5 = createComponent(Child, {
+ dynamic: state.dynamic,
+ get children: [
+ state.dynamic
+ ]
+});
+const template6 = createComponent(For, {
+ each: state.list,
+ fallback: ,
+ get children: [
+ (item) => createComponent(Show, {
+ when: state.condition,
+ get children: [
+ item
+ ]
+ })
+ ]
+});
+const template7 = createComponent(Child, {
+ get children: [
+ state.dynamic
+ ]
+});
+const template8 = createComponent(Child, {
+ get children: [
+ (item) => item,
+ (item) => item
+ ]
+});
+const template9 = createComponent(_garbage, {
+ get children: [
+ "Hi"
+ ]
+});
+const template10 = () => {
+ var _tmpl$1 = _tmpl$1.cloneNode(true);
+ insert(_tmpl$1, createComponent(Link, {
+ get children: [
+ "new"
+ ]
+ }), null);
+ insert(_tmpl$1, createComponent(Link, {
+ get children: [
+ "comments"
+ ]
+ }), null);
+ insert(_tmpl$1, createComponent(Link, {
+ get children: [
+ "show"
+ ]
+ }), null);
+ insert(_tmpl$1, createComponent(Link, {
+ get children: [
+ "ask"
+ ]
+ }), null);
+ insert(_tmpl$1, createComponent(Link, {
+ get children: [
+ "jobs"
+ ]
+ }), null);
+ insert(_tmpl$1, createComponent(Link, {
+ get children: [
+ "submit"
+ ]
+ }), null);
+ return _tmpl$1;
+};
+const template11 = () => {
+ var _tmpl$2 = _tmpl$2.cloneNode(true);
+ insert(_tmpl$2, createComponent(Link, {
+ get children: [
+ "new"
+ ]
+ }), null);
+ insert(_tmpl$2, createComponent(Link, {
+ get children: [
+ "comments"
+ ]
+ }), null);
+ insert(_tmpl$2, createComponent(Link, {
+ get children: [
+ "show"
+ ]
+ }), null);
+ insert(_tmpl$2, createComponent(Link, {
+ get children: [
+ "ask"
+ ]
+ }), null);
+ insert(_tmpl$2, createComponent(Link, {
+ get children: [
+ "jobs"
+ ]
+ }), null);
+ insert(_tmpl$2, createComponent(Link, {
+ get children: [
+ "submit"
+ ]
+ }), null);
+ return _tmpl$2;
+};
+const template12 = () => {
+ var _tmpl$1 = _tmpl$1.cloneNode(true);
+ insert(_tmpl$1, createComponent(Link, {
+ get children: [
+ "comments"
+ ]
+ }), null);
+ insert(_tmpl$1, createComponent(Link, {
+ get children: [
+ "show"
+ ]
+ }), null);
+ return _tmpl$1;
+};
+
+class Template13 {
+ render() {
+ createComponent(Component, {
+ prop: this.something,
+ get onClick: () => {
+ return () => this.shouldStay;
+ },
+ get children: [
+ createComponent(Nested, {
+ prop: this.data,
+ get children: [
+ this.content
+ ]
+ })
+ ]
+ });
+ }
+}
+const Template14 = createComponent(Component, {
+ get children: [
+ data()
+ ]
+});
+const Template15 = createComponent(Component, {});
+const Template16 = createComponent(Component, {
+ something
+});
+const Template17 = createComponent(Pre, {
+ get children: [
+ " ",
+ " "
+ ]
+});
+const Template18 = createComponent(Pre, {});
+const Template19 = createComponent(Component, {});
+const Template20 = createComponent(Component, {
+ class: prop.red ? "red" : "green"
+});
+const template21 = createComponent(Component, {});
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/components/output.js b/integration/bunjs-only-snippets/solid-dom-fixtures/components/output.js
new file mode 100644
index 000000000..0c49d60a3
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/components/output.js
@@ -0,0 +1,443 @@
+import { template as _$template } from "r-dom";
+import { memo as _$memo } from "r-dom";
+import { For as _$For } from "r-dom";
+import { createComponent as _$createComponent } from "r-dom";
+import { mergeProps as _$mergeProps } from "r-dom";
+import { insert as _$insert } from "r-dom";
+
+const _tmpl$ = /*#__PURE__*/ _$template(`<div>Hello </div>`, 2),
+ _tmpl$2 = /*#__PURE__*/ _$template(`<div></div>`, 2),
+ _tmpl$3 = /*#__PURE__*/ _$template(`<div>From Parent</div>`, 2),
+ _tmpl$4 = /*#__PURE__*/ _$template(
+ `<div> | <!> | <!> | <!> | <!> | </div>`,
+ 6
+ ),
+ _tmpl$5 = /*#__PURE__*/ _$template(`<div> | <!> | <!> | </div>`, 4),
+ _tmpl$6 = /*#__PURE__*/ _$template(`<div> | <!> | | | <!> | </div>`, 4),
+ _tmpl$7 = /*#__PURE__*/ _$template(`<span>1</span>`, 2),
+ _tmpl$8 = /*#__PURE__*/ _$template(`<span>2</span>`, 2),
+ _tmpl$9 = /*#__PURE__*/ _$template(`<span>3</span>`, 2);
+
+import { Show } from "somewhere";
+
+const Child = (props) => {
+ const [s, set] = createSignal();
+ return [
+ (() => {
+ const _el$ = _tmpl$.cloneNode(true),
+ _el$2 = _el$.firstChild;
+
+ const _ref$ = props.ref;
+ typeof _ref$ === "function" ? _ref$(_el$) : (props.ref = _el$);
+
+ _$insert(_el$, () => props.name, null);
+
+ return _el$;
+ })(),
+ (() => {
+ const _el$3 = _tmpl$2.cloneNode(true);
+
+ set(_el$3);
+
+ _$insert(_el$3, () => props.children);
+
+ return _el$3;
+ })(),
+ ];
+};
+
+const template = (props) => {
+ let childRef;
+ const { content } = props;
+ return (() => {
+ const _el$4 = _tmpl$2.cloneNode(true);
+
+ _$insert(
+ _el$4,
+ _$createComponent(
+ Child,
+ _$mergeProps(
+ {
+ name: "John",
+ },
+ props,
+ {
+ ref(r$) {
+ const _ref$2 = childRef;
+ typeof _ref$2 === "function" ? _ref$2(r$) : (childRef = r$);
+ },
+
+ booleanProperty: true,
+
+ get children() {
+ return _tmpl$3.cloneNode(true);
+ },
+ }
+ )
+ ),
+ null
+ );
+
+ _$insert(
+ _el$4,
+ _$createComponent(
+ Child,
+ _$mergeProps(
+ {
+ name: "Jason",
+ },
+ dynamicSpread,
+ {
+ ref(r$) {
+ const _ref$3 = props.ref;
+ typeof _ref$3 === "function" ? _ref$3(r$) : (props.ref = r$);
+ },
+
+ get children() {
+ const _el$6 = _tmpl$2.cloneNode(true);
+
+ _$insert(_el$6, content);
+
+ return _el$6;
+ },
+ }
+ )
+ ),
+ null
+ );
+
+ _$insert(
+ _el$4,
+ _$createComponent(Context.Consumer, {
+ ref(r$) {
+ const _ref$4 = props.consumerRef();
+
+ typeof _ref$4 === "function" && _ref$4(r$);
+ },
+
+ children: (context) => context,
+ }),
+ null
+ );
+
+ return _el$4;
+ })();
+};
+
+const template2 = _$createComponent(Child, {
+ name: "Jake",
+
+ get dynamic() {
+ return state.data;
+ },
+
+ stale: state.data,
+ handleClick: clickHandler,
+
+ get ["hyphen-ated"]() {
+ return state.data;
+ },
+
+ ref: (el) => (e = el),
+});
+
+const template3 = _$createComponent(Child, {
+ get children() {
+ return [
+ _tmpl$2.cloneNode(true),
+ _tmpl$2.cloneNode(true),
+ _tmpl$2.cloneNode(true),
+ "After",
+ ];
+ },
+});
+
+const [s, set] = createSignal();
+
+const template4 = _$createComponent(Child, {
+ ref: set,
+
+ get children() {
+ return _tmpl$2.cloneNode(true);
+ },
+});
+
+const template5 = _$createComponent(Child, {
+ get dynamic() {
+ return state.dynamic;
+ },
+
+ get children() {
+ return state.dynamic;
+ },
+}); // builtIns
+
+const template6 = _$createComponent(_$For, {
+ get each() {
+ return state.list;
+ },
+
+ get fallback() {
+ return _$createComponent(Loading, {});
+ },
+
+ children: (item) =>
+ _$createComponent(Show, {
+ get when() {
+ return state.condition;
+ },
+
+ children: item,
+ }),
+});
+
+const template7 = _$createComponent(Child, {
+ get children() {
+ return [_tmpl$2.cloneNode(true), _$memo(() => state.dynamic)];
+ },
+});
+
+const template8 = _$createComponent(Child, {
+ get children() {
+ return [(item) => item, (item) => item];
+ },
+});
+
+const template9 = _$createComponent(_garbage, {
+ children: "Hi",
+});
+
+const template10 = (() => {
+ const _el$12 = _tmpl$4.cloneNode(true),
+ _el$13 = _el$12.firstChild,
+ _el$18 = _el$13.nextSibling,
+ _el$14 = _el$18.nextSibling,
+ _el$19 = _el$14.nextSibling,
+ _el$15 = _el$19.nextSibling,
+ _el$20 = _el$15.nextSibling,
+ _el$16 = _el$20.nextSibling,
+ _el$21 = _el$16.nextSibling,
+ _el$17 = _el$21.nextSibling;
+
+ _$insert(
+ _el$12,
+ _$createComponent(Link, {
+ children: "new",
+ }),
+ _el$13
+ );
+
+ _$insert(
+ _el$12,
+ _$createComponent(Link, {
+ children: "comments",
+ }),
+ _el$18
+ );
+
+ _$insert(
+ _el$12,
+ _$createComponent(Link, {
+ children: "show",
+ }),
+ _el$19
+ );
+
+ _$insert(
+ _el$12,
+ _$createComponent(Link, {
+ children: "ask",
+ }),
+ _el$20
+ );
+
+ _$insert(
+ _el$12,
+ _$createComponent(Link, {
+ children: "jobs",
+ }),
+ _el$21
+ );
+
+ _$insert(
+ _el$12,
+ _$createComponent(Link, {
+ children: "submit",
+ }),
+ null
+ );
+
+ return _el$12;
+})();
+
+const template11 = (() => {
+ const _el$22 = _tmpl$5.cloneNode(true),
+ _el$23 = _el$22.firstChild,
+ _el$26 = _el$23.nextSibling,
+ _el$24 = _el$26.nextSibling,
+ _el$27 = _el$24.nextSibling,
+ _el$25 = _el$27.nextSibling;
+
+ _$insert(
+ _el$22,
+ _$createComponent(Link, {
+ children: "new",
+ }),
+ _el$23
+ );
+
+ _$insert(
+ _el$22,
+ _$createComponent(Link, {
+ children: "comments",
+ }),
+ _el$26
+ );
+
+ _$insert(
+ _el$22,
+ _$createComponent(Link, {
+ children: "show",
+ }),
+ _el$26
+ );
+
+ _$insert(
+ _el$22,
+ _$createComponent(Link, {
+ children: "ask",
+ }),
+ _el$27
+ );
+
+ _$insert(
+ _el$22,
+ _$createComponent(Link, {
+ children: "jobs",
+ }),
+ _el$27
+ );
+
+ _$insert(
+ _el$22,
+ _$createComponent(Link, {
+ children: "submit",
+ }),
+ null
+ );
+
+ return _el$22;
+})();
+
+const template12 = (() => {
+ const _el$28 = _tmpl$6.cloneNode(true),
+ _el$29 = _el$28.firstChild,
+ _el$34 = _el$29.nextSibling,
+ _el$30 = _el$34.nextSibling,
+ _el$35 = _el$30.nextSibling,
+ _el$33 = _el$35.nextSibling;
+
+ _$insert(
+ _el$28,
+ _$createComponent(Link, {
+ children: "comments",
+ }),
+ _el$34
+ );
+
+ _$insert(
+ _el$28,
+ _$createComponent(Link, {
+ children: "show",
+ }),
+ _el$35
+ );
+
+ return _el$28;
+})();
+
+class Template13 {
+ render() {
+ const _self$ = this;
+
+ _$createComponent(Component, {
+ get prop() {
+ return _self$.something;
+ },
+
+ onClick: () => _self$.shouldStay,
+
+ get children() {
+ return _$createComponent(Nested, {
+ get prop() {
+ return _self$.data;
+ },
+
+ get children() {
+ return _self$.content;
+ },
+ });
+ },
+ });
+ }
+}
+
+const Template14 = _$createComponent(Component, {
+ get children() {
+ return data();
+ },
+});
+
+const Template15 = _$createComponent(Component, props);
+
+const Template16 = _$createComponent(
+ Component,
+ _$mergeProps(
+ {
+ something: something,
+ },
+ props
+ )
+);
+
+const Template17 = _$createComponent(Pre, {
+ get children() {
+ return [
+ _tmpl$7.cloneNode(true),
+ " ",
+ _tmpl$8.cloneNode(true),
+ " ",
+ _tmpl$9.cloneNode(true),
+ ];
+ },
+});
+
+const Template18 = _$createComponent(Pre, {
+ get children() {
+ return [
+ _tmpl$7.cloneNode(true),
+ _tmpl$8.cloneNode(true),
+ _tmpl$9.cloneNode(true),
+ ];
+ },
+});
+
+const Template19 = _$createComponent(
+ Component,
+ _$mergeProps(() => s.dynamic())
+);
+
+const Template20 = _$createComponent(Component, {
+ get ["class"]() {
+ return prop.red ? "red" : "green";
+ },
+});
+
+const template21 = _$createComponent(
+ Component,
+ _$mergeProps(() => ({
+ get [key()]() {
+ return props.value;
+ },
+ }))
+);
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/conditionalExpressions/code.js b/integration/bunjs-only-snippets/solid-dom-fixtures/conditionalExpressions/code.js
new file mode 100644
index 000000000..80f1a6a4f
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/conditionalExpressions/code.js
@@ -0,0 +1,71 @@
+const template1 = <div>{simple}</div>;
+
+const template2 = <div>{state.dynamic}</div>;
+
+const template3 = <div>{simple ? good : bad}</div>;
+
+const template4 = <div>{simple ? good() : bad}</div>;
+
+const template5 = <div>{state.dynamic ? good() : bad}</div>;
+
+const template6 = <div>{state.dynamic && good()}</div>;
+
+const template7 = (
+ <div>{state.count > 5 ? (state.dynamic ? best : good()) : bad}</div>
+);
+
+const template8 = <div>{state.dynamic && state.something && good()}</div>;
+
+const template9 = <div>{(state.dynamic && good()) || bad}</div>;
+
+const template10 = (
+ <div>{state.a ? "a" : state.b ? "b" : state.c ? "c" : "fallback"}</div>
+);
+
+const template11 = (
+ <div>{state.a ? a() : state.b ? b() : state.c ? "c" : "fallback"}</div>
+);
+
+const template12 = <Comp render={state.dynamic ? good() : bad} />;
+
+// no dynamic predicate
+const template13 = <Comp render={state.dynamic ? good : bad} />;
+
+const template14 = <Comp render={state.dynamic && good()} />;
+
+// no dynamic predicate
+const template15 = <Comp render={state.dynamic && good} />;
+
+const template16 = <Comp render={state.dynamic || good()} />;
+
+const template17 = <Comp render={state.dynamic ? <Comp /> : <Comp />} />;
+
+const template18 = <Comp>{state.dynamic ? <Comp /> : <Comp />}</Comp>;
+
+const template19 = <div innerHTML={state.dynamic ? <Comp /> : <Comp />} />;
+
+const template20 = <div>{state.dynamic ? <Comp /> : <Comp />}</div>;
+
+const template21 = <Comp render={state?.dynamic ? "a" : "b"} />;
+
+const template22 = <Comp>{state?.dynamic ? "a" : "b"}</Comp>;
+
+const template23 = <div innerHTML={state?.dynamic ? "a" : "b"} />;
+
+const template24 = <div>{state?.dynamic ? "a" : "b"}</div>;
+
+const template25 = <Comp render={state.dynamic ?? <Comp />} />;
+
+const template26 = <Comp>{state.dynamic ?? <Comp />}</Comp>;
+
+const template27 = <div innerHTML={state.dynamic ?? <Comp />} />;
+
+const template28 = <div>{state.dynamic ?? <Comp />}</div>;
+
+const template29 = <div>{(thing() && thing1()) ?? thing2() ?? thing3()}</div>;
+
+const template30 = <div>{thing() || thing1() || thing2()}</div>;
+
+const template31 = (
+ <Comp value={count() ? (count() ? count() : count()) : count()} />
+);
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/conditionalExpressions/output.bun.js b/integration/bunjs-only-snippets/solid-dom-fixtures/conditionalExpressions/output.bun.js
new file mode 100644
index 000000000..36c3f649b
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/conditionalExpressions/output.bun.js
@@ -0,0 +1,144 @@
+var _tmpl = template("<div</div>", 2), _tmpl$1 = template("<div/>", 0);
+const template1 = () => {
+ var _tmpl = _tmpl.cloneNode(true);
+ insert(_tmpl, simple, null);
+ return _tmpl;
+};
+const template2 = () => {
+ var _tmpl = _tmpl.cloneNode(true);
+ insert(_tmpl, state.dynamic, null);
+ return _tmpl;
+};
+const template3 = () => {
+ var _tmpl = _tmpl.cloneNode(true);
+ insert(_tmpl, simple ? good : bad, null);
+ return _tmpl;
+};
+const template4 = () => {
+ var _tmpl = _tmpl.cloneNode(true);
+ insert(_tmpl, simple ? good() : bad, null);
+ return _tmpl;
+};
+const template5 = () => {
+ var _tmpl = _tmpl.cloneNode(true);
+ insert(_tmpl, state.dynamic ? good() : bad, null);
+ return _tmpl;
+};
+const template6 = () => {
+ var _tmpl = _tmpl.cloneNode(true);
+ insert(_tmpl, state.dynamic && good(), null);
+ return _tmpl;
+};
+const template7 = () => {
+ var _tmpl = _tmpl.cloneNode(true);
+ insert(_tmpl, state.count > 5 ? state.dynamic ? best : good() : bad, null);
+ return _tmpl;
+};
+const template8 = () => {
+ var _tmpl = _tmpl.cloneNode(true);
+ insert(_tmpl, state.dynamic && state.something && good(), null);
+ return _tmpl;
+};
+const template9 = () => {
+ var _tmpl = _tmpl.cloneNode(true);
+ insert(_tmpl, state.dynamic && good() || bad, null);
+ return _tmpl;
+};
+const template10 = () => {
+ var _tmpl = _tmpl.cloneNode(true);
+ insert(_tmpl, state.a ? "a" : state.b ? "b" : state.c ? "c" : "fallback", null);
+ return _tmpl;
+};
+const template11 = () => {
+ var _tmpl = _tmpl.cloneNode(true);
+ insert(_tmpl, state.a ? a() : state.b ? b() : state.c ? "c" : "fallback", null);
+ return _tmpl;
+};
+const template12 = createComponent(Comp, {
+ render: state.dynamic ? good() : bad
+});
+const template13 = createComponent(Comp, {
+ render: state.dynamic ? good : bad
+});
+const template14 = createComponent(Comp, {
+ render: state.dynamic && good()
+});
+const template15 = createComponent(Comp, {
+ render: state.dynamic && good
+});
+const template16 = createComponent(Comp, {
+ render: state.dynamic || good()
+});
+const template17 = createComponent(Comp, {
+ render: state.dynamic ? createComponent(Comp, {}) : createComponent(Comp, {})
+});
+const template18 = createComponent(Comp, {
+ get children: [
+ state.dynamic ? createComponent(Comp, {}) : createComponent(Comp, {})
+ ]
+});
+const template19 = () => {
+ var _el = _tmpl$1.cloneNode(true);
+ effect(() => {
+ return setAttribute(_el, "innerHTML", state.dynamic ? createComponent(Comp, {}) : createComponent(Comp, {}));
+ });
+ return _el;
+};
+const template20 = () => {
+ var _tmpl = _tmpl.cloneNode(true);
+ insert(_tmpl, state.dynamic ? createComponent(Comp, {}) : createComponent(Comp, {}), null);
+ return _tmpl;
+};
+const template21 = createComponent(Comp, {
+ render: state?.dynamic ? "a" : "b"
+});
+const template22 = createComponent(Comp, {
+ get children: [
+ state?.dynamic ? "a" : "b"
+ ]
+});
+const template23 = () => {
+ var _el = _tmpl$1.cloneNode(true);
+ effect(() => {
+ return setAttribute(_el, "innerHTML", state?.dynamic ? "a" : "b");
+ });
+ return _el;
+};
+const template24 = () => {
+ var _tmpl = _tmpl.cloneNode(true);
+ insert(_tmpl, state?.dynamic ? "a" : "b", null);
+ return _tmpl;
+};
+const template25 = createComponent(Comp, {
+ render: state.dynamic ?? createComponent(Comp, {})
+});
+const template26 = createComponent(Comp, {
+ get children: [
+ state.dynamic ?? createComponent(Comp, {})
+ ]
+});
+const template27 = () => {
+ var _el = _tmpl$1.cloneNode(true);
+ effect(() => {
+ return setAttribute(_el, "innerHTML", state.dynamic ?? createComponent(Comp, {}));
+ });
+ return _el;
+};
+const template28 = () => {
+ var _tmpl = _tmpl.cloneNode(true);
+ insert(_tmpl, state.dynamic ?? createComponent(Comp, {}), null);
+ return _tmpl;
+};
+const template29 = () => {
+ var _tmpl = _tmpl.cloneNode(true);
+ insert(_tmpl, (thing() && thing1()) ?? thing2() ?? thing3(), null);
+ return _tmpl;
+};
+const template30 = () => {
+ var _tmpl = _tmpl.cloneNode(true);
+ insert(_tmpl, thing() || thing1() || thing2(), null);
+ return _tmpl;
+};
+const template31 = createComponent(Comp, {
+ value: count() ? count() ? count() : count() : count()
+});
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/conditionalExpressions/output.js b/integration/bunjs-only-snippets/solid-dom-fixtures/conditionalExpressions/output.js
new file mode 100644
index 000000000..1511f4222
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/conditionalExpressions/output.js
@@ -0,0 +1,319 @@
+import { template as _$template } from "r-dom";
+import { effect as _$effect } from "r-dom";
+import { createComponent as _$createComponent } from "r-dom";
+import { memo as _$memo } from "r-dom";
+import { insert as _$insert } from "r-dom";
+
+const _tmpl$ = /*#__PURE__*/ _$template(`<div></div>`, 2);
+
+const template1 = (() => {
+ const _el$ = _tmpl$.cloneNode(true);
+
+ _$insert(_el$, simple);
+
+ return _el$;
+})();
+
+const template2 = (() => {
+ const _el$2 = _tmpl$.cloneNode(true);
+
+ _$insert(_el$2, () => state.dynamic);
+
+ return _el$2;
+})();
+
+const template3 = (() => {
+ const _el$3 = _tmpl$.cloneNode(true);
+
+ _$insert(_el$3, simple ? good : bad);
+
+ return _el$3;
+})();
+
+const template4 = (() => {
+ const _el$4 = _tmpl$.cloneNode(true);
+
+ _$insert(_el$4, () => (simple ? good() : bad));
+
+ return _el$4;
+})();
+
+const template5 = (() => {
+ const _el$5 = _tmpl$.cloneNode(true);
+
+ _$insert(
+ _el$5,
+ (() => {
+ const _c$ = _$memo(() => !!state.dynamic, true);
+
+ return () => (_c$() ? good() : bad);
+ })()
+ );
+
+ return _el$5;
+})();
+
+const template6 = (() => {
+ const _el$6 = _tmpl$.cloneNode(true);
+
+ _$insert(
+ _el$6,
+ (() => {
+ const _c$2 = _$memo(() => !!state.dynamic, true);
+
+ return () => _c$2() && good();
+ })()
+ );
+
+ return _el$6;
+})();
+
+const template7 = (() => {
+ const _el$7 = _tmpl$.cloneNode(true);
+
+ _$insert(
+ _el$7,
+ (() => {
+ const _c$3 = _$memo(() => state.count > 5, true);
+
+ return () =>
+ _c$3()
+ ? (() => {
+ const _c$4 = _$memo(() => !!state.dynamic, true);
+
+ return () => (_c$4() ? best : good());
+ })()
+ : bad;
+ })()
+ );
+
+ return _el$7;
+})();
+
+const template8 = (() => {
+ const _el$8 = _tmpl$.cloneNode(true);
+
+ _$insert(
+ _el$8,
+ (() => {
+ const _c$5 = _$memo(() => !!(state.dynamic && state.something), true);
+
+ return () => _c$5() && good();
+ })()
+ );
+
+ return _el$8;
+})();
+
+const template9 = (() => {
+ const _el$9 = _tmpl$.cloneNode(true);
+
+ _$insert(
+ _el$9,
+ (() => {
+ const _c$6 = _$memo(() => !!state.dynamic, true);
+
+ return () => (_c$6() && good()) || bad;
+ })()
+ );
+
+ return _el$9;
+})();
+
+const template10 = (() => {
+ const _el$10 = _tmpl$.cloneNode(true);
+
+ _$insert(_el$10, () =>
+ state.a ? "a" : state.b ? "b" : state.c ? "c" : "fallback"
+ );
+
+ return _el$10;
+})();
+
+const template11 = (() => {
+ const _el$11 = _tmpl$.cloneNode(true);
+
+ _$insert(
+ _el$11,
+ (() => {
+ const _c$7 = _$memo(() => !!state.a, true);
+
+ return () =>
+ _c$7()
+ ? a()
+ : (() => {
+ const _c$8 = _$memo(() => !!state.b, true);
+
+ return () => (_c$8() ? b() : state.c ? "c" : "fallback");
+ })();
+ })()
+ );
+
+ return _el$11;
+})();
+
+const template12 = _$createComponent(Comp, {
+ get render() {
+ return _$memo(() => !!state.dynamic, true)() ? good() : bad;
+ },
+}); // no dynamic predicate
+
+const template13 = _$createComponent(Comp, {
+ get render() {
+ return state.dynamic ? good : bad;
+ },
+});
+
+const template14 = _$createComponent(Comp, {
+ get render() {
+ return _$memo(() => !!state.dynamic, true)() && good();
+ },
+}); // no dynamic predicate
+
+const template15 = _$createComponent(Comp, {
+ get render() {
+ return state.dynamic && good;
+ },
+});
+
+const template16 = _$createComponent(Comp, {
+ get render() {
+ return state.dynamic || good();
+ },
+});
+
+const template17 = _$createComponent(Comp, {
+ get render() {
+ return _$memo(() => !!state.dynamic, true)()
+ ? _$createComponent(Comp, {})
+ : _$createComponent(Comp, {});
+ },
+});
+
+const template18 = _$createComponent(Comp, {
+ get children() {
+ return _$memo(() => !!state.dynamic, true)()
+ ? _$createComponent(Comp, {})
+ : _$createComponent(Comp, {});
+ },
+});
+
+const template19 = (() => {
+ const _el$12 = _tmpl$.cloneNode(true);
+
+ _$effect(
+ () =>
+ (_el$12.innerHTML = state.dynamic
+ ? _$createComponent(Comp, {})
+ : _$createComponent(Comp, {}))
+ );
+
+ return _el$12;
+})();
+
+const template20 = (() => {
+ const _el$13 = _tmpl$.cloneNode(true);
+
+ _$insert(
+ _el$13,
+ (() => {
+ const _c$9 = _$memo(() => !!state.dynamic, true);
+
+ return () =>
+ _c$9() ? _$createComponent(Comp, {}) : _$createComponent(Comp, {});
+ })()
+ );
+
+ return _el$13;
+})();
+
+const template21 = _$createComponent(Comp, {
+ get render() {
+ return state?.dynamic ? "a" : "b";
+ },
+});
+
+const template22 = _$createComponent(Comp, {
+ get children() {
+ return state?.dynamic ? "a" : "b";
+ },
+});
+
+const template23 = (() => {
+ const _el$14 = _tmpl$.cloneNode(true);
+
+ _$effect(() => (_el$14.innerHTML = state?.dynamic ? "a" : "b"));
+
+ return _el$14;
+})();
+
+const template24 = (() => {
+ const _el$15 = _tmpl$.cloneNode(true);
+
+ _$insert(_el$15, () => (state?.dynamic ? "a" : "b"));
+
+ return _el$15;
+})();
+
+const template25 = _$createComponent(Comp, {
+ get render() {
+ return state.dynamic ?? _$createComponent(Comp, {});
+ },
+});
+
+const template26 = _$createComponent(Comp, {
+ get children() {
+ return state.dynamic ?? _$createComponent(Comp, {});
+ },
+});
+
+const template27 = (() => {
+ const _el$16 = _tmpl$.cloneNode(true);
+
+ _$effect(
+ () => (_el$16.innerHTML = state.dynamic ?? _$createComponent(Comp, {}))
+ );
+
+ return _el$16;
+})();
+
+const template28 = (() => {
+ const _el$17 = _tmpl$.cloneNode(true);
+
+ _$insert(_el$17, () => state.dynamic ?? _$createComponent(Comp, {}));
+
+ return _el$17;
+})();
+
+const template29 = (() => {
+ const _el$18 = _tmpl$.cloneNode(true);
+
+ _$insert(
+ _el$18,
+ (() => {
+ const _c$10 = _$memo(() => !!thing(), true);
+
+ return () => (_c$10() && thing1()) ?? thing2() ?? thing3();
+ })()
+ );
+
+ return _el$18;
+})();
+
+const template30 = (() => {
+ const _el$19 = _tmpl$.cloneNode(true);
+
+ _$insert(_el$19, () => thing() || thing1() || thing2());
+
+ return _el$19;
+})();
+
+const template31 = _$createComponent(Comp, {
+ get value() {
+ return _$memo(() => !!count(), true)()
+ ? _$memo(() => !!count(), true)()
+ ? count()
+ : count()
+ : count();
+ },
+});
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/customElements/code.js b/integration/bunjs-only-snippets/solid-dom-fixtures/customElements/code.js
new file mode 100644
index 000000000..f2e2bd02d
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/customElements/code.js
@@ -0,0 +1,29 @@
+const template = (
+ <my-element
+ some-attr={name}
+ notProp={data}
+ attr:my-attr={data}
+ prop:someProp={data}
+ />
+);
+
+const template2 = (
+ <my-element
+ some-attr={state.name}
+ notProp={state.data}
+ attr:my-attr={state.data}
+ prop:someProp={state.data}
+ />
+);
+
+const template3 = (
+ <my-element>
+ <header slot="head">Title</header>
+ </my-element>
+);
+
+const template4 = (
+ <>
+ <slot name="head"></slot>
+ </>
+);
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/customElements/output.bun.js b/integration/bunjs-only-snippets/solid-dom-fixtures/customElements/output.bun.js
new file mode 100644
index 000000000..79c46280c
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/customElements/output.bun.js
@@ -0,0 +1,27 @@
+var _tmpl = _template$("<my-element/>", 0), _tmpl$2 = _template$('<my-element><header slot="head">Title</header></my-element>', 4);
+const template = () => {
+ var _el = _tmpl.cloneNode(true);
+ setAttribute(_el, "some-attr", name);
+ setAttribute(_el, "notProp", data);
+ setAttribute(_el, "attr:my-attr", data);
+ setAttribute(_el, "prop:someProp", data);
+ return _el;
+};
+const template2 = () => {
+ var _el = _tmpl.cloneNode(true);
+ effect(() => {
+ return setAttribute(_el, "some-attr", state.name);
+ });
+ effect(() => {
+ return setAttribute(_el, "notProp", state.data);
+ });
+ effect(() => {
+ return setAttribute(_el, "attr:my-attr", state.data);
+ });
+ effect(() => {
+ return setAttribute(_el, "prop:someProp", state.data);
+ });
+ return _el;
+};
+const template3 = _tmpl$2.cloneNode(true);
+const template4 = ;
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/customElements/output.js b/integration/bunjs-only-snippets/solid-dom-fixtures/customElements/output.js
new file mode 100644
index 000000000..79274ce2c
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/customElements/output.js
@@ -0,0 +1,66 @@
+import { template as _$template } from "r-dom";
+import { effect as _$effect } from "r-dom";
+import { getOwner as _$getOwner } from "r-dom";
+import { setAttribute as _$setAttribute } from "r-dom";
+
+const _tmpl$ = /*#__PURE__*/ _$template(`<my-element></my-element>`, 2),
+ _tmpl$2 = /*#__PURE__*/ _$template(
+ `<my-element><header slot="head">Title</header></my-element>`,
+ 4
+ ),
+ _tmpl$3 = /*#__PURE__*/ _$template(`<slot name="head"></slot>`, 2);
+
+const template = (() => {
+ const _el$ = document.importNode(_tmpl$, true);
+
+ _el$.someAttr = name;
+ _el$.notprop = data;
+
+ _$setAttribute(_el$, "my-attr", data);
+
+ _el$.someProp = data;
+ _el$._$owner = _$getOwner();
+ return _el$;
+})();
+
+const template2 = (() => {
+ const _el$2 = document.importNode(_tmpl$, true);
+
+ _el$2._$owner = _$getOwner();
+
+ _$effect(
+ (_p$) => {
+ const _v$ = state.name,
+ _v$2 = state.data,
+ _v$3 = state.data,
+ _v$4 = state.data;
+ _v$ !== _p$._v$ && (_el$2.someAttr = _p$._v$ = _v$);
+ _v$2 !== _p$._v$2 && (_el$2.notprop = _p$._v$2 = _v$2);
+ _v$3 !== _p$._v$3 && _$setAttribute(_el$2, "my-attr", (_p$._v$3 = _v$3));
+ _v$4 !== _p$._v$4 && (_el$2.someProp = _p$._v$4 = _v$4);
+ return _p$;
+ },
+ {
+ _v$: undefined,
+ _v$2: undefined,
+ _v$3: undefined,
+ _v$4: undefined,
+ }
+ );
+
+ return _el$2;
+})();
+
+const template3 = (() => {
+ const _el$3 = document.importNode(_tmpl$2, true);
+
+ _el$3._$owner = _$getOwner();
+ return _el$3;
+})();
+
+const template4 = (() => {
+ const _el$4 = _tmpl$3.cloneNode(true);
+
+ _el$4._$owner = _$getOwner();
+ return _el$4;
+})();
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/eventExpressions/code.js b/integration/bunjs-only-snippets/solid-dom-fixtures/eventExpressions/code.js
new file mode 100644
index 000000000..78bc5e199
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/eventExpressions/code.js
@@ -0,0 +1,32 @@
+function hoisted1() {
+ console.log("hoisted");
+}
+const hoisted2 = () => console.log("hoisted delegated");
+
+const template = (
+ <div id="main">
+ <button onchange={() => console.log("bound")}>Change Bound</button>
+ <button onChange={[(id) => console.log("bound", id), id]}>
+ Change Bound
+ </button>
+ <button onchange={handler}>Change Bound</button>
+ <button onchange={[handler]}>Change Bound</button>
+ <button onchange={hoisted1}>Change Bound</button>
+ <button onclick={() => console.log("delegated")}>Click Delegated</button>
+ <button onClick={[(id) => console.log("delegated", id), rowId]}>
+ Click Delegated
+ </button>
+ <button onClick={handler}>Click Delegated</button>
+ <button onClick={[handler]}>Click Delegated</button>
+ <button onClick={hoisted2}>Click Delegated</button>
+ <button
+ on:click={() => console.log("listener")}
+ on:CAPS-ev={() => console.log("custom")}
+ >
+ Click Listener
+ </button>
+ <button oncapture:camelClick={() => console.log("listener")}>
+ Click Capture
+ </button>
+ </div>
+);
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/eventExpressions/output.bun.js b/integration/bunjs-only-snippets/solid-dom-fixtures/eventExpressions/output.bun.js
new file mode 100644
index 000000000..5d90654f9
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/eventExpressions/output.bun.js
@@ -0,0 +1,57 @@
+var _tmpl$1 = _template$(
+ '<div id="main"><button>Change Bound</button><button>Change Bound</button><button>Change Bound</button><button>Change Bound</button><button>Change Bound</button><button>Click Delegated</button><button>Click Delegated</button><button>Click Delegated</button><button>Click Delegated</button><button>Click Delegated</button><button>Click Listener</button><button>Click Capture</button></div>',
+ 26
+);
+function hoisted1() {
+ console.log("hoisted");
+}
+const hoisted2 = () => console.log("hoisted delegated");
+const template = () => {
+ var _el = _tmpl.cloneNode(true),
+ _el$1 = _el.firstChild,
+ _el$2 = _el$1.nextSibling,
+ _el$3 = _el$2.nextSibling,
+ _el$4 = _el$3.nextSibling,
+ _el$5 = _el$4.nextSibling,
+ _el$6 = _el$5.nextSibling,
+ _el$7 = _el$6.nextSibling,
+ _el$8 = _el$7.nextSibling,
+ _el$9 = _el$8.nextSibling,
+ _el$10 = _el$9.nextSibling,
+ _el$11 = _el$10.nextSibling;
+ effect(() => {
+ return setAttribute(_el, "onchange", () => console.log("bound"));
+ });
+ effect(() => {
+ return setAttribute(_el$1, "onChange", [
+ (id) => console.log("bound", id),
+ id,
+ ]);
+ });
+ setAttribute(_el$2, "onchange", handler);
+ effect(() => {
+ return setAttribute(_el$3, "onchange", [handler]);
+ });
+ setAttribute(_el$4, "onchange", hoisted1);
+ _el$5.$$click = () => console.log("delegated");
+ effect(() => {
+ return (_el$6.$$click = [(id) => console.log("delegated", id), rowId]);
+ });
+ effect(() => {
+ return (_el$7.$$click = handler);
+ });
+ effect(() => {
+ return (_el$8.$$click = [handler]);
+ });
+ effect(() => {
+ return (_el$9.$$click = hoisted2);
+ });
+ _el$10.addEventListener("click", () => console.log("listener"));
+ _el$10.addEventListener("CAPS-ev", () => console.log("custom"));
+ _el$11.addEventListener(
+ "apture:camelClick",
+ () => console.log("listener"),
+ true
+ );
+ return _el;
+};
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/eventExpressions/output.js b/integration/bunjs-only-snippets/solid-dom-fixtures/eventExpressions/output.js
new file mode 100644
index 000000000..c24a1f89f
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/eventExpressions/output.js
@@ -0,0 +1,63 @@
+import { template as _$template } from "r-dom";
+import { delegateEvents as _$delegateEvents } from "r-dom";
+import { addEventListener as _$addEventListener } from "r-dom";
+
+const _tmpl$ = /*#__PURE__*/ _$template(
+ `<div id="main"><button>Change Bound</button><button>Change Bound</button><button>Change Bound</button><button>Change Bound</button><button>Change Bound</button><button>Click Delegated</button><button>Click Delegated</button><button>Click Delegated</button><button>Click Delegated</button><button>Click Delegated</button><button>Click Listener</button><button>Click Capture</button></div>`,
+ 26
+);
+
+function hoisted1() {
+ console.log("hoisted");
+}
+
+const hoisted2 = () => console.log("hoisted delegated");
+
+const template = (() => {
+ const _el$ = _tmpl$.cloneNode(true),
+ _el$2 = _el$.firstChild,
+ _el$3 = _el$2.nextSibling,
+ _el$4 = _el$3.nextSibling,
+ _el$5 = _el$4.nextSibling,
+ _el$6 = _el$5.nextSibling,
+ _el$7 = _el$6.nextSibling,
+ _el$8 = _el$7.nextSibling,
+ _el$9 = _el$8.nextSibling,
+ _el$10 = _el$9.nextSibling,
+ _el$11 = _el$10.nextSibling,
+ _el$12 = _el$11.nextSibling,
+ _el$13 = _el$12.nextSibling;
+
+ _el$2.addEventListener("change", () => console.log("bound"));
+
+ _el$3.addEventListener("change", (e) =>
+ ((id) => console.log("bound", id))(id, e)
+ );
+
+ _$addEventListener(_el$4, "change", handler);
+
+ _el$5.addEventListener("change", handler);
+
+ _el$6.addEventListener("change", hoisted1);
+
+ _el$7.$$click = () => console.log("delegated");
+
+ _el$8.$$click = (id) => console.log("delegated", id);
+
+ _el$8.$$clickData = rowId;
+
+ _$addEventListener(_el$9, "click", handler, true);
+
+ _el$10.$$click = handler;
+ _el$11.$$click = hoisted2;
+
+ _el$12.addEventListener("click", () => console.log("listener"));
+
+ _el$12.addEventListener("CAPS-ev", () => console.log("custom"));
+
+ _el$13.addEventListener("camelClick", () => console.log("listener"), true);
+
+ return _el$;
+})();
+
+_$delegateEvents(["click"]);
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/fragments/code.js b/integration/bunjs-only-snippets/solid-dom-fixtures/fragments/code.js
new file mode 100644
index 000000000..0b6021e44
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/fragments/code.js
@@ -0,0 +1,83 @@
+const multiStatic = (
+ <>
+ <div>First</div>
+ <div>Last</div>
+ </>
+);
+
+const multiExpression = (
+ <>
+ <div>First</div>
+ {inserted}
+ <div>Last</div>
+ After
+ </>
+);
+
+const multiDynamic = (
+ <>
+ <div id={state.first}>First</div>
+ {state.inserted}
+ <div id={state.last}>Last</div>
+ After
+ </>
+);
+
+const singleExpression = <>{inserted}</>;
+
+const singleDynamic = <>{inserted()}</>;
+
+const firstStatic = (
+ <>
+ {inserted}
+ <div />
+ </>
+);
+
+const firstDynamic = (
+ <>
+ {inserted()}
+ <div />
+ </>
+);
+
+const firstComponent = (
+ <>
+ <Component />
+ <div />
+ </>
+);
+
+const lastStatic = (
+ <>
+ <div />
+ {inserted}
+ </>
+);
+
+const lastDynamic = (
+ <>
+ <div />
+ {inserted()}
+ </>
+);
+
+const lastComponent = (
+ <>
+ <div />
+ <Component />
+ </>
+);
+
+const spaces = (
+ <>
+ <span>1</span> <span>2</span> <span>3</span>
+ </>
+);
+const multiLineTrailing = (
+ <>
+ <span>1</span>
+ <span>2</span>
+ <span>3</span>
+ </>
+);
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/fragments/output.bun.js b/integration/bunjs-only-snippets/solid-dom-fixtures/fragments/output.bun.js
new file mode 100644
index 000000000..54d980cee
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/fragments/output.bun.js
@@ -0,0 +1,13 @@
+const multiStatic = ;
+const multiExpression = ;
+const multiDynamic = ;
+const singleExpression = ;
+const singleDynamic = ;
+const firstStatic = ;
+const firstDynamic = ;
+const firstComponent = ;
+const lastStatic = ;
+const lastDynamic = ;
+const lastComponent = ;
+const spaces = ;
+const multiLineTrailing = ;
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/fragments/output.js b/integration/bunjs-only-snippets/solid-dom-fixtures/fragments/output.js
new file mode 100644
index 000000000..5fe0c767c
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/fragments/output.js
@@ -0,0 +1,66 @@
+import { template as _$template } from "r-dom";
+import { createComponent as _$createComponent } from "r-dom";
+import { memo as _$memo } from "r-dom";
+import { setAttribute as _$setAttribute } from "r-dom";
+import { effect as _$effect } from "r-dom";
+
+const _tmpl$ = /*#__PURE__*/ _$template(`<div>First</div>`, 2),
+ _tmpl$2 = /*#__PURE__*/ _$template(`<div>Last</div>`, 2),
+ _tmpl$3 = /*#__PURE__*/ _$template(`<div></div>`, 2),
+ _tmpl$4 = /*#__PURE__*/ _$template(`<span>1</span>`, 2),
+ _tmpl$5 = /*#__PURE__*/ _$template(`<span>2</span>`, 2),
+ _tmpl$6 = /*#__PURE__*/ _$template(`<span>3</span>`, 2);
+
+const multiStatic = [_tmpl$.cloneNode(true), _tmpl$2.cloneNode(true)];
+const multiExpression = [
+ _tmpl$.cloneNode(true),
+ inserted,
+ _tmpl$2.cloneNode(true),
+ "After",
+];
+const multiDynamic = [
+ (() => {
+ const _el$5 = _tmpl$.cloneNode(true);
+
+ _$effect(() => _$setAttribute(_el$5, "id", state.first));
+
+ return _el$5;
+ })(),
+ _$memo(() => state.inserted),
+ (() => {
+ const _el$6 = _tmpl$2.cloneNode(true);
+
+ _$effect(() => _$setAttribute(_el$6, "id", state.last));
+
+ return _el$6;
+ })(),
+ "After",
+];
+const singleExpression = inserted;
+
+const singleDynamic = _$memo(inserted);
+
+const firstStatic = [inserted, _tmpl$3.cloneNode(true)];
+const firstDynamic = [_$memo(inserted), _tmpl$3.cloneNode(true)];
+const firstComponent = [
+ _$createComponent(Component, {}),
+ _tmpl$3.cloneNode(true),
+];
+const lastStatic = [_tmpl$3.cloneNode(true), inserted];
+const lastDynamic = [_tmpl$3.cloneNode(true), _$memo(inserted)];
+const lastComponent = [
+ _tmpl$3.cloneNode(true),
+ _$createComponent(Component, {}),
+];
+const spaces = [
+ _tmpl$4.cloneNode(true),
+ " ",
+ _tmpl$5.cloneNode(true),
+ " ",
+ _tmpl$6.cloneNode(true),
+];
+const multiLineTrailing = [
+ _tmpl$4.cloneNode(true),
+ _tmpl$5.cloneNode(true),
+ _tmpl$6.cloneNode(true),
+];
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/insertChildren/code.js b/integration/bunjs-only-snippets/solid-dom-fixtures/insertChildren/code.js
new file mode 100644
index 000000000..41d3d017e
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/insertChildren/code.js
@@ -0,0 +1,36 @@
+const children = <div />;
+const dynamic = {
+ children,
+};
+const template = <Module children={children} />;
+const template2 = <module children={children} />;
+const template3 = <module children={children}>Hello</module>;
+const template4 = (
+ <module children={children}>
+ <Hello />
+ </module>
+);
+const template5 = <module children={dynamic.children} />;
+const template6 = <Module children={dynamic.children} />;
+const template7 = <module {...dynamic} />;
+const template8 = <module {...dynamic}>Hello</module>;
+const template9 = <module {...dynamic}>{dynamic.children}</module>;
+const template10 = <Module {...dynamic}>Hello</Module>;
+const template11 = <module children={/*@once*/ state.children} />;
+const template12 = <Module children={/*@once*/ state.children} />;
+const template13 = <module>{...children}</module>;
+const template14 = <Module>{...children}</Module>;
+const template15 = <module>{...dynamic.children}</module>;
+const template16 = <Module>{...dynamic.children}</Module>;
+const template18 = <module>Hi {...children}</module>;
+const template19 = <Module>Hi {...children}</Module>;
+const template20 = <module>{children()}</module>;
+const template21 = <Module>{children()}</Module>;
+const template22 = <module>{state.children()}</module>;
+const template23 = <Module>{state.children()}</Module>;
+
+const tiles = [];
+tiles.push(<div>Test 1</div>);
+const template24 = <div>{tiles}</div>;
+
+const comma = <div>{(expression(), "static")}</div>;
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/insertChildren/output.js b/integration/bunjs-only-snippets/solid-dom-fixtures/insertChildren/output.js
new file mode 100644
index 000000000..9ad937742
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/insertChildren/output.js
@@ -0,0 +1,185 @@
+import { template as _$template } from "r-dom";
+import { mergeProps as _$mergeProps } from "r-dom";
+import { spread as _$spread } from "r-dom";
+import { insert as _$insert } from "r-dom";
+import { createComponent as _$createComponent } from "r-dom";
+
+const _tmpl$ = /*#__PURE__*/ _$template(`<div></div>`, 2),
+ _tmpl$2 = /*#__PURE__*/ _$template(`<module></module>`, 2),
+ _tmpl$3 = /*#__PURE__*/ _$template(`<module>Hello</module>`, 2),
+ _tmpl$4 = /*#__PURE__*/ _$template(`<module>Hi </module>`, 2),
+ _tmpl$5 = /*#__PURE__*/ _$template(`<div>Test 1</div>`, 2);
+
+const children = _tmpl$.cloneNode(true);
+
+const dynamic = {
+ children,
+};
+
+const template = _$createComponent(Module, {
+ children: children,
+});
+
+const template2 = (() => {
+ const _el$2 = _tmpl$2.cloneNode(true);
+
+ _$insert(_el$2, children);
+
+ return _el$2;
+})();
+
+const template3 = _tmpl$3.cloneNode(true);
+
+const template4 = (() => {
+ const _el$4 = _tmpl$2.cloneNode(true);
+
+ _$insert(_el$4, _$createComponent(Hello, {}));
+
+ return _el$4;
+})();
+
+const template5 = (() => {
+ const _el$5 = _tmpl$2.cloneNode(true);
+
+ _$insert(_el$5, () => dynamic.children);
+
+ return _el$5;
+})();
+
+const template6 = _$createComponent(Module, {
+ get children() {
+ return dynamic.children;
+ },
+});
+
+const template7 = (() => {
+ const _el$6 = _tmpl$2.cloneNode(true);
+
+ _$spread(_el$6, dynamic, false, false);
+
+ return _el$6;
+})();
+
+const template8 = (() => {
+ const _el$7 = _tmpl$3.cloneNode(true);
+
+ _$spread(_el$7, dynamic, false, true);
+
+ return _el$7;
+})();
+
+const template9 = (() => {
+ const _el$8 = _tmpl$2.cloneNode(true);
+
+ _$spread(_el$8, dynamic, false, true);
+
+ _$insert(_el$8, () => dynamic.children);
+
+ return _el$8;
+})();
+
+const template10 = _$createComponent(
+ Module,
+ _$mergeProps(dynamic, {
+ children: "Hello",
+ })
+);
+
+const template11 = (() => {
+ const _el$9 = _tmpl$2.cloneNode(true);
+
+ _$insert(_el$9, state.children);
+
+ return _el$9;
+})();
+
+const template12 = _$createComponent(Module, {
+ children: state.children,
+});
+
+const template13 = (() => {
+ const _el$10 = _tmpl$2.cloneNode(true);
+
+ _$insert(_el$10, children);
+
+ return _el$10;
+})();
+
+const template14 = _$createComponent(Module, {
+ children: children,
+});
+
+const template15 = (() => {
+ const _el$11 = _tmpl$2.cloneNode(true);
+
+ _$insert(_el$11, () => dynamic.children);
+
+ return _el$11;
+})();
+
+const template16 = _$createComponent(Module, {
+ get children() {
+ return dynamic.children;
+ },
+});
+
+const template18 = (() => {
+ const _el$12 = _tmpl$4.cloneNode(true);
+
+ _$insert(_el$12, children, null);
+
+ return _el$12;
+})();
+
+const template19 = _$createComponent(Module, {
+ get children() {
+ return ["Hi ", children];
+ },
+});
+
+const template20 = (() => {
+ const _el$13 = _tmpl$2.cloneNode(true);
+
+ _$insert(_el$13, children);
+
+ return _el$13;
+})();
+
+const template21 = _$createComponent(Module, {
+ get children() {
+ return children();
+ },
+});
+
+const template22 = (() => {
+ const _el$14 = _tmpl$2.cloneNode(true);
+
+ _$insert(_el$14, () => state.children());
+
+ return _el$14;
+})();
+
+const template23 = _$createComponent(Module, {
+ get children() {
+ return state.children();
+ },
+});
+
+const tiles = [];
+tiles.push(_tmpl$5.cloneNode(true));
+
+const template24 = (() => {
+ const _el$16 = _tmpl$.cloneNode(true);
+
+ _$insert(_el$16, tiles);
+
+ return _el$16;
+})();
+
+const comma = (() => {
+ const _el$17 = _tmpl$.cloneNode(true);
+
+ _$insert(_el$17, () => (expression(), "static"));
+
+ return _el$17;
+})();
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/namespaceElements/code.js b/integration/bunjs-only-snippets/solid-dom-fixtures/namespaceElements/code.js
new file mode 100644
index 000000000..7ad410329
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/namespaceElements/code.js
@@ -0,0 +1,6 @@
+const template = <module.A />;
+const template2 = <module.a.B />;
+const template3 = <module.A.B />;
+const template4 = <module.a-b />;
+const template5 = <module.a-b.c-d />;
+const template6 = <namespace:tag />;
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/namespaceElements/output.js b/integration/bunjs-only-snippets/solid-dom-fixtures/namespaceElements/output.js
new file mode 100644
index 000000000..162ffb140
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/namespaceElements/output.js
@@ -0,0 +1,16 @@
+import { template as _$template } from "r-dom";
+import { createComponent as _$createComponent } from "r-dom";
+
+const _tmpl$ = /*#__PURE__*/ _$template(`<namespace:tag></namespace:tag>`, 2);
+
+const template = _$createComponent(module.A, {});
+
+const template2 = _$createComponent(module.a.B, {});
+
+const template3 = _$createComponent(module.A.B, {});
+
+const template4 = _$createComponent(module["a-b"], {});
+
+const template5 = _$createComponent(module["a-b"]["c-d"], {});
+
+const template6 = _tmpl$.cloneNode(true);
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/simpleElements/code.js b/integration/bunjs-only-snippets/solid-dom-fixtures/simpleElements/code.js
new file mode 100644
index 000000000..c3537ee7d
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/simpleElements/code.js
@@ -0,0 +1,9 @@
+const template = (
+ <div id="main">
+ <style>{"div { color: red; }"}</style>
+ <h1>Welcome</h1>
+ <label for={"entry"}>Edit:</label>
+ <input id="entry" type="text" />
+ {/* Comment Node */}
+ </div>
+);
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/simpleElements/output.bun.js b/integration/bunjs-only-snippets/solid-dom-fixtures/simpleElements/output.bun.js
new file mode 100644
index 000000000..72d61c1e3
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/simpleElements/output.bun.js
@@ -0,0 +1,5 @@
+var _tmpl$1 = _template$(
+ '<div id="main"><style>div { color: red; }</style><h1>Welcome</h1><label for="entry">Edit:</label><input id="entry" type="text"/></div>',
+ 8
+);
+const template = _tmpl$1.cloneNode(true);
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/simpleElements/output.js b/integration/bunjs-only-snippets/solid-dom-fixtures/simpleElements/output.js
new file mode 100644
index 000000000..5d16f6767
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/simpleElements/output.js
@@ -0,0 +1,8 @@
+import { template as _$template } from "r-dom";
+
+const _tmpl$ = /*#__PURE__*/ _$template(
+ `<div id="main"><style>div { color: red; }</style><h1>Welcome</h1><label for="entry">Edit:</label><input id="entry" type="text"></div>`,
+ 9
+);
+
+const template = _tmpl$.cloneNode(true);
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/textInterpolation/code.js b/integration/bunjs-only-snippets/solid-dom-fixtures/textInterpolation/code.js
new file mode 100644
index 000000000..21698ea89
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/textInterpolation/code.js
@@ -0,0 +1,72 @@
+const trailing = <span>Hello </span>;
+const leading = <span> John</span>;
+
+/* prettier-ignore */
+const extraSpaces = <span>Hello John</span>;
+
+const trailingExpr = <span>Hello {name}</span>;
+const leadingExpr = <span>{greeting} John</span>;
+
+/* prettier-ignore */
+const multiExpr = <span>{greeting} {name}</span>;
+
+/* prettier-ignore */
+const multiExprSpaced = <span> {greeting} {name} </span>;
+
+/* prettier-ignore */
+const multiExprTogether = <span> {greeting}{name} </span>;
+
+/* prettier-ignore */
+const multiLine = <span>
+
+ Hello
+
+</span>
+
+/* prettier-ignore */
+const multiLineTrailingSpace = <span>
+ Hello
+ John
+</span>
+
+/* prettier-ignore */
+const multiLineNoTrailingSpace = <span>
+ Hello
+ John
+</span>
+
+/* prettier-ignore */
+const escape = <span>
+ &nbsp;&lt;Hi&gt;&nbsp;
+</span>
+
+/* prettier-ignore */
+const escape2 = <Comp>
+ &nbsp;&lt;Hi&gt;&nbsp;
+</Comp>
+
+/* prettier-ignore */
+const escape3 = <>
+ &nbsp;&lt;Hi&gt;&nbsp;
+</>
+
+const injection = <span>Hi{"<script>alert();</script>"}</span>;
+
+let value = "World";
+const evaluated = <span>Hello {value + "!"}</span>;
+
+let number = 4 + 5;
+const evaluatedNonString = <span>4 + 5 = {number}</span>;
+
+const newLineLiteral = (
+ <div>
+ {s}
+ {"\n"}d
+ </div>
+);
+
+const trailingSpace = <div>{expr}</div>;
+
+const trailingSpaceComp = <Comp>{expr}</Comp>;
+
+const trailingSpaceFrag = <>{expr}</>;
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/textInterpolation/output.bun.js b/integration/bunjs-only-snippets/solid-dom-fixtures/textInterpolation/output.bun.js
new file mode 100644
index 000000000..eb4c5347a
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/textInterpolation/output.bun.js
@@ -0,0 +1,71 @@
+var _tmpl$1 = template("<span>Hello </span>", 2), _tmpl$2 = template("<span> John</span>", 2), _tmpl$3 = template("<span>Hello John</span>", 2), _tmpl$3 = template("<span> </span>", 4), _tmpl$4 = template("<span> </span>", 4), _tmpl$5 = template("<span> </span>", 4), _tmpl$7 = template("<span>Hello</span>", 2), _tmpl$8 = template("<span>Hello John</span>", 2), _tmpl$9 = template("<span> &lt;Hi&gt; </span>", 2), _tmpl$10 = template("<span>Hi&lt;script&gt;alert();&lt;/script&gt;</span>", 2), _tmpl$10 = template("<span>4 + 5 = </span>", 3), _tmpl$11 = template("<div>\nd</div>", 3), _tmpl$12 = template("<div</div>", 2);
+const trailing = _tmpl$1.cloneNode(true);
+const leading = _tmpl$2.cloneNode(true);
+const extraSpaces = _tmpl$3.cloneNode(true);
+const trailingExpr = () => {
+ var _tmpl$1 = _tmpl$1.cloneNode(true);
+ insert(_tmpl$1, name, null);
+ return _tmpl$1;
+};
+const leadingExpr = () => {
+ var _tmpl$2 = _tmpl$2.cloneNode(true);
+ insert(_tmpl$2, greeting, null);
+ return _tmpl$2;
+};
+const multiExpr = () => {
+ var _tmpl$3 = _tmpl$3.cloneNode(true);
+ insert(_tmpl$3, greeting, null);
+ insert(_tmpl$3, name, null);
+ return _tmpl$3;
+};
+const multiExprSpaced = () => {
+ var _tmpl$4 = _tmpl$4.cloneNode(true);
+ insert(_tmpl$4, greeting, null);
+ insert(_tmpl$4, name, null);
+ return _tmpl$4;
+};
+const multiExprTogether = () => {
+ var _tmpl$5 = _tmpl$5.cloneNode(true);
+ insert(_tmpl$5, greeting, null);
+ insert(_tmpl$5, name, null);
+ return _tmpl$5;
+};
+const multiLine = _tmpl$7.cloneNode(true);
+const multiLineTrailingSpace = _tmpl$8.cloneNode(true);
+const multiLineNoTrailingSpace = _tmpl$8.cloneNode(true);
+const escape = _tmpl$9.cloneNode(true);
+const escape2 = createComponent(Comp, {
+ get children: [
+ "\xA0<Hi>\xA0"
+ ]
+});
+const escape3 = ;
+const injection = _tmpl$10.cloneNode(true);
+let value = "World";
+const evaluated = () => {
+ var _tmpl$1 = _tmpl$1.cloneNode(true);
+ insert(_tmpl$1, value + "!", null);
+ return _tmpl$1;
+};
+let number = 4 + 5;
+const evaluatedNonString = () => {
+ var _tmpl$10 = _tmpl$10.cloneNode(true);
+ insert(_tmpl$10, number, null);
+ return _tmpl$10;
+};
+const newLineLiteral = () => {
+ var _tmpl$11 = _tmpl$11.cloneNode(true);
+ insert(_tmpl$11, s, null);
+ return _tmpl$11;
+};
+const trailingSpace = () => {
+ var _tmpl$12 = _tmpl$12.cloneNode(true);
+ insert(_tmpl$12, expr, null);
+ return _tmpl$12;
+};
+const trailingSpaceComp = createComponent(Comp, {
+ get children: [
+ expr
+ ]
+});
+const trailingSpaceFrag = ;
diff --git a/integration/bunjs-only-snippets/solid-dom-fixtures/textInterpolation/output.js b/integration/bunjs-only-snippets/solid-dom-fixtures/textInterpolation/output.js
new file mode 100644
index 000000000..b86a631fb
--- /dev/null
+++ b/integration/bunjs-only-snippets/solid-dom-fixtures/textInterpolation/output.js
@@ -0,0 +1,144 @@
+import { template as _$template } from "r-dom";
+import { createComponent as _$createComponent } from "r-dom";
+import { insert as _$insert } from "r-dom";
+
+const _tmpl$ = /*#__PURE__*/ _$template(`<span>Hello </span>`, 2),
+ _tmpl$2 = /*#__PURE__*/ _$template(`<span> John</span>`, 2),
+ _tmpl$3 = /*#__PURE__*/ _$template(`<span>Hello John</span>`, 2),
+ _tmpl$4 = /*#__PURE__*/ _$template(`<span> </span>`, 2),
+ _tmpl$5 = /*#__PURE__*/ _$template(`<span> <!> <!> </span>`, 4),
+ _tmpl$6 = /*#__PURE__*/ _$template(`<span> <!> </span>`, 3),
+ _tmpl$7 = /*#__PURE__*/ _$template(`<span>Hello</span>`, 2),
+ _tmpl$8 = /*#__PURE__*/ _$template(`<span>&nbsp;&lt;Hi&gt;&nbsp;</span>`, 2),
+ _tmpl$9 = /*#__PURE__*/ _$template(
+ `<span>Hi&lt;script>alert();&lt;/script></span>`,
+ 2
+ ),
+ _tmpl$10 = /*#__PURE__*/ _$template(`<span>Hello World!</span>`, 2),
+ _tmpl$11 = /*#__PURE__*/ _$template(`<span>4 + 5 = 9</span>`, 2),
+ _tmpl$12 = /*#__PURE__*/ _$template(
+ `<div>
+d</div>`,
+ 2
+ ),
+ _tmpl$13 = /*#__PURE__*/ _$template(`<div></div>`, 2);
+
+const trailing = _tmpl$.cloneNode(true);
+
+const leading = _tmpl$2.cloneNode(true);
+/* prettier-ignore */
+
+const extraSpaces = _tmpl$3.cloneNode(true);
+
+const trailingExpr = (() => {
+ const _el$4 = _tmpl$.cloneNode(true),
+ _el$5 = _el$4.firstChild;
+
+ _$insert(_el$4, name, null);
+
+ return _el$4;
+})();
+
+const leadingExpr = (() => {
+ const _el$6 = _tmpl$2.cloneNode(true),
+ _el$7 = _el$6.firstChild;
+
+ _$insert(_el$6, greeting, _el$7);
+
+ return _el$6;
+})();
+/* prettier-ignore */
+
+const multiExpr = (() => {
+ const _el$8 = _tmpl$4.cloneNode(true),
+ _el$9 = _el$8.firstChild;
+
+ _$insert(_el$8, greeting, _el$9);
+
+ _$insert(_el$8, name, null);
+
+ return _el$8;
+})();
+/* prettier-ignore */
+
+const multiExprSpaced = (() => {
+ const _el$10 = _tmpl$5.cloneNode(true),
+ _el$11 = _el$10.firstChild,
+ _el$14 = _el$11.nextSibling,
+ _el$12 = _el$14.nextSibling,
+ _el$15 = _el$12.nextSibling,
+ _el$13 = _el$15.nextSibling;
+
+ _$insert(_el$10, greeting, _el$14);
+
+ _$insert(_el$10, name, _el$15);
+
+ return _el$10;
+})();
+/* prettier-ignore */
+
+const multiExprTogether = (() => {
+ const _el$16 = _tmpl$6.cloneNode(true),
+ _el$17 = _el$16.firstChild,
+ _el$19 = _el$17.nextSibling,
+ _el$18 = _el$19.nextSibling;
+
+ _$insert(_el$16, greeting, _el$19);
+
+ _$insert(_el$16, name, _el$19);
+
+ return _el$16;
+})();
+/* prettier-ignore */
+
+const multiLine = _tmpl$7.cloneNode(true);
+/* prettier-ignore */
+
+const multiLineTrailingSpace = _tmpl$3.cloneNode(true);
+/* prettier-ignore */
+
+const multiLineNoTrailingSpace = _tmpl$3.cloneNode(true);
+/* prettier-ignore */
+
+const escape = _tmpl$8.cloneNode(true);
+/* prettier-ignore */
+
+const escape2 = _$createComponent(Comp, {
+ children: "\xA0<Hi>\xA0"
+});
+/* prettier-ignore */
+
+const escape3 = "\xA0<Hi>\xA0";
+
+const injection = _tmpl$9.cloneNode(true);
+
+let value = "World";
+
+const evaluated = _tmpl$10.cloneNode(true);
+
+let number = 4 + 5;
+
+const evaluatedNonString = _tmpl$11.cloneNode(true);
+
+const newLineLiteral = (() => {
+ const _el$27 = _tmpl$12.cloneNode(true),
+ _el$28 = _el$27.firstChild;
+
+ _$insert(_el$27, s, _el$28);
+
+ return _el$27;
+})();
+
+const trailingSpace = (() => {
+ const _el$29 = _tmpl$13.cloneNode(true);
+
+ _$insert(_el$29, expr);
+
+ return _el$29;
+})();
+
+const trailingSpaceComp = _$createComponent(Comp, {
+ children: expr,
+});
+
+const trailingSpaceFrag = expr;
diff --git a/src/global.zig b/src/global.zig
index e90a1beec..9c506404e 100644
--- a/src/global.zig
+++ b/src/global.zig
@@ -156,3 +156,6 @@ pub fn span(ptr: anytype) std.mem.Span(@TypeOf(ptr)) {
return ptr[0..l];
}
}
+
+pub const IdentityContext = @import("./identity_context.zig").IdentityContext;
+pub const ArrayIdentityContext = @import("./identity_context.zig").ArrayIdentityContext;
diff --git a/src/javascript/jsc/node/node_fs.zig b/src/javascript/jsc/node/node_fs.zig
index a4721d874..2bf1fb685 100644
--- a/src/javascript/jsc/node/node_fs.zig
+++ b/src/javascript/jsc/node/node_fs.zig
@@ -3294,6 +3294,7 @@ pub const NodeFS = struct {
}
var buf = args.data.slice();
+ var written: usize = 0;
while (buf.len > 0) {
switch (Syscall.write(fd, buf)) {
@@ -3302,12 +3303,16 @@ pub const NodeFS = struct {
},
.result => |amt| {
buf = buf[amt..];
+ written += amt;
if (amt == 0) {
break;
}
},
}
}
+
+ _ = this.ftruncate(.{ .fd = fd, .len = @truncate(JSC.WebCore.Blob.SizeType, written) }, .sync);
+
return Maybe(Return.WriteFile).success;
},
else => {},
diff --git a/src/js_ast.zig b/src/js_ast.zig
index 13ba491bf..f9a501537 100644
--- a/src/js_ast.zig
+++ b/src/js_ast.zig
@@ -2291,6 +2291,19 @@ pub const Expr = struct {
loc: logger.Loc,
data: Data,
+ pub fn wrapInArrow(this: Expr, allocator: std.mem.Allocator) !Expr {
+ var stmts = try allocator.alloc(Stmt, 1);
+ stmts[0] = Stmt.alloc(S.Return, S.Return{ .value = this }, this.loc);
+
+ return Expr.init(E.Arrow, E.Arrow{
+ .args = &.{},
+ .body = .{
+ .loc = this.loc,
+ .stmts = stmts,
+ },
+ }, this.loc);
+ }
+
pub fn fromBlob(
blob: *const JSC.WebCore.Blob,
allocator: std.mem.Allocator,
diff --git a/src/js_parser.zig b/src/js_parser.zig
index 1ec5b3840..89a3e82ca 100644
--- a/src/js_parser.zig
+++ b/src/js_parser.zig
@@ -2942,7 +2942,7 @@ pub const Parser = struct {
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 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",
@@ -2957,7 +2957,7 @@ pub const Parser = struct {
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 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) {
@@ -3006,16 +3006,16 @@ pub const Parser = struct {
import_record_ids[0] = import_record_id;
}
- if (p.solid.template_decls.items.len > 0) {
- for (p.solid.template_decls.items) |_, i| {
+ if (p.solid.template_decls.count() > 0) {
+ for (p.solid.template_decls.values()) |val, i| {
declared_symbols[i] = js_ast.DeclaredSymbol{
- .ref = p.solid.template_decls.items[i].binding.data.b_identifier.ref,
+ .ref = val.binding.data.b_identifier.ref,
.is_top_level = true,
};
}
stmts_remain[0] = p.s(
S.Local{
- .decls = p.solid.template_decls.items,
+ .decls = p.solid.template_decls.values(),
},
logger.Loc.Empty,
);
@@ -3332,12 +3332,57 @@ const SolidJS = struct {
setAttribute: GeneratedSymbol = undefined,
effect: GeneratedSymbol = undefined,
- events_to_delegate: Events.Bitset = .{},
- template_decls: std.ArrayListUnmanaged(G.Decl) = .{},
+ 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) = .{},
@@ -3367,10 +3412,10 @@ const SolidJS = struct {
}
pub fn generateTemplateName(this: *SolidJS, allocator: std.mem.Allocator) string {
- if (this.template_decls.items.len <= prefilled_template_names.len) {
- return prefilled_template_names[this.template_decls.items.len];
+ 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.items.len}) catch unreachable;
+ 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 {
@@ -3444,56 +3489,112 @@ const SolidJS = struct {
return element;
}
- pub const Events = enum {
- Click,
- Change,
- Input,
- Submit,
- KeyDown,
- KeyUp,
- KeyPress,
- MouseDown,
- MouseUp,
- MouseMove,
- MouseEnter,
- MouseLeave,
- MouseOver,
- MouseOut,
- Focus,
- Blur,
- Scroll,
- Wheel,
- TouchStart,
- TouchMove,
- TouchEnd,
- TouchCancel,
- PointerDown,
- PointerUp,
- PointerMove,
- PointerCancel,
- PointerEnter,
- PointerLeave,
- PointerOver,
- PointerOut,
- GotPointerCapture,
- LostPointerCapture,
- Select,
- ContextMenu,
- DragStart,
- Drag,
- DragEnd,
- DragEnter,
- DragLeave,
- DragOver,
- Drop,
- Copy,
- Cut,
- Paste,
- CompositionStart,
- CompositionUpdate,
- CompositionEnd,
-
- pub const Bitset = std.enums.EnumSet(Events);
+ 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{
@@ -12423,8 +12524,9 @@ fn NewParser_(
if (only_scan_imports_and_do_not_visit) {
@compileError("only_scan_imports_and_do_not_visit must not run this.");
}
- // Inline to avoid the extra unnecessary function call in the stack
- return @call(.{ .modifier = .always_inline }, P.visitExprInOut, .{ p, expr, ExprIn{} });
+
+ // hopefully this gets tailed
+ return p.visitExprInOut(expr, .{});
}
fn visitFunc(p: *P, _func: G.Fn, open_parens_loc: logger.Loc) G.Fn {
@@ -12711,7 +12813,6 @@ fn NewParser_(
_ = writer.writeString(tag.data.e_string) catch unreachable;
needs_end_bracket = true;
- var wrote_anything = false;
for (jsx_props) |*property, i| {
if (property.kind != .spread) {
property.key = p.visitExpr(e_.properties.ptr[i].key.?);
@@ -12723,116 +12824,179 @@ fn NewParser_(
if (property.kind != .spread) {
var key = property.key.?.data.e_string;
- const is_event_listener = key.hasPrefixComptime("on:");
- const is_class = !is_event_listener and
- // TODO: should this be case-insensitive?
- (key.eqlComptime("class") or key.eqlComptime("className"));
-
- const primitive = property.value.?.knownPrimitive();
- const is_dynamic = !primitive.isStatic();
- const appears_in_template = !is_event_listener and !is_dynamic;
- if (appears_in_template) {
- _ = writer.writeAll(" ") catch unreachable;
- wrote_anything = true;
- }
+ const transform: SolidJS.ExpressionTransform =
+ if (key.isUTF8())
+ SolidJS.ExpressionTransform.which(key.slice(p.allocator))
+ else
+ SolidJS.ExpressionTransform{ .setAttribute = {} };
- if (is_class and !is_dynamic) {
- _ = writer.writeAll("class") catch unreachable;
- } else if (!is_dynamic) {
- _ = writer.writeString(key) catch unreachable;
- }
- if (appears_in_template) {
- switch (primitive) {
- .number, .string => {
- if (property.value.?.data == .e_string) {
- const str = property.value.?.data.e_string;
- if (str.len() > 0) {
- _ = writer.writeAll("=") catch unreachable;
- writer.writeHTMLAttributeValueString(str) catch unreachable;
- }
- } else {
- writer.writer().print("={d}", .{property.value.?.data.e_number.value}) catch unreachable;
- }
- },
- // TODO: should "null" be written?
- // TODO: should "undefined" be written?
- .@"null", .@"undefined" => {},
- .boolean => {
- // existence of an HTML attribute implicitly is true
- // so we only need to write if it's false
- if (!property.value.?.data.e_boolean.value) {
- // TODO: verify that SolidJS writes the same value
- _ = writer.writeAll("=false") catch unreachable;
- }
- },
+ 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 } };
+ }
- else => 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
- 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 (element == null) {
+ element = global_solid.generateElement(
+ p,
+ template_expression,
+ property.value.?.loc,
+ ) catch unreachable;
+ }
}
- var stmt: Stmt = undefined;
- if (!is_event_listener) {
- var args = p.allocator.alloc(Expr, 4) catch unreachable;
- args[0] = p.e(element.?, expr.loc);
- if (is_class) {
- args[1] = p.e(E.String.init("className"), property.key.?.loc);
- } else {
- args[1] = property.key.?;
+ 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.?;
- args[2] = 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,
+ );
- // setAttribute(template_expression, key, value);
- const setAttr = 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,
+ 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.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;
+ }
},
- 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);
- stmt = p.s(S.SExpr{ .value = setAttr }, property.value.?.loc);
- } else {
- var stmts = p.allocator.alloc(Stmt, 1) catch unreachable;
- stmts[0] = p.s(S.Return{ .value = setAttr }, property.value.?.loc);
+ .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;
- args[3] = p.e(
+ 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 = args[2].loc,
+ .loc = out.loc,
},
},
property.value.?.loc,
@@ -12846,45 +13010,22 @@ fn NewParser_(
},
property.value.?.loc,
),
- .args = ExprNodeList.init(args[3..4]),
+ .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);
}
- } else {
- var args = p.allocator.alloc(Expr, 2) 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.?;
- // $element.addEventListener("MyEvent", (e) => { ... });
- const addEventListener = 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);
- stmt = p.s(S.SExpr{ .value = addEventListener }, property.value.?.loc);
+ solid.component_body.append(p.allocator, stmt) catch unreachable;
}
-
- solid.component_body.append(p.allocator, stmt) catch unreachable;
}
- } else {}
+ }
}
if (property.initializer != null) {
@@ -12892,7 +13033,7 @@ fn NewParser_(
}
}
- var wrote_any_children = false;
+ 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;
@@ -12916,7 +13057,6 @@ fn NewParser_(
needs_end_bracket = false;
}
writer.writeHTMLAttributeValueString(str) catch unreachable;
- wrote_any_children = true;
}
},
.e_number => |str| {
@@ -12925,7 +13065,6 @@ fn NewParser_(
needs_end_bracket = false;
}
writer.writer().print("{d}", .{str.value}) catch unreachable;
- wrote_any_children = true;
},
// debug assertion that we don't get here
@@ -12975,7 +13114,7 @@ fn NewParser_(
}
}
- if (wrote_any_children) {
+ if (start_node_count != solid.node_count) {
solid.node_count += 1;
_ = writer.writeAll("</") catch unreachable;
_ = writer.writeString(tag.data.e_string) catch unreachable;
@@ -12996,24 +13135,19 @@ fn NewParser_(
return p.e(E.Missing{}, expr.loc);
}
- var args = p.allocator.alloc(Expr, 2) catch unreachable;
-
+ 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 < 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 if (writer.pos == 0 and writer.context.list.items.len == 0) {
- args[0] = p.e(E.String.init(""), expr.loc);
+ 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 {
- 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);
+ var hasher = std.hash.Wyhash.init(0);
+ hasher.update(writer.context.list.items);
+ hasher.update(writer.buffer[0..writer.pos]);
+ hash = hasher.final();
}
- args[1] = p.e(E.Number{ .value = @intToFloat(f64, solid.node_count) }, expr.loc);
- solid.node_count = 0;
+ 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);
@@ -13028,9 +13162,25 @@ fn NewParser_(
template_expression = .{ .loc = expr.loc, .data = .{ .e_identifier = solid.last_template_id } };
}
- global_solid.template_decls.append(
- p.allocator,
- G.Decl{
+ 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{
@@ -13045,8 +13195,12 @@ fn NewParser_(
},
template_expression.loc,
),
- },
- ) catch unreachable;
+ };
+ } 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
@@ -13101,7 +13255,7 @@ fn NewParser_(
return p.e(E.Missing{}, expr.loc);
}
},
- .e_import_identifier, .e_identifier => {
+ .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| {
@@ -13118,10 +13272,18 @@ fn NewParser_(
}
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;
+ 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 = property.value,
+ .value = if (kind != .get)
+ property.value.?
+ else
+ property.value.?.wrapInArrow(p.allocator) catch unreachable,
+
.kind = kind,
};
out_props_i += 1;
@@ -13131,7 +13293,11 @@ fn NewParser_(
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;
+ 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,
diff --git a/src/string_immutable.zig b/src/string_immutable.zig
index c6bfdbc65..b27a0f820 100644
--- a/src/string_immutable.zig
+++ b/src/string_immutable.zig
@@ -549,6 +549,10 @@ pub fn eqlComptimeIgnoreLen(self: string, comptime alt: anytype) bool {
return eqlComptimeCheckLenWithType(u8, self, alt, false);
}
+pub fn hasPrefixComptime(self: string, comptime alt: anytype) bool {
+ return self.len >= alt.len and eqlComptimeCheckLenWithType(u8, self[0..alt.len], alt, false);
+}
+
pub inline fn eqlComptimeCheckLenWithType(comptime Type: type, a: []const Type, comptime b: anytype, comptime check_len: bool) bool {
@setEvalBranchQuota(9999);
if (comptime check_len) {