Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/universal-spread-sources.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@solidjs/universal": patch
"@solidjs/babel-plugin": patch
"@solidjs/compiler": patch
---

The universal renderer's `spread()` follows the `@solidjs/web` contract (#3388): `ref` folds into the props effect and is re-applied only when its identity changes (refs run with no owner, so nothing they create is disposed by the fold); children keep their own owned `insert` — that effect owns the child subtree — but a plain object whose `children` is a data property inserts the value with no effect at all. Three reactive nodes become two when children flow through the spread, one when they don't. `spread` also resolves a lone function source inside its own tracking scopes and accepts an array of sources — `spread(node, [a, b], skipChildren)` — the union of their keys with later sources winning, only the winning source read, function sources called inline with no merge and no memo. Both compilers' universal output uses it: a lone spread passes straight through (reactive included, no more `mergeProps(() => …)`), and several sources compile to the array instead of a `mergeProps()` call.
14 changes: 8 additions & 6 deletions packages/babel-plugin/src/universal/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,6 @@ function processSpreads(
const filteredAttributes: JSXAttributePath[] = [];
const spreadArgs: t.Expression[] = [];
let runningObject: Array<t.ObjectProperty | t.ObjectMethod> = [];
let dynamicSpread = false;
let firstSpread = false;
attributes.forEach(attribute => {
const node = attribute.node;
Expand All @@ -417,7 +416,7 @@ function processSpreads(
spreadArgs.push(
isDynamic(attribute.get("argument"), {
checkMember: true
}) && (dynamicSpread = true)
})
? t.isCallExpression(node.argument) &&
!node.argument.arguments.length &&
!t.isCallExpression(node.argument.callee) &&
Expand Down Expand Up @@ -475,10 +474,13 @@ function processSpreads(
spreadArgs.push(t.objectExpression(runningObject));
}

const props =
spreadArgs.length === 1 && !dynamicSpread
? spreadArgs[0]
: t.callExpression(registerImportMethod(path, "mergeProps"), spreadArgs);
// A lone spread — reactive included — passes straight through: the
// renderer's spread() resolves a function source inside its own tracking
// scopes. Several sources go as an ARRAY, not a mergeProps() call: spread()
// reads the sources directly (later wins per key, only the winner read)
// with no merge proxy to build and walk, and a reactive source is called
// inline with no memo. Same contract as the dom generate.
const props = spreadArgs.length === 1 ? spreadArgs[0] : t.arrayExpression(spreadArgs);

return [
filteredAttributes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { ref as _$ref } from "r-custom";
import { createElement as _$createElement } from "r-custom";
import { setProp as _$setProp } from "r-custom";
import { spread as _$spread } from "r-custom";
import { mergeProps as _$mergeProps } from "r-custom";
import { binding } from "somewhere";
function refFn() {}
const refConst = null;
Expand All @@ -21,39 +20,45 @@ _$insertNode(_el$, _el$2);
_$setProp(_el$, "id", "main");
_$spread(
_el$,
_$mergeProps(results, {
style: {
color
[
results,
{
style: {
color
}
}
}),
],
true
);
_$insertNode(_el$2, _el$3);
_$setProp(_el$2, "class", "base");
_$spread(
_el$2,
_$mergeProps(results, {
disabled: true,
readonly: "",
get title() {
return welcoming();
},
get style() {
return {
"background-color": color(),
"margin-right": "40px"
};
},
get ["class"]() {
return [
"base",
{
dynamic: dynamic(),
selected
}
];
[
results,
{
disabled: true,
readonly: "",
get title() {
return welcoming();
},
get style() {
return {
"background-color": color(),
"margin-right": "40px"
};
},
get ["class"]() {
return [
"base",
{
dynamic: dynamic(),
selected
}
];
}
}
}),
],
true
);
_$insertNode(_el$3, _$createTextNode(`Welcome`));
Expand All @@ -71,11 +76,7 @@ var _el$5 = _$createElement("div"),
_$insertNode(_el$5, _el$6);
_$insertNode(_el$5, _el$7);
_$insertNode(_el$5, _el$8);
_$spread(
_el$5,
_$mergeProps(() => getProps("test")),
true
);
_$spread(_el$5, () => getProps("test"), true);
_$effect(
() => row.label,
(_v$, _$p) => {
Expand Down Expand Up @@ -195,11 +196,11 @@ const template17 = _el$22;
var _el$24 = _$createElement("div");
_$spread(
_el$24,
_$mergeProps(() => ({
() => ({
get [key()]() {
return props.value;
}
})),
}),
false
);
const template18 = _el$24;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,25 +119,28 @@ const foldedChildren = _el$23;
var _el$25 = _$createElement("module");
_$spread(
_el$25,
_$mergeProps(
[
{
get children() {
return fallback();
}
},
props
),
],
false
);
const childrenBeforeSpread = _el$25;
var _el$26 = _$createElement("module");
_$spread(
_el$26,
_$mergeProps(props, {
get children() {
return later();
[
props,
{
get children() {
return later();
}
}
}),
],
false
);
const childrenAfterSpread = _el$26;
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { insert as _$insert } from "r-custom";
import { createComponent as _$createComponent } from "r-custom";
import { spread as _$spread } from "r-custom";
import { mergeProps as _$mergeProps } from "r-custom";
import { ref as _$ref } from "r-custom";
import { setProp as _$setProp } from "r-custom";
import { effect as _$effect } from "r-custom";
Expand Down Expand Up @@ -87,13 +86,16 @@ const refValue = _el$9;
var _el$0 = _$createElement("div");
_$spread(
_el$0,
_$mergeProps(props, {
get data() {
var _el$19 = _$createElement("span");
_$insert(_el$19, () => state.value);
return _el$19;
[
props,
{
get data() {
var _el$19 = _$createElement("span");
_$insert(_el$19, () => state.value);
return _el$19;
}
}
}),
],
false
);
const spreadValue = _el$0;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { createTextNode as _$createTextNode } from "r-custom";
import { effect as _$effect } from "r-custom";
import { mergeProps as _$mergeProps } from "r-custom";
import { spread as _$spread } from "r-custom";
import { insertNode as _$insertNode } from "r-custom";
import { setProp as _$setProp } from "r-custom";
Expand All @@ -19,10 +18,10 @@ var _el$3 = _$createElement("a", {
});
_$insertNode(_el$, _el$2);
_$setProp(_el$, "id", "main");
_$spread(_el$, _$mergeProps(results, { style: { color } }), true);
_$spread(_el$, [results, { style: { color } }], true);
_$insertNode(_el$2, _el$3);
_$setProp(_el$2, "class", "base");
_$spread(_el$2, _$mergeProps(results, {
_$spread(_el$2, [results, {
disabled: true,
readonly: "",
get title() {
Expand All @@ -40,7 +39,7 @@ _$spread(_el$2, _$mergeProps(results, {
selected
}];
}
}), true);
}], true);
_$insertNode(_el$3, _$createTextNode("Welcome"));
var _ref$ = link;
typeof _ref$ === "function" || Array.isArray(_ref$) ? _$ref(() => {
Expand All @@ -54,9 +53,9 @@ var _el$7 = _$createElement("div", { innerHTML: "<div/>" });
_$insertNode(_el$4, _el$5);
_$insertNode(_el$4, _el$6);
_$insertNode(_el$4, _el$7);
_$spread(_el$4, _$mergeProps(() => {
_$spread(_el$4, () => {
return getProps("test");
}), true);
}, true);
_$effect(() => row.label, (_v$, _$p) => {
_$setProp(_el$6, "textContent", _v$, _$p);
});
Expand Down Expand Up @@ -141,11 +140,11 @@ var _el$21 = _$createElement("button", {
_$insertNode(_el$21, _$createTextNode("Hi"));
const template17 = _el$21;
var _el$22 = _$createElement("div");
_$spread(_el$22, _$mergeProps(() => {
_$spread(_el$22, () => {
return { get [key()]() {
return props.value;
} };
}), false);
}, false);
const template18 = _el$22;
var _el$23 = _$createElement("div");
_$effect(() => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,12 @@ var _el$21 = _$createElement("module");
_$insertNode(_el$21, _$createTextNode("hello"));
const foldedChildren = _el$21;
var _el$22 = _$createElement("module");
_$spread(_el$22, _$mergeProps({ get children() {
_$spread(_el$22, [{ get children() {
return fallback();
} }, props), false);
} }, props], false);
const childrenBeforeSpread = _el$22;
var _el$23 = _$createElement("module");
_$spread(_el$23, _$mergeProps(props, { get children() {
_$spread(_el$23, [props, { get children() {
return later();
} }), false);
} }], false);
const childrenAfterSpread = _el$23;
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { createTextNode as _$createTextNode } from "r-custom";
import { effect as _$effect } from "r-custom";
import { createComponent as _$createComponent } from "r-custom";
import { mergeProps as _$mergeProps } from "r-custom";
import { spread as _$spread } from "r-custom";
import { insert as _$insert } from "r-custom";
import { insertNode as _$insertNode } from "r-custom";
Expand Down Expand Up @@ -72,13 +71,13 @@ _$ref(() => {
}, _el$8);
const refValue = _el$8;
var _el$10 = _$createElement("div");
_$spread(_el$10, _$mergeProps(props, { get data() {
_$spread(_el$10, [props, { get data() {
var _el$15 = _$createElement("span");
_$insert(_el$15, () => {
return state.value;
});
return _el$15;
} }), false);
} }], false);
const spreadValue = _el$10;
var _el$11 = _$createElement("div");
_$insert(_el$11, _$createComponent(Comp, { get fallback() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { createTextNode as _$createTextNode } from "r-custom";
import { effect as _$effect } from "r-custom";
import { mergeProps as _$mergeProps } from "r-custom";
import { spread as _$spread } from "r-custom";
import { insertNode as _$insertNode } from "r-custom";
import { setProp as _$setProp } from "r-custom";
Expand All @@ -19,10 +18,10 @@ var _el$3 = _$createElement("a", {
});
_$insertNode(_el$, _el$2);
_$setProp(_el$, "id", "main");
_$spread(_el$, _$mergeProps(results, { style: { color } }), true);
_$spread(_el$, [results, { style: { color } }], true);
_$insertNode(_el$2, _el$3);
_$setProp(_el$2, "class", "base");
_$spread(_el$2, _$mergeProps(results, {
_$spread(_el$2, [results, {
disabled: true,
readonly: "",
get title() {
Expand All @@ -40,7 +39,7 @@ _$spread(_el$2, _$mergeProps(results, {
selected
}];
}
}), true);
}], true);
_$insertNode(_el$3, _$createTextNode("Welcome"));
var _ref$ = link;
typeof _ref$ === "function" || Array.isArray(_ref$) ? _$ref(() => {
Expand All @@ -54,9 +53,9 @@ var _el$7 = _$createElement("div", { innerHTML: "<div/>" });
_$insertNode(_el$4, _el$5);
_$insertNode(_el$4, _el$6);
_$insertNode(_el$4, _el$7);
_$spread(_el$4, _$mergeProps(() => {
_$spread(_el$4, () => {
return getProps("test");
}), true);
}, true);
_$effect(() => row.label, (_v$, _$p) => {
_$setProp(_el$6, "textContent", _v$, _$p);
});
Expand Down Expand Up @@ -141,11 +140,11 @@ var _el$21 = _$createElement("button", {
_$insertNode(_el$21, _$createTextNode("Hi"));
const template17 = _el$21;
var _el$22 = _$createElement("div");
_$spread(_el$22, _$mergeProps(() => {
_$spread(_el$22, () => {
return { get [key()]() {
return props.value;
} };
}), false);
}, false);
const template18 = _el$22;
var _el$23 = _$createElement("div");
_$effect(() => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,12 @@ var _el$21 = _$createElement("module");
_$insertNode(_el$21, _$createTextNode("hello"));
const foldedChildren = _el$21;
var _el$22 = _$createElement("module");
_$spread(_el$22, _$mergeProps({ get children() {
_$spread(_el$22, [{ get children() {
return fallback();
} }, props), false);
} }, props], false);
const childrenBeforeSpread = _el$22;
var _el$23 = _$createElement("module");
_$spread(_el$23, _$mergeProps(props, { get children() {
_$spread(_el$23, [props, { get children() {
return later();
} }), false);
} }], false);
const childrenAfterSpread = _el$23;
Loading
Loading