@fictjs/compiler 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -14135,6 +14135,9 @@ var RUNTIME_HELPERS = {
14135
14135
  conditional: "createConditional",
14136
14136
  keyedList: "createKeyedList",
14137
14137
  insert: "insert",
14138
+ insertBetween: "insertBetween",
14139
+ resolvePath: "resolvePath",
14140
+ getSlotEnd: "getSlotEnd",
14138
14141
  onDestroy: "onDestroy",
14139
14142
  bindText: "bindText",
14140
14143
  bindAttribute: "bindAttribute",
@@ -14146,7 +14149,18 @@ var RUNTIME_HELPERS = {
14146
14149
  bindRef: "bindRef",
14147
14150
  toNodeArray: "toNodeArray",
14148
14151
  template: "template",
14149
- delegateEvents: "delegateEvents"
14152
+ delegateEvents: "delegateEvents",
14153
+ useLexicalScope: "__fictUseLexicalScope",
14154
+ getScopeProps: "__fictGetScopeProps",
14155
+ qrl: "__fictQrl",
14156
+ getSSRScope: "__fictGetSSRScope",
14157
+ ensureScope: "__fictEnsureScope",
14158
+ prepareContext: "__fictPrepareContext",
14159
+ enterHydration: "__fictEnterHydration",
14160
+ exitHydration: "__fictExitHydration",
14161
+ domRender: "render",
14162
+ hydrateComponent: "hydrateComponent",
14163
+ registerResume: "__fictRegisterResume"
14150
14164
  };
14151
14165
  var RUNTIME_ALIASES = {
14152
14166
  signal: "createSignal",
@@ -14171,6 +14185,9 @@ var RUNTIME_ALIASES = {
14171
14185
  conditional: "createConditional",
14172
14186
  keyedList: "createKeyedList",
14173
14187
  insert: "insert",
14188
+ insertBetween: "insertBetween",
14189
+ resolvePath: "resolvePath",
14190
+ getSlotEnd: "getSlotEnd",
14174
14191
  onDestroy: "onDestroy",
14175
14192
  bindText: "bindText",
14176
14193
  bindAttribute: "bindAttribute",
@@ -14182,7 +14199,18 @@ var RUNTIME_ALIASES = {
14182
14199
  bindRef: "bindRef",
14183
14200
  toNodeArray: "toNodeArray",
14184
14201
  template: "template",
14185
- delegateEvents: "delegateEvents"
14202
+ delegateEvents: "delegateEvents",
14203
+ useLexicalScope: "__fictUseLexicalScope",
14204
+ getScopeProps: "__fictGetScopeProps",
14205
+ qrl: "__fictQrl",
14206
+ getSSRScope: "__fictGetSSRScope",
14207
+ ensureScope: "__fictEnsureScope",
14208
+ prepareContext: "__fictPrepareContext",
14209
+ enterHydration: "__fictEnterHydration",
14210
+ exitHydration: "__fictExitHydration",
14211
+ domRender: "render",
14212
+ hydrateComponent: "hydrateComponent",
14213
+ registerResume: "__fictRegisterResume"
14186
14214
  };
14187
14215
  var DelegatedEvents = /* @__PURE__ */ new Set([...DelegatedEventNames]);
14188
14216
  var SAFE_FUNCTIONS = /* @__PURE__ */ new Set([
@@ -14533,6 +14561,9 @@ function parseFictReturnAnnotation(node) {
14533
14561
  if (content === "'memo'" || content === '"memo"') {
14534
14562
  return { directAccessor: "memo" };
14535
14563
  }
14564
+ if (/^\{\s*\}$/.test(content)) {
14565
+ return { objectProps: /* @__PURE__ */ new Map() };
14566
+ }
14536
14567
  const objectMatch = content.match(/^\{([^}]+)\}$/);
14537
14568
  if (objectMatch) {
14538
14569
  const objectProps = /* @__PURE__ */ new Map();
@@ -16362,6 +16393,9 @@ function convertJSXMemberExpr(node) {
16362
16393
  };
16363
16394
  }
16364
16395
 
16396
+ // src/ir/codegen.ts
16397
+ import { pathToFileURL } from "url";
16398
+
16365
16399
  // src/fine-grained-dom.ts
16366
16400
  function normalizeDependencyKey(name) {
16367
16401
  return name.split(".").map((part) => part.replace(/_\d+$/, "")).join(".");
@@ -21161,9 +21195,14 @@ function instructionToStatement(instr, t4, declaredVars, ctx, _buildMemoCall) {
21161
21195
  declaredVars.add(baseName2);
21162
21196
  if (treatAsTracked && !isDestructuringTemp) {
21163
21197
  if (isStateCall2) {
21164
- return t4.variableDeclaration(normalizedDecl, [
21165
- t4.variableDeclarator(t4.identifier(baseName2), lowerAssignedValue(true))
21166
- ]);
21198
+ ctx.currentAssignmentName = baseName2;
21199
+ try {
21200
+ return t4.variableDeclaration(normalizedDecl, [
21201
+ t4.variableDeclarator(t4.identifier(baseName2), lowerAssignedValue(true))
21202
+ ]);
21203
+ } finally {
21204
+ ctx.currentAssignmentName = void 0;
21205
+ }
21167
21206
  }
21168
21207
  if (dependsOnTracked) {
21169
21208
  if (instr.value.kind === "Identifier" && ctx.trackedVars.has(deSSAVarName(instr.value.name)) && !isDestructuringTemp) {
@@ -22086,7 +22125,17 @@ function createCodegenContext(t4) {
22086
22125
  hookReturnInfo: /* @__PURE__ */ new Map(),
22087
22126
  hoistedTemplates: /* @__PURE__ */ new Map(),
22088
22127
  hoistedTemplateStatements: [],
22089
- delegatedEventsUsed: /* @__PURE__ */ new Set()
22128
+ hoistedResumableStatements: [],
22129
+ resumableHandlerCounter: 0,
22130
+ resumableComponentCounter: 0,
22131
+ resumableComponents: /* @__PURE__ */ new Map(),
22132
+ resumableEnabled: false,
22133
+ autoExtractEnabled: false,
22134
+ autoExtractThreshold: 3,
22135
+ delegatedEventsUsed: /* @__PURE__ */ new Set(),
22136
+ componentFunctionDefs: /* @__PURE__ */ new Map(),
22137
+ hoistedFunctionDepCounter: 0,
22138
+ hoistedFunctionDepNames: /* @__PURE__ */ new Map()
22090
22139
  };
22091
22140
  }
22092
22141
  function withGetterCache(ctx, fn) {
@@ -22992,6 +23041,51 @@ function computeReactiveAccessors(fn, ctx) {
22992
23041
  function genTemp(ctx, prefix = "tmp") {
22993
23042
  return ctx.t.identifier(`__${prefix}_${ctx.tempCounter++}`);
22994
23043
  }
23044
+ function renameIdentifiersInExpr(expr, renames, _t) {
23045
+ const cloned = JSON.parse(JSON.stringify(expr));
23046
+ function visit(node) {
23047
+ if (!node || typeof node !== "object") return;
23048
+ const n = node;
23049
+ if (n.type === "Identifier" && typeof n.name === "string") {
23050
+ const newName = renames.get(n.name);
23051
+ if (newName) {
23052
+ n.name = newName;
23053
+ }
23054
+ }
23055
+ for (const key of Object.keys(n)) {
23056
+ if (key === "loc" || key === "start" || key === "end" || key === "extra" || key === "comments" || key === "leadingComments" || key === "trailingComments") {
23057
+ continue;
23058
+ }
23059
+ const value = n[key];
23060
+ if (Array.isArray(value)) {
23061
+ for (const item of value) {
23062
+ visit(item);
23063
+ }
23064
+ } else if (value && typeof value === "object") {
23065
+ visit(value);
23066
+ }
23067
+ }
23068
+ }
23069
+ visit(cloned);
23070
+ return cloned;
23071
+ }
23072
+ function genModuleUrlExpr(ctx) {
23073
+ const { t: t4 } = ctx;
23074
+ const filename = ctx.options?.filename;
23075
+ if (filename) {
23076
+ let fileUrl;
23077
+ if (filename.startsWith("file://")) {
23078
+ fileUrl = filename;
23079
+ } else {
23080
+ fileUrl = pathToFileURL(filename).href;
23081
+ }
23082
+ return t4.stringLiteral(fileUrl);
23083
+ }
23084
+ return t4.memberExpression(
23085
+ t4.metaProperty(t4.identifier("import"), t4.identifier("meta")),
23086
+ t4.identifier("url")
23087
+ );
23088
+ }
22995
23089
  function extractKeyFromAttributes(attributes) {
22996
23090
  for (const attr of attributes) {
22997
23091
  if (attr.name === "key" && attr.value) {
@@ -23115,6 +23209,26 @@ function lowerInstruction(instr, ctx) {
23115
23209
  ctx.memoVars?.add(baseName2);
23116
23210
  }
23117
23211
  }
23212
+ if (declKind) {
23213
+ const initKind = getReactiveCallKind(instr.value, ctx);
23214
+ if (initKind === "signal") {
23215
+ ctx.signalVars?.add(baseName2);
23216
+ ctx.trackedVars.add(baseName2);
23217
+ ctx.currentAssignmentName = baseName2;
23218
+ const loweredValue = (() => {
23219
+ try {
23220
+ return lowerTrackedExpression(instr.value, ctx);
23221
+ } finally {
23222
+ ctx.currentAssignmentName = void 0;
23223
+ }
23224
+ })();
23225
+ return applyLoc(
23226
+ t4.variableDeclaration(declKind, [
23227
+ t4.variableDeclarator(t4.identifier(baseName2), loweredValue)
23228
+ ])
23229
+ );
23230
+ }
23231
+ }
23118
23232
  if (ctx.signalVars?.has(baseName2)) {
23119
23233
  ctx.currentAssignmentName = baseName2;
23120
23234
  const loweredValue = (() => {
@@ -23840,23 +23954,23 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
23840
23954
  case "MetaProperty":
23841
23955
  return t4.metaProperty(t4.identifier(expr.meta.name), t4.identifier(expr.property.name));
23842
23956
  case "CallExpression": {
23843
- if (expr.callee.kind === "Identifier" && expr.callee.name === "$state") {
23957
+ const stateCalleeNameRaw = expr.callee.kind === "Identifier" ? expr.callee.name : null;
23958
+ const stateCalleeName = stateCalleeNameRaw ? deSSAVarName(stateCalleeNameRaw) : null;
23959
+ if (stateCalleeName && ctx.stateMacroNames?.has(stateCalleeName)) {
23844
23960
  const args = lowerCallArguments(expr.arguments);
23845
23961
  const includeDevtools = ctx.options?.dev !== false;
23846
- if (includeDevtools) {
23847
- const options = [];
23848
- if (ctx.currentAssignmentName) {
23849
- options.push(
23850
- t4.objectProperty(t4.identifier("name"), t4.stringLiteral(ctx.currentAssignmentName))
23851
- );
23852
- }
23853
- if (expr.loc) {
23854
- const source = `${ctx.options?.filename ?? ""}:${expr.loc.start.line}:${expr.loc.start.column}`;
23855
- options.push(t4.objectProperty(t4.identifier("devToolsSource"), t4.stringLiteral(source)));
23856
- }
23857
- if (options.length > 0) {
23858
- args.push(t4.objectExpression(options));
23859
- }
23962
+ const options = [];
23963
+ if (ctx.currentAssignmentName) {
23964
+ options.push(
23965
+ t4.objectProperty(t4.identifier("name"), t4.stringLiteral(ctx.currentAssignmentName))
23966
+ );
23967
+ }
23968
+ if (includeDevtools && expr.loc) {
23969
+ const source = `${ctx.options?.filename ?? ""}:${expr.loc.start.line}:${expr.loc.start.column}`;
23970
+ options.push(t4.objectProperty(t4.identifier("devToolsSource"), t4.stringLiteral(source)));
23971
+ }
23972
+ if (options.length > 0) {
23973
+ args.push(t4.objectExpression(options));
23860
23974
  }
23861
23975
  if (ctx.inModule) {
23862
23976
  ctx.helpersUsed.add("signal");
@@ -25010,17 +25124,280 @@ function resolveNamespaceContext(tagName, parentNamespace) {
25010
25124
  if (tagName === "foreignObject" && parentNamespace === "svg") return null;
25011
25125
  return parentNamespace;
25012
25126
  }
25127
+ function countExpressionNodes(expr) {
25128
+ if (!expr) return 0;
25129
+ let count = 1;
25130
+ switch (expr.kind) {
25131
+ case "Literal":
25132
+ return 1;
25133
+ case "Identifier":
25134
+ return 1;
25135
+ case "BinaryExpression":
25136
+ case "LogicalExpression":
25137
+ count += countExpressionNodes(expr.left);
25138
+ count += countExpressionNodes(expr.right);
25139
+ return count;
25140
+ case "UnaryExpression":
25141
+ count += countExpressionNodes(expr.argument);
25142
+ return count;
25143
+ case "ConditionalExpression":
25144
+ count += countExpressionNodes(expr.test);
25145
+ count += countExpressionNodes(expr.consequent);
25146
+ count += countExpressionNodes(expr.alternate);
25147
+ return count;
25148
+ case "CallExpression":
25149
+ count += countExpressionNodes(expr.callee);
25150
+ for (const arg of expr.arguments) {
25151
+ count += countExpressionNodes(arg);
25152
+ }
25153
+ return count;
25154
+ case "MemberExpression":
25155
+ count += countExpressionNodes(expr.object);
25156
+ if (expr.computed && expr.property) {
25157
+ count += countExpressionNodes(expr.property);
25158
+ }
25159
+ return count;
25160
+ case "ArrayExpression":
25161
+ for (const elem of expr.elements) {
25162
+ if (elem) count += countExpressionNodes(elem);
25163
+ }
25164
+ return count;
25165
+ case "ObjectExpression":
25166
+ for (const prop of expr.properties) {
25167
+ if (prop.kind === "Property") {
25168
+ count += countExpressionNodes(prop.value);
25169
+ } else if (prop.kind === "SpreadElement") {
25170
+ count += countExpressionNodes(prop.argument);
25171
+ }
25172
+ }
25173
+ return count;
25174
+ case "ArrowFunction":
25175
+ if (expr.isExpression && expr.body && !Array.isArray(expr.body)) {
25176
+ count += countExpressionNodes(expr.body);
25177
+ } else if (Array.isArray(expr.body)) {
25178
+ for (const block of expr.body) {
25179
+ count += countBlockNodes(block);
25180
+ }
25181
+ }
25182
+ return count;
25183
+ case "FunctionExpression":
25184
+ if (expr.body) {
25185
+ for (const block of expr.body) {
25186
+ count += countBlockNodes(block);
25187
+ }
25188
+ }
25189
+ return count;
25190
+ case "AssignmentExpression":
25191
+ count += countExpressionNodes(expr.left);
25192
+ count += countExpressionNodes(expr.right);
25193
+ return count;
25194
+ case "UpdateExpression":
25195
+ count += countExpressionNodes(expr.argument);
25196
+ return count;
25197
+ case "SequenceExpression":
25198
+ for (const e of expr.expressions) {
25199
+ count += countExpressionNodes(e);
25200
+ }
25201
+ return count;
25202
+ case "AwaitExpression":
25203
+ count += countExpressionNodes(expr.argument);
25204
+ return count + 2;
25205
+ // Async adds complexity
25206
+ case "NewExpression":
25207
+ count += countExpressionNodes(expr.callee);
25208
+ for (const arg of expr.arguments) {
25209
+ count += countExpressionNodes(arg);
25210
+ }
25211
+ return count;
25212
+ case "TemplateLiteral":
25213
+ for (const e of expr.expressions) {
25214
+ count += countExpressionNodes(e);
25215
+ }
25216
+ return count;
25217
+ default:
25218
+ return count;
25219
+ }
25220
+ }
25221
+ function countBlockNodes(block) {
25222
+ let count = 1;
25223
+ for (const instr of block.instructions) {
25224
+ count += countInstructionNodes(instr);
25225
+ }
25226
+ return count;
25227
+ }
25228
+ function countInstructionNodes(instr) {
25229
+ switch (instr.kind) {
25230
+ case "Expression":
25231
+ return 1 + countExpressionNodes(instr.value);
25232
+ case "Assign":
25233
+ return 1 + countExpressionNodes(instr.value);
25234
+ case "Phi":
25235
+ return 1;
25236
+ default:
25237
+ return 1;
25238
+ }
25239
+ }
25240
+ function hasExternalCalls(expr) {
25241
+ if (!expr) return false;
25242
+ switch (expr.kind) {
25243
+ case "CallExpression": {
25244
+ if (expr.callee.kind === "Identifier") {
25245
+ const name = expr.callee.name;
25246
+ if (!["console", "Math", "JSON", "Object", "Array"].includes(name)) {
25247
+ return true;
25248
+ }
25249
+ }
25250
+ if (expr.callee.kind === "MemberExpression") {
25251
+ return true;
25252
+ }
25253
+ for (const arg of expr.arguments) {
25254
+ if (hasExternalCalls(arg)) return true;
25255
+ }
25256
+ return false;
25257
+ }
25258
+ case "ArrowFunction":
25259
+ if (expr.isExpression && expr.body && !Array.isArray(expr.body)) {
25260
+ return hasExternalCalls(expr.body);
25261
+ } else if (Array.isArray(expr.body)) {
25262
+ for (const block of expr.body) {
25263
+ if (blockHasExternalCalls(block)) return true;
25264
+ }
25265
+ }
25266
+ return false;
25267
+ case "FunctionExpression":
25268
+ if (expr.body) {
25269
+ for (const block of expr.body) {
25270
+ if (blockHasExternalCalls(block)) return true;
25271
+ }
25272
+ }
25273
+ return false;
25274
+ case "BinaryExpression":
25275
+ case "LogicalExpression":
25276
+ return hasExternalCalls(expr.left) || hasExternalCalls(expr.right);
25277
+ case "UnaryExpression":
25278
+ return hasExternalCalls(expr.argument);
25279
+ case "ConditionalExpression":
25280
+ return hasExternalCalls(expr.test) || hasExternalCalls(expr.consequent) || hasExternalCalls(expr.alternate);
25281
+ case "MemberExpression":
25282
+ return hasExternalCalls(expr.object);
25283
+ case "AssignmentExpression":
25284
+ return hasExternalCalls(expr.right);
25285
+ case "SequenceExpression":
25286
+ return expr.expressions.some((e) => hasExternalCalls(e));
25287
+ case "AwaitExpression":
25288
+ return true;
25289
+ // Await implies async external operation
25290
+ case "NewExpression":
25291
+ return true;
25292
+ // Constructor calls are external
25293
+ default:
25294
+ return false;
25295
+ }
25296
+ }
25297
+ function blockHasExternalCalls(block) {
25298
+ for (const instr of block.instructions) {
25299
+ if (instructionHasExternalCalls(instr)) return true;
25300
+ }
25301
+ return false;
25302
+ }
25303
+ function instructionHasExternalCalls(instr) {
25304
+ switch (instr.kind) {
25305
+ case "Expression":
25306
+ return hasExternalCalls(instr.value);
25307
+ case "Assign":
25308
+ return hasExternalCalls(instr.value);
25309
+ default:
25310
+ return false;
25311
+ }
25312
+ }
25313
+ function hasAsyncAwait(expr) {
25314
+ if (!expr) return false;
25315
+ switch (expr.kind) {
25316
+ case "AwaitExpression":
25317
+ return true;
25318
+ case "ArrowFunction":
25319
+ if (expr.isAsync) return true;
25320
+ if (expr.isExpression && expr.body && !Array.isArray(expr.body)) {
25321
+ return hasAsyncAwait(expr.body);
25322
+ } else if (Array.isArray(expr.body)) {
25323
+ for (const block of expr.body) {
25324
+ if (blockHasAsyncAwait(block)) return true;
25325
+ }
25326
+ }
25327
+ return false;
25328
+ case "FunctionExpression":
25329
+ if (expr.isAsync) return true;
25330
+ if (expr.body) {
25331
+ for (const block of expr.body) {
25332
+ if (blockHasAsyncAwait(block)) return true;
25333
+ }
25334
+ }
25335
+ return false;
25336
+ case "CallExpression":
25337
+ if (hasAsyncAwait(expr.callee)) return true;
25338
+ return expr.arguments.some((arg) => hasAsyncAwait(arg));
25339
+ case "BinaryExpression":
25340
+ case "LogicalExpression":
25341
+ return hasAsyncAwait(expr.left) || hasAsyncAwait(expr.right);
25342
+ case "ConditionalExpression":
25343
+ return hasAsyncAwait(expr.test) || hasAsyncAwait(expr.consequent) || hasAsyncAwait(expr.alternate);
25344
+ case "SequenceExpression":
25345
+ return expr.expressions.some((e) => hasAsyncAwait(e));
25346
+ default:
25347
+ return false;
25348
+ }
25349
+ }
25350
+ function blockHasAsyncAwait(block) {
25351
+ for (const instr of block.instructions) {
25352
+ if (instructionHasAsyncAwait(instr)) return true;
25353
+ }
25354
+ return false;
25355
+ }
25356
+ function instructionHasAsyncAwait(instr) {
25357
+ switch (instr.kind) {
25358
+ case "Expression":
25359
+ return hasAsyncAwait(instr.value);
25360
+ case "Assign":
25361
+ return hasAsyncAwait(instr.value);
25362
+ default:
25363
+ return false;
25364
+ }
25365
+ }
25366
+ function shouldAutoExtract(expr, ctx) {
25367
+ if (!expr) return false;
25368
+ if (!ctx.autoExtractEnabled) return false;
25369
+ const threshold = ctx.autoExtractThreshold ?? 3;
25370
+ if (expr.kind === "Identifier") {
25371
+ return true;
25372
+ }
25373
+ if (expr.kind === "ArrowFunction" || expr.kind === "FunctionExpression") {
25374
+ if (expr.kind === "ArrowFunction" && expr.isAsync || expr.kind === "FunctionExpression" && expr.isAsync || hasAsyncAwait(expr)) {
25375
+ return true;
25376
+ }
25377
+ if (hasExternalCalls(expr)) {
25378
+ return true;
25379
+ }
25380
+ const nodeCount2 = countExpressionNodes(expr);
25381
+ if (nodeCount2 >= threshold) {
25382
+ return true;
25383
+ }
25384
+ return false;
25385
+ }
25386
+ const nodeCount = countExpressionNodes(expr);
25387
+ return nodeCount >= threshold;
25388
+ }
25013
25389
  function extractHIRStaticHtml(jsx, ctx, parentPath = [], namespace = null) {
25014
25390
  if (jsx.isComponent || typeof jsx.tagName !== "string") {
25015
25391
  return {
25016
- html: "<!---->",
25392
+ html: "<!--fict:slot:start--><!--fict:slot:end-->",
25017
25393
  bindings: [
25018
25394
  {
25019
25395
  type: "child",
25020
25396
  path: [...parentPath],
25021
25397
  expr: jsx
25022
25398
  }
25023
- ]
25399
+ ],
25400
+ nodeCount: 1
25024
25401
  };
25025
25402
  }
25026
25403
  const tagName = jsx.tagName;
@@ -25031,7 +25408,11 @@ function extractHIRStaticHtml(jsx, ctx, parentPath = [], namespace = null) {
25031
25408
  if (attr.isSpread) {
25032
25409
  continue;
25033
25410
  }
25034
- const name = normalizeHIRAttrName(attr.name);
25411
+ let name = normalizeHIRAttrName(attr.name);
25412
+ const isResumableEvent = name.endsWith("$");
25413
+ if (isResumableEvent) {
25414
+ name = name.slice(0, -1);
25415
+ }
25035
25416
  if (name === "key") {
25036
25417
  if (attr.value && !isStaticValue(attr.value)) {
25037
25418
  bindings.push({
@@ -25066,12 +25447,14 @@ function extractHIRStaticHtml(jsx, ctx, parentPath = [], namespace = null) {
25066
25447
  changed = true;
25067
25448
  }
25068
25449
  }
25450
+ const shouldBeResumable = isResumableEvent && ctx.resumableEnabled || !isResumableEvent && ctx.resumableEnabled && shouldAutoExtract(attr.value ?? void 0, ctx);
25069
25451
  bindings.push({
25070
25452
  type: "event",
25071
25453
  path: [...parentPath],
25072
25454
  name: eventName.toLowerCase(),
25073
25455
  expr: attr.value ?? void 0,
25074
- eventOptions: { capture, passive, once }
25456
+ eventOptions: { capture, passive, once },
25457
+ resumable: shouldBeResumable
25075
25458
  });
25076
25459
  continue;
25077
25460
  }
@@ -25127,7 +25510,7 @@ function extractHIRStaticHtml(jsx, ctx, parentPath = [], namespace = null) {
25127
25510
  const childResult = extractHIRStaticHtml(child.value, ctx, childPath, resolvedNamespace);
25128
25511
  html += childResult.html;
25129
25512
  bindings.push(...childResult.bindings);
25130
- childIndex++;
25513
+ childIndex += childResult.nodeCount;
25131
25514
  } else if (child.kind === "expression") {
25132
25515
  const inline = hasAdjacentInline(i);
25133
25516
  if (!inline && isLikelyTextExpression(child.value, ctx)) {
@@ -25140,7 +25523,7 @@ function extractHIRStaticHtml(jsx, ctx, parentPath = [], namespace = null) {
25140
25523
  namespace: resolvedNamespace
25141
25524
  });
25142
25525
  } else {
25143
- html += "<!---->";
25526
+ html += "<!--fict:slot:start--><!--fict:slot:end-->";
25144
25527
  bindings.push({
25145
25528
  type: "child",
25146
25529
  path: [...parentPath, childIndex],
@@ -25148,6 +25531,8 @@ function extractHIRStaticHtml(jsx, ctx, parentPath = [], namespace = null) {
25148
25531
  // Track namespace for dynamic child bindings
25149
25532
  namespace: resolvedNamespace
25150
25533
  });
25534
+ childIndex++;
25535
+ continue;
25151
25536
  }
25152
25537
  childIndex++;
25153
25538
  }
@@ -25158,6 +25543,7 @@ function extractHIRStaticHtml(jsx, ctx, parentPath = [], namespace = null) {
25158
25543
  return {
25159
25544
  html,
25160
25545
  bindings,
25546
+ nodeCount: 1,
25161
25547
  isSVG: needsSVG || void 0,
25162
25548
  isMathML: needsMathML || void 0
25163
25549
  };
@@ -25249,6 +25635,17 @@ function lowerIntrinsicElement(jsx, ctx) {
25249
25635
  const eventName = binding.name;
25250
25636
  const hasEventOptions = binding.eventOptions && (binding.eventOptions.capture || binding.eventOptions.passive || binding.eventOptions.once);
25251
25637
  const isDelegated = DelegatedEvents.has(eventName) && !hasEventOptions;
25638
+ if (binding.resumable && !hasEventOptions) {
25639
+ emitResumableEventBinding(
25640
+ targetId,
25641
+ eventName,
25642
+ binding.expr,
25643
+ statements,
25644
+ ctx,
25645
+ containingRegion
25646
+ );
25647
+ continue;
25648
+ }
25252
25649
  const hirDataBinding = isDelegated && binding.expr ? extractDelegatedEventDataFromHIR(binding.expr, ctx) : null;
25253
25650
  if (hirDataBinding) {
25254
25651
  ctx.delegatedEventsUsed?.add(eventName);
@@ -25545,13 +25942,16 @@ function resolveHIRBindingPath(path2, cache, statements, ctx) {
25545
25942
  ancestorId = cache.get("");
25546
25943
  relativePath = path2;
25547
25944
  }
25548
- let currentExpr = ancestorId;
25549
- for (const index of relativePath) {
25550
- currentExpr = t4.memberExpression(currentExpr, t4.identifier("firstChild"));
25551
- for (let i = 0; i < index; i++) {
25552
- currentExpr = t4.memberExpression(currentExpr, t4.identifier("nextSibling"));
25553
- }
25945
+ if (relativePath.length === 0) {
25946
+ cache.set(key, ancestorId);
25947
+ return ancestorId;
25554
25948
  }
25949
+ ctx.helpersUsed.add("resolvePath");
25950
+ const pathExpr = t4.arrayExpression(relativePath.map((index) => t4.numericLiteral(index)));
25951
+ const currentExpr = t4.callExpression(t4.identifier(RUNTIME_ALIASES.resolvePath), [
25952
+ ancestorId,
25953
+ pathExpr
25954
+ ]);
25555
25955
  const varId = genTemp(ctx, "el");
25556
25956
  statements.push(t4.variableDeclaration("const", [t4.variableDeclarator(varId, currentExpr)]));
25557
25957
  cache.set(key, varId);
@@ -25559,7 +25959,16 @@ function resolveHIRBindingPath(path2, cache, statements, ctx) {
25559
25959
  }
25560
25960
  function emitHIRChildBinding(markerId, expr, statements, ctx, containingRegion, namespace) {
25561
25961
  const { t: t4 } = ctx;
25562
- const parentId = t4.memberExpression(markerId, t4.identifier("parentNode"));
25962
+ ctx.helpersUsed.add("getSlotEnd");
25963
+ const endMarkerId = genTemp(ctx, "end");
25964
+ statements.push(
25965
+ t4.variableDeclaration("const", [
25966
+ t4.variableDeclarator(
25967
+ endMarkerId,
25968
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.getSlotEnd), [markerId])
25969
+ )
25970
+ ])
25971
+ );
25563
25972
  if (namespace !== void 0) {
25564
25973
  ctx.namespaceContext = namespace;
25565
25974
  }
@@ -25578,26 +25987,26 @@ function emitHIRChildBinding(markerId, expr, statements, ctx, containingRegion,
25578
25987
  return;
25579
25988
  }
25580
25989
  if (expr.kind === "ConditionalExpression" || expr.kind === "LogicalExpression" && expr.operator === "&&") {
25581
- emitConditionalChild(parentId, markerId, expr, statements, ctx);
25990
+ emitConditionalChild(markerId, endMarkerId, expr, statements, ctx);
25582
25991
  return;
25583
25992
  }
25584
25993
  if (expr.kind === "CallExpression" || expr.kind === "OptionalCallExpression") {
25585
25994
  const callee = expr.callee;
25586
25995
  if ((callee.kind === "MemberExpression" || callee.kind === "OptionalMemberExpression") && callee.property.kind === "Identifier" && callee.property.name === "map") {
25587
- emitListChild(parentId, markerId, expr, statements, ctx);
25996
+ emitListChild(markerId, endMarkerId, expr, statements, ctx);
25588
25997
  return;
25589
25998
  }
25590
25999
  }
25591
26000
  if (expr.kind === "JSXElement") {
25592
26001
  const childExpr = lowerJSXElement(expr, ctx);
25593
- ctx.helpersUsed.add("insert");
26002
+ ctx.helpersUsed.add("insertBetween");
25594
26003
  ctx.helpersUsed.add("createElement");
25595
26004
  statements.push(
25596
26005
  t4.expressionStatement(
25597
- t4.callExpression(t4.identifier(RUNTIME_ALIASES.insert), [
25598
- parentId,
25599
- t4.arrowFunctionExpression([], childExpr),
26006
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.insertBetween), [
25600
26007
  markerId,
26008
+ endMarkerId,
26009
+ t4.arrowFunctionExpression([], childExpr),
25601
26010
  t4.identifier(RUNTIME_ALIASES.createElement)
25602
26011
  ])
25603
26012
  )
@@ -25605,20 +26014,280 @@ function emitHIRChildBinding(markerId, expr, statements, ctx, containingRegion,
25605
26014
  return;
25606
26015
  }
25607
26016
  const valueExpr = lowerDomExpression(expr, ctx, containingRegion);
25608
- ctx.helpersUsed.add("insert");
26017
+ ctx.helpersUsed.add("insertBetween");
25609
26018
  ctx.helpersUsed.add("createElement");
25610
26019
  statements.push(
25611
26020
  t4.expressionStatement(
25612
- t4.callExpression(t4.identifier(RUNTIME_ALIASES.insert), [
25613
- parentId,
25614
- t4.arrowFunctionExpression([], valueExpr),
26021
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.insertBetween), [
25615
26022
  markerId,
26023
+ endMarkerId,
26024
+ t4.arrowFunctionExpression([], valueExpr),
25616
26025
  t4.identifier(RUNTIME_ALIASES.createElement)
25617
26026
  ])
25618
26027
  )
25619
26028
  );
25620
26029
  }
25621
- function emitConditionalChild(parentId, markerId, expr, statements, ctx) {
26030
+ function emitResumableEventBinding(targetId, eventName, expr, statements, ctx, containingRegion) {
26031
+ const { t: t4 } = ctx;
26032
+ if (!ctx.resumableEnabled) {
26033
+ return;
26034
+ }
26035
+ const prevWrapTracked = ctx.wrapTrackedExpressions;
26036
+ ctx.wrapTrackedExpressions = false;
26037
+ const valueExpr = lowerDomExpression(expr, ctx, containingRegion, {
26038
+ skipHookAccessors: true,
26039
+ skipRegionRootOverride: true
26040
+ });
26041
+ ctx.wrapTrackedExpressions = prevWrapTracked;
26042
+ const eventParam = t4.identifier("event");
26043
+ const elParam = t4.identifier("el");
26044
+ const scopeParam = t4.identifier("scopeId");
26045
+ const ensureHandlerParam = (fn) => {
26046
+ if (t4.isArrowFunctionExpression(fn)) {
26047
+ if (fn.params.length > 0) return fn;
26048
+ return t4.arrowFunctionExpression([eventParam], fn.body, fn.async);
26049
+ }
26050
+ if (t4.isFunctionExpression(fn)) {
26051
+ if (fn.params.length > 0) return fn;
26052
+ return t4.functionExpression(fn.id, [eventParam], fn.body, fn.generator, fn.async);
26053
+ }
26054
+ if (t4.isIdentifier(fn) || t4.isMemberExpression(fn)) {
26055
+ return fn;
26056
+ }
26057
+ if (t4.isCallExpression(fn) && fn.arguments.length === 0 && (t4.isIdentifier(fn.callee) || t4.isMemberExpression(fn.callee))) {
26058
+ return fn.callee;
26059
+ }
26060
+ return t4.functionExpression(
26061
+ null,
26062
+ [eventParam],
26063
+ t4.blockStatement([
26064
+ t4.returnStatement(
26065
+ t4.callExpression(
26066
+ t4.memberExpression(fn, t4.identifier("call")),
26067
+ [t4.thisExpression(), eventParam]
26068
+ )
26069
+ )
26070
+ ])
26071
+ );
26072
+ };
26073
+ const handlerExpr = ensureHandlerParam(valueExpr);
26074
+ const handlerId = t4.identifier(`__fict_e${ctx.resumableHandlerCounter ?? 0}`);
26075
+ ctx.resumableHandlerCounter = (ctx.resumableHandlerCounter ?? 0) + 1;
26076
+ const captured = /* @__PURE__ */ new Set();
26077
+ collectExpressionIdentifiersDeep(expr, captured);
26078
+ const lexicalNames = Array.from(captured).filter((name) => ctx.signalVars?.has(name));
26079
+ const propsName = ctx.propsParamName && captured.has(ctx.propsParamName) ? ctx.propsParamName : null;
26080
+ const functionDeps = [];
26081
+ const functionDepRenames = /* @__PURE__ */ new Map();
26082
+ for (const name of captured) {
26083
+ if (ctx.functionVars?.has(name) && !ctx.signalVars?.has(name)) {
26084
+ const hirDef = ctx.componentFunctionDefs?.get(name);
26085
+ if (hirDef) {
26086
+ functionDeps.push(name);
26087
+ let hoistedName = ctx.hoistedFunctionDepNames?.get(name);
26088
+ if (!hoistedName) {
26089
+ hoistedName = `__fict_fn_${name}_${ctx.hoistedFunctionDepCounter ?? 0}`;
26090
+ ctx.hoistedFunctionDepCounter = (ctx.hoistedFunctionDepCounter ?? 0) + 1;
26091
+ ctx.hoistedFunctionDepNames?.set(name, hoistedName);
26092
+ const loweredFn = lowerDomExpression(hirDef, ctx, null, {
26093
+ skipHookAccessors: true,
26094
+ skipRegionRootOverride: true
26095
+ });
26096
+ const hoistedDecl = t4.variableDeclaration("const", [
26097
+ t4.variableDeclarator(t4.identifier(hoistedName), loweredFn)
26098
+ ]);
26099
+ const hoistedExport = t4.exportNamedDeclaration(hoistedDecl, []);
26100
+ ctx.hoistedResumableStatements?.push(hoistedExport);
26101
+ }
26102
+ functionDepRenames.set(name, hoistedName);
26103
+ }
26104
+ }
26105
+ }
26106
+ let finalHandlerExpr = handlerExpr;
26107
+ if (functionDepRenames.size > 0) {
26108
+ finalHandlerExpr = renameIdentifiersInExpr(handlerExpr, functionDepRenames, t4);
26109
+ }
26110
+ const bodyStatements = [];
26111
+ if (lexicalNames.length > 0) {
26112
+ ctx.helpersUsed.add("useLexicalScope");
26113
+ bodyStatements.push(
26114
+ t4.variableDeclaration("const", [
26115
+ t4.variableDeclarator(
26116
+ t4.arrayPattern(lexicalNames.map((name) => t4.identifier(name))),
26117
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.useLexicalScope), [
26118
+ scopeParam,
26119
+ t4.arrayExpression(lexicalNames.map((name) => t4.stringLiteral(name)))
26120
+ ])
26121
+ )
26122
+ ])
26123
+ );
26124
+ }
26125
+ if (propsName) {
26126
+ ctx.helpersUsed.add("getScopeProps");
26127
+ bodyStatements.push(
26128
+ t4.variableDeclaration("const", [
26129
+ t4.variableDeclarator(
26130
+ t4.identifier(propsName),
26131
+ t4.logicalExpression(
26132
+ "||",
26133
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.getScopeProps), [scopeParam]),
26134
+ t4.objectExpression([])
26135
+ )
26136
+ )
26137
+ ])
26138
+ );
26139
+ }
26140
+ const handlerVar = t4.identifier("__handler");
26141
+ bodyStatements.push(
26142
+ t4.variableDeclaration("const", [t4.variableDeclarator(handlerVar, finalHandlerExpr)])
26143
+ );
26144
+ bodyStatements.push(
26145
+ t4.returnStatement(
26146
+ t4.callExpression(t4.memberExpression(handlerVar, t4.identifier("call")), [elParam, eventParam])
26147
+ )
26148
+ );
26149
+ const exportedHandler = t4.exportNamedDeclaration(
26150
+ t4.variableDeclaration("const", [
26151
+ t4.variableDeclarator(
26152
+ handlerId,
26153
+ t4.arrowFunctionExpression(
26154
+ [scopeParam, eventParam, elParam],
26155
+ t4.blockStatement(bodyStatements)
26156
+ )
26157
+ )
26158
+ ]),
26159
+ []
26160
+ );
26161
+ ctx.hoistedResumableStatements?.push(exportedHandler);
26162
+ ctx.helpersUsed.add("qrl");
26163
+ const qrlExpr = t4.callExpression(t4.identifier(RUNTIME_ALIASES.qrl), [
26164
+ genModuleUrlExpr(ctx),
26165
+ t4.stringLiteral(handlerId.name)
26166
+ ]);
26167
+ statements.push(
26168
+ t4.expressionStatement(
26169
+ t4.callExpression(t4.memberExpression(targetId, t4.identifier("setAttribute")), [
26170
+ t4.stringLiteral(`on:${eventName}`),
26171
+ qrlExpr
26172
+ ])
26173
+ )
26174
+ );
26175
+ }
26176
+ function registerResumableComponent(componentName, ctx) {
26177
+ if (!ctx.resumableEnabled) return;
26178
+ if (!ctx.hoistedResumableStatements || !ctx.resumableComponents) return;
26179
+ if (ctx.resumableComponents.has(componentName)) return;
26180
+ const { t: t4 } = ctx;
26181
+ const resumeExport = `__fict_r${ctx.resumableComponentCounter ?? 0}`;
26182
+ ctx.resumableComponentCounter = (ctx.resumableComponentCounter ?? 0) + 1;
26183
+ const scopeParam = t4.identifier("scopeId");
26184
+ const hostParam = t4.identifier("host");
26185
+ const snapshotId = t4.identifier("snapshot");
26186
+ const ctxId = t4.identifier("ctx");
26187
+ ctx.helpersUsed.add("getSSRScope");
26188
+ ctx.helpersUsed.add("ensureScope");
26189
+ ctx.helpersUsed.add("prepareContext");
26190
+ ctx.helpersUsed.add("pushContext");
26191
+ ctx.helpersUsed.add("popContext");
26192
+ ctx.helpersUsed.add("hydrateComponent");
26193
+ ctx.helpersUsed.add("qrl");
26194
+ const snapshotDecl = t4.variableDeclaration("const", [
26195
+ t4.variableDeclarator(
26196
+ snapshotId,
26197
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.getSSRScope), [scopeParam])
26198
+ )
26199
+ ]);
26200
+ const earlyReturn = t4.ifStatement(t4.unaryExpression("!", snapshotId), t4.returnStatement());
26201
+ const ensureCtxDecl = t4.variableDeclaration("const", [
26202
+ t4.variableDeclarator(
26203
+ ctxId,
26204
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.ensureScope), [
26205
+ scopeParam,
26206
+ hostParam,
26207
+ snapshotId
26208
+ ])
26209
+ )
26210
+ ]);
26211
+ const prepareCtx = t4.expressionStatement(
26212
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.prepareContext), [ctxId])
26213
+ );
26214
+ const pushCtx = t4.expressionStatement(
26215
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.pushContext), [])
26216
+ );
26217
+ const hydrateCall = t4.expressionStatement(
26218
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.hydrateComponent), [
26219
+ t4.arrowFunctionExpression(
26220
+ [],
26221
+ t4.callExpression(t4.identifier(componentName), [
26222
+ t4.logicalExpression(
26223
+ "||",
26224
+ t4.memberExpression(snapshotId, t4.identifier("props")),
26225
+ t4.objectExpression([])
26226
+ )
26227
+ ])
26228
+ ),
26229
+ hostParam
26230
+ ])
26231
+ );
26232
+ const popCtx = t4.expressionStatement(
26233
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.popContext), [])
26234
+ );
26235
+ const resumeFnId = t4.identifier(resumeExport);
26236
+ const resumeFn = t4.exportNamedDeclaration(
26237
+ t4.variableDeclaration("const", [
26238
+ t4.variableDeclarator(
26239
+ resumeFnId,
26240
+ t4.arrowFunctionExpression(
26241
+ [scopeParam, hostParam],
26242
+ t4.blockStatement([
26243
+ snapshotDecl,
26244
+ earlyReturn,
26245
+ ensureCtxDecl,
26246
+ t4.tryStatement(
26247
+ t4.blockStatement([prepareCtx, pushCtx, hydrateCall]),
26248
+ null,
26249
+ t4.blockStatement([popCtx])
26250
+ )
26251
+ ])
26252
+ )
26253
+ )
26254
+ ]),
26255
+ []
26256
+ );
26257
+ ctx.helpersUsed.add("registerResume");
26258
+ const registerCall = t4.expressionStatement(
26259
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.registerResume), [
26260
+ t4.stringLiteral(resumeExport),
26261
+ resumeFnId
26262
+ ])
26263
+ );
26264
+ const metaId = t4.identifier(`__fict_meta_${componentName}`);
26265
+ const moduleUrlExpr = genModuleUrlExpr(ctx);
26266
+ const typeKeyExpr = t4.binaryExpression("+", t4.stringLiteral(`${componentName}@`), moduleUrlExpr);
26267
+ const resumeQrlExpr = t4.callExpression(t4.identifier(RUNTIME_ALIASES.qrl), [
26268
+ genModuleUrlExpr(ctx),
26269
+ t4.stringLiteral(resumeExport)
26270
+ ]);
26271
+ const metaDecl = t4.variableDeclaration("const", [
26272
+ t4.variableDeclarator(
26273
+ metaId,
26274
+ t4.objectExpression([
26275
+ t4.objectProperty(t4.identifier("id"), typeKeyExpr),
26276
+ t4.objectProperty(t4.identifier("resume"), resumeQrlExpr)
26277
+ ])
26278
+ )
26279
+ ]);
26280
+ const assignMeta = t4.expressionStatement(
26281
+ t4.assignmentExpression(
26282
+ "=",
26283
+ t4.memberExpression(t4.identifier(componentName), t4.identifier("__fictMeta")),
26284
+ metaId
26285
+ )
26286
+ );
26287
+ ctx.hoistedResumableStatements.push(resumeFn, registerCall, metaDecl, assignMeta);
26288
+ ctx.resumableComponents.set(componentName, { resumeExport, typeKey: componentName });
26289
+ }
26290
+ function emitConditionalChild(startMarkerId, endMarkerId, expr, statements, ctx) {
25622
26291
  const { t: t4 } = ctx;
25623
26292
  ctx.helpersUsed.add("conditional");
25624
26293
  ctx.helpersUsed.add("createElement");
@@ -25659,7 +26328,10 @@ function emitConditionalChild(parentId, markerId, expr, statements, ctx) {
25659
26328
  ];
25660
26329
  if (alternate) {
25661
26330
  args.push(t4.arrowFunctionExpression([], alternate));
26331
+ } else {
26332
+ args.push(t4.identifier("undefined"));
25662
26333
  }
26334
+ args.push(startMarkerId, endMarkerId);
25663
26335
  statements.push(
25664
26336
  t4.variableDeclaration("const", [
25665
26337
  t4.variableDeclarator(
@@ -25668,14 +26340,6 @@ function emitConditionalChild(parentId, markerId, expr, statements, ctx) {
25668
26340
  )
25669
26341
  ])
25670
26342
  );
25671
- statements.push(
25672
- t4.expressionStatement(
25673
- t4.callExpression(t4.memberExpression(parentId, t4.identifier("insertBefore")), [
25674
- t4.memberExpression(bindingId, t4.identifier("marker")),
25675
- markerId
25676
- ])
25677
- )
25678
- );
25679
26343
  statements.push(
25680
26344
  t4.expressionStatement(
25681
26345
  t4.optionalCallExpression(
@@ -26282,40 +26946,16 @@ function buildListCallExpression(expr, statements, ctx) {
26282
26946
  }
26283
26947
  return listCall;
26284
26948
  }
26285
- function emitListChild(parentId, markerId, expr, statements, ctx) {
26949
+ function emitListChild(startMarkerId, endMarkerId, expr, statements, ctx) {
26286
26950
  const { t: t4 } = ctx;
26287
26951
  const listCall = buildListCallExpression(expr, statements, ctx);
26288
26952
  if (!listCall) return;
26953
+ if (t4.isCallExpression(listCall)) {
26954
+ listCall.arguments.push(startMarkerId, endMarkerId);
26955
+ }
26289
26956
  ctx.helpersUsed.add("onDestroy");
26290
- ctx.helpersUsed.add("toNodeArray");
26291
26957
  const listId = genTemp(ctx, "list");
26292
26958
  statements.push(t4.variableDeclaration("const", [t4.variableDeclarator(listId, listCall)]));
26293
- const markersId = genTemp(ctx, "markers");
26294
- statements.push(
26295
- t4.variableDeclaration("const", [
26296
- t4.variableDeclarator(
26297
- markersId,
26298
- t4.callExpression(t4.identifier(RUNTIME_ALIASES.toNodeArray), [
26299
- t4.memberExpression(listId, t4.identifier("marker"))
26300
- ])
26301
- )
26302
- ])
26303
- );
26304
- const mId = genTemp(ctx, "m");
26305
- statements.push(
26306
- t4.forOfStatement(
26307
- t4.variableDeclaration("const", [t4.variableDeclarator(mId)]),
26308
- markersId,
26309
- t4.blockStatement([
26310
- t4.expressionStatement(
26311
- t4.callExpression(t4.memberExpression(parentId, t4.identifier("insertBefore")), [
26312
- mId,
26313
- markerId
26314
- ])
26315
- )
26316
- ])
26317
- )
26318
- );
26319
26959
  statements.push(
26320
26960
  t4.expressionStatement(
26321
26961
  t4.optionalCallExpression(
@@ -26352,6 +26992,9 @@ function lowerHIRWithRegions(program, t4, options, macroAliases) {
26352
26992
  program.functions.filter((fn) => !!fn.name).map((fn) => [fn.name, fn])
26353
26993
  );
26354
26994
  ctx.options = options;
26995
+ ctx.resumableEnabled = options?.resumable === true;
26996
+ ctx.autoExtractEnabled = options?.autoExtractHandlers ?? options?.resumable === true;
26997
+ ctx.autoExtractThreshold = options?.autoExtractThreshold ?? 3;
26355
26998
  const body = [];
26356
26999
  const topLevelAliases = /* @__PURE__ */ new Set();
26357
27000
  let topLevelCtxInjected = false;
@@ -26598,6 +27241,9 @@ function lowerHIRWithRegions(program, t4, options, macroAliases) {
26598
27241
  lowerableBuffer.push(stmt);
26599
27242
  }
26600
27243
  flushLowerableBuffer();
27244
+ if (ctx.resumableEnabled && ctx.hoistedResumableStatements && ctx.hoistedResumableStatements.length > 0) {
27245
+ body.push(...ctx.hoistedResumableStatements);
27246
+ }
26601
27247
  for (const func of generatedFunctions.values()) {
26602
27248
  body.push(func.stmt);
26603
27249
  if (func.stmt.id?.name) emittedFunctionNames.add(func.stmt.id.name);
@@ -26638,12 +27284,15 @@ function lowerTopLevelStatementBlock(statements, ctx, t4, name = "__module_segme
26638
27284
  ctx.storeVars = storeVars;
26639
27285
  ctx.memoVars = memoVars;
26640
27286
  ctx.mutatedVars = mutatedVars;
27287
+ const componentFunctionDefs = ctx.componentFunctionDefs ?? /* @__PURE__ */ new Map();
27288
+ ctx.componentFunctionDefs = componentFunctionDefs;
26641
27289
  for (const block of fn.blocks) {
26642
27290
  for (const instr of block.instructions) {
26643
27291
  if (instr.kind === "Assign") {
26644
27292
  const target = deSSAVarName(instr.target.name);
26645
27293
  if (instr.value.kind === "ArrowFunction" || instr.value.kind === "FunctionExpression") {
26646
27294
  functionVars.add(target);
27295
+ componentFunctionDefs.set(target, instr.value);
26647
27296
  }
26648
27297
  if (instr.value.kind === "CallExpression" || instr.value.kind === "OptionalCallExpression") {
26649
27298
  const callKind = getReactiveCallKind(instr.value, ctx);
@@ -26811,6 +27460,8 @@ function lowerFunctionWithRegions(fn, ctx, options) {
26811
27460
  ctx.mutatedVars = /* @__PURE__ */ new Set();
26812
27461
  ctx.noMemo = !!(prevNoMemo || fn.meta?.noMemo);
26813
27462
  ctx.hookResultVarMap = /* @__PURE__ */ new Map();
27463
+ const prevComponentFunctionDefs = ctx.componentFunctionDefs;
27464
+ ctx.componentFunctionDefs = /* @__PURE__ */ new Map();
26814
27465
  const hookResultVars = /* @__PURE__ */ new Set();
26815
27466
  const hookAccessorAliases = /* @__PURE__ */ new Set();
26816
27467
  const prevPropsParam = ctx.propsParamName;
@@ -26827,6 +27478,7 @@ function lowerFunctionWithRegions(fn, ctx, options) {
26827
27478
  const target = deSSAVarName(instr.target.name);
26828
27479
  if (instr.value.kind === "ArrowFunction" || instr.value.kind === "FunctionExpression") {
26829
27480
  ctx.functionVars?.add(target);
27481
+ ctx.componentFunctionDefs?.set(target, instr.value);
26830
27482
  }
26831
27483
  if (instr.value.kind === "CallExpression" || instr.value.kind === "OptionalCallExpression") {
26832
27484
  const callKind = getReactiveCallKind(instr.value, ctx);
@@ -27122,6 +27774,7 @@ function lowerFunctionWithRegions(fn, ctx, options) {
27122
27774
  ctx.externalTracked = prevExternalTracked;
27123
27775
  ctx.signalVars = prevSignalVars;
27124
27776
  ctx.functionVars = prevFunctionVars;
27777
+ ctx.componentFunctionDefs = prevComponentFunctionDefs;
27125
27778
  ctx.memoVars = prevMemoVars;
27126
27779
  ctx.storeVars = prevStoreVars;
27127
27780
  ctx.mutatedVars = prevMutatedVars;
@@ -27139,6 +27792,7 @@ function lowerFunctionWithRegions(fn, ctx, options) {
27139
27792
  ctx.externalTracked = prevExternalTracked;
27140
27793
  ctx.signalVars = prevSignalVars;
27141
27794
  ctx.functionVars = prevFunctionVars;
27795
+ ctx.componentFunctionDefs = prevComponentFunctionDefs;
27142
27796
  ctx.memoVars = prevMemoVars;
27143
27797
  ctx.storeVars = prevStoreVars;
27144
27798
  ctx.mutatedVars = prevMutatedVars;
@@ -27235,6 +27889,9 @@ function lowerFunctionWithRegions(fn, ctx, options) {
27235
27889
  fn.loc
27236
27890
  );
27237
27891
  funcDecl.async = isAsync;
27892
+ if (isComponent && fn.name) {
27893
+ registerResumableComponent(fn.name, ctx);
27894
+ }
27238
27895
  ctx.needsCtx = prevNeedsCtx;
27239
27896
  ctx.shadowedNames = prevShadowed;
27240
27897
  ctx.localDeclaredNames = prevLocalDeclared;
@@ -27242,6 +27899,7 @@ function lowerFunctionWithRegions(fn, ctx, options) {
27242
27899
  ctx.externalTracked = prevExternalTracked;
27243
27900
  ctx.signalVars = prevSignalVars;
27244
27901
  ctx.functionVars = prevFunctionVars;
27902
+ ctx.componentFunctionDefs = prevComponentFunctionDefs;
27245
27903
  ctx.memoVars = prevMemoVars;
27246
27904
  ctx.storeVars = prevStoreVars;
27247
27905
  ctx.mutatedVars = prevMutatedVars;