@fictjs/compiler 0.0.14 → 0.1.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.
Files changed (3) hide show
  1. package/dist/index.cjs +515 -193
  2. package/dist/index.js +515 -193
  3. package/package.json +2 -2
package/dist/index.cjs CHANGED
@@ -15559,6 +15559,17 @@ function processStatement(stmt, bb, jumpTarget, ctx) {
15559
15559
  }
15560
15560
  function convertExpression(node) {
15561
15561
  const loc = getLoc(node);
15562
+ const convertCallArguments = (args) => args.map((arg) => {
15563
+ if (t.isSpreadElement(arg)) {
15564
+ return {
15565
+ kind: "SpreadElement",
15566
+ argument: convertExpression(arg.argument),
15567
+ loc: getLoc(arg)
15568
+ };
15569
+ }
15570
+ if (t.isExpression(arg)) return convertExpression(arg);
15571
+ return void 0;
15572
+ }).filter(Boolean);
15562
15573
  if (t.isIdentifier(node)) return { kind: "Identifier", name: node.name, loc };
15563
15574
  if (t.isStringLiteral(node) || t.isNumericLiteral(node) || t.isBooleanLiteral(node) || t.isNullLiteral(node))
15564
15575
  return { kind: "Literal", value: node.value ?? null, loc };
@@ -15566,7 +15577,7 @@ function convertExpression(node) {
15566
15577
  const call = {
15567
15578
  kind: "CallExpression",
15568
15579
  callee: convertExpression(node.callee),
15569
- arguments: node.arguments.map((arg) => t.isExpression(arg) ? convertExpression(arg) : void 0).filter(Boolean),
15580
+ arguments: convertCallArguments(node.arguments),
15570
15581
  loc
15571
15582
  };
15572
15583
  return call;
@@ -15846,7 +15857,7 @@ function convertExpression(node) {
15846
15857
  return {
15847
15858
  kind: "NewExpression",
15848
15859
  callee: convertExpression(node.callee),
15849
- arguments: node.arguments.map((arg) => t.isExpression(arg) ? convertExpression(arg) : void 0).filter(Boolean),
15860
+ arguments: convertCallArguments(node.arguments),
15850
15861
  loc
15851
15862
  };
15852
15863
  }
@@ -15869,7 +15880,7 @@ function convertExpression(node) {
15869
15880
  return {
15870
15881
  kind: "OptionalCallExpression",
15871
15882
  callee: convertExpression(node.callee),
15872
- arguments: node.arguments.map((arg) => t.isExpression(arg) ? convertExpression(arg) : void 0).filter(Boolean),
15883
+ arguments: convertCallArguments(node.arguments),
15873
15884
  optional: node.optional,
15874
15885
  loc
15875
15886
  };
@@ -16079,6 +16090,7 @@ var DiagnosticMessages = {
16079
16090
  ["FICT-P002" /* FICT_P002 */]: "Array rest in props destructuring falls back to non-reactive binding.",
16080
16091
  ["FICT-P003" /* FICT_P003 */]: "Computed property in props pattern cannot be made reactive.",
16081
16092
  ["FICT-P004" /* FICT_P004 */]: "Nested props destructuring falls back to non-reactive binding; access props directly or use prop.",
16093
+ ["FICT-P005" /* FICT_P005 */]: "Dynamic props spread may not stay reactive; consider explicit props or mergeProps(() => source).",
16082
16094
  ["FICT-S001" /* FICT_S001 */]: "State variable mutation detected outside component scope.",
16083
16095
  ["FICT-S002" /* FICT_S002 */]: "State variable escaped to external scope, may cause memory leaks.",
16084
16096
  ["FICT-E001" /* FICT_E001 */]: "Effect without reactive dependencies will run only once; consider adding state reads or removing the effect.",
@@ -16108,6 +16120,7 @@ var DiagnosticSeverities = {
16108
16120
  ["FICT-P002" /* FICT_P002 */]: "warning" /* Warning */,
16109
16121
  ["FICT-P003" /* FICT_P003 */]: "warning" /* Warning */,
16110
16122
  ["FICT-P004" /* FICT_P004 */]: "warning" /* Warning */,
16123
+ ["FICT-P005" /* FICT_P005 */]: "warning" /* Warning */,
16111
16124
  ["FICT-S001" /* FICT_S001 */]: "error" /* Error */,
16112
16125
  ["FICT-S002" /* FICT_S002 */]: "warning" /* Warning */,
16113
16126
  ["FICT-E001" /* FICT_E001 */]: "warning" /* Warning */,
@@ -16160,6 +16173,215 @@ function reportDiagnostic(ctx, code, node, context) {
16160
16173
  }
16161
16174
  }
16162
16175
 
16176
+ // src/ir/props-plan.ts
16177
+ function buildPropsPlan(attributes, children, ctx, helpers) {
16178
+ const { t: t2 } = ctx;
16179
+ const prevPropsContext = ctx.inPropsContext;
16180
+ ctx.inPropsContext = true;
16181
+ try {
16182
+ if (attributes.length === 0 && children.length === 0) return null;
16183
+ const segments = [];
16184
+ const flags = {
16185
+ needsMergeProps: false,
16186
+ hasLazySource: false
16187
+ };
16188
+ let bucket = [];
16189
+ const toPropKey = (name) => /^[a-zA-Z_$][\w$]*$/.test(name) ? t2.identifier(name) : t2.stringLiteral(name);
16190
+ const isAccessorName = (name) => (ctx.memoVars?.has(name) ?? false) || (ctx.signalVars?.has(name) ?? false) || (ctx.aliasVars?.has(name) ?? false);
16191
+ const isZeroArgFunction = (expr) => (t2.isArrowFunctionExpression(expr) || t2.isFunctionExpression(expr)) && expr.params.length === 0;
16192
+ const wrapAccessorSource = (node) => {
16193
+ if (t2.isCallExpression(node) && t2.isIdentifier(node.callee) && node.arguments.length === 0) {
16194
+ const baseName2 = helpers.deSSAVarName(node.callee.name);
16195
+ if (isAccessorName(baseName2)) {
16196
+ return t2.arrowFunctionExpression([], node);
16197
+ }
16198
+ }
16199
+ if (t2.isIdentifier(node)) {
16200
+ const baseName2 = helpers.deSSAVarName(node.name);
16201
+ if (isAccessorName(baseName2)) {
16202
+ return t2.arrowFunctionExpression([], t2.callExpression(t2.identifier(baseName2), []));
16203
+ }
16204
+ }
16205
+ return node;
16206
+ };
16207
+ const isAccessorSource = (expr) => {
16208
+ if (expr.kind === "Identifier") {
16209
+ return isAccessorName(helpers.deSSAVarName(expr.name));
16210
+ }
16211
+ if (expr.kind === "CallExpression" || expr.kind === "OptionalCallExpression") {
16212
+ if (expr.callee.kind === "Identifier" && expr.arguments.length === 0) {
16213
+ return isAccessorName(helpers.deSSAVarName(expr.callee.name));
16214
+ }
16215
+ }
16216
+ return false;
16217
+ };
16218
+ const isRuntimeMergeProps = () => !ctx.shadowedNames?.has(RUNTIME_ALIASES.mergeProps) && !ctx.localDeclaredNames?.has(RUNTIME_ALIASES.mergeProps) && (!ctx.moduleDeclaredNames?.has(RUNTIME_ALIASES.mergeProps) || (ctx.moduleRuntimeNames?.has(RUNTIME_ALIASES.mergeProps) ?? false));
16219
+ const isMergePropsCall = (expr) => expr.kind === "CallExpression" && expr.callee.kind === "Identifier" && expr.callee.name === RUNTIME_ALIASES.mergeProps && isRuntimeMergeProps();
16220
+ const isDynamicMemberSpread = (expr) => {
16221
+ if (expr.kind !== "MemberExpression" && expr.kind !== "OptionalMemberExpression") return false;
16222
+ if (expr.computed) return true;
16223
+ if (expr.kind === "OptionalMemberExpression" && expr.optional) return true;
16224
+ let current = expr;
16225
+ while (current.kind === "MemberExpression" || current.kind === "OptionalMemberExpression") {
16226
+ const obj = current.object;
16227
+ if (obj.kind === "CallExpression" || obj.kind === "OptionalCallExpression" || obj.kind === "ConditionalExpression" || obj.kind === "LogicalExpression" || obj.kind === "SequenceExpression" || obj.kind === "AssignmentExpression" || obj.kind === "UpdateExpression" || obj.kind === "AwaitExpression" || obj.kind === "NewExpression" || obj.kind === "YieldExpression") {
16228
+ return true;
16229
+ }
16230
+ if (obj.kind === "OptionalMemberExpression" && obj.optional) {
16231
+ return true;
16232
+ }
16233
+ if (obj.kind !== "MemberExpression" && obj.kind !== "OptionalMemberExpression") {
16234
+ return obj.kind !== "Identifier";
16235
+ }
16236
+ current = obj;
16237
+ }
16238
+ return false;
16239
+ };
16240
+ const isDynamicPropsSpread = (expr) => {
16241
+ if (isAccessorSource(expr) || isMergePropsCall(expr)) return false;
16242
+ if (expr.kind === "CallExpression" || expr.kind === "OptionalCallExpression" || expr.kind === "ConditionalExpression" || expr.kind === "LogicalExpression" || expr.kind === "SequenceExpression" || expr.kind === "AssignmentExpression" || expr.kind === "UpdateExpression" || expr.kind === "AwaitExpression" || expr.kind === "NewExpression" || expr.kind === "YieldExpression") {
16243
+ return true;
16244
+ }
16245
+ if (expr.kind === "MemberExpression" || expr.kind === "OptionalMemberExpression") {
16246
+ return isDynamicMemberSpread(expr);
16247
+ }
16248
+ if (expr.kind === "ObjectExpression") {
16249
+ return expr.properties.some((p) => p.kind === "SpreadElement");
16250
+ }
16251
+ return false;
16252
+ };
16253
+ const flushBucket = () => {
16254
+ if (bucket.length === 0) return;
16255
+ segments.push({ kind: "object", properties: bucket });
16256
+ bucket = [];
16257
+ };
16258
+ const pushSpread = (expr) => {
16259
+ flags.needsMergeProps = true;
16260
+ if (isZeroArgFunction(expr)) {
16261
+ flags.hasLazySource = true;
16262
+ }
16263
+ segments.push({ kind: "spread", expr });
16264
+ };
16265
+ for (const attr of attributes) {
16266
+ if (attr.isSpread && attr.spreadExpr) {
16267
+ flushBucket();
16268
+ if (isDynamicPropsSpread(attr.spreadExpr)) {
16269
+ reportDiagnostic(ctx, "FICT-P005" /* FICT_P005 */, attr.spreadExpr);
16270
+ }
16271
+ let spreadExpr = helpers.lowerDomExpression(attr.spreadExpr, ctx);
16272
+ if (t2.isCallExpression(spreadExpr) && t2.isIdentifier(spreadExpr.callee) && spreadExpr.callee.name === RUNTIME_ALIASES.mergeProps && isRuntimeMergeProps()) {
16273
+ const callExpr = spreadExpr;
16274
+ const rewrittenArgs = callExpr.arguments.map(
16275
+ (arg) => t2.isExpression(arg) ? wrapAccessorSource(arg) : arg
16276
+ );
16277
+ if (rewrittenArgs.some((arg, idx) => arg !== callExpr.arguments[idx])) {
16278
+ spreadExpr = t2.callExpression(
16279
+ callExpr.callee,
16280
+ rewrittenArgs
16281
+ );
16282
+ }
16283
+ const flattenArgs = [];
16284
+ let canFlatten = true;
16285
+ for (const arg of rewrittenArgs) {
16286
+ if (t2.isExpression(arg)) {
16287
+ flattenArgs.push(arg);
16288
+ } else {
16289
+ canFlatten = false;
16290
+ break;
16291
+ }
16292
+ }
16293
+ if (canFlatten) {
16294
+ for (const arg of flattenArgs) {
16295
+ pushSpread(arg);
16296
+ }
16297
+ continue;
16298
+ }
16299
+ }
16300
+ spreadExpr = wrapAccessorSource(spreadExpr);
16301
+ pushSpread(spreadExpr);
16302
+ continue;
16303
+ }
16304
+ if (attr.value) {
16305
+ const isFunctionLike = attr.value.kind === "ArrowFunction" || attr.value.kind === "FunctionExpression";
16306
+ const prevPropsCtx = ctx.inPropsContext;
16307
+ if (isFunctionLike) {
16308
+ ctx.inPropsContext = false;
16309
+ }
16310
+ const lowered = helpers.lowerDomExpression(attr.value, ctx);
16311
+ if (isFunctionLike) {
16312
+ ctx.inPropsContext = prevPropsCtx;
16313
+ }
16314
+ const baseIdent = attr.value.kind === "Identifier" ? helpers.deSSAVarName(attr.value.name) : void 0;
16315
+ const isAccessorBase = baseIdent && ((ctx.memoVars?.has(baseIdent) ?? false) || (ctx.signalVars?.has(baseIdent) ?? false) || (ctx.aliasVars?.has(baseIdent) ?? false));
16316
+ const isStoreBase = baseIdent ? ctx.storeVars?.has(baseIdent) ?? false : false;
16317
+ const alreadyGetter = isFunctionLike || (baseIdent ? isStoreBase || (ctx.memoVars?.has(baseIdent) ?? false) || (ctx.aliasVars?.has(baseIdent) ?? false) : false);
16318
+ const usesTracked = (!ctx.nonReactiveScopeDepth || ctx.nonReactiveScopeDepth === 0) && helpers.expressionUsesTracked(attr.value, ctx) && !alreadyGetter;
16319
+ const trackedExpr = usesTracked ? helpers.lowerTrackedExpression(
16320
+ attr.value,
16321
+ ctx
16322
+ ) : null;
16323
+ const useMemoProp = usesTracked && trackedExpr && t2.isExpression(trackedExpr) && !t2.isIdentifier(trackedExpr) && !t2.isMemberExpression(trackedExpr) && !t2.isLiteral(trackedExpr);
16324
+ const valueExpr = !isFunctionLike && isAccessorBase && baseIdent ? (() => {
16325
+ ctx.helpersUsed.add("propGetter");
16326
+ return t2.callExpression(t2.identifier(RUNTIME_ALIASES.propGetter), [
16327
+ t2.arrowFunctionExpression([], t2.callExpression(t2.identifier(baseIdent), []))
16328
+ ]);
16329
+ })() : usesTracked && t2.isExpression(lowered) ? (() => {
16330
+ if (useMemoProp) {
16331
+ ctx.helpersUsed.add("prop");
16332
+ return t2.callExpression(t2.identifier(RUNTIME_ALIASES.prop), [
16333
+ t2.arrowFunctionExpression([], trackedExpr ?? lowered)
16334
+ ]);
16335
+ }
16336
+ ctx.helpersUsed.add("propGetter");
16337
+ return t2.callExpression(t2.identifier(RUNTIME_ALIASES.propGetter), [
16338
+ t2.arrowFunctionExpression([], trackedExpr ?? lowered)
16339
+ ]);
16340
+ })() : lowered;
16341
+ bucket.push(t2.objectProperty(toPropKey(attr.name), valueExpr));
16342
+ continue;
16343
+ }
16344
+ bucket.push(t2.objectProperty(toPropKey(attr.name), t2.booleanLiteral(true)));
16345
+ }
16346
+ if (children.length === 1 && children[0]) {
16347
+ bucket.push(t2.objectProperty(t2.identifier("children"), children[0]));
16348
+ } else if (children.length > 1) {
16349
+ bucket.push(t2.objectProperty(t2.identifier("children"), t2.arrayExpression(children)));
16350
+ }
16351
+ flushBucket();
16352
+ if (segments.length === 0) return null;
16353
+ return { segments, flags };
16354
+ } finally {
16355
+ ctx.inPropsContext = prevPropsContext;
16356
+ }
16357
+ }
16358
+ function lowerPropsPlan(plan, ctx) {
16359
+ const { t: t2 } = ctx;
16360
+ const args = [];
16361
+ for (const segment of plan.segments) {
16362
+ if (segment.kind === "object") {
16363
+ if (segment.properties.length === 0) continue;
16364
+ args.push(t2.objectExpression(segment.properties));
16365
+ continue;
16366
+ }
16367
+ args.push(segment.expr);
16368
+ }
16369
+ if (args.length === 0) return null;
16370
+ if (!plan.flags.needsMergeProps) {
16371
+ return args[0] ?? null;
16372
+ }
16373
+ if (args.length === 1 && !plan.flags.hasLazySource) {
16374
+ return args[0];
16375
+ }
16376
+ ctx.helpersUsed.add("mergeProps");
16377
+ return t2.callExpression(t2.identifier(RUNTIME_ALIASES.mergeProps), args);
16378
+ }
16379
+ function buildPropsExpression(attributes, children, ctx, helpers) {
16380
+ const plan = buildPropsPlan(attributes, children, ctx, helpers);
16381
+ if (!plan) return null;
16382
+ return lowerPropsPlan(plan, ctx);
16383
+ }
16384
+
16163
16385
  // src/ir/ssa.ts
16164
16386
  function analyzeCFG(blocks) {
16165
16387
  const predecessors = computePredecessors(blocks);
@@ -16657,6 +16879,9 @@ function collectExprReads(expr, into, paths, bound = /* @__PURE__ */ new Set(),
16657
16879
  expr.arguments?.forEach((a) => collectExprReads(a, into, paths, bound));
16658
16880
  return;
16659
16881
  }
16882
+ case "SpreadElement":
16883
+ collectExprReads(expr.argument, into, paths, bound);
16884
+ return;
16660
16885
  case "MemberExpression":
16661
16886
  case "OptionalMemberExpression": {
16662
16887
  const depPath = extractDependencyPath(expr);
@@ -18151,11 +18376,15 @@ function containsJSXExpr(expr) {
18151
18376
  case "ArrayExpression":
18152
18377
  return expr.elements?.some((el) => containsJSXExpr(el)) ?? false;
18153
18378
  case "ObjectExpression":
18154
- return expr.properties?.some((p) => containsJSXExpr(p.value)) ?? false;
18379
+ return expr.properties?.some(
18380
+ (p) => p.kind === "SpreadElement" ? containsJSXExpr(p.argument) : containsJSXExpr(p.value)
18381
+ ) ?? false;
18155
18382
  case "ConditionalExpression":
18156
18383
  return containsJSXExpr(expr.consequent) || containsJSXExpr(expr.alternate);
18157
18384
  case "ArrowFunction":
18158
18385
  return containsJSXExpr(expr.body);
18386
+ case "SpreadElement":
18387
+ return containsJSXExpr(expr.argument);
18159
18388
  default:
18160
18389
  return false;
18161
18390
  }
@@ -18185,6 +18414,8 @@ function expressionUsesTracked(expr, ctx) {
18185
18414
  });
18186
18415
  case "TemplateLiteral":
18187
18416
  return expr.expressions.some((e) => expressionUsesTracked(e, ctx));
18417
+ case "SpreadElement":
18418
+ return expressionUsesTracked(expr.argument, ctx);
18188
18419
  default:
18189
18420
  return false;
18190
18421
  }
@@ -20231,6 +20462,9 @@ function collectCalledIdentifiers(fn) {
20231
20462
  function createCodegenContext(t2) {
20232
20463
  return {
20233
20464
  t: t2,
20465
+ moduleDeclaredNames: /* @__PURE__ */ new Set(),
20466
+ moduleRuntimeNames: /* @__PURE__ */ new Set(),
20467
+ localDeclaredNames: /* @__PURE__ */ new Set(),
20234
20468
  helpersUsed: /* @__PURE__ */ new Set(),
20235
20469
  tempCounter: 0,
20236
20470
  trackedVars: /* @__PURE__ */ new Set(),
@@ -21375,8 +21609,7 @@ function lowerTerminator(block, ctx) {
21375
21609
  return applyLoc([]);
21376
21610
  }
21377
21611
  }
21378
- function attachHelperImports(ctx, body, t2) {
21379
- if (ctx.helpersUsed.size === 0) return body;
21612
+ function collectDeclaredNames(body, t2) {
21380
21613
  const declared = /* @__PURE__ */ new Set();
21381
21614
  const addPatternNames = (pattern) => {
21382
21615
  if (t2.isIdentifier(pattern)) {
@@ -21450,6 +21683,78 @@ function attachHelperImports(ctx, body, t2) {
21450
21683
  declared.add(stmt.declaration.name);
21451
21684
  }
21452
21685
  }
21686
+ return declared;
21687
+ }
21688
+ function collectRuntimeImportNames(body, t2) {
21689
+ const runtimeModules = /* @__PURE__ */ new Set([RUNTIME_MODULE, "@fictjs/runtime", "fict"]);
21690
+ const imported = /* @__PURE__ */ new Set();
21691
+ for (const stmt of body) {
21692
+ if (!t2.isImportDeclaration(stmt)) continue;
21693
+ if (!runtimeModules.has(stmt.source.value)) continue;
21694
+ for (const spec of stmt.specifiers) {
21695
+ imported.add(spec.local.name);
21696
+ }
21697
+ }
21698
+ return imported;
21699
+ }
21700
+ function collectLocalDeclaredNames(params, blocks, t2) {
21701
+ const declared = /* @__PURE__ */ new Set();
21702
+ const addPatternNames = (pattern) => {
21703
+ if (t2.isIdentifier(pattern)) {
21704
+ declared.add(deSSAVarName(pattern.name));
21705
+ return;
21706
+ }
21707
+ if (t2.isAssignmentPattern(pattern)) {
21708
+ addPatternNames(pattern.left);
21709
+ return;
21710
+ }
21711
+ if (t2.isRestElement(pattern)) {
21712
+ addPatternNames(pattern.argument);
21713
+ return;
21714
+ }
21715
+ if (t2.isObjectPattern(pattern)) {
21716
+ for (const prop of pattern.properties) {
21717
+ if (t2.isRestElement(prop)) {
21718
+ addPatternNames(prop.argument);
21719
+ } else if (t2.isObjectProperty(prop)) {
21720
+ addPatternNames(prop.value);
21721
+ }
21722
+ }
21723
+ return;
21724
+ }
21725
+ if (t2.isArrayPattern(pattern)) {
21726
+ for (const el of pattern.elements) {
21727
+ if (!el) continue;
21728
+ if (t2.isPatternLike(el)) addPatternNames(el);
21729
+ }
21730
+ }
21731
+ };
21732
+ params.forEach((param) => declared.add(deSSAVarName(param.name)));
21733
+ if (!blocks) return declared;
21734
+ for (const block of blocks) {
21735
+ for (const instr of block.instructions) {
21736
+ if (instr.kind !== "Assign") continue;
21737
+ const target = deSSAVarName(instr.target.name);
21738
+ const isFunctionDecl = instr.value.kind === "FunctionExpression" && !!instr.value.name && deSSAVarName(instr.value.name) === target;
21739
+ if (instr.declarationKind || isFunctionDecl) {
21740
+ declared.add(target);
21741
+ }
21742
+ }
21743
+ const term = block.terminator;
21744
+ if (term.kind === "ForOf" || term.kind === "ForIn") {
21745
+ declared.add(deSSAVarName(term.variable));
21746
+ if (term.pattern) {
21747
+ addPatternNames(term.pattern);
21748
+ }
21749
+ } else if (term.kind === "Try" && term.catchParam) {
21750
+ declared.add(deSSAVarName(term.catchParam));
21751
+ }
21752
+ }
21753
+ return declared;
21754
+ }
21755
+ function attachHelperImports(ctx, body, t2) {
21756
+ if (ctx.helpersUsed.size === 0) return body;
21757
+ const declared = collectDeclaredNames(body, t2);
21453
21758
  const specifiers = [];
21454
21759
  for (const name of ctx.helpersUsed) {
21455
21760
  const alias = RUNTIME_ALIASES[name];
@@ -21519,11 +21824,21 @@ function lowerExpression(expr, ctx, isAssigned = false) {
21519
21824
  function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21520
21825
  const { t: t2 } = ctx;
21521
21826
  const mapParams = (params) => params.map((p) => t2.identifier(deSSAVarName(p.name)));
21522
- const withFunctionScope = (paramNames, fn) => {
21827
+ const lowerArgsAsExpressions = (args) => args.map(
21828
+ (arg) => arg.kind === "SpreadElement" ? lowerExpression(arg.argument, ctx) : lowerExpression(arg, ctx)
21829
+ );
21830
+ const lowerCallArguments = (args, mapArg) => args.map((arg, idx) => {
21831
+ if (arg.kind === "SpreadElement") {
21832
+ return t2.spreadElement(lowerExpression(arg.argument, ctx));
21833
+ }
21834
+ return mapArg ? mapArg(arg, idx) : lowerExpression(arg, ctx);
21835
+ });
21836
+ const withFunctionScope = (paramNames, fn, localDeclared) => {
21523
21837
  const prevTracked = ctx.trackedVars;
21524
21838
  const prevAlias = ctx.aliasVars;
21525
21839
  const prevExternal = ctx.externalTracked;
21526
21840
  const prevShadowed = ctx.shadowedNames;
21841
+ const prevLocalDeclared = ctx.localDeclaredNames;
21527
21842
  const scoped = new Set(ctx.trackedVars);
21528
21843
  paramNames.forEach((n) => scoped.delete(deSSAVarName(n)));
21529
21844
  ctx.trackedVars = scoped;
@@ -21532,11 +21847,19 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21532
21847
  const shadowed = new Set(prevShadowed ?? []);
21533
21848
  paramNames.forEach((n) => shadowed.add(deSSAVarName(n)));
21534
21849
  ctx.shadowedNames = shadowed;
21850
+ const localNames = new Set(prevLocalDeclared ?? []);
21851
+ if (localDeclared) {
21852
+ for (const name of localDeclared) {
21853
+ localNames.add(deSSAVarName(name));
21854
+ }
21855
+ }
21856
+ ctx.localDeclaredNames = localNames;
21535
21857
  const result = fn();
21536
21858
  ctx.trackedVars = prevTracked;
21537
21859
  ctx.aliasVars = prevAlias;
21538
21860
  ctx.externalTracked = prevExternal;
21539
21861
  ctx.shadowedNames = prevShadowed;
21862
+ ctx.localDeclaredNames = prevLocalDeclared;
21540
21863
  return result;
21541
21864
  };
21542
21865
  const lowerBlocksToStatements = (blocks) => {
@@ -21598,7 +21921,7 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21598
21921
  ctx.needsCtx = true;
21599
21922
  return t2.callExpression(t2.identifier(RUNTIME_ALIASES.useSignal), [
21600
21923
  t2.identifier("__fictCtx"),
21601
- ...expr.arguments.map((a) => lowerExpression(a, ctx))
21924
+ ...lowerCallArguments(expr.arguments)
21602
21925
  ]);
21603
21926
  }
21604
21927
  if (expr.callee.kind === "Identifier" && expr.callee.name === "$effect") {
@@ -21606,14 +21929,15 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21606
21929
  ctx.needsCtx = true;
21607
21930
  return t2.callExpression(t2.identifier(RUNTIME_ALIASES.useEffect), [
21608
21931
  t2.identifier("__fictCtx"),
21609
- ...expr.arguments.map(
21932
+ ...lowerCallArguments(
21933
+ expr.arguments,
21610
21934
  (arg) => arg.kind === "ArrowFunction" || arg.kind === "FunctionExpression" ? withNonReactiveScope(ctx, () => lowerExpression(arg, ctx)) : lowerExpression(arg, ctx)
21611
21935
  )
21612
21936
  ]);
21613
21937
  }
21614
21938
  if (expr.callee.kind === "Identifier" && expr.callee.name === "__forOf") {
21615
21939
  ctx.needsForOfHelper = true;
21616
- const [iterable, cb] = expr.arguments.map((a) => lowerExpression(a, ctx));
21940
+ const [iterable, cb] = lowerArgsAsExpressions(expr.arguments);
21617
21941
  return t2.callExpression(t2.identifier("__fictForOf"), [
21618
21942
  iterable ?? t2.identifier("undefined"),
21619
21943
  cb ?? t2.arrowFunctionExpression([], t2.identifier("undefined"))
@@ -21621,7 +21945,7 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21621
21945
  }
21622
21946
  if (expr.callee.kind === "Identifier" && expr.callee.name === "__forIn") {
21623
21947
  ctx.needsForInHelper = true;
21624
- const [obj, cb] = expr.arguments.map((a) => lowerExpression(a, ctx));
21948
+ const [obj, cb] = lowerArgsAsExpressions(expr.arguments);
21625
21949
  return t2.callExpression(t2.identifier("__fictForIn"), [
21626
21950
  obj ?? t2.identifier("undefined"),
21627
21951
  cb ?? t2.arrowFunctionExpression([], t2.identifier("undefined"))
@@ -21629,12 +21953,12 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21629
21953
  }
21630
21954
  if (expr.callee.kind === "Identifier" && expr.callee.name === "__fictPropsRest") {
21631
21955
  ctx.helpersUsed.add("propsRest");
21632
- const args = expr.arguments.map((a) => lowerExpression(a, ctx));
21956
+ const args = lowerCallArguments(expr.arguments);
21633
21957
  return t2.callExpression(t2.identifier(RUNTIME_ALIASES.propsRest), args);
21634
21958
  }
21635
21959
  if (expr.callee.kind === "Identifier" && expr.callee.name === "mergeProps") {
21636
21960
  ctx.helpersUsed.add("mergeProps");
21637
- const args = expr.arguments.map((a) => lowerExpression(a, ctx));
21961
+ const args = lowerCallArguments(expr.arguments);
21638
21962
  return t2.callExpression(t2.identifier(RUNTIME_ALIASES.mergeProps), args);
21639
21963
  }
21640
21964
  const isIIFE = (expr.callee.kind === "ArrowFunction" || expr.callee.kind === "FunctionExpression") && expr.arguments.length === 0 && expr.callee.params.length === 0;
@@ -21642,7 +21966,7 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21642
21966
  const calleeIsMemoAccessor = !!calleeName && ctx.memoVars?.has(calleeName);
21643
21967
  const calleeIsSignalLike = !!calleeName && (ctx.signalVars?.has(calleeName) || ctx.storeVars?.has(calleeName));
21644
21968
  if (calleeIsMemoAccessor && !calleeIsSignalLike && expr.arguments.length > 0) {
21645
- const loweredArgs2 = expr.arguments.map((a) => lowerExpression(a, ctx));
21969
+ const loweredArgs2 = lowerCallArguments(expr.arguments);
21646
21970
  return t2.callExpression(t2.callExpression(t2.identifier(calleeName), []), loweredArgs2);
21647
21971
  }
21648
21972
  const lowerCallee = () => isIIFE ? withNonReactiveScope(ctx, () => lowerExpression(expr.callee, ctx)) : lowerExpression(expr.callee, ctx);
@@ -21651,7 +21975,7 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21651
21975
  ) || expr.callee.property.kind === "Literal" && ["map", "reduce", "forEach", "filter", "flatMap", "some", "every", "find"].includes(
21652
21976
  String(expr.callee.property.value)
21653
21977
  ));
21654
- const loweredArgs = expr.arguments.map((a, idx) => {
21978
+ const loweredArgs = lowerCallArguments(expr.arguments, (a, idx) => {
21655
21979
  if (idx === 0 && isIteratingMethod && (a.kind === "ArrowFunction" || a.kind === "FunctionExpression")) {
21656
21980
  return withNoMemoAndDynamicHooks(ctx, () => lowerExpression(a, ctx));
21657
21981
  }
@@ -21757,67 +22081,81 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21757
22081
  case "ArrowFunction": {
21758
22082
  const paramIds = mapParams(expr.params);
21759
22083
  const shadowed = new Set(expr.params.map((p) => deSSAVarName(p.name)));
22084
+ const localDeclared = collectLocalDeclaredNames(
22085
+ expr.params,
22086
+ Array.isArray(expr.body) ? expr.body : null,
22087
+ t2
22088
+ );
21760
22089
  return withNonReactiveScope(
21761
22090
  ctx,
21762
- () => withFunctionScope(shadowed, () => {
21763
- let fn;
21764
- if (expr.isExpression && !Array.isArray(expr.body)) {
21765
- const { result: bodyExpr, cacheDeclarations } = withGetterCache(
21766
- ctx,
21767
- () => lowerTrackedExpression(expr.body, ctx)
21768
- );
21769
- if (cacheDeclarations.length > 0) {
22091
+ () => withFunctionScope(
22092
+ shadowed,
22093
+ () => {
22094
+ let fn;
22095
+ if (expr.isExpression && !Array.isArray(expr.body)) {
22096
+ const { result: bodyExpr, cacheDeclarations } = withGetterCache(
22097
+ ctx,
22098
+ () => lowerTrackedExpression(expr.body, ctx)
22099
+ );
22100
+ if (cacheDeclarations.length > 0) {
22101
+ fn = t2.arrowFunctionExpression(
22102
+ paramIds,
22103
+ t2.blockStatement([...cacheDeclarations, t2.returnStatement(bodyExpr)])
22104
+ );
22105
+ } else {
22106
+ fn = t2.arrowFunctionExpression(paramIds, bodyExpr);
22107
+ }
22108
+ } else if (Array.isArray(expr.body)) {
22109
+ const { result: stmts, cacheDeclarations } = withGetterCache(
22110
+ ctx,
22111
+ () => lowerStructuredBlocks(expr.body, expr.params, paramIds)
22112
+ );
21770
22113
  fn = t2.arrowFunctionExpression(
21771
22114
  paramIds,
21772
- t2.blockStatement([...cacheDeclarations, t2.returnStatement(bodyExpr)])
22115
+ t2.blockStatement([...cacheDeclarations, ...stmts])
21773
22116
  );
21774
22117
  } else {
21775
- fn = t2.arrowFunctionExpression(paramIds, bodyExpr);
22118
+ fn = t2.arrowFunctionExpression(paramIds, t2.blockStatement([]));
21776
22119
  }
21777
- } else if (Array.isArray(expr.body)) {
21778
- const { result: stmts, cacheDeclarations } = withGetterCache(
21779
- ctx,
21780
- () => lowerStructuredBlocks(expr.body, expr.params, paramIds)
21781
- );
21782
- fn = t2.arrowFunctionExpression(
21783
- paramIds,
21784
- t2.blockStatement([...cacheDeclarations, ...stmts])
21785
- );
21786
- } else {
21787
- fn = t2.arrowFunctionExpression(paramIds, t2.blockStatement([]));
21788
- }
21789
- fn.async = expr.isAsync ?? false;
21790
- return fn;
21791
- })
22120
+ fn.async = expr.isAsync ?? false;
22121
+ return fn;
22122
+ },
22123
+ localDeclared
22124
+ )
21792
22125
  );
21793
22126
  }
21794
22127
  case "FunctionExpression": {
21795
22128
  const paramIds = mapParams(expr.params);
21796
22129
  const shadowed = new Set(expr.params.map((p) => deSSAVarName(p.name)));
22130
+ const localDeclared = collectLocalDeclaredNames(expr.params, expr.body, t2);
21797
22131
  return withNonReactiveScope(
21798
22132
  ctx,
21799
- () => withFunctionScope(shadowed, () => {
21800
- let fn;
21801
- if (Array.isArray(expr.body)) {
21802
- const { result: stmts, cacheDeclarations } = withGetterCache(
21803
- ctx,
21804
- () => lowerStructuredBlocks(expr.body, expr.params, paramIds)
21805
- );
21806
- fn = t2.functionExpression(
21807
- expr.name ? t2.identifier(deSSAVarName(expr.name)) : null,
21808
- paramIds,
21809
- t2.blockStatement([...cacheDeclarations, ...stmts])
21810
- );
21811
- } else {
21812
- fn = t2.functionExpression(
21813
- expr.name ? t2.identifier(deSSAVarName(expr.name)) : null,
21814
- paramIds,
21815
- t2.blockStatement([])
21816
- );
21817
- }
21818
- fn.async = expr.isAsync ?? false;
21819
- return fn;
21820
- })
22133
+ () => withFunctionScope(
22134
+ shadowed,
22135
+ () => {
22136
+ let fn;
22137
+ if (Array.isArray(expr.body)) {
22138
+ const { result: stmts, cacheDeclarations } = withGetterCache(
22139
+ ctx,
22140
+ () => lowerStructuredBlocks(expr.body, expr.params, paramIds)
22141
+ );
22142
+ fn = t2.functionExpression(
22143
+ expr.name ? t2.identifier(deSSAVarName(expr.name)) : null,
22144
+ paramIds,
22145
+ t2.blockStatement([...cacheDeclarations, ...stmts])
22146
+ );
22147
+ } else {
22148
+ fn = t2.functionExpression(
22149
+ expr.name ? t2.identifier(deSSAVarName(expr.name)) : null,
22150
+ paramIds,
22151
+ t2.blockStatement([])
22152
+ );
22153
+ }
22154
+ fn.async = expr.isAsync ?? false;
22155
+ return fn;
22156
+ },
22157
+ localDeclared
22158
+ )
21821
22159
  );
21822
22160
  }
21823
22161
  case "AssignmentExpression":
@@ -21951,10 +22289,7 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21951
22289
  case "AwaitExpression":
21952
22290
  return t2.awaitExpression(lowerExpression(expr.argument, ctx));
21953
22291
  case "NewExpression":
21954
- return t2.newExpression(
21955
- lowerExpression(expr.callee, ctx),
21956
- expr.arguments.map((a) => lowerExpression(a, ctx))
21957
- );
22292
+ return t2.newExpression(lowerExpression(expr.callee, ctx), lowerCallArguments(expr.arguments));
21958
22293
  case "SequenceExpression":
21959
22294
  return t2.sequenceExpression(expr.expressions.map((e) => lowerExpression(e, ctx)));
21960
22295
  case "YieldExpression":
@@ -21965,7 +22300,7 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21965
22300
  case "OptionalCallExpression":
21966
22301
  return t2.optionalCallExpression(
21967
22302
  lowerExpression(expr.callee, ctx),
21968
- expr.arguments.map((a) => lowerExpression(a, ctx)),
22303
+ lowerCallArguments(expr.arguments),
21969
22304
  expr.optional
21970
22305
  );
21971
22306
  case "TaggedTemplateExpression":
@@ -22097,26 +22432,17 @@ function lowerJSXElement(jsx, ctx) {
22097
22432
  ]);
22098
22433
  }
22099
22434
  ctx.helpersUsed.add("createElement");
22100
- const propsObj = buildPropsObject(jsx.attributes, ctx);
22101
22435
  const children = jsx.children.map((c) => lowerJSXChild(c, ctx));
22436
+ const propsExpr = buildPropsExpression(jsx.attributes, children, ctx, {
22437
+ lowerDomExpression,
22438
+ lowerTrackedExpression,
22439
+ expressionUsesTracked,
22440
+ deSSAVarName
22441
+ });
22102
22442
  const componentRef = typeof jsx.tagName === "string" ? t2.identifier(jsx.tagName) : lowerExpression(jsx.tagName, ctx);
22103
- const propsWithChildren = [];
22104
- if (propsObj && t2.isObjectExpression(propsObj)) {
22105
- propsWithChildren.push(...propsObj.properties);
22106
- }
22107
- if (children.length === 1 && children[0]) {
22108
- propsWithChildren.push(t2.objectProperty(t2.identifier("children"), children[0]));
22109
- } else if (children.length > 1) {
22110
- propsWithChildren.push(
22111
- t2.objectProperty(t2.identifier("children"), t2.arrayExpression(children))
22112
- );
22113
- }
22114
22443
  return t2.objectExpression([
22115
22444
  t2.objectProperty(t2.identifier("type"), componentRef),
22116
- t2.objectProperty(
22117
- t2.identifier("props"),
22118
- propsWithChildren.length > 0 ? t2.objectExpression(propsWithChildren) : t2.nullLiteral()
22119
- )
22445
+ t2.objectProperty(t2.identifier("props"), propsExpr ?? t2.nullLiteral())
22120
22446
  ]);
22121
22447
  }
22122
22448
  const useFineGrainedDom = !ctx.noMemo;
@@ -23869,98 +24195,6 @@ function lowerJSXChild(child, ctx) {
23869
24195
  return applyRegionMetadataToExpression(lowerExpression(child.value, ctx), ctx);
23870
24196
  }
23871
24197
  }
23872
- function buildPropsObject(attributes, ctx) {
23873
- const { t: t2 } = ctx;
23874
- const prevPropsContext = ctx.inPropsContext;
23875
- ctx.inPropsContext = true;
23876
- try {
23877
- if (attributes.length === 0) return null;
23878
- const properties = [];
23879
- const spreads = [];
23880
- const toPropKey = (name) => /^[a-zA-Z_$][\w$]*$/.test(name) ? t2.identifier(name) : t2.stringLiteral(name);
23881
- const isAccessorName = (name) => (ctx.memoVars?.has(name) ?? false) || (ctx.signalVars?.has(name) ?? false) || (ctx.aliasVars?.has(name) ?? false);
23882
- const wrapAccessorSource = (node) => {
23883
- if (t2.isCallExpression(node) && t2.isIdentifier(node.callee) && node.arguments.length === 0) {
23884
- const baseName2 = deSSAVarName(node.callee.name);
23885
- if (isAccessorName(baseName2)) {
23886
- return t2.arrowFunctionExpression([], node);
23887
- }
23888
- }
23889
- if (t2.isIdentifier(node)) {
23890
- const baseName2 = deSSAVarName(node.name);
23891
- if (isAccessorName(baseName2)) {
23892
- return t2.arrowFunctionExpression([], t2.callExpression(t2.identifier(baseName2), []));
23893
- }
23894
- }
23895
- return node;
23896
- };
23897
- for (const attr of attributes) {
23898
- if (attr.isSpread && attr.spreadExpr) {
23899
- let spreadExpr = lowerDomExpression(attr.spreadExpr, ctx);
23900
- if (t2.isCallExpression(spreadExpr)) {
23901
- const callExpr = spreadExpr;
23902
- const rewrittenArgs = callExpr.arguments.map(
23903
- (arg) => t2.isExpression(arg) ? wrapAccessorSource(arg) : arg
23904
- );
23905
- if (rewrittenArgs.some((arg, idx) => arg !== callExpr.arguments[idx])) {
23906
- spreadExpr = t2.callExpression(callExpr.callee, rewrittenArgs);
23907
- }
23908
- }
23909
- spreadExpr = wrapAccessorSource(spreadExpr);
23910
- spreads.push(t2.spreadElement(spreadExpr));
23911
- } else if (attr.value) {
23912
- const isFunctionLike = attr.value.kind === "ArrowFunction" || attr.value.kind === "FunctionExpression";
23913
- const prevPropsCtx = ctx.inPropsContext;
23914
- if (isFunctionLike) {
23915
- ctx.inPropsContext = false;
23916
- }
23917
- const lowered = lowerDomExpression(attr.value, ctx);
23918
- if (isFunctionLike) {
23919
- ctx.inPropsContext = prevPropsCtx;
23920
- }
23921
- const baseIdent = attr.value.kind === "Identifier" ? deSSAVarName(attr.value.name) : void 0;
23922
- const isAccessorBase = baseIdent && ((ctx.memoVars?.has(baseIdent) ?? false) || (ctx.signalVars?.has(baseIdent) ?? false) || (ctx.aliasVars?.has(baseIdent) ?? false));
23923
- const isStoreBase = baseIdent ? ctx.storeVars?.has(baseIdent) ?? false : false;
23924
- const alreadyGetter = isFunctionLike || (baseIdent ? isStoreBase || (ctx.memoVars?.has(baseIdent) ?? false) || (ctx.aliasVars?.has(baseIdent) ?? false) : false);
23925
- const usesTracked = (!ctx.nonReactiveScopeDepth || ctx.nonReactiveScopeDepth === 0) && expressionUsesTracked(attr.value, ctx) && !alreadyGetter;
23926
- const trackedExpr = usesTracked ? lowerTrackedExpression(attr.value, ctx) : null;
23927
- const useMemoProp = usesTracked && trackedExpr && t2.isExpression(trackedExpr) && !t2.isIdentifier(trackedExpr) && !t2.isMemberExpression(trackedExpr) && !t2.isLiteral(trackedExpr);
23928
- const valueExpr = !isFunctionLike && isAccessorBase && baseIdent ? (() => {
23929
- ctx.helpersUsed.add("propGetter");
23930
- return t2.callExpression(t2.identifier(RUNTIME_ALIASES.propGetter), [
23931
- t2.arrowFunctionExpression([], t2.callExpression(t2.identifier(baseIdent), []))
23932
- ]);
23933
- })() : usesTracked && t2.isExpression(lowered) ? (() => {
23934
- if (useMemoProp) {
23935
- ctx.helpersUsed.add("prop");
23936
- return t2.callExpression(t2.identifier(RUNTIME_ALIASES.prop), [
23937
- t2.arrowFunctionExpression(
23938
- [],
23939
- trackedExpr ?? lowered
23940
- )
23941
- ]);
23942
- }
23943
- ctx.helpersUsed.add("propGetter");
23944
- return t2.callExpression(t2.identifier(RUNTIME_ALIASES.propGetter), [
23945
- t2.arrowFunctionExpression(
23946
- [],
23947
- trackedExpr ?? lowered
23948
- )
23949
- ]);
23950
- })() : lowered;
23951
- properties.push(t2.objectProperty(toPropKey(attr.name), valueExpr));
23952
- } else {
23953
- properties.push(t2.objectProperty(toPropKey(attr.name), t2.booleanLiteral(true)));
23954
- }
23955
- }
23956
- if (spreads.length > 0) {
23957
- return t2.objectExpression([...spreads, ...properties]);
23958
- }
23959
- return t2.objectExpression(properties);
23960
- } finally {
23961
- ctx.inPropsContext = prevPropsContext;
23962
- }
23963
- }
23964
24198
  function isDOMProperty(name) {
23965
24199
  return ["value", "checked", "selected", "disabled", "readOnly", "multiple", "muted"].includes(
23966
24200
  name
@@ -23977,6 +24211,8 @@ function lowerHIRWithRegions(program, t2, options) {
23977
24211
  let topLevelCtxInjected = false;
23978
24212
  const emittedFunctionNames = /* @__PURE__ */ new Set();
23979
24213
  const originalBody = program.originalBody ?? [];
24214
+ ctx.moduleDeclaredNames = collectDeclaredNames(originalBody, t2);
24215
+ ctx.moduleRuntimeNames = collectRuntimeImportNames(originalBody, t2);
23980
24216
  for (const stmt of originalBody) {
23981
24217
  if (t2.isVariableDeclaration(stmt)) {
23982
24218
  for (const decl of stmt.declarations) {
@@ -24374,6 +24610,12 @@ function lowerFunctionWithRegions(fn, ctx) {
24374
24610
  const functionShadowed = new Set(prevShadowed ?? []);
24375
24611
  shadowedParams.forEach((n) => functionShadowed.add(n));
24376
24612
  ctx.shadowedNames = functionShadowed;
24613
+ const prevLocalDeclared = ctx.localDeclaredNames;
24614
+ const localDeclared = new Set(prevLocalDeclared ?? []);
24615
+ for (const name of collectLocalDeclaredNames(fn.params, fn.blocks, t2)) {
24616
+ localDeclared.add(name);
24617
+ }
24618
+ ctx.localDeclaredNames = localDeclared;
24377
24619
  const prevExternalTracked = ctx.externalTracked;
24378
24620
  const inheritedTracked = new Set(ctx.trackedVars);
24379
24621
  ctx.externalTracked = inheritedTracked;
@@ -24458,13 +24700,72 @@ function lowerFunctionWithRegions(fn, ctx) {
24458
24700
  let usesProp = false;
24459
24701
  let usesPropsRest = false;
24460
24702
  let warnedNested = false;
24703
+ const reportedPatternNodes = /* @__PURE__ */ new Set();
24704
+ const reportPatternDiagnostic = (node, code) => {
24705
+ if (reportedPatternNodes.has(node)) return;
24706
+ reportedPatternNodes.add(node);
24707
+ reportDiagnostic(ctx, code, node);
24708
+ };
24709
+ const reportPropsPatternIssues = (objectPattern, allowRest) => {
24710
+ for (const prop of objectPattern.properties) {
24711
+ if (t2.isObjectProperty(prop)) {
24712
+ if (prop.computed) {
24713
+ reportPatternDiagnostic(prop, "FICT-P003" /* FICT_P003 */);
24714
+ continue;
24715
+ }
24716
+ const keyName = t2.isIdentifier(prop.key) ? prop.key.name : t2.isStringLiteral(prop.key) ? prop.key.value : t2.isNumericLiteral(prop.key) ? String(prop.key.value) : null;
24717
+ if (!keyName) {
24718
+ reportPatternDiagnostic(prop, "FICT-P003" /* FICT_P003 */);
24719
+ continue;
24720
+ }
24721
+ const value = prop.value;
24722
+ if (t2.isIdentifier(value)) {
24723
+ continue;
24724
+ }
24725
+ if (t2.isObjectPattern(value)) {
24726
+ reportPropsPatternIssues(value, false);
24727
+ continue;
24728
+ }
24729
+ if (t2.isAssignmentPattern(value)) {
24730
+ if (t2.isIdentifier(value.left)) {
24731
+ continue;
24732
+ }
24733
+ reportPatternDiagnostic(prop, "FICT-P004" /* FICT_P004 */);
24734
+ continue;
24735
+ }
24736
+ if (t2.isArrayPattern(value)) {
24737
+ const hasRest = value.elements.some((el) => t2.isRestElement(el));
24738
+ reportPatternDiagnostic(
24739
+ value,
24740
+ hasRest ? "FICT-P002" /* FICT_P002 */ : "FICT-P001" /* FICT_P001 */
24741
+ );
24742
+ continue;
24743
+ }
24744
+ reportPatternDiagnostic(prop, "FICT-P004" /* FICT_P004 */);
24745
+ continue;
24746
+ }
24747
+ if (t2.isRestElement(prop)) {
24748
+ if (!allowRest || !t2.isIdentifier(prop.argument)) {
24749
+ reportPatternDiagnostic(prop, "FICT-P004" /* FICT_P004 */);
24750
+ }
24751
+ continue;
24752
+ }
24753
+ reportPatternDiagnostic(prop, "FICT-P004" /* FICT_P004 */);
24754
+ }
24755
+ };
24461
24756
  const memberExprForKey = (base, key) => t2.memberExpression(base, t2.identifier(key), false);
24462
24757
  const buildDestructure = (objectPattern, baseExpr, allowRest) => {
24463
24758
  for (const prop of objectPattern.properties) {
24464
- if (t2.isObjectProperty(prop) && !prop.computed) {
24759
+ if (t2.isObjectProperty(prop)) {
24760
+ if (prop.computed) {
24761
+ reportPatternDiagnostic(prop, "FICT-P003" /* FICT_P003 */);
24762
+ supported = false;
24763
+ warnedNested = true;
24764
+ break;
24765
+ }
24465
24766
  const keyName = t2.isIdentifier(prop.key) ? prop.key.name : t2.isStringLiteral(prop.key) ? prop.key.value : t2.isNumericLiteral(prop.key) ? String(prop.key.value) : null;
24466
24767
  if (!keyName) {
24467
- reportDiagnostic(ctx, "FICT-P003" /* FICT_P003 */, prop);
24768
+ reportPatternDiagnostic(prop, "FICT-P003" /* FICT_P003 */);
24468
24769
  supported = false;
24469
24770
  warnedNested = true;
24470
24771
  break;
@@ -24497,26 +24798,44 @@ function lowerFunctionWithRegions(fn, ctx) {
24497
24798
  if (!supported) break;
24498
24799
  continue;
24499
24800
  }
24500
- if (t2.isAssignmentPattern(value) && t2.isIdentifier(value.left)) {
24501
- const shouldWrapProp = !calledIdentifiers.has(value.left.name);
24502
- if (shouldWrapProp) {
24503
- usesProp = true;
24504
- propsPlanAliases.add(value.left.name);
24801
+ if (t2.isAssignmentPattern(value)) {
24802
+ if (t2.isIdentifier(value.left)) {
24803
+ const shouldWrapProp = !calledIdentifiers.has(value.left.name);
24804
+ if (shouldWrapProp) {
24805
+ usesProp = true;
24806
+ propsPlanAliases.add(value.left.name);
24807
+ }
24808
+ const baseInit = t2.logicalExpression("??", member, value.right);
24809
+ const init = shouldWrapProp ? t2.callExpression(t2.identifier(RUNTIME_ALIASES.prop), [
24810
+ t2.arrowFunctionExpression([], baseInit)
24811
+ ]) : baseInit;
24812
+ stmts.push(
24813
+ t2.variableDeclaration("const", [
24814
+ t2.variableDeclarator(t2.identifier(value.left.name), init)
24815
+ ])
24816
+ );
24817
+ continue;
24505
24818
  }
24506
- const baseInit = t2.logicalExpression("??", member, value.right);
24507
- const init = shouldWrapProp ? t2.callExpression(t2.identifier(RUNTIME_ALIASES.prop), [
24508
- t2.arrowFunctionExpression([], baseInit)
24509
- ]) : baseInit;
24510
- stmts.push(
24511
- t2.variableDeclaration("const", [
24512
- t2.variableDeclarator(t2.identifier(value.left.name), init)
24513
- ])
24819
+ supported = false;
24820
+ if (!warnedNested) {
24821
+ reportPatternDiagnostic(prop, "FICT-P004" /* FICT_P004 */);
24822
+ warnedNested = true;
24823
+ }
24824
+ break;
24825
+ }
24826
+ if (t2.isArrayPattern(value)) {
24827
+ const hasRest = value.elements.some((el) => t2.isRestElement(el));
24828
+ reportPatternDiagnostic(
24829
+ value,
24830
+ hasRest ? "FICT-P002" /* FICT_P002 */ : "FICT-P001" /* FICT_P001 */
24514
24831
  );
24515
- continue;
24832
+ supported = false;
24833
+ warnedNested = true;
24834
+ break;
24516
24835
  }
24517
24836
  supported = false;
24518
24837
  if (!warnedNested) {
24519
- reportDiagnostic(ctx, "FICT-P004" /* FICT_P004 */, prop);
24838
+ reportPatternDiagnostic(prop, "FICT-P004" /* FICT_P004 */);
24520
24839
  warnedNested = true;
24521
24840
  }
24522
24841
  break;
@@ -24537,13 +24856,14 @@ function lowerFunctionWithRegions(fn, ctx) {
24537
24856
  } else {
24538
24857
  supported = false;
24539
24858
  if (!warnedNested) {
24540
- reportDiagnostic(ctx, "FICT-P004" /* FICT_P004 */, prop);
24859
+ reportPatternDiagnostic(prop, "FICT-P004" /* FICT_P004 */);
24541
24860
  warnedNested = true;
24542
24861
  }
24543
24862
  break;
24544
24863
  }
24545
24864
  }
24546
24865
  };
24866
+ reportPropsPatternIssues(pattern, true);
24547
24867
  buildDestructure(pattern, t2.identifier("__props"), true);
24548
24868
  if (supported) {
24549
24869
  propsDestructurePlan = {
@@ -24590,6 +24910,7 @@ function lowerFunctionWithRegions(fn, ctx) {
24590
24910
  if (!hasJSX && !hasTrackedValues) {
24591
24911
  ctx.needsCtx = prevNeedsCtx;
24592
24912
  ctx.shadowedNames = prevShadowed;
24913
+ ctx.localDeclaredNames = prevLocalDeclared;
24593
24914
  ctx.trackedVars = prevTracked;
24594
24915
  ctx.externalTracked = prevExternalTracked;
24595
24916
  ctx.signalVars = prevSignalVars;
@@ -24672,6 +24993,7 @@ function lowerFunctionWithRegions(fn, ctx) {
24672
24993
  );
24673
24994
  ctx.needsCtx = prevNeedsCtx;
24674
24995
  ctx.shadowedNames = prevShadowed;
24996
+ ctx.localDeclaredNames = prevLocalDeclared;
24675
24997
  ctx.trackedVars = prevTracked;
24676
24998
  ctx.externalTracked = prevExternalTracked;
24677
24999
  ctx.signalVars = prevSignalVars;