@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.js CHANGED
@@ -15547,6 +15547,17 @@ function processStatement(stmt, bb, jumpTarget, ctx) {
15547
15547
  }
15548
15548
  function convertExpression(node) {
15549
15549
  const loc = getLoc(node);
15550
+ const convertCallArguments = (args) => args.map((arg) => {
15551
+ if (t.isSpreadElement(arg)) {
15552
+ return {
15553
+ kind: "SpreadElement",
15554
+ argument: convertExpression(arg.argument),
15555
+ loc: getLoc(arg)
15556
+ };
15557
+ }
15558
+ if (t.isExpression(arg)) return convertExpression(arg);
15559
+ return void 0;
15560
+ }).filter(Boolean);
15550
15561
  if (t.isIdentifier(node)) return { kind: "Identifier", name: node.name, loc };
15551
15562
  if (t.isStringLiteral(node) || t.isNumericLiteral(node) || t.isBooleanLiteral(node) || t.isNullLiteral(node))
15552
15563
  return { kind: "Literal", value: node.value ?? null, loc };
@@ -15554,7 +15565,7 @@ function convertExpression(node) {
15554
15565
  const call = {
15555
15566
  kind: "CallExpression",
15556
15567
  callee: convertExpression(node.callee),
15557
- arguments: node.arguments.map((arg) => t.isExpression(arg) ? convertExpression(arg) : void 0).filter(Boolean),
15568
+ arguments: convertCallArguments(node.arguments),
15558
15569
  loc
15559
15570
  };
15560
15571
  return call;
@@ -15834,7 +15845,7 @@ function convertExpression(node) {
15834
15845
  return {
15835
15846
  kind: "NewExpression",
15836
15847
  callee: convertExpression(node.callee),
15837
- arguments: node.arguments.map((arg) => t.isExpression(arg) ? convertExpression(arg) : void 0).filter(Boolean),
15848
+ arguments: convertCallArguments(node.arguments),
15838
15849
  loc
15839
15850
  };
15840
15851
  }
@@ -15857,7 +15868,7 @@ function convertExpression(node) {
15857
15868
  return {
15858
15869
  kind: "OptionalCallExpression",
15859
15870
  callee: convertExpression(node.callee),
15860
- arguments: node.arguments.map((arg) => t.isExpression(arg) ? convertExpression(arg) : void 0).filter(Boolean),
15871
+ arguments: convertCallArguments(node.arguments),
15861
15872
  optional: node.optional,
15862
15873
  loc
15863
15874
  };
@@ -16067,6 +16078,7 @@ var DiagnosticMessages = {
16067
16078
  ["FICT-P002" /* FICT_P002 */]: "Array rest in props destructuring falls back to non-reactive binding.",
16068
16079
  ["FICT-P003" /* FICT_P003 */]: "Computed property in props pattern cannot be made reactive.",
16069
16080
  ["FICT-P004" /* FICT_P004 */]: "Nested props destructuring falls back to non-reactive binding; access props directly or use prop.",
16081
+ ["FICT-P005" /* FICT_P005 */]: "Dynamic props spread may not stay reactive; consider explicit props or mergeProps(() => source).",
16070
16082
  ["FICT-S001" /* FICT_S001 */]: "State variable mutation detected outside component scope.",
16071
16083
  ["FICT-S002" /* FICT_S002 */]: "State variable escaped to external scope, may cause memory leaks.",
16072
16084
  ["FICT-E001" /* FICT_E001 */]: "Effect without reactive dependencies will run only once; consider adding state reads or removing the effect.",
@@ -16096,6 +16108,7 @@ var DiagnosticSeverities = {
16096
16108
  ["FICT-P002" /* FICT_P002 */]: "warning" /* Warning */,
16097
16109
  ["FICT-P003" /* FICT_P003 */]: "warning" /* Warning */,
16098
16110
  ["FICT-P004" /* FICT_P004 */]: "warning" /* Warning */,
16111
+ ["FICT-P005" /* FICT_P005 */]: "warning" /* Warning */,
16099
16112
  ["FICT-S001" /* FICT_S001 */]: "error" /* Error */,
16100
16113
  ["FICT-S002" /* FICT_S002 */]: "warning" /* Warning */,
16101
16114
  ["FICT-E001" /* FICT_E001 */]: "warning" /* Warning */,
@@ -16148,6 +16161,215 @@ function reportDiagnostic(ctx, code, node, context) {
16148
16161
  }
16149
16162
  }
16150
16163
 
16164
+ // src/ir/props-plan.ts
16165
+ function buildPropsPlan(attributes, children, ctx, helpers) {
16166
+ const { t: t2 } = ctx;
16167
+ const prevPropsContext = ctx.inPropsContext;
16168
+ ctx.inPropsContext = true;
16169
+ try {
16170
+ if (attributes.length === 0 && children.length === 0) return null;
16171
+ const segments = [];
16172
+ const flags = {
16173
+ needsMergeProps: false,
16174
+ hasLazySource: false
16175
+ };
16176
+ let bucket = [];
16177
+ const toPropKey = (name) => /^[a-zA-Z_$][\w$]*$/.test(name) ? t2.identifier(name) : t2.stringLiteral(name);
16178
+ const isAccessorName = (name) => (ctx.memoVars?.has(name) ?? false) || (ctx.signalVars?.has(name) ?? false) || (ctx.aliasVars?.has(name) ?? false);
16179
+ const isZeroArgFunction = (expr) => (t2.isArrowFunctionExpression(expr) || t2.isFunctionExpression(expr)) && expr.params.length === 0;
16180
+ const wrapAccessorSource = (node) => {
16181
+ if (t2.isCallExpression(node) && t2.isIdentifier(node.callee) && node.arguments.length === 0) {
16182
+ const baseName2 = helpers.deSSAVarName(node.callee.name);
16183
+ if (isAccessorName(baseName2)) {
16184
+ return t2.arrowFunctionExpression([], node);
16185
+ }
16186
+ }
16187
+ if (t2.isIdentifier(node)) {
16188
+ const baseName2 = helpers.deSSAVarName(node.name);
16189
+ if (isAccessorName(baseName2)) {
16190
+ return t2.arrowFunctionExpression([], t2.callExpression(t2.identifier(baseName2), []));
16191
+ }
16192
+ }
16193
+ return node;
16194
+ };
16195
+ const isAccessorSource = (expr) => {
16196
+ if (expr.kind === "Identifier") {
16197
+ return isAccessorName(helpers.deSSAVarName(expr.name));
16198
+ }
16199
+ if (expr.kind === "CallExpression" || expr.kind === "OptionalCallExpression") {
16200
+ if (expr.callee.kind === "Identifier" && expr.arguments.length === 0) {
16201
+ return isAccessorName(helpers.deSSAVarName(expr.callee.name));
16202
+ }
16203
+ }
16204
+ return false;
16205
+ };
16206
+ 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));
16207
+ const isMergePropsCall = (expr) => expr.kind === "CallExpression" && expr.callee.kind === "Identifier" && expr.callee.name === RUNTIME_ALIASES.mergeProps && isRuntimeMergeProps();
16208
+ const isDynamicMemberSpread = (expr) => {
16209
+ if (expr.kind !== "MemberExpression" && expr.kind !== "OptionalMemberExpression") return false;
16210
+ if (expr.computed) return true;
16211
+ if (expr.kind === "OptionalMemberExpression" && expr.optional) return true;
16212
+ let current = expr;
16213
+ while (current.kind === "MemberExpression" || current.kind === "OptionalMemberExpression") {
16214
+ const obj = current.object;
16215
+ 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") {
16216
+ return true;
16217
+ }
16218
+ if (obj.kind === "OptionalMemberExpression" && obj.optional) {
16219
+ return true;
16220
+ }
16221
+ if (obj.kind !== "MemberExpression" && obj.kind !== "OptionalMemberExpression") {
16222
+ return obj.kind !== "Identifier";
16223
+ }
16224
+ current = obj;
16225
+ }
16226
+ return false;
16227
+ };
16228
+ const isDynamicPropsSpread = (expr) => {
16229
+ if (isAccessorSource(expr) || isMergePropsCall(expr)) return false;
16230
+ 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") {
16231
+ return true;
16232
+ }
16233
+ if (expr.kind === "MemberExpression" || expr.kind === "OptionalMemberExpression") {
16234
+ return isDynamicMemberSpread(expr);
16235
+ }
16236
+ if (expr.kind === "ObjectExpression") {
16237
+ return expr.properties.some((p) => p.kind === "SpreadElement");
16238
+ }
16239
+ return false;
16240
+ };
16241
+ const flushBucket = () => {
16242
+ if (bucket.length === 0) return;
16243
+ segments.push({ kind: "object", properties: bucket });
16244
+ bucket = [];
16245
+ };
16246
+ const pushSpread = (expr) => {
16247
+ flags.needsMergeProps = true;
16248
+ if (isZeroArgFunction(expr)) {
16249
+ flags.hasLazySource = true;
16250
+ }
16251
+ segments.push({ kind: "spread", expr });
16252
+ };
16253
+ for (const attr of attributes) {
16254
+ if (attr.isSpread && attr.spreadExpr) {
16255
+ flushBucket();
16256
+ if (isDynamicPropsSpread(attr.spreadExpr)) {
16257
+ reportDiagnostic(ctx, "FICT-P005" /* FICT_P005 */, attr.spreadExpr);
16258
+ }
16259
+ let spreadExpr = helpers.lowerDomExpression(attr.spreadExpr, ctx);
16260
+ if (t2.isCallExpression(spreadExpr) && t2.isIdentifier(spreadExpr.callee) && spreadExpr.callee.name === RUNTIME_ALIASES.mergeProps && isRuntimeMergeProps()) {
16261
+ const callExpr = spreadExpr;
16262
+ const rewrittenArgs = callExpr.arguments.map(
16263
+ (arg) => t2.isExpression(arg) ? wrapAccessorSource(arg) : arg
16264
+ );
16265
+ if (rewrittenArgs.some((arg, idx) => arg !== callExpr.arguments[idx])) {
16266
+ spreadExpr = t2.callExpression(
16267
+ callExpr.callee,
16268
+ rewrittenArgs
16269
+ );
16270
+ }
16271
+ const flattenArgs = [];
16272
+ let canFlatten = true;
16273
+ for (const arg of rewrittenArgs) {
16274
+ if (t2.isExpression(arg)) {
16275
+ flattenArgs.push(arg);
16276
+ } else {
16277
+ canFlatten = false;
16278
+ break;
16279
+ }
16280
+ }
16281
+ if (canFlatten) {
16282
+ for (const arg of flattenArgs) {
16283
+ pushSpread(arg);
16284
+ }
16285
+ continue;
16286
+ }
16287
+ }
16288
+ spreadExpr = wrapAccessorSource(spreadExpr);
16289
+ pushSpread(spreadExpr);
16290
+ continue;
16291
+ }
16292
+ if (attr.value) {
16293
+ const isFunctionLike = attr.value.kind === "ArrowFunction" || attr.value.kind === "FunctionExpression";
16294
+ const prevPropsCtx = ctx.inPropsContext;
16295
+ if (isFunctionLike) {
16296
+ ctx.inPropsContext = false;
16297
+ }
16298
+ const lowered = helpers.lowerDomExpression(attr.value, ctx);
16299
+ if (isFunctionLike) {
16300
+ ctx.inPropsContext = prevPropsCtx;
16301
+ }
16302
+ const baseIdent = attr.value.kind === "Identifier" ? helpers.deSSAVarName(attr.value.name) : void 0;
16303
+ const isAccessorBase = baseIdent && ((ctx.memoVars?.has(baseIdent) ?? false) || (ctx.signalVars?.has(baseIdent) ?? false) || (ctx.aliasVars?.has(baseIdent) ?? false));
16304
+ const isStoreBase = baseIdent ? ctx.storeVars?.has(baseIdent) ?? false : false;
16305
+ const alreadyGetter = isFunctionLike || (baseIdent ? isStoreBase || (ctx.memoVars?.has(baseIdent) ?? false) || (ctx.aliasVars?.has(baseIdent) ?? false) : false);
16306
+ const usesTracked = (!ctx.nonReactiveScopeDepth || ctx.nonReactiveScopeDepth === 0) && helpers.expressionUsesTracked(attr.value, ctx) && !alreadyGetter;
16307
+ const trackedExpr = usesTracked ? helpers.lowerTrackedExpression(
16308
+ attr.value,
16309
+ ctx
16310
+ ) : null;
16311
+ const useMemoProp = usesTracked && trackedExpr && t2.isExpression(trackedExpr) && !t2.isIdentifier(trackedExpr) && !t2.isMemberExpression(trackedExpr) && !t2.isLiteral(trackedExpr);
16312
+ const valueExpr = !isFunctionLike && isAccessorBase && baseIdent ? (() => {
16313
+ ctx.helpersUsed.add("propGetter");
16314
+ return t2.callExpression(t2.identifier(RUNTIME_ALIASES.propGetter), [
16315
+ t2.arrowFunctionExpression([], t2.callExpression(t2.identifier(baseIdent), []))
16316
+ ]);
16317
+ })() : usesTracked && t2.isExpression(lowered) ? (() => {
16318
+ if (useMemoProp) {
16319
+ ctx.helpersUsed.add("prop");
16320
+ return t2.callExpression(t2.identifier(RUNTIME_ALIASES.prop), [
16321
+ t2.arrowFunctionExpression([], trackedExpr ?? lowered)
16322
+ ]);
16323
+ }
16324
+ ctx.helpersUsed.add("propGetter");
16325
+ return t2.callExpression(t2.identifier(RUNTIME_ALIASES.propGetter), [
16326
+ t2.arrowFunctionExpression([], trackedExpr ?? lowered)
16327
+ ]);
16328
+ })() : lowered;
16329
+ bucket.push(t2.objectProperty(toPropKey(attr.name), valueExpr));
16330
+ continue;
16331
+ }
16332
+ bucket.push(t2.objectProperty(toPropKey(attr.name), t2.booleanLiteral(true)));
16333
+ }
16334
+ if (children.length === 1 && children[0]) {
16335
+ bucket.push(t2.objectProperty(t2.identifier("children"), children[0]));
16336
+ } else if (children.length > 1) {
16337
+ bucket.push(t2.objectProperty(t2.identifier("children"), t2.arrayExpression(children)));
16338
+ }
16339
+ flushBucket();
16340
+ if (segments.length === 0) return null;
16341
+ return { segments, flags };
16342
+ } finally {
16343
+ ctx.inPropsContext = prevPropsContext;
16344
+ }
16345
+ }
16346
+ function lowerPropsPlan(plan, ctx) {
16347
+ const { t: t2 } = ctx;
16348
+ const args = [];
16349
+ for (const segment of plan.segments) {
16350
+ if (segment.kind === "object") {
16351
+ if (segment.properties.length === 0) continue;
16352
+ args.push(t2.objectExpression(segment.properties));
16353
+ continue;
16354
+ }
16355
+ args.push(segment.expr);
16356
+ }
16357
+ if (args.length === 0) return null;
16358
+ if (!plan.flags.needsMergeProps) {
16359
+ return args[0] ?? null;
16360
+ }
16361
+ if (args.length === 1 && !plan.flags.hasLazySource) {
16362
+ return args[0];
16363
+ }
16364
+ ctx.helpersUsed.add("mergeProps");
16365
+ return t2.callExpression(t2.identifier(RUNTIME_ALIASES.mergeProps), args);
16366
+ }
16367
+ function buildPropsExpression(attributes, children, ctx, helpers) {
16368
+ const plan = buildPropsPlan(attributes, children, ctx, helpers);
16369
+ if (!plan) return null;
16370
+ return lowerPropsPlan(plan, ctx);
16371
+ }
16372
+
16151
16373
  // src/ir/ssa.ts
16152
16374
  function analyzeCFG(blocks) {
16153
16375
  const predecessors = computePredecessors(blocks);
@@ -16645,6 +16867,9 @@ function collectExprReads(expr, into, paths, bound = /* @__PURE__ */ new Set(),
16645
16867
  expr.arguments?.forEach((a) => collectExprReads(a, into, paths, bound));
16646
16868
  return;
16647
16869
  }
16870
+ case "SpreadElement":
16871
+ collectExprReads(expr.argument, into, paths, bound);
16872
+ return;
16648
16873
  case "MemberExpression":
16649
16874
  case "OptionalMemberExpression": {
16650
16875
  const depPath = extractDependencyPath(expr);
@@ -18139,11 +18364,15 @@ function containsJSXExpr(expr) {
18139
18364
  case "ArrayExpression":
18140
18365
  return expr.elements?.some((el) => containsJSXExpr(el)) ?? false;
18141
18366
  case "ObjectExpression":
18142
- return expr.properties?.some((p) => containsJSXExpr(p.value)) ?? false;
18367
+ return expr.properties?.some(
18368
+ (p) => p.kind === "SpreadElement" ? containsJSXExpr(p.argument) : containsJSXExpr(p.value)
18369
+ ) ?? false;
18143
18370
  case "ConditionalExpression":
18144
18371
  return containsJSXExpr(expr.consequent) || containsJSXExpr(expr.alternate);
18145
18372
  case "ArrowFunction":
18146
18373
  return containsJSXExpr(expr.body);
18374
+ case "SpreadElement":
18375
+ return containsJSXExpr(expr.argument);
18147
18376
  default:
18148
18377
  return false;
18149
18378
  }
@@ -18173,6 +18402,8 @@ function expressionUsesTracked(expr, ctx) {
18173
18402
  });
18174
18403
  case "TemplateLiteral":
18175
18404
  return expr.expressions.some((e) => expressionUsesTracked(e, ctx));
18405
+ case "SpreadElement":
18406
+ return expressionUsesTracked(expr.argument, ctx);
18176
18407
  default:
18177
18408
  return false;
18178
18409
  }
@@ -20219,6 +20450,9 @@ function collectCalledIdentifiers(fn) {
20219
20450
  function createCodegenContext(t2) {
20220
20451
  return {
20221
20452
  t: t2,
20453
+ moduleDeclaredNames: /* @__PURE__ */ new Set(),
20454
+ moduleRuntimeNames: /* @__PURE__ */ new Set(),
20455
+ localDeclaredNames: /* @__PURE__ */ new Set(),
20222
20456
  helpersUsed: /* @__PURE__ */ new Set(),
20223
20457
  tempCounter: 0,
20224
20458
  trackedVars: /* @__PURE__ */ new Set(),
@@ -21363,8 +21597,7 @@ function lowerTerminator(block, ctx) {
21363
21597
  return applyLoc([]);
21364
21598
  }
21365
21599
  }
21366
- function attachHelperImports(ctx, body, t2) {
21367
- if (ctx.helpersUsed.size === 0) return body;
21600
+ function collectDeclaredNames(body, t2) {
21368
21601
  const declared = /* @__PURE__ */ new Set();
21369
21602
  const addPatternNames = (pattern) => {
21370
21603
  if (t2.isIdentifier(pattern)) {
@@ -21438,6 +21671,78 @@ function attachHelperImports(ctx, body, t2) {
21438
21671
  declared.add(stmt.declaration.name);
21439
21672
  }
21440
21673
  }
21674
+ return declared;
21675
+ }
21676
+ function collectRuntimeImportNames(body, t2) {
21677
+ const runtimeModules = /* @__PURE__ */ new Set([RUNTIME_MODULE, "@fictjs/runtime", "fict"]);
21678
+ const imported = /* @__PURE__ */ new Set();
21679
+ for (const stmt of body) {
21680
+ if (!t2.isImportDeclaration(stmt)) continue;
21681
+ if (!runtimeModules.has(stmt.source.value)) continue;
21682
+ for (const spec of stmt.specifiers) {
21683
+ imported.add(spec.local.name);
21684
+ }
21685
+ }
21686
+ return imported;
21687
+ }
21688
+ function collectLocalDeclaredNames(params, blocks, t2) {
21689
+ const declared = /* @__PURE__ */ new Set();
21690
+ const addPatternNames = (pattern) => {
21691
+ if (t2.isIdentifier(pattern)) {
21692
+ declared.add(deSSAVarName(pattern.name));
21693
+ return;
21694
+ }
21695
+ if (t2.isAssignmentPattern(pattern)) {
21696
+ addPatternNames(pattern.left);
21697
+ return;
21698
+ }
21699
+ if (t2.isRestElement(pattern)) {
21700
+ addPatternNames(pattern.argument);
21701
+ return;
21702
+ }
21703
+ if (t2.isObjectPattern(pattern)) {
21704
+ for (const prop of pattern.properties) {
21705
+ if (t2.isRestElement(prop)) {
21706
+ addPatternNames(prop.argument);
21707
+ } else if (t2.isObjectProperty(prop)) {
21708
+ addPatternNames(prop.value);
21709
+ }
21710
+ }
21711
+ return;
21712
+ }
21713
+ if (t2.isArrayPattern(pattern)) {
21714
+ for (const el of pattern.elements) {
21715
+ if (!el) continue;
21716
+ if (t2.isPatternLike(el)) addPatternNames(el);
21717
+ }
21718
+ }
21719
+ };
21720
+ params.forEach((param) => declared.add(deSSAVarName(param.name)));
21721
+ if (!blocks) return declared;
21722
+ for (const block of blocks) {
21723
+ for (const instr of block.instructions) {
21724
+ if (instr.kind !== "Assign") continue;
21725
+ const target = deSSAVarName(instr.target.name);
21726
+ const isFunctionDecl = instr.value.kind === "FunctionExpression" && !!instr.value.name && deSSAVarName(instr.value.name) === target;
21727
+ if (instr.declarationKind || isFunctionDecl) {
21728
+ declared.add(target);
21729
+ }
21730
+ }
21731
+ const term = block.terminator;
21732
+ if (term.kind === "ForOf" || term.kind === "ForIn") {
21733
+ declared.add(deSSAVarName(term.variable));
21734
+ if (term.pattern) {
21735
+ addPatternNames(term.pattern);
21736
+ }
21737
+ } else if (term.kind === "Try" && term.catchParam) {
21738
+ declared.add(deSSAVarName(term.catchParam));
21739
+ }
21740
+ }
21741
+ return declared;
21742
+ }
21743
+ function attachHelperImports(ctx, body, t2) {
21744
+ if (ctx.helpersUsed.size === 0) return body;
21745
+ const declared = collectDeclaredNames(body, t2);
21441
21746
  const specifiers = [];
21442
21747
  for (const name of ctx.helpersUsed) {
21443
21748
  const alias = RUNTIME_ALIASES[name];
@@ -21507,11 +21812,21 @@ function lowerExpression(expr, ctx, isAssigned = false) {
21507
21812
  function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21508
21813
  const { t: t2 } = ctx;
21509
21814
  const mapParams = (params) => params.map((p) => t2.identifier(deSSAVarName(p.name)));
21510
- const withFunctionScope = (paramNames, fn) => {
21815
+ const lowerArgsAsExpressions = (args) => args.map(
21816
+ (arg) => arg.kind === "SpreadElement" ? lowerExpression(arg.argument, ctx) : lowerExpression(arg, ctx)
21817
+ );
21818
+ const lowerCallArguments = (args, mapArg) => args.map((arg, idx) => {
21819
+ if (arg.kind === "SpreadElement") {
21820
+ return t2.spreadElement(lowerExpression(arg.argument, ctx));
21821
+ }
21822
+ return mapArg ? mapArg(arg, idx) : lowerExpression(arg, ctx);
21823
+ });
21824
+ const withFunctionScope = (paramNames, fn, localDeclared) => {
21511
21825
  const prevTracked = ctx.trackedVars;
21512
21826
  const prevAlias = ctx.aliasVars;
21513
21827
  const prevExternal = ctx.externalTracked;
21514
21828
  const prevShadowed = ctx.shadowedNames;
21829
+ const prevLocalDeclared = ctx.localDeclaredNames;
21515
21830
  const scoped = new Set(ctx.trackedVars);
21516
21831
  paramNames.forEach((n) => scoped.delete(deSSAVarName(n)));
21517
21832
  ctx.trackedVars = scoped;
@@ -21520,11 +21835,19 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21520
21835
  const shadowed = new Set(prevShadowed ?? []);
21521
21836
  paramNames.forEach((n) => shadowed.add(deSSAVarName(n)));
21522
21837
  ctx.shadowedNames = shadowed;
21838
+ const localNames = new Set(prevLocalDeclared ?? []);
21839
+ if (localDeclared) {
21840
+ for (const name of localDeclared) {
21841
+ localNames.add(deSSAVarName(name));
21842
+ }
21843
+ }
21844
+ ctx.localDeclaredNames = localNames;
21523
21845
  const result = fn();
21524
21846
  ctx.trackedVars = prevTracked;
21525
21847
  ctx.aliasVars = prevAlias;
21526
21848
  ctx.externalTracked = prevExternal;
21527
21849
  ctx.shadowedNames = prevShadowed;
21850
+ ctx.localDeclaredNames = prevLocalDeclared;
21528
21851
  return result;
21529
21852
  };
21530
21853
  const lowerBlocksToStatements = (blocks) => {
@@ -21586,7 +21909,7 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21586
21909
  ctx.needsCtx = true;
21587
21910
  return t2.callExpression(t2.identifier(RUNTIME_ALIASES.useSignal), [
21588
21911
  t2.identifier("__fictCtx"),
21589
- ...expr.arguments.map((a) => lowerExpression(a, ctx))
21912
+ ...lowerCallArguments(expr.arguments)
21590
21913
  ]);
21591
21914
  }
21592
21915
  if (expr.callee.kind === "Identifier" && expr.callee.name === "$effect") {
@@ -21594,14 +21917,15 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21594
21917
  ctx.needsCtx = true;
21595
21918
  return t2.callExpression(t2.identifier(RUNTIME_ALIASES.useEffect), [
21596
21919
  t2.identifier("__fictCtx"),
21597
- ...expr.arguments.map(
21920
+ ...lowerCallArguments(
21921
+ expr.arguments,
21598
21922
  (arg) => arg.kind === "ArrowFunction" || arg.kind === "FunctionExpression" ? withNonReactiveScope(ctx, () => lowerExpression(arg, ctx)) : lowerExpression(arg, ctx)
21599
21923
  )
21600
21924
  ]);
21601
21925
  }
21602
21926
  if (expr.callee.kind === "Identifier" && expr.callee.name === "__forOf") {
21603
21927
  ctx.needsForOfHelper = true;
21604
- const [iterable, cb] = expr.arguments.map((a) => lowerExpression(a, ctx));
21928
+ const [iterable, cb] = lowerArgsAsExpressions(expr.arguments);
21605
21929
  return t2.callExpression(t2.identifier("__fictForOf"), [
21606
21930
  iterable ?? t2.identifier("undefined"),
21607
21931
  cb ?? t2.arrowFunctionExpression([], t2.identifier("undefined"))
@@ -21609,7 +21933,7 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21609
21933
  }
21610
21934
  if (expr.callee.kind === "Identifier" && expr.callee.name === "__forIn") {
21611
21935
  ctx.needsForInHelper = true;
21612
- const [obj, cb] = expr.arguments.map((a) => lowerExpression(a, ctx));
21936
+ const [obj, cb] = lowerArgsAsExpressions(expr.arguments);
21613
21937
  return t2.callExpression(t2.identifier("__fictForIn"), [
21614
21938
  obj ?? t2.identifier("undefined"),
21615
21939
  cb ?? t2.arrowFunctionExpression([], t2.identifier("undefined"))
@@ -21617,12 +21941,12 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21617
21941
  }
21618
21942
  if (expr.callee.kind === "Identifier" && expr.callee.name === "__fictPropsRest") {
21619
21943
  ctx.helpersUsed.add("propsRest");
21620
- const args = expr.arguments.map((a) => lowerExpression(a, ctx));
21944
+ const args = lowerCallArguments(expr.arguments);
21621
21945
  return t2.callExpression(t2.identifier(RUNTIME_ALIASES.propsRest), args);
21622
21946
  }
21623
21947
  if (expr.callee.kind === "Identifier" && expr.callee.name === "mergeProps") {
21624
21948
  ctx.helpersUsed.add("mergeProps");
21625
- const args = expr.arguments.map((a) => lowerExpression(a, ctx));
21949
+ const args = lowerCallArguments(expr.arguments);
21626
21950
  return t2.callExpression(t2.identifier(RUNTIME_ALIASES.mergeProps), args);
21627
21951
  }
21628
21952
  const isIIFE = (expr.callee.kind === "ArrowFunction" || expr.callee.kind === "FunctionExpression") && expr.arguments.length === 0 && expr.callee.params.length === 0;
@@ -21630,7 +21954,7 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21630
21954
  const calleeIsMemoAccessor = !!calleeName && ctx.memoVars?.has(calleeName);
21631
21955
  const calleeIsSignalLike = !!calleeName && (ctx.signalVars?.has(calleeName) || ctx.storeVars?.has(calleeName));
21632
21956
  if (calleeIsMemoAccessor && !calleeIsSignalLike && expr.arguments.length > 0) {
21633
- const loweredArgs2 = expr.arguments.map((a) => lowerExpression(a, ctx));
21957
+ const loweredArgs2 = lowerCallArguments(expr.arguments);
21634
21958
  return t2.callExpression(t2.callExpression(t2.identifier(calleeName), []), loweredArgs2);
21635
21959
  }
21636
21960
  const lowerCallee = () => isIIFE ? withNonReactiveScope(ctx, () => lowerExpression(expr.callee, ctx)) : lowerExpression(expr.callee, ctx);
@@ -21639,7 +21963,7 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21639
21963
  ) || expr.callee.property.kind === "Literal" && ["map", "reduce", "forEach", "filter", "flatMap", "some", "every", "find"].includes(
21640
21964
  String(expr.callee.property.value)
21641
21965
  ));
21642
- const loweredArgs = expr.arguments.map((a, idx) => {
21966
+ const loweredArgs = lowerCallArguments(expr.arguments, (a, idx) => {
21643
21967
  if (idx === 0 && isIteratingMethod && (a.kind === "ArrowFunction" || a.kind === "FunctionExpression")) {
21644
21968
  return withNoMemoAndDynamicHooks(ctx, () => lowerExpression(a, ctx));
21645
21969
  }
@@ -21745,67 +22069,81 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21745
22069
  case "ArrowFunction": {
21746
22070
  const paramIds = mapParams(expr.params);
21747
22071
  const shadowed = new Set(expr.params.map((p) => deSSAVarName(p.name)));
22072
+ const localDeclared = collectLocalDeclaredNames(
22073
+ expr.params,
22074
+ Array.isArray(expr.body) ? expr.body : null,
22075
+ t2
22076
+ );
21748
22077
  return withNonReactiveScope(
21749
22078
  ctx,
21750
- () => withFunctionScope(shadowed, () => {
21751
- let fn;
21752
- if (expr.isExpression && !Array.isArray(expr.body)) {
21753
- const { result: bodyExpr, cacheDeclarations } = withGetterCache(
21754
- ctx,
21755
- () => lowerTrackedExpression(expr.body, ctx)
21756
- );
21757
- if (cacheDeclarations.length > 0) {
22079
+ () => withFunctionScope(
22080
+ shadowed,
22081
+ () => {
22082
+ let fn;
22083
+ if (expr.isExpression && !Array.isArray(expr.body)) {
22084
+ const { result: bodyExpr, cacheDeclarations } = withGetterCache(
22085
+ ctx,
22086
+ () => lowerTrackedExpression(expr.body, ctx)
22087
+ );
22088
+ if (cacheDeclarations.length > 0) {
22089
+ fn = t2.arrowFunctionExpression(
22090
+ paramIds,
22091
+ t2.blockStatement([...cacheDeclarations, t2.returnStatement(bodyExpr)])
22092
+ );
22093
+ } else {
22094
+ fn = t2.arrowFunctionExpression(paramIds, bodyExpr);
22095
+ }
22096
+ } else if (Array.isArray(expr.body)) {
22097
+ const { result: stmts, cacheDeclarations } = withGetterCache(
22098
+ ctx,
22099
+ () => lowerStructuredBlocks(expr.body, expr.params, paramIds)
22100
+ );
21758
22101
  fn = t2.arrowFunctionExpression(
21759
22102
  paramIds,
21760
- t2.blockStatement([...cacheDeclarations, t2.returnStatement(bodyExpr)])
22103
+ t2.blockStatement([...cacheDeclarations, ...stmts])
21761
22104
  );
21762
22105
  } else {
21763
- fn = t2.arrowFunctionExpression(paramIds, bodyExpr);
22106
+ fn = t2.arrowFunctionExpression(paramIds, t2.blockStatement([]));
21764
22107
  }
21765
- } else if (Array.isArray(expr.body)) {
21766
- const { result: stmts, cacheDeclarations } = withGetterCache(
21767
- ctx,
21768
- () => lowerStructuredBlocks(expr.body, expr.params, paramIds)
21769
- );
21770
- fn = t2.arrowFunctionExpression(
21771
- paramIds,
21772
- t2.blockStatement([...cacheDeclarations, ...stmts])
21773
- );
21774
- } else {
21775
- fn = t2.arrowFunctionExpression(paramIds, t2.blockStatement([]));
21776
- }
21777
- fn.async = expr.isAsync ?? false;
21778
- return fn;
21779
- })
22108
+ fn.async = expr.isAsync ?? false;
22109
+ return fn;
22110
+ },
22111
+ localDeclared
22112
+ )
21780
22113
  );
21781
22114
  }
21782
22115
  case "FunctionExpression": {
21783
22116
  const paramIds = mapParams(expr.params);
21784
22117
  const shadowed = new Set(expr.params.map((p) => deSSAVarName(p.name)));
22118
+ const localDeclared = collectLocalDeclaredNames(expr.params, expr.body, t2);
21785
22119
  return withNonReactiveScope(
21786
22120
  ctx,
21787
- () => withFunctionScope(shadowed, () => {
21788
- let fn;
21789
- if (Array.isArray(expr.body)) {
21790
- const { result: stmts, cacheDeclarations } = withGetterCache(
21791
- ctx,
21792
- () => lowerStructuredBlocks(expr.body, expr.params, paramIds)
21793
- );
21794
- fn = t2.functionExpression(
21795
- expr.name ? t2.identifier(deSSAVarName(expr.name)) : null,
21796
- paramIds,
21797
- t2.blockStatement([...cacheDeclarations, ...stmts])
21798
- );
21799
- } else {
21800
- fn = t2.functionExpression(
21801
- expr.name ? t2.identifier(deSSAVarName(expr.name)) : null,
21802
- paramIds,
21803
- t2.blockStatement([])
21804
- );
21805
- }
21806
- fn.async = expr.isAsync ?? false;
21807
- return fn;
21808
- })
22121
+ () => withFunctionScope(
22122
+ shadowed,
22123
+ () => {
22124
+ let fn;
22125
+ if (Array.isArray(expr.body)) {
22126
+ const { result: stmts, cacheDeclarations } = withGetterCache(
22127
+ ctx,
22128
+ () => lowerStructuredBlocks(expr.body, expr.params, paramIds)
22129
+ );
22130
+ fn = t2.functionExpression(
22131
+ expr.name ? t2.identifier(deSSAVarName(expr.name)) : null,
22132
+ paramIds,
22133
+ t2.blockStatement([...cacheDeclarations, ...stmts])
22134
+ );
22135
+ } else {
22136
+ fn = t2.functionExpression(
22137
+ expr.name ? t2.identifier(deSSAVarName(expr.name)) : null,
22138
+ paramIds,
22139
+ t2.blockStatement([])
22140
+ );
22141
+ }
22142
+ fn.async = expr.isAsync ?? false;
22143
+ return fn;
22144
+ },
22145
+ localDeclared
22146
+ )
21809
22147
  );
21810
22148
  }
21811
22149
  case "AssignmentExpression":
@@ -21939,10 +22277,7 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21939
22277
  case "AwaitExpression":
21940
22278
  return t2.awaitExpression(lowerExpression(expr.argument, ctx));
21941
22279
  case "NewExpression":
21942
- return t2.newExpression(
21943
- lowerExpression(expr.callee, ctx),
21944
- expr.arguments.map((a) => lowerExpression(a, ctx))
21945
- );
22280
+ return t2.newExpression(lowerExpression(expr.callee, ctx), lowerCallArguments(expr.arguments));
21946
22281
  case "SequenceExpression":
21947
22282
  return t2.sequenceExpression(expr.expressions.map((e) => lowerExpression(e, ctx)));
21948
22283
  case "YieldExpression":
@@ -21953,7 +22288,7 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
21953
22288
  case "OptionalCallExpression":
21954
22289
  return t2.optionalCallExpression(
21955
22290
  lowerExpression(expr.callee, ctx),
21956
- expr.arguments.map((a) => lowerExpression(a, ctx)),
22291
+ lowerCallArguments(expr.arguments),
21957
22292
  expr.optional
21958
22293
  );
21959
22294
  case "TaggedTemplateExpression":
@@ -22085,26 +22420,17 @@ function lowerJSXElement(jsx, ctx) {
22085
22420
  ]);
22086
22421
  }
22087
22422
  ctx.helpersUsed.add("createElement");
22088
- const propsObj = buildPropsObject(jsx.attributes, ctx);
22089
22423
  const children = jsx.children.map((c) => lowerJSXChild(c, ctx));
22424
+ const propsExpr = buildPropsExpression(jsx.attributes, children, ctx, {
22425
+ lowerDomExpression,
22426
+ lowerTrackedExpression,
22427
+ expressionUsesTracked,
22428
+ deSSAVarName
22429
+ });
22090
22430
  const componentRef = typeof jsx.tagName === "string" ? t2.identifier(jsx.tagName) : lowerExpression(jsx.tagName, ctx);
22091
- const propsWithChildren = [];
22092
- if (propsObj && t2.isObjectExpression(propsObj)) {
22093
- propsWithChildren.push(...propsObj.properties);
22094
- }
22095
- if (children.length === 1 && children[0]) {
22096
- propsWithChildren.push(t2.objectProperty(t2.identifier("children"), children[0]));
22097
- } else if (children.length > 1) {
22098
- propsWithChildren.push(
22099
- t2.objectProperty(t2.identifier("children"), t2.arrayExpression(children))
22100
- );
22101
- }
22102
22431
  return t2.objectExpression([
22103
22432
  t2.objectProperty(t2.identifier("type"), componentRef),
22104
- t2.objectProperty(
22105
- t2.identifier("props"),
22106
- propsWithChildren.length > 0 ? t2.objectExpression(propsWithChildren) : t2.nullLiteral()
22107
- )
22433
+ t2.objectProperty(t2.identifier("props"), propsExpr ?? t2.nullLiteral())
22108
22434
  ]);
22109
22435
  }
22110
22436
  const useFineGrainedDom = !ctx.noMemo;
@@ -23857,98 +24183,6 @@ function lowerJSXChild(child, ctx) {
23857
24183
  return applyRegionMetadataToExpression(lowerExpression(child.value, ctx), ctx);
23858
24184
  }
23859
24185
  }
23860
- function buildPropsObject(attributes, ctx) {
23861
- const { t: t2 } = ctx;
23862
- const prevPropsContext = ctx.inPropsContext;
23863
- ctx.inPropsContext = true;
23864
- try {
23865
- if (attributes.length === 0) return null;
23866
- const properties = [];
23867
- const spreads = [];
23868
- const toPropKey = (name) => /^[a-zA-Z_$][\w$]*$/.test(name) ? t2.identifier(name) : t2.stringLiteral(name);
23869
- const isAccessorName = (name) => (ctx.memoVars?.has(name) ?? false) || (ctx.signalVars?.has(name) ?? false) || (ctx.aliasVars?.has(name) ?? false);
23870
- const wrapAccessorSource = (node) => {
23871
- if (t2.isCallExpression(node) && t2.isIdentifier(node.callee) && node.arguments.length === 0) {
23872
- const baseName2 = deSSAVarName(node.callee.name);
23873
- if (isAccessorName(baseName2)) {
23874
- return t2.arrowFunctionExpression([], node);
23875
- }
23876
- }
23877
- if (t2.isIdentifier(node)) {
23878
- const baseName2 = deSSAVarName(node.name);
23879
- if (isAccessorName(baseName2)) {
23880
- return t2.arrowFunctionExpression([], t2.callExpression(t2.identifier(baseName2), []));
23881
- }
23882
- }
23883
- return node;
23884
- };
23885
- for (const attr of attributes) {
23886
- if (attr.isSpread && attr.spreadExpr) {
23887
- let spreadExpr = lowerDomExpression(attr.spreadExpr, ctx);
23888
- if (t2.isCallExpression(spreadExpr)) {
23889
- const callExpr = spreadExpr;
23890
- const rewrittenArgs = callExpr.arguments.map(
23891
- (arg) => t2.isExpression(arg) ? wrapAccessorSource(arg) : arg
23892
- );
23893
- if (rewrittenArgs.some((arg, idx) => arg !== callExpr.arguments[idx])) {
23894
- spreadExpr = t2.callExpression(callExpr.callee, rewrittenArgs);
23895
- }
23896
- }
23897
- spreadExpr = wrapAccessorSource(spreadExpr);
23898
- spreads.push(t2.spreadElement(spreadExpr));
23899
- } else if (attr.value) {
23900
- const isFunctionLike = attr.value.kind === "ArrowFunction" || attr.value.kind === "FunctionExpression";
23901
- const prevPropsCtx = ctx.inPropsContext;
23902
- if (isFunctionLike) {
23903
- ctx.inPropsContext = false;
23904
- }
23905
- const lowered = lowerDomExpression(attr.value, ctx);
23906
- if (isFunctionLike) {
23907
- ctx.inPropsContext = prevPropsCtx;
23908
- }
23909
- const baseIdent = attr.value.kind === "Identifier" ? deSSAVarName(attr.value.name) : void 0;
23910
- const isAccessorBase = baseIdent && ((ctx.memoVars?.has(baseIdent) ?? false) || (ctx.signalVars?.has(baseIdent) ?? false) || (ctx.aliasVars?.has(baseIdent) ?? false));
23911
- const isStoreBase = baseIdent ? ctx.storeVars?.has(baseIdent) ?? false : false;
23912
- const alreadyGetter = isFunctionLike || (baseIdent ? isStoreBase || (ctx.memoVars?.has(baseIdent) ?? false) || (ctx.aliasVars?.has(baseIdent) ?? false) : false);
23913
- const usesTracked = (!ctx.nonReactiveScopeDepth || ctx.nonReactiveScopeDepth === 0) && expressionUsesTracked(attr.value, ctx) && !alreadyGetter;
23914
- const trackedExpr = usesTracked ? lowerTrackedExpression(attr.value, ctx) : null;
23915
- const useMemoProp = usesTracked && trackedExpr && t2.isExpression(trackedExpr) && !t2.isIdentifier(trackedExpr) && !t2.isMemberExpression(trackedExpr) && !t2.isLiteral(trackedExpr);
23916
- const valueExpr = !isFunctionLike && isAccessorBase && baseIdent ? (() => {
23917
- ctx.helpersUsed.add("propGetter");
23918
- return t2.callExpression(t2.identifier(RUNTIME_ALIASES.propGetter), [
23919
- t2.arrowFunctionExpression([], t2.callExpression(t2.identifier(baseIdent), []))
23920
- ]);
23921
- })() : usesTracked && t2.isExpression(lowered) ? (() => {
23922
- if (useMemoProp) {
23923
- ctx.helpersUsed.add("prop");
23924
- return t2.callExpression(t2.identifier(RUNTIME_ALIASES.prop), [
23925
- t2.arrowFunctionExpression(
23926
- [],
23927
- trackedExpr ?? lowered
23928
- )
23929
- ]);
23930
- }
23931
- ctx.helpersUsed.add("propGetter");
23932
- return t2.callExpression(t2.identifier(RUNTIME_ALIASES.propGetter), [
23933
- t2.arrowFunctionExpression(
23934
- [],
23935
- trackedExpr ?? lowered
23936
- )
23937
- ]);
23938
- })() : lowered;
23939
- properties.push(t2.objectProperty(toPropKey(attr.name), valueExpr));
23940
- } else {
23941
- properties.push(t2.objectProperty(toPropKey(attr.name), t2.booleanLiteral(true)));
23942
- }
23943
- }
23944
- if (spreads.length > 0) {
23945
- return t2.objectExpression([...spreads, ...properties]);
23946
- }
23947
- return t2.objectExpression(properties);
23948
- } finally {
23949
- ctx.inPropsContext = prevPropsContext;
23950
- }
23951
- }
23952
24186
  function isDOMProperty(name) {
23953
24187
  return ["value", "checked", "selected", "disabled", "readOnly", "multiple", "muted"].includes(
23954
24188
  name
@@ -23965,6 +24199,8 @@ function lowerHIRWithRegions(program, t2, options) {
23965
24199
  let topLevelCtxInjected = false;
23966
24200
  const emittedFunctionNames = /* @__PURE__ */ new Set();
23967
24201
  const originalBody = program.originalBody ?? [];
24202
+ ctx.moduleDeclaredNames = collectDeclaredNames(originalBody, t2);
24203
+ ctx.moduleRuntimeNames = collectRuntimeImportNames(originalBody, t2);
23968
24204
  for (const stmt of originalBody) {
23969
24205
  if (t2.isVariableDeclaration(stmt)) {
23970
24206
  for (const decl of stmt.declarations) {
@@ -24362,6 +24598,12 @@ function lowerFunctionWithRegions(fn, ctx) {
24362
24598
  const functionShadowed = new Set(prevShadowed ?? []);
24363
24599
  shadowedParams.forEach((n) => functionShadowed.add(n));
24364
24600
  ctx.shadowedNames = functionShadowed;
24601
+ const prevLocalDeclared = ctx.localDeclaredNames;
24602
+ const localDeclared = new Set(prevLocalDeclared ?? []);
24603
+ for (const name of collectLocalDeclaredNames(fn.params, fn.blocks, t2)) {
24604
+ localDeclared.add(name);
24605
+ }
24606
+ ctx.localDeclaredNames = localDeclared;
24365
24607
  const prevExternalTracked = ctx.externalTracked;
24366
24608
  const inheritedTracked = new Set(ctx.trackedVars);
24367
24609
  ctx.externalTracked = inheritedTracked;
@@ -24446,13 +24688,72 @@ function lowerFunctionWithRegions(fn, ctx) {
24446
24688
  let usesProp = false;
24447
24689
  let usesPropsRest = false;
24448
24690
  let warnedNested = false;
24691
+ const reportedPatternNodes = /* @__PURE__ */ new Set();
24692
+ const reportPatternDiagnostic = (node, code) => {
24693
+ if (reportedPatternNodes.has(node)) return;
24694
+ reportedPatternNodes.add(node);
24695
+ reportDiagnostic(ctx, code, node);
24696
+ };
24697
+ const reportPropsPatternIssues = (objectPattern, allowRest) => {
24698
+ for (const prop of objectPattern.properties) {
24699
+ if (t2.isObjectProperty(prop)) {
24700
+ if (prop.computed) {
24701
+ reportPatternDiagnostic(prop, "FICT-P003" /* FICT_P003 */);
24702
+ continue;
24703
+ }
24704
+ 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;
24705
+ if (!keyName) {
24706
+ reportPatternDiagnostic(prop, "FICT-P003" /* FICT_P003 */);
24707
+ continue;
24708
+ }
24709
+ const value = prop.value;
24710
+ if (t2.isIdentifier(value)) {
24711
+ continue;
24712
+ }
24713
+ if (t2.isObjectPattern(value)) {
24714
+ reportPropsPatternIssues(value, false);
24715
+ continue;
24716
+ }
24717
+ if (t2.isAssignmentPattern(value)) {
24718
+ if (t2.isIdentifier(value.left)) {
24719
+ continue;
24720
+ }
24721
+ reportPatternDiagnostic(prop, "FICT-P004" /* FICT_P004 */);
24722
+ continue;
24723
+ }
24724
+ if (t2.isArrayPattern(value)) {
24725
+ const hasRest = value.elements.some((el) => t2.isRestElement(el));
24726
+ reportPatternDiagnostic(
24727
+ value,
24728
+ hasRest ? "FICT-P002" /* FICT_P002 */ : "FICT-P001" /* FICT_P001 */
24729
+ );
24730
+ continue;
24731
+ }
24732
+ reportPatternDiagnostic(prop, "FICT-P004" /* FICT_P004 */);
24733
+ continue;
24734
+ }
24735
+ if (t2.isRestElement(prop)) {
24736
+ if (!allowRest || !t2.isIdentifier(prop.argument)) {
24737
+ reportPatternDiagnostic(prop, "FICT-P004" /* FICT_P004 */);
24738
+ }
24739
+ continue;
24740
+ }
24741
+ reportPatternDiagnostic(prop, "FICT-P004" /* FICT_P004 */);
24742
+ }
24743
+ };
24449
24744
  const memberExprForKey = (base, key) => t2.memberExpression(base, t2.identifier(key), false);
24450
24745
  const buildDestructure = (objectPattern, baseExpr, allowRest) => {
24451
24746
  for (const prop of objectPattern.properties) {
24452
- if (t2.isObjectProperty(prop) && !prop.computed) {
24747
+ if (t2.isObjectProperty(prop)) {
24748
+ if (prop.computed) {
24749
+ reportPatternDiagnostic(prop, "FICT-P003" /* FICT_P003 */);
24750
+ supported = false;
24751
+ warnedNested = true;
24752
+ break;
24753
+ }
24453
24754
  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;
24454
24755
  if (!keyName) {
24455
- reportDiagnostic(ctx, "FICT-P003" /* FICT_P003 */, prop);
24756
+ reportPatternDiagnostic(prop, "FICT-P003" /* FICT_P003 */);
24456
24757
  supported = false;
24457
24758
  warnedNested = true;
24458
24759
  break;
@@ -24485,26 +24786,44 @@ function lowerFunctionWithRegions(fn, ctx) {
24485
24786
  if (!supported) break;
24486
24787
  continue;
24487
24788
  }
24488
- if (t2.isAssignmentPattern(value) && t2.isIdentifier(value.left)) {
24489
- const shouldWrapProp = !calledIdentifiers.has(value.left.name);
24490
- if (shouldWrapProp) {
24491
- usesProp = true;
24492
- propsPlanAliases.add(value.left.name);
24789
+ if (t2.isAssignmentPattern(value)) {
24790
+ if (t2.isIdentifier(value.left)) {
24791
+ const shouldWrapProp = !calledIdentifiers.has(value.left.name);
24792
+ if (shouldWrapProp) {
24793
+ usesProp = true;
24794
+ propsPlanAliases.add(value.left.name);
24795
+ }
24796
+ const baseInit = t2.logicalExpression("??", member, value.right);
24797
+ const init = shouldWrapProp ? t2.callExpression(t2.identifier(RUNTIME_ALIASES.prop), [
24798
+ t2.arrowFunctionExpression([], baseInit)
24799
+ ]) : baseInit;
24800
+ stmts.push(
24801
+ t2.variableDeclaration("const", [
24802
+ t2.variableDeclarator(t2.identifier(value.left.name), init)
24803
+ ])
24804
+ );
24805
+ continue;
24493
24806
  }
24494
- const baseInit = t2.logicalExpression("??", member, value.right);
24495
- const init = shouldWrapProp ? t2.callExpression(t2.identifier(RUNTIME_ALIASES.prop), [
24496
- t2.arrowFunctionExpression([], baseInit)
24497
- ]) : baseInit;
24498
- stmts.push(
24499
- t2.variableDeclaration("const", [
24500
- t2.variableDeclarator(t2.identifier(value.left.name), init)
24501
- ])
24807
+ supported = false;
24808
+ if (!warnedNested) {
24809
+ reportPatternDiagnostic(prop, "FICT-P004" /* FICT_P004 */);
24810
+ warnedNested = true;
24811
+ }
24812
+ break;
24813
+ }
24814
+ if (t2.isArrayPattern(value)) {
24815
+ const hasRest = value.elements.some((el) => t2.isRestElement(el));
24816
+ reportPatternDiagnostic(
24817
+ value,
24818
+ hasRest ? "FICT-P002" /* FICT_P002 */ : "FICT-P001" /* FICT_P001 */
24502
24819
  );
24503
- continue;
24820
+ supported = false;
24821
+ warnedNested = true;
24822
+ break;
24504
24823
  }
24505
24824
  supported = false;
24506
24825
  if (!warnedNested) {
24507
- reportDiagnostic(ctx, "FICT-P004" /* FICT_P004 */, prop);
24826
+ reportPatternDiagnostic(prop, "FICT-P004" /* FICT_P004 */);
24508
24827
  warnedNested = true;
24509
24828
  }
24510
24829
  break;
@@ -24525,13 +24844,14 @@ function lowerFunctionWithRegions(fn, ctx) {
24525
24844
  } else {
24526
24845
  supported = false;
24527
24846
  if (!warnedNested) {
24528
- reportDiagnostic(ctx, "FICT-P004" /* FICT_P004 */, prop);
24847
+ reportPatternDiagnostic(prop, "FICT-P004" /* FICT_P004 */);
24529
24848
  warnedNested = true;
24530
24849
  }
24531
24850
  break;
24532
24851
  }
24533
24852
  }
24534
24853
  };
24854
+ reportPropsPatternIssues(pattern, true);
24535
24855
  buildDestructure(pattern, t2.identifier("__props"), true);
24536
24856
  if (supported) {
24537
24857
  propsDestructurePlan = {
@@ -24578,6 +24898,7 @@ function lowerFunctionWithRegions(fn, ctx) {
24578
24898
  if (!hasJSX && !hasTrackedValues) {
24579
24899
  ctx.needsCtx = prevNeedsCtx;
24580
24900
  ctx.shadowedNames = prevShadowed;
24901
+ ctx.localDeclaredNames = prevLocalDeclared;
24581
24902
  ctx.trackedVars = prevTracked;
24582
24903
  ctx.externalTracked = prevExternalTracked;
24583
24904
  ctx.signalVars = prevSignalVars;
@@ -24660,6 +24981,7 @@ function lowerFunctionWithRegions(fn, ctx) {
24660
24981
  );
24661
24982
  ctx.needsCtx = prevNeedsCtx;
24662
24983
  ctx.shadowedNames = prevShadowed;
24984
+ ctx.localDeclaredNames = prevLocalDeclared;
24663
24985
  ctx.trackedVars = prevTracked;
24664
24986
  ctx.externalTracked = prevExternalTracked;
24665
24987
  ctx.signalVars = prevSignalVars;