diff options
37 files changed, 3469 insertions, 217 deletions
@@ -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="<div/>"/></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> + <Hi> +</span> + +/* prettier-ignore */ +const escape2 = <Comp> + <Hi> +</Comp> + +/* prettier-ignore */ +const escape3 = <> + <Hi> +</> + +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>Â <Hi>Â </span>", 2), _tmpl$10 = template("<span>Hi<script>alert();</script></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> <Hi> </span>`, 2), + _tmpl$9 = /*#__PURE__*/ _$template( + `<span>Hi<script>alert();</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) { |