@barefootjs/jsx 0.31.6 → 0.31.7
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/dist/compiler.d.ts.map +1 -1
- package/dist/errors.d.ts +1 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/index.js +96 -9
- package/dist/ir-to-client-js/build-references.d.ts.map +1 -1
- package/dist/ir-to-client-js/emit-reactive.d.ts.map +1 -1
- package/dist/ir-to-client-js/html-template.d.ts.map +1 -1
- package/dist/rich-type-evidence.d.ts +86 -0
- package/dist/rich-type-evidence.d.ts.map +1 -1
- package/dist/rich-type-refusal.d.ts +59 -11
- package/dist/rich-type-refusal.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/client-only-date-lowering.test.ts +182 -0
- package/src/__tests__/prop-references.test.ts +72 -0
- package/src/__tests__/rich-type-method-refusal.test.ts +79 -2
- package/src/__tests__/rich-type-prop-serialization.test.ts +238 -0
- package/src/compiler.ts +3 -1
- package/src/errors.ts +13 -0
- package/src/ir-to-client-js/build-references.ts +17 -0
- package/src/ir-to-client-js/emit-reactive.ts +29 -8
- package/src/ir-to-client-js/html-template.ts +22 -4
- package/src/rich-type-evidence.ts +104 -0
- package/src/rich-type-refusal.ts +177 -23
package/dist/compiler.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,cAAc,EACd,aAAa,EACb,UAAU,EACX,MAAM,YAAY,CAAA;AAEnB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,EAAE,gBAAgB,EAAyE,MAAM,eAAe,CAAA;AAiBvH;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,cAAc;IAC/D,wDAAwD;IACxD,OAAO,EAAE,eAAe,CAAA;CACzB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAyC5D;
|
|
1
|
+
{"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,cAAc,EACd,aAAa,EACb,UAAU,EACX,MAAM,YAAY,CAAA;AAEnB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,EAAE,gBAAgB,EAAyE,MAAM,eAAe,CAAA;AAiBvH;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,cAAc;IAC/D,wDAAwD;IACxD,OAAO,EAAE,eAAe,CAAA;CACzB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAyC5D;AA8hBD,wBAAgB,aAAa,CAC3B,GAAG,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GACvC,UAAU,CAoCZ;AAMD,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,yBAAyB,GACjC,aAAa,CAwPf;AAMD,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,CAAA"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export declare const ErrorCodes: {
|
|
|
16
16
|
readonly COMPONENT_REQUIRED_PROP_MISSING: 'BF046';
|
|
17
17
|
readonly JSX_BRANCH_LOCAL_IN_CALLBACK: 'BF047';
|
|
18
18
|
readonly SIBLING_COMPONENT_NOT_COMPILED: 'BF048';
|
|
19
|
+
readonly RICH_TYPE_PROP_NOT_HYDRATABLE: 'BF049';
|
|
19
20
|
readonly SHARED_PROGRAM_REQUIRED: 'BF050';
|
|
20
21
|
readonly WRONG_PACKAGE_IMPORT: 'BF051';
|
|
21
22
|
readonly BUILTIN_REQUIRES_IMPORT: 'BF054';
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,eAAe,EACf,cAAc,EACf,MAAM,YAAY,CAAA;AAMnB,eAAO,MAAM,UAAU;aAErB,kBAAkB,EAAE,OAAO;aAC3B,uBAAuB,EAAE,OAAO;aAGhC,wBAAwB,EAAE,OAAO;aAGjC,uBAAuB,EAAE,OAAO;aAChC,mBAAmB,EAAE,OAAO;aAC5B,0BAA0B,EAAE,OAAO;aACnC,4BAA4B,EAAE,OAAO;aAGrC,mBAAmB,EAAE,OAAO;aAC5B,wBAAwB,EAAE,OAAO;aACjC,qBAAqB,EAAE,OAAO;aAC9B,+BAA+B,EAAE,OAAO;aAUxC,4BAA4B,EAAE,OAAO;aAUrC,8BAA8B,EAAE,OAAO;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,eAAe,EACf,cAAc,EACf,MAAM,YAAY,CAAA;AAMnB,eAAO,MAAM,UAAU;aAErB,kBAAkB,EAAE,OAAO;aAC3B,uBAAuB,EAAE,OAAO;aAGhC,wBAAwB,EAAE,OAAO;aAGjC,uBAAuB,EAAE,OAAO;aAChC,mBAAmB,EAAE,OAAO;aAC5B,0BAA0B,EAAE,OAAO;aACnC,4BAA4B,EAAE,OAAO;aAGrC,mBAAmB,EAAE,OAAO;aAC5B,wBAAwB,EAAE,OAAO;aACjC,qBAAqB,EAAE,OAAO;aAC9B,+BAA+B,EAAE,OAAO;aAUxC,4BAA4B,EAAE,OAAO;aAUrC,8BAA8B,EAAE,OAAO;aAUvC,6BAA6B,EAAE,OAAO;aAGtC,uBAAuB,EAAE,OAAO;aAChC,oBAAoB,EAAE,OAAO;aAK7B,uBAAuB,EAAE,OAAO;aAQhC,6BAA6B,EAAE,OAAO;aAGtC,mCAAmC,EAAE,OAAO;aAQ5C,iCAAiC,EAAE,OAAO;aAa1C,0BAA0B,EAAE,OAAO;aACnC,4BAA4B,EAAE,OAAO;aACrC,uBAAuB,EAAE,OAAO;aAMhC,2BAA2B,EAAE,OAAO;aAGpC,6BAA6B,EAAE,OAAO;aACtC,mCAAmC,EAAE,OAAO;aAC5C,+BAA+B,EAAE,OAAO;aACxC,iCAAiC,EAAE,OAAO;aAC1C,+BAA+B,EAAE,OAAO;CAChC,CAAA;AAEV,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAA;AAmHpE,wBAAgB,WAAW,CACzB,IAAI,EAAE,SAAS,EACf,GAAG,EAAE,cAAc,EACnB,OAAO,CAAC,EAAE;IACR,QAAQ,CAAC,EAAE,aAAa,CAAA;IACxB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,eAAe,CAAA;CAC7B,GACA,aAAa,CAuBf;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,SAAS,EACf,GAAG,EAAE,cAAc,EACnB,OAAO,CAAC,EAAE;IACR,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,eAAe,CAAA;CAC7B,GACA,aAAa,CAEf;AAED,wBAAgB,UAAU,CACxB,IAAI,EAAE,SAAS,EACf,GAAG,EAAE,cAAc,EACnB,OAAO,CAAC,EAAE;IACR,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,eAAe,CAAA;CAC7B,GACA,aAAa,CAEf;AAMD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,cAAc,EACnB,YAAY,SAAI,GACf,MAAM,CA6BR;AAmBD,wBAAgB,WAAW,CACzB,KAAK,EAAE,aAAa,EACpB,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAChC,MAAM,CA6CR;AAMD;;;;;;;GAOG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAId;AAMD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,cAAc,CAMhB;AAED,wBAAgB,cAAc,CAC5B,KAAK,EAAE,cAAc,EACrB,GAAG,EAAE,cAAc,GAClB,cAAc,CAMhB"}
|
package/dist/index.js
CHANGED
|
@@ -4154,6 +4154,11 @@ function irToComponentTemplateWithOpts(node, opts) {
|
|
|
4154
4154
|
case "expression": {
|
|
4155
4155
|
if (node.expr === "null" || node.expr === "undefined")
|
|
4156
4156
|
return "";
|
|
4157
|
+
if (node.clientOnly && node.slotId) {
|
|
4158
|
+
if (node.markerless)
|
|
4159
|
+
return "";
|
|
4160
|
+
return `<!--bf:${node.slotId}--><!--/-->`;
|
|
4161
|
+
}
|
|
4157
4162
|
const wrapped = transformExpr(node.expr, node.templateExpr);
|
|
4158
4163
|
const value = node.joinArrayChild ? `Array.isArray(${wrapped}) ? ${wrapped}.join('') : (${wrapped} ?? '')` : wrapped;
|
|
4159
4164
|
if (node.slotId) {
|
|
@@ -5605,6 +5610,7 @@ var ErrorCodes = {
|
|
|
5605
5610
|
COMPONENT_REQUIRED_PROP_MISSING: "BF046",
|
|
5606
5611
|
JSX_BRANCH_LOCAL_IN_CALLBACK: "BF047",
|
|
5607
5612
|
SIBLING_COMPONENT_NOT_COMPILED: "BF048",
|
|
5613
|
+
RICH_TYPE_PROP_NOT_HYDRATABLE: "BF049",
|
|
5608
5614
|
SHARED_PROGRAM_REQUIRED: "BF050",
|
|
5609
5615
|
WRONG_PACKAGE_IMPORT: "BF051",
|
|
5610
5616
|
BUILTIN_REQUIRES_IMPORT: "BF054",
|
|
@@ -5635,6 +5641,7 @@ var errorMessages = {
|
|
|
5635
5641
|
[ErrorCodes.COMPONENT_REQUIRED_PROP_MISSING]: "Built-in component is missing a required prop.",
|
|
5636
5642
|
[ErrorCodes.JSX_BRANCH_LOCAL_IN_CALLBACK]: "JSX-typed local declared inside an `if`-block cannot be referenced from a callback body (ref / event handler). " + "Render it as a child instead: `<div ref={...}>{local}</div>`.",
|
|
5637
5643
|
[ErrorCodes.SIBLING_COMPONENT_NOT_COMPILED]: "Referenced component did not compile to a template, so this reference would throw " + "`ReferenceError` at render time. Multi-return JSX dispatch (a `switch` or `if`/`else` " + "chain across multiple JSX-returning branches) cannot compile as a component in a " + `'use client' file. Extract it to a separate non-"use client" file (where it is preserved ` + "verbatim, see #932), or rewrite it as a single-return ternary/conditional chain so the " + "component pipeline can compile it.",
|
|
5644
|
+
[ErrorCodes.RICH_TYPE_PROP_NOT_HYDRATABLE]: "Rich-typed prop cannot cross the bf-p hydration boundary as JSON.",
|
|
5638
5645
|
[ErrorCodes.SHARED_PROGRAM_REQUIRED]: "Shared ts.Program required for type-based reactivity classification. This source imports a Reactive<T>-branded library (e.g. @barefootjs/form) whose getters cannot be classified by regex alone. Pass `options.program` (built via `createProgramForCorpus`) so the analyzer can resolve the brand through the TypeChecker.",
|
|
5639
5646
|
[ErrorCodes.WRONG_PACKAGE_IMPORT]: "Import from wrong package.",
|
|
5640
5647
|
[ErrorCodes.BUILTIN_REQUIRES_IMPORT]: "Built-in <Async> / <Region> must be imported from '@barefootjs/client'. " + "The compiler recognises these tags by their import (not by tag name), " + "so an unimported tag with this name is treated as an undeclared component.",
|
|
@@ -5752,6 +5759,8 @@ var HOST_RICH_TYPE_NAMES = new Set([
|
|
|
5752
5759
|
"BigInt",
|
|
5753
5760
|
"Function"
|
|
5754
5761
|
]);
|
|
5762
|
+
var JSON_REVIVABLE_RICH_TYPE_NAMES = new Set(["Date", "URL"]);
|
|
5763
|
+
var JSON_UNSAFE_RICH_TYPE_NAMES = new Set([...HOST_RICH_TYPE_NAMES].filter((n) => !JSON_REVIVABLE_RICH_TYPE_NAMES.has(n)));
|
|
5755
5764
|
function baseTypeName(raw) {
|
|
5756
5765
|
const idx = raw.indexOf("<");
|
|
5757
5766
|
return (idx === -1 ? raw : raw.slice(0, idx)).trim();
|
|
@@ -5784,6 +5793,21 @@ function lookupProperty(objType, propName, meta) {
|
|
|
5784
5793
|
const prop = deref.properties?.find((p) => p.name === propName);
|
|
5785
5794
|
return prop ? stripUnion(prop.type) : null;
|
|
5786
5795
|
}
|
|
5796
|
+
function resolvePropDeclaredType(propName, meta) {
|
|
5797
|
+
return lookupProperty(meta.propsType, propName, meta);
|
|
5798
|
+
}
|
|
5799
|
+
function jsonUnsafeTypeName(type) {
|
|
5800
|
+
if (!type)
|
|
5801
|
+
return null;
|
|
5802
|
+
if (type.kind === "interface") {
|
|
5803
|
+
const name = baseTypeName(type.raw);
|
|
5804
|
+
return JSON_UNSAFE_RICH_TYPE_NAMES.has(name) ? name : null;
|
|
5805
|
+
}
|
|
5806
|
+
if (type.kind === "unknown" && (type.raw === "bigint" || type.raw === "symbol")) {
|
|
5807
|
+
return type.raw;
|
|
5808
|
+
}
|
|
5809
|
+
return null;
|
|
5810
|
+
}
|
|
5787
5811
|
function resolveReceiverType(expr, meta, bindings) {
|
|
5788
5812
|
if (expr.kind === "identifier") {
|
|
5789
5813
|
if (bindings.has(expr.name))
|
|
@@ -15574,6 +15598,9 @@ function buildReferencesGraph(ctx, irRoot) {
|
|
|
15574
15598
|
addExprEdges(ROOT_SOURCE, event.handler, "init-body");
|
|
15575
15599
|
}
|
|
15576
15600
|
}
|
|
15601
|
+
for (const elem of ctx.clientOnlyElements) {
|
|
15602
|
+
addExprEdges(ROOT_SOURCE, elem.expression, "init-body");
|
|
15603
|
+
}
|
|
15577
15604
|
for (const elem of ctx.loopElements) {
|
|
15578
15605
|
addExprEdges(ROOT_SOURCE, elem.array, "template-closure");
|
|
15579
15606
|
addTemplateEdges(ROOT_SOURCE, elem.template, "template-closure");
|
|
@@ -20034,9 +20061,15 @@ function lowerDateCallsInReactiveExpr(expr, matcher) {
|
|
|
20034
20061
|
}
|
|
20035
20062
|
return restore(result);
|
|
20036
20063
|
}
|
|
20037
|
-
function
|
|
20038
|
-
const
|
|
20064
|
+
function makeCataloguedCallLowerer(ctx) {
|
|
20065
|
+
const dateMatcher = getReactiveDateLoweringMatcher(ctx);
|
|
20039
20066
|
const toLocaleMatcher = getReactiveToLocaleMatcher(ctx);
|
|
20067
|
+
if (!dateMatcher && !toLocaleMatcher)
|
|
20068
|
+
return (expr) => expr;
|
|
20069
|
+
return (expr) => lowerToLocaleCallsInReactiveExpr(lowerDateCallsInReactiveExpr(expr, dateMatcher), toLocaleMatcher);
|
|
20070
|
+
}
|
|
20071
|
+
function emitDynamicTextUpdates(lines, ctx) {
|
|
20072
|
+
const lower = makeCataloguedCallLowerer(ctx);
|
|
20040
20073
|
const byExpression = new Map;
|
|
20041
20074
|
for (const elem of ctx.dynamicElements) {
|
|
20042
20075
|
const key = elem.expression;
|
|
@@ -20046,7 +20079,7 @@ function emitDynamicTextUpdates(lines, ctx) {
|
|
|
20046
20079
|
byExpression.get(key).push(elem);
|
|
20047
20080
|
}
|
|
20048
20081
|
for (const [rawExpr, elems] of byExpression) {
|
|
20049
|
-
const expr =
|
|
20082
|
+
const expr = lower(rawExpr);
|
|
20050
20083
|
const conditionalElems = elems.filter((e) => e.insideConditional);
|
|
20051
20084
|
const normalElems = elems.filter((e) => !e.insideConditional);
|
|
20052
20085
|
if (normalElems.length > 0 || conditionalElems.length > 0) {
|
|
@@ -20083,19 +20116,21 @@ function emitDynamicTextUpdates(lines, ctx) {
|
|
|
20083
20116
|
}
|
|
20084
20117
|
}
|
|
20085
20118
|
function emitClientOnlyExpressions(lines, ctx) {
|
|
20119
|
+
const lower = makeCataloguedCallLowerer(ctx);
|
|
20086
20120
|
for (const elem of ctx.clientOnlyElements) {
|
|
20087
20121
|
const slots = elem.elidedPath ? [{ id: elem.slotId, kind: "text", path: elem.elidedPath, markerless: true }] : [{ id: elem.slotId, kind: "text", path: [] }];
|
|
20088
20122
|
const writer = claimWriterVarName(slots, varSlotId);
|
|
20089
20123
|
lines.push(` // @client: ${elem.slotId}`);
|
|
20090
20124
|
lines.push(` { const ${writer} = lazySlots(__scope, ${claimPlanLiteral(slots)})`);
|
|
20091
20125
|
lines.push(` createEffect(() => {`);
|
|
20092
|
-
lines.push(` ${writer}('${elem.slotId}', ${elem.expression})`);
|
|
20126
|
+
lines.push(` ${writer}('${elem.slotId}', ${lower(elem.expression)})`);
|
|
20093
20127
|
lines.push(` }${bindingIdArg(ctx, elem.slotId)}) }`);
|
|
20094
20128
|
lines.push("");
|
|
20095
20129
|
}
|
|
20096
20130
|
}
|
|
20097
20131
|
function emitReactiveAttributeUpdates(lines, ctx) {
|
|
20098
20132
|
if (ctx.reactiveAttrs.length > 0) {
|
|
20133
|
+
const lower = makeCataloguedCallLowerer(ctx);
|
|
20099
20134
|
const attrsBySlot = new Map;
|
|
20100
20135
|
for (const attr of ctx.reactiveAttrs) {
|
|
20101
20136
|
if (!attrsBySlot.has(attr.slotId)) {
|
|
@@ -20108,7 +20143,7 @@ function emitReactiveAttributeUpdates(lines, ctx) {
|
|
|
20108
20143
|
lines.push(` createEffect(() => {`);
|
|
20109
20144
|
lines.push(` if (_${v}) {`);
|
|
20110
20145
|
for (const attr of attrs) {
|
|
20111
|
-
const expression = rewriteDestructuredPropsInExpr(attr.expression, ctx);
|
|
20146
|
+
const expression = rewriteDestructuredPropsInExpr(lower(attr.expression), ctx);
|
|
20112
20147
|
for (const stmt of emitAttrUpdate(`_${v}`, attr.attrName, expression, attr)) {
|
|
20113
20148
|
lines.push(` ${stmt}`);
|
|
20114
20149
|
}
|
|
@@ -23871,6 +23906,38 @@ function checkRichTypeMethodCalls(root, metadata, errors) {
|
|
|
23871
23906
|
const seen = new Set;
|
|
23872
23907
|
walkNode2(root, metadata, EMPTY_BINDINGS2, matchers, errors, seen);
|
|
23873
23908
|
}
|
|
23909
|
+
function checkRichTypePropSerialization(root, metadata, errors, declLoc) {
|
|
23910
|
+
if (!metadata.propsType || !metadata.clientAnalysis?.needsInit)
|
|
23911
|
+
return;
|
|
23912
|
+
const usedProps = new Set(metadata.clientAnalysis.usedProps);
|
|
23913
|
+
const loc = declLoc ?? root.loc;
|
|
23914
|
+
for (const param of metadata.propsParams) {
|
|
23915
|
+
if (param.isRest || param.name.startsWith("on") || param.name.startsWith("__"))
|
|
23916
|
+
continue;
|
|
23917
|
+
if (!usedProps.has(param.name))
|
|
23918
|
+
continue;
|
|
23919
|
+
const declared = resolvePropDeclaredType(param.sourceName ?? param.name, metadata);
|
|
23920
|
+
const typeName = jsonUnsafeTypeName(declared);
|
|
23921
|
+
if (!typeName)
|
|
23922
|
+
continue;
|
|
23923
|
+
if (metadata.typeDefinitions.some((d) => d.name === typeName))
|
|
23924
|
+
continue;
|
|
23925
|
+
pushPropSerializationDiagnostic(errors, loc, param.name, typeName, declared.raw);
|
|
23926
|
+
}
|
|
23927
|
+
}
|
|
23928
|
+
function pushPropSerializationDiagnostic(errors, loc, propName, typeName, declaredRaw) {
|
|
23929
|
+
const consequence = typeName === "bigint" || typeName === "BigInt" ? "JSON.stringify throws at SSR render ('Do not know how to serialize a BigInt'), failing the whole page" : typeName === "symbol" || typeName === "Symbol" || typeName === "Function" ? "JSON.stringify drops the value entirely, so the client reads undefined at hydrate" : "it serializes de-riched (e.g. a Map or Set becomes {} with every entry silently dropped), so the client hydrates against corrupt data";
|
|
23930
|
+
errors.push({
|
|
23931
|
+
code: ErrorCodes.RICH_TYPE_PROP_NOT_HYDRATABLE,
|
|
23932
|
+
severity: "error",
|
|
23933
|
+
message: `Prop '${propName}' is typed '${declaredRaw}' and is read by this component's own client code, so it must cross the bf-p hydration boundary as JSON — and ${typeName} cannot: ${consequence}.`,
|
|
23934
|
+
loc,
|
|
23935
|
+
suggestion: {
|
|
23936
|
+
message: "Pre-compute a JSON-serializable value server-side — a string, number, boolean, array, or plain object " + "(e.g. pass [...map.entries()] and rebuild the Map client-side where needed) — and pass that as the prop " + "instead. /* @client */ is NOT an escape here: the prop still crosses the bf-p boundary as JSON and arrives " + "de-riched (#2636).",
|
|
23937
|
+
escape: [{ kind: "prop-precompute" }]
|
|
23938
|
+
}
|
|
23939
|
+
});
|
|
23940
|
+
}
|
|
23874
23941
|
function isLoweringClaimed(matchers, callee, args) {
|
|
23875
23942
|
return matchers.some((m) => m(callee, args) !== null);
|
|
23876
23943
|
}
|
|
@@ -23887,21 +23954,39 @@ function receiverRootIsProp(expr, bindings) {
|
|
|
23887
23954
|
root = root.object;
|
|
23888
23955
|
return root.kind === "identifier" && !bindings.has(root.name);
|
|
23889
23956
|
}
|
|
23957
|
+
function buildSuggestion(method, receiverPath, receiver, typeName) {
|
|
23958
|
+
const revivalExpr = receiverPath === "<expression>" ? `wrapping the receiver in new ${typeName}(...) before calling .${method}()` : `{/* @client */ new ${typeName}(${receiverPath}).${method}(...)}`;
|
|
23959
|
+
const revivalReason = `a bare /* @client */ crashes at hydrate because ${receiver} crosses the bf-p boundary as JSON and arrives as a plain string, not a ${typeName} instance (#2636)`;
|
|
23960
|
+
if (method === "toLocaleDateString" && typeName === "Date") {
|
|
23961
|
+
return {
|
|
23962
|
+
message: "Pass a literal locale and an explicit literal timeZone — .toLocaleDateString('ja-JP', { timeZone: 'UTC' }), a fixed '±HH:MM' offset, or a canonical IANA zone ID like 'Asia/Tokyo' (exact case; #2344) — to compile it to the format_date helper; for a runtime locale, resolve the pattern in your i18n layer and use formatDate(date, pattern, tz) from @barefootjs/client. " + `Alternatively pre-compute server-side, or evaluate client-only by ${revivalExpr} — ${revivalReason}.`,
|
|
23963
|
+
escape: [{ kind: "rewrite" }, { kind: "prop-precompute" }, { kind: "client-directive" }]
|
|
23964
|
+
};
|
|
23965
|
+
}
|
|
23966
|
+
if (JSON_REVIVABLE_RICH_TYPE_NAMES.has(typeName)) {
|
|
23967
|
+
return {
|
|
23968
|
+
message: `Pre-compute the value server-side and pass it as a prop. Alternatively, evaluate client-only by ${revivalExpr} — ${revivalReason}.`,
|
|
23969
|
+
escape: [{ kind: "prop-precompute" }, { kind: "client-directive" }]
|
|
23970
|
+
};
|
|
23971
|
+
}
|
|
23972
|
+
return {
|
|
23973
|
+
message: `Pre-compute the value server-side and pass the result — a string, number, array, or plain object — as a prop. ` + `/* @client */ is NOT a safe escape here: ${receiver} cannot cross the bf-p hydration boundary as JSON — it arrives de-riched ` + `(e.g. a Map or Set serializes to {}), so the call throws or silently returns the wrong result at hydrate (#2636).`,
|
|
23974
|
+
escape: [{ kind: "prop-precompute" }]
|
|
23975
|
+
};
|
|
23976
|
+
}
|
|
23890
23977
|
function pushDiagnostic(errors, seen, loc, method, receiverPath, isProp, typeName) {
|
|
23891
23978
|
const key = `${loc.start.line}:${loc.start.column}:${receiverPath}.${method}`;
|
|
23892
23979
|
if (seen.has(key))
|
|
23893
23980
|
return;
|
|
23894
23981
|
seen.add(key);
|
|
23895
23982
|
const receiver = isProp ? `prop '${receiverPath}'` : `'${receiverPath}'`;
|
|
23896
|
-
const suggestion = method
|
|
23983
|
+
const suggestion = buildSuggestion(method, receiverPath, receiver, typeName);
|
|
23897
23984
|
errors.push({
|
|
23898
23985
|
code: ErrorCodes.UNSUPPORTED_JSX_PATTERN,
|
|
23899
23986
|
severity: "error",
|
|
23900
23987
|
message: `Expression cannot be compiled to marked template: method '.${method}()' on ${receiver} of host type '${typeName}' has no catalogued lowering.`,
|
|
23901
23988
|
loc,
|
|
23902
|
-
suggestion
|
|
23903
|
-
message: suggestion
|
|
23904
|
-
}
|
|
23989
|
+
suggestion
|
|
23905
23990
|
});
|
|
23906
23991
|
}
|
|
23907
23992
|
function checkExpr(expr, loc, meta, bindings, matchers, errors, seen) {
|
|
@@ -24146,6 +24231,7 @@ function compileMultipleComponents(source, filePath, componentNames, options) {
|
|
|
24146
24231
|
};
|
|
24147
24232
|
componentIR.metadata.clientAnalysis = analyzeClientNeeds(componentIR);
|
|
24148
24233
|
checkRichTypeMethodCalls(componentIR.root, componentIR.metadata, errors);
|
|
24234
|
+
checkRichTypePropSerialization(componentIR.root, componentIR.metadata, errors, ctx.propsDestructuring?.loc);
|
|
24149
24235
|
decideClientOnlyElision(componentIR.root);
|
|
24150
24236
|
entries.push({ componentIR, ctx });
|
|
24151
24237
|
}
|
|
@@ -24548,6 +24634,7 @@ function compileJSX(source, filePath, options) {
|
|
|
24548
24634
|
};
|
|
24549
24635
|
componentIR.metadata.clientAnalysis = analyzeClientNeeds(componentIR);
|
|
24550
24636
|
checkRichTypeMethodCalls(componentIR.root, componentIR.metadata, errors);
|
|
24637
|
+
checkRichTypePropSerialization(componentIR.root, componentIR.metadata, errors, ctx.propsDestructuring?.loc);
|
|
24551
24638
|
decideClientOnlyElision(componentIR.root);
|
|
24552
24639
|
if (ctx.importedClientSignalNames.size > 0) {
|
|
24553
24640
|
const sources = new Set;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-references.d.ts","sourceRoot":"","sources":["../../src/ir-to-client-js/build-references.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAEV,MAAM,EAIN,eAAe,EAChB,MAAM,aAAa,CAAA;AAIpB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAYjD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"build-references.d.ts","sourceRoot":"","sources":["../../src/ir-to-client-js/build-references.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAEV,MAAM,EAIN,eAAe,EAChB,MAAM,aAAa,CAAA;AAIpB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAYjD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,eAAe,CA0V1F;AAMD;;2DAE2D;AAC3D,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,eAAe,GAAG,GAAG,CAAC,MAAM,CAAC,CAOxE;AAED;0CAC0C;AAC1C,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,GAAG,GAAG,CAAC,MAAM,CAAC,CAMtE;AAED;6CAC6C;AAC7C,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,eAAe,GAAG,GAAG,CAAC,MAAM,CAAC,CAM5E;AAED;;qDAEqD;AACrD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAE3F;AAED;;8CAE8C;AAC9C,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,EACjD,IAAI,EAAE,MAAM,GACX,GAAG,CAAC,MAAM,CAAC,CAQb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit-reactive.d.ts","sourceRoot":"","sources":["../../src/ir-to-client-js/emit-reactive.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,aAAa,CAAA;AAEvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAqBjD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE,CAyC7G;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,GAAG,MAAM,CAqBzF;
|
|
1
|
+
{"version":3,"file":"emit-reactive.d.ts","sourceRoot":"","sources":["../../src/ir-to-client-js/emit-reactive.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,aAAa,CAAA;AAEvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAqBjD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE,CAyC7G;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,GAAG,MAAM,CAqBzF;AAwMD,gFAAgF;AAChF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,eAAe,GAAG,IAAI,CAkFlF;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,eAAe,GAAG,IAAI,CAiBrF;AAED,kGAAkG;AAClG,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,eAAe,GAAG,IAAI,CA8BxF;AAED,+FAA+F;AAC/F,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,eAAe,GAAG,IAAI,CAqDpF;AAED,2FAA2F;AAC3F,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,eAAe,GAAG,IAAI,CAgClF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html-template.d.ts","sourceRoot":"","sources":["../../src/ir-to-client-js/html-template.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"html-template.d.ts","sourceRoot":"","sources":["../../src/ir-to-client-js/html-template.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,6 +31,68 @@ import type { ParsedExpr } from './expression-parser.ts';
|
|
|
31
31
|
* catalogue lookup sees `Timestamp`, not `Date`.
|
|
32
32
|
*/
|
|
33
33
|
export declare const HOST_RICH_TYPE_NAMES: ReadonlySet<string>;
|
|
34
|
+
/**
|
|
35
|
+
* The subset of `HOST_RICH_TYPE_NAMES` whose `toJSON()` output is accepted
|
|
36
|
+
* by the type's own one-argument constructor, so a value that crossed the
|
|
37
|
+
* `bf-p` hydration boundary as JSON can be revived with `new T(jsonValue)`
|
|
38
|
+
* (#2636). `Date.prototype.toJSON()` returns an ISO string `new Date()`
|
|
39
|
+
* re-parses; `URL.prototype.toJSON()` returns an `href` string `new URL()`
|
|
40
|
+
* re-parses. Every other host rich type fails this test:
|
|
41
|
+
* - `Map` / `Set` / `WeakMap` / `WeakSet` — `JSON.stringify` drops all
|
|
42
|
+
* entries, serializing to `{}`; there is no envelope to revive FROM.
|
|
43
|
+
* - `URLSearchParams` / `RegExp` / `Promise` / `Error` — likewise
|
|
44
|
+
* serialize to `{}` (or, for `Error`, an empty-looking object missing
|
|
45
|
+
* `message`/`stack` under most engines' own `toJSON`-less default).
|
|
46
|
+
* - `Symbol` / `Function` — dropped entirely by `JSON.stringify` (become
|
|
47
|
+
* `undefined` in an object, elided in an array).
|
|
48
|
+
* - `BigInt` — `JSON.stringify` throws `TypeError` before a hydrate-time
|
|
49
|
+
* revival could ever run.
|
|
50
|
+
*
|
|
51
|
+
* Used only to decide which escape suggestion `rich-type-refusal.ts`'s
|
|
52
|
+
* `pushDiagnostic` may offer: a bare `/* @client *\/` recommendation is
|
|
53
|
+
* unsound for every host rich type here (see that module's docstring), but
|
|
54
|
+
* wrapping the receiver in `new T(...)` — `{/* @client *\/ new
|
|
55
|
+
* Date(createdAt).getUTCFullYear()}` — is a genuine, hydrate-safe escape
|
|
56
|
+
* for this subset only.
|
|
57
|
+
*
|
|
58
|
+
* A GENERAL typed-prop revival mechanism across the rest of
|
|
59
|
+
* `HOST_RICH_TYPE_NAMES` — a `bf-p` wire envelope reviving `Map`/`Set`/
|
|
60
|
+
* `URLSearchParams`/`RegExp`/`BigInt` the way `Date`/`URL` revive via their
|
|
61
|
+
* own constructor — was evaluated and DEFERRED (#2642), not rejected on
|
|
62
|
+
* technical grounds. Two decisions worth recording here so a future
|
|
63
|
+
* contributor doesn't re-litigate them from scratch:
|
|
64
|
+
* - A value-shaped sentinel envelope (`{ $map: [[k,v],...] }`, detected
|
|
65
|
+
* by `parseProps`) was rejected: the type signal lives in the VALUE, so
|
|
66
|
+
* a user prop that happens to share the sentinel's shape would be
|
|
67
|
+
* silently misrevived on every adapter, not just ones that emit
|
|
68
|
+
* envelopes — the only sound fix is a user-data escaping rule
|
|
69
|
+
* implemented in all 9 adapters' serializers, which is the actual
|
|
70
|
+
* protocol cost, paid by every payload, not just rich-typed ones.
|
|
71
|
+
* - If ever built, the sanctioned shape is TYPE-DIRECTED USE-SITE
|
|
72
|
+
* REVIVAL — the generalization of `date()` (`packages/client/src/
|
|
73
|
+
* runtime/date.ts`): plain-JSON canonical wire shapes per type, with
|
|
74
|
+
* the compiler (which already resolves prop types here) emitting a
|
|
75
|
+
* revival call at each prop's client-JS extraction site, not a
|
|
76
|
+
* value-sniffing `parseProps` reviver.
|
|
77
|
+
* `WeakMap` / `WeakSet` / `Promise` / `Symbol` / `Function` are excluded
|
|
78
|
+
* from that future scope permanently, independent of mechanism — they are
|
|
79
|
+
* structurally impossible to serialize (non-enumerable by spec, not data,
|
|
80
|
+
* or identity-is-the-semantics), not merely unrevived today.
|
|
81
|
+
*/
|
|
82
|
+
export declare const JSON_REVIVABLE_RICH_TYPE_NAMES: ReadonlySet<string>;
|
|
83
|
+
/**
|
|
84
|
+
* The complement of `JSON_REVIVABLE_RICH_TYPE_NAMES` within `HOST_RICH_TYPE_NAMES`
|
|
85
|
+
* — every host rich type whose `JSON.stringify` output is NOT revivable via its
|
|
86
|
+
* own constructor. Used by `checkRichTypePropSerialization`
|
|
87
|
+
* (`rich-type-refusal.ts`, #2643) to flag a rich-typed prop that a client
|
|
88
|
+
* reads but that will cross the `bf-p` hydration boundary de-riched or
|
|
89
|
+
* (for `BigInt`) fail to serialize at all — a distinct failure from the
|
|
90
|
+
* method-call refusal above: whether or not client code goes on to call a
|
|
91
|
+
* method on the value is irrelevant here, since the method-call refusal
|
|
92
|
+
* only walks template-lowered expression positions and never sees a
|
|
93
|
+
* handler/effect body regardless.
|
|
94
|
+
*/
|
|
95
|
+
export declare const JSON_UNSAFE_RICH_TYPE_NAMES: ReadonlySet<string>;
|
|
34
96
|
/**
|
|
35
97
|
* Strip generic type arguments from a `TypeInfo.raw` string (`Map<string,
|
|
36
98
|
* string>` → `Map`) so a parametrized host type still matches the bare-name
|
|
@@ -50,6 +112,30 @@ export declare function stripUnion(type: TypeInfo | null): TypeInfo | null;
|
|
|
50
112
|
* `{ kind: 'interface', raw }` with no member walk of its own.
|
|
51
113
|
*/
|
|
52
114
|
export declare function derefNamedType(type: TypeInfo, meta: EvidenceMetadata): TypeInfo;
|
|
115
|
+
/**
|
|
116
|
+
* Resolve a prop's declared type straight off `propsType` by its SOURCE
|
|
117
|
+
* name (`lookupProperty`'s public face for `checkRichTypePropSerialization`,
|
|
118
|
+
* which has no receiver expression to walk — only a `propsParams` entry).
|
|
119
|
+
*/
|
|
120
|
+
export declare function resolvePropDeclaredType(propName: string, meta: EvidenceMetadata): TypeInfo | null;
|
|
121
|
+
/**
|
|
122
|
+
* The JSON-unsafe type name a declared prop type resolves to, or `null` if
|
|
123
|
+
* it isn't one. Recognizes:
|
|
124
|
+
* - an interface-kind type whose `baseTypeName` is in
|
|
125
|
+
* `JSON_UNSAFE_RICH_TYPE_NAMES` (caller must still apply the in-file
|
|
126
|
+
* `typeDefinitions` shadow guard — this function has no `meta` to check
|
|
127
|
+
* it against, mirroring `checkRichTypeMethodCalls`'s own split between
|
|
128
|
+
* type resolution and shadow-checking);
|
|
129
|
+
* - the KEYWORD spellings `bigint` / `symbol`, which `typeNodeToTypeInfo`
|
|
130
|
+
* lowers to `{ kind: 'unknown', raw: '<keyword>' }` (only the object-form
|
|
131
|
+
* `BigInt` / `Symbol` type references reach `kind: 'interface'` and match
|
|
132
|
+
* the catalogue above) — an exact-equality check on the AST-derived raw
|
|
133
|
+
* text, the same class of raw use as `baseTypeName`, not a type-syntax
|
|
134
|
+
* parse. Closes this module's own documented conservative miss, but only
|
|
135
|
+
* for THIS check — `HOST_RICH_TYPE_NAMES`/method-call refusal still miss
|
|
136
|
+
* the keyword spellings, unchanged.
|
|
137
|
+
*/
|
|
138
|
+
export declare function jsonUnsafeTypeName(type: TypeInfo | null): string | null;
|
|
53
139
|
/**
|
|
54
140
|
* Resolve the TypeInfo of a receiver expression, using only propsType /
|
|
55
141
|
* propsParams / typeDefinitions and the caller-supplied local bindings.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rich-type-evidence.d.ts","sourceRoot":"","sources":["../src/rich-type-evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAgB,QAAQ,EAAE,MAAM,YAAY,CAAA;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAExD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAcnD,CAAA;AAEF;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGhD;AAED,KAAK,gBAAgB,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,GAAG,iBAAiB,GAAG,aAAa,GAAG,iBAAiB,CAAC,CAAA;AAkB7G,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,CAIjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,gBAAgB,GAAG,QAAQ,CAO/E;AAgBD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,gBAAgB,EACtB,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC,GAC7C,QAAQ,GAAG,IAAI,CAwBjB"}
|
|
1
|
+
{"version":3,"file":"rich-type-evidence.d.ts","sourceRoot":"","sources":["../src/rich-type-evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAgB,QAAQ,EAAE,MAAM,YAAY,CAAA;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAExD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAcnD,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,eAAO,MAAM,8BAA8B,EAAE,WAAW,CAAC,MAAM,CAA4B,CAAA;AAE3F;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,2BAA2B,EAAE,WAAW,CAAC,MAAM,CAE3D,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGhD;AAED,KAAK,gBAAgB,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,GAAG,iBAAiB,GAAG,aAAa,GAAG,iBAAiB,CAAC,CAAA;AAkB7G,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,CAIjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,gBAAgB,GAAG,QAAQ,CAO/E;AAgBD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,QAAQ,GAAG,IAAI,CAEjG;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAUvE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,gBAAgB,EACtB,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC,GAC7C,QAAQ,GAAG,IAAI,CAwBjB"}
|
|
@@ -1,17 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Rich-type
|
|
2
|
+
* Rich-type refusals: two sibling checks over a prop typed as a built-in
|
|
3
|
+
* "host rich type" (`Date`, `Map`, …), for the two distinct ways such a
|
|
4
|
+
* value breaks that have nothing to do with each other structurally.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
6
|
+
* `checkRichTypeMethodCalls` (#2273, BF021): a METHOD CALL on the receiver
|
|
7
|
+
* has no catalogued lowering — no adapter can emit `.toISOString()` into a
|
|
8
|
+
* template. Left unchecked, such a call transliterates into the target
|
|
9
|
+
* template's own dot-call syntax and dies at request time (a Go template
|
|
10
|
+
* `.CreatedAt.ToISOString` panic, a Jinja `AttributeError`, …), once per
|
|
11
|
+
* adapter, only once someone renders the page. This module makes that gap
|
|
12
|
+
* loud at compile time instead: `checkRichTypeMethodCalls` walks every
|
|
13
|
+
* expression position the compiler already treats as template-lowered and
|
|
14
|
+
* pushes BF021 for any call this build has no evidence a lowering plugin
|
|
13
15
|
* (or `/* @client *\/`) will handle.
|
|
14
16
|
*
|
|
17
|
+
* `checkRichTypePropSerialization` (#2643, BF049): a rich-typed prop is used
|
|
18
|
+
* anywhere in this component's own CLIENT code (a handler, an effect) —
|
|
19
|
+
* regardless of whether a method is ever called on it. `checkRichTypeMethodCalls`
|
|
20
|
+
* only walks expression positions reachable through template lowering (JSX
|
|
21
|
+
* text/attribute positions rendered at SSR); a handler or effect body is a
|
|
22
|
+
* different code path it never analyzes, so even a method call there (e.g.
|
|
23
|
+
* `data.get(...)` inside an `onClick`) is just as invisible to it as a bare
|
|
24
|
+
* read. Either way the prop still crosses the `bf-p` hydration boundary as
|
|
25
|
+
* JSON: it arrives de-riched (`Map`/`Set` → `{}`) or fails to serialize
|
|
26
|
+
* (`BigInt` throws at SSR render). See that function's own doc for
|
|
27
|
+
* why this is metadata-driven rather than an IR walk.
|
|
28
|
+
*
|
|
15
29
|
* Deliberately conservative in both directions:
|
|
16
30
|
* - `resolveReceiverType` (rich-type-evidence.ts) returns `null` — no
|
|
17
31
|
* opinion — for any receiver shape it can't prove a type for, so an
|
|
@@ -22,8 +36,21 @@
|
|
|
22
36
|
* claims (`prepareLoweringMatchers`) is exempt — the seam #2274 and
|
|
23
37
|
* later plugins use to catalogue a rich-type API without touching this
|
|
24
38
|
* module.
|
|
39
|
+
*
|
|
40
|
+
* Every receiver this module can prove a type for is rooted at `propsType`
|
|
41
|
+
* (`resolveReceiverType` only resolves a bare prop, a `props.x` chain, or a
|
|
42
|
+
* loop item of a prop array) — so it always crosses the `bf-p` hydration
|
|
43
|
+
* boundary as JSON. That means `/* @client *\/`, the escape this module used
|
|
44
|
+
* to recommend unconditionally, is UNSOUND on its own: the receiver arrives
|
|
45
|
+
* de-riched (a `Date` prop as an ISO string, a `Map`/`Set` as `{}`), so the
|
|
46
|
+
* spliced call throws or silently misbehaves at hydrate (#2636).
|
|
47
|
+
* `buildSuggestion` never offers a bare `/* @client *\/` for this reason —
|
|
48
|
+
* only a pre-compute-server-side escape (sound for every host rich type)
|
|
49
|
+
* and, for `Date`/`URL` only, a `/* @client *\/` block that explicitly
|
|
50
|
+
* revives the receiver first (`new Date(createdAt)...`), since those two
|
|
51
|
+
* types' `toJSON()` output round-trips through their own constructor.
|
|
25
52
|
*/
|
|
26
|
-
import type { IRNode, IRMetadata, CompilerError } from './types.ts';
|
|
53
|
+
import type { IRNode, IRMetadata, CompilerError, SourceLocation } from './types.ts';
|
|
27
54
|
/**
|
|
28
55
|
* Walk `root` looking for a method call on a host rich-typed receiver with
|
|
29
56
|
* no catalogued lowering, pushing BF021 into `errors` for each one found.
|
|
@@ -32,4 +59,25 @@ import type { IRNode, IRMetadata, CompilerError } from './types.ts';
|
|
|
32
59
|
* than attaching it, and additionally skips anything under `/* @client *\/`.
|
|
33
60
|
*/
|
|
34
61
|
export declare function checkRichTypeMethodCalls(root: IRNode, metadata: IRMetadata, errors: CompilerError[]): void;
|
|
62
|
+
/**
|
|
63
|
+
* BF049 (#2643): flag a prop typed as a JSON-unsafe host rich type
|
|
64
|
+
* (`Map`, `Set`, `BigInt`, …) that this component's own client code reads —
|
|
65
|
+
* regardless of whether a method is ever called on it, since
|
|
66
|
+
* `checkRichTypeMethodCalls` only walks template-lowered expression
|
|
67
|
+
* positions and never sees a handler/effect body either way. The prop still
|
|
68
|
+
* crosses the `bf-p` hydration boundary as JSON: it arrives de-riched
|
|
69
|
+
* (`Map`/`Set` → `{}`, every entry silently
|
|
70
|
+
* dropped) or fails to serialize at all (`BigInt` throws `TypeError` at SSR
|
|
71
|
+
* render, killing the whole page).
|
|
72
|
+
*
|
|
73
|
+
* Metadata-driven, not an IR walk — the fire condition is "this prop WILL BE
|
|
74
|
+
* SERIALIZED into bf-p", which is exactly what `ir.metadata.clientAnalysis`
|
|
75
|
+
* (`analyzeClientNeeds`) already decided, and what every adapter's own
|
|
76
|
+
* prop-serialization step (e.g. Hono's `propsToSerialize` filter in
|
|
77
|
+
* `hono-adapter.ts`) reads off the SAME metadata. Mirroring that filter here
|
|
78
|
+
* — rather than re-walking JSX attribute positions — means this check fires
|
|
79
|
+
* in lockstep with what actually gets serialized, on every adapter, without
|
|
80
|
+
* duplicating per-adapter serialization logic into the compiler.
|
|
81
|
+
*/
|
|
82
|
+
export declare function checkRichTypePropSerialization(root: IRNode, metadata: IRMetadata, errors: CompilerError[], declLoc?: SourceLocation): void;
|
|
35
83
|
//# sourceMappingURL=rich-type-refusal.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rich-type-refusal.d.ts","sourceRoot":"","sources":["../src/rich-type-refusal.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"rich-type-refusal.d.ts","sourceRoot":"","sources":["../src/rich-type-refusal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH,OAAO,KAAK,EACV,MAAM,EACN,UAAU,EACV,aAAa,EACb,cAAc,EAKf,MAAM,YAAY,CAAA;AAiBnB;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,CAQ1G;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,IAAI,CAe1I"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/jsx",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.7",
|
|
4
4
|
"description": "JSX compiler for BarefootJS - transforms JSX to server HTML + client JS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"directory": "packages/jsx"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@barefootjs/shared": "0.31.
|
|
52
|
+
"@barefootjs/shared": "0.31.7"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"@barefootjs/client": ">=0.2.0",
|