@fictjs/compiler 0.14.0 → 0.15.0

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/README.md CHANGED
@@ -56,6 +56,9 @@ createFictPlugin({
56
56
  - `'auto'` (default): writes metadata to cache directory (not source tree) only when no external metadata store/resolver is provided.
57
57
  - `moduleMetadataCacheDir` (default: `<cwd>/.fict-cache/metadata`): cache directory used by `emitModuleMetadata: 'auto'`.
58
58
  - `moduleMetadata` / `resolveModuleMetadata`: external metadata integration hooks. When provided, `'auto'` does not write metadata files.
59
+ - Built-in metadata resolution only covers local filesystem modules (relative/absolute paths + configured alias/ts resolution from the caller).
60
+ - Bare package imports are treated as opaque unless your `resolveModuleMetadata` hook provides metadata.
61
+ - Cross-module metadata lookup does not perform cycle detection; cyclical hook metadata chains should be handled by a custom resolver if needed.
59
62
  - `reactiveScopes`: function names whose **first callback argument** is treated as a component-like reactive scope.
60
63
  - Only **direct calls** are recognized (e.g., `renderHook(() => ...)` or `utils.renderHook(() => ...)`).
61
64
  - **Aliases/indirect calls** are not recognized (e.g., `const rh = renderHook; rh(() => ...)`).
package/dist/index.cjs CHANGED
@@ -14174,6 +14174,7 @@ var RUNTIME_HELPERS = {
14174
14174
  bindEvent: "bindEvent",
14175
14175
  callEventHandler: "callEventHandler",
14176
14176
  bindRef: "bindRef",
14177
+ spread: "spread",
14177
14178
  nonReactive: "nonReactive",
14178
14179
  toNodeArray: "toNodeArray",
14179
14180
  template: "template",
@@ -14231,6 +14232,7 @@ var RUNTIME_ALIASES = {
14231
14232
  bindEvent: "bindEvent",
14232
14233
  callEventHandler: "callEventHandler",
14233
14234
  bindRef: "bindRef",
14235
+ spread: "spread",
14234
14236
  nonReactive: "nonReactive",
14235
14237
  toNodeArray: "toNodeArray",
14236
14238
  template: "template",
@@ -22616,138 +22618,212 @@ function emitConditionalChild(startMarkerId, endMarkerId, expr, statements, ctx,
22616
22618
  );
22617
22619
  }
22618
22620
 
22619
- // src/ir/codegen-expression-deps.ts
22620
- function getMemberDependencyPath(expr) {
22621
- if (expr.kind === "MemberExpression") {
22622
- const prop = expr.property;
22623
- let propName;
22624
- if (!expr.computed && prop.kind === "Identifier") {
22625
- propName = prop.name;
22626
- } else if (prop.kind === "Literal" && typeof prop.value === "string") {
22627
- propName = prop.value;
22628
- }
22629
- if (!propName) return void 0;
22630
- const object = expr.object;
22631
- if (object.kind === "Identifier") {
22632
- return `${deSSAVarName(object.name)}.${propName}`;
22633
- }
22634
- if (object.kind === "MemberExpression") {
22635
- const parent = getMemberDependencyPath(object);
22636
- return parent ? `${parent}.${propName}` : void 0;
22637
- }
22621
+ // src/ir/walk-expression.ts
22622
+ function assertNever(value) {
22623
+ throw new Error(`Unhandled node in walkExpression: ${JSON.stringify(value)}`);
22624
+ }
22625
+ function walkTerminator(term, visitNode, inFunctionBody) {
22626
+ switch (term.kind) {
22627
+ case "Return":
22628
+ if (term.argument) visitNode(term.argument, null, inFunctionBody);
22629
+ return;
22630
+ case "Throw":
22631
+ visitNode(term.argument, null, inFunctionBody);
22632
+ return;
22633
+ case "Branch":
22634
+ visitNode(term.test, null, inFunctionBody);
22635
+ return;
22636
+ case "Switch":
22637
+ visitNode(term.discriminant, null, inFunctionBody);
22638
+ term.cases.forEach((c) => {
22639
+ if (c.test) visitNode(c.test, null, inFunctionBody);
22640
+ });
22641
+ return;
22642
+ case "ForOf":
22643
+ visitNode(term.iterable, null, inFunctionBody);
22644
+ return;
22645
+ case "ForIn":
22646
+ visitNode(term.object, null, inFunctionBody);
22647
+ return;
22648
+ case "Jump":
22649
+ case "Unreachable":
22650
+ case "Break":
22651
+ case "Continue":
22652
+ case "Try":
22653
+ return;
22654
+ default:
22655
+ assertNever(term);
22638
22656
  }
22639
- return void 0;
22640
22657
  }
22641
- function collectBlockDependencies(blocks, deps) {
22658
+ function walkInstruction(instr, visitNode, inFunctionBody) {
22659
+ switch (instr.kind) {
22660
+ case "Assign":
22661
+ case "Expression":
22662
+ visitNode(instr.value, null, inFunctionBody);
22663
+ return;
22664
+ case "Phi":
22665
+ instr.sources.forEach((source) => visitNode(source.id, null, inFunctionBody));
22666
+ return;
22667
+ default:
22668
+ assertNever(instr);
22669
+ }
22670
+ }
22671
+ function walkBlocks(blocks, visitNode, inFunctionBody) {
22642
22672
  for (const block of blocks) {
22643
- for (const instr of block.instructions) {
22644
- switch (instr.kind) {
22645
- case "Assign":
22646
- case "Expression":
22647
- collectExpressionDependencies(instr.value, deps);
22648
- break;
22649
- case "Phi":
22650
- for (const source of instr.sources) {
22651
- deps.add(deSSAVarName(source.id.name));
22673
+ block.instructions.forEach((instr) => walkInstruction(instr, visitNode, inFunctionBody));
22674
+ walkTerminator(block.terminator, visitNode, inFunctionBody);
22675
+ }
22676
+ }
22677
+ function walkExpression(expr, visit, options = {}) {
22678
+ const includeFunctionBodies = options.includeFunctionBodies ?? true;
22679
+ const visitNode = (node, parent, inFunctionBody) => {
22680
+ visit(node, { parent, inFunctionBody });
22681
+ switch (node.kind) {
22682
+ case "Identifier":
22683
+ case "Literal":
22684
+ case "MetaProperty":
22685
+ case "ThisExpression":
22686
+ case "SuperExpression":
22687
+ return;
22688
+ case "ImportExpression":
22689
+ visitNode(node.source, node, inFunctionBody);
22690
+ return;
22691
+ case "CallExpression":
22692
+ case "OptionalCallExpression":
22693
+ visitNode(node.callee, node, inFunctionBody);
22694
+ node.arguments.forEach((arg) => visitNode(arg, node, inFunctionBody));
22695
+ return;
22696
+ case "MemberExpression":
22697
+ case "OptionalMemberExpression":
22698
+ visitNode(node.object, node, inFunctionBody);
22699
+ if (node.computed) {
22700
+ visitNode(node.property, node, inFunctionBody);
22701
+ }
22702
+ return;
22703
+ case "BinaryExpression":
22704
+ case "LogicalExpression":
22705
+ visitNode(node.left, node, inFunctionBody);
22706
+ visitNode(node.right, node, inFunctionBody);
22707
+ return;
22708
+ case "UnaryExpression":
22709
+ case "AwaitExpression":
22710
+ visitNode(node.argument, node, inFunctionBody);
22711
+ return;
22712
+ case "ConditionalExpression":
22713
+ visitNode(node.test, node, inFunctionBody);
22714
+ visitNode(node.consequent, node, inFunctionBody);
22715
+ visitNode(node.alternate, node, inFunctionBody);
22716
+ return;
22717
+ case "ArrayExpression":
22718
+ node.elements.forEach((el) => visitNode(el, node, inFunctionBody));
22719
+ return;
22720
+ case "ObjectExpression":
22721
+ node.properties.forEach((prop) => {
22722
+ if (prop.kind === "SpreadElement") {
22723
+ visitNode(prop.argument, node, inFunctionBody);
22724
+ } else {
22725
+ if (prop.computed) {
22726
+ visitNode(prop.key, node, inFunctionBody);
22727
+ }
22728
+ visitNode(prop.value, node, inFunctionBody);
22652
22729
  }
22653
- break;
22654
- default:
22655
- break;
22656
- }
22657
- }
22658
- const term = block.terminator;
22659
- switch (term.kind) {
22660
- case "Return":
22661
- if (term.argument) collectExpressionDependencies(term.argument, deps);
22662
- break;
22663
- case "Throw":
22664
- collectExpressionDependencies(term.argument, deps);
22665
- break;
22666
- case "Branch":
22667
- collectExpressionDependencies(term.test, deps);
22668
- break;
22669
- case "Switch":
22670
- collectExpressionDependencies(term.discriminant, deps);
22671
- for (const c of term.cases) {
22672
- if (c.test) collectExpressionDependencies(c.test, deps);
22730
+ });
22731
+ return;
22732
+ case "JSXElement":
22733
+ if (typeof node.tagName !== "string") {
22734
+ visitNode(node.tagName, node, inFunctionBody);
22673
22735
  }
22674
- break;
22675
- case "ForOf":
22676
- collectExpressionDependencies(term.iterable, deps);
22677
- break;
22678
- case "ForIn":
22679
- collectExpressionDependencies(term.object, deps);
22680
- break;
22736
+ node.attributes.forEach((attr) => {
22737
+ if (attr.isSpread && attr.spreadExpr) {
22738
+ visitNode(attr.spreadExpr, node, inFunctionBody);
22739
+ } else if (attr.value) {
22740
+ visitNode(attr.value, node, inFunctionBody);
22741
+ }
22742
+ });
22743
+ node.children.forEach((child) => {
22744
+ if (child.kind === "expression") {
22745
+ visitNode(child.value, node, inFunctionBody);
22746
+ } else if (child.kind === "element") {
22747
+ visitNode(child.value, node, inFunctionBody);
22748
+ }
22749
+ });
22750
+ return;
22751
+ case "ArrowFunction":
22752
+ if (!includeFunctionBodies) return;
22753
+ if (node.isExpression && !Array.isArray(node.body)) {
22754
+ visitNode(node.body, node, true);
22755
+ } else if (Array.isArray(node.body)) {
22756
+ walkBlocks(node.body, visitNode, true);
22757
+ }
22758
+ return;
22759
+ case "FunctionExpression":
22760
+ if (!includeFunctionBodies) return;
22761
+ walkBlocks(node.body, visitNode, true);
22762
+ return;
22763
+ case "AssignmentExpression":
22764
+ visitNode(node.left, node, inFunctionBody);
22765
+ visitNode(node.right, node, inFunctionBody);
22766
+ return;
22767
+ case "UpdateExpression":
22768
+ visitNode(node.argument, node, inFunctionBody);
22769
+ return;
22770
+ case "TemplateLiteral":
22771
+ node.expressions.forEach((item) => visitNode(item, node, inFunctionBody));
22772
+ return;
22773
+ case "SpreadElement":
22774
+ visitNode(node.argument, node, inFunctionBody);
22775
+ return;
22776
+ case "NewExpression":
22777
+ visitNode(node.callee, node, inFunctionBody);
22778
+ node.arguments.forEach((arg) => visitNode(arg, node, inFunctionBody));
22779
+ return;
22780
+ case "SequenceExpression":
22781
+ node.expressions.forEach((item) => visitNode(item, node, inFunctionBody));
22782
+ return;
22783
+ case "YieldExpression":
22784
+ if (node.argument) {
22785
+ visitNode(node.argument, node, inFunctionBody);
22786
+ }
22787
+ return;
22788
+ case "TaggedTemplateExpression":
22789
+ visitNode(node.tag, node, inFunctionBody);
22790
+ node.quasi.expressions.forEach((item) => visitNode(item, node, inFunctionBody));
22791
+ return;
22792
+ case "ClassExpression":
22793
+ if (node.superClass) {
22794
+ visitNode(node.superClass, node, inFunctionBody);
22795
+ }
22796
+ return;
22681
22797
  default:
22682
- break;
22798
+ assertNever(node);
22683
22799
  }
22800
+ };
22801
+ visitNode(expr, null, false);
22802
+ }
22803
+
22804
+ // src/ir/codegen-expression-deps.ts
22805
+ function getMemberDependencyPath(expr) {
22806
+ if (expr.kind !== "MemberExpression" && expr.kind !== "OptionalMemberExpression") return void 0;
22807
+ const depPath = extractDependencyPath(expr);
22808
+ if (!depPath || depPath.segments.length === 0) return void 0;
22809
+ const base = deSSAVarName(depPath.base);
22810
+ if (depPath.segments.some((segment) => segment.computed)) {
22811
+ return base;
22684
22812
  }
22813
+ const tail = depPath.segments.map((segment) => segment.property).join(".");
22814
+ return tail ? `${base}.${tail}` : void 0;
22685
22815
  }
22686
22816
  function collectExpressionDependencies(expr, deps) {
22687
- if (expr.kind === "Identifier") {
22688
- deps.add(deSSAVarName(expr.name));
22689
- return;
22690
- }
22691
- if (expr.kind === "ArrowFunction") {
22692
- if (expr.isExpression && !Array.isArray(expr.body)) {
22693
- collectExpressionDependencies(expr.body, deps);
22694
- } else if (Array.isArray(expr.body)) {
22695
- collectBlockDependencies(expr.body, deps);
22817
+ walkExpression(expr, (node) => {
22818
+ if (node.kind === "Identifier") {
22819
+ deps.add(deSSAVarName(node.name));
22820
+ return;
22696
22821
  }
22697
- return;
22698
- }
22699
- if (expr.kind === "FunctionExpression") {
22700
- collectBlockDependencies(expr.body, deps);
22701
- return;
22702
- }
22703
- if (expr.kind === "MemberExpression") {
22704
- const path2 = getMemberDependencyPath(expr);
22705
- if (path2) deps.add(path2);
22706
- collectExpressionDependencies(expr.object, deps);
22707
- if (expr.computed && expr.property.kind !== "Literal") {
22708
- collectExpressionDependencies(expr.property, deps);
22822
+ const path2 = getMemberDependencyPath(node);
22823
+ if (path2) {
22824
+ deps.add(path2);
22709
22825
  }
22710
- return;
22711
- }
22712
- if (expr.kind === "CallExpression") {
22713
- collectExpressionDependencies(expr.callee, deps);
22714
- expr.arguments.forEach((a) => collectExpressionDependencies(a, deps));
22715
- return;
22716
- }
22717
- if (expr.kind === "BinaryExpression" || expr.kind === "LogicalExpression") {
22718
- collectExpressionDependencies(expr.left, deps);
22719
- collectExpressionDependencies(expr.right, deps);
22720
- return;
22721
- }
22722
- if (expr.kind === "ConditionalExpression") {
22723
- collectExpressionDependencies(expr.test, deps);
22724
- collectExpressionDependencies(expr.consequent, deps);
22725
- collectExpressionDependencies(expr.alternate, deps);
22726
- return;
22727
- }
22728
- if (expr.kind === "UnaryExpression") {
22729
- collectExpressionDependencies(expr.argument, deps);
22730
- return;
22731
- }
22732
- if (expr.kind === "ArrayExpression") {
22733
- expr.elements.forEach((el) => collectExpressionDependencies(el, deps));
22734
- return;
22735
- }
22736
- if (expr.kind === "ObjectExpression") {
22737
- expr.properties.forEach((p) => {
22738
- if (p.kind === "SpreadElement") {
22739
- collectExpressionDependencies(p.argument, deps);
22740
- } else {
22741
- if (p.computed) collectExpressionDependencies(p.key, deps);
22742
- collectExpressionDependencies(p.value, deps);
22743
- }
22744
- });
22745
- return;
22746
- }
22747
- if (expr.kind === "TemplateLiteral") {
22748
- expr.expressions.forEach((e) => collectExpressionDependencies(e, deps));
22749
- return;
22750
- }
22826
+ });
22751
22827
  }
22752
22828
 
22753
22829
  // src/ir/codegen-reactive-kind.ts
@@ -26125,8 +26201,31 @@ function extractHIRStaticHtml(jsx, ctx, ops, parentPath = [], namespace = null)
26125
26201
  const resolvedNamespace = resolveNamespaceContext(tagName, namespace);
26126
26202
  let html = `<${tagName}`;
26127
26203
  const bindings = [];
26128
- for (const attr of jsx.attributes) {
26204
+ for (let attrIndex = 0; attrIndex < jsx.attributes.length; attrIndex++) {
26205
+ const attr = jsx.attributes[attrIndex];
26129
26206
  if (attr.isSpread) {
26207
+ if (attr.spreadExpr) {
26208
+ const excluded = /* @__PURE__ */ new Set();
26209
+ for (let nextIndex = attrIndex + 1; nextIndex < jsx.attributes.length; nextIndex++) {
26210
+ const nextAttr = jsx.attributes[nextIndex];
26211
+ if (nextAttr.isSpread) continue;
26212
+ let nextName = normalizeHIRAttrName(nextAttr.name);
26213
+ if (nextName.endsWith("$")) {
26214
+ nextName = nextName.slice(0, -1);
26215
+ }
26216
+ if (nextName === "key") continue;
26217
+ excluded.add(nextName);
26218
+ if (nextName !== nextAttr.name) {
26219
+ excluded.add(nextAttr.name);
26220
+ }
26221
+ }
26222
+ bindings.push({
26223
+ type: "spread",
26224
+ path: [...parentPath],
26225
+ expr: attr.spreadExpr,
26226
+ exclude: excluded.size > 0 ? Array.from(excluded) : void 0
26227
+ });
26228
+ }
26130
26229
  continue;
26131
26230
  }
26132
26231
  let name = normalizeHIRAttrName(attr.name);
@@ -28311,10 +28410,28 @@ function lowerIntrinsicElement(jsx, ctx) {
28311
28410
  )
28312
28411
  );
28313
28412
  }
28413
+ fusedPatchGroups.clear();
28314
28414
  };
28315
28415
  for (const binding of bindings) {
28316
28416
  const targetId = resolveHIRBindingPath(binding.path, nodeCache, statements, ctx, genTemp3);
28317
- if (binding.type === "event" && binding.expr && binding.name) {
28417
+ if (binding.type === "spread" && binding.expr) {
28418
+ flushFusedPatchGroups();
28419
+ ctx.helpersUsed.add("spread");
28420
+ const spreadValueExpr = lowerDomExpression(binding.expr, ctx, containingRegion);
28421
+ const spreadGetter = t4.arrowFunctionExpression([], spreadValueExpr);
28422
+ const spreadArgs = [
28423
+ targetId,
28424
+ spreadGetter,
28425
+ t4.booleanLiteral(Boolean(isSVG || isMathML)),
28426
+ t4.booleanLiteral(true)
28427
+ ];
28428
+ if (binding.exclude && binding.exclude.length > 0) {
28429
+ spreadArgs.push(t4.arrayExpression(binding.exclude.map((name) => t4.stringLiteral(name))));
28430
+ }
28431
+ statements.push(
28432
+ t4.expressionStatement(t4.callExpression(t4.identifier(RUNTIME_ALIASES.spread), spreadArgs))
28433
+ );
28434
+ } else if (binding.type === "event" && binding.expr && binding.name) {
28318
28435
  const eventName = binding.name;
28319
28436
  const hasEventOptions = binding.eventOptions && (binding.eventOptions.capture || binding.eventOptions.passive || binding.eventOptions.once);
28320
28437
  const isDelegated = DelegatedEvents.has(eventName) && !hasEventOptions;
@@ -33102,106 +33219,106 @@ function collectUsesFromTerminator(term, add, inFunctionBody = false) {
33102
33219
  }
33103
33220
  }
33104
33221
  function collectUsesFromExpression(expr, add, inFunctionBody = false) {
33105
- walkExpression(expr, add, { inFunctionBody, shadowed: /* @__PURE__ */ new Set() });
33222
+ walkExpression2(expr, add, { inFunctionBody, shadowed: /* @__PURE__ */ new Set() });
33106
33223
  }
33107
- function walkExpression(expr, add, ctx) {
33224
+ function walkExpression2(expr, add, ctx) {
33108
33225
  switch (expr.kind) {
33109
33226
  case "Identifier":
33110
33227
  if (!ctx.shadowed.has(expr.name)) add(expr.name, ctx.inFunctionBody);
33111
33228
  return;
33112
33229
  case "CallExpression":
33113
33230
  case "OptionalCallExpression":
33114
- walkExpression(expr.callee, add, ctx);
33115
- expr.arguments.forEach((arg) => walkExpression(arg, add, ctx));
33231
+ walkExpression2(expr.callee, add, ctx);
33232
+ expr.arguments.forEach((arg) => walkExpression2(arg, add, ctx));
33116
33233
  return;
33117
33234
  case "MemberExpression":
33118
33235
  case "OptionalMemberExpression":
33119
- walkExpression(expr.object, add, ctx);
33120
- if (expr.computed) walkExpression(expr.property, add, ctx);
33236
+ walkExpression2(expr.object, add, ctx);
33237
+ if (expr.computed) walkExpression2(expr.property, add, ctx);
33121
33238
  return;
33122
33239
  case "BinaryExpression":
33123
33240
  case "LogicalExpression":
33124
- walkExpression(expr.left, add, ctx);
33125
- walkExpression(expr.right, add, ctx);
33241
+ walkExpression2(expr.left, add, ctx);
33242
+ walkExpression2(expr.right, add, ctx);
33126
33243
  return;
33127
33244
  case "UnaryExpression":
33128
- walkExpression(expr.argument, add, ctx);
33245
+ walkExpression2(expr.argument, add, ctx);
33129
33246
  return;
33130
33247
  case "ConditionalExpression":
33131
- walkExpression(expr.test, add, ctx);
33132
- walkExpression(expr.consequent, add, ctx);
33133
- walkExpression(expr.alternate, add, ctx);
33248
+ walkExpression2(expr.test, add, ctx);
33249
+ walkExpression2(expr.consequent, add, ctx);
33250
+ walkExpression2(expr.alternate, add, ctx);
33134
33251
  return;
33135
33252
  case "ArrayExpression":
33136
33253
  expr.elements.forEach((el) => {
33137
- if (el) walkExpression(el, add, ctx);
33254
+ if (el) walkExpression2(el, add, ctx);
33138
33255
  });
33139
33256
  return;
33140
33257
  case "ObjectExpression":
33141
33258
  expr.properties.forEach((prop) => {
33142
33259
  if (prop.kind === "SpreadElement") {
33143
- walkExpression(prop.argument, add, ctx);
33260
+ walkExpression2(prop.argument, add, ctx);
33144
33261
  } else {
33145
- if (prop.computed) walkExpression(prop.key, add, ctx);
33146
- walkExpression(prop.value, add, ctx);
33262
+ if (prop.computed) walkExpression2(prop.key, add, ctx);
33263
+ walkExpression2(prop.value, add, ctx);
33147
33264
  }
33148
33265
  });
33149
33266
  return;
33150
33267
  case "TemplateLiteral":
33151
- expr.expressions.forEach((e) => walkExpression(e, add, ctx));
33268
+ expr.expressions.forEach((e) => walkExpression2(e, add, ctx));
33152
33269
  return;
33153
33270
  case "SpreadElement":
33154
- walkExpression(expr.argument, add, ctx);
33271
+ walkExpression2(expr.argument, add, ctx);
33155
33272
  return;
33156
33273
  case "SequenceExpression":
33157
- expr.expressions.forEach((e) => walkExpression(e, add, ctx));
33274
+ expr.expressions.forEach((e) => walkExpression2(e, add, ctx));
33158
33275
  return;
33159
33276
  case "AwaitExpression":
33160
- walkExpression(expr.argument, add, ctx);
33277
+ walkExpression2(expr.argument, add, ctx);
33161
33278
  return;
33162
33279
  case "NewExpression":
33163
- walkExpression(expr.callee, add, ctx);
33164
- expr.arguments.forEach((arg) => walkExpression(arg, add, ctx));
33280
+ walkExpression2(expr.callee, add, ctx);
33281
+ expr.arguments.forEach((arg) => walkExpression2(arg, add, ctx));
33165
33282
  return;
33166
33283
  case "ArrowFunction": {
33167
33284
  const shadowed = new Set(ctx.shadowed);
33168
33285
  expr.params.forEach((p) => shadowed.add(p.name));
33169
33286
  if (expr.isExpression) {
33170
- walkExpression(expr.body, add, { inFunctionBody: true, shadowed });
33287
+ walkExpression2(expr.body, add, { inFunctionBody: true, shadowed });
33171
33288
  return;
33172
33289
  }
33173
- walkBlocks(expr.body, add, { inFunctionBody: true, shadowed });
33290
+ walkBlocks2(expr.body, add, { inFunctionBody: true, shadowed });
33174
33291
  return;
33175
33292
  }
33176
33293
  case "FunctionExpression": {
33177
33294
  const shadowed = new Set(ctx.shadowed);
33178
33295
  expr.params.forEach((p) => shadowed.add(p.name));
33179
- walkBlocks(expr.body, add, { inFunctionBody: true, shadowed });
33296
+ walkBlocks2(expr.body, add, { inFunctionBody: true, shadowed });
33180
33297
  return;
33181
33298
  }
33182
33299
  case "AssignmentExpression":
33183
- walkExpression(expr.left, add, ctx);
33184
- walkExpression(expr.right, add, ctx);
33300
+ walkExpression2(expr.left, add, ctx);
33301
+ walkExpression2(expr.right, add, ctx);
33185
33302
  return;
33186
33303
  case "UpdateExpression":
33187
- walkExpression(expr.argument, add, ctx);
33304
+ walkExpression2(expr.argument, add, ctx);
33188
33305
  return;
33189
33306
  case "JSXElement":
33190
33307
  if (typeof expr.tagName !== "string") {
33191
- walkExpression(expr.tagName, add, ctx);
33308
+ walkExpression2(expr.tagName, add, ctx);
33192
33309
  }
33193
33310
  expr.attributes.forEach((attr) => {
33194
33311
  if (attr.isSpread && attr.spreadExpr) {
33195
- walkExpression(attr.spreadExpr, add, ctx);
33312
+ walkExpression2(attr.spreadExpr, add, ctx);
33196
33313
  } else if (attr.value) {
33197
- walkExpression(attr.value, add, ctx);
33314
+ walkExpression2(attr.value, add, ctx);
33198
33315
  }
33199
33316
  });
33200
33317
  expr.children.forEach((child) => {
33201
33318
  if (child.kind === "expression") {
33202
- walkExpression(child.value, add, ctx);
33319
+ walkExpression2(child.value, add, ctx);
33203
33320
  } else if (child.kind === "element") {
33204
- walkExpression(child.value, add, ctx);
33321
+ walkExpression2(child.value, add, ctx);
33205
33322
  }
33206
33323
  });
33207
33324
  return;
@@ -33209,16 +33326,16 @@ function walkExpression(expr, add, ctx) {
33209
33326
  return;
33210
33327
  }
33211
33328
  }
33212
- function walkBlocks(blocks, add, ctx) {
33329
+ function walkBlocks2(blocks, add, ctx) {
33213
33330
  for (const block of blocks) {
33214
33331
  for (const instr of block.instructions) {
33215
33332
  if (instr.kind === "Assign") {
33216
- walkExpression(instr.value, add, ctx);
33333
+ walkExpression2(instr.value, add, ctx);
33217
33334
  if (instr.declarationKind) {
33218
33335
  ctx.shadowed.add(instr.target.name);
33219
33336
  }
33220
33337
  } else if (instr.kind === "Expression") {
33221
- walkExpression(instr.value, add, ctx);
33338
+ walkExpression2(instr.value, add, ctx);
33222
33339
  } else if (instr.kind === "Phi") {
33223
33340
  instr.sources.forEach((src) => {
33224
33341
  if (!ctx.shadowed.has(src.id.name)) add(src.id.name, ctx.inFunctionBody);
@@ -33237,7 +33354,7 @@ function walkBlocks(blocks, add, ctx) {
33237
33354
  function collectExpressionIdentifiers2(expr, deep = false) {
33238
33355
  const deps = /* @__PURE__ */ new Set();
33239
33356
  const collect = (name) => deps.add(name);
33240
- walkExpression(expr, (name, _inFunctionBody) => collect(name), {
33357
+ walkExpression2(expr, (name, _inFunctionBody) => collect(name), {
33241
33358
  inFunctionBody: deep,
33242
33359
  shadowed: /* @__PURE__ */ new Set()
33243
33360
  });
package/dist/index.js CHANGED
@@ -14159,6 +14159,7 @@ var RUNTIME_HELPERS = {
14159
14159
  bindEvent: "bindEvent",
14160
14160
  callEventHandler: "callEventHandler",
14161
14161
  bindRef: "bindRef",
14162
+ spread: "spread",
14162
14163
  nonReactive: "nonReactive",
14163
14164
  toNodeArray: "toNodeArray",
14164
14165
  template: "template",
@@ -14216,6 +14217,7 @@ var RUNTIME_ALIASES = {
14216
14217
  bindEvent: "bindEvent",
14217
14218
  callEventHandler: "callEventHandler",
14218
14219
  bindRef: "bindRef",
14220
+ spread: "spread",
14219
14221
  nonReactive: "nonReactive",
14220
14222
  toNodeArray: "toNodeArray",
14221
14223
  template: "template",
@@ -22601,138 +22603,212 @@ function emitConditionalChild(startMarkerId, endMarkerId, expr, statements, ctx,
22601
22603
  );
22602
22604
  }
22603
22605
 
22604
- // src/ir/codegen-expression-deps.ts
22605
- function getMemberDependencyPath(expr) {
22606
- if (expr.kind === "MemberExpression") {
22607
- const prop = expr.property;
22608
- let propName;
22609
- if (!expr.computed && prop.kind === "Identifier") {
22610
- propName = prop.name;
22611
- } else if (prop.kind === "Literal" && typeof prop.value === "string") {
22612
- propName = prop.value;
22613
- }
22614
- if (!propName) return void 0;
22615
- const object = expr.object;
22616
- if (object.kind === "Identifier") {
22617
- return `${deSSAVarName(object.name)}.${propName}`;
22618
- }
22619
- if (object.kind === "MemberExpression") {
22620
- const parent = getMemberDependencyPath(object);
22621
- return parent ? `${parent}.${propName}` : void 0;
22622
- }
22606
+ // src/ir/walk-expression.ts
22607
+ function assertNever(value) {
22608
+ throw new Error(`Unhandled node in walkExpression: ${JSON.stringify(value)}`);
22609
+ }
22610
+ function walkTerminator(term, visitNode, inFunctionBody) {
22611
+ switch (term.kind) {
22612
+ case "Return":
22613
+ if (term.argument) visitNode(term.argument, null, inFunctionBody);
22614
+ return;
22615
+ case "Throw":
22616
+ visitNode(term.argument, null, inFunctionBody);
22617
+ return;
22618
+ case "Branch":
22619
+ visitNode(term.test, null, inFunctionBody);
22620
+ return;
22621
+ case "Switch":
22622
+ visitNode(term.discriminant, null, inFunctionBody);
22623
+ term.cases.forEach((c) => {
22624
+ if (c.test) visitNode(c.test, null, inFunctionBody);
22625
+ });
22626
+ return;
22627
+ case "ForOf":
22628
+ visitNode(term.iterable, null, inFunctionBody);
22629
+ return;
22630
+ case "ForIn":
22631
+ visitNode(term.object, null, inFunctionBody);
22632
+ return;
22633
+ case "Jump":
22634
+ case "Unreachable":
22635
+ case "Break":
22636
+ case "Continue":
22637
+ case "Try":
22638
+ return;
22639
+ default:
22640
+ assertNever(term);
22623
22641
  }
22624
- return void 0;
22625
22642
  }
22626
- function collectBlockDependencies(blocks, deps) {
22643
+ function walkInstruction(instr, visitNode, inFunctionBody) {
22644
+ switch (instr.kind) {
22645
+ case "Assign":
22646
+ case "Expression":
22647
+ visitNode(instr.value, null, inFunctionBody);
22648
+ return;
22649
+ case "Phi":
22650
+ instr.sources.forEach((source) => visitNode(source.id, null, inFunctionBody));
22651
+ return;
22652
+ default:
22653
+ assertNever(instr);
22654
+ }
22655
+ }
22656
+ function walkBlocks(blocks, visitNode, inFunctionBody) {
22627
22657
  for (const block of blocks) {
22628
- for (const instr of block.instructions) {
22629
- switch (instr.kind) {
22630
- case "Assign":
22631
- case "Expression":
22632
- collectExpressionDependencies(instr.value, deps);
22633
- break;
22634
- case "Phi":
22635
- for (const source of instr.sources) {
22636
- deps.add(deSSAVarName(source.id.name));
22658
+ block.instructions.forEach((instr) => walkInstruction(instr, visitNode, inFunctionBody));
22659
+ walkTerminator(block.terminator, visitNode, inFunctionBody);
22660
+ }
22661
+ }
22662
+ function walkExpression(expr, visit, options = {}) {
22663
+ const includeFunctionBodies = options.includeFunctionBodies ?? true;
22664
+ const visitNode = (node, parent, inFunctionBody) => {
22665
+ visit(node, { parent, inFunctionBody });
22666
+ switch (node.kind) {
22667
+ case "Identifier":
22668
+ case "Literal":
22669
+ case "MetaProperty":
22670
+ case "ThisExpression":
22671
+ case "SuperExpression":
22672
+ return;
22673
+ case "ImportExpression":
22674
+ visitNode(node.source, node, inFunctionBody);
22675
+ return;
22676
+ case "CallExpression":
22677
+ case "OptionalCallExpression":
22678
+ visitNode(node.callee, node, inFunctionBody);
22679
+ node.arguments.forEach((arg) => visitNode(arg, node, inFunctionBody));
22680
+ return;
22681
+ case "MemberExpression":
22682
+ case "OptionalMemberExpression":
22683
+ visitNode(node.object, node, inFunctionBody);
22684
+ if (node.computed) {
22685
+ visitNode(node.property, node, inFunctionBody);
22686
+ }
22687
+ return;
22688
+ case "BinaryExpression":
22689
+ case "LogicalExpression":
22690
+ visitNode(node.left, node, inFunctionBody);
22691
+ visitNode(node.right, node, inFunctionBody);
22692
+ return;
22693
+ case "UnaryExpression":
22694
+ case "AwaitExpression":
22695
+ visitNode(node.argument, node, inFunctionBody);
22696
+ return;
22697
+ case "ConditionalExpression":
22698
+ visitNode(node.test, node, inFunctionBody);
22699
+ visitNode(node.consequent, node, inFunctionBody);
22700
+ visitNode(node.alternate, node, inFunctionBody);
22701
+ return;
22702
+ case "ArrayExpression":
22703
+ node.elements.forEach((el) => visitNode(el, node, inFunctionBody));
22704
+ return;
22705
+ case "ObjectExpression":
22706
+ node.properties.forEach((prop) => {
22707
+ if (prop.kind === "SpreadElement") {
22708
+ visitNode(prop.argument, node, inFunctionBody);
22709
+ } else {
22710
+ if (prop.computed) {
22711
+ visitNode(prop.key, node, inFunctionBody);
22712
+ }
22713
+ visitNode(prop.value, node, inFunctionBody);
22637
22714
  }
22638
- break;
22639
- default:
22640
- break;
22641
- }
22642
- }
22643
- const term = block.terminator;
22644
- switch (term.kind) {
22645
- case "Return":
22646
- if (term.argument) collectExpressionDependencies(term.argument, deps);
22647
- break;
22648
- case "Throw":
22649
- collectExpressionDependencies(term.argument, deps);
22650
- break;
22651
- case "Branch":
22652
- collectExpressionDependencies(term.test, deps);
22653
- break;
22654
- case "Switch":
22655
- collectExpressionDependencies(term.discriminant, deps);
22656
- for (const c of term.cases) {
22657
- if (c.test) collectExpressionDependencies(c.test, deps);
22715
+ });
22716
+ return;
22717
+ case "JSXElement":
22718
+ if (typeof node.tagName !== "string") {
22719
+ visitNode(node.tagName, node, inFunctionBody);
22658
22720
  }
22659
- break;
22660
- case "ForOf":
22661
- collectExpressionDependencies(term.iterable, deps);
22662
- break;
22663
- case "ForIn":
22664
- collectExpressionDependencies(term.object, deps);
22665
- break;
22721
+ node.attributes.forEach((attr) => {
22722
+ if (attr.isSpread && attr.spreadExpr) {
22723
+ visitNode(attr.spreadExpr, node, inFunctionBody);
22724
+ } else if (attr.value) {
22725
+ visitNode(attr.value, node, inFunctionBody);
22726
+ }
22727
+ });
22728
+ node.children.forEach((child) => {
22729
+ if (child.kind === "expression") {
22730
+ visitNode(child.value, node, inFunctionBody);
22731
+ } else if (child.kind === "element") {
22732
+ visitNode(child.value, node, inFunctionBody);
22733
+ }
22734
+ });
22735
+ return;
22736
+ case "ArrowFunction":
22737
+ if (!includeFunctionBodies) return;
22738
+ if (node.isExpression && !Array.isArray(node.body)) {
22739
+ visitNode(node.body, node, true);
22740
+ } else if (Array.isArray(node.body)) {
22741
+ walkBlocks(node.body, visitNode, true);
22742
+ }
22743
+ return;
22744
+ case "FunctionExpression":
22745
+ if (!includeFunctionBodies) return;
22746
+ walkBlocks(node.body, visitNode, true);
22747
+ return;
22748
+ case "AssignmentExpression":
22749
+ visitNode(node.left, node, inFunctionBody);
22750
+ visitNode(node.right, node, inFunctionBody);
22751
+ return;
22752
+ case "UpdateExpression":
22753
+ visitNode(node.argument, node, inFunctionBody);
22754
+ return;
22755
+ case "TemplateLiteral":
22756
+ node.expressions.forEach((item) => visitNode(item, node, inFunctionBody));
22757
+ return;
22758
+ case "SpreadElement":
22759
+ visitNode(node.argument, node, inFunctionBody);
22760
+ return;
22761
+ case "NewExpression":
22762
+ visitNode(node.callee, node, inFunctionBody);
22763
+ node.arguments.forEach((arg) => visitNode(arg, node, inFunctionBody));
22764
+ return;
22765
+ case "SequenceExpression":
22766
+ node.expressions.forEach((item) => visitNode(item, node, inFunctionBody));
22767
+ return;
22768
+ case "YieldExpression":
22769
+ if (node.argument) {
22770
+ visitNode(node.argument, node, inFunctionBody);
22771
+ }
22772
+ return;
22773
+ case "TaggedTemplateExpression":
22774
+ visitNode(node.tag, node, inFunctionBody);
22775
+ node.quasi.expressions.forEach((item) => visitNode(item, node, inFunctionBody));
22776
+ return;
22777
+ case "ClassExpression":
22778
+ if (node.superClass) {
22779
+ visitNode(node.superClass, node, inFunctionBody);
22780
+ }
22781
+ return;
22666
22782
  default:
22667
- break;
22783
+ assertNever(node);
22668
22784
  }
22785
+ };
22786
+ visitNode(expr, null, false);
22787
+ }
22788
+
22789
+ // src/ir/codegen-expression-deps.ts
22790
+ function getMemberDependencyPath(expr) {
22791
+ if (expr.kind !== "MemberExpression" && expr.kind !== "OptionalMemberExpression") return void 0;
22792
+ const depPath = extractDependencyPath(expr);
22793
+ if (!depPath || depPath.segments.length === 0) return void 0;
22794
+ const base = deSSAVarName(depPath.base);
22795
+ if (depPath.segments.some((segment) => segment.computed)) {
22796
+ return base;
22669
22797
  }
22798
+ const tail = depPath.segments.map((segment) => segment.property).join(".");
22799
+ return tail ? `${base}.${tail}` : void 0;
22670
22800
  }
22671
22801
  function collectExpressionDependencies(expr, deps) {
22672
- if (expr.kind === "Identifier") {
22673
- deps.add(deSSAVarName(expr.name));
22674
- return;
22675
- }
22676
- if (expr.kind === "ArrowFunction") {
22677
- if (expr.isExpression && !Array.isArray(expr.body)) {
22678
- collectExpressionDependencies(expr.body, deps);
22679
- } else if (Array.isArray(expr.body)) {
22680
- collectBlockDependencies(expr.body, deps);
22802
+ walkExpression(expr, (node) => {
22803
+ if (node.kind === "Identifier") {
22804
+ deps.add(deSSAVarName(node.name));
22805
+ return;
22681
22806
  }
22682
- return;
22683
- }
22684
- if (expr.kind === "FunctionExpression") {
22685
- collectBlockDependencies(expr.body, deps);
22686
- return;
22687
- }
22688
- if (expr.kind === "MemberExpression") {
22689
- const path2 = getMemberDependencyPath(expr);
22690
- if (path2) deps.add(path2);
22691
- collectExpressionDependencies(expr.object, deps);
22692
- if (expr.computed && expr.property.kind !== "Literal") {
22693
- collectExpressionDependencies(expr.property, deps);
22807
+ const path2 = getMemberDependencyPath(node);
22808
+ if (path2) {
22809
+ deps.add(path2);
22694
22810
  }
22695
- return;
22696
- }
22697
- if (expr.kind === "CallExpression") {
22698
- collectExpressionDependencies(expr.callee, deps);
22699
- expr.arguments.forEach((a) => collectExpressionDependencies(a, deps));
22700
- return;
22701
- }
22702
- if (expr.kind === "BinaryExpression" || expr.kind === "LogicalExpression") {
22703
- collectExpressionDependencies(expr.left, deps);
22704
- collectExpressionDependencies(expr.right, deps);
22705
- return;
22706
- }
22707
- if (expr.kind === "ConditionalExpression") {
22708
- collectExpressionDependencies(expr.test, deps);
22709
- collectExpressionDependencies(expr.consequent, deps);
22710
- collectExpressionDependencies(expr.alternate, deps);
22711
- return;
22712
- }
22713
- if (expr.kind === "UnaryExpression") {
22714
- collectExpressionDependencies(expr.argument, deps);
22715
- return;
22716
- }
22717
- if (expr.kind === "ArrayExpression") {
22718
- expr.elements.forEach((el) => collectExpressionDependencies(el, deps));
22719
- return;
22720
- }
22721
- if (expr.kind === "ObjectExpression") {
22722
- expr.properties.forEach((p) => {
22723
- if (p.kind === "SpreadElement") {
22724
- collectExpressionDependencies(p.argument, deps);
22725
- } else {
22726
- if (p.computed) collectExpressionDependencies(p.key, deps);
22727
- collectExpressionDependencies(p.value, deps);
22728
- }
22729
- });
22730
- return;
22731
- }
22732
- if (expr.kind === "TemplateLiteral") {
22733
- expr.expressions.forEach((e) => collectExpressionDependencies(e, deps));
22734
- return;
22735
- }
22811
+ });
22736
22812
  }
22737
22813
 
22738
22814
  // src/ir/codegen-reactive-kind.ts
@@ -26110,8 +26186,31 @@ function extractHIRStaticHtml(jsx, ctx, ops, parentPath = [], namespace = null)
26110
26186
  const resolvedNamespace = resolveNamespaceContext(tagName, namespace);
26111
26187
  let html = `<${tagName}`;
26112
26188
  const bindings = [];
26113
- for (const attr of jsx.attributes) {
26189
+ for (let attrIndex = 0; attrIndex < jsx.attributes.length; attrIndex++) {
26190
+ const attr = jsx.attributes[attrIndex];
26114
26191
  if (attr.isSpread) {
26192
+ if (attr.spreadExpr) {
26193
+ const excluded = /* @__PURE__ */ new Set();
26194
+ for (let nextIndex = attrIndex + 1; nextIndex < jsx.attributes.length; nextIndex++) {
26195
+ const nextAttr = jsx.attributes[nextIndex];
26196
+ if (nextAttr.isSpread) continue;
26197
+ let nextName = normalizeHIRAttrName(nextAttr.name);
26198
+ if (nextName.endsWith("$")) {
26199
+ nextName = nextName.slice(0, -1);
26200
+ }
26201
+ if (nextName === "key") continue;
26202
+ excluded.add(nextName);
26203
+ if (nextName !== nextAttr.name) {
26204
+ excluded.add(nextAttr.name);
26205
+ }
26206
+ }
26207
+ bindings.push({
26208
+ type: "spread",
26209
+ path: [...parentPath],
26210
+ expr: attr.spreadExpr,
26211
+ exclude: excluded.size > 0 ? Array.from(excluded) : void 0
26212
+ });
26213
+ }
26115
26214
  continue;
26116
26215
  }
26117
26216
  let name = normalizeHIRAttrName(attr.name);
@@ -28296,10 +28395,28 @@ function lowerIntrinsicElement(jsx, ctx) {
28296
28395
  )
28297
28396
  );
28298
28397
  }
28398
+ fusedPatchGroups.clear();
28299
28399
  };
28300
28400
  for (const binding of bindings) {
28301
28401
  const targetId = resolveHIRBindingPath(binding.path, nodeCache, statements, ctx, genTemp3);
28302
- if (binding.type === "event" && binding.expr && binding.name) {
28402
+ if (binding.type === "spread" && binding.expr) {
28403
+ flushFusedPatchGroups();
28404
+ ctx.helpersUsed.add("spread");
28405
+ const spreadValueExpr = lowerDomExpression(binding.expr, ctx, containingRegion);
28406
+ const spreadGetter = t4.arrowFunctionExpression([], spreadValueExpr);
28407
+ const spreadArgs = [
28408
+ targetId,
28409
+ spreadGetter,
28410
+ t4.booleanLiteral(Boolean(isSVG || isMathML)),
28411
+ t4.booleanLiteral(true)
28412
+ ];
28413
+ if (binding.exclude && binding.exclude.length > 0) {
28414
+ spreadArgs.push(t4.arrayExpression(binding.exclude.map((name) => t4.stringLiteral(name))));
28415
+ }
28416
+ statements.push(
28417
+ t4.expressionStatement(t4.callExpression(t4.identifier(RUNTIME_ALIASES.spread), spreadArgs))
28418
+ );
28419
+ } else if (binding.type === "event" && binding.expr && binding.name) {
28303
28420
  const eventName = binding.name;
28304
28421
  const hasEventOptions = binding.eventOptions && (binding.eventOptions.capture || binding.eventOptions.passive || binding.eventOptions.once);
28305
28422
  const isDelegated = DelegatedEvents.has(eventName) && !hasEventOptions;
@@ -33087,106 +33204,106 @@ function collectUsesFromTerminator(term, add, inFunctionBody = false) {
33087
33204
  }
33088
33205
  }
33089
33206
  function collectUsesFromExpression(expr, add, inFunctionBody = false) {
33090
- walkExpression(expr, add, { inFunctionBody, shadowed: /* @__PURE__ */ new Set() });
33207
+ walkExpression2(expr, add, { inFunctionBody, shadowed: /* @__PURE__ */ new Set() });
33091
33208
  }
33092
- function walkExpression(expr, add, ctx) {
33209
+ function walkExpression2(expr, add, ctx) {
33093
33210
  switch (expr.kind) {
33094
33211
  case "Identifier":
33095
33212
  if (!ctx.shadowed.has(expr.name)) add(expr.name, ctx.inFunctionBody);
33096
33213
  return;
33097
33214
  case "CallExpression":
33098
33215
  case "OptionalCallExpression":
33099
- walkExpression(expr.callee, add, ctx);
33100
- expr.arguments.forEach((arg) => walkExpression(arg, add, ctx));
33216
+ walkExpression2(expr.callee, add, ctx);
33217
+ expr.arguments.forEach((arg) => walkExpression2(arg, add, ctx));
33101
33218
  return;
33102
33219
  case "MemberExpression":
33103
33220
  case "OptionalMemberExpression":
33104
- walkExpression(expr.object, add, ctx);
33105
- if (expr.computed) walkExpression(expr.property, add, ctx);
33221
+ walkExpression2(expr.object, add, ctx);
33222
+ if (expr.computed) walkExpression2(expr.property, add, ctx);
33106
33223
  return;
33107
33224
  case "BinaryExpression":
33108
33225
  case "LogicalExpression":
33109
- walkExpression(expr.left, add, ctx);
33110
- walkExpression(expr.right, add, ctx);
33226
+ walkExpression2(expr.left, add, ctx);
33227
+ walkExpression2(expr.right, add, ctx);
33111
33228
  return;
33112
33229
  case "UnaryExpression":
33113
- walkExpression(expr.argument, add, ctx);
33230
+ walkExpression2(expr.argument, add, ctx);
33114
33231
  return;
33115
33232
  case "ConditionalExpression":
33116
- walkExpression(expr.test, add, ctx);
33117
- walkExpression(expr.consequent, add, ctx);
33118
- walkExpression(expr.alternate, add, ctx);
33233
+ walkExpression2(expr.test, add, ctx);
33234
+ walkExpression2(expr.consequent, add, ctx);
33235
+ walkExpression2(expr.alternate, add, ctx);
33119
33236
  return;
33120
33237
  case "ArrayExpression":
33121
33238
  expr.elements.forEach((el) => {
33122
- if (el) walkExpression(el, add, ctx);
33239
+ if (el) walkExpression2(el, add, ctx);
33123
33240
  });
33124
33241
  return;
33125
33242
  case "ObjectExpression":
33126
33243
  expr.properties.forEach((prop) => {
33127
33244
  if (prop.kind === "SpreadElement") {
33128
- walkExpression(prop.argument, add, ctx);
33245
+ walkExpression2(prop.argument, add, ctx);
33129
33246
  } else {
33130
- if (prop.computed) walkExpression(prop.key, add, ctx);
33131
- walkExpression(prop.value, add, ctx);
33247
+ if (prop.computed) walkExpression2(prop.key, add, ctx);
33248
+ walkExpression2(prop.value, add, ctx);
33132
33249
  }
33133
33250
  });
33134
33251
  return;
33135
33252
  case "TemplateLiteral":
33136
- expr.expressions.forEach((e) => walkExpression(e, add, ctx));
33253
+ expr.expressions.forEach((e) => walkExpression2(e, add, ctx));
33137
33254
  return;
33138
33255
  case "SpreadElement":
33139
- walkExpression(expr.argument, add, ctx);
33256
+ walkExpression2(expr.argument, add, ctx);
33140
33257
  return;
33141
33258
  case "SequenceExpression":
33142
- expr.expressions.forEach((e) => walkExpression(e, add, ctx));
33259
+ expr.expressions.forEach((e) => walkExpression2(e, add, ctx));
33143
33260
  return;
33144
33261
  case "AwaitExpression":
33145
- walkExpression(expr.argument, add, ctx);
33262
+ walkExpression2(expr.argument, add, ctx);
33146
33263
  return;
33147
33264
  case "NewExpression":
33148
- walkExpression(expr.callee, add, ctx);
33149
- expr.arguments.forEach((arg) => walkExpression(arg, add, ctx));
33265
+ walkExpression2(expr.callee, add, ctx);
33266
+ expr.arguments.forEach((arg) => walkExpression2(arg, add, ctx));
33150
33267
  return;
33151
33268
  case "ArrowFunction": {
33152
33269
  const shadowed = new Set(ctx.shadowed);
33153
33270
  expr.params.forEach((p) => shadowed.add(p.name));
33154
33271
  if (expr.isExpression) {
33155
- walkExpression(expr.body, add, { inFunctionBody: true, shadowed });
33272
+ walkExpression2(expr.body, add, { inFunctionBody: true, shadowed });
33156
33273
  return;
33157
33274
  }
33158
- walkBlocks(expr.body, add, { inFunctionBody: true, shadowed });
33275
+ walkBlocks2(expr.body, add, { inFunctionBody: true, shadowed });
33159
33276
  return;
33160
33277
  }
33161
33278
  case "FunctionExpression": {
33162
33279
  const shadowed = new Set(ctx.shadowed);
33163
33280
  expr.params.forEach((p) => shadowed.add(p.name));
33164
- walkBlocks(expr.body, add, { inFunctionBody: true, shadowed });
33281
+ walkBlocks2(expr.body, add, { inFunctionBody: true, shadowed });
33165
33282
  return;
33166
33283
  }
33167
33284
  case "AssignmentExpression":
33168
- walkExpression(expr.left, add, ctx);
33169
- walkExpression(expr.right, add, ctx);
33285
+ walkExpression2(expr.left, add, ctx);
33286
+ walkExpression2(expr.right, add, ctx);
33170
33287
  return;
33171
33288
  case "UpdateExpression":
33172
- walkExpression(expr.argument, add, ctx);
33289
+ walkExpression2(expr.argument, add, ctx);
33173
33290
  return;
33174
33291
  case "JSXElement":
33175
33292
  if (typeof expr.tagName !== "string") {
33176
- walkExpression(expr.tagName, add, ctx);
33293
+ walkExpression2(expr.tagName, add, ctx);
33177
33294
  }
33178
33295
  expr.attributes.forEach((attr) => {
33179
33296
  if (attr.isSpread && attr.spreadExpr) {
33180
- walkExpression(attr.spreadExpr, add, ctx);
33297
+ walkExpression2(attr.spreadExpr, add, ctx);
33181
33298
  } else if (attr.value) {
33182
- walkExpression(attr.value, add, ctx);
33299
+ walkExpression2(attr.value, add, ctx);
33183
33300
  }
33184
33301
  });
33185
33302
  expr.children.forEach((child) => {
33186
33303
  if (child.kind === "expression") {
33187
- walkExpression(child.value, add, ctx);
33304
+ walkExpression2(child.value, add, ctx);
33188
33305
  } else if (child.kind === "element") {
33189
- walkExpression(child.value, add, ctx);
33306
+ walkExpression2(child.value, add, ctx);
33190
33307
  }
33191
33308
  });
33192
33309
  return;
@@ -33194,16 +33311,16 @@ function walkExpression(expr, add, ctx) {
33194
33311
  return;
33195
33312
  }
33196
33313
  }
33197
- function walkBlocks(blocks, add, ctx) {
33314
+ function walkBlocks2(blocks, add, ctx) {
33198
33315
  for (const block of blocks) {
33199
33316
  for (const instr of block.instructions) {
33200
33317
  if (instr.kind === "Assign") {
33201
- walkExpression(instr.value, add, ctx);
33318
+ walkExpression2(instr.value, add, ctx);
33202
33319
  if (instr.declarationKind) {
33203
33320
  ctx.shadowed.add(instr.target.name);
33204
33321
  }
33205
33322
  } else if (instr.kind === "Expression") {
33206
- walkExpression(instr.value, add, ctx);
33323
+ walkExpression2(instr.value, add, ctx);
33207
33324
  } else if (instr.kind === "Phi") {
33208
33325
  instr.sources.forEach((src) => {
33209
33326
  if (!ctx.shadowed.has(src.id.name)) add(src.id.name, ctx.inFunctionBody);
@@ -33222,7 +33339,7 @@ function walkBlocks(blocks, add, ctx) {
33222
33339
  function collectExpressionIdentifiers2(expr, deep = false) {
33223
33340
  const deps = /* @__PURE__ */ new Set();
33224
33341
  const collect = (name) => deps.add(name);
33225
- walkExpression(expr, (name, _inFunctionBody) => collect(name), {
33342
+ walkExpression2(expr, (name, _inFunctionBody) => collect(name), {
33226
33343
  inFunctionBody: deep,
33227
33344
  shadowed: /* @__PURE__ */ new Set()
33228
33345
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fictjs/compiler",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "Babel plugin for Fict Compiler",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -48,7 +48,7 @@
48
48
  "@types/babel__helper-plugin-utils": "^7.10.3",
49
49
  "@types/babel__traverse": "^7.28.0",
50
50
  "tsup": "^8.5.1",
51
- "@fictjs/runtime": "0.14.0"
51
+ "@fictjs/runtime": "0.15.0"
52
52
  },
53
53
  "scripts": {
54
54
  "build": "tsup src/index.ts --format cjs,esm --dts",