@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.cjs CHANGED
@@ -14150,6 +14150,9 @@ var RUNTIME_HELPERS = {
14150
14150
  conditional: "createConditional",
14151
14151
  keyedList: "createKeyedList",
14152
14152
  insert: "insert",
14153
+ insertBetween: "insertBetween",
14154
+ resolvePath: "resolvePath",
14155
+ getSlotEnd: "getSlotEnd",
14153
14156
  onDestroy: "onDestroy",
14154
14157
  bindText: "bindText",
14155
14158
  bindAttribute: "bindAttribute",
@@ -14161,7 +14164,18 @@ var RUNTIME_HELPERS = {
14161
14164
  bindRef: "bindRef",
14162
14165
  toNodeArray: "toNodeArray",
14163
14166
  template: "template",
14164
- delegateEvents: "delegateEvents"
14167
+ delegateEvents: "delegateEvents",
14168
+ useLexicalScope: "__fictUseLexicalScope",
14169
+ getScopeProps: "__fictGetScopeProps",
14170
+ qrl: "__fictQrl",
14171
+ getSSRScope: "__fictGetSSRScope",
14172
+ ensureScope: "__fictEnsureScope",
14173
+ prepareContext: "__fictPrepareContext",
14174
+ enterHydration: "__fictEnterHydration",
14175
+ exitHydration: "__fictExitHydration",
14176
+ domRender: "render",
14177
+ hydrateComponent: "hydrateComponent",
14178
+ registerResume: "__fictRegisterResume"
14165
14179
  };
14166
14180
  var RUNTIME_ALIASES = {
14167
14181
  signal: "createSignal",
@@ -14186,6 +14200,9 @@ var RUNTIME_ALIASES = {
14186
14200
  conditional: "createConditional",
14187
14201
  keyedList: "createKeyedList",
14188
14202
  insert: "insert",
14203
+ insertBetween: "insertBetween",
14204
+ resolvePath: "resolvePath",
14205
+ getSlotEnd: "getSlotEnd",
14189
14206
  onDestroy: "onDestroy",
14190
14207
  bindText: "bindText",
14191
14208
  bindAttribute: "bindAttribute",
@@ -14197,7 +14214,18 @@ var RUNTIME_ALIASES = {
14197
14214
  bindRef: "bindRef",
14198
14215
  toNodeArray: "toNodeArray",
14199
14216
  template: "template",
14200
- delegateEvents: "delegateEvents"
14217
+ delegateEvents: "delegateEvents",
14218
+ useLexicalScope: "__fictUseLexicalScope",
14219
+ getScopeProps: "__fictGetScopeProps",
14220
+ qrl: "__fictQrl",
14221
+ getSSRScope: "__fictGetSSRScope",
14222
+ ensureScope: "__fictEnsureScope",
14223
+ prepareContext: "__fictPrepareContext",
14224
+ enterHydration: "__fictEnterHydration",
14225
+ exitHydration: "__fictExitHydration",
14226
+ domRender: "render",
14227
+ hydrateComponent: "hydrateComponent",
14228
+ registerResume: "__fictRegisterResume"
14201
14229
  };
14202
14230
  var DelegatedEvents = /* @__PURE__ */ new Set([...DelegatedEventNames]);
14203
14231
  var SAFE_FUNCTIONS = /* @__PURE__ */ new Set([
@@ -14548,6 +14576,9 @@ function parseFictReturnAnnotation(node) {
14548
14576
  if (content === "'memo'" || content === '"memo"') {
14549
14577
  return { directAccessor: "memo" };
14550
14578
  }
14579
+ if (/^\{\s*\}$/.test(content)) {
14580
+ return { objectProps: /* @__PURE__ */ new Map() };
14581
+ }
14551
14582
  const objectMatch = content.match(/^\{([^}]+)\}$/);
14552
14583
  if (objectMatch) {
14553
14584
  const objectProps = /* @__PURE__ */ new Map();
@@ -16377,6 +16408,9 @@ function convertJSXMemberExpr(node) {
16377
16408
  };
16378
16409
  }
16379
16410
 
16411
+ // src/ir/codegen.ts
16412
+ var import_node_url2 = require("url");
16413
+
16380
16414
  // src/fine-grained-dom.ts
16381
16415
  function normalizeDependencyKey(name) {
16382
16416
  return name.split(".").map((part) => part.replace(/_\d+$/, "")).join(".");
@@ -21176,9 +21210,14 @@ function instructionToStatement(instr, t4, declaredVars, ctx, _buildMemoCall) {
21176
21210
  declaredVars.add(baseName2);
21177
21211
  if (treatAsTracked && !isDestructuringTemp) {
21178
21212
  if (isStateCall2) {
21179
- return t4.variableDeclaration(normalizedDecl, [
21180
- t4.variableDeclarator(t4.identifier(baseName2), lowerAssignedValue(true))
21181
- ]);
21213
+ ctx.currentAssignmentName = baseName2;
21214
+ try {
21215
+ return t4.variableDeclaration(normalizedDecl, [
21216
+ t4.variableDeclarator(t4.identifier(baseName2), lowerAssignedValue(true))
21217
+ ]);
21218
+ } finally {
21219
+ ctx.currentAssignmentName = void 0;
21220
+ }
21182
21221
  }
21183
21222
  if (dependsOnTracked) {
21184
21223
  if (instr.value.kind === "Identifier" && ctx.trackedVars.has(deSSAVarName(instr.value.name)) && !isDestructuringTemp) {
@@ -22101,7 +22140,17 @@ function createCodegenContext(t4) {
22101
22140
  hookReturnInfo: /* @__PURE__ */ new Map(),
22102
22141
  hoistedTemplates: /* @__PURE__ */ new Map(),
22103
22142
  hoistedTemplateStatements: [],
22104
- delegatedEventsUsed: /* @__PURE__ */ new Set()
22143
+ hoistedResumableStatements: [],
22144
+ resumableHandlerCounter: 0,
22145
+ resumableComponentCounter: 0,
22146
+ resumableComponents: /* @__PURE__ */ new Map(),
22147
+ resumableEnabled: false,
22148
+ autoExtractEnabled: false,
22149
+ autoExtractThreshold: 3,
22150
+ delegatedEventsUsed: /* @__PURE__ */ new Set(),
22151
+ componentFunctionDefs: /* @__PURE__ */ new Map(),
22152
+ hoistedFunctionDepCounter: 0,
22153
+ hoistedFunctionDepNames: /* @__PURE__ */ new Map()
22105
22154
  };
22106
22155
  }
22107
22156
  function withGetterCache(ctx, fn) {
@@ -23007,6 +23056,51 @@ function computeReactiveAccessors(fn, ctx) {
23007
23056
  function genTemp(ctx, prefix = "tmp") {
23008
23057
  return ctx.t.identifier(`__${prefix}_${ctx.tempCounter++}`);
23009
23058
  }
23059
+ function renameIdentifiersInExpr(expr, renames, _t) {
23060
+ const cloned = JSON.parse(JSON.stringify(expr));
23061
+ function visit(node) {
23062
+ if (!node || typeof node !== "object") return;
23063
+ const n = node;
23064
+ if (n.type === "Identifier" && typeof n.name === "string") {
23065
+ const newName = renames.get(n.name);
23066
+ if (newName) {
23067
+ n.name = newName;
23068
+ }
23069
+ }
23070
+ for (const key of Object.keys(n)) {
23071
+ if (key === "loc" || key === "start" || key === "end" || key === "extra" || key === "comments" || key === "leadingComments" || key === "trailingComments") {
23072
+ continue;
23073
+ }
23074
+ const value = n[key];
23075
+ if (Array.isArray(value)) {
23076
+ for (const item of value) {
23077
+ visit(item);
23078
+ }
23079
+ } else if (value && typeof value === "object") {
23080
+ visit(value);
23081
+ }
23082
+ }
23083
+ }
23084
+ visit(cloned);
23085
+ return cloned;
23086
+ }
23087
+ function genModuleUrlExpr(ctx) {
23088
+ const { t: t4 } = ctx;
23089
+ const filename = ctx.options?.filename;
23090
+ if (filename) {
23091
+ let fileUrl;
23092
+ if (filename.startsWith("file://")) {
23093
+ fileUrl = filename;
23094
+ } else {
23095
+ fileUrl = (0, import_node_url2.pathToFileURL)(filename).href;
23096
+ }
23097
+ return t4.stringLiteral(fileUrl);
23098
+ }
23099
+ return t4.memberExpression(
23100
+ t4.metaProperty(t4.identifier("import"), t4.identifier("meta")),
23101
+ t4.identifier("url")
23102
+ );
23103
+ }
23010
23104
  function extractKeyFromAttributes(attributes) {
23011
23105
  for (const attr of attributes) {
23012
23106
  if (attr.name === "key" && attr.value) {
@@ -23130,6 +23224,26 @@ function lowerInstruction(instr, ctx) {
23130
23224
  ctx.memoVars?.add(baseName2);
23131
23225
  }
23132
23226
  }
23227
+ if (declKind) {
23228
+ const initKind = getReactiveCallKind(instr.value, ctx);
23229
+ if (initKind === "signal") {
23230
+ ctx.signalVars?.add(baseName2);
23231
+ ctx.trackedVars.add(baseName2);
23232
+ ctx.currentAssignmentName = baseName2;
23233
+ const loweredValue = (() => {
23234
+ try {
23235
+ return lowerTrackedExpression(instr.value, ctx);
23236
+ } finally {
23237
+ ctx.currentAssignmentName = void 0;
23238
+ }
23239
+ })();
23240
+ return applyLoc(
23241
+ t4.variableDeclaration(declKind, [
23242
+ t4.variableDeclarator(t4.identifier(baseName2), loweredValue)
23243
+ ])
23244
+ );
23245
+ }
23246
+ }
23133
23247
  if (ctx.signalVars?.has(baseName2)) {
23134
23248
  ctx.currentAssignmentName = baseName2;
23135
23249
  const loweredValue = (() => {
@@ -23855,23 +23969,23 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
23855
23969
  case "MetaProperty":
23856
23970
  return t4.metaProperty(t4.identifier(expr.meta.name), t4.identifier(expr.property.name));
23857
23971
  case "CallExpression": {
23858
- if (expr.callee.kind === "Identifier" && expr.callee.name === "$state") {
23972
+ const stateCalleeNameRaw = expr.callee.kind === "Identifier" ? expr.callee.name : null;
23973
+ const stateCalleeName = stateCalleeNameRaw ? deSSAVarName(stateCalleeNameRaw) : null;
23974
+ if (stateCalleeName && ctx.stateMacroNames?.has(stateCalleeName)) {
23859
23975
  const args = lowerCallArguments(expr.arguments);
23860
23976
  const includeDevtools = ctx.options?.dev !== false;
23861
- if (includeDevtools) {
23862
- const options = [];
23863
- if (ctx.currentAssignmentName) {
23864
- options.push(
23865
- t4.objectProperty(t4.identifier("name"), t4.stringLiteral(ctx.currentAssignmentName))
23866
- );
23867
- }
23868
- if (expr.loc) {
23869
- const source = `${ctx.options?.filename ?? ""}:${expr.loc.start.line}:${expr.loc.start.column}`;
23870
- options.push(t4.objectProperty(t4.identifier("devToolsSource"), t4.stringLiteral(source)));
23871
- }
23872
- if (options.length > 0) {
23873
- args.push(t4.objectExpression(options));
23874
- }
23977
+ const options = [];
23978
+ if (ctx.currentAssignmentName) {
23979
+ options.push(
23980
+ t4.objectProperty(t4.identifier("name"), t4.stringLiteral(ctx.currentAssignmentName))
23981
+ );
23982
+ }
23983
+ if (includeDevtools && expr.loc) {
23984
+ const source = `${ctx.options?.filename ?? ""}:${expr.loc.start.line}:${expr.loc.start.column}`;
23985
+ options.push(t4.objectProperty(t4.identifier("devToolsSource"), t4.stringLiteral(source)));
23986
+ }
23987
+ if (options.length > 0) {
23988
+ args.push(t4.objectExpression(options));
23875
23989
  }
23876
23990
  if (ctx.inModule) {
23877
23991
  ctx.helpersUsed.add("signal");
@@ -25025,17 +25139,280 @@ function resolveNamespaceContext(tagName, parentNamespace) {
25025
25139
  if (tagName === "foreignObject" && parentNamespace === "svg") return null;
25026
25140
  return parentNamespace;
25027
25141
  }
25142
+ function countExpressionNodes(expr) {
25143
+ if (!expr) return 0;
25144
+ let count = 1;
25145
+ switch (expr.kind) {
25146
+ case "Literal":
25147
+ return 1;
25148
+ case "Identifier":
25149
+ return 1;
25150
+ case "BinaryExpression":
25151
+ case "LogicalExpression":
25152
+ count += countExpressionNodes(expr.left);
25153
+ count += countExpressionNodes(expr.right);
25154
+ return count;
25155
+ case "UnaryExpression":
25156
+ count += countExpressionNodes(expr.argument);
25157
+ return count;
25158
+ case "ConditionalExpression":
25159
+ count += countExpressionNodes(expr.test);
25160
+ count += countExpressionNodes(expr.consequent);
25161
+ count += countExpressionNodes(expr.alternate);
25162
+ return count;
25163
+ case "CallExpression":
25164
+ count += countExpressionNodes(expr.callee);
25165
+ for (const arg of expr.arguments) {
25166
+ count += countExpressionNodes(arg);
25167
+ }
25168
+ return count;
25169
+ case "MemberExpression":
25170
+ count += countExpressionNodes(expr.object);
25171
+ if (expr.computed && expr.property) {
25172
+ count += countExpressionNodes(expr.property);
25173
+ }
25174
+ return count;
25175
+ case "ArrayExpression":
25176
+ for (const elem of expr.elements) {
25177
+ if (elem) count += countExpressionNodes(elem);
25178
+ }
25179
+ return count;
25180
+ case "ObjectExpression":
25181
+ for (const prop of expr.properties) {
25182
+ if (prop.kind === "Property") {
25183
+ count += countExpressionNodes(prop.value);
25184
+ } else if (prop.kind === "SpreadElement") {
25185
+ count += countExpressionNodes(prop.argument);
25186
+ }
25187
+ }
25188
+ return count;
25189
+ case "ArrowFunction":
25190
+ if (expr.isExpression && expr.body && !Array.isArray(expr.body)) {
25191
+ count += countExpressionNodes(expr.body);
25192
+ } else if (Array.isArray(expr.body)) {
25193
+ for (const block of expr.body) {
25194
+ count += countBlockNodes(block);
25195
+ }
25196
+ }
25197
+ return count;
25198
+ case "FunctionExpression":
25199
+ if (expr.body) {
25200
+ for (const block of expr.body) {
25201
+ count += countBlockNodes(block);
25202
+ }
25203
+ }
25204
+ return count;
25205
+ case "AssignmentExpression":
25206
+ count += countExpressionNodes(expr.left);
25207
+ count += countExpressionNodes(expr.right);
25208
+ return count;
25209
+ case "UpdateExpression":
25210
+ count += countExpressionNodes(expr.argument);
25211
+ return count;
25212
+ case "SequenceExpression":
25213
+ for (const e of expr.expressions) {
25214
+ count += countExpressionNodes(e);
25215
+ }
25216
+ return count;
25217
+ case "AwaitExpression":
25218
+ count += countExpressionNodes(expr.argument);
25219
+ return count + 2;
25220
+ // Async adds complexity
25221
+ case "NewExpression":
25222
+ count += countExpressionNodes(expr.callee);
25223
+ for (const arg of expr.arguments) {
25224
+ count += countExpressionNodes(arg);
25225
+ }
25226
+ return count;
25227
+ case "TemplateLiteral":
25228
+ for (const e of expr.expressions) {
25229
+ count += countExpressionNodes(e);
25230
+ }
25231
+ return count;
25232
+ default:
25233
+ return count;
25234
+ }
25235
+ }
25236
+ function countBlockNodes(block) {
25237
+ let count = 1;
25238
+ for (const instr of block.instructions) {
25239
+ count += countInstructionNodes(instr);
25240
+ }
25241
+ return count;
25242
+ }
25243
+ function countInstructionNodes(instr) {
25244
+ switch (instr.kind) {
25245
+ case "Expression":
25246
+ return 1 + countExpressionNodes(instr.value);
25247
+ case "Assign":
25248
+ return 1 + countExpressionNodes(instr.value);
25249
+ case "Phi":
25250
+ return 1;
25251
+ default:
25252
+ return 1;
25253
+ }
25254
+ }
25255
+ function hasExternalCalls(expr) {
25256
+ if (!expr) return false;
25257
+ switch (expr.kind) {
25258
+ case "CallExpression": {
25259
+ if (expr.callee.kind === "Identifier") {
25260
+ const name = expr.callee.name;
25261
+ if (!["console", "Math", "JSON", "Object", "Array"].includes(name)) {
25262
+ return true;
25263
+ }
25264
+ }
25265
+ if (expr.callee.kind === "MemberExpression") {
25266
+ return true;
25267
+ }
25268
+ for (const arg of expr.arguments) {
25269
+ if (hasExternalCalls(arg)) return true;
25270
+ }
25271
+ return false;
25272
+ }
25273
+ case "ArrowFunction":
25274
+ if (expr.isExpression && expr.body && !Array.isArray(expr.body)) {
25275
+ return hasExternalCalls(expr.body);
25276
+ } else if (Array.isArray(expr.body)) {
25277
+ for (const block of expr.body) {
25278
+ if (blockHasExternalCalls(block)) return true;
25279
+ }
25280
+ }
25281
+ return false;
25282
+ case "FunctionExpression":
25283
+ if (expr.body) {
25284
+ for (const block of expr.body) {
25285
+ if (blockHasExternalCalls(block)) return true;
25286
+ }
25287
+ }
25288
+ return false;
25289
+ case "BinaryExpression":
25290
+ case "LogicalExpression":
25291
+ return hasExternalCalls(expr.left) || hasExternalCalls(expr.right);
25292
+ case "UnaryExpression":
25293
+ return hasExternalCalls(expr.argument);
25294
+ case "ConditionalExpression":
25295
+ return hasExternalCalls(expr.test) || hasExternalCalls(expr.consequent) || hasExternalCalls(expr.alternate);
25296
+ case "MemberExpression":
25297
+ return hasExternalCalls(expr.object);
25298
+ case "AssignmentExpression":
25299
+ return hasExternalCalls(expr.right);
25300
+ case "SequenceExpression":
25301
+ return expr.expressions.some((e) => hasExternalCalls(e));
25302
+ case "AwaitExpression":
25303
+ return true;
25304
+ // Await implies async external operation
25305
+ case "NewExpression":
25306
+ return true;
25307
+ // Constructor calls are external
25308
+ default:
25309
+ return false;
25310
+ }
25311
+ }
25312
+ function blockHasExternalCalls(block) {
25313
+ for (const instr of block.instructions) {
25314
+ if (instructionHasExternalCalls(instr)) return true;
25315
+ }
25316
+ return false;
25317
+ }
25318
+ function instructionHasExternalCalls(instr) {
25319
+ switch (instr.kind) {
25320
+ case "Expression":
25321
+ return hasExternalCalls(instr.value);
25322
+ case "Assign":
25323
+ return hasExternalCalls(instr.value);
25324
+ default:
25325
+ return false;
25326
+ }
25327
+ }
25328
+ function hasAsyncAwait(expr) {
25329
+ if (!expr) return false;
25330
+ switch (expr.kind) {
25331
+ case "AwaitExpression":
25332
+ return true;
25333
+ case "ArrowFunction":
25334
+ if (expr.isAsync) return true;
25335
+ if (expr.isExpression && expr.body && !Array.isArray(expr.body)) {
25336
+ return hasAsyncAwait(expr.body);
25337
+ } else if (Array.isArray(expr.body)) {
25338
+ for (const block of expr.body) {
25339
+ if (blockHasAsyncAwait(block)) return true;
25340
+ }
25341
+ }
25342
+ return false;
25343
+ case "FunctionExpression":
25344
+ if (expr.isAsync) return true;
25345
+ if (expr.body) {
25346
+ for (const block of expr.body) {
25347
+ if (blockHasAsyncAwait(block)) return true;
25348
+ }
25349
+ }
25350
+ return false;
25351
+ case "CallExpression":
25352
+ if (hasAsyncAwait(expr.callee)) return true;
25353
+ return expr.arguments.some((arg) => hasAsyncAwait(arg));
25354
+ case "BinaryExpression":
25355
+ case "LogicalExpression":
25356
+ return hasAsyncAwait(expr.left) || hasAsyncAwait(expr.right);
25357
+ case "ConditionalExpression":
25358
+ return hasAsyncAwait(expr.test) || hasAsyncAwait(expr.consequent) || hasAsyncAwait(expr.alternate);
25359
+ case "SequenceExpression":
25360
+ return expr.expressions.some((e) => hasAsyncAwait(e));
25361
+ default:
25362
+ return false;
25363
+ }
25364
+ }
25365
+ function blockHasAsyncAwait(block) {
25366
+ for (const instr of block.instructions) {
25367
+ if (instructionHasAsyncAwait(instr)) return true;
25368
+ }
25369
+ return false;
25370
+ }
25371
+ function instructionHasAsyncAwait(instr) {
25372
+ switch (instr.kind) {
25373
+ case "Expression":
25374
+ return hasAsyncAwait(instr.value);
25375
+ case "Assign":
25376
+ return hasAsyncAwait(instr.value);
25377
+ default:
25378
+ return false;
25379
+ }
25380
+ }
25381
+ function shouldAutoExtract(expr, ctx) {
25382
+ if (!expr) return false;
25383
+ if (!ctx.autoExtractEnabled) return false;
25384
+ const threshold = ctx.autoExtractThreshold ?? 3;
25385
+ if (expr.kind === "Identifier") {
25386
+ return true;
25387
+ }
25388
+ if (expr.kind === "ArrowFunction" || expr.kind === "FunctionExpression") {
25389
+ if (expr.kind === "ArrowFunction" && expr.isAsync || expr.kind === "FunctionExpression" && expr.isAsync || hasAsyncAwait(expr)) {
25390
+ return true;
25391
+ }
25392
+ if (hasExternalCalls(expr)) {
25393
+ return true;
25394
+ }
25395
+ const nodeCount2 = countExpressionNodes(expr);
25396
+ if (nodeCount2 >= threshold) {
25397
+ return true;
25398
+ }
25399
+ return false;
25400
+ }
25401
+ const nodeCount = countExpressionNodes(expr);
25402
+ return nodeCount >= threshold;
25403
+ }
25028
25404
  function extractHIRStaticHtml(jsx, ctx, parentPath = [], namespace = null) {
25029
25405
  if (jsx.isComponent || typeof jsx.tagName !== "string") {
25030
25406
  return {
25031
- html: "<!---->",
25407
+ html: "<!--fict:slot:start--><!--fict:slot:end-->",
25032
25408
  bindings: [
25033
25409
  {
25034
25410
  type: "child",
25035
25411
  path: [...parentPath],
25036
25412
  expr: jsx
25037
25413
  }
25038
- ]
25414
+ ],
25415
+ nodeCount: 1
25039
25416
  };
25040
25417
  }
25041
25418
  const tagName = jsx.tagName;
@@ -25046,7 +25423,11 @@ function extractHIRStaticHtml(jsx, ctx, parentPath = [], namespace = null) {
25046
25423
  if (attr.isSpread) {
25047
25424
  continue;
25048
25425
  }
25049
- const name = normalizeHIRAttrName(attr.name);
25426
+ let name = normalizeHIRAttrName(attr.name);
25427
+ const isResumableEvent = name.endsWith("$");
25428
+ if (isResumableEvent) {
25429
+ name = name.slice(0, -1);
25430
+ }
25050
25431
  if (name === "key") {
25051
25432
  if (attr.value && !isStaticValue(attr.value)) {
25052
25433
  bindings.push({
@@ -25081,12 +25462,14 @@ function extractHIRStaticHtml(jsx, ctx, parentPath = [], namespace = null) {
25081
25462
  changed = true;
25082
25463
  }
25083
25464
  }
25465
+ const shouldBeResumable = isResumableEvent && ctx.resumableEnabled || !isResumableEvent && ctx.resumableEnabled && shouldAutoExtract(attr.value ?? void 0, ctx);
25084
25466
  bindings.push({
25085
25467
  type: "event",
25086
25468
  path: [...parentPath],
25087
25469
  name: eventName.toLowerCase(),
25088
25470
  expr: attr.value ?? void 0,
25089
- eventOptions: { capture, passive, once }
25471
+ eventOptions: { capture, passive, once },
25472
+ resumable: shouldBeResumable
25090
25473
  });
25091
25474
  continue;
25092
25475
  }
@@ -25142,7 +25525,7 @@ function extractHIRStaticHtml(jsx, ctx, parentPath = [], namespace = null) {
25142
25525
  const childResult = extractHIRStaticHtml(child.value, ctx, childPath, resolvedNamespace);
25143
25526
  html += childResult.html;
25144
25527
  bindings.push(...childResult.bindings);
25145
- childIndex++;
25528
+ childIndex += childResult.nodeCount;
25146
25529
  } else if (child.kind === "expression") {
25147
25530
  const inline = hasAdjacentInline(i);
25148
25531
  if (!inline && isLikelyTextExpression(child.value, ctx)) {
@@ -25155,7 +25538,7 @@ function extractHIRStaticHtml(jsx, ctx, parentPath = [], namespace = null) {
25155
25538
  namespace: resolvedNamespace
25156
25539
  });
25157
25540
  } else {
25158
- html += "<!---->";
25541
+ html += "<!--fict:slot:start--><!--fict:slot:end-->";
25159
25542
  bindings.push({
25160
25543
  type: "child",
25161
25544
  path: [...parentPath, childIndex],
@@ -25163,6 +25546,8 @@ function extractHIRStaticHtml(jsx, ctx, parentPath = [], namespace = null) {
25163
25546
  // Track namespace for dynamic child bindings
25164
25547
  namespace: resolvedNamespace
25165
25548
  });
25549
+ childIndex++;
25550
+ continue;
25166
25551
  }
25167
25552
  childIndex++;
25168
25553
  }
@@ -25173,6 +25558,7 @@ function extractHIRStaticHtml(jsx, ctx, parentPath = [], namespace = null) {
25173
25558
  return {
25174
25559
  html,
25175
25560
  bindings,
25561
+ nodeCount: 1,
25176
25562
  isSVG: needsSVG || void 0,
25177
25563
  isMathML: needsMathML || void 0
25178
25564
  };
@@ -25264,6 +25650,17 @@ function lowerIntrinsicElement(jsx, ctx) {
25264
25650
  const eventName = binding.name;
25265
25651
  const hasEventOptions = binding.eventOptions && (binding.eventOptions.capture || binding.eventOptions.passive || binding.eventOptions.once);
25266
25652
  const isDelegated = DelegatedEvents.has(eventName) && !hasEventOptions;
25653
+ if (binding.resumable && !hasEventOptions) {
25654
+ emitResumableEventBinding(
25655
+ targetId,
25656
+ eventName,
25657
+ binding.expr,
25658
+ statements,
25659
+ ctx,
25660
+ containingRegion
25661
+ );
25662
+ continue;
25663
+ }
25267
25664
  const hirDataBinding = isDelegated && binding.expr ? extractDelegatedEventDataFromHIR(binding.expr, ctx) : null;
25268
25665
  if (hirDataBinding) {
25269
25666
  ctx.delegatedEventsUsed?.add(eventName);
@@ -25560,13 +25957,16 @@ function resolveHIRBindingPath(path2, cache, statements, ctx) {
25560
25957
  ancestorId = cache.get("");
25561
25958
  relativePath = path2;
25562
25959
  }
25563
- let currentExpr = ancestorId;
25564
- for (const index of relativePath) {
25565
- currentExpr = t4.memberExpression(currentExpr, t4.identifier("firstChild"));
25566
- for (let i = 0; i < index; i++) {
25567
- currentExpr = t4.memberExpression(currentExpr, t4.identifier("nextSibling"));
25568
- }
25960
+ if (relativePath.length === 0) {
25961
+ cache.set(key, ancestorId);
25962
+ return ancestorId;
25569
25963
  }
25964
+ ctx.helpersUsed.add("resolvePath");
25965
+ const pathExpr = t4.arrayExpression(relativePath.map((index) => t4.numericLiteral(index)));
25966
+ const currentExpr = t4.callExpression(t4.identifier(RUNTIME_ALIASES.resolvePath), [
25967
+ ancestorId,
25968
+ pathExpr
25969
+ ]);
25570
25970
  const varId = genTemp(ctx, "el");
25571
25971
  statements.push(t4.variableDeclaration("const", [t4.variableDeclarator(varId, currentExpr)]));
25572
25972
  cache.set(key, varId);
@@ -25574,7 +25974,16 @@ function resolveHIRBindingPath(path2, cache, statements, ctx) {
25574
25974
  }
25575
25975
  function emitHIRChildBinding(markerId, expr, statements, ctx, containingRegion, namespace) {
25576
25976
  const { t: t4 } = ctx;
25577
- const parentId = t4.memberExpression(markerId, t4.identifier("parentNode"));
25977
+ ctx.helpersUsed.add("getSlotEnd");
25978
+ const endMarkerId = genTemp(ctx, "end");
25979
+ statements.push(
25980
+ t4.variableDeclaration("const", [
25981
+ t4.variableDeclarator(
25982
+ endMarkerId,
25983
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.getSlotEnd), [markerId])
25984
+ )
25985
+ ])
25986
+ );
25578
25987
  if (namespace !== void 0) {
25579
25988
  ctx.namespaceContext = namespace;
25580
25989
  }
@@ -25593,26 +26002,26 @@ function emitHIRChildBinding(markerId, expr, statements, ctx, containingRegion,
25593
26002
  return;
25594
26003
  }
25595
26004
  if (expr.kind === "ConditionalExpression" || expr.kind === "LogicalExpression" && expr.operator === "&&") {
25596
- emitConditionalChild(parentId, markerId, expr, statements, ctx);
26005
+ emitConditionalChild(markerId, endMarkerId, expr, statements, ctx);
25597
26006
  return;
25598
26007
  }
25599
26008
  if (expr.kind === "CallExpression" || expr.kind === "OptionalCallExpression") {
25600
26009
  const callee = expr.callee;
25601
26010
  if ((callee.kind === "MemberExpression" || callee.kind === "OptionalMemberExpression") && callee.property.kind === "Identifier" && callee.property.name === "map") {
25602
- emitListChild(parentId, markerId, expr, statements, ctx);
26011
+ emitListChild(markerId, endMarkerId, expr, statements, ctx);
25603
26012
  return;
25604
26013
  }
25605
26014
  }
25606
26015
  if (expr.kind === "JSXElement") {
25607
26016
  const childExpr = lowerJSXElement(expr, ctx);
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([], childExpr),
26021
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.insertBetween), [
25615
26022
  markerId,
26023
+ endMarkerId,
26024
+ t4.arrowFunctionExpression([], childExpr),
25616
26025
  t4.identifier(RUNTIME_ALIASES.createElement)
25617
26026
  ])
25618
26027
  )
@@ -25620,20 +26029,280 @@ function emitHIRChildBinding(markerId, expr, statements, ctx, containingRegion,
25620
26029
  return;
25621
26030
  }
25622
26031
  const valueExpr = lowerDomExpression(expr, ctx, containingRegion);
25623
- ctx.helpersUsed.add("insert");
26032
+ ctx.helpersUsed.add("insertBetween");
25624
26033
  ctx.helpersUsed.add("createElement");
25625
26034
  statements.push(
25626
26035
  t4.expressionStatement(
25627
- t4.callExpression(t4.identifier(RUNTIME_ALIASES.insert), [
25628
- parentId,
25629
- t4.arrowFunctionExpression([], valueExpr),
26036
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.insertBetween), [
25630
26037
  markerId,
26038
+ endMarkerId,
26039
+ t4.arrowFunctionExpression([], valueExpr),
25631
26040
  t4.identifier(RUNTIME_ALIASES.createElement)
25632
26041
  ])
25633
26042
  )
25634
26043
  );
25635
26044
  }
25636
- function emitConditionalChild(parentId, markerId, expr, statements, ctx) {
26045
+ function emitResumableEventBinding(targetId, eventName, expr, statements, ctx, containingRegion) {
26046
+ const { t: t4 } = ctx;
26047
+ if (!ctx.resumableEnabled) {
26048
+ return;
26049
+ }
26050
+ const prevWrapTracked = ctx.wrapTrackedExpressions;
26051
+ ctx.wrapTrackedExpressions = false;
26052
+ const valueExpr = lowerDomExpression(expr, ctx, containingRegion, {
26053
+ skipHookAccessors: true,
26054
+ skipRegionRootOverride: true
26055
+ });
26056
+ ctx.wrapTrackedExpressions = prevWrapTracked;
26057
+ const eventParam = t4.identifier("event");
26058
+ const elParam = t4.identifier("el");
26059
+ const scopeParam = t4.identifier("scopeId");
26060
+ const ensureHandlerParam = (fn) => {
26061
+ if (t4.isArrowFunctionExpression(fn)) {
26062
+ if (fn.params.length > 0) return fn;
26063
+ return t4.arrowFunctionExpression([eventParam], fn.body, fn.async);
26064
+ }
26065
+ if (t4.isFunctionExpression(fn)) {
26066
+ if (fn.params.length > 0) return fn;
26067
+ return t4.functionExpression(fn.id, [eventParam], fn.body, fn.generator, fn.async);
26068
+ }
26069
+ if (t4.isIdentifier(fn) || t4.isMemberExpression(fn)) {
26070
+ return fn;
26071
+ }
26072
+ if (t4.isCallExpression(fn) && fn.arguments.length === 0 && (t4.isIdentifier(fn.callee) || t4.isMemberExpression(fn.callee))) {
26073
+ return fn.callee;
26074
+ }
26075
+ return t4.functionExpression(
26076
+ null,
26077
+ [eventParam],
26078
+ t4.blockStatement([
26079
+ t4.returnStatement(
26080
+ t4.callExpression(
26081
+ t4.memberExpression(fn, t4.identifier("call")),
26082
+ [t4.thisExpression(), eventParam]
26083
+ )
26084
+ )
26085
+ ])
26086
+ );
26087
+ };
26088
+ const handlerExpr = ensureHandlerParam(valueExpr);
26089
+ const handlerId = t4.identifier(`__fict_e${ctx.resumableHandlerCounter ?? 0}`);
26090
+ ctx.resumableHandlerCounter = (ctx.resumableHandlerCounter ?? 0) + 1;
26091
+ const captured = /* @__PURE__ */ new Set();
26092
+ collectExpressionIdentifiersDeep(expr, captured);
26093
+ const lexicalNames = Array.from(captured).filter((name) => ctx.signalVars?.has(name));
26094
+ const propsName = ctx.propsParamName && captured.has(ctx.propsParamName) ? ctx.propsParamName : null;
26095
+ const functionDeps = [];
26096
+ const functionDepRenames = /* @__PURE__ */ new Map();
26097
+ for (const name of captured) {
26098
+ if (ctx.functionVars?.has(name) && !ctx.signalVars?.has(name)) {
26099
+ const hirDef = ctx.componentFunctionDefs?.get(name);
26100
+ if (hirDef) {
26101
+ functionDeps.push(name);
26102
+ let hoistedName = ctx.hoistedFunctionDepNames?.get(name);
26103
+ if (!hoistedName) {
26104
+ hoistedName = `__fict_fn_${name}_${ctx.hoistedFunctionDepCounter ?? 0}`;
26105
+ ctx.hoistedFunctionDepCounter = (ctx.hoistedFunctionDepCounter ?? 0) + 1;
26106
+ ctx.hoistedFunctionDepNames?.set(name, hoistedName);
26107
+ const loweredFn = lowerDomExpression(hirDef, ctx, null, {
26108
+ skipHookAccessors: true,
26109
+ skipRegionRootOverride: true
26110
+ });
26111
+ const hoistedDecl = t4.variableDeclaration("const", [
26112
+ t4.variableDeclarator(t4.identifier(hoistedName), loweredFn)
26113
+ ]);
26114
+ const hoistedExport = t4.exportNamedDeclaration(hoistedDecl, []);
26115
+ ctx.hoistedResumableStatements?.push(hoistedExport);
26116
+ }
26117
+ functionDepRenames.set(name, hoistedName);
26118
+ }
26119
+ }
26120
+ }
26121
+ let finalHandlerExpr = handlerExpr;
26122
+ if (functionDepRenames.size > 0) {
26123
+ finalHandlerExpr = renameIdentifiersInExpr(handlerExpr, functionDepRenames, t4);
26124
+ }
26125
+ const bodyStatements = [];
26126
+ if (lexicalNames.length > 0) {
26127
+ ctx.helpersUsed.add("useLexicalScope");
26128
+ bodyStatements.push(
26129
+ t4.variableDeclaration("const", [
26130
+ t4.variableDeclarator(
26131
+ t4.arrayPattern(lexicalNames.map((name) => t4.identifier(name))),
26132
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.useLexicalScope), [
26133
+ scopeParam,
26134
+ t4.arrayExpression(lexicalNames.map((name) => t4.stringLiteral(name)))
26135
+ ])
26136
+ )
26137
+ ])
26138
+ );
26139
+ }
26140
+ if (propsName) {
26141
+ ctx.helpersUsed.add("getScopeProps");
26142
+ bodyStatements.push(
26143
+ t4.variableDeclaration("const", [
26144
+ t4.variableDeclarator(
26145
+ t4.identifier(propsName),
26146
+ t4.logicalExpression(
26147
+ "||",
26148
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.getScopeProps), [scopeParam]),
26149
+ t4.objectExpression([])
26150
+ )
26151
+ )
26152
+ ])
26153
+ );
26154
+ }
26155
+ const handlerVar = t4.identifier("__handler");
26156
+ bodyStatements.push(
26157
+ t4.variableDeclaration("const", [t4.variableDeclarator(handlerVar, finalHandlerExpr)])
26158
+ );
26159
+ bodyStatements.push(
26160
+ t4.returnStatement(
26161
+ t4.callExpression(t4.memberExpression(handlerVar, t4.identifier("call")), [elParam, eventParam])
26162
+ )
26163
+ );
26164
+ const exportedHandler = t4.exportNamedDeclaration(
26165
+ t4.variableDeclaration("const", [
26166
+ t4.variableDeclarator(
26167
+ handlerId,
26168
+ t4.arrowFunctionExpression(
26169
+ [scopeParam, eventParam, elParam],
26170
+ t4.blockStatement(bodyStatements)
26171
+ )
26172
+ )
26173
+ ]),
26174
+ []
26175
+ );
26176
+ ctx.hoistedResumableStatements?.push(exportedHandler);
26177
+ ctx.helpersUsed.add("qrl");
26178
+ const qrlExpr = t4.callExpression(t4.identifier(RUNTIME_ALIASES.qrl), [
26179
+ genModuleUrlExpr(ctx),
26180
+ t4.stringLiteral(handlerId.name)
26181
+ ]);
26182
+ statements.push(
26183
+ t4.expressionStatement(
26184
+ t4.callExpression(t4.memberExpression(targetId, t4.identifier("setAttribute")), [
26185
+ t4.stringLiteral(`on:${eventName}`),
26186
+ qrlExpr
26187
+ ])
26188
+ )
26189
+ );
26190
+ }
26191
+ function registerResumableComponent(componentName, ctx) {
26192
+ if (!ctx.resumableEnabled) return;
26193
+ if (!ctx.hoistedResumableStatements || !ctx.resumableComponents) return;
26194
+ if (ctx.resumableComponents.has(componentName)) return;
26195
+ const { t: t4 } = ctx;
26196
+ const resumeExport = `__fict_r${ctx.resumableComponentCounter ?? 0}`;
26197
+ ctx.resumableComponentCounter = (ctx.resumableComponentCounter ?? 0) + 1;
26198
+ const scopeParam = t4.identifier("scopeId");
26199
+ const hostParam = t4.identifier("host");
26200
+ const snapshotId = t4.identifier("snapshot");
26201
+ const ctxId = t4.identifier("ctx");
26202
+ ctx.helpersUsed.add("getSSRScope");
26203
+ ctx.helpersUsed.add("ensureScope");
26204
+ ctx.helpersUsed.add("prepareContext");
26205
+ ctx.helpersUsed.add("pushContext");
26206
+ ctx.helpersUsed.add("popContext");
26207
+ ctx.helpersUsed.add("hydrateComponent");
26208
+ ctx.helpersUsed.add("qrl");
26209
+ const snapshotDecl = t4.variableDeclaration("const", [
26210
+ t4.variableDeclarator(
26211
+ snapshotId,
26212
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.getSSRScope), [scopeParam])
26213
+ )
26214
+ ]);
26215
+ const earlyReturn = t4.ifStatement(t4.unaryExpression("!", snapshotId), t4.returnStatement());
26216
+ const ensureCtxDecl = t4.variableDeclaration("const", [
26217
+ t4.variableDeclarator(
26218
+ ctxId,
26219
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.ensureScope), [
26220
+ scopeParam,
26221
+ hostParam,
26222
+ snapshotId
26223
+ ])
26224
+ )
26225
+ ]);
26226
+ const prepareCtx = t4.expressionStatement(
26227
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.prepareContext), [ctxId])
26228
+ );
26229
+ const pushCtx = t4.expressionStatement(
26230
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.pushContext), [])
26231
+ );
26232
+ const hydrateCall = t4.expressionStatement(
26233
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.hydrateComponent), [
26234
+ t4.arrowFunctionExpression(
26235
+ [],
26236
+ t4.callExpression(t4.identifier(componentName), [
26237
+ t4.logicalExpression(
26238
+ "||",
26239
+ t4.memberExpression(snapshotId, t4.identifier("props")),
26240
+ t4.objectExpression([])
26241
+ )
26242
+ ])
26243
+ ),
26244
+ hostParam
26245
+ ])
26246
+ );
26247
+ const popCtx = t4.expressionStatement(
26248
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.popContext), [])
26249
+ );
26250
+ const resumeFnId = t4.identifier(resumeExport);
26251
+ const resumeFn = t4.exportNamedDeclaration(
26252
+ t4.variableDeclaration("const", [
26253
+ t4.variableDeclarator(
26254
+ resumeFnId,
26255
+ t4.arrowFunctionExpression(
26256
+ [scopeParam, hostParam],
26257
+ t4.blockStatement([
26258
+ snapshotDecl,
26259
+ earlyReturn,
26260
+ ensureCtxDecl,
26261
+ t4.tryStatement(
26262
+ t4.blockStatement([prepareCtx, pushCtx, hydrateCall]),
26263
+ null,
26264
+ t4.blockStatement([popCtx])
26265
+ )
26266
+ ])
26267
+ )
26268
+ )
26269
+ ]),
26270
+ []
26271
+ );
26272
+ ctx.helpersUsed.add("registerResume");
26273
+ const registerCall = t4.expressionStatement(
26274
+ t4.callExpression(t4.identifier(RUNTIME_ALIASES.registerResume), [
26275
+ t4.stringLiteral(resumeExport),
26276
+ resumeFnId
26277
+ ])
26278
+ );
26279
+ const metaId = t4.identifier(`__fict_meta_${componentName}`);
26280
+ const moduleUrlExpr = genModuleUrlExpr(ctx);
26281
+ const typeKeyExpr = t4.binaryExpression("+", t4.stringLiteral(`${componentName}@`), moduleUrlExpr);
26282
+ const resumeQrlExpr = t4.callExpression(t4.identifier(RUNTIME_ALIASES.qrl), [
26283
+ genModuleUrlExpr(ctx),
26284
+ t4.stringLiteral(resumeExport)
26285
+ ]);
26286
+ const metaDecl = t4.variableDeclaration("const", [
26287
+ t4.variableDeclarator(
26288
+ metaId,
26289
+ t4.objectExpression([
26290
+ t4.objectProperty(t4.identifier("id"), typeKeyExpr),
26291
+ t4.objectProperty(t4.identifier("resume"), resumeQrlExpr)
26292
+ ])
26293
+ )
26294
+ ]);
26295
+ const assignMeta = t4.expressionStatement(
26296
+ t4.assignmentExpression(
26297
+ "=",
26298
+ t4.memberExpression(t4.identifier(componentName), t4.identifier("__fictMeta")),
26299
+ metaId
26300
+ )
26301
+ );
26302
+ ctx.hoistedResumableStatements.push(resumeFn, registerCall, metaDecl, assignMeta);
26303
+ ctx.resumableComponents.set(componentName, { resumeExport, typeKey: componentName });
26304
+ }
26305
+ function emitConditionalChild(startMarkerId, endMarkerId, expr, statements, ctx) {
25637
26306
  const { t: t4 } = ctx;
25638
26307
  ctx.helpersUsed.add("conditional");
25639
26308
  ctx.helpersUsed.add("createElement");
@@ -25674,7 +26343,10 @@ function emitConditionalChild(parentId, markerId, expr, statements, ctx) {
25674
26343
  ];
25675
26344
  if (alternate) {
25676
26345
  args.push(t4.arrowFunctionExpression([], alternate));
26346
+ } else {
26347
+ args.push(t4.identifier("undefined"));
25677
26348
  }
26349
+ args.push(startMarkerId, endMarkerId);
25678
26350
  statements.push(
25679
26351
  t4.variableDeclaration("const", [
25680
26352
  t4.variableDeclarator(
@@ -25683,14 +26355,6 @@ function emitConditionalChild(parentId, markerId, expr, statements, ctx) {
25683
26355
  )
25684
26356
  ])
25685
26357
  );
25686
- statements.push(
25687
- t4.expressionStatement(
25688
- t4.callExpression(t4.memberExpression(parentId, t4.identifier("insertBefore")), [
25689
- t4.memberExpression(bindingId, t4.identifier("marker")),
25690
- markerId
25691
- ])
25692
- )
25693
- );
25694
26358
  statements.push(
25695
26359
  t4.expressionStatement(
25696
26360
  t4.optionalCallExpression(
@@ -26297,40 +26961,16 @@ function buildListCallExpression(expr, statements, ctx) {
26297
26961
  }
26298
26962
  return listCall;
26299
26963
  }
26300
- function emitListChild(parentId, markerId, expr, statements, ctx) {
26964
+ function emitListChild(startMarkerId, endMarkerId, expr, statements, ctx) {
26301
26965
  const { t: t4 } = ctx;
26302
26966
  const listCall = buildListCallExpression(expr, statements, ctx);
26303
26967
  if (!listCall) return;
26968
+ if (t4.isCallExpression(listCall)) {
26969
+ listCall.arguments.push(startMarkerId, endMarkerId);
26970
+ }
26304
26971
  ctx.helpersUsed.add("onDestroy");
26305
- ctx.helpersUsed.add("toNodeArray");
26306
26972
  const listId = genTemp(ctx, "list");
26307
26973
  statements.push(t4.variableDeclaration("const", [t4.variableDeclarator(listId, listCall)]));
26308
- const markersId = genTemp(ctx, "markers");
26309
- statements.push(
26310
- t4.variableDeclaration("const", [
26311
- t4.variableDeclarator(
26312
- markersId,
26313
- t4.callExpression(t4.identifier(RUNTIME_ALIASES.toNodeArray), [
26314
- t4.memberExpression(listId, t4.identifier("marker"))
26315
- ])
26316
- )
26317
- ])
26318
- );
26319
- const mId = genTemp(ctx, "m");
26320
- statements.push(
26321
- t4.forOfStatement(
26322
- t4.variableDeclaration("const", [t4.variableDeclarator(mId)]),
26323
- markersId,
26324
- t4.blockStatement([
26325
- t4.expressionStatement(
26326
- t4.callExpression(t4.memberExpression(parentId, t4.identifier("insertBefore")), [
26327
- mId,
26328
- markerId
26329
- ])
26330
- )
26331
- ])
26332
- )
26333
- );
26334
26974
  statements.push(
26335
26975
  t4.expressionStatement(
26336
26976
  t4.optionalCallExpression(
@@ -26367,6 +27007,9 @@ function lowerHIRWithRegions(program, t4, options, macroAliases) {
26367
27007
  program.functions.filter((fn) => !!fn.name).map((fn) => [fn.name, fn])
26368
27008
  );
26369
27009
  ctx.options = options;
27010
+ ctx.resumableEnabled = options?.resumable === true;
27011
+ ctx.autoExtractEnabled = options?.autoExtractHandlers ?? options?.resumable === true;
27012
+ ctx.autoExtractThreshold = options?.autoExtractThreshold ?? 3;
26370
27013
  const body = [];
26371
27014
  const topLevelAliases = /* @__PURE__ */ new Set();
26372
27015
  let topLevelCtxInjected = false;
@@ -26613,6 +27256,9 @@ function lowerHIRWithRegions(program, t4, options, macroAliases) {
26613
27256
  lowerableBuffer.push(stmt);
26614
27257
  }
26615
27258
  flushLowerableBuffer();
27259
+ if (ctx.resumableEnabled && ctx.hoistedResumableStatements && ctx.hoistedResumableStatements.length > 0) {
27260
+ body.push(...ctx.hoistedResumableStatements);
27261
+ }
26616
27262
  for (const func of generatedFunctions.values()) {
26617
27263
  body.push(func.stmt);
26618
27264
  if (func.stmt.id?.name) emittedFunctionNames.add(func.stmt.id.name);
@@ -26653,12 +27299,15 @@ function lowerTopLevelStatementBlock(statements, ctx, t4, name = "__module_segme
26653
27299
  ctx.storeVars = storeVars;
26654
27300
  ctx.memoVars = memoVars;
26655
27301
  ctx.mutatedVars = mutatedVars;
27302
+ const componentFunctionDefs = ctx.componentFunctionDefs ?? /* @__PURE__ */ new Map();
27303
+ ctx.componentFunctionDefs = componentFunctionDefs;
26656
27304
  for (const block of fn.blocks) {
26657
27305
  for (const instr of block.instructions) {
26658
27306
  if (instr.kind === "Assign") {
26659
27307
  const target = deSSAVarName(instr.target.name);
26660
27308
  if (instr.value.kind === "ArrowFunction" || instr.value.kind === "FunctionExpression") {
26661
27309
  functionVars.add(target);
27310
+ componentFunctionDefs.set(target, instr.value);
26662
27311
  }
26663
27312
  if (instr.value.kind === "CallExpression" || instr.value.kind === "OptionalCallExpression") {
26664
27313
  const callKind = getReactiveCallKind(instr.value, ctx);
@@ -26826,6 +27475,8 @@ function lowerFunctionWithRegions(fn, ctx, options) {
26826
27475
  ctx.mutatedVars = /* @__PURE__ */ new Set();
26827
27476
  ctx.noMemo = !!(prevNoMemo || fn.meta?.noMemo);
26828
27477
  ctx.hookResultVarMap = /* @__PURE__ */ new Map();
27478
+ const prevComponentFunctionDefs = ctx.componentFunctionDefs;
27479
+ ctx.componentFunctionDefs = /* @__PURE__ */ new Map();
26829
27480
  const hookResultVars = /* @__PURE__ */ new Set();
26830
27481
  const hookAccessorAliases = /* @__PURE__ */ new Set();
26831
27482
  const prevPropsParam = ctx.propsParamName;
@@ -26842,6 +27493,7 @@ function lowerFunctionWithRegions(fn, ctx, options) {
26842
27493
  const target = deSSAVarName(instr.target.name);
26843
27494
  if (instr.value.kind === "ArrowFunction" || instr.value.kind === "FunctionExpression") {
26844
27495
  ctx.functionVars?.add(target);
27496
+ ctx.componentFunctionDefs?.set(target, instr.value);
26845
27497
  }
26846
27498
  if (instr.value.kind === "CallExpression" || instr.value.kind === "OptionalCallExpression") {
26847
27499
  const callKind = getReactiveCallKind(instr.value, ctx);
@@ -27137,6 +27789,7 @@ function lowerFunctionWithRegions(fn, ctx, options) {
27137
27789
  ctx.externalTracked = prevExternalTracked;
27138
27790
  ctx.signalVars = prevSignalVars;
27139
27791
  ctx.functionVars = prevFunctionVars;
27792
+ ctx.componentFunctionDefs = prevComponentFunctionDefs;
27140
27793
  ctx.memoVars = prevMemoVars;
27141
27794
  ctx.storeVars = prevStoreVars;
27142
27795
  ctx.mutatedVars = prevMutatedVars;
@@ -27154,6 +27807,7 @@ function lowerFunctionWithRegions(fn, ctx, options) {
27154
27807
  ctx.externalTracked = prevExternalTracked;
27155
27808
  ctx.signalVars = prevSignalVars;
27156
27809
  ctx.functionVars = prevFunctionVars;
27810
+ ctx.componentFunctionDefs = prevComponentFunctionDefs;
27157
27811
  ctx.memoVars = prevMemoVars;
27158
27812
  ctx.storeVars = prevStoreVars;
27159
27813
  ctx.mutatedVars = prevMutatedVars;
@@ -27250,6 +27904,9 @@ function lowerFunctionWithRegions(fn, ctx, options) {
27250
27904
  fn.loc
27251
27905
  );
27252
27906
  funcDecl.async = isAsync;
27907
+ if (isComponent && fn.name) {
27908
+ registerResumableComponent(fn.name, ctx);
27909
+ }
27253
27910
  ctx.needsCtx = prevNeedsCtx;
27254
27911
  ctx.shadowedNames = prevShadowed;
27255
27912
  ctx.localDeclaredNames = prevLocalDeclared;
@@ -27257,6 +27914,7 @@ function lowerFunctionWithRegions(fn, ctx, options) {
27257
27914
  ctx.externalTracked = prevExternalTracked;
27258
27915
  ctx.signalVars = prevSignalVars;
27259
27916
  ctx.functionVars = prevFunctionVars;
27917
+ ctx.componentFunctionDefs = prevComponentFunctionDefs;
27260
27918
  ctx.memoVars = prevMemoVars;
27261
27919
  ctx.storeVars = prevStoreVars;
27262
27920
  ctx.mutatedVars = prevMutatedVars;