@solidjs/babel-plugin 2.0.0-rc.5 → 2.0.0-rc.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/index.js CHANGED
@@ -1520,7 +1520,11 @@ value,
1520
1520
  const isLocked = isLockedDOMProperty(tagName, name);
1521
1521
 
1522
1522
  if (isChildProp || namespace === "prop" || isLocked) {
1523
- if (config.hydratable && namespace !== "prop" && !isLocked) {
1523
+ // Locked/stateful DOM properties (value/checked/...) must go through the
1524
+ // runtime in hydratable builds so the hydration claim pass can adopt
1525
+ // pre-hydration user state instead of overwriting it (#3182). setProperty
1526
+ // carries the select-microtask and input/textarea nullish special cases.
1527
+ if (config.hydratable && (isLocked || namespace !== "prop")) {
1524
1528
  return t$1.callExpression(registerImportMethod(path, "setProperty"), [
1525
1529
  elem,
1526
1530
  t$1.stringLiteral(name),
@@ -2330,7 +2334,10 @@ results)
2330
2334
  }
2331
2335
 
2332
2336
  // properties
2333
- if (staticValue && ChildProperties.has(key)) {
2337
+ if (
2338
+ staticValue && (
2339
+ ChildProperties.has(key) || tagName === "select" && key === "value"))
2340
+ {
2334
2341
  results.exprs.push(
2335
2342
  t$1.expressionStatement(
2336
2343
  setAttr$2(attribute, elem, key, staticValue, { tagName })
@@ -2814,170 +2821,6 @@ attributes,
2814
2821
 
2815
2822
  }
2816
2823
 
2817
- /**
2818
- * Patch-mode eligibility + emission (DESIGN-PATCH-CHANNEL.md, PR-C).
2819
- *
2820
- * A template scope qualifies for patch mode when EVERY dynamic binding's
2821
- * value is a pure expression over member reads of ONE stable subject
2822
- * identifier (Tier 1: bare member chains; Tier 2: ternary/binary/logical/
2823
- * template-literal/unary compositions of Tier-1 reads and literals).
2824
- * Anything else — calls, assignments, functions, foreign identifiers —
2825
- * disqualifies the SCOPE (per-binding islands remain future work; v1 is
2826
- * all-or-nothing per template scope, matching the fixture shape).
2827
- *
2828
- * Emission (dual driver, shared body):
2829
- *
2830
- * _$patchDriver(subject, (_n$, _p$, _f$) => {
2831
- * let _v$;
2832
- * if (_f$ || (_v$ = <expr(_n$)>) !== <expr(_p$)>) <setAttr(..., _v$)>;
2833
- * ...
2834
- * });
2835
- *
2836
- * The runtime driver registers on the store's patch channel when the
2837
- * subject is a patchable record, else falls back to a tracked force-mode
2838
- * effect running the same body (reads through the subject track; force
2839
- * short-circuits every compare, so `prev` is never dereferenced there).
2840
- * Semantics are therefore IDENTICAL either way; patch mode only changes
2841
- * who dispatches.
2842
- */
2843
-
2844
- // Node types allowed inside an eligible binding expression (Tier 1+2).
2845
- function isEligibleExpr(node, subject) {
2846
- switch (node.type) {
2847
- case "Identifier":
2848
- return node.name === subject || node.name === "undefined";
2849
- case "MemberExpression":{
2850
- const m = node;
2851
- if (m.computed) {
2852
- if (!t__namespace.isStringLiteral(m.property) && !t__namespace.isNumericLiteral(m.property)) return false;
2853
- } else if (!t__namespace.isIdentifier(m.property)) {
2854
- return false;
2855
- }
2856
- return isEligibleExpr(m.object, subject);
2857
- }
2858
- case "StringLiteral":
2859
- case "NumericLiteral":
2860
- case "BooleanLiteral":
2861
- case "NullLiteral":
2862
- case "BigIntLiteral":
2863
- return true;
2864
- case "ConditionalExpression":{
2865
- const c = node;
2866
- return (
2867
- isEligibleExpr(c.test, subject) &&
2868
- isEligibleExpr(c.consequent, subject) &&
2869
- isEligibleExpr(c.alternate, subject));
2870
-
2871
- }
2872
- case "BinaryExpression":{
2873
- const b = node;
2874
- if (b.operator === "in" || b.operator === "instanceof") return false;
2875
- return isEligibleExpr(b.left, subject) && isEligibleExpr(b.right, subject);
2876
- }
2877
- case "LogicalExpression":{
2878
- const l = node;
2879
- return isEligibleExpr(l.left, subject) && isEligibleExpr(l.right, subject);
2880
- }
2881
- case "UnaryExpression":{
2882
- const u = node;
2883
- if (u.operator === "delete" || u.operator === "throw") return false;
2884
- return isEligibleExpr(u.argument, subject);
2885
- }
2886
- case "TemplateLiteral":
2887
- return node.expressions.every((e) =>
2888
- t__namespace.isExpression(e) ? isEligibleExpr(e, subject) : false
2889
- );
2890
- case "ParenthesizedExpression":
2891
- return isEligibleExpr(node.expression, subject);
2892
- default:
2893
- return false;
2894
- }
2895
- }
2896
-
2897
- /** Find the single subject: the root identifier of the FIRST member chain
2898
- * encountered. Every other read must root at the same name. */
2899
- function findSubject(node) {
2900
- switch (node.type) {
2901
- case "MemberExpression":
2902
- return findSubject(node.object);
2903
- case "Identifier":
2904
- return node.name === "undefined" ? null : node.name;
2905
- case "ConditionalExpression":
2906
- return (
2907
- findSubject(node.test) ??
2908
- findSubject(node.consequent) ??
2909
- findSubject(node.alternate));
2910
-
2911
- case "BinaryExpression":
2912
- case "LogicalExpression":
2913
- return (
2914
- findSubject(node.left) ?? findSubject(node.right));
2915
-
2916
- case "UnaryExpression":
2917
- return findSubject(node.argument);
2918
- case "TemplateLiteral":{
2919
- for (const e of node.expressions) {
2920
- const s = findSubject(e);
2921
- if (s) return s;
2922
- }
2923
- return null;
2924
- }
2925
- case "ParenthesizedExpression":
2926
- return findSubject(node.expression);
2927
- default:
2928
- return null;
2929
- }
2930
- }
2931
-
2932
-
2933
-
2934
-
2935
-
2936
- /** Analyze a template scope's dynamic binding values. Returns the subject
2937
- * when EVERY value is an eligible pure expression over it, else null. */
2938
- function analyzePatchEligibility(values) {
2939
- if (values.length === 0) return null;
2940
- let subject = null;
2941
- for (const v of values) {
2942
- const s = findSubject(v);
2943
- if (s === null) return null; // static-only binding: no dispatch source
2944
- if (subject === null) subject = s;else
2945
- if (subject !== s) return null; // multi-subject: Q3 territory, bail in v1
2946
- }
2947
- if (subject === null) return null;
2948
- for (const v of values) {
2949
- if (!isEligibleExpr(v, subject)) return null;
2950
- }
2951
- return { subject };
2952
- }
2953
-
2954
- /** Clone `expr` substituting the subject identifier with `replacement`.
2955
- * Safe because eligibility rejected functions/shadowing constructs. */
2956
- function substituteSubject(
2957
- expr,
2958
- subject,
2959
- replacement)
2960
- {
2961
- const clone = t__namespace.cloneNode(expr, true);
2962
- const rewrite = (node) => {
2963
- if (t__namespace.isIdentifier(node) && node.name === subject) return t__namespace.cloneNode(replacement);
2964
- for (const key of Object.keys(node)) {
2965
- const value = node[key];
2966
- if (Array.isArray(value)) {
2967
- for (let i = 0; i < value.length; i++) {
2968
- if (value[i] && typeof value[i].type === "string") value[i] = rewrite(value[i]);
2969
- }
2970
- } else if (value && typeof value.type === "string") {
2971
- // Never rewrite non-computed member PROPERTY positions.
2972
- if (t__namespace.isMemberExpression(node) && key === "property" && !node.computed) continue;
2973
- node[key] = rewrite(value);
2974
- }
2975
- }
2976
- return node;
2977
- };
2978
- return rewrite(clone);
2979
- }
2980
-
2981
2824
  function createTemplate$2(
2982
2825
  path,
2983
2826
  result,
@@ -2991,16 +2834,9 @@ wrap)
2991
2834
  !(result.exprs.length || result.dynamics.length || result.postExprs?.length) &&
2992
2835
  decl.declarations.length === 1)
2993
2836
  {
2994
- // Static single-root template: a candidate row function returning it is
2995
- // trivially pure (no reactive work at all).
2996
- if (config.patchDriver) recordPureRow(path, result, null);
2997
2837
  return decl.declarations[0].init;
2998
2838
  } else {
2999
- const patched = config.patchDriver ? wrapPatchMode(path, result.dynamics) : undefined;
3000
- const dynamicsStmt = patched ? patched.stmt : wrapDynamics$1(path, result.dynamics);
3001
- if (config.patchDriver && (result.dynamics.length === 0 || patched)) {
3002
- recordPureRow(path, result, patched ? patched.subject : null);
3003
- }
2839
+ const dynamicsStmt = wrapDynamics$1(path, result.dynamics);
3004
2840
  const stmts = [
3005
2841
  decl,
3006
2842
  ...result.exprs,
@@ -3116,179 +2952,6 @@ function registerTemplate(path, results) {
3116
2952
  results.decl = t__namespace.variableDeclaration("var", results.declarations);
3117
2953
  }
3118
2954
 
3119
- /**
3120
- * Row-proof analysis (DESIGN-PATCH-CHANNEL §3c). A function qualifies as a
3121
- * PURE ROW — buildable with no per-row owner, so the patch-mode list driver
3122
- * may engage — when ALL of:
3123
- *
3124
- * - it is a single-parameter function (plain Identifier param, not
3125
- * destructured; not async/generator) whose body is exactly this compiled
3126
- * template: an expression body, or a block whose ONLY statement returns
3127
- * it (checked before the flat-statement emission inserts our own);
3128
- * - the template has a single root element (`result.id` — fragments never
3129
- * reach here) and emitted NO reactive or owned work: dynamics either
3130
- * absent or all landed in ONE patchDriver body, and `result.exprs` holds
3131
- * only inert DOM wiring (member-target assignments like `_el$.$$click =
3132
- * fn` / `_el$.style.cssText = v`, and `_el$.addEventListener(...)`) —
3133
- * any `insert`/`createComponent`/`memo`/`use`/ref/spread emission is a
3134
- * call or conditional shape and fails the walk (default-deny);
3135
- * - the patch subject IS the row parameter. A pure template patching an
3136
- * OUTER subject would register once per created row on a long-lived
3137
- * record with no per-row disposal — the foreign-subject leak the runtime
3138
- * probe never caught.
3139
- *
3140
- * Handler/attribute VALUE expressions may be arbitrary user code: stamped
3141
- * rows are only ever built for real mounts (never speculatively), so their
3142
- * evaluation timing is identical to the classic path. Event handlers are
3143
- * not reactive bindings — values evaluate exactly once at build — so the
3144
- * only ownership divergence is a factory creating owned work in value
3145
- * position (`onClick={makeHandler(row)}` calling onCleanup), which is not
3146
- * a supported pattern (owned work belongs in effects/refs; ruled
3147
- * non-responsibility). Denying evaluation-position calls would cost
3148
- * legitimate currying to guard it; instead the runtime dev-asserts that a
3149
- * stamped row's build attaches nothing to the list owner.
3150
- *
3151
- * Qualifying functions are recorded and wrapped with `rowProof` at program
3152
- * exit (postprocess) — the stamp travels with the function object, so
3153
- * extracted row functions prove at their DEFINITION site and work across
3154
- * modules, which the runtime probe could never see.
3155
- */
3156
- function recordPureRow(path, result, subject) {
3157
- const parent = path.parentPath;
3158
- if (!parent) return;
3159
- let fn;
3160
- if (
3161
- (t__namespace.isArrowFunctionExpression(parent.node) || t__namespace.isFunctionExpression(parent.node)) &&
3162
- parent.node.body === path.node)
3163
- {
3164
- fn = parent.node;
3165
- } else if (
3166
- t__namespace.isReturnStatement(parent.node) &&
3167
- parent.node.argument === path.node &&
3168
- parent.parentPath &&
3169
- t__namespace.isBlockStatement(parent.parentPath.node) &&
3170
- parent.parentPath.node.body.length === 1 &&
3171
- parent.parentPath.parentPath && (
3172
- t__namespace.isArrowFunctionExpression(parent.parentPath.parentPath.node) ||
3173
- t__namespace.isFunctionExpression(parent.parentPath.parentPath.node)) &&
3174
- parent.parentPath.parentPath.node.body === parent.parentPath.node)
3175
- {
3176
- fn = parent.parentPath.parentPath.node;
3177
- }
3178
- if (!fn || fn.async || fn.generator) return;
3179
- if (fn.params.length !== 1 || !t__namespace.isIdentifier(fn.params[0])) return;
3180
- const param = fn.params[0].name;
3181
- if (subject !== null && subject !== param) return;
3182
-
3183
- const isLocalMemberTarget = (n) => {
3184
- if (!t__namespace.isMemberExpression(n) || n.computed) return false;
3185
- let obj = n.object;
3186
- while (t__namespace.isMemberExpression(obj) && !obj.computed) obj = obj.object;
3187
- return t__namespace.isIdentifier(obj);
3188
- };
3189
- for (const stmt of result.exprs) {
3190
- if (!t__namespace.isExpressionStatement(stmt)) return;
3191
- const e = stmt.expression;
3192
- if (t__namespace.isAssignmentExpression(e) && e.operator === "=" && isLocalMemberTarget(e.left)) continue;
3193
- if (
3194
- t__namespace.isCallExpression(e) &&
3195
- t__namespace.isMemberExpression(e.callee) &&
3196
- !e.callee.computed &&
3197
- t__namespace.isIdentifier(e.callee.property) &&
3198
- e.callee.property.name === "addEventListener")
3199
-
3200
- continue;
3201
- return;
3202
- }
3203
- if (result.postExprs?.length) {
3204
- const data = path.scope.getProgramParent().data;
3205
- const moduleName = getRendererConfig(path, "dom").moduleName;
3206
- const rheUid = data.imports?.get(`${moduleName}:runHydrationEvents`);
3207
- for (const stmt of result.postExprs) {
3208
- if (
3209
- !t__namespace.isExpressionStatement(stmt) ||
3210
- !t__namespace.isCallExpression(stmt.expression) ||
3211
- !t__namespace.isIdentifier(stmt.expression.callee) ||
3212
- !rheUid ||
3213
- stmt.expression.callee.name !== rheUid.name)
3214
-
3215
- return;
3216
- }
3217
- }
3218
-
3219
- const data = path.scope.getProgramParent().data;
3220
- (data.pureRows || (data.pureRows = new Set())).add(fn);
3221
- }
3222
-
3223
- /** Patch-mode emission (shared/patch.ts): one compiled body doing inline
3224
- * compares + setAttr writes, handed to the runtime driver which registers
3225
- * on the store patch channel (patchable subject) or falls back to a
3226
- * tracked force-mode effect running the SAME body. Returns undefined when
3227
- * the scope is ineligible — caller falls through to the effect shapes.
3228
- * The subject rides along for row-proof analysis (recordPureRow). */
3229
- function wrapPatchMode(
3230
- path,
3231
- dynamics)
3232
- {
3233
- const config = getConfig(path);
3234
- if (dynamics.length === 0) return;
3235
- const eligibility = analyzePatchEligibility(dynamics.map((d) => d.value));
3236
- if (!eligibility) return;
3237
- const subject = eligibility.subject;
3238
- // The subject must be a stable local binding (not reassigned): row params
3239
- // and const destructures qualify; anything else falls back to effects.
3240
- const binding = path.scope.getBinding(subject);
3241
- if (!binding || !binding.constant) return;
3242
- // Fixed `$`-suffixed locals, matching wrapDynamics' `_v$`/`_p$` convention
3243
- // (and byte-parity with the Oxc compiler's emission): substitution only
3244
- // rewrites subject references, so nothing else in an eligible expression
3245
- // can collide with these.
3246
- const nId = t__namespace.identifier("_n$");
3247
- const pId = t__namespace.identifier("_p$");
3248
- const fId = t__namespace.identifier("_f$");
3249
- const stmts = [];
3250
- let vIndex = 0;
3251
- for (const d of dynamics) {
3252
- let value = d.value;
3253
- if (d.classProperty && !t__namespace.isBooleanLiteral(value) && !t__namespace.isUnaryExpression(value)) {
3254
- value = t__namespace.unaryExpression("!", t__namespace.unaryExpression("!", value));
3255
- }
3256
- const vId = t__namespace.identifier(++vIndex === 1 ? "_v$" : `_v$${vIndex}`);
3257
- stmts.push(
3258
- t__namespace.variableDeclaration("const", [
3259
- t__namespace.variableDeclarator(vId, substituteSubject(value, subject, nId))]
3260
- )
3261
- );
3262
- stmts.push(
3263
- t__namespace.ifStatement(
3264
- t__namespace.logicalExpression(
3265
- "||",
3266
- t__namespace.cloneNode(fId),
3267
- t__namespace.binaryExpression("!==", t__namespace.cloneNode(vId), substituteSubject(value, subject, pId))
3268
- ),
3269
- t__namespace.expressionStatement(
3270
- setAttr$2(path, d.elem, d.key, t__namespace.cloneNode(vId), {
3271
- tagName: d.tagName,
3272
- dynamic: true,
3273
- styleProperty: d.styleProperty,
3274
- classProperty: d.classProperty
3275
- })
3276
- )
3277
- )
3278
- );
3279
- }
3280
- const driverId = registerImportMethod(path, config.patchDriver, undefined);
3281
- return {
3282
- stmt: t__namespace.expressionStatement(
3283
- t__namespace.callExpression(driverId, [
3284
- t__namespace.identifier(subject),
3285
- t__namespace.arrowFunctionExpression([nId, pId, fId], t__namespace.blockStatement(stmts))]
3286
- )
3287
- ),
3288
- subject
3289
- };
3290
- }
3291
-
3292
2955
  function wrapDynamics$1(path, dynamics) {
3293
2956
  if (!dynamics.length) return;
3294
2957
  const config = getConfig(path);
@@ -4375,9 +4038,15 @@ path,
4375
4038
  return memo;
4376
4039
  }, []);
4377
4040
 
4041
+ // The DOM transform handles `ref` outside its spread prop sources.
4042
+ const propAttributes = attributes.filter((attribute) => {
4043
+ const node = attribute.node;
4044
+ return !(t.isJSXAttribute(node) && t.isJSXIdentifier(node.name) && node.name.name === "ref");
4045
+ });
4046
+
4378
4047
  let props;
4379
- if (attributes.length === 1 && t.isJSXSpreadAttribute(attributes[0].node)) {
4380
- props = [attributes[0].node.argument];
4048
+ if (propAttributes.length === 1 && t.isJSXSpreadAttribute(propAttributes[0].node)) {
4049
+ props = [propAttributes[0].node.argument];
4381
4050
  } else {
4382
4051
  props = [];
4383
4052
  let runningObject = [],
@@ -14276,6 +13945,29 @@ function serialize(node, options) {
14276
13945
  }
14277
13946
  return serializeChildNodes(node, opts);
14278
13947
  }
13948
+ /**
13949
+ * Serializes an AST element node to an HTML string, including the element node.
13950
+ *
13951
+ * @example
13952
+ *
13953
+ * ```js
13954
+ * const parse5 = require('parse5');
13955
+ *
13956
+ * const document = parse5.parseFragment('<div>Hello, <b>world</b>!</div>');
13957
+ *
13958
+ * // Serializes the <div> element.
13959
+ * const str = parse5.serializeOuter(document.childNodes[0]);
13960
+ *
13961
+ * console.log(str); //> '<div>Hello, <b>world</b>!</div>'
13962
+ * ```
13963
+ *
13964
+ * @param node Node to serialize.
13965
+ * @param options Serialization options.
13966
+ */
13967
+ function serializeOuter(node, options) {
13968
+ const opts = { ...defaultOpts, ...options };
13969
+ return serializeNode(node, opts);
13970
+ }
14279
13971
  function serializeChildNodes(parentNode, options) {
14280
13972
  let html = '';
14281
13973
  // Get container of the child nodes
@@ -14409,6 +14101,29 @@ function innerHTML(htmlFragment) {
14409
14101
  return serialize(parsedFragment);
14410
14102
  }
14411
14103
 
14104
+ /**
14105
+ * A document shell (`<html>`/`<head>`/`<body>` root) can never round-trip a
14106
+ * body-context fragment parse — the parser strips those wrappers no matter
14107
+ * how well-formed the markup is — so it is parsed as a DOCUMENT instead and
14108
+ * the shell element serialized back out (#3259). The same "used in the right
14109
+ * place" assumption the synthetic `<table>` makes for table partials: a
14110
+ * shell template is hydrated against a real document, not client-created.
14111
+ * Restructuring inside the shell still mismatches — an implied `<head>`,
14112
+ * flow content hoisted out of `<head>`, a `<p>` split in `<body>` — so the
14113
+ * #3099 guarantee holds for markup a browser would actually rebuild.
14114
+ */
14115
+ function documentShell(html, tag) {
14116
+ const document = parse(html);
14117
+ const htmlElement = document.childNodes.find(
14118
+ (node) => node.tagName === "html"
14119
+ );
14120
+ const shell =
14121
+ tag === "html" ?
14122
+ htmlElement :
14123
+ htmlElement.childNodes.find((node) => node.tagName === tag);
14124
+ return serializeOuter(shell);
14125
+ }
14126
+
14412
14127
  /**
14413
14128
  * Returns an object with information when the markup is invalid
14414
14129
  *
@@ -14479,7 +14194,8 @@ function isInvalidMarkup(html) {
14479
14194
  }
14480
14195
 
14481
14196
  /** Parse HTML. `browser` is a string with the supposed resulting html of a real `innerHTML` call */
14482
- const browser = innerHTML(html);
14197
+ const shell = /^<(html|head|body)>/.exec(html);
14198
+ const browser = shell ? documentShell(html, shell[1]) : innerHTML(html);
14483
14199
 
14484
14200
  if (html.toLowerCase() !== browser.toLowerCase()) {
14485
14201
  return {
@@ -14540,35 +14256,11 @@ var postprocess = (path, state) => {
14540
14256
  domTemplates.length > 0 && appendTemplates$1(path, domTemplates);
14541
14257
  ssrTemplates.length > 0 && appendTemplates(path, ssrTemplates);
14542
14258
  }
14543
-
14544
- // Compile-time row proofs (DESIGN-PATCH-CHANNEL §3c): wrap each function
14545
- // recorded by recordPureRow with the runtime's `rowProof` marker so the
14546
- // patch-mode list driver can engage on proven-pure rows — admission is
14547
- // decided here, statically; there is no runtime purity probe. The stamp
14548
- // travels with the function object, so extracted row functions qualify at
14549
- // their definition site.
14550
- if (data.pureRows?.size) {
14551
- const rowProofId = registerImportMethod(
14552
- path,
14553
- "rowProof",
14554
- getRendererConfig(path, "dom").moduleName
14555
- );
14556
- const pureRows = data.pureRows;
14557
- path.traverse({
14558
- "ArrowFunctionExpression|FunctionExpression"(fnPath) {
14559
- if (!pureRows.has(fnPath.node)) return;
14560
- pureRows.delete(fnPath.node);
14561
- fnPath.replaceWith(
14562
- t__namespace.callExpression(t__namespace.cloneNode(rowProofId), [fnPath.node])
14563
- );
14564
- fnPath.skip();
14565
- }
14566
- });
14567
- }
14568
14259
  };
14569
14260
 
14570
14261
  const config = {
14571
14262
  moduleName: "@solidjs/web",
14263
+ syntax: "auto",
14572
14264
  generate: "dom",
14573
14265
  hydratable: false,
14574
14266
  dev: false,
@@ -14595,7 +14287,6 @@ const config = {
14595
14287
  contextToCustomElements: true,
14596
14288
  staticMarker: "@static",
14597
14289
  effectWrapper: "effect",
14598
- patchDriver: false,
14599
14290
  memoWrapper: "memo",
14600
14291
  validate: true,
14601
14292
  inlineStyles: true,
@@ -14604,10 +14295,13 @@ const config = {
14604
14295
 
14605
14296
  var preprocess = (path, state) => {
14606
14297
  const file = path.hub.file;
14298
+ const parsedMetadata = file.ast.tsrxStyle;
14299
+ if (parsedMetadata) {
14300
+ file.metadata.css = parsedMetadata.css;
14301
+ file.metadata.cssHash = parsedMetadata.cssHash;
14302
+ delete file.ast.tsrxStyle;
14303
+ }
14607
14304
  const merged = file.metadata.config = Object.assign({}, config, state.opts);
14608
- // Boolean opt-in parity with the native loader: `patchDriver: true` means
14609
- // the default import name (downstream code uses the value AS the name).
14610
- if (merged.patchDriver === true) merged.patchDriver = "patchDriver";
14611
14305
  const lib = merged.requireImportSource;
14612
14306
  if (lib) {
14613
14307
  const comments = file.ast.comments ?? [];
@@ -14627,14 +14321,3459 @@ var preprocess = (path, state) => {
14627
14321
  }
14628
14322
  };
14629
14323
 
14630
- var index = () =>
14324
+ /**
14325
+ * TSRX → Solid JSX desugaring.
14326
+ *
14327
+ * Walks the ESTree AST produced by `@tsrx/core` (before Solid's local
14328
+ * lazy-destructuring transform runs) and lowers every TSRX construct to Solid 2.0 builtIn
14329
+ * component JSX, in place. The result is a plain ESTree TSX program that
14330
+ * `estree-to-babel` converts for the existing JSX pipeline. BuiltIns are
14331
+ * referenced as bare identifiers (`Show`, `For`, …) so the plugin's normal
14332
+ * `builtIns` auto-import machinery resolves them against `moduleName`.
14333
+ *
14334
+ * Lowering contract (mirrored byte-for-byte by the Oxc frontend):
14335
+ * - `@{ body; render }` — expression position: `render` alone when there is no
14336
+ * setup, otherwise `(() => { body; return render; })()`; function-body
14337
+ * position: inline statements ending in `return render`.
14338
+ * - `@if` — `Show` for a single branch, `Switch`/`Match` for chains; `@else`
14339
+ * becomes `fallback`.
14340
+ * - `@for (const x of expr; index i; key k)` — `For`; `key` present emits
14341
+ * `keyed={(x) => k}`, while an index without a key emits `keyed={false}`;
14342
+ * `@empty` becomes `fallback`. RC `For` hands the callback an item accessor
14343
+ * in custom-key and non-keyed modes. The index is an accessor only with a
14344
+ * custom key.
14345
+ * - `@switch` — `Switch` with one `Match when={disc === test}` per `@case`;
14346
+ * `@default` becomes `fallback`.
14347
+ * - `@try/@pending/@catch (e, reset)` — `<Errored fallback={(e, reset) =>
14348
+ * …}><Loading fallback={pending}>{content}</Loading></Errored>`; RC
14349
+ * `Errored` passes an `ErrorAccessor`, so reads of `e` rewrite to calls.
14350
+ * - `<{expr}>` — `<Dynamic component={expr} …>` (deliberate adaptation from
14351
+ * `@tsrx/solid`'s hoisted `dynamic()` factory; semantically equivalent).
14352
+ *
14353
+ * Scoped `<style>` elements are handled and stripped by the preceding style
14354
+ * pass, so they must never reach this transform.
14355
+ */
14631
14356
 
14632
14357
 
14633
14358
 
14634
- {
14635
- return {
14636
- name: "@solidjs/babel-plugin",
14637
- inherits: SyntaxJSX.default,
14359
+
14360
+
14361
+
14362
+
14363
+
14364
+
14365
+
14366
+
14367
+ /** Keys that are never traversed: locations, tooling metadata, and TSRX
14368
+ * keyword-span pointers that carry no semantics of their own. */
14369
+ const SKIP_KEYS$2 = new Set([
14370
+ "type",
14371
+ "loc",
14372
+ "start",
14373
+ "end",
14374
+ "range",
14375
+ "metadata",
14376
+ "leadingComments",
14377
+ "trailingComments",
14378
+ "innerComments",
14379
+ "alternateKeyword",
14380
+ "emptyKeyword"]
14381
+ );
14382
+
14383
+ const RENDER_ENTRY_TYPES = new Set([
14384
+ "JSXElement",
14385
+ "JSXFragment",
14386
+ "JSXText",
14387
+ "JSXCodeBlock",
14388
+ "JSXIfExpression",
14389
+ "JSXForExpression",
14390
+ "JSXSwitchExpression",
14391
+ "JSXTryExpression",
14392
+ "JSXStyleElement"]
14393
+ );
14394
+
14395
+ const VALID_JSX_CHILD_TYPES = new Set([
14396
+ "JSXElement",
14397
+ "JSXFragment",
14398
+ "JSXText",
14399
+ "JSXExpressionContainer",
14400
+ "JSXSpreadChild"]
14401
+ );
14402
+
14403
+ const FUNCTION_TYPES$1 = new Set([
14404
+ "FunctionDeclaration",
14405
+ "FunctionExpression",
14406
+ "ArrowFunctionExpression"]
14407
+ );
14408
+
14409
+ function isNode$3(value) {
14410
+ return (
14411
+ typeof value === "object" &&
14412
+ value !== null &&
14413
+ typeof value.type === "string");
14414
+
14415
+ }
14416
+
14417
+ function fail$2(message, node) {
14418
+ const start = node?.loc?.start;
14419
+ throw new SyntaxError(start ? `${message} (${start.line}:${start.column})` : message);
14420
+ }
14421
+
14422
+ // ---------------------------------------------------------------------------
14423
+ // ESTree builders (converted to Babel shapes later by estree-to-babel)
14424
+ // ---------------------------------------------------------------------------
14425
+
14426
+ function withLoc$2(node, src) {
14427
+ if (src) {
14428
+ if (src.start !== undefined) node.start = src.start;
14429
+ if (src.end !== undefined) node.end = src.end;
14430
+ if (src.loc !== undefined) node.loc = src.loc;
14431
+ }
14432
+ return node;
14433
+ }
14434
+
14435
+ function ident$1(name, src) {
14436
+ return withLoc$2({ type: "Identifier", name }, src);
14437
+ }
14438
+
14439
+ function jsxIdent(name, src) {
14440
+ return withLoc$2({ type: "JSXIdentifier", name }, src);
14441
+ }
14442
+
14443
+ function jsxContainer(expression, src) {
14444
+ return withLoc$2({ type: "JSXExpressionContainer", expression }, src ?? expression);
14445
+ }
14446
+
14447
+ function jsxAttr(name, expression, src) {
14448
+ return withLoc$2(
14449
+ {
14450
+ type: "JSXAttribute",
14451
+ name: jsxIdent(name, src),
14452
+ value: jsxContainer(expression, src ?? expression)
14453
+ },
14454
+ src ?? expression
14455
+ );
14456
+ }
14457
+
14458
+ function jsxElement(name, attributes, children, src) {
14459
+ const selfClosing = children.length === 0;
14460
+ return withLoc$2(
14461
+ {
14462
+ type: "JSXElement",
14463
+ openingElement: withLoc$2(
14464
+ { type: "JSXOpeningElement", name: jsxIdent(name, src), attributes, selfClosing },
14465
+ src
14466
+ ),
14467
+ closingElement: selfClosing ?
14468
+ null :
14469
+ withLoc$2({ type: "JSXClosingElement", name: jsxIdent(name, src) }, src),
14470
+ children
14471
+ },
14472
+ src
14473
+ );
14474
+ }
14475
+
14476
+ function jsxFragment(children, src) {
14477
+ return withLoc$2(
14478
+ {
14479
+ type: "JSXFragment",
14480
+ openingFragment: withLoc$2({ type: "JSXOpeningFragment" }, src),
14481
+ closingFragment: withLoc$2({ type: "JSXClosingFragment" }, src),
14482
+ children
14483
+ },
14484
+ src
14485
+ );
14486
+ }
14487
+
14488
+ function arrow(params, body, src) {
14489
+ return withLoc$2(
14490
+ {
14491
+ type: "ArrowFunctionExpression",
14492
+ id: null,
14493
+ params,
14494
+ body,
14495
+ expression: body.type !== "BlockStatement",
14496
+ async: false,
14497
+ generator: false
14498
+ },
14499
+ src
14500
+ );
14501
+ }
14502
+
14503
+ function blockStatement(body, src) {
14504
+ return withLoc$2({ type: "BlockStatement", body }, src);
14505
+ }
14506
+
14507
+ function returnStatement(argument, src) {
14508
+ return withLoc$2({ type: "ReturnStatement", argument }, src);
14509
+ }
14510
+
14511
+ function iife(statements, src) {
14512
+ return withLoc$2(
14513
+ {
14514
+ type: "CallExpression",
14515
+ callee: arrow([], blockStatement(statements, src), src),
14516
+ arguments: [],
14517
+ optional: false
14518
+ },
14519
+ src
14520
+ );
14521
+ }
14522
+
14523
+ function callOn(callee, src) {
14524
+ return withLoc$2({ type: "CallExpression", callee, arguments: [], optional: false }, src);
14525
+ }
14526
+
14527
+ function strictEquals(left, right, src) {
14528
+ return withLoc$2({ type: "BinaryExpression", operator: "===", left, right }, src);
14529
+ }
14530
+
14531
+ function stringLiteral(value, src) {
14532
+ return withLoc$2({ type: "Literal", value, raw: JSON.stringify(value) }, src);
14533
+ }
14534
+
14535
+ function cloneNode$1(value) {
14536
+ if (Array.isArray(value)) return value.map(cloneNode$1);
14537
+ if (typeof value === "object" && value !== null) {
14538
+ const out = {};
14539
+ for (const key of Object.keys(value)) {
14540
+ out[key] = cloneNode$1(value[key]);
14541
+ }
14542
+ return out;
14543
+ }
14544
+ return value;
14545
+ }
14546
+
14547
+ function accessorLazyPattern(pattern) {
14548
+ const clone = cloneNode$1(pattern);
14549
+ clone.lazy = true;
14550
+ const metadata = clone.metadata ??= {};
14551
+ delete metadata.lazy_id;
14552
+ metadata.lazy_source_accessor = true;
14553
+ return clone;
14554
+ }
14555
+
14556
+ function eagerPattern(pattern) {
14557
+ const clone = cloneNode$1(pattern);
14558
+ clearLazy(clone);
14559
+ return clone;
14560
+
14561
+ function clearLazy(node) {
14562
+ if (node.type === "ObjectPattern" || node.type === "ArrayPattern") node.lazy = false;
14563
+ for (const key of Object.keys(node)) {
14564
+ if (SKIP_KEYS$2.has(key)) continue;
14565
+ const value = node[key];
14566
+ if (Array.isArray(value)) {
14567
+ for (const item of value) if (isNode$3(item)) clearLazy(item);
14568
+ } else if (isNode$3(value)) {
14569
+ clearLazy(value);
14570
+ }
14571
+ }
14572
+ }
14573
+ }
14574
+
14575
+ // ---------------------------------------------------------------------------
14576
+ // Main walk
14577
+ // ---------------------------------------------------------------------------
14578
+
14579
+ function desugarProgram(program) {
14580
+ genericVisit(program);
14581
+ return program;
14582
+ }
14583
+
14584
+ /** Desugars `node`, returning its replacement for expression-shaped slots. */
14585
+ function transform$1(node) {
14586
+ switch (node.type) {
14587
+ case "JSXCodeBlock":
14588
+ return codeBlockToExpression(node);
14589
+ case "JSXIfExpression":
14590
+ return ifToJsx(node);
14591
+ case "JSXForExpression":
14592
+ return forToJsx(node);
14593
+ case "JSXSwitchExpression":
14594
+ return switchToJsx(node);
14595
+ case "JSXTryExpression":
14596
+ return tryToJsx(node);
14597
+ case "JSXStyleElement":
14598
+ return fail$2("A TSRX <style> element survived the scoped style pass", node);
14599
+ case "JSXElement":
14600
+ return desugarElement(node);
14601
+ case "JSXFragment":
14602
+ node.children && (node.children = desugarChildren(node.children));
14603
+ return node;
14604
+ default:
14605
+ if (FUNCTION_TYPES$1.has(node.type) && isNode$3(node.body) && node.body.type === "JSXCodeBlock") {
14606
+ const body = node.body;
14607
+ genericVisit(node, "body");
14608
+ node.body = codeBlockToFunctionBody(body);
14609
+ if (node.type === "ArrowFunctionExpression") node.expression = false;
14610
+ return node;
14611
+ }
14612
+ genericVisit(node);
14613
+ return node;
14614
+ }
14615
+ }
14616
+
14617
+ function genericVisit(node, skipKey) {
14618
+ for (const key of Object.keys(node)) {
14619
+ if (SKIP_KEYS$2.has(key) || key === skipKey) continue;
14620
+ const value = node[key];
14621
+ if (Array.isArray(value)) {
14622
+ for (let i = 0; i < value.length; i++) {
14623
+ if (isNode$3(value[i])) value[i] = transform$1(value[i]);
14624
+ }
14625
+ } else if (isNode$3(value)) {
14626
+ node[key] = transform$1(value);
14627
+ }
14628
+ }
14629
+ }
14630
+
14631
+ // ---------------------------------------------------------------------------
14632
+ // Elements and children
14633
+ // ---------------------------------------------------------------------------
14634
+
14635
+ function desugarElement(el) {
14636
+ const opening = el.openingElement;
14637
+ const isDynamic = !!opening.isDynamic;
14638
+ genericVisit(opening);
14639
+ const children = desugarChildren(el.children ?? []);
14640
+ if (isDynamic) {
14641
+ const nameContainer = opening.name;
14642
+ const componentExpr = nameContainer.expression;
14643
+ const attributes = [
14644
+ jsxAttr("component", componentExpr, nameContainer),
14645
+ ...(opening.attributes ?? [])];
14646
+
14647
+ return jsxElement("Dynamic", attributes, children, el);
14648
+ }
14649
+ el.children = children;
14650
+ return el;
14651
+ }
14652
+
14653
+ function desugarChildren(children) {
14654
+ return children.map((child) => {
14655
+ const result = transform$1(child);
14656
+ if (!VALID_JSX_CHILD_TYPES.has(result.type)) return jsxContainer(result, child);
14657
+ return result;
14658
+ });
14659
+ }
14660
+
14661
+ /** Embed an expression as a JSX child: JSX stays structural, everything else
14662
+ * goes through an expression container. */
14663
+ function asChild(expression) {
14664
+ if (expression.type === "JSXElement" || expression.type === "JSXFragment") return expression;
14665
+ return jsxContainer(expression);
14666
+ }
14667
+
14668
+ // ---------------------------------------------------------------------------
14669
+ // Template blocks (implicit statement containers)
14670
+ // ---------------------------------------------------------------------------
14671
+
14672
+
14673
+
14674
+
14675
+
14676
+
14677
+ const LOOP_TYPES = new Set([
14678
+ "ForStatement",
14679
+ "ForInStatement",
14680
+ "ForOfStatement",
14681
+ "WhileStatement",
14682
+ "DoWhileStatement"]
14683
+ );
14684
+
14685
+ /** TSRX constructs are validation boundaries: their blocks are checked when
14686
+ * they desugar, with their own construct label. `@{}` containers become
14687
+ * function bodies (IIFEs) where escaping statements are legal again. */
14688
+ const ESCAPE_BOUNDARY_TYPES = new Set([
14689
+ "JSXCodeBlock",
14690
+ "JSXIfExpression",
14691
+ "JSXForExpression",
14692
+ "JSXSwitchExpression",
14693
+ "JSXTryExpression"]
14694
+ );
14695
+
14696
+ function escapeMessage(kind, construct) {
14697
+ // Match the ecosystem (@tsrx/solid) diagnostics verbatim for @if and @for.
14698
+ if (construct === "@if" || construct === "@else") {
14699
+ if (kind === "return")
14700
+ return "Return statements are not allowed inside TSRX template @if blocks. Move the return before the template output or render conditionally instead.";
14701
+ if (kind === "break")
14702
+ return "Break statements are not allowed inside TSRX template @if blocks.";
14703
+ return "Continue statements are not allowed inside TSRX template @if blocks. Filter before rendering or use conditional output instead.";
14704
+ }
14705
+ if (construct === "@for" || construct === "@empty") {
14706
+ if (kind === "return")
14707
+ return "Return statements are not allowed inside TSRX template for...of loops. Filter the iterable before rendering or use an @empty fallback for empty lists.";
14708
+ if (kind === "break")
14709
+ return "Break statements are not allowed inside TSRX template for...of loops.";
14710
+ return "Continue statements are not allowed inside TSRX template for...of loops. Filter the iterable before rendering.";
14711
+ }
14712
+ const noun = kind === "return" ? "Return" : kind === "break" ? "Break" : "Continue";
14713
+ return `${noun} statements are not allowed inside TSRX template ${construct} blocks.`;
14714
+ }
14715
+
14716
+ /** Reject return/break/continue that would escape a template control-flow
14717
+ * block. Nested functions, loops, switches, and labels open their own escape
14718
+ * targets; nested TSRX constructs validate themselves. */
14719
+ function validateNoControlFlowEscape(entries, construct) {
14720
+ for (const entry of entries) check(entry, 0, 0, new Set());
14721
+
14722
+ function check(node, loops, breakables, labels) {
14723
+ if (FUNCTION_TYPES$1.has(node.type) || ESCAPE_BOUNDARY_TYPES.has(node.type)) return;
14724
+ switch (node.type) {
14725
+ case "ReturnStatement":
14726
+ fail$2(escapeMessage("return", construct), node);
14727
+ break;
14728
+ case "BreakStatement":{
14729
+ const label = isNode$3(node.label) ? node.label.name : null;
14730
+ if (label ? !labels.has(label) : breakables === 0) {
14731
+ fail$2(escapeMessage("break", construct), node);
14732
+ }
14733
+ return;
14734
+ }
14735
+ case "ContinueStatement":{
14736
+ const label = isNode$3(node.label) ? node.label.name : null;
14737
+ if (label ? !labels.has(label) : loops === 0) {
14738
+ fail$2(escapeMessage("continue", construct), node);
14739
+ }
14740
+ return;
14741
+ }
14742
+ case "SwitchStatement":{
14743
+ if (isNode$3(node.discriminant)) check(node.discriminant, loops, breakables, labels);
14744
+ for (const switchCase of node.cases) {
14745
+ check(switchCase, loops, breakables + 1, labels);
14746
+ }
14747
+ return;
14748
+ }
14749
+ case "LabeledStatement":{
14750
+ const withLabel = new Set(labels);
14751
+ withLabel.add(node.label.name);
14752
+ check(node.body, loops, breakables, withLabel);
14753
+ return;
14754
+ }
14755
+ }
14756
+ const nextLoops = LOOP_TYPES.has(node.type) ? loops + 1 : loops;
14757
+ const nextBreakables = LOOP_TYPES.has(node.type) ? breakables + 1 : breakables;
14758
+ for (const key of Object.keys(node)) {
14759
+ if (SKIP_KEYS$2.has(key)) continue;
14760
+ const value = node[key];
14761
+ if (Array.isArray(value)) {
14762
+ for (const item of value) if (isNode$3(item)) check(item, nextLoops, nextBreakables, labels);
14763
+ } else if (isNode$3(value)) {
14764
+ check(value, nextLoops, nextBreakables, labels);
14765
+ }
14766
+ }
14767
+ }
14768
+ }
14769
+
14770
+ function toBlockBody(node) {
14771
+ return node.type === "BlockStatement" ? node.body : [node];
14772
+ }
14773
+
14774
+ /** Split a template block into leading setup statements and trailing render
14775
+ * output nodes. Setup is desugared here; renders are desugared by callers
14776
+ * (their lowering depends on the position they land in). When `construct` is
14777
+ * given, escaping control flow (return/break/continue) is rejected first. */
14778
+ function blockToParts(entries, construct) {
14779
+ if (construct) validateNoControlFlowEscape(entries, construct);
14780
+ const setup = [];
14781
+ const renders = [];
14782
+ for (const entry of entries) {
14783
+ if (RENDER_ENTRY_TYPES.has(entry.type)) {
14784
+ if (entry.type === "JSXText" && /^\s*$/.test(String(entry.value))) continue;
14785
+ renders.push(entry);
14786
+ } else {
14787
+ if (renders.length > 0) {
14788
+ fail$2("Statements may not follow the rendered output inside a TSRX template block", entry);
14789
+ }
14790
+ setup.push(transform$1(entry));
14791
+ }
14792
+ }
14793
+ return { setup, renders };
14794
+ }
14795
+
14796
+ function renderNodeToExpression(node) {
14797
+ const result = transform$1(node);
14798
+ if (result.type === "JSXText") return stringLiteral(String(result.value), result);
14799
+ return result;
14800
+ }
14801
+
14802
+ /** Combine desugared render nodes into one expression (fragment for
14803
+ * siblings). Returns null when the block rendered nothing. */
14804
+ function rendersToExpression(renders, src) {
14805
+ if (renders.length === 0) return null;
14806
+ if (renders.length === 1) return renderNodeToExpression(renders[0]);
14807
+ return jsxFragment(
14808
+ renders.map((render) => {
14809
+ const result = transform$1(render);
14810
+ if (!VALID_JSX_CHILD_TYPES.has(result.type)) return jsxContainer(result, render);
14811
+ return result;
14812
+ }),
14813
+ src
14814
+ );
14815
+ }
14816
+
14817
+ /** Lower a whole template block to a single expression. Returns null only for
14818
+ * a fully empty block; a block with setup but no render is an error. */
14819
+ function blockToExpression(blockNode, context) {
14820
+ const parts = blockToParts(toBlockBody(blockNode), context);
14821
+ const renderExpr = rendersToExpression(parts.renders, blockNode);
14822
+ if (parts.setup.length === 0) return renderExpr;
14823
+ if (!renderExpr) {
14824
+ fail$2(`A TSRX ${context} block with setup statements must end with rendered output`, blockNode);
14825
+ }
14826
+ return iife([...parts.setup, returnStatement(renderExpr, blockNode)], blockNode);
14827
+ }
14828
+
14829
+ // ---------------------------------------------------------------------------
14830
+ // @{} statement containers
14831
+ // ---------------------------------------------------------------------------
14832
+
14833
+ function codeBlockToExpression(cb) {
14834
+ const setup = cb.body.map(transform$1);
14835
+ if (!isNode$3(cb.render)) {
14836
+ fail$2("A TSRX statement container is missing its rendered output node", cb);
14837
+ }
14838
+ const renderExpr = renderNodeToExpression(cb.render);
14839
+ if (setup.length === 0) return renderExpr;
14840
+ return iife([...setup, returnStatement(renderExpr, cb)], cb);
14841
+ }
14842
+
14843
+ function codeBlockToFunctionBody(cb) {
14844
+ const setup = cb.body.map(transform$1);
14845
+ if (!isNode$3(cb.render)) {
14846
+ fail$2("A TSRX statement container is missing its rendered output node", cb);
14847
+ }
14848
+ const renderExpr = renderNodeToExpression(cb.render);
14849
+ return blockStatement([...setup, returnStatement(renderExpr, cb)], cb);
14850
+ }
14851
+
14852
+ // ---------------------------------------------------------------------------
14853
+ // @if — Show / Switch+Match
14854
+ // ---------------------------------------------------------------------------
14855
+
14856
+ function ifToJsx(node) {
14857
+ const branches = [];
14858
+ let current = node;
14859
+ let elseBlock = null;
14860
+ for (;;) {
14861
+ branches.push({
14862
+ test: transform$1(current.test),
14863
+ block: current.consequent,
14864
+ src: current
14865
+ });
14866
+ const alternate = current.alternate;
14867
+ if (alternate && (alternate.type === "IfStatement" || alternate.type === "JSXIfExpression")) {
14868
+ current = alternate;
14869
+ } else {
14870
+ elseBlock = alternate;
14871
+ break;
14872
+ }
14873
+ }
14874
+
14875
+ const elseExpr = elseBlock ? blockToExpression(elseBlock, "@else") : null;
14876
+
14877
+ if (branches.length === 1) {
14878
+ const branch = branches[0];
14879
+ const branchExpr = blockToExpression(branch.block, "@if");
14880
+ const attributes = [jsxAttr("when", branch.test, branch.src)];
14881
+ if (elseExpr) attributes.push(jsxAttr("fallback", elseExpr, elseBlock));
14882
+ return jsxElement("Show", attributes, branchExpr ? [asChild(branchExpr)] : [], node);
14883
+ }
14884
+
14885
+ const matches = branches.map((branch) => {
14886
+ const branchExpr = blockToExpression(branch.block, "@if");
14887
+ return jsxElement(
14888
+ "Match",
14889
+ [jsxAttr("when", branch.test, branch.src)],
14890
+ branchExpr ? [asChild(branchExpr)] : [],
14891
+ branch.src
14892
+ );
14893
+ });
14894
+ const attributes = elseExpr ? [jsxAttr("fallback", elseExpr, elseBlock)] : [];
14895
+ return jsxElement("Switch", attributes, matches, node);
14896
+ }
14897
+
14898
+ // ---------------------------------------------------------------------------
14899
+ // @for — For
14900
+ // ---------------------------------------------------------------------------
14901
+
14902
+ function forToJsx(node) {
14903
+ if (node.statementType !== "ForOfStatement") {
14904
+ fail$2(
14905
+ "@for must iterate with for...of; for...in and classic for loops are not TSRX template constructs",
14906
+ node
14907
+ );
14908
+ }
14909
+ if (node.await) {
14910
+ fail$2("`for await` is not supported inside Solid TSRX templates", node);
14911
+ }
14912
+
14913
+ const left = node.left;
14914
+ const pattern =
14915
+ left.type === "VariableDeclaration" ? left.declarations[0].id : left;
14916
+ const each = transform$1(node.right);
14917
+ const index = isNode$3(node.index) ? node.index : null;
14918
+ const key = isNode$3(node.key) ? node.key : null;
14919
+ const usesIndexOnlyMode = index !== null && key === null;
14920
+ const itemIsAccessor = key !== null || usesIndexOnlyMode;
14921
+
14922
+ const parts = blockToParts(toBlockBody(node.body), "@for");
14923
+ const renderExpr = rendersToExpression(parts.renders, node.body);
14924
+ if (!renderExpr) fail$2("A TSRX @for body must end with rendered output", node);
14925
+
14926
+ const callbackBody =
14927
+ parts.setup.length > 0 ?
14928
+ blockStatement(
14929
+ [...parts.setup, returnStatement(renderExpr, node.body)],
14930
+ node.body
14931
+ ) :
14932
+ renderExpr;
14933
+
14934
+ // RC `For` callback shape:
14935
+ // - default keyed mode: raw item, accessor index (there is no TSRX index)
14936
+ // - keyed={false}: accessor item, raw index
14937
+ // - custom key: accessor item, accessor index
14938
+ if (itemIsAccessor && pattern.type === "Identifier")
14939
+ rewriteReadsToCalls(callbackBody, pattern.name);
14940
+ if (key && index) rewriteReadsToCalls(callbackBody, index.name);
14941
+
14942
+ const callbackPattern =
14943
+ itemIsAccessor && pattern.type !== "Identifier" ? accessorLazyPattern(pattern) : pattern;
14944
+ const params = [callbackPattern];
14945
+ if (index) params.push(index);
14946
+
14947
+ const attributes = [jsxAttr("each", each, node.right)];
14948
+ if (key) {
14949
+ attributes.push(jsxAttr("keyed", arrow([eagerPattern(pattern)], transform$1(key), key), key));
14950
+ } else if (usesIndexOnlyMode) {
14951
+ attributes.push(
14952
+ jsxAttr("keyed", withLoc$2({ type: "Literal", value: false, raw: "false" }, index), index)
14953
+ );
14954
+ }
14955
+ if (isNode$3(node.empty)) {
14956
+ const emptyExpr = blockToExpression(node.empty, "@empty");
14957
+ if (emptyExpr) attributes.push(jsxAttr("fallback", emptyExpr, node.empty));
14958
+ }
14959
+
14960
+ return jsxElement(
14961
+ "For",
14962
+ attributes,
14963
+ [jsxContainer(arrow(params, callbackBody, node), node)],
14964
+ node
14965
+ );
14966
+ }
14967
+
14968
+ // ---------------------------------------------------------------------------
14969
+ // @switch — Switch / Match
14970
+ // ---------------------------------------------------------------------------
14971
+
14972
+ function switchToJsx(node) {
14973
+ const discriminant = transform$1(node.discriminant);
14974
+ const matches = [];
14975
+ let fallbackExpr = null;
14976
+ let fallbackSrc = null;
14977
+
14978
+ for (const switchCase of node.cases) {
14979
+ const consequent = switchCase.consequent;
14980
+ const entries =
14981
+ consequent.length === 1 && consequent[0].type === "BlockStatement" ?
14982
+ consequent[0].body :
14983
+ consequent;
14984
+ const parts = blockToParts(entries, switchCase.test == null ? "@default" : "@case");
14985
+ const renderExpr = rendersToExpression(parts.renders, switchCase);
14986
+ const caseExpr =
14987
+ parts.setup.length > 0 ?
14988
+ renderExpr ?
14989
+ iife([...parts.setup, returnStatement(renderExpr, switchCase)], switchCase) :
14990
+ fail$2(
14991
+ "A TSRX @case block with setup statements must end with rendered output",
14992
+ switchCase
14993
+ ) :
14994
+ renderExpr;
14995
+
14996
+ if (switchCase.test == null) {
14997
+ fallbackExpr = caseExpr;
14998
+ fallbackSrc = switchCase;
14999
+ } else {
15000
+ const when = strictEquals(
15001
+ cloneNode$1(discriminant),
15002
+ transform$1(switchCase.test),
15003
+ switchCase
15004
+ );
15005
+ matches.push(
15006
+ jsxElement(
15007
+ "Match",
15008
+ [jsxAttr("when", when, switchCase)],
15009
+ caseExpr ? [asChild(caseExpr)] : [],
15010
+ switchCase
15011
+ )
15012
+ );
15013
+ }
15014
+ }
15015
+
15016
+ const attributes = fallbackExpr ? [jsxAttr("fallback", fallbackExpr, fallbackSrc)] : [];
15017
+ return jsxElement("Switch", attributes, matches, node);
15018
+ }
15019
+
15020
+ // ---------------------------------------------------------------------------
15021
+ // @try / @pending / @catch — Errored / Loading
15022
+ // ---------------------------------------------------------------------------
15023
+
15024
+ function tryToJsx(node) {
15025
+ if (isNode$3(node.finalizer)) {
15026
+ fail$2("@finally is not part of the TSRX template grammar", node.finalizer);
15027
+ }
15028
+
15029
+ const contentExpr = blockToExpression(node.block, "@try");
15030
+ if (!contentExpr) fail$2("A TSRX @try block must end with rendered output", node);
15031
+
15032
+ let result = contentExpr;
15033
+
15034
+ if (isNode$3(node.pending)) {
15035
+ const pendingExpr = blockToExpression(node.pending, "@pending");
15036
+ const attributes = pendingExpr ? [jsxAttr("fallback", pendingExpr, node.pending)] : [];
15037
+ result = jsxElement("Loading", attributes, [asChild(result)], node);
15038
+ }
15039
+
15040
+ if (isNode$3(node.handler)) {
15041
+ const handler = node.handler;
15042
+ const param = isNode$3(handler.param) ? handler.param : null;
15043
+ if (
15044
+ param &&
15045
+ param.type !== "Identifier" &&
15046
+ param.type !== "ObjectPattern" &&
15047
+ param.type !== "ArrayPattern")
15048
+ {
15049
+ fail$2(
15050
+ "The @catch error binding must be an identifier, object pattern, or array pattern",
15051
+ param
15052
+ );
15053
+ }
15054
+ const resetParam = isNode$3(handler.resetParam) ? handler.resetParam : null;
15055
+ const errorName = param ? param.name : "_e";
15056
+
15057
+ const handlerExpr = blockToExpression(handler.body, "@catch");
15058
+ if (!handlerExpr) fail$2("A TSRX @catch block must end with rendered output", handler);
15059
+ // RC `Errored` passes an `ErrorAccessor`: reads of the binding become calls.
15060
+ if (param) rewriteReadsToCalls(handlerExpr, errorName);
15061
+
15062
+ const params = [
15063
+ param && param.type !== "Identifier" ? accessorLazyPattern(param) : ident$1(errorName, param)];
15064
+
15065
+ if (resetParam)
15066
+ params.push(ident$1(resetParam.name, resetParam));
15067
+
15068
+ result = jsxElement(
15069
+ "Errored",
15070
+ [jsxAttr("fallback", arrow(params, handlerExpr, handler), handler)],
15071
+ [asChild(result)],
15072
+ node
15073
+ );
15074
+ }
15075
+
15076
+ return result;
15077
+ }
15078
+
15079
+ // ---------------------------------------------------------------------------
15080
+ // Lazy-engine adaptation: intrinsic element names
15081
+ // ---------------------------------------------------------------------------
15082
+
15083
+ /**
15084
+ * Older lazy-transform paths rewrote *any* JSX name matching a lazy binding —
15085
+ * including lowercase intrinsic tags (`<address>` with a lazy `address` in
15086
+ * scope became `<__lazy0.address>`), which hijacked the element into a
15087
+ * component. Per JSX semantics a single lowercase identifier tag is always
15088
+ * intrinsic, so such rewrites are unambiguously wrong. Keep this repair for
15089
+ * compatibility with trees produced by those paths; the local engine does not
15090
+ * produce the invalid rewrite.
15091
+ */
15092
+ function restoreIntrinsicJsxNames(root) {
15093
+ visit(root);
15094
+
15095
+ function restore(owner) {
15096
+ const name = owner.name;
15097
+ if (!name || name.type !== "JSXMemberExpression") return;
15098
+ const object = name.object;
15099
+ const property = name.property;
15100
+ if (
15101
+ object.type === "JSXIdentifier" &&
15102
+ /^__lazy\d+$/.test(object.name) &&
15103
+ property.type === "JSXIdentifier" &&
15104
+ /^[a-z]/.test(property.name))
15105
+ {
15106
+ owner.name = jsxIdent(property.name, name);
15107
+ }
15108
+ }
15109
+
15110
+ function visit(node) {
15111
+ if (node.type === "JSXOpeningElement" || node.type === "JSXClosingElement") restore(node);
15112
+ for (const key of Object.keys(node)) {
15113
+ if (SKIP_KEYS$2.has(key)) continue;
15114
+ const value = node[key];
15115
+ if (Array.isArray(value)) {
15116
+ for (const item of value) if (isNode$3(item)) visit(item);
15117
+ } else if (isNode$3(value)) {
15118
+ visit(value);
15119
+ }
15120
+ }
15121
+ }
15122
+ }
15123
+
15124
+ // ---------------------------------------------------------------------------
15125
+ // Scope-aware read → call rewriting (accessor adaptations)
15126
+ // ---------------------------------------------------------------------------
15127
+
15128
+ /** Keys whose contents are TS type positions — never value references. */
15129
+ const TYPE_KEYS$1 = new Set([
15130
+ "typeAnnotation",
15131
+ "typeParameters",
15132
+ "typeArguments",
15133
+ "superTypeArguments",
15134
+ "returnType"]
15135
+ );
15136
+
15137
+ function patternNames$1(pattern, into) {
15138
+ switch (pattern.type) {
15139
+ case "Identifier":
15140
+ into.add(pattern.name);
15141
+ break;
15142
+ case "ObjectPattern":
15143
+ for (const prop of pattern.properties) {
15144
+ if (prop.type === "RestElement") patternNames$1(prop.argument, into);else
15145
+ patternNames$1(prop.value, into);
15146
+ }
15147
+ break;
15148
+ case "ArrayPattern":
15149
+ for (const el of pattern.elements) {
15150
+ if (el) patternNames$1(el, into);
15151
+ }
15152
+ break;
15153
+ case "AssignmentPattern":
15154
+ patternNames$1(pattern.left, into);
15155
+ break;
15156
+ case "RestElement":
15157
+ patternNames$1(pattern.argument, into);
15158
+ break;
15159
+ }
15160
+ }
15161
+
15162
+ function statementsShadow(statements, name) {
15163
+ const names = new Set();
15164
+ for (const stmt of statements) {
15165
+ if (stmt.type === "VariableDeclaration") {
15166
+ for (const decl of stmt.declarations) patternNames$1(decl.id, names);
15167
+ } else if (
15168
+ (stmt.type === "FunctionDeclaration" || stmt.type === "ClassDeclaration") &&
15169
+ isNode$3(stmt.id))
15170
+ {
15171
+ names.add(stmt.id.name);
15172
+ }
15173
+ }
15174
+ return names.has(name);
15175
+ }
15176
+
15177
+ /**
15178
+ * Rewrite value reads of `name` within `root` (a plain, already-desugared
15179
+ * subtree) to zero-argument calls, respecting shadowing by function params,
15180
+ * block declarations, and catch clauses. Write targets are left untouched.
15181
+ */
15182
+ function rewriteReadsToCalls(root, name) {
15183
+ visit(root);
15184
+
15185
+ function shouldReplace(value) {
15186
+ return isNode$3(value) && value.type === "Identifier" && value.name === name;
15187
+ }
15188
+
15189
+ function replaceIn(container, key) {
15190
+ const value = container[key];
15191
+ container[key] = callOn(value, value);
15192
+ }
15193
+
15194
+ function visit(node) {
15195
+ if (FUNCTION_TYPES$1.has(node.type)) {
15196
+ const bound = new Set();
15197
+ for (const param of node.params) patternNames$1(param, bound);
15198
+ if (bound.has(name)) return;
15199
+ if (isNode$3(node.body)) visit(node.body);
15200
+ return;
15201
+ }
15202
+ if (node.type === "BlockStatement" || node.type === "Program") {
15203
+ if (statementsShadow(node.body, name)) return;
15204
+ }
15205
+ if (node.type === "CatchClause") {
15206
+ const bound = new Set();
15207
+ if (isNode$3(node.param)) patternNames$1(node.param, bound);
15208
+ if (bound.has(name)) return;
15209
+ }
15210
+ if (node.type === "MetaProperty") return;
15211
+
15212
+ for (const key of Object.keys(node)) {
15213
+ if (SKIP_KEYS$2.has(key) || TYPE_KEYS$1.has(key)) continue;
15214
+ // Labels, binding sites, and non-computed accesses are not value reads.
15215
+ if (key === "property" && node.type === "MemberExpression" && !node.computed) continue;
15216
+ if (key === "property" && node.type === "JSXMemberExpression") continue;
15217
+ if (key === "name" && (node.type === "JSXAttribute" || node.type === "JSXNamespacedName"))
15218
+ continue;
15219
+ if (key === "key" && node.type === "Property" && !node.computed) continue;
15220
+ if (key === "id" && (node.type === "VariableDeclarator" || FUNCTION_TYPES$1.has(node.type)))
15221
+ continue;
15222
+ if (key === "label") continue;
15223
+ if (key === "left" && node.type === "AssignmentExpression") {
15224
+ // Writes to the accessor binding are invalid anyway; skip identifier
15225
+ // targets but still walk member-expression targets.
15226
+ if (shouldReplace(node.left)) continue;
15227
+ }
15228
+ if (key === "argument" && node.type === "UpdateExpression" && shouldReplace(node.argument))
15229
+ continue;
15230
+ if (
15231
+ (key === "imported" || key === "local" || key === "exported") &&
15232
+ /Specifier$/.test(node.type))
15233
+
15234
+ continue;
15235
+
15236
+ const value = node[key];
15237
+ if (Array.isArray(value)) {
15238
+ for (let i = 0; i < value.length; i++) {
15239
+ const item = value[i];
15240
+ if (shouldReplace(item)) replaceIn(value, i);else
15241
+ if (isNode$3(item)) visit(item);
15242
+ }
15243
+ } else if (shouldReplace(value)) {
15244
+ // Object-pattern shorthand shares the key/value node: split them.
15245
+ if (node.type === "Property" && node.shorthand && key === "value") {
15246
+ node.shorthand = false;
15247
+ node.key = ident$1(name, value);
15248
+ }
15249
+ replaceIn(node, key);
15250
+ } else if (isNode$3(value)) {
15251
+ visit(value);
15252
+ }
15253
+ }
15254
+ }
15255
+ }
15256
+
15257
+ /**
15258
+ * ESTree (acorn / typescript-eslint shaped, as produced by `@tsrx/core`) to
15259
+ * Babel AST conversion.
15260
+ *
15261
+ * Purely mechanical: no TSRX node may reach this pass (the desugarer lowers
15262
+ * them all first), and unknown shapes fail closed rather than producing a
15263
+ * silently wrong tree. Location info (`start`/`end`/`loc`) is preserved for
15264
+ * sourcemaps. Comments are not attached in v1 (documented limitation).
15265
+ */
15266
+
15267
+
15268
+
15269
+
15270
+ /** ESTree/TSRX bookkeeping keys with no Babel equivalent. */
15271
+ const STRIP_KEYS = new Set([
15272
+ "type",
15273
+ "start",
15274
+ "end",
15275
+ "loc",
15276
+ "range",
15277
+ "metadata",
15278
+ "leadingComments",
15279
+ "trailingComments",
15280
+ "innerComments",
15281
+ "alternateKeyword",
15282
+ "emptyKeyword",
15283
+ "isDynamic",
15284
+ "statementType",
15285
+ "resetParam",
15286
+ "lazy",
15287
+ "directive"]
15288
+ );
15289
+
15290
+ function isNode$2(value) {
15291
+ return (
15292
+ typeof value === "object" &&
15293
+ value !== null &&
15294
+ typeof value.type === "string");
15295
+
15296
+ }
15297
+
15298
+ function fail$1(message, node) {
15299
+ const start = node.loc?.start;
15300
+ throw new SyntaxError(start ? `${message} (${start.line}:${start.column})` : message);
15301
+ }
15302
+
15303
+ function copyLoc(from, to) {
15304
+ if (from.start !== undefined) to.start = from.start;
15305
+ if (from.end !== undefined) to.end = from.end;
15306
+ if (from.loc !== undefined) to.loc = from.loc;
15307
+ }
15308
+
15309
+ function convertValue(value) {
15310
+ if (Array.isArray(value)) return value.map(convertValue);
15311
+ if (isNode$2(value)) return convertNode(value);
15312
+ return value;
15313
+ }
15314
+
15315
+ /** Shallow-map every kept key, renaming typescript-eslint's `typeArguments`
15316
+ * to Babel 7's `typeParameters` along the way. */
15317
+ function convertGeneric(node, overrideType) {
15318
+ const out = { type: overrideType ?? node.type };
15319
+ copyLoc(node, out);
15320
+ for (const key of Object.keys(node)) {
15321
+ if (STRIP_KEYS.has(key)) continue;
15322
+ const outKey =
15323
+ key === "typeArguments" && node.typeParameters === undefined ? "typeParameters" : key;
15324
+ out[outKey] = convertValue(node[key]);
15325
+ }
15326
+ return out;
15327
+ }
15328
+
15329
+ function convertLiteral(node) {
15330
+ const out = {};
15331
+ copyLoc(node, out);
15332
+ const regex = node.regex;
15333
+ if (regex) {
15334
+ out.type = "RegExpLiteral";
15335
+ out.pattern = regex.pattern;
15336
+ out.flags = regex.flags;
15337
+ return out;
15338
+ }
15339
+ if (node.bigint !== undefined && node.bigint !== null) {
15340
+ out.type = "BigIntLiteral";
15341
+ out.value = node.bigint;
15342
+ return out;
15343
+ }
15344
+ const value = node.value;
15345
+ if (value === null) {
15346
+ out.type = "NullLiteral";
15347
+ return out;
15348
+ }
15349
+ switch (typeof value) {
15350
+ case "string":
15351
+ out.type = "StringLiteral";
15352
+ break;
15353
+ case "number":
15354
+ out.type = "NumericLiteral";
15355
+ break;
15356
+ case "boolean":
15357
+ out.type = "BooleanLiteral";
15358
+ break;
15359
+ default:
15360
+ return fail$1(`Unsupported literal value type: ${typeof value}`, node);
15361
+ }
15362
+ out.value = value;
15363
+ if (typeof node.raw === "string") out.extra = { raw: node.raw, rawValue: value };
15364
+ return out;
15365
+ }
15366
+
15367
+ function extractDirectives(body) {
15368
+ const directives = [];
15369
+ let i = 0;
15370
+ while (i < body.length) {
15371
+ const stmt = body[i];
15372
+ if (stmt.type !== "ExpressionStatement" || typeof stmt.directive !== "string") break;
15373
+ const expr = stmt.expression;
15374
+ const literal = {
15375
+ type: "DirectiveLiteral",
15376
+ value: expr.value
15377
+ };
15378
+ copyLoc(expr, literal);
15379
+ if (typeof expr.raw === "string") literal.extra = { raw: expr.raw, rawValue: expr.value };
15380
+ const directive = { type: "Directive", value: literal };
15381
+ copyLoc(stmt, directive);
15382
+ directives.push(directive);
15383
+ i++;
15384
+ }
15385
+ return { directives, rest: body.slice(i) };
15386
+ }
15387
+
15388
+ function convertFunctionParts(fn, out) {
15389
+ out.params = convertValue(fn.params);
15390
+ out.body = convertValue(fn.body);
15391
+ out.generator = !!fn.generator;
15392
+ out.async = !!fn.async;
15393
+ if (fn.returnType !== undefined) out.returnType = convertValue(fn.returnType);
15394
+ if (fn.typeParameters !== undefined) out.typeParameters = convertValue(fn.typeParameters);
15395
+ }
15396
+
15397
+ /** Convert an optional chain, dropping the ESTree `ChainExpression` wrapper
15398
+ * and switching member/call links to Babel's `Optional*` node types. */
15399
+ function convertChainLink(node) {
15400
+ switch (node.type) {
15401
+ case "MemberExpression":{
15402
+ const out = {
15403
+ type: "OptionalMemberExpression",
15404
+ object: convertChainLink(node.object),
15405
+ property: convertValue(node.property),
15406
+ computed: !!node.computed,
15407
+ optional: !!node.optional
15408
+ };
15409
+ copyLoc(node, out);
15410
+ return out;
15411
+ }
15412
+ case "CallExpression":{
15413
+ const out = {
15414
+ type: "OptionalCallExpression",
15415
+ callee: convertChainLink(node.callee),
15416
+ arguments: convertValue(node.arguments),
15417
+ optional: !!node.optional
15418
+ };
15419
+ copyLoc(node, out);
15420
+ if (node.typeParameters !== undefined || node.typeArguments !== undefined) {
15421
+ out.typeParameters = convertValue(node.typeParameters ?? node.typeArguments);
15422
+ }
15423
+ return out;
15424
+ }
15425
+ case "TSNonNullExpression":{
15426
+ const out = {
15427
+ type: "TSNonNullExpression",
15428
+ expression: convertChainLink(node.expression)
15429
+ };
15430
+ copyLoc(node, out);
15431
+ return out;
15432
+ }
15433
+ default:
15434
+ return convertNode(node);
15435
+ }
15436
+ }
15437
+
15438
+ function convertNode(node) {
15439
+ switch (node.type) {
15440
+ case "Program":{
15441
+ const { directives, rest } = extractDirectives(node.body);
15442
+ const out = {
15443
+ type: "Program",
15444
+ sourceType: node.sourceType ?? "module",
15445
+ interpreter: null,
15446
+ body: rest.map(convertNode),
15447
+ directives
15448
+ };
15449
+ copyLoc(node, out);
15450
+ return out;
15451
+ }
15452
+
15453
+ case "BlockStatement":{
15454
+ const { directives, rest } = extractDirectives(node.body);
15455
+ const out = {
15456
+ type: "BlockStatement",
15457
+ body: rest.map(convertNode),
15458
+ directives
15459
+ };
15460
+ copyLoc(node, out);
15461
+ return out;
15462
+ }
15463
+
15464
+ case "Literal":
15465
+ return convertLiteral(node);
15466
+
15467
+ case "Property":{
15468
+ const kind = node.kind;
15469
+ if (kind === "get" || kind === "set" || node.method) {
15470
+ const fn = node.value;
15471
+ const out = {
15472
+ type: "ObjectMethod",
15473
+ kind: node.method ? "method" : kind,
15474
+ key: convertValue(node.key),
15475
+ computed: !!node.computed
15476
+ };
15477
+ copyLoc(node, out);
15478
+ convertFunctionParts(fn, out);
15479
+ return out;
15480
+ }
15481
+ const out = {
15482
+ type: "ObjectProperty",
15483
+ key: convertValue(node.key),
15484
+ value: convertValue(node.value),
15485
+ computed: !!node.computed,
15486
+ shorthand: !!node.shorthand
15487
+ };
15488
+ copyLoc(node, out);
15489
+ return out;
15490
+ }
15491
+
15492
+ case "MethodDefinition":{
15493
+ const fn = node.value;
15494
+ const isPrivate = node.key.type === "PrivateIdentifier";
15495
+ const out = {
15496
+ type: isPrivate ? "ClassPrivateMethod" : "ClassMethod",
15497
+ kind: node.kind,
15498
+ key: convertValue(node.key),
15499
+ computed: !!node.computed,
15500
+ static: !!node.static
15501
+ };
15502
+ copyLoc(node, out);
15503
+ convertFunctionParts(fn, out);
15504
+ if (node.accessibility !== undefined) out.accessibility = node.accessibility;
15505
+ if (node.override !== undefined) out.override = node.override;
15506
+ if (node.optional !== undefined) out.optional = node.optional;
15507
+ return out;
15508
+ }
15509
+
15510
+ case "PropertyDefinition":{
15511
+ const isPrivate = node.key.type === "PrivateIdentifier";
15512
+ const out = {
15513
+ type: isPrivate ? "ClassPrivateProperty" : "ClassProperty",
15514
+ key: convertValue(node.key),
15515
+ value: node.value == null ? null : convertValue(node.value),
15516
+ computed: !!node.computed,
15517
+ static: !!node.static
15518
+ };
15519
+ copyLoc(node, out);
15520
+ for (const key of [
15521
+ "typeAnnotation",
15522
+ "declare",
15523
+ "readonly",
15524
+ "accessibility",
15525
+ "optional",
15526
+ "definite",
15527
+ "override"])
15528
+ {
15529
+ if (node[key] !== undefined) out[key] = convertValue(node[key]);
15530
+ }
15531
+ return out;
15532
+ }
15533
+
15534
+ case "PrivateIdentifier":{
15535
+ const id = { type: "Identifier", name: node.name };
15536
+ copyLoc(node, id);
15537
+ const out = { type: "PrivateName", id };
15538
+ copyLoc(node, out);
15539
+ return out;
15540
+ }
15541
+
15542
+ case "ChainExpression":
15543
+ return convertChainLink(node.expression);
15544
+
15545
+ case "ImportExpression":{
15546
+ const importCallee = { type: "Import" };
15547
+ copyLoc(node, importCallee);
15548
+ const args = [convertValue(node.source)];
15549
+ if (node.options != null) args.push(convertValue(node.options));
15550
+ const out = {
15551
+ type: "CallExpression",
15552
+ callee: importCallee,
15553
+ arguments: args
15554
+ };
15555
+ copyLoc(node, out);
15556
+ return out;
15557
+ }
15558
+
15559
+ case "JSXText":{
15560
+ const out = { type: "JSXText", value: node.value };
15561
+ copyLoc(node, out);
15562
+ if (typeof node.raw === "string") out.extra = { raw: node.raw, rawValue: node.value };
15563
+ return out;
15564
+ }
15565
+
15566
+ case "TSTypeParameter":{
15567
+ const out = convertGeneric(node);
15568
+ if (isNode$2(out.name)) out.name = out.name.name;
15569
+ return out;
15570
+ }
15571
+
15572
+ case "TSInterfaceHeritage":
15573
+ return convertGeneric(node, "TSExpressionWithTypeArguments");
15574
+
15575
+ case "TSAbstractMethodDefinition":
15576
+ case "TSAbstractPropertyDefinition":
15577
+ case "TSParameterProperty":
15578
+ return fail$1(`Unsupported TypeScript construct in TSRX source: ${node.type}`, node);
15579
+
15580
+ case "JSXCodeBlock":
15581
+ case "JSXIfExpression":
15582
+ case "JSXForExpression":
15583
+ case "JSXSwitchExpression":
15584
+ case "JSXTryExpression":
15585
+ case "JSXStyleElement":
15586
+ return fail$1(
15587
+ `TSRX node ${node.type} survived desugaring; this is a bug in the frontend`,
15588
+ node
15589
+ );
15590
+
15591
+ default:
15592
+ return convertGeneric(node);
15593
+ }
15594
+ }
15595
+
15596
+ function toBabelFile(program) {
15597
+ const file = {
15598
+ type: "File",
15599
+ program: convertNode(program),
15600
+ comments: [],
15601
+ tokens: []
15602
+ };
15603
+ copyLoc(program, file);
15604
+ return file;
15605
+ }
15606
+
15607
+ /**
15608
+ * Solid's TSRX lazy-destructuring transform.
15609
+ *
15610
+ * This is intentionally local to the Babel frontend. `@tsrx/core` still owns
15611
+ * parsing and semantic analysis, but its framework-agnostic lazy transform
15612
+ * cannot express Solid's reactive object-rest view or JavaScript-correct lazy
15613
+ * defaults and updates.
15614
+ *
15615
+ * The scope and pattern traversal is adapted from @tsrx/core 0.1.61's
15616
+ * MIT-licensed `src/transform/lazy.js`.
15617
+ */
15618
+
15619
+
15620
+
15621
+
15622
+
15623
+
15624
+
15625
+
15626
+
15627
+
15628
+
15629
+
15630
+
15631
+
15632
+
15633
+
15634
+
15635
+
15636
+
15637
+
15638
+
15639
+
15640
+
15641
+
15642
+
15643
+
15644
+
15645
+
15646
+
15647
+
15648
+
15649
+
15650
+ const FUNCTION_TYPES = new Set([
15651
+ "FunctionDeclaration",
15652
+ "FunctionExpression",
15653
+ "ArrowFunctionExpression"]
15654
+ );
15655
+
15656
+ const TYPE_KEYS = new Set([
15657
+ "typeAnnotation",
15658
+ "typeParameters",
15659
+ "typeArguments",
15660
+ "superTypeArguments",
15661
+ "returnType",
15662
+ "implements"]
15663
+ );
15664
+
15665
+ const SKIP_KEYS$1 = new Set([
15666
+ "type",
15667
+ "loc",
15668
+ "start",
15669
+ "end",
15670
+ "range",
15671
+ "metadata",
15672
+ "leadingComments",
15673
+ "trailingComments",
15674
+ "innerComments"]
15675
+ );
15676
+
15677
+ function isNode$1(value) {
15678
+ return (
15679
+ typeof value === "object" &&
15680
+ value !== null &&
15681
+ typeof value.type === "string");
15682
+
15683
+ }
15684
+
15685
+ function metadata(node) {
15686
+ return node.metadata ??= {};
15687
+ }
15688
+
15689
+ function withLoc$1(node, source) {
15690
+ if (source) {
15691
+ if (source.start !== undefined) node.start = source.start;
15692
+ if (source.end !== undefined) node.end = source.end;
15693
+ if (source.loc !== undefined) node.loc = source.loc;
15694
+ }
15695
+ return node;
15696
+ }
15697
+
15698
+ function cloneNode(value) {
15699
+ if (Array.isArray(value)) return value.map(cloneNode);
15700
+ if (typeof value === "object" && value !== null) {
15701
+ const clone = {};
15702
+ for (const key of Object.keys(value)) {
15703
+ clone[key] = cloneNode(value[key]);
15704
+ }
15705
+ return clone;
15706
+ }
15707
+ return value;
15708
+ }
15709
+
15710
+ function ident(name, source) {
15711
+ return withLoc$1({ type: "Identifier", name }, source);
15712
+ }
15713
+
15714
+ function literal(value, source) {
15715
+ return withLoc$1({ type: "Literal", value, raw: JSON.stringify(value) }, source);
15716
+ }
15717
+
15718
+ function undefinedExpression(source) {
15719
+ return withLoc$1(
15720
+ { type: "UnaryExpression", operator: "void", prefix: true, argument: literal(0, source) },
15721
+ source
15722
+ );
15723
+ }
15724
+
15725
+ function member(object, property, computed, source) {
15726
+ return withLoc$1({ type: "MemberExpression", object, property, computed, optional: false }, source);
15727
+ }
15728
+
15729
+ function call(callee, args, source) {
15730
+ return withLoc$1({ type: "CallExpression", callee, arguments: args, optional: false }, source);
15731
+ }
15732
+
15733
+ function assignment(operator, left, right, source) {
15734
+ return withLoc$1({ type: "AssignmentExpression", operator, left, right }, source);
15735
+ }
15736
+
15737
+ function sequence(expressions, source) {
15738
+ return withLoc$1({ type: "SequenceExpression", expressions }, source);
15739
+ }
15740
+
15741
+ function conditional(test, consequent, alternate, source) {
15742
+ return withLoc$1({ type: "ConditionalExpression", test, consequent, alternate }, source);
15743
+ }
15744
+
15745
+ function binary(operator, left, right, source) {
15746
+ return withLoc$1({ type: "BinaryExpression", operator, left, right }, source);
15747
+ }
15748
+
15749
+ function logical(operator, left, right, source) {
15750
+ return withLoc$1({ type: "LogicalExpression", operator, left, right }, source);
15751
+ }
15752
+
15753
+ function variableDeclaration(kind, names, init) {
15754
+ return {
15755
+ type: "VariableDeclaration",
15756
+ kind,
15757
+ declarations: names.map((name, index) => ({
15758
+ type: "VariableDeclarator",
15759
+ id: ident(name),
15760
+ init: index === 0 && init ? init : null
15761
+ }))
15762
+ };
15763
+ }
15764
+
15765
+ function fail(message, node) {
15766
+ const start = node?.loc?.start;
15767
+ throw new SyntaxError(start ? `${message} (${start.line}:${start.column})` : message);
15768
+ }
15769
+
15770
+ const AUTHORED_LAZY_UNSUPPORTED =
15771
+ "Solid's TSRX frontend does not support authored lazy destructuring; keep property and accessor reads explicit";
15772
+
15773
+ /**
15774
+ * Reject parser-authored `&{}` / `&[]` before TSRX controls synthesize the
15775
+ * deferred patterns Solid needs for accessor-backed `@for` and `@catch`
15776
+ * callbacks.
15777
+ */
15778
+ function rejectAuthoredLazyDestructuring(root) {
15779
+ const visit = (value) => {
15780
+ if (Array.isArray(value)) {
15781
+ for (const child of value) visit(child);
15782
+ return;
15783
+ }
15784
+ if (!isNode$1(value)) return;
15785
+ if ((value.type === "ObjectPattern" || value.type === "ArrayPattern") && value.lazy === true) {
15786
+ fail(AUTHORED_LAZY_UNSUPPORTED, value);
15787
+ }
15788
+ for (const key of Object.keys(value)) {
15789
+ if (!SKIP_KEYS$1.has(key)) visit(value[key]);
15790
+ }
15791
+ };
15792
+ visit(root);
15793
+ }
15794
+
15795
+ class LazyState {
15796
+ names = new Set();
15797
+ next = new Map();
15798
+ programTemps = [];
15799
+ tempScopes = [this.programTemps];
15800
+
15801
+
15802
+ usesArrayRest = false;
15803
+ topLevelGlobalThisBinding = false;
15804
+
15805
+ constructor(root) {
15806
+ this.collectNames(root);
15807
+ this.topLevelGlobalThisBinding = programBindsName(root, "globalThis");
15808
+ }
15809
+
15810
+ collectNames(value) {
15811
+ if (Array.isArray(value)) {
15812
+ for (const child of value) this.collectNames(child);
15813
+ return;
15814
+ }
15815
+ if (!isNode$1(value)) return;
15816
+ if (value.type === "Identifier" || value.type === "JSXIdentifier") {
15817
+ this.names.add(value.name);
15818
+ }
15819
+ for (const key of Object.keys(value)) {
15820
+ if (!SKIP_KEYS$1.has(key)) this.collectNames(value[key]);
15821
+ }
15822
+ }
15823
+
15824
+ name(prefix) {
15825
+ let index = this.next.get(prefix) ?? 0;
15826
+ let name;
15827
+ do name = `${prefix}${index++}`; while (
15828
+ this.names.has(name));
15829
+ this.next.set(prefix, index);
15830
+ this.names.add(name);
15831
+ return name;
15832
+ }
15833
+
15834
+ temp() {
15835
+ const name = this.name("__lazyValue");
15836
+ this.tempScopes[this.tempScopes.length - 1].push(name);
15837
+ return name;
15838
+ }
15839
+
15840
+ pushFunctionTemps() {
15841
+ this.tempScopes.push([]);
15842
+ }
15843
+
15844
+ popFunctionTemps() {
15845
+ if (this.tempScopes.length === 1) {
15846
+ return fail("Internal TSRX lazy-transform temporary-scope imbalance");
15847
+ }
15848
+ return this.tempScopes.pop();
15849
+ }
15850
+
15851
+ defaultRead(
15852
+ raw,
15853
+ fallback,
15854
+ bindings,
15855
+ selfName,
15856
+ source)
15857
+ {
15858
+ const tempName = this.temp();
15859
+ const temp = () => ident(tempName, source);
15860
+ const fallbackBindings = new Map(bindings);
15861
+ fallbackBindings.delete(selfName);
15862
+ return sequence(
15863
+ [
15864
+ assignment("=", temp(), raw, source),
15865
+ conditional(
15866
+ binary("===", temp(), undefinedExpression(source), source),
15867
+ transform(cloneNode(fallback), fallbackBindings, this),
15868
+ temp(),
15869
+ source
15870
+ )],
15871
+
15872
+ source
15873
+ );
15874
+ }
15875
+
15876
+ omitIdentifier() {
15877
+ this.omitName ??= this.name("__lazyOmit");
15878
+ return ident(this.omitName);
15879
+ }
15880
+
15881
+ arrayIdentifier(node) {
15882
+ if (this.topLevelGlobalThisBinding) {
15883
+ fail(
15884
+ "TSRX lazy array rest cannot safely access the intrinsic Array because this module binds `globalThis`; rename that top-level binding",
15885
+ node
15886
+ );
15887
+ }
15888
+ this.usesArrayRest = true;
15889
+ this.arrayName ??= this.name("__lazyArray");
15890
+ return ident(this.arrayName, node);
15891
+ }
15892
+
15893
+ finalize(program) {
15894
+ if (program.type !== "Program") {
15895
+ if (this.omitName || this.usesArrayRest || this.programTemps.length) {
15896
+ return fail("The TSRX lazy transform requires a Program root", program);
15897
+ }
15898
+ return program;
15899
+ }
15900
+
15901
+ const generated = [];
15902
+ if (this.arrayName) {
15903
+ generated.push(
15904
+ variableDeclaration(
15905
+ "const",
15906
+ [this.arrayName],
15907
+ member(ident("globalThis"), ident("Array"), false)
15908
+ )
15909
+ );
15910
+ }
15911
+ if (this.programTemps.length) generated.push(variableDeclaration("let", this.programTemps));
15912
+
15913
+ const body = program.body;
15914
+ let directiveEnd = 0;
15915
+ while (
15916
+ directiveEnd < body.length &&
15917
+ body[directiveEnd].type === "ExpressionStatement" &&
15918
+ typeof body[directiveEnd].directive === "string")
15919
+ {
15920
+ directiveEnd++;
15921
+ }
15922
+ let importEnd = directiveEnd;
15923
+ while (importEnd < body.length && body[importEnd].type === "ImportDeclaration") importEnd++;
15924
+
15925
+ const additions = [];
15926
+ if (this.omitName) {
15927
+ additions.push({
15928
+ type: "ImportDeclaration",
15929
+ specifiers: [
15930
+ {
15931
+ type: "ImportSpecifier",
15932
+ imported: ident("omit"),
15933
+ local: ident(this.omitName)
15934
+ }],
15935
+
15936
+ source: literal("solid-js")
15937
+ });
15938
+ }
15939
+ additions.push(...generated);
15940
+ if (additions.length) {
15941
+ program.body = [...body.slice(0, importEnd), ...additions, ...body.slice(importEnd)];
15942
+ }
15943
+ return program;
15944
+ }
15945
+ }
15946
+
15947
+ function programBindsName(root, name) {
15948
+ if (root.type !== "Program") return false;
15949
+ for (const statement of root.body) {
15950
+ const declaration =
15951
+ (statement.type === "ExportNamedDeclaration" ||
15952
+ statement.type === "ExportDefaultDeclaration") &&
15953
+ isNode$1(statement.declaration) ?
15954
+ statement.declaration :
15955
+ statement;
15956
+ if (declaration.type === "VariableDeclaration") {
15957
+ for (const item of declaration.declarations) {
15958
+ const names = new Set();
15959
+ patternNames(item.id, names);
15960
+ if (names.has(name)) return true;
15961
+ }
15962
+ } else if (
15963
+ (declaration.type === "FunctionDeclaration" || declaration.type === "ClassDeclaration") &&
15964
+ isNode$1(declaration.id) &&
15965
+ declaration.id.name === name)
15966
+ {
15967
+ return true;
15968
+ } else if (statement.type === "ImportDeclaration") {
15969
+ for (const specifier of statement.specifiers) {
15970
+ if (isNode$1(specifier.local) && specifier.local.name === name) return true;
15971
+ }
15972
+ }
15973
+ }
15974
+ return false;
15975
+ }
15976
+
15977
+ function assertWritable(binding, node) {
15978
+ if (binding.complexDefault) {
15979
+ fail(
15980
+ "A TSRX lazy binding nested beneath an ancestor default is read-only; assign to the source object explicitly",
15981
+ node
15982
+ );
15983
+ }
15984
+ }
15985
+
15986
+ function staticPropertyName(node) {
15987
+ if (node.type === "Identifier") return node.name;
15988
+ if (node.type === "Literal") return String(node.value);
15989
+ return null;
15990
+ }
15991
+
15992
+ function typePropertyKeys(typeAnnotation) {
15993
+ const keys = new Map();
15994
+ const type = typeAnnotation?.typeAnnotation;
15995
+ if (type?.type !== "TSTypeLiteral") return keys;
15996
+ for (const item of type.members ?? []) {
15997
+ if (item.type !== "TSPropertySignature" || !isNode$1(item.key)) continue;
15998
+ const name = staticPropertyName(item.key);
15999
+ if (name !== null && !keys.has(name)) keys.set(name, item.key);
16000
+ }
16001
+ return keys;
16002
+ }
16003
+
16004
+ function patternRange(pattern) {
16005
+ if (pattern.start === undefined || pattern.end === undefined || pattern.loc === undefined) {
16006
+ return null;
16007
+ }
16008
+ const annotation = pattern.typeAnnotation;
16009
+ return {
16010
+ type: "Identifier",
16011
+ start: pattern.start,
16012
+ end: annotation?.start ?? pattern.end,
16013
+ loc: {
16014
+ start: pattern.loc.start,
16015
+ end:
16016
+ annotation?.loc?.start ??
16017
+ pattern.loc.end
16018
+ }
16019
+ };
16020
+ }
16021
+
16022
+ function generatedPatternIdentifier(pattern, name, isTop) {
16023
+ const range = patternRange(pattern);
16024
+ const id = ident(name, range);
16025
+ if (range && range.start !== undefined && range.end !== undefined) {
16026
+ metadata(id).source_length = range.end - range.start;
16027
+ }
16028
+ if (isTop && isNode$1(pattern.typeAnnotation)) id.typeAnnotation = pattern.typeAnnotation;
16029
+ if (isTop) setParamTypeMappings(id, pattern);
16030
+ return id;
16031
+ }
16032
+
16033
+ function setParamTypeMappings(id, pattern) {
16034
+ if (pattern.type !== "ObjectPattern") return;
16035
+ const keys = typePropertyKeys(id.typeAnnotation);
16036
+ if (!keys.size) return;
16037
+ const mappings = [];
16038
+ for (const property of pattern.properties) {
16039
+ if (property.type === "RestElement" || property.computed) continue;
16040
+ const value = property.value;
16041
+ const actual = value.type === "AssignmentPattern" ? value.left : value;
16042
+ if (actual.type !== "Identifier" || actual.start === undefined) continue;
16043
+ const name = staticPropertyName(property.key);
16044
+ const generated = name === null ? undefined : keys.get(name);
16045
+ if (generated?.start !== undefined) {
16046
+ metadata(generated).disable_verification = true;
16047
+ mappings.push({ source: actual, generated });
16048
+ }
16049
+ }
16050
+ if (mappings.length) metadata(id).lazy_param_binding_mappings = mappings;
16051
+ }
16052
+
16053
+ function visitTopmostLazyPatterns(
16054
+ pattern,
16055
+ visit)
16056
+ {
16057
+ if (!pattern) return;
16058
+ if (pattern.type === "AssignmentPattern") {
16059
+ visitTopmostLazyPatterns(pattern.left, visit);
16060
+ return;
16061
+ }
16062
+ if (pattern.type === "RestElement") {
16063
+ visitTopmostLazyPatterns(pattern.argument, visit);
16064
+ return;
16065
+ }
16066
+ if (pattern.type !== "ObjectPattern" && pattern.type !== "ArrayPattern") return;
16067
+ if (pattern.lazy) {
16068
+ visit(pattern);
16069
+ return;
16070
+ }
16071
+ if (pattern.type === "ObjectPattern") {
16072
+ for (const property of pattern.properties) {
16073
+ visitTopmostLazyPatterns(
16074
+ property.type === "RestElement" ? property.argument : property.value,
16075
+ visit
16076
+ );
16077
+ }
16078
+ } else {
16079
+ for (const element of pattern.elements) {
16080
+ if (element) visitTopmostLazyPatterns(element, visit);
16081
+ }
16082
+ }
16083
+ }
16084
+
16085
+ function preallocate(root, state) {
16086
+ const assign = (pattern) => {
16087
+ visitTopmostLazyPatterns(pattern, (lazy) => {
16088
+ if (!metadata(lazy).lazy_id) metadata(lazy).lazy_id = state.name("__lazy");
16089
+ });
16090
+ };
16091
+
16092
+ const visit = (value) => {
16093
+ if (Array.isArray(value)) {
16094
+ let found = false;
16095
+ for (const child of value) if (visit(child)) found = true;
16096
+ return found;
16097
+ }
16098
+ if (!isNode$1(value)) return false;
16099
+
16100
+ const functionLike = FUNCTION_TYPES.has(value.type);
16101
+ if (functionLike) {
16102
+ for (const param of value.params) {
16103
+ assign(param.type === "AssignmentPattern" ? param.left : param);
16104
+ }
16105
+ }
16106
+ if (value.type === "VariableDeclarator") assign(value.id);
16107
+ if (value.type === "CatchClause" && isNode$1(value.param)) assign(value.param);
16108
+ if (
16109
+ value.type === "ExpressionStatement" &&
16110
+ isNode$1(value.expression) &&
16111
+ value.expression.type === "AssignmentExpression" &&
16112
+ value.expression.operator === "=")
16113
+ {
16114
+ assign(value.expression.left);
16115
+ }
16116
+
16117
+ let found =
16118
+ (value.type === "ObjectPattern" || value.type === "ArrayPattern") && value.lazy === true;
16119
+ for (const key of Object.keys(value)) {
16120
+ if (SKIP_KEYS$1.has(key)) continue;
16121
+ if (visit(value[key])) found = true;
16122
+ }
16123
+ if (functionLike && found) metadata(value).has_lazy_descendants = true;
16124
+ return found;
16125
+ };
16126
+ visit(root);
16127
+ }
16128
+
16129
+ function transformedEmbedded(
16130
+ node,
16131
+ bindings,
16132
+ state,
16133
+ selfName)
16134
+ {
16135
+ const effective = new Map(bindings);
16136
+ effective.delete(selfName);
16137
+ return transform(cloneNode(node), effective, state);
16138
+ }
16139
+
16140
+ function rootAccess(sourceName, accessor) {
16141
+ const source = (reference) => {
16142
+ const identifier = ident(sourceName, reference);
16143
+ return accessor ? call(identifier, [], reference) : identifier;
16144
+ };
16145
+ return {
16146
+ raw: (reference) => source(reference),
16147
+ value: (reference) => source(reference),
16148
+ plain: true,
16149
+ jsxCompatible: !accessor,
16150
+ complexDefault: false
16151
+ };
16152
+ }
16153
+
16154
+ function propertyAccess(parent, key, computed, state) {
16155
+ const property = (bindings, selfName, reference) =>
16156
+ computed ?
16157
+ transformedEmbedded(key, bindings, state, selfName) :
16158
+ ident(key.name, reference);
16159
+ return {
16160
+ raw: (reference, bindings, selfName) =>
16161
+ member(
16162
+ parent.raw(reference, bindings, selfName),
16163
+ property(bindings, selfName, reference),
16164
+ computed,
16165
+ reference
16166
+ ),
16167
+ value: (reference, bindings, selfName) =>
16168
+ member(
16169
+ parent.value(reference, bindings, selfName),
16170
+ property(bindings, selfName, reference),
16171
+ computed,
16172
+ reference
16173
+ ),
16174
+ plain: parent.plain,
16175
+ jsxCompatible: parent.jsxCompatible && !computed,
16176
+ complexDefault: parent.complexDefault || parent.directDefault !== undefined
16177
+ };
16178
+ }
16179
+
16180
+ function defaultAccess(parent, fallback, state) {
16181
+ return {
16182
+ raw: parent.raw,
16183
+ value: (reference, bindings, selfName) =>
16184
+ state.defaultRead(
16185
+ parent.value(reference, bindings, selfName),
16186
+ fallback,
16187
+ bindings,
16188
+ selfName,
16189
+ reference
16190
+ ),
16191
+ plain: false,
16192
+ jsxCompatible: false,
16193
+ directDefault: fallback,
16194
+ complexDefault: parent.complexDefault || parent.directDefault !== undefined
16195
+ };
16196
+ }
16197
+
16198
+ function jsxNameFromMember(expression, source) {
16199
+ if (expression.type === "Identifier") {
16200
+ return withLoc$1({ type: "JSXIdentifier", name: expression.name }, source);
16201
+ }
16202
+ if (
16203
+ expression.type === "MemberExpression" &&
16204
+ !expression.computed &&
16205
+ isNode$1(expression.property) &&
16206
+ expression.property.type === "Identifier")
16207
+ {
16208
+ const object = jsxNameFromMember(expression.object, source);
16209
+ if (object) {
16210
+ return withLoc$1(
16211
+ {
16212
+ type: "JSXMemberExpression",
16213
+ object,
16214
+ property: withLoc$1(
16215
+ { type: "JSXIdentifier", name: expression.property.name },
16216
+ expression.property
16217
+ )
16218
+ },
16219
+ source
16220
+ );
16221
+ }
16222
+ }
16223
+ return null;
16224
+ }
16225
+
16226
+ function registerBinding(
16227
+ name,
16228
+ sourceName,
16229
+ access,
16230
+ bindings)
16231
+ {
16232
+ bindings.set(name, {
16233
+ sourceName,
16234
+ read(reference, current) {
16235
+ return access.value(reference, current, name);
16236
+ },
16237
+ target(reference, current) {
16238
+ return access.raw(reference, current, name);
16239
+ },
16240
+ jsxName(reference, current) {
16241
+ return access.jsxCompatible ?
16242
+ jsxNameFromMember(access.raw(reference, current, name), reference) :
16243
+ null;
16244
+ },
16245
+ directDefault: access.directDefault,
16246
+ complexDefault: access.complexDefault
16247
+ });
16248
+ }
16249
+
16250
+ function collectBindingsAt(
16251
+ pattern,
16252
+ sourceName,
16253
+ access,
16254
+ bindings,
16255
+ state)
16256
+ {
16257
+ if (pattern.type === "AssignmentPattern") {
16258
+ collectBindingsAt(
16259
+ pattern.left,
16260
+ sourceName,
16261
+ defaultAccess(access, pattern.right, state),
16262
+ bindings,
16263
+ state
16264
+ );
16265
+ return;
16266
+ }
16267
+ if (pattern.type === "Identifier") {
16268
+ registerBinding(pattern.name, sourceName, access, bindings);
16269
+ return;
16270
+ }
16271
+ if (pattern.type === "ObjectPattern") {
16272
+ const properties = pattern.properties;
16273
+ const sourceKeys = properties.
16274
+ filter((property) => property.type !== "RestElement").
16275
+ map((property) => {
16276
+ const key = property.key;
16277
+ return property.computed ? key : literal(staticPropertyName(key) ?? "", key);
16278
+ });
16279
+ for (const property of properties) {
16280
+ if (property.type === "RestElement") {
16281
+ const argument = property.argument;
16282
+ if (argument.type !== "Identifier") {
16283
+ fail("TSRX lazy object rest currently requires an identifier binding", argument);
16284
+ }
16285
+ const name = argument.name;
16286
+ bindings.set(name, {
16287
+ sourceName,
16288
+ read(reference, current) {
16289
+ const effective = new Map(current);
16290
+ effective.delete(name);
16291
+ return call(
16292
+ state.omitIdentifier(),
16293
+ [
16294
+ access.value(reference, current, name),
16295
+ ...sourceKeys.map((key) => transform(cloneNode(key), effective, state))],
16296
+
16297
+ reference
16298
+ );
16299
+ },
16300
+ target() {
16301
+ return null;
16302
+ },
16303
+ jsxName() {
16304
+ return null;
16305
+ },
16306
+ complexDefault: access.complexDefault
16307
+ });
16308
+ continue;
16309
+ }
16310
+ const key = property.key;
16311
+ const computed = !!property.computed || key.type !== "Identifier";
16312
+ collectBindingsAt(
16313
+ property.value,
16314
+ sourceName,
16315
+ propertyAccess(access, key, computed, state),
16316
+ bindings,
16317
+ state
16318
+ );
16319
+ }
16320
+ return;
16321
+ }
16322
+ if (pattern.type === "ArrayPattern") {
16323
+ const elements = pattern.elements;
16324
+ for (let index = 0; index < elements.length; index++) {
16325
+ const element = elements[index];
16326
+ if (!element) continue;
16327
+ if (element.type === "RestElement") {
16328
+ const argument = element.argument;
16329
+ if (argument.type !== "Identifier") {
16330
+ fail("TSRX lazy array rest currently requires an identifier binding", argument);
16331
+ }
16332
+ const name = argument.name;
16333
+ // Reserve and validate the intrinsic alias when the pattern is
16334
+ // registered, even if the rest binding is never read. The native
16335
+ // frontend plans helpers at binding time and must emit the same
16336
+ // `globalThis` shadowing diagnostic.
16337
+ state.arrayIdentifier(argument);
16338
+ bindings.set(name, {
16339
+ sourceName,
16340
+ read(reference, current) {
16341
+ const from = member(
16342
+ state.arrayIdentifier(reference),
16343
+ ident("from", reference),
16344
+ false,
16345
+ reference
16346
+ );
16347
+ const array = call(from, [access.value(reference, current, name)], reference);
16348
+ return call(
16349
+ member(array, ident("slice", reference), false, reference),
16350
+ [literal(index, reference)],
16351
+ reference
16352
+ );
16353
+ },
16354
+ target() {
16355
+ return null;
16356
+ },
16357
+ jsxName() {
16358
+ return null;
16359
+ },
16360
+ complexDefault: access.complexDefault
16361
+ });
16362
+ continue;
16363
+ }
16364
+ collectBindingsAt(
16365
+ element,
16366
+ sourceName,
16367
+ propertyAccess(access, literal(index, element), true, state),
16368
+ bindings,
16369
+ state
16370
+ );
16371
+ }
16372
+ }
16373
+ }
16374
+
16375
+ function collectBindings(
16376
+ pattern,
16377
+ sourceName,
16378
+ bindings,
16379
+ state)
16380
+ {
16381
+ collectBindingsAt(
16382
+ pattern,
16383
+ sourceName,
16384
+ rootAccess(sourceName, metadata(pattern).lazy_source_accessor === true),
16385
+ bindings,
16386
+ state
16387
+ );
16388
+ }
16389
+
16390
+ function collectBindingsFromStatements(
16391
+ statements,
16392
+ bindings,
16393
+ state)
16394
+ {
16395
+ for (const statement of statements) {
16396
+ const declaration =
16397
+ (statement.type === "ExportNamedDeclaration" ||
16398
+ statement.type === "ExportDefaultDeclaration") &&
16399
+ isNode$1(statement.declaration) ?
16400
+ statement.declaration :
16401
+ statement;
16402
+ if (declaration.type === "VariableDeclaration" && declaration.kind !== "var") {
16403
+ for (const item of declaration.declarations) {
16404
+ visitTopmostLazyPatterns(item.id, (lazy) => {
16405
+ const sourceName = metadata(lazy).lazy_id;
16406
+ if (sourceName) collectBindings(lazy, sourceName, bindings, state);
16407
+ });
16408
+ }
16409
+ } else if (
16410
+ statement.type === "ExpressionStatement" &&
16411
+ isNode$1(statement.expression) &&
16412
+ statement.expression.type === "AssignmentExpression" &&
16413
+ statement.expression.operator === "=")
16414
+ {
16415
+ visitTopmostLazyPatterns(statement.expression.left, (lazy) => {
16416
+ const sourceName = metadata(lazy).lazy_id;
16417
+ if (sourceName) collectBindings(lazy, sourceName, bindings, state);
16418
+ });
16419
+ }
16420
+ }
16421
+ }
16422
+
16423
+
16424
+
16425
+
16426
+
16427
+
16428
+ /**
16429
+ * Collect function/program-scoped `var` declarations before rewriting any
16430
+ * references in that scope. `var` crosses blocks, loops, switches, and catch
16431
+ * bodies, but never crosses a nested function, class, or class static block.
16432
+ */
16433
+ function collectVarScopeBindings(statements, state) {
16434
+ const declared = new Set();
16435
+ const lazy = new Map();
16436
+
16437
+ const visit = (value) => {
16438
+ if (Array.isArray(value)) {
16439
+ for (const child of value) visit(child);
16440
+ return;
16441
+ }
16442
+ if (!isNode$1(value)) return;
16443
+ if (
16444
+ FUNCTION_TYPES.has(value.type) ||
16445
+ value.type === "ClassDeclaration" ||
16446
+ value.type === "ClassExpression" ||
16447
+ value.type === "StaticBlock" ||
16448
+ value.type === "ClassStaticBlock")
16449
+ {
16450
+ return;
16451
+ }
16452
+ if (value.type === "VariableDeclaration" && value.kind === "var") {
16453
+ for (const declaration of value.declarations) {
16454
+ patternNames(declaration.id, declared);
16455
+ visitTopmostLazyPatterns(declaration.id, (pattern) => {
16456
+ const sourceName = metadata(pattern).lazy_id;
16457
+ if (sourceName) collectBindings(pattern, sourceName, lazy, state);
16458
+ });
16459
+ }
16460
+ }
16461
+ for (const key of Object.keys(value)) {
16462
+ if (!SKIP_KEYS$1.has(key)) visit(value[key]);
16463
+ }
16464
+ };
16465
+
16466
+ visit(statements);
16467
+ return { declared, lazy };
16468
+ }
16469
+
16470
+ function replaceLazyInPattern(pattern, isTop = true) {
16471
+ if (pattern.type === "AssignmentPattern") {
16472
+ const left = replaceLazyInPattern(pattern.left, isTop);
16473
+ return left === pattern.left ? pattern : { ...pattern, left };
16474
+ }
16475
+ if (pattern.type === "RestElement") {
16476
+ const argument = replaceLazyInPattern(pattern.argument, false);
16477
+ return argument === pattern.argument ? pattern : { ...pattern, argument };
16478
+ }
16479
+ if (pattern.type !== "ObjectPattern" && pattern.type !== "ArrayPattern") return pattern;
16480
+ const sourceName = metadata(pattern).lazy_id;
16481
+ if (pattern.lazy && sourceName) return generatedPatternIdentifier(pattern, sourceName, isTop);
16482
+ if (pattern.type === "ObjectPattern") {
16483
+ let changed = false;
16484
+ const properties = pattern.properties.map((property) => {
16485
+ const key = property.type === "RestElement" ? "argument" : "value";
16486
+ const value = property[key];
16487
+ const replacement = replaceLazyInPattern(value, false);
16488
+ if (replacement === value) return property;
16489
+ changed = true;
16490
+ return { ...property, [key]: replacement };
16491
+ });
16492
+ return changed ? { ...pattern, properties } : pattern;
16493
+ }
16494
+ let changed = false;
16495
+ const elements = pattern.elements.map((element) => {
16496
+ if (!element) return element;
16497
+ const replacement = replaceLazyInPattern(element, false);
16498
+ if (replacement !== element) changed = true;
16499
+ return replacement;
16500
+ });
16501
+ return changed ? { ...pattern, elements } : pattern;
16502
+ }
16503
+
16504
+ function replaceLazyParams(params) {
16505
+ return params.map((param) => replaceLazyInPattern(param));
16506
+ }
16507
+
16508
+ function patternNames(pattern, names) {
16509
+ switch (pattern.type) {
16510
+ case "Identifier":
16511
+ names.add(pattern.name);
16512
+ return;
16513
+ case "AssignmentPattern":
16514
+ patternNames(pattern.left, names);
16515
+ return;
16516
+ case "RestElement":
16517
+ patternNames(pattern.argument, names);
16518
+ return;
16519
+ case "ObjectPattern":
16520
+ for (const property of pattern.properties) {
16521
+ patternNames(
16522
+ property.type === "RestElement" ? property.argument : property.value,
16523
+ names
16524
+ );
16525
+ }
16526
+ return;
16527
+ case "ArrayPattern":
16528
+ for (const element of pattern.elements) {
16529
+ if (element) patternNames(element, names);
16530
+ }
16531
+ }
16532
+ }
16533
+
16534
+ function collectShadowed(pattern, bindings, names) {
16535
+ const all = new Set();
16536
+ patternNames(pattern, all);
16537
+ for (const name of all) if (bindings.has(name)) names.add(name);
16538
+ }
16539
+
16540
+ function collectBlockShadowed(statements, bindings) {
16541
+ const names = new Set();
16542
+ for (const statement of statements) {
16543
+ const declaration =
16544
+ (statement.type === "ExportNamedDeclaration" ||
16545
+ statement.type === "ExportDefaultDeclaration") &&
16546
+ isNode$1(statement.declaration) ?
16547
+ statement.declaration :
16548
+ statement;
16549
+ if (declaration.type === "VariableDeclaration" && declaration.kind !== "var") {
16550
+ for (const item of declaration.declarations) {
16551
+ collectShadowed(item.id, bindings, names);
16552
+ }
16553
+ } else if (
16554
+ (declaration.type === "FunctionDeclaration" || declaration.type === "ClassDeclaration") &&
16555
+ isNode$1(declaration.id) &&
16556
+ bindings.has(declaration.id.name))
16557
+ {
16558
+ names.add(declaration.id.name);
16559
+ } else if (statement.type === "ImportDeclaration") {
16560
+ for (const specifier of statement.specifiers) {
16561
+ if (isNode$1(specifier.local) && bindings.has(specifier.local.name)) {
16562
+ names.add(specifier.local.name);
16563
+ }
16564
+ }
16565
+ }
16566
+ }
16567
+ return names;
16568
+ }
16569
+
16570
+ function without(bindings, names) {
16571
+ const result = new Map(bindings);
16572
+ for (const name of names) result.delete(name);
16573
+ return result;
16574
+ }
16575
+
16576
+ function transformValue(value, bindings, state) {
16577
+ if (Array.isArray(value)) return value.map((item) => transformValue(item, bindings, state));
16578
+ return isNode$1(value) ? transform(value, bindings, state) : value;
16579
+ }
16580
+
16581
+ function targetParts(target, source) {
16582
+ if (target.type !== "MemberExpression") {
16583
+ return fail("A writable TSRX lazy binding did not resolve to a member expression", source);
16584
+ }
16585
+ const property = target.property;
16586
+ return {
16587
+ object: target.object,
16588
+ key: target.computed ? property : literal(property.name, property)
16589
+ };
16590
+ }
16591
+
16592
+ function lowerDefaultedAssignment(
16593
+ node,
16594
+ binding,
16595
+ bindings,
16596
+ state)
16597
+ {
16598
+ if (!binding.directDefault) return fail("Missing default for TSRX lazy assignment", node);
16599
+ const left = node.left;
16600
+ const target = binding.target(left, bindings);
16601
+ if (!target) return fail("A TSRX lazy rest binding is read-only", left);
16602
+ const { object, key } = targetParts(target, left);
16603
+ const objectName = state.temp();
16604
+ const keyName = state.temp();
16605
+ const valueName = state.temp();
16606
+ const objectId = () => ident(objectName, left);
16607
+ const keyId = () => ident(keyName, left);
16608
+ const valueId = () => ident(valueName, left);
16609
+ const destination = () => member(objectId(), keyId(), true, left);
16610
+ const effective = new Map(bindings);
16611
+ effective.delete(left.name);
16612
+ const fallback = transform(cloneNode(binding.directDefault), effective, state);
16613
+ const right = transform(node.right, bindings, state);
16614
+ const operator = node.operator;
16615
+ const expressions = [
16616
+ assignment("=", objectId(), object, left),
16617
+ assignment("=", keyId(), key, left),
16618
+ assignment("=", valueId(), destination(), left),
16619
+ assignment(
16620
+ "=",
16621
+ valueId(),
16622
+ conditional(
16623
+ binary("===", valueId(), undefinedExpression(left), left),
16624
+ fallback,
16625
+ valueId(),
16626
+ left
16627
+ ),
16628
+ left
16629
+ )];
16630
+
16631
+
16632
+ if (operator === "&&=" || operator === "||=" || operator === "??=") {
16633
+ expressions.push(
16634
+ logical(operator.slice(0, -1), valueId(), assignment("=", destination(), right, node), node)
16635
+ );
16636
+ } else {
16637
+ expressions.push(
16638
+ assignment("=", destination(), binary(operator.slice(0, -1), valueId(), right, node), node)
16639
+ );
16640
+ }
16641
+ return sequence(expressions, node);
16642
+ }
16643
+
16644
+ function lowerDefaultedUpdate(
16645
+ node,
16646
+ binding,
16647
+ bindings,
16648
+ state)
16649
+ {
16650
+ if (!binding.directDefault) return fail("Missing default for TSRX lazy update", node);
16651
+ const argument = node.argument;
16652
+ const target = binding.target(argument, bindings);
16653
+ if (!target) return fail("A TSRX lazy rest binding is read-only", argument);
16654
+ const { object, key } = targetParts(target, argument);
16655
+ const objectName = state.temp();
16656
+ const keyName = state.temp();
16657
+ const valueName = state.temp();
16658
+ const objectId = () => ident(objectName, argument);
16659
+ const keyId = () => ident(keyName, argument);
16660
+ const valueId = () => ident(valueName, argument);
16661
+ const destination = () => member(objectId(), keyId(), true, argument);
16662
+ const effective = new Map(bindings);
16663
+ effective.delete(argument.name);
16664
+ const fallback = transform(cloneNode(binding.directDefault), effective, state);
16665
+ const expressions = [
16666
+ assignment("=", objectId(), object, argument),
16667
+ assignment("=", keyId(), key, argument),
16668
+ assignment("=", valueId(), destination(), argument),
16669
+ assignment(
16670
+ "=",
16671
+ valueId(),
16672
+ conditional(
16673
+ binary("===", valueId(), undefinedExpression(argument), argument),
16674
+ fallback,
16675
+ valueId(),
16676
+ argument
16677
+ ),
16678
+ argument
16679
+ )];
16680
+
16681
+
16682
+ if (node.prefix) {
16683
+ expressions.push(
16684
+ assignment(
16685
+ "=",
16686
+ destination(),
16687
+ withLoc$1(
16688
+ {
16689
+ type: "UpdateExpression",
16690
+ operator: node.operator,
16691
+ prefix: true,
16692
+ argument: valueId()
16693
+ },
16694
+ node
16695
+ ),
16696
+ node
16697
+ )
16698
+ );
16699
+ } else {
16700
+ const oldName = state.temp();
16701
+ const oldId = () => ident(oldName, argument);
16702
+ expressions.push(
16703
+ assignment(
16704
+ "=",
16705
+ oldId(),
16706
+ withLoc$1(
16707
+ {
16708
+ type: "UpdateExpression",
16709
+ operator: node.operator,
16710
+ prefix: false,
16711
+ argument: valueId()
16712
+ },
16713
+ node
16714
+ ),
16715
+ node
16716
+ ),
16717
+ assignment("=", destination(), valueId(), node),
16718
+ oldId()
16719
+ );
16720
+ }
16721
+ return sequence(expressions, node);
16722
+ }
16723
+
16724
+ function dynamicJsxElement(node, bindings, state) {
16725
+ const opening = node.openingElement;
16726
+ const name = opening.name;
16727
+ let base = name;
16728
+ const properties = [];
16729
+ while (base.type === "JSXMemberExpression") {
16730
+ properties.unshift(base.property);
16731
+ base = base.object;
16732
+ }
16733
+ if (base.type !== "JSXIdentifier" || !/^[A-Z]/.test(base.name)) return null;
16734
+ const binding = bindings.get(base.name);
16735
+ if (!binding || binding.jsxName(base, bindings)) return null;
16736
+
16737
+ let expression = binding.read(base, bindings);
16738
+ for (const property of properties) {
16739
+ expression = member(expression, ident(property.name, property), false, property);
16740
+ }
16741
+ const dynamicName = withLoc$1({ type: "JSXIdentifier", name: "Dynamic" }, name);
16742
+ const componentAttribute = {
16743
+ type: "JSXAttribute",
16744
+ name: withLoc$1({ type: "JSXIdentifier", name: "component" }, name),
16745
+ value: withLoc$1({ type: "JSXExpressionContainer", expression }, name)
16746
+ };
16747
+ const nextOpening = {
16748
+ ...opening,
16749
+ name: dynamicName,
16750
+ attributes: [
16751
+ componentAttribute,
16752
+ ...(opening.attributes ?? []).map((attribute) =>
16753
+ transform(attribute, bindings, state)
16754
+ )]
16755
+
16756
+ };
16757
+ const closing = node.closingElement;
16758
+ return {
16759
+ ...node,
16760
+ openingElement: nextOpening,
16761
+ closingElement: closing ? { ...closing, name: cloneNode(dynamicName) } : null,
16762
+ children: (node.children ?? []).map((child) => transform(child, bindings, state))
16763
+ };
16764
+ }
16765
+
16766
+ function addFunctionTemps(body, names) {
16767
+ if (!names.length) return body;
16768
+ const declaration = variableDeclaration("let", names);
16769
+ if (body.type !== "BlockStatement") {
16770
+ return {
16771
+ type: "BlockStatement",
16772
+ body: [declaration, withLoc$1({ type: "ReturnStatement", argument: body }, body)]
16773
+ };
16774
+ }
16775
+ const statements = body.body;
16776
+ let directiveEnd = 0;
16777
+ while (
16778
+ directiveEnd < statements.length &&
16779
+ statements[directiveEnd].type === "ExpressionStatement" &&
16780
+ typeof statements[directiveEnd].directive === "string")
16781
+ {
16782
+ directiveEnd++;
16783
+ }
16784
+ return {
16785
+ ...body,
16786
+ body: [...statements.slice(0, directiveEnd), declaration, ...statements.slice(directiveEnd)]
16787
+ };
16788
+ }
16789
+
16790
+ function transform(node, bindings, state) {
16791
+ if (FUNCTION_TYPES.has(node.type)) {
16792
+ const shadowed = new Set();
16793
+ if (isNode$1(node.id)) collectShadowed(node.id, bindings, shadowed);
16794
+ for (const param of node.params) collectShadowed(param, bindings, shadowed);
16795
+ const outer = shadowed.size ? without(bindings, shadowed) : bindings;
16796
+ const own = new Map();
16797
+ let lazyParam = false;
16798
+ for (const param of node.params) {
16799
+ visitTopmostLazyPatterns(param, (lazy) => {
16800
+ const sourceName = metadata(lazy).lazy_id;
16801
+ if (!sourceName) return;
16802
+ lazyParam = true;
16803
+ collectBindings(lazy, sourceName, own, state);
16804
+ });
16805
+ }
16806
+ const inner = own.size ? new Map([...outer, ...own]) : outer;
16807
+ let paramsChanged = false;
16808
+ const params = node.params.map((param) => {
16809
+ if (param.type !== "AssignmentPattern") return param;
16810
+ const right = transform(param.right, inner, state);
16811
+ if (right === param.right) return param;
16812
+ paramsChanged = true;
16813
+ return { ...param, right };
16814
+ });
16815
+ if (!inner.size && !paramsChanged && !lazyParam && !metadata(node).has_lazy_descendants) {
16816
+ return node;
16817
+ }
16818
+ state.pushFunctionTemps();
16819
+ const functionBody = node.body;
16820
+ let bodyBindings = inner;
16821
+ if (functionBody.type === "BlockStatement") {
16822
+ const varScope = collectVarScopeBindings(functionBody.body, state);
16823
+ const unshadowed = varScope.declared.size ?
16824
+ without(bodyBindings, varScope.declared) :
16825
+ bodyBindings;
16826
+ bodyBindings = new Map([...unshadowed, ...own, ...varScope.lazy]);
16827
+ }
16828
+ const transformedBody = transform(functionBody, bodyBindings, state);
16829
+ const bodyTemps = state.popFunctionTemps();
16830
+ const body = addFunctionTemps(transformedBody, bodyTemps);
16831
+ const finalParams = lazyParam ? replaceLazyParams(params) : params;
16832
+ return body !== node.body || finalParams !== node.params ?
16833
+ {
16834
+ ...node,
16835
+ params: finalParams,
16836
+ body,
16837
+ ...(node.type === "ArrowFunctionExpression" && body.type === "BlockStatement" ?
16838
+ { expression: false } :
16839
+ {})
16840
+ } :
16841
+ node;
16842
+ }
16843
+
16844
+ if (node.type === "Program") {
16845
+ const body = node.body;
16846
+ const varScope = collectVarScopeBindings(body, state);
16847
+ const varOuter = varScope.declared.size ? without(bindings, varScope.declared) : bindings;
16848
+ const withVar = varScope.lazy.size ? new Map([...varOuter, ...varScope.lazy]) : varOuter;
16849
+ const shadowed = collectBlockShadowed(body, withVar);
16850
+ const outer = shadowed.size ? without(withVar, shadowed) : withVar;
16851
+ const own = new Map();
16852
+ collectBindingsFromStatements(body, own, state);
16853
+ const inner = own.size ? new Map([...outer, ...own]) : outer;
16854
+ let changed = false;
16855
+ const next = body.map((statement) => {
16856
+ const result = transform(statement, inner, state);
16857
+ if (result !== statement) changed = true;
16858
+ return result;
16859
+ });
16860
+ return changed ? { ...node, body: next } : node;
16861
+ }
16862
+
16863
+ if (node.type === "BlockStatement") {
16864
+ const body = node.body;
16865
+ const shadowed = collectBlockShadowed(body, bindings);
16866
+ const outer = shadowed.size ? without(bindings, shadowed) : bindings;
16867
+ const own = new Map();
16868
+ collectBindingsFromStatements(body, own, state);
16869
+ const inner = own.size ? new Map([...outer, ...own]) : outer;
16870
+ let changed = false;
16871
+ const next = body.map((statement) => {
16872
+ const result = transform(statement, inner, state);
16873
+ if (result !== statement) changed = true;
16874
+ return result;
16875
+ });
16876
+ return changed ? { ...node, body: next } : node;
16877
+ }
16878
+
16879
+ if (node.type === "StaticBlock" || node.type === "ClassStaticBlock") {
16880
+ const body = node.body;
16881
+ const varScope = collectVarScopeBindings(body, state);
16882
+ const varOuter = varScope.declared.size ? without(bindings, varScope.declared) : bindings;
16883
+ const withVar = varScope.lazy.size ? new Map([...varOuter, ...varScope.lazy]) : varOuter;
16884
+ const shadowed = collectBlockShadowed(body, withVar);
16885
+ const outer = shadowed.size ? without(withVar, shadowed) : withVar;
16886
+ const own = new Map();
16887
+ collectBindingsFromStatements(body, own, state);
16888
+ const inner = own.size ? new Map([...outer, ...own]) : outer;
16889
+ let changed = false;
16890
+ const next = body.map((statement) => {
16891
+ const result = transform(statement, inner, state);
16892
+ if (result !== statement) changed = true;
16893
+ return result;
16894
+ });
16895
+ return changed ? { ...node, body: next } : node;
16896
+ }
16897
+
16898
+ if (node.type === "CatchClause") {
16899
+ const own = new Map();
16900
+ if (isNode$1(node.param)) {
16901
+ visitTopmostLazyPatterns(node.param, (lazy) => {
16902
+ const sourceName = metadata(lazy).lazy_id;
16903
+ if (sourceName) collectBindings(lazy, sourceName, own, state);
16904
+ });
16905
+ }
16906
+ const shadowed = new Set();
16907
+ if (isNode$1(node.param)) collectShadowed(node.param, bindings, shadowed);
16908
+ const outer = shadowed.size ? without(bindings, shadowed) : bindings;
16909
+ const inner = own.size ? new Map([...outer, ...own]) : outer;
16910
+ const param = isNode$1(node.param) ? replaceLazyInPattern(node.param, true) : node.param;
16911
+ const body = transform(node.body, inner, state);
16912
+ return param === node.param && body === node.body ? node : { ...node, param, body };
16913
+ }
16914
+
16915
+ if (node.type === "ForStatement") {
16916
+ const shadowed = new Set();
16917
+ const own = new Map();
16918
+ const init = node.init;
16919
+ if (init?.type === "VariableDeclaration") {
16920
+ for (const declaration of init.declarations) {
16921
+ if (init.kind !== "var") {
16922
+ visitTopmostLazyPatterns(declaration.id, (lazy) => {
16923
+ const sourceName = metadata(lazy).lazy_id;
16924
+ if (sourceName) collectBindings(lazy, sourceName, own, state);
16925
+ });
16926
+ collectShadowed(declaration.id, bindings, shadowed);
16927
+ }
16928
+ }
16929
+ }
16930
+ const outer = shadowed.size ? without(bindings, shadowed) : bindings;
16931
+ const inner = own.size ? new Map([...outer, ...own]) : outer;
16932
+ return {
16933
+ ...node,
16934
+ init: init ? transform(init, inner, state) : init,
16935
+ test: isNode$1(node.test) ? transform(node.test, inner, state) : node.test,
16936
+ update: isNode$1(node.update) ? transform(node.update, inner, state) : node.update,
16937
+ body: transform(node.body, inner, state)
16938
+ };
16939
+ }
16940
+
16941
+ if (node.type === "ForOfStatement" || node.type === "ForInStatement") {
16942
+ const shadowed = new Set();
16943
+ const own = new Map();
16944
+ const left = node.left;
16945
+ if (left.type === "VariableDeclaration") {
16946
+ for (const declaration of left.declarations) {
16947
+ if (left.kind !== "var") {
16948
+ visitTopmostLazyPatterns(declaration.id, (lazy) => {
16949
+ const sourceName = metadata(lazy).lazy_id;
16950
+ if (sourceName) collectBindings(lazy, sourceName, own, state);
16951
+ });
16952
+ collectShadowed(declaration.id, bindings, shadowed);
16953
+ }
16954
+ }
16955
+ }
16956
+ const outer = shadowed.size ? without(bindings, shadowed) : bindings;
16957
+ const inner = own.size ? new Map([...outer, ...own]) : outer;
16958
+ return {
16959
+ ...node,
16960
+ left: transform(left, inner, state),
16961
+ right: transform(node.right, inner, state),
16962
+ body: transform(node.body, inner, state)
16963
+ };
16964
+ }
16965
+
16966
+ if (node.type === "SwitchStatement") {
16967
+ const cases = node.cases;
16968
+ const statements = cases.flatMap((item) => item.consequent);
16969
+ const shadowed = collectBlockShadowed(statements, bindings);
16970
+ const outer = shadowed.size ? without(bindings, shadowed) : bindings;
16971
+ const own = new Map();
16972
+ collectBindingsFromStatements(statements, own, state);
16973
+ const inner = own.size ? new Map([...outer, ...own]) : outer;
16974
+ return {
16975
+ ...node,
16976
+ discriminant: transform(node.discriminant, outer, state),
16977
+ cases: cases.map((item) => ({
16978
+ ...item,
16979
+ test: isNode$1(item.test) ? transform(item.test, inner, state) : item.test,
16980
+ consequent: item.consequent.map((statement) =>
16981
+ transform(statement, inner, state)
16982
+ )
16983
+ }))
16984
+ };
16985
+ }
16986
+
16987
+ if (node.type === "ClassDeclaration" || node.type === "ClassExpression") {
16988
+ const shadowed = new Set();
16989
+ if (isNode$1(node.id)) collectShadowed(node.id, bindings, shadowed);
16990
+ const inner = shadowed.size ? without(bindings, shadowed) : bindings;
16991
+ return {
16992
+ ...node,
16993
+ superClass: isNode$1(node.superClass) ?
16994
+ transform(node.superClass, bindings, state) :
16995
+ node.superClass,
16996
+ body: transform(node.body, inner, state)
16997
+ };
16998
+ }
16999
+
17000
+ if (
17001
+ node.type === "ExportNamedDeclaration" &&
17002
+ isNode$1(node.declaration) &&
17003
+ node.declaration.type === "VariableDeclaration")
17004
+ {
17005
+ for (const declaration of node.declaration.declarations) {
17006
+ visitTopmostLazyPatterns(declaration.id, (pattern) => {
17007
+ fail(
17008
+ "TSRX lazy bindings cannot be exported; export the source object or an explicit accessor instead",
17009
+ pattern
17010
+ );
17011
+ });
17012
+ }
17013
+ }
17014
+
17015
+ if (
17016
+ node.type === "ExportSpecifier" &&
17017
+ isNode$1(node.local) &&
17018
+ node.local.type === "Identifier" &&
17019
+ bindings.has(node.local.name))
17020
+ {
17021
+ return fail(
17022
+ "TSRX lazy bindings cannot be exported; export the source object or an explicit accessor instead",
17023
+ node.local
17024
+ );
17025
+ }
17026
+
17027
+ if (node.type === "JSXElement") {
17028
+ const dynamic = dynamicJsxElement(node, bindings, state);
17029
+ if (dynamic) return dynamic;
17030
+ }
17031
+
17032
+ if (
17033
+ node.type === "ExpressionStatement" &&
17034
+ isNode$1(node.expression) &&
17035
+ node.expression.type === "AssignmentExpression" &&
17036
+ node.expression.operator === "=" &&
17037
+ isNode$1(node.expression.left) && (
17038
+ node.expression.left.type === "ObjectPattern" ||
17039
+ node.expression.left.type === "ArrayPattern") &&
17040
+ node.expression.left.lazy)
17041
+ {
17042
+ const pattern = node.expression.left;
17043
+ const sourceName = metadata(pattern).lazy_id;
17044
+ if (sourceName) {
17045
+ const id = generatedPatternIdentifier(pattern, sourceName, true);
17046
+ return {
17047
+ type: "VariableDeclaration",
17048
+ kind: "const",
17049
+ declarations: [
17050
+ {
17051
+ type: "VariableDeclarator",
17052
+ id,
17053
+ init: transform(node.expression.right, bindings, state)
17054
+ }]
17055
+
17056
+ };
17057
+ }
17058
+ }
17059
+
17060
+ if (
17061
+ node.type === "ExpressionStatement" &&
17062
+ isNode$1(node.expression) &&
17063
+ node.expression.type === "AssignmentExpression" &&
17064
+ node.expression.operator === "=" &&
17065
+ isNode$1(node.expression.left) && (
17066
+ node.expression.left.type === "ObjectPattern" ||
17067
+ node.expression.left.type === "ArrayPattern") &&
17068
+ !node.expression.left.lazy)
17069
+ {
17070
+ const left = replaceLazyInPattern(node.expression.left);
17071
+ if (left !== node.expression.left) {
17072
+ return fail(
17073
+ "A lazy pattern nested inside a standalone destructuring assignment is not supported because its generated source binding cannot be scoped correctly; use a lazy variable declaration",
17074
+ node.expression.left
17075
+ );
17076
+ }
17077
+ }
17078
+
17079
+ if (
17080
+ node.type === "AssignmentExpression" &&
17081
+ isNode$1(node.left) &&
17082
+ node.left.type === "Identifier")
17083
+ {
17084
+ const binding = bindings.get(node.left.name);
17085
+ if (binding) {
17086
+ assertWritable(binding, node.left);
17087
+ if (node.operator !== "=" && binding.directDefault) {
17088
+ return lowerDefaultedAssignment(node, binding, bindings, state);
17089
+ }
17090
+ const target = binding.target(node.left, bindings);
17091
+ if (!target) return fail("A TSRX lazy rest binding is read-only", node.left);
17092
+ return {
17093
+ ...node,
17094
+ left: target,
17095
+ right: transform(node.right, bindings, state)
17096
+ };
17097
+ }
17098
+ }
17099
+
17100
+ if (
17101
+ node.type === "UpdateExpression" &&
17102
+ isNode$1(node.argument) &&
17103
+ node.argument.type === "Identifier")
17104
+ {
17105
+ const binding = bindings.get(node.argument.name);
17106
+ if (binding) {
17107
+ assertWritable(binding, node.argument);
17108
+ if (binding.directDefault) {
17109
+ return lowerDefaultedUpdate(node, binding, bindings, state);
17110
+ }
17111
+ const target = binding.target(node.argument, bindings);
17112
+ if (!target) return fail("A TSRX lazy rest binding is read-only", node.argument);
17113
+ return { ...node, argument: target };
17114
+ }
17115
+ }
17116
+
17117
+ if (node.type === "VariableDeclarator" && isNode$1(node.id) && metadata(node.id).lazy_id) {
17118
+ const sourceName = metadata(node.id).lazy_id;
17119
+ return {
17120
+ ...node,
17121
+ id: generatedPatternIdentifier(node.id, sourceName, true),
17122
+ init: isNode$1(node.init) ? transform(node.init, bindings, state) : node.init
17123
+ };
17124
+ }
17125
+
17126
+ if (
17127
+ node.type === "VariableDeclarator" &&
17128
+ isNode$1(node.id) && (
17129
+ node.id.type === "ObjectPattern" || node.id.type === "ArrayPattern") &&
17130
+ !node.id.lazy)
17131
+ {
17132
+ const id = replaceLazyInPattern(node.id);
17133
+ if (id !== node.id) {
17134
+ return {
17135
+ ...node,
17136
+ id,
17137
+ init: isNode$1(node.init) ? transform(node.init, bindings, state) : node.init
17138
+ };
17139
+ }
17140
+ }
17141
+
17142
+ if (
17143
+ node.type === "Property" &&
17144
+ node.shorthand &&
17145
+ isNode$1(node.value) &&
17146
+ node.value.type === "Identifier")
17147
+ {
17148
+ const binding = bindings.get(node.value.name);
17149
+ if (binding) return { ...node, shorthand: false, value: binding.read(node.value, bindings) };
17150
+ }
17151
+
17152
+ if (node.type === "Identifier") {
17153
+ const binding = bindings.get(node.name);
17154
+ return binding ? binding.read(node, bindings) : node;
17155
+ }
17156
+
17157
+ if (node.type === "JSXIdentifier") return node;
17158
+ if (node.type === "MetaProperty") return node;
17159
+
17160
+ let changed = false;
17161
+ const clone = { ...node };
17162
+ for (const key of Object.keys(node)) {
17163
+ if (SKIP_KEYS$1.has(key) || TYPE_KEYS.has(key)) continue;
17164
+ if (
17165
+ key === "key" &&
17166
+ !node.computed && (
17167
+ node.type === "Property" ||
17168
+ node.type === "MethodDefinition" ||
17169
+ node.type === "PropertyDefinition"))
17170
+ {
17171
+ continue;
17172
+ }
17173
+ if (key === "property" && node.type === "MemberExpression" && !node.computed) continue;
17174
+ if (key === "property" && node.type === "JSXMemberExpression") continue;
17175
+ if (key === "name" && node.type === "JSXAttribute") continue;
17176
+ if (key === "id" && node.type === "VariableDeclarator") continue;
17177
+ if (
17178
+ (key === "local" || key === "imported" || key === "exported") &&
17179
+ /Specifier$/.test(node.type))
17180
+ {
17181
+ continue;
17182
+ }
17183
+ if (key === "label") continue;
17184
+
17185
+ if (
17186
+ key === "name" && (
17187
+ node.type === "JSXOpeningElement" || node.type === "JSXClosingElement") &&
17188
+ isNode$1(node.name))
17189
+ {
17190
+ const jsxName = rewriteJsxName(node.name, bindings);
17191
+ if (jsxName) {
17192
+ clone[key] = jsxName;
17193
+ changed = true;
17194
+ continue;
17195
+ }
17196
+ }
17197
+ const value = transformValue(node[key], bindings, state);
17198
+ if (value !== node[key]) {
17199
+ clone[key] = value;
17200
+ changed = true;
17201
+ }
17202
+ }
17203
+ return changed ? clone : node;
17204
+ }
17205
+
17206
+ function rewriteJsxName(name, bindings) {
17207
+ if (name.type === "JSXIdentifier") {
17208
+ if (!/^[A-Z]/.test(name.name)) return null;
17209
+ return bindings.get(name.name)?.jsxName(name, bindings) ?? null;
17210
+ }
17211
+ if (name.type === "JSXMemberExpression") {
17212
+ const object = rewriteJsxName(name.object, bindings);
17213
+ return object ? { ...name, object } : null;
17214
+ }
17215
+ return null;
17216
+ }
17217
+
17218
+ /** Apply Solid's local lazy transform to a fully desugared TSRX program. */
17219
+ function applyLazyTransforms(root) {
17220
+ const state = new LazyState(root);
17221
+ preallocate(root, state);
17222
+ return state.finalize(transform(root, new Map(), state));
17223
+ }
17224
+
17225
+ const SKIP_KEYS = new Set([
17226
+ "type",
17227
+ "loc",
17228
+ "start",
17229
+ "end",
17230
+ "range",
17231
+ "metadata",
17232
+ "css",
17233
+ "leadingComments",
17234
+ "trailingComments",
17235
+ "innerComments"]
17236
+ );
17237
+
17238
+ const FUNCTION_BOUNDARIES = new Set([
17239
+ "FunctionDeclaration",
17240
+ "FunctionExpression",
17241
+ "ArrowFunctionExpression",
17242
+ "ClassDeclaration",
17243
+ "ClassExpression"]
17244
+ );
17245
+
17246
+ function isNode(value) {
17247
+ return (
17248
+ typeof value === "object" &&
17249
+ value !== null &&
17250
+ typeof value.type === "string");
17251
+
17252
+ }
17253
+
17254
+ function isStyleElement(node) {
17255
+ return node.type === "JSXStyleElement";
17256
+ }
17257
+
17258
+ function isNativeRenderRoot(node) {
17259
+ return (
17260
+ (node.type === "JSXElement" || node.type === "JSXFragment") &&
17261
+ !!node.metadata?.native_tsrx);
17262
+
17263
+ }
17264
+
17265
+ function isNativeTsrxNode(node) {
17266
+ return (
17267
+ node?.type === "JSXCodeBlock" ||
17268
+ !!node && (
17269
+ node.type === "JSXElement" ||
17270
+ node.type === "JSXFragment" ||
17271
+ node.type === "JSXStyleElement") &&
17272
+ !!node.metadata?.native_tsrx);
17273
+
17274
+ }
17275
+
17276
+ function isStyleExpressionPosition(path) {
17277
+ const parent = path[path.length - 1];
17278
+ return !(
17279
+ isNativeTsrxNode(parent) ||
17280
+ parent?.type === "BlockStatement" ||
17281
+ parent?.type === "Program" ||
17282
+ parent?.type === "SwitchCase");
17283
+
17284
+ }
17285
+
17286
+ function structuralChildren(node) {
17287
+ switch (node.type) {
17288
+ case "JSXElement":
17289
+ case "JSXFragment":
17290
+ return (node.children ?? []).filter(isNode);
17291
+ case "JSXCodeBlock":
17292
+ return [
17293
+ ...(node.body ?? []).filter(isNode),
17294
+ ...(isNode(node.render) ? [node.render] : [])];
17295
+
17296
+ case "BlockStatement":
17297
+ return (node.body ?? []).filter(isNode);
17298
+ case "JSXIfExpression":
17299
+ case "IfStatement":
17300
+ return [node.consequent, node.alternate].filter(isNode);
17301
+ case "JSXForExpression":
17302
+ return [node.body, node.empty].filter(isNode);
17303
+ case "JSXSwitchExpression":
17304
+ case "SwitchStatement":
17305
+ return (node.cases ?? []).flatMap((switchCase) =>
17306
+ (switchCase.consequent ?? []).filter(isNode)
17307
+ );
17308
+ case "JSXTryExpression":
17309
+ case "TryStatement":
17310
+ return [node.block, node.pending, node.handler, node.finalizer].filter(isNode);
17311
+ case "CatchClause":
17312
+ return isNode(node.body) ? [node.body] : [];
17313
+ default:
17314
+ return [];
17315
+ }
17316
+ }
17317
+
17318
+ function collectRuntimeStyleElements(value, styles) {
17319
+ if (Array.isArray(value)) {
17320
+ for (const child of value) collectRuntimeStyleElements(child, styles);
17321
+ return;
17322
+ }
17323
+ if (isStyleElement(value)) {
17324
+ styles.push(value);
17325
+ return;
17326
+ }
17327
+ if (FUNCTION_BOUNDARIES.has(value.type)) return;
17328
+
17329
+ if ((value.type === "JSXElement" || value.type === "JSXFragment") && isNativeRenderRoot(value)) {
17330
+ collectRuntimeStyleElements(value.children ?? [], styles);
17331
+ return;
17332
+ }
17333
+ if (value.type === "BlockStatement") {
17334
+ collectRuntimeStyleElements(value.body ?? [], styles);
17335
+ return;
17336
+ }
17337
+ if (value.type === "JSXIfExpression" || value.type === "IfStatement") {
17338
+ if (isNode(value.consequent)) collectRuntimeStyleElements(value.consequent, styles);
17339
+ if (isNode(value.alternate)) collectRuntimeStyleElements(value.alternate, styles);
17340
+ return;
17341
+ }
17342
+ // This is an intentional ownership boundary in @tsrx/core: a style directly
17343
+ // rendered by an @for body is visited later as an unowned statement style.
17344
+ if (value.type === "JSXForExpression") return;
17345
+ if (value.type === "JSXSwitchExpression" || value.type === "SwitchStatement") {
17346
+ for (const switchCase of value.cases ?? []) {
17347
+ collectRuntimeStyleElements(switchCase.consequent ?? [], styles);
17348
+ }
17349
+ return;
17350
+ }
17351
+ if (value.type === "JSXTryExpression" || value.type === "TryStatement") {
17352
+ if (isNode(value.block)) collectRuntimeStyleElements(value.block, styles);
17353
+ const handler = isNode(value.handler) ? value.handler : undefined;
17354
+ if (handler && isNode(handler.body)) collectRuntimeStyleElements(handler.body, styles);
17355
+ if (isNode(value.finalizer)) collectRuntimeStyleElements(value.finalizer, styles);
17356
+ // `pending` is deliberately absent: core does not assign direct @pending
17357
+ // statement styles to the surrounding fragment.
17358
+ }
17359
+ }
17360
+
17361
+ function collectPrunableElements(
17362
+ value,
17363
+ elements,
17364
+ path = [])
17365
+ {
17366
+ if (Array.isArray(value)) {
17367
+ for (const child of value) collectPrunableElements(child, elements, path);
17368
+ return;
17369
+ }
17370
+ if (FUNCTION_BOUNDARIES.has(value.type) || isStyleElement(value)) return;
17371
+
17372
+ if (value.type === "JSXElement" && isNativeRenderRoot(value)) {
17373
+ const metadata = value.metadata ??= {};
17374
+ metadata.path = path;
17375
+ elements.push(value);
17376
+ }
17377
+
17378
+ const childPath = [...path, value];
17379
+ for (const child of structuralChildren(value)) {
17380
+ collectPrunableElements(child, elements, childPath);
17381
+ }
17382
+ }
17383
+
17384
+ function annotateRuntimeValue(value, hash, core) {
17385
+ if (isStyleElement(value)) return null;
17386
+ if (FUNCTION_BOUNDARIES.has(value.type)) return value;
17387
+ if (value.type === "JSXElement") {
17388
+ return core.annotateWithHash(value, hash, "class", false);
17389
+ }
17390
+ if (value.type === "JSXFragment") {
17391
+ value.children = annotateRuntimeList(
17392
+ value.children ?? [],
17393
+ hash,
17394
+ core
17395
+ );
17396
+ return value;
17397
+ }
17398
+
17399
+ mutateStructuralChildren(value, (child) => annotateRuntimeValue(child, hash, core));
17400
+ return value;
17401
+ }
17402
+
17403
+ function annotateRuntimeList(values, hash, core) {
17404
+ return values.
17405
+ map((value) => annotateRuntimeValue(value, hash, core)).
17406
+ filter((value) => value !== null);
17407
+ }
17408
+
17409
+ function mutateStructuralChildren(node, transform) {
17410
+ const mapList = (values) =>
17411
+ (values ?? []).map(transform).filter((value) => value !== null);
17412
+ const mapSlot = (key) => {
17413
+ const value = node[key];
17414
+ if (isNode(value)) node[key] = transform(value);
17415
+ };
17416
+
17417
+ switch (node.type) {
17418
+ case "JSXElement":
17419
+ case "JSXFragment":
17420
+ node.children = mapList(node.children);
17421
+ break;
17422
+ case "JSXCodeBlock":
17423
+ node.body = mapList(node.body);
17424
+ mapSlot("render");
17425
+ break;
17426
+ case "BlockStatement":
17427
+ node.body = mapList(node.body);
17428
+ break;
17429
+ case "JSXIfExpression":
17430
+ case "IfStatement":
17431
+ mapSlot("consequent");
17432
+ mapSlot("alternate");
17433
+ break;
17434
+ case "JSXForExpression":
17435
+ mapSlot("body");
17436
+ mapSlot("empty");
17437
+ break;
17438
+ case "JSXSwitchExpression":
17439
+ case "SwitchStatement":
17440
+ for (const switchCase of node.cases ?? []) {
17441
+ switchCase.consequent = mapList(switchCase.consequent);
17442
+ }
17443
+ break;
17444
+ case "JSXTryExpression":
17445
+ case "TryStatement":
17446
+ mapSlot("block");
17447
+ mapSlot("pending");
17448
+ mapSlot("handler");
17449
+ mapSlot("finalizer");
17450
+ break;
17451
+ case "CatchClause":
17452
+ mapSlot("body");
17453
+ break;
17454
+ }
17455
+ }
17456
+
17457
+ function cleanRuntimeStyles(node) {
17458
+ if (FUNCTION_BOUNDARIES.has(node.type)) return;
17459
+ mutateStructuralChildren(node, (child) => {
17460
+ if (isStyleElement(child)) return null;
17461
+ cleanRuntimeStyles(child);
17462
+ return child;
17463
+ });
17464
+ }
17465
+
17466
+ function withLoc(node, source) {
17467
+ if (source.start !== undefined) node.start = source.start;
17468
+ if (source.end !== undefined) node.end = source.end;
17469
+ if (source.loc !== undefined) node.loc = source.loc;
17470
+ return node;
17471
+ }
17472
+
17473
+ function wrapWithSetup(expression, statements) {
17474
+ const body = withLoc(
17475
+ {
17476
+ type: "BlockStatement",
17477
+ body: [...statements, withLoc({ type: "ReturnStatement", argument: expression }, expression)]
17478
+ },
17479
+ expression
17480
+ );
17481
+ const fn = withLoc(
17482
+ {
17483
+ type: "ArrowFunctionExpression",
17484
+ id: null,
17485
+ params: [],
17486
+ body,
17487
+ expression: false,
17488
+ async: false,
17489
+ generator: false
17490
+ },
17491
+ expression
17492
+ );
17493
+ return withLoc(
17494
+ { type: "CallExpression", callee: fn, arguments: [], optional: false },
17495
+ expression
17496
+ );
17497
+ }
17498
+
17499
+ function collectIdentifierNames(node, names) {
17500
+ if (node.type === "Identifier" && typeof node.name === "string") names.add(node.name);
17501
+ for (const key of Object.keys(node)) {
17502
+ if (SKIP_KEYS.has(key)) continue;
17503
+ const value = node[key];
17504
+ if (Array.isArray(value)) {
17505
+ for (const child of value) if (isNode(child)) collectIdentifierNames(child, names);
17506
+ } else if (isNode(value)) {
17507
+ collectIdentifierNames(value, names);
17508
+ }
17509
+ }
17510
+ }
17511
+
17512
+ function createTempIdentifierFactory(program) {
17513
+ const names = new Set();
17514
+ collectIdentifierNames(program, names);
17515
+ let index = 0;
17516
+ return () => {
17517
+ let name;
17518
+ do {
17519
+ name = `_tsrx_style_ref_${++index}`;
17520
+ } while (names.has(name));
17521
+ names.add(name);
17522
+ return { type: "Identifier", name };
17523
+ };
17524
+ }
17525
+
17526
+ function createEmptyStyleElement(node) {
17527
+ const metadata = node.metadata ?? {};
17528
+ const cloneElementPart = (part) => {
17529
+ if (!isNode(part)) return part;
17530
+ return {
17531
+ ...part,
17532
+ metadata: {
17533
+ path: [...(metadata.path ?? [])]
17534
+ }
17535
+ };
17536
+ };
17537
+ return {
17538
+ ...node,
17539
+ type: "JSXElement",
17540
+ openingElement: cloneElementPart(node.openingElement),
17541
+ closingElement: cloneElementPart(node.closingElement),
17542
+ children: []
17543
+ };
17544
+ }
17545
+
17546
+ function prepareRuntimeStyle(
17547
+ owner,
17548
+ style,
17549
+ core,
17550
+ createTempIdentifier)
17551
+ {
17552
+ const stylesheet = core.getStyleElementStylesheet(style);
17553
+ if (!stylesheet) {
17554
+ throw new SyntaxError("A TSRX <style> element is missing its parsed stylesheet");
17555
+ }
17556
+
17557
+ core.analyzeCss(stylesheet);
17558
+ const metadata = owner.metadata ??= {};
17559
+ const styleClasses = new Map();
17560
+ const topScopedClasses = new Map();
17561
+
17562
+ const elements = [];
17563
+ collectPrunableElements(owner.children ?? [], elements);
17564
+ for (const element of elements) {
17565
+ core.pruneCss(stylesheet, element, styleClasses, topScopedClasses, stylesheet.hash);
17566
+ }
17567
+
17568
+ const refs = core.collectStyleRefAttributes(owner);
17569
+ if (refs.length > 0) {
17570
+ for (const [name, classInfo] of topScopedClasses) {
17571
+ styleClasses.set(
17572
+ name,
17573
+ classInfo?.selector ?? classInfo
17574
+ );
17575
+ }
17576
+ for (const element of elements) {
17577
+ core.pruneCss(stylesheet, element, styleClasses, topScopedClasses, stylesheet.hash);
17578
+ }
17579
+ }
17580
+ if (topScopedClasses.size > 0) metadata.topScopedClasses = topScopedClasses;
17581
+
17582
+ const setup =
17583
+ refs.length === 0 ?
17584
+ [] :
17585
+ core.createStyleRefSetupStatements(refs, core.createStyleClassMap(owner, stylesheet), {
17586
+ allowMutableRefTarget: true,
17587
+ createTempIdentifier
17588
+ });
17589
+
17590
+ mutateStructuralChildren(owner, (child) => annotateRuntimeValue(child, stylesheet.hash, core));
17591
+ cleanRuntimeStyles(owner);
17592
+ return { owner, stylesheet, setup };
17593
+ }
17594
+
17595
+ function prepareStyleOwner(
17596
+ owner,
17597
+ core,
17598
+ createTempIdentifier)
17599
+ {
17600
+ const styles = [];
17601
+ collectRuntimeStyleElements(owner.children ?? [], styles);
17602
+ if (styles.length > 1) {
17603
+ throw new SyntaxError("TSRX fragments can only have one style tag");
17604
+ }
17605
+ return styles.length === 1 ?
17606
+ prepareRuntimeStyle(owner, styles[0], core, createTempIdentifier) :
17607
+ null;
17608
+ }
17609
+
17610
+ function processTsrxStyles(program, core) {
17611
+ const stylesheets = [];
17612
+ const createTempIdentifier = createTempIdentifierFactory(program);
17613
+
17614
+ const visit = (node, path) => {
17615
+ if (isStyleElement(node)) {
17616
+ if (!isStyleExpressionPosition(path)) return createEmptyStyleElement(node);
17617
+ const stylesheet = core.getStyleElementStylesheet(node);
17618
+ if (!stylesheet) {
17619
+ throw new SyntaxError("A TSRX <style> expression is missing its parsed stylesheet");
17620
+ }
17621
+ core.analyzeCss(stylesheet);
17622
+ stylesheets.push(core.prepareStylesheetForRender(stylesheet, true));
17623
+ return core.createStyleClassMapFromStylesheet(stylesheet);
17624
+ }
17625
+
17626
+ if (node.type === "JSXCodeBlock" && isNode(node.render) && isNativeRenderRoot(node.render)) {
17627
+ // Core gives a code block's native element/fragment render one style
17628
+ // scope. A native element elsewhere is deliberately not an owner.
17629
+ const prepared = prepareStyleOwner(node.render, core, createTempIdentifier);
17630
+ if (prepared) {
17631
+ stylesheets.push(prepared.stylesheet);
17632
+ node.render = prepared.owner;
17633
+ node.body = [...(node.body ?? []), ...prepared.setup];
17634
+ }
17635
+ } else if (node.type === "JSXFragment" && isNativeRenderRoot(node)) {
17636
+ // Native fragments are owners in every expression/child position.
17637
+ const prepared = prepareStyleOwner(node, core, createTempIdentifier);
17638
+ if (prepared) {
17639
+ stylesheets.push(prepared.stylesheet);
17640
+ node = prepared.setup.length ?
17641
+ wrapWithSetup(prepared.owner, prepared.setup) :
17642
+ prepared.owner;
17643
+ }
17644
+ }
17645
+
17646
+ for (const key of Object.keys(node)) {
17647
+ if (SKIP_KEYS.has(key)) continue;
17648
+ const value = node[key];
17649
+ if (Array.isArray(value)) {
17650
+ node[key] = value.map((child) => isNode(child) ? visit(child, [...path, node]) : child);
17651
+ } else if (isNode(value)) {
17652
+ node[key] = visit(value, [...path, node]);
17653
+ }
17654
+ }
17655
+ return node;
17656
+ };
17657
+
17658
+ visit(program, []);
17659
+ return core.renderCssResult(stylesheets);
17660
+ }
17661
+
17662
+ /**
17663
+ * TSRX syntax frontend entry point.
17664
+ *
17665
+ * Routes `.tsrx` sources (or any source when `syntax: "tsrx"`) through
17666
+ * `@tsrx/core`'s parser + semantic analysis, processes scoped styles with
17667
+ * core's CSS helpers, desugars every TSRX construct to Solid builtIn JSX,
17668
+ * applies Solid's local deferred-pattern transform for generated control-flow
17669
+ * callbacks, and converts the result to a Babel `File` for the unchanged JSX
17670
+ * pipeline. Authored lazy destructuring is rejected for the Solid target.
17671
+ *
17672
+ * `@tsrx/core` is an optional peer dependency loaded lazily on first TSRX
17673
+ * routing, so plain JSX users never pay for it.
17674
+ */
17675
+
17676
+
17677
+
17678
+ // The plugin ships as CJS; `require` of the ESM-only `@tsrx/core` is
17679
+ // supported natively on Node >= 22.12. No @types/node in this package.
17680
+
17681
+
17682
+
17683
+
17684
+
17685
+
17686
+
17687
+
17688
+
17689
+
17690
+
17691
+ let core;
17692
+
17693
+ function loadTsrxCore() {
17694
+ if (core) return core;
17695
+ if (typeof require !== "function") {
17696
+ throw new Error(
17697
+ "@solidjs/babel-plugin: TSRX support requires a CommonJS environment with `require` available."
17698
+ );
17699
+ }
17700
+ try {
17701
+ core = require("@tsrx/core");
17702
+ } catch (error) {
17703
+ const err = error;
17704
+ if (err.code === "MODULE_NOT_FOUND") {
17705
+ throw new Error(
17706
+ "@solidjs/babel-plugin: compiling .tsrx sources requires the optional peer dependency `@tsrx/core`. Install it with your package manager (e.g. `pnpm add -D @tsrx/core`)."
17707
+ );
17708
+ }
17709
+ if (err.code === "ERR_REQUIRE_ESM" || err.code === "ERR_REQUIRE_ASYNC_MODULE") {
17710
+ throw new Error(
17711
+ "@solidjs/babel-plugin: loading `@tsrx/core` synchronously requires Node.js >= 22.12 (require(esm) support)."
17712
+ );
17713
+ }
17714
+ throw error;
17715
+ }
17716
+ return core;
17717
+ }
17718
+
17719
+
17720
+
17721
+ /** Whether the given file should be parsed as TSRX under the configured
17722
+ * `syntax` option. */
17723
+ function isTsrxSource(syntax, filename) {
17724
+ const mode = syntax ?? "auto";
17725
+ if (mode === "tsrx") return true;
17726
+ if (mode === "jsx") return false;
17727
+ return typeof filename === "string" && filename.endsWith(".tsrx");
17728
+ }
17729
+
17730
+ /** Parse TSRX source text into a Babel `File` with all TSRX constructs
17731
+ * lowered to Solid builtIn JSX. */
17732
+ function parseTsrx(code, filename) {
17733
+ const tsrx = loadTsrxCore();
17734
+ const program = tsrx.parseModule(code, filename ?? "module.tsrx");
17735
+ rejectAuthoredLazyDestructuring(program);
17736
+ // Throws structured diagnostics (invalid returns, misplaced directives, …).
17737
+ tsrx.analyzeTsrx(program, filename ?? null);
17738
+ const styleResult = processTsrxStyles(program, tsrx);
17739
+
17740
+ // Desugar before the lazy transform: the lazy engine collects block-level
17741
+ // `let &[…]`/`const &{…}` bindings in its BlockStatement/Program handlers,
17742
+ // which only fire once `@{}` containers have become real blocks. Lazy
17743
+ // patterns themselves pass through the desugarer untouched.
17744
+ desugarProgram(program);
17745
+
17746
+ const transformed = applyLazyTransforms(program);
17747
+ // Keep this compatibility repair in place for trees produced by older
17748
+ // desugaring paths. The local engine itself never rewrites intrinsic names.
17749
+ restoreIntrinsicJsxNames(transformed);
17750
+
17751
+ const file = toBabelFile(transformed);
17752
+ // Babel's default AST clone preserves enumerable string keys. Program.enter
17753
+ // lifts this temporary payload into transform metadata and removes it from
17754
+ // the AST, avoiding mutable plugin-factory state (and concurrent-run races).
17755
+ file.tsrxStyle = styleResult;
17756
+ return file;
17757
+ }
17758
+
17759
+ var index = (
17760
+ _api,
17761
+ options = {}) =>
17762
+
17763
+
17764
+
17765
+
17766
+
17767
+ {
17768
+ return {
17769
+ name: "@solidjs/babel-plugin",
17770
+ inherits: SyntaxJSX.default,
17771
+ parserOverride(code, parserOpts, parse) {
17772
+ if (isTsrxSource(options.syntax, parserOpts?.sourceFileName)) {
17773
+ return parseTsrx(code, parserOpts?.sourceFileName);
17774
+ }
17775
+ return parse(code, parserOpts);
17776
+ },
14638
17777
  visitor: {
14639
17778
  JSXElement: transformJSX,
14640
17779
  JSXFragment: transformJSX,