octane 0.1.20 → 0.1.21
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/compiler/compile.js +138 -48
- package/dist/runtime.js +272 -11
- package/package.json +1 -1
package/dist/compiler/compile.js
CHANGED
|
@@ -3995,11 +3995,22 @@ function isConditionalJsx(node) {
|
|
|
3995
3995
|
);
|
|
3996
3996
|
}
|
|
3997
3997
|
|
|
3998
|
-
/** Wrap
|
|
3998
|
+
/** Wrap a ternary arm as a BlockStatement body, so makeIfCall can consume it. */
|
|
3999
3999
|
function wrapAsBlockStmt(node) {
|
|
4000
4000
|
if (!node) return null;
|
|
4001
4001
|
// null / Literal(null) / Literal(false) → no branch
|
|
4002
4002
|
if (node.type === 'Literal' && (node.value === null || node.value === false)) return null;
|
|
4003
|
+
if (!isJsxLike(node)) {
|
|
4004
|
+
// A non-JSX arm (`{cond ? xs.map(…) : <Jsx/>}`, a string, a variable
|
|
4005
|
+
// holding an element, a nested ternary) is the branch's render VALUE. As
|
|
4006
|
+
// a bare statement the branch body would evaluate-and-discard it, so wrap
|
|
4007
|
+
// it as the authored-equivalent `<>{expr}</>` — the branch renders the
|
|
4008
|
+
// value through the fragment's child hole. The hole sits at the
|
|
4009
|
+
// fragment's ROOT, a value position on both compilers: a nested ternary
|
|
4010
|
+
// stays a value hole here (it is NOT re-claimed into a nested ifBlock),
|
|
4011
|
+
// which is why the server claim requires host-child position too.
|
|
4012
|
+
node = inheritOriginLoc(b.jsx_fragment([b.jsx_expression_container(node, node)]), node);
|
|
4013
|
+
}
|
|
4003
4014
|
return b.block([node]);
|
|
4004
4015
|
}
|
|
4005
4016
|
|
|
@@ -7482,7 +7493,15 @@ function ssrCompileBodyWithMapTemps(
|
|
|
7482
7493
|
((!!(node.body && node.body.type === 'JSXCodeBlock') && !returnedOutput) ||
|
|
7483
7494
|
returnedFragmentRoot) &&
|
|
7484
7495
|
inheritSoleCompRoot(bodyNodes, ctx);
|
|
7496
|
+
// Body/sub ROOTS (including fragment-root children) are not host-element
|
|
7497
|
+
// children: the client routes rich holes there through the de-opt value
|
|
7498
|
+
// path (a portal has no host to stamp — see the emitNodeHtml root branch),
|
|
7499
|
+
// so the ternary claim must stay off until an element's own children walk
|
|
7500
|
+
// (ssrEmitElement) turns the flag on.
|
|
7501
|
+
const prevHostChildPos = ctx._ssrHostChildPos;
|
|
7502
|
+
ctx._ssrHostChildPos = false;
|
|
7485
7503
|
const htmlExpr = ssrEmitNodes(bodyNodes, ctx, name, inlinedSubs, parentNs, cssHash, componentNs);
|
|
7504
|
+
ctx._ssrHostChildPos = prevHostChildPos;
|
|
7486
7505
|
ctx._ssrInheritRoot = prevInheritRoot;
|
|
7487
7506
|
ctx._returnedFragmentTemplate = prevReturnedFragmentTemplate;
|
|
7488
7507
|
ctx._tsxValuePos = prevValuePos;
|
|
@@ -8587,6 +8606,11 @@ function ssrEmitElement(node, ctx, name, inlinedSubs, parentNs, cssHash, compone
|
|
|
8587
8606
|
// pre/textarea/listing: the parser eats a '\n' right after the opening tag —
|
|
8588
8607
|
// the first text part must protect a leading newline (see ssrEmitNodes).
|
|
8589
8608
|
const nlGuardFirst = tag === 'pre' || tag === 'textarea' || tag === 'listing';
|
|
8609
|
+
// These children sit directly under a host element — the one position
|
|
8610
|
+
// where the client claims `{cond ? A : B}` holes (emitElementHtml). Root
|
|
8611
|
+
// positions reset this in ssrCompileBody.
|
|
8612
|
+
const prevHostChildPos = ctx._ssrHostChildPos;
|
|
8613
|
+
ctx._ssrHostChildPos = true;
|
|
8590
8614
|
childrenExpr = ssrEmitNodes(
|
|
8591
8615
|
normChildren,
|
|
8592
8616
|
ctx,
|
|
@@ -8597,6 +8621,7 @@ function ssrEmitElement(node, ctx, name, inlinedSubs, parentNs, cssHash, compone
|
|
|
8597
8621
|
childComponentNs,
|
|
8598
8622
|
nlGuardFirst,
|
|
8599
8623
|
);
|
|
8624
|
+
ctx._ssrHostChildPos = prevHostChildPos;
|
|
8600
8625
|
}
|
|
8601
8626
|
// `children=` and spread-held children are content props, not attributes.
|
|
8602
8627
|
// With no nested JSX children, the last present writer renders as the host's
|
|
@@ -8925,18 +8950,35 @@ function ssrCompileSub(
|
|
|
8925
8950
|
) {
|
|
8926
8951
|
const fnName = `${baseName}$${ctx.nextHelperId++}`;
|
|
8927
8952
|
const synth = { params: paramNodes || [], body: bodyStmts };
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
|
|
8931
|
-
|
|
8932
|
-
|
|
8933
|
-
|
|
8934
|
-
|
|
8935
|
-
|
|
8936
|
-
|
|
8937
|
-
|
|
8938
|
-
|
|
8939
|
-
|
|
8953
|
+
// Returned-tree mirror subs (`__sfragment`): extractFragment folds EVERY
|
|
8954
|
+
// expression hole in the mirrored tree into a descriptor value hole on the
|
|
8955
|
+
// client (`props.hN` + childTextHole), even holes sitting inside host
|
|
8956
|
+
// elements. Mark them so ssrEmitTsrxExpression keeps `{cond ? A : B}` on
|
|
8957
|
+
// ssrChild throughout the mirror, matching that fold. Directive-arm subs
|
|
8958
|
+
// reset the flag through this same save/restore, so an @if INSIDE a mirror
|
|
8959
|
+
// claims again, exactly like the client. (Component `__schildren` subs are
|
|
8960
|
+
// NOT folded wholesale — only their ROOT holes are the children-as-props
|
|
8961
|
+
// value, which `_ssrHostChildPos` already leaves unclaimed — while a hole
|
|
8962
|
+
// inside a host element within children claims like any template child.)
|
|
8963
|
+
const prevFoldedExprHoles = ctx._ssrFoldedExprHoles;
|
|
8964
|
+
ctx._ssrFoldedExprHoles = baseName === '__sfragment';
|
|
8965
|
+
let fn;
|
|
8966
|
+
try {
|
|
8967
|
+
fn = ssrCompileBody(
|
|
8968
|
+
synth,
|
|
8969
|
+
ctx,
|
|
8970
|
+
fnName,
|
|
8971
|
+
cssHash,
|
|
8972
|
+
[],
|
|
8973
|
+
parentNs || 'html',
|
|
8974
|
+
false,
|
|
8975
|
+
componentNs,
|
|
8976
|
+
returnedFragmentTemplate,
|
|
8977
|
+
returnedFragmentRoot,
|
|
8978
|
+
);
|
|
8979
|
+
} finally {
|
|
8980
|
+
ctx._ssrFoldedExprHoles = prevFoldedExprHoles;
|
|
8981
|
+
}
|
|
8940
8982
|
return { fnName, fn };
|
|
8941
8983
|
}
|
|
8942
8984
|
|
|
@@ -8944,10 +8986,19 @@ function ssrEmitIf(node, ctx, name, inlinedSubs, parentNs, cssHash, componentNs)
|
|
|
8944
8986
|
// rewriteHookCalls: key any `use(thenable)` in the @if test (it bypasses the
|
|
8945
8987
|
// setup rewrite, so without a stable key it collides with sibling/body use()).
|
|
8946
8988
|
const testExpr = rewriteHookCalls(node.test, ctx, name);
|
|
8947
|
-
|
|
8948
|
-
|
|
8949
|
-
|
|
8950
|
-
|
|
8989
|
+
// A null consequent (`{cond ? null : <Jsx/>}` lowered by wrapAsBlockStmt)
|
|
8990
|
+
// means "no then branch". It must emit like a MISSING @else — plain '' with
|
|
8991
|
+
// no inner arm range — because the hydrating client renders that branch with
|
|
8992
|
+
// a null body and adopts an empty slot range.
|
|
8993
|
+
const thenStmts = node.consequent
|
|
8994
|
+
? node.consequent.type === 'BlockStatement'
|
|
8995
|
+
? node.consequent.body
|
|
8996
|
+
: [node.consequent]
|
|
8997
|
+
: null;
|
|
8998
|
+
const thenSub = thenStmts
|
|
8999
|
+
? ssrCompileSub(thenStmts, ctx, '__sif', [], cssHash, parentNs, componentNs)
|
|
9000
|
+
: null;
|
|
9001
|
+
if (thenSub) inlinedSubs.push(thenSub.fn);
|
|
8951
9002
|
let elseCall = ssrHtmlTemplate([], node, ctx);
|
|
8952
9003
|
let elseFnName = null;
|
|
8953
9004
|
if (node.alternate) {
|
|
@@ -8968,26 +9019,33 @@ function ssrEmitIf(node, ctx, name, inlinedSubs, parentNs, cssHash, componentNs)
|
|
|
8968
9019
|
ctx.runtimeNeeded.add('ssrBlock');
|
|
8969
9020
|
ctx.runtimeNeeded.add('ssrControl');
|
|
8970
9021
|
ctx.runtimeNeeded.add('ssrArm');
|
|
8971
|
-
registerDirectiveOrigin(ctx, node, [
|
|
9022
|
+
registerDirectiveOrigin(ctx, node, [
|
|
9023
|
+
'_$ssrControl',
|
|
9024
|
+
'_$ssrArm',
|
|
9025
|
+
thenSub ? thenSub.fnName : null,
|
|
9026
|
+
elseFnName,
|
|
9027
|
+
]);
|
|
8972
9028
|
// Nested ranges: the OUTER ssrBlock is the if-slot; the INNER one wraps the
|
|
8973
9029
|
// taken branch's content. The client adopts BOTH on hydration (slot = outer,
|
|
8974
9030
|
// branch = inner) so no comment markers are inserted — byte-for-byte, exactly
|
|
8975
9031
|
// like @for. The not-taken arm emits no inner range (just `''`).
|
|
8976
|
-
const thenInner =
|
|
8977
|
-
|
|
8978
|
-
|
|
8979
|
-
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
|
|
8984
|
-
|
|
8985
|
-
|
|
9032
|
+
const thenInner = thenSub
|
|
9033
|
+
? ssrCall(
|
|
9034
|
+
'ssrArm',
|
|
9035
|
+
[
|
|
9036
|
+
b.literal('then', '"then"'),
|
|
9037
|
+
ssrThunk(
|
|
9038
|
+
ssrCall(
|
|
9039
|
+
'ssrBlock',
|
|
9040
|
+
[ssrSubCall(thenSub.fnName, [b.id('undefined')], node.consequent)],
|
|
9041
|
+
node.consequent,
|
|
9042
|
+
),
|
|
9043
|
+
node.consequent,
|
|
9044
|
+
),
|
|
9045
|
+
],
|
|
8986
9046
|
node.consequent,
|
|
8987
|
-
)
|
|
8988
|
-
],
|
|
8989
|
-
node.consequent,
|
|
8990
|
-
);
|
|
9047
|
+
)
|
|
9048
|
+
: ssrHtmlTemplate([], node, ctx);
|
|
8991
9049
|
const elseInner = node.alternate
|
|
8992
9050
|
? ssrCall(
|
|
8993
9051
|
'ssrArm',
|
|
@@ -9441,6 +9499,30 @@ function ssrEmitTsrxExpression(node, ctx, name, inlinedSubs, parentNs, cssHash,
|
|
|
9441
9499
|
ctx.runtimeNeeded.add('ssrPortal');
|
|
9442
9500
|
return ssrCall('ssrPortal', [], node);
|
|
9443
9501
|
}
|
|
9502
|
+
if (
|
|
9503
|
+
node.returnedJsxValue !== true &&
|
|
9504
|
+
ctx._tsxValuePos !== true &&
|
|
9505
|
+
ctx._ssrFoldedExprHoles !== true &&
|
|
9506
|
+
ctx._ssrHostChildPos === true &&
|
|
9507
|
+
isConditionalJsx(expr)
|
|
9508
|
+
) {
|
|
9509
|
+
// Mirror the client's claim EXACTLY: only emitElementHtml's children
|
|
9510
|
+
// walk lowers `{cond ? A : B}` with a JSX arm to an @if, so both sides
|
|
9511
|
+
// compile each arm as an ordinary arm body and the hydration shapes
|
|
9512
|
+
// (control key, arm ranges, a keyed `.map` claimed inside a value arm)
|
|
9513
|
+
// agree by construction. Everywhere else the hole is a VALUE on the
|
|
9514
|
+
// client and must stay on ssrChild here: returned `.tsx` trees
|
|
9515
|
+
// (`_tsxValuePos`), returned-tree mirrors whose holes extractFragment
|
|
9516
|
+
// folds to `props.hN` (`_ssrFoldedExprHoles`), and every non-host-child
|
|
9517
|
+
// position — body/arm/fragment roots and component-children roots,
|
|
9518
|
+
// where a rich hole rides the de-opt value path because a portal there
|
|
9519
|
+
// has no host to stamp (`_ssrHostChildPos`).
|
|
9520
|
+
const asIf = {
|
|
9521
|
+
...b.if(expr.test, wrapAsBlockStmt(expr.consequent), wrapAsBlockStmt(expr.alternate)),
|
|
9522
|
+
loc: expr.loc, // same devLoc/control-key position as the client's claim
|
|
9523
|
+
};
|
|
9524
|
+
return ssrEmitIf(asIf, ctx, name, inlinedSubs, parentNs, cssHash, componentNs);
|
|
9525
|
+
}
|
|
9444
9526
|
ctx.runtimeNeeded.add('ssrChild');
|
|
9445
9527
|
// rewriteHookCalls first (key any `use(thenable)` in the hole — it bypasses the
|
|
9446
9528
|
// setup rewrite), then rewriteJsxValues (lower nested JSX to createElement).
|
|
@@ -20169,10 +20251,16 @@ function hoistBodyHelper(
|
|
|
20169
20251
|
// ===========================================================================
|
|
20170
20252
|
|
|
20171
20253
|
function makeIfCall(node, ctx, inlinedSubs, parentNs = 'html', cssHash = null) {
|
|
20172
|
-
// node.test, node.consequent (BlockStatement | Element), node.alternate (BlockStatement | IfStatement | null)
|
|
20173
|
-
|
|
20174
|
-
|
|
20175
|
-
|
|
20254
|
+
// node.test, node.consequent (BlockStatement | Element | null), node.alternate (BlockStatement | IfStatement | null)
|
|
20255
|
+
// A null consequent (`{cond ? null : <Jsx/>}` lowered by wrapAsBlockStmt)
|
|
20256
|
+
// means "no then branch" — same contract as the null alternate: the helper
|
|
20257
|
+
// slot compiles to `null` and the runtime renders an empty branch.
|
|
20258
|
+
|
|
20259
|
+
const thenStmts = node.consequent
|
|
20260
|
+
? node.consequent.type === 'BlockStatement'
|
|
20261
|
+
? node.consequent.body
|
|
20262
|
+
: [node.consequent]
|
|
20263
|
+
: null;
|
|
20176
20264
|
const elseStmts = node.alternate
|
|
20177
20265
|
? node.alternate.type === 'BlockStatement'
|
|
20178
20266
|
? node.alternate.body
|
|
@@ -20180,20 +20268,22 @@ function makeIfCall(node, ctx, inlinedSubs, parentNs = 'html', cssHash = null) {
|
|
|
20180
20268
|
: null;
|
|
20181
20269
|
// Phase 2: one shared env tuple for both branches (see unionEnv).
|
|
20182
20270
|
const envNames = unionEnv(ctx, [
|
|
20183
|
-
{ stmts: thenStmts, params: [] },
|
|
20271
|
+
thenStmts && { stmts: thenStmts, params: [] },
|
|
20184
20272
|
elseStmts && { stmts: elseStmts, params: [] },
|
|
20185
20273
|
]);
|
|
20186
|
-
const thenHelperName =
|
|
20187
|
-
|
|
20188
|
-
|
|
20189
|
-
|
|
20190
|
-
|
|
20191
|
-
|
|
20192
|
-
|
|
20193
|
-
|
|
20194
|
-
|
|
20195
|
-
|
|
20196
|
-
|
|
20274
|
+
const thenHelperName = thenStmts
|
|
20275
|
+
? hoistBodyHelper(
|
|
20276
|
+
ctx,
|
|
20277
|
+
inlinedSubs,
|
|
20278
|
+
'__then',
|
|
20279
|
+
thenStmts,
|
|
20280
|
+
[],
|
|
20281
|
+
parentNs,
|
|
20282
|
+
cssHash,
|
|
20283
|
+
envNames,
|
|
20284
|
+
directiveKeywordOrigin(ctx, node),
|
|
20285
|
+
)
|
|
20286
|
+
: null;
|
|
20197
20287
|
|
|
20198
20288
|
let elseHelperName = null;
|
|
20199
20289
|
if (elseStmts) {
|
package/dist/runtime.js
CHANGED
|
@@ -315,6 +315,13 @@ function flushTransitionActionBatch(batch) {
|
|
|
315
315
|
);
|
|
316
316
|
scheduleRender(block);
|
|
317
317
|
}
|
|
318
|
+
if (batch.updates.size > 0) {
|
|
319
|
+
const retained = [];
|
|
320
|
+
for (const update of batch.updates.values()) {
|
|
321
|
+
if (!update.block.disposed) retained.push(update);
|
|
322
|
+
}
|
|
323
|
+
if (retained.length > 0) FLUSHED_TRANSITION_UPDATES.push(retained);
|
|
324
|
+
}
|
|
318
325
|
batch.updates.clear();
|
|
319
326
|
if (IN_FLIGHT_TRANSITION_ACTION_BATCH === batch) {
|
|
320
327
|
IN_FLIGHT_TRANSITION_ACTION_BATCH = null;
|
|
@@ -331,6 +338,183 @@ const HELD_TRANSITIONS = /* @__PURE__ */ new Set();
|
|
|
331
338
|
const STAGED_REVEALS = /* @__PURE__ */ new Set();
|
|
332
339
|
let flushingStagedReveals = false;
|
|
333
340
|
let deferringStagedRevealEffects = false;
|
|
341
|
+
let ACTIVE_TRANSITION_ATTEMPT = null;
|
|
342
|
+
let FLUSHED_TRANSITION_UPDATES = [];
|
|
343
|
+
let HELD_SYNC_TRANSITION = null;
|
|
344
|
+
let PROMOTED_PU_SWAPS = null;
|
|
345
|
+
let PROMOTED_WARM_HARVEST = null;
|
|
346
|
+
function beginTransitionAttempt(block) {
|
|
347
|
+
if (block.pendingMode !== "transition" || ACTIVE_TRANSITION_ATTEMPT !== null) return null;
|
|
348
|
+
TRANSITION_JOURNAL ??= [];
|
|
349
|
+
TRANSITION_JOURNAL_BAGS ??= /* @__PURE__ */ new Set();
|
|
350
|
+
TRANSITION_JOURNAL_DEPTH++;
|
|
351
|
+
const attempt = {
|
|
352
|
+
origin: block,
|
|
353
|
+
journalCheckpoint: TRANSITION_JOURNAL.length,
|
|
354
|
+
effects: [effectQueues[0].length, effectQueues[1].length, effectQueues[2].length],
|
|
355
|
+
effectEvents: effectEventQueue.length,
|
|
356
|
+
effectEventActions: effectEventCommitActions.length,
|
|
357
|
+
stores: storeSyncQueue.length,
|
|
358
|
+
refAttach: refAttachQueue.length,
|
|
359
|
+
refDetach: refDetachQueue.length,
|
|
360
|
+
effectDeps: snapshotSubtreeEffectDeps(block),
|
|
361
|
+
heldSlots: null,
|
|
362
|
+
puSwaps: null
|
|
363
|
+
};
|
|
364
|
+
ACTIVE_TRANSITION_ATTEMPT = attempt;
|
|
365
|
+
return attempt;
|
|
366
|
+
}
|
|
367
|
+
function endTransitionAttempt(attempt) {
|
|
368
|
+
if (attempt === null) return;
|
|
369
|
+
ACTIVE_TRANSITION_ATTEMPT = null;
|
|
370
|
+
const held = attempt.heldSlots;
|
|
371
|
+
if (held === null || held.size === 0) {
|
|
372
|
+
PROMOTED_PU_SWAPS = null;
|
|
373
|
+
PROMOTED_WARM_HARVEST = null;
|
|
374
|
+
}
|
|
375
|
+
let entries = null;
|
|
376
|
+
if (held !== null && held.size > 0) {
|
|
377
|
+
entries = [];
|
|
378
|
+
for (let i = FLUSHED_TRANSITION_UPDATES.length - 1; i >= 0; i--) {
|
|
379
|
+
const group = FLUSHED_TRANSITION_UPDATES[i];
|
|
380
|
+
let single = true;
|
|
381
|
+
for (let k = 0; k < group.length; k++) {
|
|
382
|
+
if (group[k].block !== attempt.origin) {
|
|
383
|
+
single = false;
|
|
384
|
+
break;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
if (!single) continue;
|
|
388
|
+
for (let k = 0; k < group.length; k++) entries.push(group[k]);
|
|
389
|
+
FLUSHED_TRANSITION_UPDATES.splice(i, 1);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (held !== null && held.size > 0 && entries !== null && entries.length > 0) {
|
|
393
|
+
rollbackTransitionJournal(attempt.journalCheckpoint);
|
|
394
|
+
for (let phase = 0; phase < 3; phase++) {
|
|
395
|
+
effectQueues[phase].length = attempt.effects[phase];
|
|
396
|
+
}
|
|
397
|
+
effectEventQueue.length = attempt.effectEvents;
|
|
398
|
+
effectEventCommitActions.length = attempt.effectEventActions;
|
|
399
|
+
for (let i = attempt.stores; i < storeSyncQueue.length; i++) {
|
|
400
|
+
storeSyncQueue[i].queued = false;
|
|
401
|
+
}
|
|
402
|
+
storeSyncQueue.length = attempt.stores;
|
|
403
|
+
refAttachQueue.length = attempt.refAttach;
|
|
404
|
+
refDetachQueue.length = attempt.refDetach;
|
|
405
|
+
restoreSubtreeEffectDeps(attempt.origin, attempt.effectDeps);
|
|
406
|
+
const continuing = PROMOTED_PU_SWAPS !== null || PROMOTED_WARM_HARVEST !== null;
|
|
407
|
+
let puSwaps = attempt.puSwaps;
|
|
408
|
+
if (continuing) {
|
|
409
|
+
if (PROMOTED_PU_SWAPS !== null) {
|
|
410
|
+
puSwaps = puSwaps === null ? PROMOTED_PU_SWAPS : PROMOTED_PU_SWAPS.concat(puSwaps);
|
|
411
|
+
PROMOTED_PU_SWAPS = null;
|
|
412
|
+
}
|
|
413
|
+
} else if (puSwaps !== null) {
|
|
414
|
+
for (let i = puSwaps.length - 1; i >= 0; i--) {
|
|
415
|
+
const [hooks, slot, prev] = puSwaps[i];
|
|
416
|
+
if (prev === void 0) hooks.delete(slot);
|
|
417
|
+
else hooks.set(slot, prev);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
for (let i = 0; i < entries.length; i++) {
|
|
421
|
+
entries[i].slot.value = entries[i].baseValue;
|
|
422
|
+
}
|
|
423
|
+
let warmHarvest = PROMOTED_WARM_HARVEST;
|
|
424
|
+
PROMOTED_WARM_HARVEST = null;
|
|
425
|
+
if (warmHarvest !== null) {
|
|
426
|
+
for (let i = 0; i < warmHarvest.length; i++) warmHarvest[i].taken = false;
|
|
427
|
+
}
|
|
428
|
+
const harvest = (scope) => {
|
|
429
|
+
const cache = scope.block.__warmCache;
|
|
430
|
+
if (cache !== void 0) {
|
|
431
|
+
for (const [slot, list] of cache) {
|
|
432
|
+
for (let i = 0; i < list.length; i++) {
|
|
433
|
+
const entry = list[i];
|
|
434
|
+
if (entry.available) {
|
|
435
|
+
(warmHarvest ??= []).push({
|
|
436
|
+
slot,
|
|
437
|
+
deps: entry.deps,
|
|
438
|
+
value: entry.value,
|
|
439
|
+
taken: false
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
forEachSubtreeChild(scope, harvest);
|
|
446
|
+
};
|
|
447
|
+
harvest(attempt.origin);
|
|
448
|
+
HELD_SYNC_TRANSITION = {
|
|
449
|
+
origin: attempt.origin,
|
|
450
|
+
entries,
|
|
451
|
+
puSwaps,
|
|
452
|
+
warmHarvest,
|
|
453
|
+
holders: new Set(held)
|
|
454
|
+
};
|
|
455
|
+
if (!continuing) scheduleRender(attempt.origin);
|
|
456
|
+
}
|
|
457
|
+
if (--TRANSITION_JOURNAL_DEPTH === 0) {
|
|
458
|
+
TRANSITION_JOURNAL = null;
|
|
459
|
+
TRANSITION_JOURNAL_BAGS = null;
|
|
460
|
+
flushParkedItems();
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
function journalPuEntry(scope, slot, next) {
|
|
464
|
+
const attempt = ACTIVE_TRANSITION_ATTEMPT;
|
|
465
|
+
if (attempt === null) return;
|
|
466
|
+
const hooks = ensureHooks(scope);
|
|
467
|
+
(attempt.puSwaps ??= []).push([hooks, slot, hooks.get(slot), next]);
|
|
468
|
+
}
|
|
469
|
+
function heldSyncCellsIntact(state) {
|
|
470
|
+
const held = HELD_SYNC_TRANSITION;
|
|
471
|
+
if (held === null || !held.holders.has(state)) return false;
|
|
472
|
+
for (let i = 0; i < held.entries.length; i++) {
|
|
473
|
+
const entry = held.entries[i];
|
|
474
|
+
if (!Object.is(entry.slot.value, entry.baseValue)) return false;
|
|
475
|
+
}
|
|
476
|
+
return true;
|
|
477
|
+
}
|
|
478
|
+
function promoteHeldSyncTransition() {
|
|
479
|
+
const held = HELD_SYNC_TRANSITION;
|
|
480
|
+
if (held === null) return false;
|
|
481
|
+
HELD_SYNC_TRANSITION = null;
|
|
482
|
+
const puSwaps = held.puSwaps;
|
|
483
|
+
if (puSwaps !== null) {
|
|
484
|
+
for (let i = 0; i < puSwaps.length; i++) {
|
|
485
|
+
const [hooks, slot, , next] = puSwaps[i];
|
|
486
|
+
hooks.set(slot, next);
|
|
487
|
+
}
|
|
488
|
+
PROMOTED_PU_SWAPS = PROMOTED_PU_SWAPS === null ? puSwaps : PROMOTED_PU_SWAPS.concat(puSwaps);
|
|
489
|
+
}
|
|
490
|
+
PROMOTED_WARM_HARVEST = held.warmHarvest;
|
|
491
|
+
const promoted = [];
|
|
492
|
+
TRANSITION_DEPTH++;
|
|
493
|
+
try {
|
|
494
|
+
for (let i = 0; i < held.entries.length; i++) {
|
|
495
|
+
const entry = held.entries[i];
|
|
496
|
+
if (!Object.is(entry.slot.value, entry.baseValue)) continue;
|
|
497
|
+
entry.slot.value = entry.value;
|
|
498
|
+
if (!entry.block.disposed) {
|
|
499
|
+
promoted.push(entry);
|
|
500
|
+
scheduleRender(entry.block);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
} finally {
|
|
504
|
+
TRANSITION_DEPTH--;
|
|
505
|
+
}
|
|
506
|
+
if (promoted.length > 0) FLUSHED_TRANSITION_UPDATES.push(promoted);
|
|
507
|
+
return true;
|
|
508
|
+
}
|
|
509
|
+
function discardHeldSyncTransition(state) {
|
|
510
|
+
const held = HELD_SYNC_TRANSITION;
|
|
511
|
+
if (held === null || !held.holders.delete(state)) return;
|
|
512
|
+
if (held.holders.size === 0) {
|
|
513
|
+
HELD_SYNC_TRANSITION = null;
|
|
514
|
+
PROMOTED_PU_SWAPS = null;
|
|
515
|
+
PROMOTED_WARM_HARVEST = null;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
334
518
|
const JOURNAL_TEXT = 0;
|
|
335
519
|
const JOURNAL_ATTR = 1;
|
|
336
520
|
const JOURNAL_BAG = 2;
|
|
@@ -1007,7 +1191,12 @@ function drainQueue() {
|
|
|
1007
1191
|
block.drainStamp = drainId;
|
|
1008
1192
|
block.drainRenders = 1;
|
|
1009
1193
|
}
|
|
1010
|
-
|
|
1194
|
+
const attempt = beginTransitionAttempt(block);
|
|
1195
|
+
try {
|
|
1196
|
+
renderBlock(block);
|
|
1197
|
+
} finally {
|
|
1198
|
+
endTransitionAttempt(attempt);
|
|
1199
|
+
}
|
|
1011
1200
|
} catch (err) {
|
|
1012
1201
|
try {
|
|
1013
1202
|
handleRenderError(block, err);
|
|
@@ -1040,6 +1229,7 @@ function flush() {
|
|
|
1040
1229
|
}
|
|
1041
1230
|
function flushWork() {
|
|
1042
1231
|
inFlush = true;
|
|
1232
|
+
const clearRetainedTransitionUpdates = FLUSHED_TRANSITION_UPDATES.length > 0;
|
|
1043
1233
|
const viewTransitionDriver = VIEW_TRANSITION_DRIVER;
|
|
1044
1234
|
const clearViewTransitionTypes = viewTransitionDriver?.shouldClearTypesAfterFlush() === true;
|
|
1045
1235
|
try {
|
|
@@ -1049,6 +1239,8 @@ function flushWork() {
|
|
|
1049
1239
|
if (pendingError !== null) throw pendingError.err;
|
|
1050
1240
|
} finally {
|
|
1051
1241
|
inFlush = false;
|
|
1242
|
+
if (clearRetainedTransitionUpdates || FLUSHED_TRANSITION_UPDATES.length > 0)
|
|
1243
|
+
FLUSHED_TRANSITION_UPDATES.length = 0;
|
|
1052
1244
|
if (typeof __OCTANE_PROFILE_ENABLED__ !== "undefined" && __OCTANE_PROFILE_ENABLED__)
|
|
1053
1245
|
__devtoolsNotifyFlush();
|
|
1054
1246
|
if (clearViewTransitionTypes) viewTransitionDriver.clearTypes();
|
|
@@ -2766,16 +2958,19 @@ function useMemo(compute, deps, slot) {
|
|
|
2766
2958
|
if (WARM_EVER && d !== void 0) {
|
|
2767
2959
|
const adopted = adoptWarmValue(s, d);
|
|
2768
2960
|
if (adopted !== WARM_MISS) {
|
|
2769
|
-
|
|
2961
|
+
const adoptedEntry = {
|
|
2770
2962
|
deps: d,
|
|
2771
2963
|
value: adopted,
|
|
2772
2964
|
warmEpisode: CURRENT_WARM_EPISODE
|
|
2773
|
-
}
|
|
2965
|
+
};
|
|
2966
|
+
if (ACTIVE_TRANSITION_ATTEMPT !== null) journalPuEntry(scope, s, adoptedEntry);
|
|
2967
|
+
ensureHooks(scope).set(s, adoptedEntry);
|
|
2774
2968
|
return adopted;
|
|
2775
2969
|
}
|
|
2776
2970
|
}
|
|
2777
2971
|
const value = compute.apply(null, d ?? []);
|
|
2778
2972
|
const entry = { deps: d, value };
|
|
2973
|
+
if (ACTIVE_TRANSITION_ATTEMPT !== null) journalPuEntry(scope, s, entry);
|
|
2779
2974
|
ensureHooks(scope).set(s, entry);
|
|
2780
2975
|
if (d !== void 0 && recordRealWarmMemo(s, d, entry)) {
|
|
2781
2976
|
entry.warmEpisode = CURRENT_WARM_EPISODE;
|
|
@@ -4332,6 +4527,16 @@ function adoptWarmValue(slot, deps) {
|
|
|
4332
4527
|
}
|
|
4333
4528
|
b = b.parentBlock;
|
|
4334
4529
|
}
|
|
4530
|
+
const harvestList = HELD_SYNC_TRANSITION?.warmHarvest ?? PROMOTED_WARM_HARVEST;
|
|
4531
|
+
if (harvestList !== null && harvestList !== void 0) {
|
|
4532
|
+
for (let i = 0; i < harvestList.length; i++) {
|
|
4533
|
+
const entry = harvestList[i];
|
|
4534
|
+
if (!entry.taken && entry.slot === slot && !depsChanged(entry.deps, deps)) {
|
|
4535
|
+
entry.taken = true;
|
|
4536
|
+
return entry.value;
|
|
4537
|
+
}
|
|
4538
|
+
}
|
|
4539
|
+
}
|
|
4335
4540
|
return WARM_MISS;
|
|
4336
4541
|
}
|
|
4337
4542
|
const puMiss = /* @__PURE__ */ Symbol("octane.pu.miss");
|
|
@@ -4344,11 +4549,13 @@ function puHit(slot, entry) {
|
|
|
4344
4549
|
function puAdopt(slot, deps) {
|
|
4345
4550
|
const adopted = adoptWarmValue(slot, deps);
|
|
4346
4551
|
if (adopted === WARM_MISS) return puMiss;
|
|
4347
|
-
|
|
4552
|
+
const adoptedEntry = {
|
|
4348
4553
|
deps,
|
|
4349
4554
|
value: adopted,
|
|
4350
4555
|
warmEpisode: CURRENT_WARM_EPISODE
|
|
4351
|
-
}
|
|
4556
|
+
};
|
|
4557
|
+
if (ACTIVE_TRANSITION_ATTEMPT !== null) journalPuEntry(CURRENT_SCOPE, slot, adoptedEntry);
|
|
4558
|
+
ensureHooks(CURRENT_SCOPE).set(slot, adoptedEntry);
|
|
4352
4559
|
return adopted;
|
|
4353
4560
|
}
|
|
4354
4561
|
function puTake0(slot) {
|
|
@@ -4403,6 +4610,7 @@ function puTake4(slot, d0, d1, d2, d3) {
|
|
|
4403
4610
|
}
|
|
4404
4611
|
function puPub(slot, value, ...deps) {
|
|
4405
4612
|
const entry = { deps, value };
|
|
4613
|
+
if (ACTIVE_TRANSITION_ATTEMPT !== null) journalPuEntry(CURRENT_SCOPE, slot, entry);
|
|
4406
4614
|
ensureHooks(CURRENT_SCOPE).set(slot, entry);
|
|
4407
4615
|
if (recordRealWarmMemo(slot, deps, entry)) entry.warmEpisode = CURRENT_WARM_EPISODE;
|
|
4408
4616
|
return value;
|
|
@@ -9721,6 +9929,10 @@ function childSlot(parentScope, slotKey, domParent, value, anchor, ownEnd, ownsH
|
|
|
9721
9929
|
if (preparedList !== null) {
|
|
9722
9930
|
if (state.forSlot === null) {
|
|
9723
9931
|
if (hydration === null && !upgradeArmed) clearChildContent(state);
|
|
9932
|
+
if (state.end !== null && state.end.parentNode === null) {
|
|
9933
|
+
state.end = null;
|
|
9934
|
+
state.start = null;
|
|
9935
|
+
}
|
|
9724
9936
|
if (state.end === null) {
|
|
9725
9937
|
state.end = document.createComment("");
|
|
9726
9938
|
domParent.insertBefore(state.end, null);
|
|
@@ -10563,8 +10775,10 @@ function tryBlock(parentScope, slotKey, domParent, tryBody, catchBody, pendingBo
|
|
|
10563
10775
|
const journalCheckpoint = armTransitionJournal(s);
|
|
10564
10776
|
try {
|
|
10565
10777
|
renderBlock(s.tryBlock);
|
|
10566
|
-
|
|
10567
|
-
|
|
10778
|
+
if (!heldSyncCellsIntact(s)) {
|
|
10779
|
+
releaseHeldTransition(s);
|
|
10780
|
+
s.pendingThenable = null;
|
|
10781
|
+
}
|
|
10568
10782
|
} catch (err) {
|
|
10569
10783
|
if (isHostContextRequest(err)) throw err;
|
|
10570
10784
|
if (isSuspenseException(err)) {
|
|
@@ -10790,6 +11004,7 @@ function showTryBlock(state) {
|
|
|
10790
11004
|
}
|
|
10791
11005
|
}
|
|
10792
11006
|
function releaseHeldTransition(state) {
|
|
11007
|
+
discardHeldSyncTransition(state);
|
|
10793
11008
|
if (state.transitionHeld) {
|
|
10794
11009
|
state.transitionHeld = false;
|
|
10795
11010
|
tickTransitionCount(-1);
|
|
@@ -10804,6 +11019,9 @@ function handleSuspense(state, thenable, sourceBlock, journalCheckpoint = -1) {
|
|
|
10804
11019
|
const isTransition = sourceBlock.currentRenderMode === "transition";
|
|
10805
11020
|
if ((isTransition || state.transitionHeld) && state.hasResolved && state.branch === 1 && state.hiddenDom === null) {
|
|
10806
11021
|
rollbackTransitionJournal(journalCheckpoint);
|
|
11022
|
+
if (ACTIVE_TRANSITION_ATTEMPT !== null) {
|
|
11023
|
+
(ACTIVE_TRANSITION_ATTEMPT.heldSlots ??= /* @__PURE__ */ new Set()).add(state);
|
|
11024
|
+
}
|
|
10807
11025
|
if (!state.transitionHeld) {
|
|
10808
11026
|
state.transitionHeld = true;
|
|
10809
11027
|
tickTransitionCount(1);
|
|
@@ -10920,6 +11138,9 @@ function refreshPendingBody(state) {
|
|
|
10920
11138
|
}
|
|
10921
11139
|
function swapToPendingFallback(state) {
|
|
10922
11140
|
if (!state.pendingBody || state.branch !== 1 || !state.tryBlock) return;
|
|
11141
|
+
if (HELD_SYNC_TRANSITION !== null && HELD_SYNC_TRANSITION.holders.has(state)) {
|
|
11142
|
+
promoteHeldSyncTransition();
|
|
11143
|
+
}
|
|
10923
11144
|
hideTryContentAndMountPending(state);
|
|
10924
11145
|
}
|
|
10925
11146
|
function commitResume(state) {
|
|
@@ -11275,6 +11496,20 @@ function rebaseOffscreenCaptureSeq(capture) {
|
|
|
11275
11496
|
}
|
|
11276
11497
|
function flushStagedReveals() {
|
|
11277
11498
|
if (flushingStagedReveals) return;
|
|
11499
|
+
if (HELD_SYNC_TRANSITION !== null) {
|
|
11500
|
+
let allVisible = true;
|
|
11501
|
+
for (const holder of HELD_SYNC_TRANSITION.holders) {
|
|
11502
|
+
if (holder.hiddenDom !== null) {
|
|
11503
|
+
allVisible = false;
|
|
11504
|
+
break;
|
|
11505
|
+
}
|
|
11506
|
+
}
|
|
11507
|
+
if (allVisible && promoteHeldSyncTransition()) {
|
|
11508
|
+
STAGED_REVEALS.clear();
|
|
11509
|
+
flush();
|
|
11510
|
+
return;
|
|
11511
|
+
}
|
|
11512
|
+
}
|
|
11278
11513
|
flushingStagedReveals = true;
|
|
11279
11514
|
try {
|
|
11280
11515
|
const run = () => {
|
|
@@ -11970,10 +12205,31 @@ function renderBranchSlot(parentScope, slotKey, state, domParent, next, body, ma
|
|
|
11970
12205
|
let bStart;
|
|
11971
12206
|
let bEnd;
|
|
11972
12207
|
let borrowed = false;
|
|
12208
|
+
let rebuild = false;
|
|
12209
|
+
let inner = null;
|
|
12210
|
+
let innerEnd = null;
|
|
11973
12211
|
if (hydration !== null && hydration.isOpen(state.start.nextSibling)) {
|
|
11974
|
-
|
|
11975
|
-
|
|
11976
|
-
|
|
12212
|
+
inner = state.start.nextSibling;
|
|
12213
|
+
innerEnd = hydration.close(inner);
|
|
12214
|
+
if (innerEnd !== state.end && innerEnd.nextSibling !== state.end) {
|
|
12215
|
+
if (process.env.NODE_ENV !== "production") {
|
|
12216
|
+
const mmLoc = siteLoc(parentScope, slotKey);
|
|
12217
|
+
if (mmLoc)
|
|
12218
|
+
hydration.warnStructural(
|
|
12219
|
+
mmLoc,
|
|
12220
|
+
"a single branch range",
|
|
12221
|
+
hydration.describe(innerEnd.nextSibling)
|
|
12222
|
+
);
|
|
12223
|
+
}
|
|
12224
|
+
removeRange(state.start.nextSibling, state.end);
|
|
12225
|
+
inner = null;
|
|
12226
|
+
rebuild = true;
|
|
12227
|
+
}
|
|
12228
|
+
}
|
|
12229
|
+
if (inner !== null) {
|
|
12230
|
+
bStart = inner;
|
|
12231
|
+
bEnd = innerEnd;
|
|
12232
|
+
hydration.node = inner.nextSibling;
|
|
11977
12233
|
} else {
|
|
11978
12234
|
bStart = state.start;
|
|
11979
12235
|
bEnd = state.end;
|
|
@@ -11992,7 +12248,12 @@ function renderBranchSlot(parentScope, slotKey, state, domParent, next, body, ma
|
|
|
11992
12248
|
);
|
|
11993
12249
|
if (borrowed) b.exclusiveMarkers = true;
|
|
11994
12250
|
state.block = b;
|
|
11995
|
-
|
|
12251
|
+
if (rebuild) {
|
|
12252
|
+
hydration.suspend(() => renderBlock(b));
|
|
12253
|
+
hydration.node = state.end.nextSibling;
|
|
12254
|
+
} else {
|
|
12255
|
+
renderBlock(b);
|
|
12256
|
+
}
|
|
11996
12257
|
} else if (hydration !== null && state.start.nextSibling !== state.end) {
|
|
11997
12258
|
if (process.env.NODE_ENV !== "production") {
|
|
11998
12259
|
const mmLoc = siteLoc(parentScope, slotKey);
|