@barefootjs/hono 0.31.1 → 0.31.3
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/adapter/hono-adapter.d.ts +67 -2
- package/dist/adapter/hono-adapter.d.ts.map +1 -1
- package/dist/adapter/index.js +46 -187398
- package/dist/app.js +0 -71
- package/dist/async.js +0 -71
- package/dist/client-shim.js +0 -71
- package/dist/dev-worker.js +0 -71
- package/dist/dialog-context.js +0 -71
- package/dist/index.js +46 -187398
- package/dist/jsx/jsx-dev-runtime/index.d.ts +3 -1
- package/dist/jsx/jsx-dev-runtime/index.d.ts.map +1 -1
- package/dist/jsx/jsx-dev-runtime/index.js +14 -69
- package/dist/jsx/jsx-runtime/index.d.ts +4 -1
- package/dist/jsx/jsx-runtime/index.d.ts.map +1 -1
- package/dist/jsx/jsx-runtime/index.js +24 -69
- package/dist/jsx/resolve-dangerously-set-inner-html.d.ts +2 -0
- package/dist/jsx/resolve-dangerously-set-inner-html.d.ts.map +1 -0
- package/dist/portal-ssr.js +0 -71
- package/dist/portals.js +0 -71
- package/dist/preload.js +0 -71
- package/dist/render.js +0 -71
- package/dist/request-env.js +0 -71
- package/dist/scripts.js +0 -71
- package/dist/utils.js +0 -71
- package/dist/vite.js +394 -143
- package/package.json +2 -2
- package/src/__tests__/aliased-destructured-prop.test.ts +8 -7
- package/src/__tests__/consumer-typecheck.test.ts +358 -51
- package/src/__tests__/corpus-typecheck.test.ts +130 -0
- package/src/__tests__/dangerously-set-inner-html.test.ts +70 -0
- package/src/__tests__/nested-ternary-bare-branch.test.ts +70 -0
- package/src/adapter/hono-adapter.ts +123 -166
- package/src/jsx/jsx-dev-runtime/index.ts +13 -1
- package/src/jsx/jsx-runtime/index.ts +24 -1
- package/src/jsx/resolve-dangerously-set-inner-html.ts +34 -0
package/dist/vite.js
CHANGED
|
@@ -4,8 +4,11 @@ import { dirname, resolve } from "node:path";
|
|
|
4
4
|
import { barefoot as coreBarefoot } from "@barefootjs/vite";
|
|
5
5
|
import { devModuleUrl, loadManifest, resolveDevOrigin, resolveScriptAssets, toPosixRelative } from "@barefootjs/vite";
|
|
6
6
|
|
|
7
|
+
// ../jsx/src/compiler.ts
|
|
8
|
+
import ts23 from "typescript";
|
|
9
|
+
|
|
7
10
|
// ../jsx/src/analyzer.ts
|
|
8
|
-
import
|
|
11
|
+
import ts9 from "typescript";
|
|
9
12
|
|
|
10
13
|
// ../jsx/src/expression-parser.ts
|
|
11
14
|
import ts from "typescript";
|
|
@@ -98,6 +101,29 @@ function buildLoopChainExpr(opts) {
|
|
|
98
101
|
return `${opts.base}${sortExpr}${filterExpr}`;
|
|
99
102
|
}
|
|
100
103
|
|
|
104
|
+
// ../jsx/src/template-parts.ts
|
|
105
|
+
function lookupPartToJsExpr(part, opts) {
|
|
106
|
+
const key = opts?.useTemplate && part.templateKey ? part.templateKey : part.key;
|
|
107
|
+
const obj = "{" + Object.entries(part.cases).map(([k, v]) => `${JSON.stringify(k)}: ${JSON.stringify(v)}`).join(", ") + "}";
|
|
108
|
+
const typed = opts?.typed ? " as Record<string, string>" : "";
|
|
109
|
+
return `(${obj}${typed})[${key}]`;
|
|
110
|
+
}
|
|
111
|
+
function templatePartsToJsExpr(parts, opts) {
|
|
112
|
+
let result = "`";
|
|
113
|
+
for (const part of parts) {
|
|
114
|
+
if (part.type === "string") {
|
|
115
|
+
result += opts?.useTemplate && part.templateValue ? part.templateValue : part.value;
|
|
116
|
+
} else if (part.type === "ternary") {
|
|
117
|
+
const cond = opts?.useTemplate && part.templateCondition ? part.templateCondition : part.condition;
|
|
118
|
+
result += `\${${cond} ? '${part.whenTrue}' : '${part.whenFalse}'}`;
|
|
119
|
+
} else if (part.type === "lookup") {
|
|
120
|
+
result += `\${${lookupPartToJsExpr(part, opts)}}`;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
result += "`";
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
|
|
101
127
|
// ../jsx/src/scanner/js-scanner.ts
|
|
102
128
|
import ts2 from "typescript";
|
|
103
129
|
|
|
@@ -203,6 +229,16 @@ function escapeHtml(text) {
|
|
|
203
229
|
}
|
|
204
230
|
// ../jsx/src/ir-to-client-js/csr-substitute.ts
|
|
205
231
|
import ts4 from "typescript";
|
|
232
|
+
function extractFreeIdentifiersFromText(text) {
|
|
233
|
+
if (!text || text.trim().length === 0)
|
|
234
|
+
return new Set;
|
|
235
|
+
const sf = ts4.createSourceFile("__free_ids__.ts", `(${text});`, ts4.ScriptTarget.Latest, true, ts4.ScriptKind.TS);
|
|
236
|
+
const stmt = sf.statements[0];
|
|
237
|
+
if (!stmt || !ts4.isExpressionStatement(stmt))
|
|
238
|
+
return new Set;
|
|
239
|
+
const expr = ts4.isParenthesizedExpression(stmt.expression) ? stmt.expression.expression : stmt.expression;
|
|
240
|
+
return extractFreeIdentifiersFromNode(expr);
|
|
241
|
+
}
|
|
206
242
|
|
|
207
243
|
// ../jsx/src/ir-to-client-js/html-template.ts
|
|
208
244
|
var VOID_ELEMENTS = new Set([
|
|
@@ -248,6 +284,27 @@ var SKELETON_PATH_FORCE_CLOSE_GROUPS = [
|
|
|
248
284
|
new Set(["li"])
|
|
249
285
|
];
|
|
250
286
|
|
|
287
|
+
// ../jsx/src/props-binding.ts
|
|
288
|
+
import ts6 from "typescript";
|
|
289
|
+
function isIdentifierName(key) {
|
|
290
|
+
if (key.length === 0)
|
|
291
|
+
return false;
|
|
292
|
+
for (let i = 0;i < key.length; ) {
|
|
293
|
+
const cp = key.codePointAt(i);
|
|
294
|
+
const ok = i === 0 ? ts6.isIdentifierStart(cp, ts6.ScriptTarget.Latest) : ts6.isIdentifierPart(cp, ts6.ScriptTarget.Latest);
|
|
295
|
+
if (!ok)
|
|
296
|
+
return false;
|
|
297
|
+
i += cp > 65535 ? 2 : 1;
|
|
298
|
+
}
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
function propsDestructureBinding(p) {
|
|
302
|
+
const callerKey = p.sourceName ?? p.name;
|
|
303
|
+
const localName = p.name;
|
|
304
|
+
const binding = callerKey === localName ? localName : `${isIdentifierName(callerKey) ? callerKey : JSON.stringify(callerKey)}: ${localName}`;
|
|
305
|
+
return p.defaultValue ? `${binding} = ${p.defaultValue}` : binding;
|
|
306
|
+
}
|
|
307
|
+
|
|
251
308
|
// ../jsx/src/instrumentation.ts
|
|
252
309
|
var _counters = freshCounters();
|
|
253
310
|
function freshCounters() {
|
|
@@ -261,14 +318,14 @@ function freshCounters() {
|
|
|
261
318
|
}
|
|
262
319
|
|
|
263
320
|
// ../jsx/src/analyzer-context.ts
|
|
264
|
-
import
|
|
321
|
+
import ts8 from "typescript";
|
|
265
322
|
|
|
266
323
|
// ../jsx/src/strip-types.ts
|
|
267
|
-
import
|
|
324
|
+
import ts7 from "typescript";
|
|
268
325
|
|
|
269
326
|
// ../jsx/src/analyzer-context.ts
|
|
270
|
-
var _typePrinter =
|
|
271
|
-
var _blankTypeSourceFile =
|
|
327
|
+
var _typePrinter = ts8.createPrinter({ removeComments: true, omitTrailingSemicolon: true });
|
|
328
|
+
var _blankTypeSourceFile = ts8.createSourceFile("__bf_types__.ts", "", ts8.ScriptTarget.Latest);
|
|
272
329
|
|
|
273
330
|
// ../jsx/src/errors.ts
|
|
274
331
|
var ErrorCodes = {
|
|
@@ -284,6 +341,7 @@ var ErrorCodes = {
|
|
|
284
341
|
JSX_IN_LOCAL_FUNCTION: "BF045",
|
|
285
342
|
COMPONENT_REQUIRED_PROP_MISSING: "BF046",
|
|
286
343
|
JSX_BRANCH_LOCAL_IN_CALLBACK: "BF047",
|
|
344
|
+
SIBLING_COMPONENT_NOT_COMPILED: "BF048",
|
|
287
345
|
SHARED_PROGRAM_REQUIRED: "BF050",
|
|
288
346
|
WRONG_PACKAGE_IMPORT: "BF051",
|
|
289
347
|
BUILTIN_REQUIRES_IMPORT: "BF054",
|
|
@@ -313,6 +371,7 @@ var errorMessages = {
|
|
|
313
371
|
[ErrorCodes.JSX_IN_LOCAL_FUNCTION]: "Local function returns JSX but cannot be inlined. Extract it as a top-level PascalCase component or use a single return statement.",
|
|
314
372
|
[ErrorCodes.COMPONENT_REQUIRED_PROP_MISSING]: "Built-in component is missing a required prop.",
|
|
315
373
|
[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>`.",
|
|
374
|
+
[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.",
|
|
316
375
|
[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.",
|
|
317
376
|
[ErrorCodes.WRONG_PACKAGE_IMPORT]: "Import from wrong package.",
|
|
318
377
|
[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.",
|
|
@@ -486,6 +545,54 @@ var CLIENT_EXPORTS = new Set([
|
|
|
486
545
|
"Async",
|
|
487
546
|
"Region"
|
|
488
547
|
]);
|
|
548
|
+
function extractFreeIdentifiersFromNode(node) {
|
|
549
|
+
const ids = new Set;
|
|
550
|
+
const boundNames = new Set;
|
|
551
|
+
function addBindingNames(name, out) {
|
|
552
|
+
if (ts9.isIdentifier(name))
|
|
553
|
+
out.push(name.text);
|
|
554
|
+
else if (ts9.isObjectBindingPattern(name))
|
|
555
|
+
name.elements.forEach((e) => addBindingNames(e.name, out));
|
|
556
|
+
else if (ts9.isArrayBindingPattern(name))
|
|
557
|
+
name.elements.forEach((e) => {
|
|
558
|
+
if (!ts9.isOmittedExpression(e))
|
|
559
|
+
addBindingNames(e.name, out);
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
function visit(n) {
|
|
563
|
+
if (ts9.isTypeNode(n))
|
|
564
|
+
return;
|
|
565
|
+
if (ts9.isIdentifier(n)) {
|
|
566
|
+
const parent = n.parent;
|
|
567
|
+
if (parent && ts9.isPropertyAccessExpression(parent) && parent.name === n)
|
|
568
|
+
return;
|
|
569
|
+
if (parent && ts9.isPropertyAssignment(parent) && parent.name === n)
|
|
570
|
+
return;
|
|
571
|
+
if (parent && ts9.isParameter(parent) && parent.name === n)
|
|
572
|
+
return;
|
|
573
|
+
if (parent && ts9.isVariableDeclaration(parent) && parent.name === n)
|
|
574
|
+
return;
|
|
575
|
+
if (boundNames.has(n.text))
|
|
576
|
+
return;
|
|
577
|
+
ids.add(n.text);
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
if (ts9.isArrowFunction(n)) {
|
|
581
|
+
const params = [];
|
|
582
|
+
for (const p of n.parameters)
|
|
583
|
+
addBindingNames(p.name, params);
|
|
584
|
+
for (const name of params)
|
|
585
|
+
boundNames.add(name);
|
|
586
|
+
ts9.forEachChild(n, visit);
|
|
587
|
+
for (const name of params)
|
|
588
|
+
boundNames.delete(name);
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
ts9.forEachChild(n, visit);
|
|
592
|
+
}
|
|
593
|
+
visit(node);
|
|
594
|
+
return ids;
|
|
595
|
+
}
|
|
489
596
|
var BROWSER_ONLY_CLIENT_APIS = new Set([
|
|
490
597
|
"useContext",
|
|
491
598
|
"provideContext",
|
|
@@ -504,7 +611,7 @@ var REACTIVE_PRIMITIVES = new Set([
|
|
|
504
611
|
]);
|
|
505
612
|
|
|
506
613
|
// ../jsx/src/jsx-to-ir.ts
|
|
507
|
-
import
|
|
614
|
+
import ts12 from "typescript";
|
|
508
615
|
|
|
509
616
|
// ../jsx/src/types.ts
|
|
510
617
|
var SCOPE_FORBIDDEN = {
|
|
@@ -572,10 +679,10 @@ function findReachableNames(primaryRefs, declarations) {
|
|
|
572
679
|
}
|
|
573
680
|
|
|
574
681
|
// ../jsx/src/reactivity-checker.ts
|
|
575
|
-
import
|
|
682
|
+
import ts10 from "typescript";
|
|
576
683
|
|
|
577
684
|
// ../jsx/src/free-refs.ts
|
|
578
|
-
import
|
|
685
|
+
import ts11 from "typescript";
|
|
579
686
|
var _bindingMapCache = new WeakMap;
|
|
580
687
|
|
|
581
688
|
// ../jsx/src/to-locale-date-lowering.ts
|
|
@@ -893,6 +1000,83 @@ var toLocaleDatePlugin = {
|
|
|
893
1000
|
}
|
|
894
1001
|
};
|
|
895
1002
|
|
|
1003
|
+
// ../jsx/src/scope/binding-scope.ts
|
|
1004
|
+
class BindingScope {
|
|
1005
|
+
frames;
|
|
1006
|
+
static EMPTY = new BindingScope([]);
|
|
1007
|
+
constructor(frames) {
|
|
1008
|
+
this.frames = frames;
|
|
1009
|
+
}
|
|
1010
|
+
enterLoopRow(loop) {
|
|
1011
|
+
const bindings = new Map;
|
|
1012
|
+
if (loop.paramBindings && loop.paramBindings.length > 0) {
|
|
1013
|
+
for (const b of loop.paramBindings)
|
|
1014
|
+
bindings.set(b.name, { source: "destructure" });
|
|
1015
|
+
} else {
|
|
1016
|
+
bindings.set(loop.param, { source: "item" });
|
|
1017
|
+
}
|
|
1018
|
+
if (loop.index != null)
|
|
1019
|
+
bindings.set(loop.index, { source: "index" });
|
|
1020
|
+
for (const name of loop.preamble?.declaredNames ?? [])
|
|
1021
|
+
bindings.set(name, { source: "preamble" });
|
|
1022
|
+
const frame = { kind: "loop-row", bindings };
|
|
1023
|
+
return new BindingScope([frame, ...this.frames]);
|
|
1024
|
+
}
|
|
1025
|
+
enterCallback(params) {
|
|
1026
|
+
const bindings = new Map;
|
|
1027
|
+
for (const name of params)
|
|
1028
|
+
bindings.set(name, { source: "param" });
|
|
1029
|
+
const frame = { kind: "callback", bindings };
|
|
1030
|
+
return new BindingScope([frame, ...this.frames]);
|
|
1031
|
+
}
|
|
1032
|
+
isBound(name) {
|
|
1033
|
+
for (const frame of this.frames) {
|
|
1034
|
+
if (frame.bindings.has(name))
|
|
1035
|
+
return true;
|
|
1036
|
+
}
|
|
1037
|
+
return false;
|
|
1038
|
+
}
|
|
1039
|
+
lookup(name) {
|
|
1040
|
+
for (let depth = 0;depth < this.frames.length; depth++) {
|
|
1041
|
+
const frame = this.frames[depth];
|
|
1042
|
+
const binding = frame.bindings.get(name);
|
|
1043
|
+
if (binding)
|
|
1044
|
+
return { depth, frame, binding };
|
|
1045
|
+
}
|
|
1046
|
+
return null;
|
|
1047
|
+
}
|
|
1048
|
+
boundNames() {
|
|
1049
|
+
if (this.boundNamesCache)
|
|
1050
|
+
return this.boundNamesCache;
|
|
1051
|
+
const names = new Set;
|
|
1052
|
+
for (const frame of this.frames) {
|
|
1053
|
+
for (const name of frame.bindings.keys())
|
|
1054
|
+
names.add(name);
|
|
1055
|
+
}
|
|
1056
|
+
this.boundNamesCache = names;
|
|
1057
|
+
return names;
|
|
1058
|
+
}
|
|
1059
|
+
boundNamesCache;
|
|
1060
|
+
valueBoundNamesCache;
|
|
1061
|
+
valueBoundNames() {
|
|
1062
|
+
if (this.valueBoundNamesCache)
|
|
1063
|
+
return this.valueBoundNamesCache;
|
|
1064
|
+
const names = new Set;
|
|
1065
|
+
for (const frame of this.frames) {
|
|
1066
|
+
for (const [name, binding] of frame.bindings) {
|
|
1067
|
+
if (binding.source === "item" || binding.source === "index" || binding.source === "destructure") {
|
|
1068
|
+
names.add(name);
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
this.valueBoundNamesCache = names;
|
|
1073
|
+
return names;
|
|
1074
|
+
}
|
|
1075
|
+
asShadowPredicate() {
|
|
1076
|
+
return (name) => this.isBound(name);
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
|
|
896
1080
|
// ../jsx/src/jsx-to-ir.ts
|
|
897
1081
|
var EMPTY_BOUND = new Set;
|
|
898
1082
|
var constInitializerCache = new WeakMap;
|
|
@@ -989,13 +1173,13 @@ var KEYWORDS_AND_GLOBALS = new Set([
|
|
|
989
1173
|
]);
|
|
990
1174
|
|
|
991
1175
|
// ../jsx/src/ir-to-client-js/walk-prop-accesses.ts
|
|
992
|
-
import
|
|
1176
|
+
import ts13 from "typescript";
|
|
993
1177
|
|
|
994
1178
|
// ../jsx/src/value-references.ts
|
|
995
|
-
import
|
|
1179
|
+
import ts14 from "typescript";
|
|
996
1180
|
|
|
997
1181
|
// ../jsx/src/relocate.ts
|
|
998
|
-
import
|
|
1182
|
+
import ts15 from "typescript";
|
|
999
1183
|
|
|
1000
1184
|
// ../jsx/src/lowering-registry.ts
|
|
1001
1185
|
var plugins = [];
|
|
@@ -1174,10 +1358,10 @@ function formatDateLocalNames(metadata) {
|
|
|
1174
1358
|
}
|
|
1175
1359
|
|
|
1176
1360
|
// ../jsx/src/ir-to-client-js/prune-unused-prop-extractions.ts
|
|
1177
|
-
import
|
|
1361
|
+
import ts16 from "typescript";
|
|
1178
1362
|
|
|
1179
1363
|
// ../jsx/src/ir-to-client-js/control-flow/plan/lazy-preamble.ts
|
|
1180
|
-
import
|
|
1364
|
+
import ts17 from "typescript";
|
|
1181
1365
|
var NO_PREAMBLE = {
|
|
1182
1366
|
lazySafe: true,
|
|
1183
1367
|
facts: { declaredNames: new Set, freeNames: new Set }
|
|
@@ -1227,7 +1411,7 @@ var INERT_BINDING_GLOBALS = new Set([
|
|
|
1227
1411
|
]);
|
|
1228
1412
|
|
|
1229
1413
|
// ../jsx/src/ir-to-client-js/emit-reactive.ts
|
|
1230
|
-
import
|
|
1414
|
+
import ts18 from "typescript";
|
|
1231
1415
|
|
|
1232
1416
|
// ../jsx/src/ir-to-client-js/control-flow/stringify/event-delegation.ts
|
|
1233
1417
|
var NON_BUBBLING_EVENTS = new Set([
|
|
@@ -1242,7 +1426,7 @@ var NON_BUBBLING_EVENTS = new Set([
|
|
|
1242
1426
|
]);
|
|
1243
1427
|
|
|
1244
1428
|
// ../jsx/src/ir-to-client-js/rewrite-props-object.ts
|
|
1245
|
-
import
|
|
1429
|
+
import ts19 from "typescript";
|
|
1246
1430
|
|
|
1247
1431
|
// ../jsx/src/ir-to-client-js/source-map.ts
|
|
1248
1432
|
var BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
@@ -1333,20 +1517,20 @@ class SourceMapGenerator {
|
|
|
1333
1517
|
}
|
|
1334
1518
|
|
|
1335
1519
|
// ../jsx/src/preprocess-inline-jsx-callbacks.ts
|
|
1336
|
-
import
|
|
1520
|
+
import ts20 from "typescript";
|
|
1337
1521
|
|
|
1338
1522
|
// ../jsx/src/ssr-defaults.ts
|
|
1339
|
-
import
|
|
1523
|
+
import ts21 from "typescript";
|
|
1340
1524
|
var UNRESOLVED = Symbol("unresolved");
|
|
1341
1525
|
var NO_RETURN = Symbol("no-return");
|
|
1342
1526
|
|
|
1343
1527
|
// ../jsx/src/augment-inherited-props.ts
|
|
1344
|
-
import
|
|
1528
|
+
import ts22 from "typescript";
|
|
1345
1529
|
|
|
1346
1530
|
// ../jsx/src/rich-type-refusal.ts
|
|
1347
1531
|
var EMPTY_BINDINGS2 = new Map;
|
|
1348
1532
|
// ../jsx/src/shared-program.ts
|
|
1349
|
-
import
|
|
1533
|
+
import ts24 from "typescript";
|
|
1350
1534
|
// ../jsx/src/adapters/interface.ts
|
|
1351
1535
|
class BaseAdapter {
|
|
1352
1536
|
renderChildren(children) {
|
|
@@ -1422,7 +1606,7 @@ class JsxAdapter extends BaseAdapter {
|
|
|
1422
1606
|
}
|
|
1423
1607
|
const rawInitialValue = preserveTypes ? signal.typedInitialValue ?? signal.initialValue : signal.initialValue;
|
|
1424
1608
|
const initialValue = rawInitialValue.trim().startsWith("{") ? `(${rawInitialValue})` : rawInitialValue;
|
|
1425
|
-
const needsTypeAssertion = preserveTypes && !signal.typedInitialValue && signal.type.kind !== "unknown" && signal.type.kind !== "primitive";
|
|
1609
|
+
const needsTypeAssertion = preserveTypes && !signal.typedInitialValue && signal.type.kind !== "unknown" && signal.type.kind !== "primitive" && signal.type.raw !== "object";
|
|
1426
1610
|
if (needsTypeAssertion) {
|
|
1427
1611
|
lines.push(` const ${signal.getter} = () => ${initialValue} as ${signal.type.raw}`);
|
|
1428
1612
|
} else {
|
|
@@ -1441,12 +1625,16 @@ class JsxAdapter extends BaseAdapter {
|
|
|
1441
1625
|
const computation = preserveTypes ? memo.typedComputation ?? memo.computation : memo.computation;
|
|
1442
1626
|
lines.push(` const ${memo.name} = ${computation}`);
|
|
1443
1627
|
}
|
|
1628
|
+
const moduleScopeNames = this.moduleScopeDeclarationNames(ir);
|
|
1444
1629
|
for (const constant of ir.metadata.localConstants) {
|
|
1445
1630
|
if (constant.isExported)
|
|
1446
1631
|
continue;
|
|
1632
|
+
if (moduleScopeNames.has(constant.name))
|
|
1633
|
+
continue;
|
|
1447
1634
|
const keyword = constant.declarationKind ?? "const";
|
|
1448
1635
|
if (!constant.value) {
|
|
1449
|
-
|
|
1636
|
+
const typeAnnotation = preserveTypes && (constant.typeAnnotation ?? constant.type) ? `: ${constant.typeAnnotation ?? constant.type?.raw}` : "";
|
|
1637
|
+
lines.push(` ${keyword} ${constant.name}${typeAnnotation}`);
|
|
1450
1638
|
continue;
|
|
1451
1639
|
}
|
|
1452
1640
|
const value = constant.value.trim();
|
|
@@ -1455,9 +1643,12 @@ class JsxAdapter extends BaseAdapter {
|
|
|
1455
1643
|
if (!reachable.has(constant.name))
|
|
1456
1644
|
continue;
|
|
1457
1645
|
const constValue = preserveTypes ? constant.typedValue ?? constant.value : constant.value;
|
|
1458
|
-
|
|
1646
|
+
const letTypeAnnotation = preserveTypes && keyword === "let" && constant.typeAnnotation ? `: ${constant.typeAnnotation}` : "";
|
|
1647
|
+
lines.push(` ${keyword} ${constant.name}${letTypeAnnotation} = ${constValue}`);
|
|
1459
1648
|
}
|
|
1460
1649
|
for (const func of localFunctions) {
|
|
1650
|
+
if (moduleScopeNames.has(func.name))
|
|
1651
|
+
continue;
|
|
1461
1652
|
if (!reachable.has(func.name))
|
|
1462
1653
|
continue;
|
|
1463
1654
|
const params = preserveTypes && func.typedParams !== undefined ? func.typedParams : func.params.map(formatParamWithType).join(", ");
|
|
@@ -1467,6 +1658,127 @@ class JsxAdapter extends BaseAdapter {
|
|
|
1467
1658
|
lines.push(` ${asyncKw}function ${func.name}(${params})${returnAnnotation} ${body}`);
|
|
1468
1659
|
}
|
|
1469
1660
|
return lines.join(`
|
|
1661
|
+
`);
|
|
1662
|
+
}
|
|
1663
|
+
moduleScopeNamesCache = new WeakMap;
|
|
1664
|
+
moduleScopeDeclarationNames(ir) {
|
|
1665
|
+
const cached = this.moduleScopeNamesCache.get(ir);
|
|
1666
|
+
if (cached)
|
|
1667
|
+
return cached;
|
|
1668
|
+
const componentScope = new Set;
|
|
1669
|
+
for (const sig of ir.metadata.signals) {
|
|
1670
|
+
if (sig.isModule)
|
|
1671
|
+
continue;
|
|
1672
|
+
componentScope.add(sig.getter);
|
|
1673
|
+
if (sig.setter)
|
|
1674
|
+
componentScope.add(sig.setter);
|
|
1675
|
+
}
|
|
1676
|
+
for (const memo of ir.metadata.memos) {
|
|
1677
|
+
if (!memo.isModule)
|
|
1678
|
+
componentScope.add(memo.name);
|
|
1679
|
+
}
|
|
1680
|
+
for (const p of ir.metadata.propsParams)
|
|
1681
|
+
componentScope.add(p.name);
|
|
1682
|
+
if (ir.metadata.propsObjectName)
|
|
1683
|
+
componentScope.add(ir.metadata.propsObjectName);
|
|
1684
|
+
if (ir.metadata.restPropsName)
|
|
1685
|
+
componentScope.add(ir.metadata.restPropsName);
|
|
1686
|
+
for (const c of ir.metadata.localConstants) {
|
|
1687
|
+
if (!c.isModule)
|
|
1688
|
+
componentScope.add(c.name);
|
|
1689
|
+
}
|
|
1690
|
+
for (const f of ir.metadata.localFunctions) {
|
|
1691
|
+
if (!f.isModule)
|
|
1692
|
+
componentScope.add(f.name);
|
|
1693
|
+
}
|
|
1694
|
+
const exported = new Set;
|
|
1695
|
+
const candidates = new Map;
|
|
1696
|
+
for (const c of ir.metadata.localConstants) {
|
|
1697
|
+
if (!c.isModule)
|
|
1698
|
+
continue;
|
|
1699
|
+
if (c.isJsx || c.isJsxFunction)
|
|
1700
|
+
continue;
|
|
1701
|
+
if (c.isExported) {
|
|
1702
|
+
exported.add(c.name);
|
|
1703
|
+
continue;
|
|
1704
|
+
}
|
|
1705
|
+
candidates.set(c.name, c.freeIdentifiers ?? extractFreeIdentifiersFromText(c.value ?? ""));
|
|
1706
|
+
}
|
|
1707
|
+
for (const f of ir.metadata.localFunctions) {
|
|
1708
|
+
if (!f.isModule)
|
|
1709
|
+
continue;
|
|
1710
|
+
if (f.isJsxFunction || f.isMultiReturnJsxHelper)
|
|
1711
|
+
continue;
|
|
1712
|
+
if (f.isExported) {
|
|
1713
|
+
exported.add(f.name);
|
|
1714
|
+
continue;
|
|
1715
|
+
}
|
|
1716
|
+
const params = f.typedParams !== undefined ? f.typedParams : f.params.map(formatParamWithType).join(", ");
|
|
1717
|
+
candidates.set(f.name, extractFreeIdentifiersFromText(`(${params}) => ${f.body}`));
|
|
1718
|
+
}
|
|
1719
|
+
const referencesAny = (refs, names) => {
|
|
1720
|
+
for (const ref of refs) {
|
|
1721
|
+
if (names.has(ref))
|
|
1722
|
+
return true;
|
|
1723
|
+
}
|
|
1724
|
+
return false;
|
|
1725
|
+
};
|
|
1726
|
+
let changed = true;
|
|
1727
|
+
while (changed) {
|
|
1728
|
+
changed = false;
|
|
1729
|
+
for (const [name, refs] of candidates) {
|
|
1730
|
+
if (referencesAny(refs, componentScope)) {
|
|
1731
|
+
candidates.delete(name);
|
|
1732
|
+
componentScope.add(name);
|
|
1733
|
+
changed = true;
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
const result = new Set([...exported, ...candidates.keys()]);
|
|
1738
|
+
this.moduleScopeNamesCache.set(ir, result);
|
|
1739
|
+
return result;
|
|
1740
|
+
}
|
|
1741
|
+
generateModuleScopeDeclarations(ir) {
|
|
1742
|
+
const { preserveTypes } = this.jsxConfig;
|
|
1743
|
+
const moduleNames = this.moduleScopeDeclarationNames(ir);
|
|
1744
|
+
const entries = [];
|
|
1745
|
+
for (const t of ir.metadata.typeDefinitions) {
|
|
1746
|
+
entries.push({ line: t.loc.start.line, text: t.definition });
|
|
1747
|
+
}
|
|
1748
|
+
for (const c of ir.metadata.localConstants) {
|
|
1749
|
+
if (!c.isModule || !moduleNames.has(c.name))
|
|
1750
|
+
continue;
|
|
1751
|
+
const keyword = c.declarationKind ?? "const";
|
|
1752
|
+
const exportKw = c.isExported ? "export " : "";
|
|
1753
|
+
if (!c.value) {
|
|
1754
|
+
const typeAnnotation = preserveTypes && (c.typeAnnotation ?? c.type) ? `: ${c.typeAnnotation ?? c.type?.raw}` : "";
|
|
1755
|
+
entries.push({ line: c.loc.start.line, text: `${exportKw}${keyword} ${c.name}${typeAnnotation}` });
|
|
1756
|
+
continue;
|
|
1757
|
+
}
|
|
1758
|
+
const trimmed = c.value.trim();
|
|
1759
|
+
if (/^new WeakMap\b/.test(trimmed))
|
|
1760
|
+
continue;
|
|
1761
|
+
if (c.isExported && /^createContext\b/.test(trimmed))
|
|
1762
|
+
continue;
|
|
1763
|
+
const value = preserveTypes ? c.typedValue ?? c.value : c.value;
|
|
1764
|
+
const letTypeAnnotation = preserveTypes && keyword === "let" && c.typeAnnotation ? `: ${c.typeAnnotation}` : "";
|
|
1765
|
+
entries.push({ line: c.loc.start.line, text: `${exportKw}${keyword} ${c.name}${letTypeAnnotation} = ${value}` });
|
|
1766
|
+
}
|
|
1767
|
+
for (const f of ir.metadata.localFunctions) {
|
|
1768
|
+
if (!f.isModule || !moduleNames.has(f.name))
|
|
1769
|
+
continue;
|
|
1770
|
+
const params = preserveTypes && f.typedParams !== undefined ? f.typedParams : f.params.map(formatParamWithType).join(", ");
|
|
1771
|
+
const returnAnnotation = preserveTypes && f.typedReturnType ? `: ${f.typedReturnType}` : "";
|
|
1772
|
+
const body = preserveTypes ? f.typedBody ?? f.body : f.body;
|
|
1773
|
+
const asyncKw = f.isAsync ? "async " : "";
|
|
1774
|
+
const exportKw = f.isExported ? "export " : "";
|
|
1775
|
+
entries.push({
|
|
1776
|
+
line: f.loc.start.line,
|
|
1777
|
+
text: `${exportKw}${asyncKw}function ${f.name}(${params})${returnAnnotation} ${body}`
|
|
1778
|
+
});
|
|
1779
|
+
}
|
|
1780
|
+
entries.sort((a, b) => a.line - b.line);
|
|
1781
|
+
return entries.map((e) => e.text).join(`
|
|
1470
1782
|
`);
|
|
1471
1783
|
}
|
|
1472
1784
|
renderNodeRaw(node) {
|
|
@@ -1478,6 +1790,15 @@ class JsxAdapter extends BaseAdapter {
|
|
|
1478
1790
|
}
|
|
1479
1791
|
return this.renderNode(node);
|
|
1480
1792
|
}
|
|
1793
|
+
renderTemplatePartsAsJs(parts) {
|
|
1794
|
+
return templatePartsToJsExpr(parts, { typed: this.jsxConfig.preserveTypes });
|
|
1795
|
+
}
|
|
1796
|
+
expressionValueToJs(value) {
|
|
1797
|
+
if (this.jsxConfig.preserveTypes && value.parts && value.expr === templatePartsToJsExpr(value.parts)) {
|
|
1798
|
+
return this.renderTemplatePartsAsJs(value.parts);
|
|
1799
|
+
}
|
|
1800
|
+
return value.expr;
|
|
1801
|
+
}
|
|
1481
1802
|
renderScopeMarker(instanceIdExpr) {
|
|
1482
1803
|
return `${BF_SCOPE}={${instanceIdExpr}}`;
|
|
1483
1804
|
}
|
|
@@ -1545,6 +1866,7 @@ class TestAdapter extends JsxAdapter {
|
|
|
1545
1866
|
generate(ir) {
|
|
1546
1867
|
this.componentName = ir.metadata.componentName;
|
|
1547
1868
|
const imports = this.generateImports(ir);
|
|
1869
|
+
const moduleConstants = this.generateModuleScopeDeclarations(ir);
|
|
1548
1870
|
const types = this.generateTypes(ir);
|
|
1549
1871
|
const component = this.generateComponent(ir);
|
|
1550
1872
|
const defaultExport = ir.metadata.hasDefaultExport ? `
|
|
@@ -1553,9 +1875,11 @@ export default ${this.componentName}` : "";
|
|
|
1553
1875
|
imports,
|
|
1554
1876
|
types: types || "",
|
|
1555
1877
|
component,
|
|
1556
|
-
defaultExport
|
|
1878
|
+
defaultExport,
|
|
1879
|
+
moduleConstants,
|
|
1880
|
+
moduleConstantsIncludeExports: true
|
|
1557
1881
|
};
|
|
1558
|
-
const template = [imports, types, component].filter(Boolean).join(`
|
|
1882
|
+
const template = [imports, moduleConstants, types, component].filter(Boolean).join(`
|
|
1559
1883
|
|
|
1560
1884
|
`) + defaultExport;
|
|
1561
1885
|
return {
|
|
@@ -1586,9 +1910,6 @@ export default ${this.componentName}` : "";
|
|
|
1586
1910
|
}
|
|
1587
1911
|
generateTypes(ir) {
|
|
1588
1912
|
const lines = [];
|
|
1589
|
-
for (const typeDef of ir.metadata.typeDefinitions) {
|
|
1590
|
-
lines.push(typeDef.definition);
|
|
1591
|
-
}
|
|
1592
1913
|
const propsTypeName = ir.metadata.propsType?.raw;
|
|
1593
1914
|
if (propsTypeName && !ir.metadata.propsObjectName) {
|
|
1594
1915
|
lines.push("");
|
|
@@ -1611,7 +1932,7 @@ export default ${this.componentName}` : "";
|
|
|
1611
1932
|
const bodyRefText = [jsxBody, signalInits, scopeIdLine].join(`
|
|
1612
1933
|
`);
|
|
1613
1934
|
const bfScopeAlias = /\b__bfScope\b/.test(bodyRefText) ? "__bfScope" : "__bfScope: _bfScope";
|
|
1614
|
-
const propsParams = ir.metadata.propsParams.map((p) => p
|
|
1935
|
+
const propsParams = ir.metadata.propsParams.map((p) => propsDestructureBinding(p)).join(", ");
|
|
1615
1936
|
const restPropsName = ir.metadata.restPropsName;
|
|
1616
1937
|
const hydrationProps = `__instanceId, ${bfScopeAlias}`;
|
|
1617
1938
|
const parts = [];
|
|
@@ -1758,13 +2079,7 @@ export default ${this.componentName}` : "";
|
|
|
1758
2079
|
}
|
|
1759
2080
|
flattenTemplate(value) {
|
|
1760
2081
|
const v = value;
|
|
1761
|
-
return
|
|
1762
|
-
if (p.type === "string")
|
|
1763
|
-
return p.value;
|
|
1764
|
-
if (p.type === "ternary")
|
|
1765
|
-
return `\${${p.condition} ? '${p.whenTrue}' : '${p.whenFalse}'}`;
|
|
1766
|
-
return `\${(${JSON.stringify(p.cases)})[${p.key}]}`;
|
|
1767
|
-
}).join("") + "`";
|
|
2082
|
+
return this.renderTemplatePartsAsJs(v.parts);
|
|
1768
2083
|
}
|
|
1769
2084
|
renderComponentProps(comp) {
|
|
1770
2085
|
const parts = [];
|
|
@@ -1940,17 +2255,16 @@ function emitAttrValue(value, emitter, name) {
|
|
|
1940
2255
|
}
|
|
1941
2256
|
}
|
|
1942
2257
|
// ../jsx/src/combine-client-js.ts
|
|
1943
|
-
import
|
|
2258
|
+
import ts25 from "typescript";
|
|
1944
2259
|
// ../jsx/src/debug.ts
|
|
1945
|
-
import
|
|
2260
|
+
import ts26 from "typescript";
|
|
1946
2261
|
// ../jsx/src/profiler.ts
|
|
1947
|
-
import
|
|
2262
|
+
import ts27 from "typescript";
|
|
1948
2263
|
|
|
1949
2264
|
// ../jsx/src/index.ts
|
|
1950
2265
|
registerBuiltinLoweringPlugins();
|
|
1951
2266
|
|
|
1952
2267
|
// src/adapter/hono-adapter.ts
|
|
1953
|
-
import ts26 from "typescript";
|
|
1954
2268
|
function applyHonoLoopChain(loop) {
|
|
1955
2269
|
return buildLoopChainExpr({
|
|
1956
2270
|
base: loop.array,
|
|
@@ -1959,18 +2273,6 @@ function applyHonoLoopChain(loop) {
|
|
|
1959
2273
|
chainOrder: loop.chainOrder
|
|
1960
2274
|
});
|
|
1961
2275
|
}
|
|
1962
|
-
function isIdentifierName(key) {
|
|
1963
|
-
if (key.length === 0)
|
|
1964
|
-
return false;
|
|
1965
|
-
for (let i = 0;i < key.length; ) {
|
|
1966
|
-
const cp = key.codePointAt(i);
|
|
1967
|
-
const ok = i === 0 ? ts26.isIdentifierStart(cp, ts26.ScriptTarget.Latest) : ts26.isIdentifierPart(cp, ts26.ScriptTarget.Latest);
|
|
1968
|
-
if (!ok)
|
|
1969
|
-
return false;
|
|
1970
|
-
i += cp > 65535 ? 2 : 1;
|
|
1971
|
-
}
|
|
1972
|
-
return true;
|
|
1973
|
-
}
|
|
1974
2276
|
|
|
1975
2277
|
class HonoAdapter extends JsxAdapter {
|
|
1976
2278
|
name = "hono";
|
|
@@ -2008,11 +2310,11 @@ class HonoAdapter extends JsxAdapter {
|
|
|
2008
2310
|
this.preloadAssets = options?.preloadAssets;
|
|
2009
2311
|
}
|
|
2010
2312
|
const component = this.generateComponent(ir);
|
|
2011
|
-
const types = this.generateTypes(ir
|
|
2012
|
-
const
|
|
2313
|
+
const types = this.generateTypes(ir);
|
|
2314
|
+
const moduleConstants = this.generateModuleScopeDeclarations(ir);
|
|
2315
|
+
const componentCode = [moduleConstants, types, component].filter(Boolean).join(`
|
|
2013
2316
|
`);
|
|
2014
2317
|
const imports = this.generateImports(ir, componentCode);
|
|
2015
|
-
const moduleConstants = this.generateModuleLevelContextBindings(ir);
|
|
2016
2318
|
const defaultExport = ir.metadata.hasDefaultExport ? `
|
|
2017
2319
|
export default ${this.componentName}` : "";
|
|
2018
2320
|
const sections = {
|
|
@@ -2020,7 +2322,8 @@ export default ${this.componentName}` : "";
|
|
|
2020
2322
|
types: types || "",
|
|
2021
2323
|
component,
|
|
2022
2324
|
defaultExport,
|
|
2023
|
-
moduleConstants
|
|
2325
|
+
moduleConstants,
|
|
2326
|
+
moduleConstantsIncludeExports: true
|
|
2024
2327
|
};
|
|
2025
2328
|
const template = [imports, moduleConstants, types, component].filter(Boolean).join(`
|
|
2026
2329
|
|
|
@@ -2042,24 +2345,6 @@ export default ${this.componentName}` : "";
|
|
|
2042
2345
|
hasPreloadAssets() {
|
|
2043
2346
|
return this.hasScriptAssets() && !!this.preloadAssets && this.preloadAssets.length > 0;
|
|
2044
2347
|
}
|
|
2045
|
-
generateModuleLevelContextBindings(ir) {
|
|
2046
|
-
const lines = [];
|
|
2047
|
-
for (const c of ir.metadata.localConstants) {
|
|
2048
|
-
if (!c.isModule)
|
|
2049
|
-
continue;
|
|
2050
|
-
if (c.isExported)
|
|
2051
|
-
continue;
|
|
2052
|
-
if (c.systemConstructKind !== "createContext")
|
|
2053
|
-
continue;
|
|
2054
|
-
if (!c.value)
|
|
2055
|
-
continue;
|
|
2056
|
-
const keyword = c.declarationKind ?? "const";
|
|
2057
|
-
const value = this.jsxConfig.preserveTypes ? c.typedValue ?? c.value : c.value;
|
|
2058
|
-
lines.push(`${keyword} ${c.name} = ${value}`);
|
|
2059
|
-
}
|
|
2060
|
-
return lines.join(`
|
|
2061
|
-
`);
|
|
2062
|
-
}
|
|
2063
2348
|
generateImports(ir, componentCode) {
|
|
2064
2349
|
const lines = [];
|
|
2065
2350
|
const utilImports = [];
|
|
@@ -2101,50 +2386,10 @@ export default ${this.componentName}` : "";
|
|
|
2101
2386
|
return lines.join(`
|
|
2102
2387
|
`);
|
|
2103
2388
|
}
|
|
2104
|
-
generateTypes(ir
|
|
2389
|
+
generateTypes(ir) {
|
|
2105
2390
|
const lines = [];
|
|
2106
|
-
if (componentBody && ir.metadata.typeDefinitions.length > 0) {
|
|
2107
|
-
const propsTypeName2 = this.getPropsTypeName(ir);
|
|
2108
|
-
const seedText = [
|
|
2109
|
-
componentBody,
|
|
2110
|
-
propsTypeName2 && !ir.metadata.propsObjectName ? propsTypeName2 : "",
|
|
2111
|
-
...ir.metadata.namedExports.filter((block) => block.source === null).flatMap((block) => block.specifiers.map((s) => s.name))
|
|
2112
|
-
].filter(Boolean).join(`
|
|
2113
|
-
`);
|
|
2114
|
-
const included = new Set;
|
|
2115
|
-
for (const typeDef of ir.metadata.typeDefinitions) {
|
|
2116
|
-
if (new RegExp(`\\b${typeDef.name}\\b`).test(seedText)) {
|
|
2117
|
-
included.add(typeDef.name);
|
|
2118
|
-
}
|
|
2119
|
-
}
|
|
2120
|
-
let changed = true;
|
|
2121
|
-
while (changed) {
|
|
2122
|
-
changed = false;
|
|
2123
|
-
for (const typeDef of ir.metadata.typeDefinitions) {
|
|
2124
|
-
if (included.has(typeDef.name))
|
|
2125
|
-
continue;
|
|
2126
|
-
for (const name of included) {
|
|
2127
|
-
const includedDef = ir.metadata.typeDefinitions.find((t) => t.name === name);
|
|
2128
|
-
if (includedDef && new RegExp(`\\b${typeDef.name}\\b`).test(includedDef.definition)) {
|
|
2129
|
-
included.add(typeDef.name);
|
|
2130
|
-
changed = true;
|
|
2131
|
-
break;
|
|
2132
|
-
}
|
|
2133
|
-
}
|
|
2134
|
-
}
|
|
2135
|
-
}
|
|
2136
|
-
for (const typeDef of ir.metadata.typeDefinitions) {
|
|
2137
|
-
if (included.has(typeDef.name))
|
|
2138
|
-
lines.push(typeDef.definition);
|
|
2139
|
-
}
|
|
2140
|
-
} else {
|
|
2141
|
-
for (const typeDef of ir.metadata.typeDefinitions) {
|
|
2142
|
-
lines.push(typeDef.definition);
|
|
2143
|
-
}
|
|
2144
|
-
}
|
|
2145
2391
|
const propsTypeName = this.getPropsTypeName(ir);
|
|
2146
2392
|
if (propsTypeName && !ir.metadata.propsObjectName) {
|
|
2147
|
-
lines.push("");
|
|
2148
2393
|
lines.push(`type ${this.componentName}PropsWithHydration = ${propsTypeName} & {`);
|
|
2149
2394
|
lines.push(" __instanceId?: string");
|
|
2150
2395
|
lines.push(" __bfScope?: string");
|
|
@@ -2224,12 +2469,7 @@ export default ${this.componentName}` : "";
|
|
|
2224
2469
|
} else {
|
|
2225
2470
|
const hydrationProps = `__instanceId, ${bfScopeAlias}, ${bfChildAlias}, ${bfParentPropsAlias}, ${bfParentAlias}, ${bfMountAlias}, ${dataKeyAlias}`;
|
|
2226
2471
|
const parts = [];
|
|
2227
|
-
const propsParams = ir.metadata.propsParams.map((p) =>
|
|
2228
|
-
const callerKey = p.sourceName ?? p.name;
|
|
2229
|
-
const localName = p.name;
|
|
2230
|
-
const binding = callerKey === localName ? localName : `${isIdentifierName(callerKey) ? callerKey : JSON.stringify(callerKey)}: ${localName}`;
|
|
2231
|
-
return p.defaultValue ? `${binding} = ${p.defaultValue}` : binding;
|
|
2232
|
-
}).join(", ");
|
|
2472
|
+
const propsParams = ir.metadata.propsParams.map((p) => propsDestructureBinding(p)).join(", ");
|
|
2233
2473
|
if (propsParams) {
|
|
2234
2474
|
parts.push(propsParams);
|
|
2235
2475
|
}
|
|
@@ -2270,7 +2510,8 @@ export default ${this.componentName}` : "";
|
|
|
2270
2510
|
lines.push(` const __hydrateProps: Record<string, unknown> = {}`);
|
|
2271
2511
|
for (const p of propsToSerialize) {
|
|
2272
2512
|
const propAccess = propsObjectName ? `${propsObjectName}.${p.name}` : p.name;
|
|
2273
|
-
|
|
2513
|
+
const callerKey = p.sourceName ?? p.name;
|
|
2514
|
+
lines.push(` if (typeof ${propAccess} !== 'function' && !(typeof ${propAccess} === 'object' && ${propAccess} !== null && 'isEscaped' in ${propAccess})) __hydrateProps['${callerKey}'] = ${propAccess}`);
|
|
2274
2515
|
}
|
|
2275
2516
|
lines.push(` const __bfPropsJson = __bfParentProps || (Object.keys(__hydrateProps).length > 0 ? JSON.stringify(__hydrateProps) : undefined)`);
|
|
2276
2517
|
} else if (hasClientInteractivity && isRootComponent) {
|
|
@@ -2335,6 +2576,7 @@ export default ${this.componentName}` : "";
|
|
|
2335
2576
|
case "literal":
|
|
2336
2577
|
return JSON.stringify(v.value);
|
|
2337
2578
|
case "expression":
|
|
2579
|
+
return this.expressionValueToJs(v);
|
|
2338
2580
|
case "spread":
|
|
2339
2581
|
return v.expr;
|
|
2340
2582
|
case "template":
|
|
@@ -2406,18 +2648,26 @@ export default ${this.componentName}` : "";
|
|
|
2406
2648
|
if (cond.clientOnly && cond.slotId) {
|
|
2407
2649
|
return `{bfComment("cond-start:${cond.slotId}")}{bfComment("cond-end:${cond.slotId}")}`;
|
|
2408
2650
|
}
|
|
2651
|
+
return `{${this.renderConditionalBody(cond, ctx)}}`;
|
|
2652
|
+
}
|
|
2653
|
+
renderConditionalBody(cond, ctx) {
|
|
2409
2654
|
const branchCtx = ctx?.isLoopItemRoot ? { isLoopItemRoot: true } : undefined;
|
|
2655
|
+
if (!cond.slotId) {
|
|
2656
|
+
const whenTrue2 = this.renderBareBranch(cond.whenTrue, branchCtx);
|
|
2657
|
+
let whenFalse2 = this.renderBareBranch(cond.whenFalse, branchCtx);
|
|
2658
|
+
if (!whenFalse2 || whenFalse2 === "" || whenFalse2 === "null") {
|
|
2659
|
+
whenFalse2 = "null";
|
|
2660
|
+
}
|
|
2661
|
+
return `${cond.condition} ? ${whenTrue2} : ${whenFalse2}`;
|
|
2662
|
+
}
|
|
2410
2663
|
const whenTrue = this.renderNodeRawCtx(cond.whenTrue, branchCtx);
|
|
2411
2664
|
let whenFalse = this.renderNodeRawCtx(cond.whenFalse, branchCtx);
|
|
2412
2665
|
if (!whenFalse || whenFalse === "" || whenFalse === "null") {
|
|
2413
2666
|
whenFalse = "null";
|
|
2414
2667
|
}
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
return `{${cond.condition} ? ${trueWithMarker} : ${falseWithMarker}}`;
|
|
2419
|
-
}
|
|
2420
|
-
return `{${cond.condition} ? ${whenTrue} : ${whenFalse}}`;
|
|
2668
|
+
const trueWithMarker = this.wrapWithCondMarker(cond.whenTrue, whenTrue, cond.slotId);
|
|
2669
|
+
const falseWithMarker = cond.whenFalse.type === "expression" && cond.whenFalse.expr === "null" ? `<>{bfComment("cond-start:${cond.slotId}")}{bfComment("cond-end:${cond.slotId}")}</>` : this.wrapWithCondMarker(cond.whenFalse, whenFalse, cond.slotId);
|
|
2670
|
+
return `${cond.condition} ? ${trueWithMarker} : ${falseWithMarker}`;
|
|
2421
2671
|
}
|
|
2422
2672
|
renderNodeRawCtx(node, ctx) {
|
|
2423
2673
|
if (node.type === "expression") {
|
|
@@ -2427,6 +2677,17 @@ export default ${this.componentName}` : "";
|
|
|
2427
2677
|
}
|
|
2428
2678
|
return this.renderNode(node, ctx);
|
|
2429
2679
|
}
|
|
2680
|
+
renderBareBranch(node, ctx) {
|
|
2681
|
+
if (node.type === "expression") {
|
|
2682
|
+
if (node.expr === "null" || node.expr === "undefined")
|
|
2683
|
+
return "null";
|
|
2684
|
+
return node.expr;
|
|
2685
|
+
}
|
|
2686
|
+
if (node.type === "conditional" && !(node.clientOnly && node.slotId)) {
|
|
2687
|
+
return this.renderConditionalBody(node, ctx);
|
|
2688
|
+
}
|
|
2689
|
+
return this.renderNode(node, ctx);
|
|
2690
|
+
}
|
|
2430
2691
|
wrapWithCondMarker(node, content, condId) {
|
|
2431
2692
|
if (node.type === "component") {
|
|
2432
2693
|
return `<>{bfComment("cond-start:${condId}")}${content}{bfComment("cond-end:${condId}")}</>`;
|
|
@@ -2578,10 +2839,11 @@ export default ${this.componentName}` : "";
|
|
|
2578
2839
|
elementAttrEmitter = {
|
|
2579
2840
|
emitLiteral: (value, name) => `${name}="${escapeHtml(value.value)}"`,
|
|
2580
2841
|
emitExpression: (value, name) => {
|
|
2842
|
+
const expr = this.expressionValueToJs(value);
|
|
2581
2843
|
if (isBooleanAttr(name) || value.presenceOrUndefined) {
|
|
2582
|
-
return `${name}={(${
|
|
2844
|
+
return `${name}={(${expr}) || undefined}`;
|
|
2583
2845
|
}
|
|
2584
|
-
return `${name}={${
|
|
2846
|
+
return `${name}={${expr}}`;
|
|
2585
2847
|
},
|
|
2586
2848
|
emitBooleanAttr: (_value, name) => name,
|
|
2587
2849
|
emitBooleanShorthand: () => "",
|
|
@@ -2591,7 +2853,7 @@ export default ${this.componentName}` : "";
|
|
|
2591
2853
|
};
|
|
2592
2854
|
componentPropEmitter = {
|
|
2593
2855
|
emitLiteral: (value, name) => `${name}="${escapeHtml(value.value)}"`,
|
|
2594
|
-
emitExpression: (value, name) => `${name}={${value
|
|
2856
|
+
emitExpression: (value, name) => `${name}={${this.expressionValueToJs(value)}}`,
|
|
2595
2857
|
emitBooleanAttr: (_value, name) => name,
|
|
2596
2858
|
emitBooleanShorthand: (_value, name) => name,
|
|
2597
2859
|
emitTemplate: (value, name) => `${name}={${this.renderTemplateLiteralParts(value.parts)}}`,
|
|
@@ -2639,6 +2901,7 @@ export default ${this.componentName}` : "";
|
|
|
2639
2901
|
case "literal":
|
|
2640
2902
|
return JSON.stringify(value.value);
|
|
2641
2903
|
case "expression":
|
|
2904
|
+
return this.expressionValueToJs(value);
|
|
2642
2905
|
case "spread":
|
|
2643
2906
|
return value.expr;
|
|
2644
2907
|
case "template":
|
|
@@ -2651,19 +2914,7 @@ export default ${this.componentName}` : "";
|
|
|
2651
2914
|
}
|
|
2652
2915
|
}
|
|
2653
2916
|
renderTemplateLiteralParts(parts) {
|
|
2654
|
-
|
|
2655
|
-
for (const part of parts) {
|
|
2656
|
-
if (part.type === "string") {
|
|
2657
|
-
output += part.value;
|
|
2658
|
-
} else if (part.type === "ternary") {
|
|
2659
|
-
output += `\${${part.condition} ? '${part.whenTrue}' : '${part.whenFalse}'}`;
|
|
2660
|
-
} else if (part.type === "lookup") {
|
|
2661
|
-
const obj = "{" + Object.entries(part.cases).map(([k, v]) => `${JSON.stringify(k)}: ${JSON.stringify(v)}`).join(", ") + "}";
|
|
2662
|
-
output += `\${(${obj})[${part.key}]}`;
|
|
2663
|
-
}
|
|
2664
|
-
}
|
|
2665
|
-
output += "`";
|
|
2666
|
-
return output;
|
|
2917
|
+
return this.renderTemplatePartsAsJs(parts);
|
|
2667
2918
|
}
|
|
2668
2919
|
}
|
|
2669
2920
|
var honoAdapter = new HonoAdapter;
|