@solidjs/babel-plugin 2.0.0-rc.4 → 2.0.0-rc.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +21 -0
- package/index.js +68 -18
- package/package.json +1 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -7,4 +7,4 @@ src/shared/transform.ts -> src/ssr/element.ts -> src/shared/transform.ts
|
|
|
7
7
|
src/shared/transform.ts -> src/universal/element.ts -> src/shared/transform.ts
|
|
8
8
|
src/shared/transform.ts -> src/shared/component.ts -> src/shared/transform.ts
|
|
9
9
|
src/shared/transform.ts -> src/shared/fragment.ts -> src/shared/transform.ts
|
|
10
|
-
[32mcreated [1mindex.js[22m in [1m2.
|
|
10
|
+
[32mcreated [1mindex.js[22m in [1m2.6s[22m[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @solidjs/babel-plugin
|
|
2
2
|
|
|
3
|
+
## 2.0.0-rc.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 320f1f5: Universal text is text (#3127). The DOM and SSR generators splice static
|
|
8
|
+
text into an HTML template that a parser later unescapes, so they escape
|
|
9
|
+
static values and keep JSX entities as written. The universal generator
|
|
10
|
+
hands strings straight to the host — `createTextNode`, `setProp` — with no
|
|
11
|
+
parser downstream, so the escaping rendered literally (`{"<b>"}` showed as
|
|
12
|
+
`<b>`) and entities never decoded (`<` showed as `<`), leaving no
|
|
13
|
+
spelling that produced a literal `<` in static text under a custom
|
|
14
|
+
renderer. Universal-rendered element children now pass static values
|
|
15
|
+
through unescaped and decode JSX entities in text and string attributes,
|
|
16
|
+
matching what component children and fragment text always did. The flag
|
|
17
|
+
rides on the element, not the config, so `generate: "dynamic"` decides per
|
|
18
|
+
renderer. Applied to both compilers; the attribute half closed ten pinned
|
|
19
|
+
cross-mode parity divergences between them. Reported with the fix mapped
|
|
20
|
+
out by @antoinevanwel.
|
|
21
|
+
- 5230666: Fix hydration ids drifting after a reactive lone spread (#3105). A lone spread now passes its accessor straight to `spread()` on the client — no `mergeProps`, no memo, no hydration id — matching the server's existing pass-through fast path. The runtime resolves a function props source inside its own tracking scopes.
|
|
22
|
+
- e27dc29: `validate` now fails the compile instead of warning when a template's markup would be restructured by the browser's HTML parser (#3099). Once the validator fires the emitted positional walk is guaranteed not to match the browser-built DOM (crashed or silently misplaced bindings; desynced hydration under SSR), so warn-and-emit shipped certain breakage with the diagnostic buried in server logs. Errors now point at the offending JSX (code frame in Babel, line:col in the native compiler). `validate: false` remains the opt-out.
|
|
23
|
+
|
|
3
24
|
## 2.0.0-rc.4
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/index.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
var SyntaxJSX = require('@babel/plugin-syntax-jsx');
|
|
4
4
|
var t$2 = require('@babel/types');
|
|
5
|
-
var helperModuleImports = require('@babel/helper-module-imports');
|
|
6
5
|
var htmlEntities = require('html-entities');
|
|
6
|
+
var helperModuleImports = require('@babel/helper-module-imports');
|
|
7
7
|
|
|
8
8
|
function _interopNamespaceDefault(e) {
|
|
9
9
|
var n = Object.create(null);
|
|
@@ -2725,7 +2725,6 @@ attributes,
|
|
|
2725
2725
|
const filteredAttributes = [];
|
|
2726
2726
|
const spreadArgs = [];
|
|
2727
2727
|
let runningObject = [];
|
|
2728
|
-
let dynamicSpread = false;
|
|
2729
2728
|
attributes.forEach((attribute) => {
|
|
2730
2729
|
const node = attribute.node;
|
|
2731
2730
|
const key =
|
|
@@ -2744,10 +2743,9 @@ attributes,
|
|
|
2744
2743
|
runningObject = [];
|
|
2745
2744
|
}
|
|
2746
2745
|
|
|
2747
|
-
const s =
|
|
2748
|
-
isDynamic(attribute.get("argument"), {
|
|
2746
|
+
const s = isDynamic(attribute.get("argument"), {
|
|
2749
2747
|
checkMember: true
|
|
2750
|
-
})
|
|
2748
|
+
}) ?
|
|
2751
2749
|
inlineCallExpression(node.argument) :
|
|
2752
2750
|
node.argument;
|
|
2753
2751
|
|
|
@@ -2796,8 +2794,12 @@ attributes,
|
|
|
2796
2794
|
spreadArgs.push(t$1.objectExpression(runningObject));
|
|
2797
2795
|
}
|
|
2798
2796
|
|
|
2797
|
+
// A lone spread — reactive included — passes straight through: spread()
|
|
2798
|
+
// resolves a function source inside its own tracking scopes, and merging
|
|
2799
|
+
// one source would mint a memo that consumes a hydration id the SSR fast
|
|
2800
|
+
// path never allocates (#3105).
|
|
2799
2801
|
const props =
|
|
2800
|
-
spreadArgs.length === 1
|
|
2802
|
+
spreadArgs.length === 1 ?
|
|
2801
2803
|
spreadArgs[0] :
|
|
2802
2804
|
t$1.callExpression(registerImportMethod(path, "mergeProps"), spreadArgs);
|
|
2803
2805
|
|
|
@@ -3091,7 +3093,11 @@ function registerTemplate(path, results) {
|
|
|
3091
3093
|
templateWithClosingTags: results.templateWithClosingTags,
|
|
3092
3094
|
isImportNode: results.isImportNode,
|
|
3093
3095
|
isWrapped: results.isWrapped,
|
|
3094
|
-
renderer: "dom"
|
|
3096
|
+
renderer: "dom",
|
|
3097
|
+
// templates dedupe on markup, so the FIRST site carries the blame
|
|
3098
|
+
// for a validate failure (#3099) — good enough: every site with
|
|
3099
|
+
// this markup has the same problem
|
|
3100
|
+
path
|
|
3095
3101
|
});
|
|
3096
3102
|
}
|
|
3097
3103
|
}
|
|
@@ -4841,7 +4847,15 @@ results)
|
|
|
4841
4847
|
t__namespace.jsxExpressionContainer(value || t__namespace.booleanLiteral(true));
|
|
4842
4848
|
}
|
|
4843
4849
|
} else {
|
|
4844
|
-
addStaticAttr(
|
|
4850
|
+
addStaticAttr(
|
|
4851
|
+
attribute,
|
|
4852
|
+
results,
|
|
4853
|
+
initProps,
|
|
4854
|
+
elem,
|
|
4855
|
+
key,
|
|
4856
|
+
decodedAttrValue(value),
|
|
4857
|
+
hasSpread
|
|
4858
|
+
);
|
|
4845
4859
|
}
|
|
4846
4860
|
});
|
|
4847
4861
|
if (spreadExpr) results.exprs.push(spreadExpr);
|
|
@@ -4851,6 +4865,18 @@ results)
|
|
|
4851
4865
|
return initProps;
|
|
4852
4866
|
}
|
|
4853
4867
|
|
|
4868
|
+
// A JSX string attribute prints its `extra.raw` — the source text, entities
|
|
4869
|
+
// included — so `normal="Search…"` reached the host's setProp as the
|
|
4870
|
+
// six raw characters (#3127, same class as text children). The parser
|
|
4871
|
+
// already decoded the entities into `.value` (that decoded form is what the
|
|
4872
|
+
// DOM generator's template parser produces and what component props receive);
|
|
4873
|
+
// rebuild the literal so the host gets the decoded string. Only for the
|
|
4874
|
+
// attribute's own StringLiteral: an expression container's string is a JS
|
|
4875
|
+
// string, where `…` is six literal characters by JS semantics.
|
|
4876
|
+
function decodedAttrValue(value) {
|
|
4877
|
+
return t__namespace.isStringLiteral(value) ? t__namespace.stringLiteral(value.value) : value;
|
|
4878
|
+
}
|
|
4879
|
+
|
|
4854
4880
|
function addStaticAttr(
|
|
4855
4881
|
path,
|
|
4856
4882
|
results,
|
|
@@ -4893,8 +4919,11 @@ value,
|
|
|
4893
4919
|
function transformChildren(path, results) {
|
|
4894
4920
|
const filteredChildren = filterChildren(path.get("children")),
|
|
4895
4921
|
multi = checkLength(filteredChildren),
|
|
4896
|
-
childNodes = filteredChildren
|
|
4897
|
-
|
|
4922
|
+
childNodes = filteredChildren
|
|
4923
|
+
// `universal: true`: this text feeds the host's createTextNode, so the
|
|
4924
|
+
// shared text branch must not HTML-escape it and must decode entities
|
|
4925
|
+
// (#3127) — element-scoped because dynamic mode mixes renderers.
|
|
4926
|
+
.map((path) => transformNode(path, { universal: true })).
|
|
4898
4927
|
reduce((memo, child) => {
|
|
4899
4928
|
if (!child) return memo;
|
|
4900
4929
|
const i = memo.length;
|
|
@@ -5061,7 +5090,7 @@ attributes,
|
|
|
5061
5090
|
t__namespace.stringLiteral(key),
|
|
5062
5091
|
isContainer ?
|
|
5063
5092
|
node.value.expression :
|
|
5064
|
-
node.value || t__namespace.booleanLiteral(true)
|
|
5093
|
+
decodedAttrValue(node.value) || t__namespace.booleanLiteral(true)
|
|
5065
5094
|
)
|
|
5066
5095
|
);
|
|
5067
5096
|
}
|
|
@@ -5795,11 +5824,23 @@ info = {})
|
|
|
5795
5824
|
t__namespace.isJSXText(node) ||
|
|
5796
5825
|
(staticValue = getStaticExpression(path)) !== false)
|
|
5797
5826
|
{
|
|
5827
|
+
// Universal text is text (#3127): the DOM and SSR generators splice this
|
|
5828
|
+
// string into an HTML template that a parser later unescapes, so static
|
|
5829
|
+
// values are escaped and JSXText keeps its source entities. Universal
|
|
5830
|
+
// text goes straight to the host's `createTextNode` with no parser
|
|
5831
|
+
// downstream — what is written here is what renders — so static values
|
|
5832
|
+
// pass through unescaped and JSX entities decode, exactly as text
|
|
5833
|
+
// reaching a component child already did (component.ts, fragment.ts).
|
|
5834
|
+
// `info.universal` marks children of a universal-rendered element, which
|
|
5835
|
+
// in `generate: "dynamic"` is a per-element fact, not a config-wide one.
|
|
5836
|
+
const universal = info.universal || config.generate === "universal";
|
|
5798
5837
|
const text =
|
|
5799
5838
|
staticValue !== undefined ?
|
|
5800
|
-
info.doNotEscape ?
|
|
5839
|
+
info.doNotEscape || universal ?
|
|
5801
5840
|
String(staticValue) :
|
|
5802
5841
|
escapeHTML(String(staticValue)) :
|
|
5842
|
+
universal ?
|
|
5843
|
+
htmlEntities.decode(trimWhitespace(node.extra?.raw ?? "")) :
|
|
5803
5844
|
trimWhitespace(node.extra?.raw ?? "");
|
|
5804
5845
|
if (!text.length) return null;
|
|
5805
5846
|
const results = {
|
|
@@ -14474,13 +14515,22 @@ var postprocess = (path, state) => {
|
|
|
14474
14515
|
if (typeof html === "string") {
|
|
14475
14516
|
const result = isInvalidMarkup(html);
|
|
14476
14517
|
if (result) {
|
|
14518
|
+
// A compile ERROR, not a warning (#3099): once the validator has
|
|
14519
|
+
// fired, the emitted template is guaranteed not to match its own
|
|
14520
|
+
// positional walk — the browser rebuilds the DOM, and the walk
|
|
14521
|
+
// binds against nodes that moved (crash or silent wrong-node
|
|
14522
|
+
// bindings; under SSR the restructuring desyncs hydration too).
|
|
14523
|
+
// Warn-and-emit put this diagnostic in server stdout while the
|
|
14524
|
+
// browser failed with an unrelated-looking runtime crash. The
|
|
14525
|
+
// error throws from the template's registration site, so
|
|
14526
|
+
// bundlers surface it at the right file and line. `validate:
|
|
14527
|
+
// false` remains the opt-out.
|
|
14477
14528
|
const message =
|
|
14478
|
-
"
|
|
14479
|
-
|
|
14480
|
-
|
|
14481
|
-
|
|
14482
|
-
|
|
14483
|
-
// throw path.buildCodeFrameError();
|
|
14529
|
+
"The HTML provided is malformed and will yield unexpected output when evaluated by a browser.\n" +
|
|
14530
|
+
`User HTML:\n ${result.html}\n` +
|
|
14531
|
+
`Browser HTML:\n ${result.browser}\n` +
|
|
14532
|
+
`Original HTML:\n ${html}`;
|
|
14533
|
+
throw (template.path ?? path).buildCodeFrameError(message);
|
|
14484
14534
|
}
|
|
14485
14535
|
}
|
|
14486
14536
|
}
|