@solidjs/babel-plugin 2.0.0-rc.7 → 2.0.0-rc.9

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
@@ -2172,7 +2172,7 @@ results)
2172
2172
  t$1.expressionStatement(
2173
2173
  t$1.assignmentExpression(
2174
2174
  "=",
2175
- t$1.memberExpression(elem, t$1.identifier(`$$${ev}Data`)),
2175
+ t$1.memberExpression(elem, t$1.identifier(`_$$${ev}Data`)),
2176
2176
  handler.elements[1]
2177
2177
  )
2178
2178
  )
@@ -2183,7 +2183,7 @@ results)
2183
2183
  t$1.expressionStatement(
2184
2184
  t$1.assignmentExpression(
2185
2185
  "=",
2186
- t$1.memberExpression(elem, t$1.identifier(`$$${ev}`)),
2186
+ t$1.memberExpression(elem, t$1.identifier(`_$$${ev}`)),
2187
2187
  handler
2188
2188
  )
2189
2189
  )
@@ -2193,7 +2193,7 @@ results)
2193
2193
  t$1.expressionStatement(
2194
2194
  t$1.assignmentExpression(
2195
2195
  "=",
2196
- t$1.memberExpression(elem, t$1.identifier(`$$${ev}`)),
2196
+ t$1.memberExpression(elem, t$1.identifier(`_$$${ev}`)),
2197
2197
  handler
2198
2198
  )
2199
2199
  )
@@ -2781,7 +2781,7 @@ attributes,
2781
2781
  id,
2782
2782
  [],
2783
2783
  t$1.blockStatement([t$1.returnStatement(expression)]),
2784
- !t$1.isValidIdentifier(normalized)
2784
+ false // never computed; see shared/component.ts (#3511)
2785
2785
  )
2786
2786
  );
2787
2787
  } else {
@@ -2804,11 +2804,12 @@ attributes,
2804
2804
  // A lone spread — reactive included — passes straight through: spread()
2805
2805
  // resolves a function source inside its own tracking scopes, and merging
2806
2806
  // one source would mint a memo that consumes a hydration id the SSR fast
2807
- // path never allocates (#3105).
2808
- const props =
2809
- spreadArgs.length === 1 ?
2810
- spreadArgs[0] :
2811
- t$1.callExpression(registerImportMethod(path, "mergeProps"), spreadArgs);
2807
+ // path never allocates (#3105). Several sources go as an ARRAY, not a
2808
+ // mergeProps() call: spread() reads the sources directly (later wins per
2809
+ // key, only the winner read) with no merge proxy to build and walk, and a
2810
+ // reactive source is called inside the tracking scope with no memo — so
2811
+ // no hydration id here either, matching the ssrElement array form.
2812
+ const props = spreadArgs.length === 1 ? spreadArgs[0] : t$1.arrayExpression(spreadArgs);
2812
2813
 
2813
2814
  return [
2814
2815
  filteredAttributes,
@@ -2952,6 +2953,32 @@ function registerTemplate(path, results) {
2952
2953
  results.decl = t__namespace.variableDeclaration("var", results.declarations);
2953
2954
  }
2954
2955
 
2956
+ /** A non-inline object-valued `style` / `class` binding is read in the TRACKED
2957
+ * half of its effect through `readShallow()`: `style()`/`className()` enumerate
2958
+ * their object in the untracked commit phase, so a proxy value (a store
2959
+ * sub-object, merged props) would be identity-reactive only. Skipped when the
2960
+ * expression is provably a string or a fresh literal (`readShallow` would pass
2961
+ * those through anyway; the call is what's saved). */
2962
+ function wrapReadShallow(path, key, value) {
2963
+ if (key !== "class" && key !== "style") return value;
2964
+ if (
2965
+ t__namespace.isStringLiteral(value) ||
2966
+ t__namespace.isTemplateLiteral(value) ||
2967
+ t__namespace.isBinaryExpression(value) ||
2968
+ t__namespace.isObjectExpression(value) ||
2969
+ // a class array of literals cannot hold a proxy either
2970
+ t__namespace.isArrayExpression(value) &&
2971
+ value.elements.every(
2972
+ (e) => t__namespace.isStringLiteral(e) || t__namespace.isTemplateLiteral(e) || t__namespace.isObjectExpression(e)
2973
+ ))
2974
+
2975
+ return value;
2976
+ return t__namespace.callExpression(
2977
+ registerImportMethod(path, "readShallow", getRendererConfig(path, "dom").moduleName),
2978
+ [value]
2979
+ );
2980
+ }
2981
+
2955
2982
  function wrapDynamics$1(path, dynamics) {
2956
2983
  if (!dynamics.length) return;
2957
2984
  const config = getConfig(path);
@@ -2975,7 +3002,7 @@ function wrapDynamics$1(path, dynamics) {
2975
3002
  const newValue = t__namespace.identifier("_v$");
2976
3003
  return t__namespace.expressionStatement(
2977
3004
  t__namespace.callExpression(effectWrapperId, [
2978
- wrapForEffect(dynamics[0].value),
3005
+ wrapForEffect(wrapReadShallow(path, dynamics[0].key, dynamics[0].value)),
2979
3006
  t__namespace.arrowFunctionExpression(
2980
3007
  prevValue ? [newValue, prevValue] : [newValue],
2981
3008
  t__namespace.blockStatement([
@@ -3010,7 +3037,7 @@ function wrapDynamics$1(path, dynamics) {
3010
3037
  }
3011
3038
 
3012
3039
  properties.push(propIdent);
3013
- values.push(t__namespace.objectProperty(propIdent, value));
3040
+ values.push(t__namespace.objectProperty(propIdent, wrapReadShallow(path, key, value)));
3014
3041
 
3015
3042
  if (key === "class" || key === "style" || isStatefulDOMProperty(tagName, key)) {
3016
3043
  statements.push(
@@ -3465,9 +3492,8 @@ escapeLiterals)
3465
3492
  expression.wontEscape = true;
3466
3493
  return expression;
3467
3494
  } else if (t.isJSXFragment(expression) && fragmentWillSelfEscape(expression)) {
3468
- // The fragment will later be transformed into a runtime value the
3469
- // `escape` helper passes through unchanged — either a memoized
3470
- // accessor function or an `_$ssr(...)` SSRNode object (see
3495
+ // The fragment will later be transformed into an `_$ssr(...)` SSRNode
3496
+ // object the `escape` helper passes through unchanged (see
3471
3497
  // `fragmentWillSelfEscape`). Wrapping it in another `_$escape(...)`
3472
3498
  // here would be a guaranteed no-op, so leave the fragment in place
3473
3499
  // and let the later traversal emit the inner form directly.
@@ -3495,23 +3521,16 @@ function escapeTemplateQuasis(expression, attr) {
3495
3521
  // Predicts whether a JSXFragment AST will compile to a single runtime
3496
3522
  // value for which the outer `_$escape(...)` wrap is a no-op. Must stay
3497
3523
  // conservative: any shape this returns `true` for must, when later
3498
- // transformed, produce a self-escaping (or escape-immune) runtime value.
3499
- // When in doubt, return false so the outer `_$escape` wrap is kept.
3524
+ // transformed, produce an escape-immune runtime value. When in doubt,
3525
+ // return false so the outer `_$escape` wrap is kept.
3526
+ //
3527
+ // The one recognized shape is `<><native /></>` — a single native
3528
+ // (non-component) JSXElement, whose `createTemplate` output is
3529
+ // `_$ssr(_tmpl$N, …)`: an SSRNode object `escape` passes through.
3500
3530
  //
3501
- // Recognized single-significant-child shapes:
3502
- // A. `<>{memberOrCall}</>` — a `JSXExpressionContainer` whose
3503
- // expression matches the top-level subset of
3504
- // `isDynamic({ checkMember: true })` (member access, call, tagged
3505
- // template, optional variants, `in` checks). `createTemplate`
3506
- // emits `_$memo(() => _$escape(expr))`; the memo returns a
3507
- // function accessor at runtime and `escape(fn)` is a pass-through.
3508
- // Nested-dynamic shapes (conditional/logical carrying dynamic
3509
- // sub-expressions) are excluded — confirming them needs the full
3510
- // `isDynamic` traversal and a missed optimization costs only one
3511
- // runtime no-op call.
3512
- // B. `<><native /></>` — a single native (non-component) JSXElement.
3513
- // `createTemplate` emits `_$ssr(_tmpl$N, …)`, which returns an
3514
- // SSRNode object; `escape(object)` is a pass-through.
3531
+ // A single expression child (`<>{x()}</>`) is NOT immune: it compiles to a
3532
+ // memo the runtime's `escape` defers into (a function's yield is content
3533
+ // like any other), so the hole must keep its wrap.
3515
3534
  function fragmentWillSelfEscape(fragment) {
3516
3535
  let only = null;
3517
3536
  for (const c of fragment.children) {
@@ -3521,25 +3540,10 @@ function fragmentWillSelfEscape(fragment) {
3521
3540
  }
3522
3541
  if (t__namespace.isJSXExpressionContainer(c) && t__namespace.isJSXEmptyExpression(c.expression))
3523
3542
  continue;
3524
- if (only !== null) return false;
3525
- if (t__namespace.isJSXElement(c) || t__namespace.isJSXExpressionContainer(c)) only = c;else
3526
- return false;
3527
- }
3528
- if (!only) return false;
3529
- if (t__namespace.isJSXExpressionContainer(only)) {
3530
- const expr = only.expression;
3531
- if (t__namespace.isJSXEmptyExpression(expr)) return false;
3532
- return (
3533
- t.isCallExpression(expr) ||
3534
- t.isOptionalCallExpression(expr) ||
3535
- t.isTaggedTemplateExpression(expr) ||
3536
- t.isMemberExpression(expr) ||
3537
- t.isOptionalMemberExpression(expr) ||
3538
- t__namespace.isBinaryExpression(expr) && expr.operator === "in");
3539
-
3543
+ if (only !== null || !t__namespace.isJSXElement(c)) return false;
3544
+ only = c;
3540
3545
  }
3541
- if (t__namespace.isJSXElement(only)) return !isComponent(getTagName(only));
3542
- return false;
3546
+ return only !== null && !isComponent(getTagName(only));
3543
3547
  }
3544
3548
 
3545
3549
  function normalizeAttributes(path) {
@@ -4050,7 +4054,6 @@ path,
4050
4054
  } else {
4051
4055
  props = [];
4052
4056
  let runningObject = [],
4053
- dynamicSpread = false,
4054
4057
  hasChildren = path.node.children.length > 0;
4055
4058
 
4056
4059
  attributes.forEach((attribute) => {
@@ -4060,10 +4063,16 @@ path,
4060
4063
  props.push(t.objectExpression(runningObject));
4061
4064
  runningObject = [];
4062
4065
  }
4066
+ // A dynamic spread defers behind a thunk: evaluated in argument
4067
+ // position it would run before `ssrElement` allocates the element's
4068
+ // own hydration id, while the client claims the element
4069
+ // (getNextElement) before applying the spread — shifting the
4070
+ // element's id by one and leaving it unclaimed. `ssrElement` calls
4071
+ // function sources after allocating the key, matching that order.
4063
4072
  props.push(
4064
4073
  isDynamic(attribute.get("argument"), {
4065
4074
  checkMember: true
4066
- }) && (dynamicSpread = true) ?
4075
+ }) ?
4067
4076
  inlineCallExpression(node.argument) :
4068
4077
  node.argument
4069
4078
  );
@@ -4092,7 +4101,7 @@ path,
4092
4101
  id,
4093
4102
  [],
4094
4103
  t.blockStatement([t.returnStatement(expression)]),
4095
- !t.isValidIdentifier(key)
4104
+ false // never computed; see shared/component.ts (#3511)
4096
4105
  )
4097
4106
  );
4098
4107
  } else runningObject.push(t.objectProperty(id, expression));
@@ -4102,21 +4111,13 @@ path,
4102
4111
 
4103
4112
  if (runningObject.length || !props.length) props.push(t.objectExpression(runningObject));
4104
4113
 
4105
- if (props.length > 1 || dynamicSpread) {
4106
- let merged = t.callExpression(
4107
- registerImportMethod(path, "mergeProps"),
4108
- props
4109
- );
4110
- // Defer the merge behind a thunk when hydratable: `mergeProps` with a
4111
- // function source creates a memo, which consumes a hydration child id.
4112
- // Evaluated in argument position it would run before `ssrElement`
4113
- // allocates the element's own id, while the client claims the element
4114
- // (getNextElement) before applying the spread — shifting the element's
4115
- // id by one and leaving it unclaimed. `ssrElement` resolves function
4116
- // props after allocating the hydration key, matching the client order.
4117
- if (hydratable) merged = t.arrowFunctionExpression([], merged);
4118
- props = [merged];
4119
- }
4114
+ // Several sources go as an ARRAY, not a mergeProps() call: ssrElement
4115
+ // serializes straight from the sources (later wins per key, only the
4116
+ // winner read) with no merged object to build and walk once, and a
4117
+ // function source is a plain thunk called after the key — no memo, so no
4118
+ // hydration id, matching the client spread() array form. A single
4119
+ // source, thunk included, passes through as the props argument itself.
4120
+ if (props.length > 1) props = [t.arrayExpression(props)];
4120
4121
  }
4121
4122
 
4122
4123
  const exprs = [
@@ -4139,31 +4140,6 @@ path,
4139
4140
  return { exprs, template: "", declarations: [], dynamics: [], spreadElement: true };
4140
4141
  }
4141
4142
 
4142
- // Wrap the *inner* value of a fragment-child accessor with `_$escape` so that
4143
- // hostile string values returned from reactive accessors cannot be
4144
- // concatenated raw into the SSR output. Element-child expressions already get
4145
- // this treatment via `escapeExpression` in `ssr/element.js`; fragment
4146
- // children reach SSR via a different code path and would otherwise skip the
4147
- // escape step.
4148
- //
4149
- // `expr` is the first entry of `result.exprs` produced by `transformNode`
4150
- // for a `JSXExpressionContainer`. It is either:
4151
- // - an arrow function `() => X` (default case)
4152
- // - a bare callee (`fnRef`, emitted when the expression is `fnRef()` with
4153
- // no args — see the JSXExpressionContainer branch in shared/transform.js)
4154
- // - the result of `transformCondition(..., inline=true)`, which also
4155
- // returns an arrow function
4156
- // For arrows with an expression body we rewrite in place; for anything else
4157
- // we conservatively wrap in a new arrow that calls and escapes.
4158
- function wrapFragmentChildWithEscape(path, expr) {
4159
- const escape = registerImportMethod(path, "escape", undefined);
4160
- if (t__namespace.isArrowFunctionExpression(expr) && !t__namespace.isBlockStatement(expr.body)) {
4161
- expr.body = t__namespace.callExpression(escape, [expr.body]);
4162
- return expr;
4163
- }
4164
- return t__namespace.arrowFunctionExpression([], t__namespace.callExpression(escape, [t__namespace.callExpression(expr, [])]));
4165
- }
4166
-
4167
4143
  function createTemplate$1(
4168
4144
  path,
4169
4145
  result,
@@ -4171,19 +4147,16 @@ wrap)
4171
4147
  {
4172
4148
  if (!result.template) {
4173
4149
  // `wrap` is true for fragment children and for mixed component children.
4174
- // A sole component child (`wrap === false`) is a value passed to the
4175
- // callee — do not `_$escape` it here; the callee's insert/SSR sites
4176
- // escape when interpolating into HTML. Escaping both layers double-escapes.
4150
+ // Both are VALUES — they flow to whatever hole eventually inserts them,
4151
+ // and that hole's `_$escape` covers everything reachable from the value:
4152
+ // strings, array items, and what a function (this memo) yields when the
4153
+ // resolver calls it. Escaping here as well double-escapes through
4154
+ // `<Comp>{props.children}</Comp>`. The memo exists for hydration-id
4155
+ // alignment with the client, not for escaping.
4177
4156
  if (wrap && result.dynamic && getConfig(path).memoWrapper) {
4178
- // wontEscape is set on JSXElement children whose compiled form is
4179
- // already a safe SSR node (e.g. `_$ssr(...)` call). Wrapping those in
4180
- // escape would be a no-op at runtime but obscures intent — skip it.
4181
- const inner = result.wontEscape ?
4182
- result.exprs[0] :
4183
- wrapFragmentChildWithEscape(path, result.exprs[0]);
4184
4157
  return t__namespace.callExpression(
4185
4158
  registerImportMethod(path, getConfig(path).memoWrapper, undefined),
4186
- [inner]
4159
+ [result.exprs[0]]
4187
4160
  );
4188
4161
  }
4189
4162
  return result.exprs[0];
@@ -4694,7 +4667,6 @@ attributes,
4694
4667
  const filteredAttributes = [];
4695
4668
  const spreadArgs = [];
4696
4669
  let runningObject = [];
4697
- let dynamicSpread = false;
4698
4670
  let firstSpread = false;
4699
4671
  attributes.forEach((attribute) => {
4700
4672
  const node = attribute.node;
@@ -4712,7 +4684,7 @@ attributes,
4712
4684
  spreadArgs.push(
4713
4685
  isDynamic(attribute.get("argument"), {
4714
4686
  checkMember: true
4715
- }) && (dynamicSpread = true) ?
4687
+ }) ?
4716
4688
  t__namespace.isCallExpression(node.argument) &&
4717
4689
  !node.argument.arguments.length &&
4718
4690
  !t__namespace.isCallExpression(node.argument.callee) &&
@@ -4750,7 +4722,7 @@ attributes,
4750
4722
  id,
4751
4723
  [],
4752
4724
  t__namespace.blockStatement([t__namespace.returnStatement(expr.body)]),
4753
- !t__namespace.isValidIdentifier(key)
4725
+ false // never computed; see shared/component.ts (#3511)
4754
4726
  )
4755
4727
  );
4756
4728
  } else {
@@ -4770,10 +4742,13 @@ attributes,
4770
4742
  spreadArgs.push(t__namespace.objectExpression(runningObject));
4771
4743
  }
4772
4744
 
4773
- const props =
4774
- spreadArgs.length === 1 && !dynamicSpread ?
4775
- spreadArgs[0] :
4776
- t__namespace.callExpression(registerImportMethod(path, "mergeProps"), spreadArgs);
4745
+ // A lone spread — reactive included — passes straight through: the
4746
+ // renderer's spread() resolves a function source inside its own tracking
4747
+ // scopes. Several sources go as an ARRAY, not a mergeProps() call: spread()
4748
+ // reads the sources directly (later wins per key, only the winner read)
4749
+ // with no merge proxy to build and walk, and a reactive source is called
4750
+ // inline with no memo. Same contract as the dom generate.
4751
+ const props = spreadArgs.length === 1 ? spreadArgs[0] : t__namespace.arrayExpression(spreadArgs);
4777
4752
 
4778
4753
  return [
4779
4754
  filteredAttributes,
@@ -4940,11 +4915,24 @@ node)
4940
4915
  return t__namespace.stringLiteral(`${node.namespace.name}:${node.name.name}`);
4941
4916
  }
4942
4917
 
4918
+ /**
4919
+ * The tag as written in source (`Home`, `Ui.Button`, `this.Row`) — the label
4920
+ * `componentNames` emits. Read before `convertComponentIdentifier` since that
4921
+ * retypes the JSX identifier nodes in place.
4922
+ */
4923
+ function jsxTagName(node) {
4924
+ if (t__namespace.isJSXIdentifier(node)) return thisTagIdentifiers.has(node) ? "this" : node.name;
4925
+ if (t__namespace.isJSXMemberExpression(node))
4926
+ return `${jsxTagName(node.object)}.${jsxTagName(node.property)}`;
4927
+ return `${node.namespace.name}:${node.name.name}`;
4928
+ }
4929
+
4943
4930
  function transformComponent(
4944
4931
  path)
4945
4932
  {
4946
4933
  let exprs = [],
4947
4934
  config = getConfig(path),
4935
+ tagName = jsxTagName(path.node.openingElement.name),
4948
4936
  tagId = convertComponentIdentifier(path.node.openingElement.name),
4949
4937
  props = [],
4950
4938
  runningObject = [],
@@ -5152,13 +5140,19 @@ path)
5152
5140
  {
5153
5141
  const expr = transformCondition(attribute.get("value").get("expression"), true);
5154
5142
 
5143
+ // Getter keys are never computed: `id` is an identifier or a
5144
+ // string literal (`get "aria-label"()`), the same property as
5145
+ // `get ["aria-label"]()` but on V8's object-literal boilerplate
5146
+ // path — a computed key drops the whole literal to per-property
5147
+ // runtime definition (#3511). Same at every getter site below
5148
+ // and in dom/ssr/universal element.ts.
5155
5149
  runningObject.push(
5156
5150
  t__namespace.objectMethod(
5157
5151
  "get",
5158
5152
  id,
5159
5153
  [],
5160
5154
  t__namespace.blockStatement([t__namespace.returnStatement(expr.body)]),
5161
- !t__namespace.isValidIdentifier(key)
5155
+ false
5162
5156
  )
5163
5157
  );
5164
5158
  } else if (
@@ -5171,7 +5165,7 @@ path)
5171
5165
  callee.body :
5172
5166
  t__namespace.blockStatement([t__namespace.returnStatement(callee.body)]);
5173
5167
 
5174
- runningObject.push(t__namespace.objectMethod("get", id, [], body, !t__namespace.isValidIdentifier(key)));
5168
+ runningObject.push(t__namespace.objectMethod("get", id, [], body, false));
5175
5169
  } else {
5176
5170
  runningObject.push(
5177
5171
  t__namespace.objectMethod(
@@ -5179,7 +5173,7 @@ path)
5179
5173
  id,
5180
5174
  [],
5181
5175
  t__namespace.blockStatement([t__namespace.returnStatement(value.expression)]),
5182
- !t__namespace.isValidIdentifier(key)
5176
+ false
5183
5177
  )
5184
5178
  );
5185
5179
  }
@@ -5213,13 +5207,29 @@ path)
5213
5207
  props = [t__namespace.callExpression(registerImportMethod(path, "mergeProps"), props)];
5214
5208
  }
5215
5209
  const componentArgs = [tagId, props[0]];
5216
- // SSR's `createComponent` is literally `Comp(props || {})`. Since the
5210
+ // `componentNames` carries the source tag name into the call so the
5211
+ // dev/observe runtimes can label the owner after minification renames the
5212
+ // function — on the client (`createComponent` in solid-js's client entry)
5213
+ // and on the server (its server entry's, which runs the body under a
5214
+ // transparent `<Name>` owner in observe/dev so a server finding's
5215
+ // `ownerPath` reads like the client's). Not for the universal renderer,
5216
+ // whose `createComponent` is user code with a two-argument contract, nor
5217
+ // the dynamic renderer's subtrees.
5218
+ const labelled =
5219
+ config.componentNames && (config.generate === "dom" || config.generate === "ssr");
5220
+ if (labelled) {
5221
+ componentArgs.push(t__namespace.stringLiteral(tagName));
5222
+ }
5223
+ // SSR's prod `createComponent` is literally `Comp(props || {})`. Since the
5217
5224
  // compiler always emits a real `props[0]` object expression above (see the
5218
5225
  // `props.push(t.objectExpression(runningObject))` line), the `|| {}` fallback
5219
5226
  // never fires in compiled output. Inline to a direct `Comp(props)` call to
5220
5227
  // drop one function-call frame per component invocation. (DOM/dev modes
5221
5228
  // keep the wrapper since it does real work — `untrack`, dev metadata.)
5222
- if (getConfig(path).generate === "ssr") {
5229
+ // With `componentNames` the wrapper IS the work — the label has nowhere
5230
+ // else to go — so SSR output keeps the call; the vite-plugin turns the
5231
+ // option on for dev and observe builds only, so prod output stays inlined.
5232
+ if (config.generate === "ssr" && !labelled) {
5223
5233
  exprs.push(t__namespace.callExpression(tagId, [props[0]]));
5224
5234
  } else {
5225
5235
  exprs.push(t__namespace.callExpression(registerImportMethod(path, "createComponent"), componentArgs));
@@ -5411,6 +5421,13 @@ function getTargetFunctionParent(path, parent) {
5411
5421
  return current;
5412
5422
  }
5413
5423
 
5424
+ /**
5425
+ * JSX tag identifiers `transformThis` rewrote from `this` to the `_self$`
5426
+ * capture, so `componentNames` can label `<this.Row />` by its source text
5427
+ * rather than the generated uid.
5428
+ */
5429
+ const thisTagIdentifiers = new WeakSet();
5430
+
5414
5431
  function transformThis(path) {
5415
5432
  const parent = path.scope.getFunctionParent();
5416
5433
  let thisId, inserted;
@@ -5431,7 +5448,9 @@ function transformThis(path) {
5431
5448
  const current = getTargetFunctionParent(path, parent);
5432
5449
  if (current === parent) {
5433
5450
  thisId || (thisId = path.scope.generateUidIdentifier("self$"));
5434
- source.replaceWith(t__namespace.jsxIdentifier(thisId.name));
5451
+ const selfTag = t__namespace.jsxIdentifier(thisId.name);
5452
+ thisTagIdentifiers.add(selfTag);
5453
+ source.replaceWith(selfTag);
5435
5454
 
5436
5455
  if (path.node.closingElement) {
5437
5456
  path.node.closingElement.name = path.node.openingElement.name;
@@ -14264,6 +14283,7 @@ const config = {
14264
14283
  generate: "dom",
14265
14284
  hydratable: false,
14266
14285
  dev: false,
14286
+ componentNames: false,
14267
14287
  delegateEvents: true,
14268
14288
  delegatedEvents: [],
14269
14289
  builtIns: [
@@ -14324,9 +14344,8 @@ var preprocess = (path, state) => {
14324
14344
  /**
14325
14345
  * TSRX → Solid JSX desugaring.
14326
14346
  *
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
14347
+ * Walks the ESTree AST produced by `@tsrx/core` and lowers every TSRX
14348
+ * construct to Solid 2.0 builtIn component JSX, in place. The result is a plain ESTree TSX program that
14330
14349
  * `estree-to-babel` converts for the existing JSX pipeline. BuiltIns are
14331
14350
  * referenced as bare identifiers (`Show`, `For`, …) so the plugin's normal
14332
14351
  * `builtIns` auto-import machinery resolves them against `moduleName`.
@@ -14339,14 +14358,17 @@ var preprocess = (path, state) => {
14339
14358
  * becomes `fallback`.
14340
14359
  * - `@for (const x of expr; index i; key k)` — `For`; `key` present emits
14341
14360
  * `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.
14361
+ * `@empty` becomes `fallback`. The bindings pass through as authored:
14362
+ * `For` hands the callback an item accessor in custom-key and non-keyed
14363
+ * modes (and an index accessor only with a custom key), and the author
14364
+ * reads it as `x()` exactly as in JSX. Destructuring `x` where it is an
14365
+ * accessor is rejected (#3474).
14345
14366
  * - `@switch` — `Switch` with one `Match when={disc === test}` per `@case`;
14346
14367
  * `@default` becomes `fallback`.
14347
14368
  * - `@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.
14369
+ * …}><Loading fallback={pending}>{content}</Loading></Errored>`; `Errored`
14370
+ * passes an `ErrorAccessor`, which the author reads as `e()`. Destructuring
14371
+ * `e` is rejected.
14350
14372
  * - `<{expr}>` — `<Dynamic component={expr} …>` (deliberate adaptation from
14351
14373
  * `@tsrx/solid`'s hoisted `dynamic()` factory; semantically equivalent).
14352
14374
  *
@@ -14400,7 +14422,7 @@ const VALID_JSX_CHILD_TYPES = new Set([
14400
14422
  "JSXSpreadChild"]
14401
14423
  );
14402
14424
 
14403
- const FUNCTION_TYPES$1 = new Set([
14425
+ const FUNCTION_TYPES = new Set([
14404
14426
  "FunctionDeclaration",
14405
14427
  "FunctionExpression",
14406
14428
  "ArrowFunctionExpression"]
@@ -14419,11 +14441,21 @@ function fail$2(message, node) {
14419
14441
  throw new SyntaxError(start ? `${message} (${start.line}:${start.column})` : message);
14420
14442
  }
14421
14443
 
14444
+ /** Diagnostic for a destructured `@for` item where Solid passes an accessor.
14445
+ * Shared text with the Oxc frontend (`tsrx/semantic.rs`). */
14446
+ const FOR_ACCESSOR_DESTRUCTURING_MESSAGE =
14447
+ "A destructured `@for` item binding is not supported together with `index` or `key`: Solid passes the item as an accessor. Bind a name and read it as a call (`item().name`)";
14448
+
14449
+ /** Diagnostic for a destructured `@catch` error binding. Shared text with the
14450
+ * Oxc frontend (`tsrx/semantic.rs`). */
14451
+ const CATCH_ACCESSOR_DESTRUCTURING_MESSAGE =
14452
+ "A destructured `@catch` error binding is not supported: Solid passes the error as an accessor. Bind a name and read it as a call (`err().message`)";
14453
+
14422
14454
  // ---------------------------------------------------------------------------
14423
14455
  // ESTree builders (converted to Babel shapes later by estree-to-babel)
14424
14456
  // ---------------------------------------------------------------------------
14425
14457
 
14426
- function withLoc$2(node, src) {
14458
+ function withLoc$1(node, src) {
14427
14459
  if (src) {
14428
14460
  if (src.start !== undefined) node.start = src.start;
14429
14461
  if (src.end !== undefined) node.end = src.end;
@@ -14432,20 +14464,20 @@ function withLoc$2(node, src) {
14432
14464
  return node;
14433
14465
  }
14434
14466
 
14435
- function ident$1(name, src) {
14436
- return withLoc$2({ type: "Identifier", name }, src);
14467
+ function ident(name, src) {
14468
+ return withLoc$1({ type: "Identifier", name }, src);
14437
14469
  }
14438
14470
 
14439
14471
  function jsxIdent(name, src) {
14440
- return withLoc$2({ type: "JSXIdentifier", name }, src);
14472
+ return withLoc$1({ type: "JSXIdentifier", name }, src);
14441
14473
  }
14442
14474
 
14443
14475
  function jsxContainer(expression, src) {
14444
- return withLoc$2({ type: "JSXExpressionContainer", expression }, src ?? expression);
14476
+ return withLoc$1({ type: "JSXExpressionContainer", expression }, src ?? expression);
14445
14477
  }
14446
14478
 
14447
14479
  function jsxAttr(name, expression, src) {
14448
- return withLoc$2(
14480
+ return withLoc$1(
14449
14481
  {
14450
14482
  type: "JSXAttribute",
14451
14483
  name: jsxIdent(name, src),
@@ -14457,16 +14489,16 @@ function jsxAttr(name, expression, src) {
14457
14489
 
14458
14490
  function jsxElement(name, attributes, children, src) {
14459
14491
  const selfClosing = children.length === 0;
14460
- return withLoc$2(
14492
+ return withLoc$1(
14461
14493
  {
14462
14494
  type: "JSXElement",
14463
- openingElement: withLoc$2(
14495
+ openingElement: withLoc$1(
14464
14496
  { type: "JSXOpeningElement", name: jsxIdent(name, src), attributes, selfClosing },
14465
14497
  src
14466
14498
  ),
14467
14499
  closingElement: selfClosing ?
14468
14500
  null :
14469
- withLoc$2({ type: "JSXClosingElement", name: jsxIdent(name, src) }, src),
14501
+ withLoc$1({ type: "JSXClosingElement", name: jsxIdent(name, src) }, src),
14470
14502
  children
14471
14503
  },
14472
14504
  src
@@ -14474,11 +14506,11 @@ function jsxElement(name, attributes, children, src) {
14474
14506
  }
14475
14507
 
14476
14508
  function jsxFragment(children, src) {
14477
- return withLoc$2(
14509
+ return withLoc$1(
14478
14510
  {
14479
14511
  type: "JSXFragment",
14480
- openingFragment: withLoc$2({ type: "JSXOpeningFragment" }, src),
14481
- closingFragment: withLoc$2({ type: "JSXClosingFragment" }, src),
14512
+ openingFragment: withLoc$1({ type: "JSXOpeningFragment" }, src),
14513
+ closingFragment: withLoc$1({ type: "JSXClosingFragment" }, src),
14482
14514
  children
14483
14515
  },
14484
14516
  src
@@ -14486,7 +14518,7 @@ function jsxFragment(children, src) {
14486
14518
  }
14487
14519
 
14488
14520
  function arrow(params, body, src) {
14489
- return withLoc$2(
14521
+ return withLoc$1(
14490
14522
  {
14491
14523
  type: "ArrowFunctionExpression",
14492
14524
  id: null,
@@ -14501,15 +14533,15 @@ function arrow(params, body, src) {
14501
14533
  }
14502
14534
 
14503
14535
  function blockStatement(body, src) {
14504
- return withLoc$2({ type: "BlockStatement", body }, src);
14536
+ return withLoc$1({ type: "BlockStatement", body }, src);
14505
14537
  }
14506
14538
 
14507
14539
  function returnStatement(argument, src) {
14508
- return withLoc$2({ type: "ReturnStatement", argument }, src);
14540
+ return withLoc$1({ type: "ReturnStatement", argument }, src);
14509
14541
  }
14510
14542
 
14511
14543
  function iife(statements, src) {
14512
- return withLoc$2(
14544
+ return withLoc$1(
14513
14545
  {
14514
14546
  type: "CallExpression",
14515
14547
  callee: arrow([], blockStatement(statements, src), src),
@@ -14520,58 +14552,26 @@ function iife(statements, src) {
14520
14552
  );
14521
14553
  }
14522
14554
 
14523
- function callOn(callee, src) {
14524
- return withLoc$2({ type: "CallExpression", callee, arguments: [], optional: false }, src);
14525
- }
14526
-
14527
14555
  function strictEquals(left, right, src) {
14528
- return withLoc$2({ type: "BinaryExpression", operator: "===", left, right }, src);
14556
+ return withLoc$1({ type: "BinaryExpression", operator: "===", left, right }, src);
14529
14557
  }
14530
14558
 
14531
14559
  function stringLiteral(value, src) {
14532
- return withLoc$2({ type: "Literal", value, raw: JSON.stringify(value) }, src);
14560
+ return withLoc$1({ type: "Literal", value, raw: JSON.stringify(value) }, src);
14533
14561
  }
14534
14562
 
14535
- function cloneNode$1(value) {
14536
- if (Array.isArray(value)) return value.map(cloneNode$1);
14563
+ function cloneNode(value) {
14564
+ if (Array.isArray(value)) return value.map(cloneNode);
14537
14565
  if (typeof value === "object" && value !== null) {
14538
14566
  const out = {};
14539
14567
  for (const key of Object.keys(value)) {
14540
- out[key] = cloneNode$1(value[key]);
14568
+ out[key] = cloneNode(value[key]);
14541
14569
  }
14542
14570
  return out;
14543
14571
  }
14544
14572
  return value;
14545
14573
  }
14546
14574
 
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
14575
  // ---------------------------------------------------------------------------
14576
14576
  // Main walk
14577
14577
  // ---------------------------------------------------------------------------
@@ -14582,7 +14582,7 @@ function desugarProgram(program) {
14582
14582
  }
14583
14583
 
14584
14584
  /** Desugars `node`, returning its replacement for expression-shaped slots. */
14585
- function transform$1(node) {
14585
+ function transform(node) {
14586
14586
  switch (node.type) {
14587
14587
  case "JSXCodeBlock":
14588
14588
  return codeBlockToExpression(node);
@@ -14602,7 +14602,7 @@ function transform$1(node) {
14602
14602
  node.children && (node.children = desugarChildren(node.children));
14603
14603
  return node;
14604
14604
  default:
14605
- if (FUNCTION_TYPES$1.has(node.type) && isNode$3(node.body) && node.body.type === "JSXCodeBlock") {
14605
+ if (FUNCTION_TYPES.has(node.type) && isNode$3(node.body) && node.body.type === "JSXCodeBlock") {
14606
14606
  const body = node.body;
14607
14607
  genericVisit(node, "body");
14608
14608
  node.body = codeBlockToFunctionBody(body);
@@ -14620,10 +14620,10 @@ function genericVisit(node, skipKey) {
14620
14620
  const value = node[key];
14621
14621
  if (Array.isArray(value)) {
14622
14622
  for (let i = 0; i < value.length; i++) {
14623
- if (isNode$3(value[i])) value[i] = transform$1(value[i]);
14623
+ if (isNode$3(value[i])) value[i] = transform(value[i]);
14624
14624
  }
14625
14625
  } else if (isNode$3(value)) {
14626
- node[key] = transform$1(value);
14626
+ node[key] = transform(value);
14627
14627
  }
14628
14628
  }
14629
14629
  }
@@ -14652,7 +14652,7 @@ function desugarElement(el) {
14652
14652
 
14653
14653
  function desugarChildren(children) {
14654
14654
  return children.map((child) => {
14655
- const result = transform$1(child);
14655
+ const result = transform(child);
14656
14656
  if (!VALID_JSX_CHILD_TYPES.has(result.type)) return jsxContainer(result, child);
14657
14657
  return result;
14658
14658
  });
@@ -14720,7 +14720,7 @@ function validateNoControlFlowEscape(entries, construct) {
14720
14720
  for (const entry of entries) check(entry, 0, 0, new Set());
14721
14721
 
14722
14722
  function check(node, loops, breakables, labels) {
14723
- if (FUNCTION_TYPES$1.has(node.type) || ESCAPE_BOUNDARY_TYPES.has(node.type)) return;
14723
+ if (FUNCTION_TYPES.has(node.type) || ESCAPE_BOUNDARY_TYPES.has(node.type)) return;
14724
14724
  switch (node.type) {
14725
14725
  case "ReturnStatement":
14726
14726
  fail$2(escapeMessage("return", construct), node);
@@ -14787,14 +14787,14 @@ function blockToParts(entries, construct) {
14787
14787
  if (renders.length > 0) {
14788
14788
  fail$2("Statements may not follow the rendered output inside a TSRX template block", entry);
14789
14789
  }
14790
- setup.push(transform$1(entry));
14790
+ setup.push(transform(entry));
14791
14791
  }
14792
14792
  }
14793
14793
  return { setup, renders };
14794
14794
  }
14795
14795
 
14796
14796
  function renderNodeToExpression(node) {
14797
- const result = transform$1(node);
14797
+ const result = transform(node);
14798
14798
  if (result.type === "JSXText") return stringLiteral(String(result.value), result);
14799
14799
  return result;
14800
14800
  }
@@ -14806,7 +14806,7 @@ function rendersToExpression(renders, src) {
14806
14806
  if (renders.length === 1) return renderNodeToExpression(renders[0]);
14807
14807
  return jsxFragment(
14808
14808
  renders.map((render) => {
14809
- const result = transform$1(render);
14809
+ const result = transform(render);
14810
14810
  if (!VALID_JSX_CHILD_TYPES.has(result.type)) return jsxContainer(result, render);
14811
14811
  return result;
14812
14812
  }),
@@ -14831,7 +14831,7 @@ function blockToExpression(blockNode, context) {
14831
14831
  // ---------------------------------------------------------------------------
14832
14832
 
14833
14833
  function codeBlockToExpression(cb) {
14834
- const setup = cb.body.map(transform$1);
14834
+ const setup = cb.body.map(transform);
14835
14835
  if (!isNode$3(cb.render)) {
14836
14836
  fail$2("A TSRX statement container is missing its rendered output node", cb);
14837
14837
  }
@@ -14841,7 +14841,7 @@ function codeBlockToExpression(cb) {
14841
14841
  }
14842
14842
 
14843
14843
  function codeBlockToFunctionBody(cb) {
14844
- const setup = cb.body.map(transform$1);
14844
+ const setup = cb.body.map(transform);
14845
14845
  if (!isNode$3(cb.render)) {
14846
14846
  fail$2("A TSRX statement container is missing its rendered output node", cb);
14847
14847
  }
@@ -14859,7 +14859,7 @@ function ifToJsx(node) {
14859
14859
  let elseBlock = null;
14860
14860
  for (;;) {
14861
14861
  branches.push({
14862
- test: transform$1(current.test),
14862
+ test: transform(current.test),
14863
14863
  block: current.consequent,
14864
14864
  src: current
14865
14865
  });
@@ -14913,7 +14913,7 @@ function forToJsx(node) {
14913
14913
  const left = node.left;
14914
14914
  const pattern =
14915
14915
  left.type === "VariableDeclaration" ? left.declarations[0].id : left;
14916
- const each = transform$1(node.right);
14916
+ const each = transform(node.right);
14917
14917
  const index = isNode$3(node.index) ? node.index : null;
14918
14918
  const key = isNode$3(node.key) ? node.key : null;
14919
14919
  const usesIndexOnlyMode = index !== null && key === null;
@@ -14931,25 +14931,22 @@ function forToJsx(node) {
14931
14931
  ) :
14932
14932
  renderExpr;
14933
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];
14934
+ // The callback bindings pass through as authored (#3474): where `For` hands
14935
+ // the callback an accessor (the item in every non-default mode, the index
14936
+ // under a custom key), the author reads it as one — `item()`, `i()` — exactly
14937
+ // as in JSX. Destructuring an accessor has nothing to destructure.
14938
+ if (itemIsAccessor && pattern.type !== "Identifier") {
14939
+ fail$2(FOR_ACCESSOR_DESTRUCTURING_MESSAGE, pattern);
14940
+ }
14941
+ const params = [pattern];
14945
14942
  if (index) params.push(index);
14946
14943
 
14947
14944
  const attributes = [jsxAttr("each", each, node.right)];
14948
14945
  if (key) {
14949
- attributes.push(jsxAttr("keyed", arrow([eagerPattern(pattern)], transform$1(key), key), key));
14946
+ attributes.push(jsxAttr("keyed", arrow([cloneNode(pattern)], transform(key), key), key));
14950
14947
  } else if (usesIndexOnlyMode) {
14951
14948
  attributes.push(
14952
- jsxAttr("keyed", withLoc$2({ type: "Literal", value: false, raw: "false" }, index), index)
14949
+ jsxAttr("keyed", withLoc$1({ type: "Literal", value: false, raw: "false" }, index), index)
14953
14950
  );
14954
14951
  }
14955
14952
  if (isNode$3(node.empty)) {
@@ -14970,7 +14967,7 @@ function forToJsx(node) {
14970
14967
  // ---------------------------------------------------------------------------
14971
14968
 
14972
14969
  function switchToJsx(node) {
14973
- const discriminant = transform$1(node.discriminant);
14970
+ const discriminant = transform(node.discriminant);
14974
14971
  const matches = [];
14975
14972
  let fallbackExpr = null;
14976
14973
  let fallbackSrc = null;
@@ -14998,8 +14995,8 @@ function switchToJsx(node) {
14998
14995
  fallbackSrc = switchCase;
14999
14996
  } else {
15000
14997
  const when = strictEquals(
15001
- cloneNode$1(discriminant),
15002
- transform$1(switchCase.test),
14998
+ cloneNode(discriminant),
14999
+ transform(switchCase.test),
15003
15000
  switchCase
15004
15001
  );
15005
15002
  matches.push(
@@ -15040,30 +15037,23 @@ function tryToJsx(node) {
15040
15037
  if (isNode$3(node.handler)) {
15041
15038
  const handler = node.handler;
15042
15039
  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
- );
15040
+ // `Errored` passes an `ErrorAccessor`; the binding passes through as
15041
+ // authored and the author reads it as `err()` (#3474).
15042
+ if (param && (param.type === "ObjectPattern" || param.type === "ArrayPattern")) {
15043
+ fail$2(CATCH_ACCESSOR_DESTRUCTURING_MESSAGE, param);
15044
+ }
15045
+ if (param && param.type !== "Identifier") {
15046
+ fail$2("The @catch error binding must be an identifier", param);
15053
15047
  }
15054
15048
  const resetParam = isNode$3(handler.resetParam) ? handler.resetParam : null;
15055
15049
  const errorName = param ? param.name : "_e";
15056
15050
 
15057
15051
  const handlerExpr = blockToExpression(handler.body, "@catch");
15058
15052
  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
15053
 
15054
+ const params = [ident(errorName, param)];
15065
15055
  if (resetParam)
15066
- params.push(ident$1(resetParam.name, resetParam));
15056
+ params.push(ident(resetParam.name, resetParam));
15067
15057
 
15068
15058
  result = jsxElement(
15069
15059
  "Errored",
@@ -15076,184 +15066,6 @@ function tryToJsx(node) {
15076
15066
  return result;
15077
15067
  }
15078
15068
 
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
15069
  /**
15258
15070
  * ESTree (acorn / typescript-eslint shaped, as produced by `@tsrx/core`) to
15259
15071
  * Babel AST conversion.
@@ -15605,63 +15417,16 @@ function toBabelFile(program) {
15605
15417
  }
15606
15418
 
15607
15419
  /**
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`.
15420
+ * Authored lazy destructuring (`&{ … }` / `&[ … ]`) is not part of the Solid
15421
+ * TSRX target. TSRX removed the sigil from the language, and Solid never
15422
+ * lowered it: a binding that reads like a value but compiles to a property
15423
+ * read is the hazard Solid keeps explicit with accessor calls. Parsers that
15424
+ * still produce the pattern are rejected here, before any desugaring, so the
15425
+ * failure is one clear message rather than a downstream type error.
15617
15426
  */
15618
15427
 
15619
15428
 
15620
15429
 
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
15430
  const SKIP_KEYS$1 = new Set([
15666
15431
  "type",
15667
15432
  "loc",
@@ -15682,86 +15447,6 @@ function isNode$1(value) {
15682
15447
 
15683
15448
  }
15684
15449
 
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
15450
  function fail(message, node) {
15766
15451
  const start = node?.loc?.start;
15767
15452
  throw new SyntaxError(start ? `${message} (${start.line}:${start.column})` : message);
@@ -15770,11 +15455,7 @@ function fail(message, node) {
15770
15455
  const AUTHORED_LAZY_UNSUPPORTED =
15771
15456
  "Solid's TSRX frontend does not support authored lazy destructuring; keep property and accessor reads explicit";
15772
15457
 
15773
- /**
15774
- * Reject parser-authored `&{}` / `&[]` before TSRX controls synthesize the
15775
- * deferred patterns Solid needs for accessor-backed `@for` and `@catch`
15776
- * callbacks.
15777
- */
15458
+ /** Reject parser-authored `&{}` / `&[]` anywhere in the module. */
15778
15459
  function rejectAuthoredLazyDestructuring(root) {
15779
15460
  const visit = (value) => {
15780
15461
  if (Array.isArray(value)) {
@@ -15792,1468 +15473,38 @@ function rejectAuthoredLazyDestructuring(root) {
15792
15473
  visit(root);
15793
15474
  }
15794
15475
 
15795
- class LazyState {
15796
- names = new Set();
15797
- next = new Map();
15798
- programTemps = [];
15799
- tempScopes = [this.programTemps];
15800
-
15476
+ const SKIP_KEYS = new Set([
15477
+ "type",
15478
+ "loc",
15479
+ "start",
15480
+ "end",
15481
+ "range",
15482
+ "metadata",
15483
+ "css",
15484
+ "leadingComments",
15485
+ "trailingComments",
15486
+ "innerComments"]
15487
+ );
15801
15488
 
15802
- usesArrayRest = false;
15803
- topLevelGlobalThisBinding = false;
15489
+ const FUNCTION_BOUNDARIES = new Set([
15490
+ "FunctionDeclaration",
15491
+ "FunctionExpression",
15492
+ "ArrowFunctionExpression",
15493
+ "ClassDeclaration",
15494
+ "ClassExpression"]
15495
+ );
15804
15496
 
15805
- constructor(root) {
15806
- this.collectNames(root);
15807
- this.topLevelGlobalThisBinding = programBindsName(root, "globalThis");
15808
- }
15497
+ function isNode(value) {
15498
+ return (
15499
+ typeof value === "object" &&
15500
+ value !== null &&
15501
+ typeof value.type === "string");
15809
15502
 
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
- }
15503
+ }
15823
15504
 
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
- }
15505
+ function isStyleElement(node) {
15506
+ return node.type === "JSXStyleElement";
15507
+ }
17257
15508
 
17258
15509
  function isNativeRenderRoot(node) {
17259
15510
  return (
@@ -17664,10 +15915,10 @@ function processTsrxStyles(program, core) {
17664
15915
  *
17665
15916
  * Routes `.tsrx` sources (or any source when `syntax: "tsrx"`) through
17666
15917
  * `@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.
15918
+ * core's CSS helpers, desugars every TSRX construct to Solid builtIn JSX, and
15919
+ * converts the result to a Babel `File` for the unchanged JSX pipeline.
15920
+ * Bindings pass through as authored; authored lazy destructuring is rejected
15921
+ * for the Solid target.
17671
15922
  *
17672
15923
  * `@tsrx/core` is an optional peer dependency loaded lazily on first TSRX
17673
15924
  * routing, so plain JSX users never pay for it.
@@ -17737,18 +15988,9 @@ function parseTsrx(code, filename) {
17737
15988
  tsrx.analyzeTsrx(program, filename ?? null);
17738
15989
  const styleResult = processTsrxStyles(program, tsrx);
17739
15990
 
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
15991
  desugarProgram(program);
17745
15992
 
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);
15993
+ const file = toBabelFile(program);
17752
15994
  // Babel's default AST clone preserves enumerable string keys. Program.enter
17753
15995
  // lifts this temporary payload into transform metadata and removes it from
17754
15996
  // the AST, avoiding mutable plugin-factory state (and concurrent-run races).