octane 0.1.41 → 0.1.42
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/README.md +3 -0
- package/dist/cjs/runtime.cjs +42 -12
- package/dist/cjs/version.cjs +1 -1
- package/dist/compiler/compile.js +145 -19
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.js +42 -12
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,6 +36,9 @@ For the full story, see the
|
|
|
36
36
|
|
|
37
37
|
## Browser compatibility
|
|
38
38
|
|
|
39
|
+
See the [browser support guide](https://octanejs.dev/docs/browser-support) for
|
|
40
|
+
recommended targets, required browser APIs, and optional fallbacks.
|
|
41
|
+
|
|
39
42
|
Configure your application's build target for the browser engines you support.
|
|
40
43
|
The Rsbuild integration's `modules` target includes Chromium 87 and Samsung
|
|
41
44
|
Internet 14; Samsung Internet can also be selected directly with targets such as
|
package/dist/cjs/runtime.cjs
CHANGED
|
@@ -475,18 +475,19 @@ function stagedTransitionValue(slot) {
|
|
|
475
475
|
function stageTransitionValue(slot, block, operation, value, forceRender = false) {
|
|
476
476
|
const batch = transitionActionBatchForUpdate();
|
|
477
477
|
if (batch === null) return false;
|
|
478
|
+
const replay = typeof operation === "function" ? operation : () => operation;
|
|
478
479
|
const current = batch.updates.get(slot);
|
|
479
480
|
if (current === void 0) {
|
|
480
481
|
batch.updates.set(slot, {
|
|
481
482
|
slot,
|
|
482
483
|
block,
|
|
483
|
-
operations: [
|
|
484
|
+
operations: [replay],
|
|
484
485
|
baseValue: slot.value,
|
|
485
486
|
value,
|
|
486
487
|
forceRender
|
|
487
488
|
});
|
|
488
489
|
} else {
|
|
489
|
-
current.operations.push(
|
|
490
|
+
current.operations.push(replay);
|
|
490
491
|
current.value = value;
|
|
491
492
|
current.forceRender ||= forceRender;
|
|
492
493
|
}
|
|
@@ -1457,12 +1458,21 @@ function flush() {
|
|
|
1457
1458
|
}
|
|
1458
1459
|
return;
|
|
1459
1460
|
}
|
|
1461
|
+
if (!hasPendingWork() && refDetachQueue.length === 0 && refAttachQueue.length === 0 && activeFragments.size === 0 && FLUSHED_TRANSITION_UPDATES.length === 0 && VIEW_TRANSITION_DRIVER === null) {
|
|
1462
|
+
if (typeof __OCTANE_PROFILE_ENABLED__ !== "undefined" && __OCTANE_PROFILE_ENABLED__)
|
|
1463
|
+
(0, import_devtools_hook.__devtoolsNotifyFlush)();
|
|
1464
|
+
return;
|
|
1465
|
+
}
|
|
1460
1466
|
if (VIEW_TRANSITION_DRIVER?.routeFlush() === true) return;
|
|
1461
1467
|
flushWork();
|
|
1462
1468
|
}
|
|
1463
1469
|
function activeElementForDocument(doc) {
|
|
1464
1470
|
try {
|
|
1465
1471
|
let focused = doc.activeElement;
|
|
1472
|
+
if (focused === doc.body) {
|
|
1473
|
+
focused = focused?.shadowRoot?.activeElement ?? null;
|
|
1474
|
+
if (focused === null) return null;
|
|
1475
|
+
}
|
|
1466
1476
|
while (focused !== null) {
|
|
1467
1477
|
if (focused.localName === "iframe") {
|
|
1468
1478
|
let nested;
|
|
@@ -3118,10 +3128,9 @@ function useState(initial, slot) {
|
|
|
3118
3128
|
value: initVal,
|
|
3119
3129
|
setter: (next) => {
|
|
3120
3130
|
const previous = stagedTransitionValue(s);
|
|
3121
|
-
const
|
|
3122
|
-
const computed = operation(previous);
|
|
3131
|
+
const computed = typeof next === "function" ? next(previous) : next;
|
|
3123
3132
|
if (Object.is(computed, previous)) return;
|
|
3124
|
-
if (stageTransitionValue(s, block,
|
|
3133
|
+
if (stageTransitionValue(s, block, next, computed)) {
|
|
3125
3134
|
if (typeof __OCTANE_PROFILE_ENABLED__ !== "undefined" && __OCTANE_PROFILE_ENABLED__) {
|
|
3126
3135
|
const update = s.pendingActionBatch?.updates.get(s);
|
|
3127
3136
|
if (update !== void 0) {
|
|
@@ -4638,6 +4647,10 @@ function activateHydrateBoundary(state) {
|
|
|
4638
4647
|
renderBlock(block);
|
|
4639
4648
|
drainHydrationRenderPhaseUpdates(block);
|
|
4640
4649
|
if (state.hydrated) {
|
|
4650
|
+
const adoptedSlot = block.slots[0];
|
|
4651
|
+
if (adoptedSlot?.__kind === "trySlotSlot") {
|
|
4652
|
+
hydration.claimRootRemainder(adoptedSlot.end.nextSibling);
|
|
4653
|
+
}
|
|
4641
4654
|
hydration.flushClassWrites();
|
|
4642
4655
|
hydration.flushTextWarnings();
|
|
4643
4656
|
hydration.finishRoot();
|
|
@@ -14982,7 +14995,7 @@ function forBlock(parentScope, slotKey, domParent, items, getKey, itemBody, flag
|
|
|
14982
14995
|
hydration.node = state.end.nextSibling;
|
|
14983
14996
|
}
|
|
14984
14997
|
}
|
|
14985
|
-
function keyedForBlock(parentScope, slotKey, domParent, items, getKey, itemBody, flags, deps, emptyBody, anchor, ownEnd) {
|
|
14998
|
+
function keyedForBlock(parentScope, slotKey, domParent, items, getKey, itemBody, flags, deps, emptyBody, anchor, ownEnd, selectionBody) {
|
|
14986
14999
|
const state = parentScope.slots[slotKey];
|
|
14987
15000
|
if (TRANSITION_JOURNAL !== null) {
|
|
14988
15001
|
if (state !== void 0) {
|
|
@@ -14990,7 +15003,15 @@ function keyedForBlock(parentScope, slotKey, domParent, items, getKey, itemBody,
|
|
|
14990
15003
|
state.selectionItems = void 0;
|
|
14991
15004
|
}
|
|
14992
15005
|
flags &= ~4;
|
|
14993
|
-
} else if (state !== void 0 && activeHydration() === null && state.cachedDeps !== null && tryUpdateKeyedSelection(
|
|
15006
|
+
} else if (state !== void 0 && activeHydration() === null && state.cachedDeps !== null && tryUpdateKeyedSelection(
|
|
15007
|
+
state,
|
|
15008
|
+
items,
|
|
15009
|
+
itemBody,
|
|
15010
|
+
state.cachedDeps,
|
|
15011
|
+
deps,
|
|
15012
|
+
flags >>> 6,
|
|
15013
|
+
selectionBody
|
|
15014
|
+
)) {
|
|
14994
15015
|
return;
|
|
14995
15016
|
}
|
|
14996
15017
|
forBlock(
|
|
@@ -15114,7 +15135,7 @@ function fastForBlock(parentScope, slotKey, domParent, items, getKey, itemBody,
|
|
|
15114
15135
|
}
|
|
15115
15136
|
mountFastHostItems(parentScope, state, parent, items, getKey, itemBody, flags, deps, false);
|
|
15116
15137
|
}
|
|
15117
|
-
function fastKeyedForBlock(parentScope, slotKey, domParent, items, getKey, itemBody, flags, deps, emptyBody, anchor, ownEnd) {
|
|
15138
|
+
function fastKeyedForBlock(parentScope, slotKey, domParent, items, getKey, itemBody, flags, deps, emptyBody, anchor, ownEnd, selectionBody) {
|
|
15118
15139
|
const state = parentScope.slots[slotKey];
|
|
15119
15140
|
const parent = fastHostListParent(state, items, flags);
|
|
15120
15141
|
if (parent === null) {
|
|
@@ -15129,7 +15150,8 @@ function fastKeyedForBlock(parentScope, slotKey, domParent, items, getKey, itemB
|
|
|
15129
15150
|
deps,
|
|
15130
15151
|
emptyBody,
|
|
15131
15152
|
anchor,
|
|
15132
|
-
ownEnd
|
|
15153
|
+
ownEnd,
|
|
15154
|
+
selectionBody
|
|
15133
15155
|
);
|
|
15134
15156
|
return;
|
|
15135
15157
|
}
|
|
@@ -15201,7 +15223,7 @@ function depsEqual(a, b) {
|
|
|
15201
15223
|
}
|
|
15202
15224
|
return true;
|
|
15203
15225
|
}
|
|
15204
|
-
function tryUpdateKeyedSelection(state, items, itemBody, previousDeps, deps, selectionIndex) {
|
|
15226
|
+
function tryUpdateKeyedSelection(state, items, itemBody, previousDeps, deps, selectionIndex, selectionBody) {
|
|
15205
15227
|
if (state.selectionItems !== items || state.size !== items.length || state.items.size !== state.size || previousDeps.length !== deps.length || selectionIndex >= deps.length) {
|
|
15206
15228
|
return false;
|
|
15207
15229
|
}
|
|
@@ -15224,12 +15246,20 @@ function tryUpdateKeyedSelection(state, items, itemBody, previousDeps, deps, sel
|
|
|
15224
15246
|
if (first !== void 0) {
|
|
15225
15247
|
first.body = itemBody;
|
|
15226
15248
|
first.extra = deps;
|
|
15227
|
-
|
|
15249
|
+
if (selectionBody !== void 0 && first._slots === null) {
|
|
15250
|
+
selectionBody(first.props, first, deps);
|
|
15251
|
+
} else {
|
|
15252
|
+
itemBody(first.props, first, deps);
|
|
15253
|
+
}
|
|
15228
15254
|
}
|
|
15229
15255
|
if (second !== void 0) {
|
|
15230
15256
|
second.body = itemBody;
|
|
15231
15257
|
second.extra = deps;
|
|
15232
|
-
|
|
15258
|
+
if (selectionBody !== void 0 && second._slots === null) {
|
|
15259
|
+
selectionBody(second.props, second, deps);
|
|
15260
|
+
} else {
|
|
15261
|
+
itemBody(second.props, second, deps);
|
|
15262
|
+
}
|
|
15233
15263
|
}
|
|
15234
15264
|
return true;
|
|
15235
15265
|
}
|
package/dist/cjs/version.cjs
CHANGED
|
@@ -21,7 +21,7 @@ __export(version_exports, {
|
|
|
21
21
|
version: () => version
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(version_exports);
|
|
24
|
-
const version = "0.1.
|
|
24
|
+
const version = "0.1.42";
|
|
25
25
|
// Annotate the CommonJS export names for ESM import in node:
|
|
26
26
|
0 && (module.exports = {
|
|
27
27
|
version
|
package/dist/compiler/compile.js
CHANGED
|
@@ -8188,6 +8188,7 @@ function compileInternal(
|
|
|
8188
8188
|
!hmrEnabled &&
|
|
8189
8189
|
!devEnabled &&
|
|
8190
8190
|
!profileEnabled &&
|
|
8191
|
+
options?.__universal == null &&
|
|
8191
8192
|
!((source.includes('eval') || source.includes('\\u')) && hasInlineMemoDirectEval(ast));
|
|
8192
8193
|
// Same production-only gate as the tiers above, and for the same reason: a
|
|
8193
8194
|
// lifted callback has left the component, which dev tooling, HMR boundaries,
|
|
@@ -13480,7 +13481,16 @@ function compileFunctionBody(node, ctx, name, parentNs = 'html', cssHash = null,
|
|
|
13480
13481
|
cssHash,
|
|
13481
13482
|
);
|
|
13482
13483
|
} else {
|
|
13483
|
-
plan = planJsx(
|
|
13484
|
+
plan = planJsx(
|
|
13485
|
+
jsxNodes,
|
|
13486
|
+
ctx,
|
|
13487
|
+
name,
|
|
13488
|
+
inlinedSubs,
|
|
13489
|
+
parentNs,
|
|
13490
|
+
cssHash,
|
|
13491
|
+
mountCallbackSinks,
|
|
13492
|
+
options?.keyedSelection ?? null,
|
|
13493
|
+
);
|
|
13484
13494
|
}
|
|
13485
13495
|
ctx.currentInvariantLocals = prevInvariantLocals;
|
|
13486
13496
|
ctx.currentEventInvariantLocals = prevEventInvariantLocals;
|
|
@@ -17421,6 +17431,11 @@ function extractFragment(node, ctx, holeProps, parentNs = 'html') {
|
|
|
17421
17431
|
const bodyHole = `h${holeProps.length}`;
|
|
17422
17432
|
holeProps.push(objectProp(bodyHole, b.id(rec.bodyHelper)));
|
|
17423
17433
|
rec.bodyHelper = `props.${bodyHole}`;
|
|
17434
|
+
if (rec.selectionHelper != null) {
|
|
17435
|
+
const selectionHole = `h${holeProps.length}`;
|
|
17436
|
+
holeProps.push(objectProp(selectionHole, b.id(rec.selectionHelper)));
|
|
17437
|
+
rec.selectionHelper = `props.${selectionHole}`;
|
|
17438
|
+
}
|
|
17424
17439
|
}
|
|
17425
17440
|
if (mapCall) {
|
|
17426
17441
|
const methodHole = `h${holeProps.length}`;
|
|
@@ -20439,6 +20454,7 @@ function planJsx(
|
|
|
20439
20454
|
parentNs = 'html',
|
|
20440
20455
|
cssHash = null,
|
|
20441
20456
|
mountCallbackSinks = null,
|
|
20457
|
+
keyedSelection = null,
|
|
20442
20458
|
) {
|
|
20443
20459
|
// DEV ONLY: per-element source-location map for THIS body (path-key → [line, col]),
|
|
20444
20460
|
// populated at the top of emitElementHtml and read in the binding mount loop to emit
|
|
@@ -20712,6 +20728,15 @@ function planJsx(
|
|
|
20712
20728
|
resolvedFrag = tplNs !== 'opaque';
|
|
20713
20729
|
}
|
|
20714
20730
|
}
|
|
20731
|
+
// Binding planning precedes the final template namespace. An inherited
|
|
20732
|
+
// opaque namespace can now use the same concrete namespace as clone(),
|
|
20733
|
+
// including HTML's faster className property. Preserve explicit foreign
|
|
20734
|
+
// content and leave genuinely opaque/mixed templates destination-aware.
|
|
20735
|
+
if (tplNs !== 'opaque') {
|
|
20736
|
+
for (const binding of elementBindings) {
|
|
20737
|
+
if (binding.ns === 'opaque') binding.ns = tplNs;
|
|
20738
|
+
}
|
|
20739
|
+
}
|
|
20715
20740
|
const flag = nsFlag(tplNs);
|
|
20716
20741
|
const fragArg = !single && (flag !== 0 || resolvedFrag) ? 1 : 0;
|
|
20717
20742
|
let template = rootTemplate;
|
|
@@ -21234,6 +21259,24 @@ function planJsx(
|
|
|
21234
21259
|
if (b.deferred) everyRenderLines.push(updateEmit);
|
|
21235
21260
|
else updateLines.push(updateEmit);
|
|
21236
21261
|
}
|
|
21262
|
+
if (keyedSelection !== null && single && !noTemplate) {
|
|
21263
|
+
// Reuse the ordinary root-class write and its exact bag fields. Updating
|
|
21264
|
+
// only the DOM would leave the normal row diff's previous value stale.
|
|
21265
|
+
const classes = elementBindings.filter(
|
|
21266
|
+
(binding) => binding.kind === 'class' && binding.path.length === 0,
|
|
21267
|
+
);
|
|
21268
|
+
if (
|
|
21269
|
+
classes.length === 1 &&
|
|
21270
|
+
!classes[0].fresh &&
|
|
21271
|
+
!classes[0].mountOnly &&
|
|
21272
|
+
collectFreeIdentifiers(classes[0].expr, [
|
|
21273
|
+
keyedSelection.itemName,
|
|
21274
|
+
keyedSelection.selectedName,
|
|
21275
|
+
]).size === 0
|
|
21276
|
+
) {
|
|
21277
|
+
keyedSelection.update = emitBindingUpdate(classes[0], bag);
|
|
21278
|
+
}
|
|
21279
|
+
}
|
|
21237
21280
|
|
|
21238
21281
|
// After (forBlock + ifBlock calls run on every render — they reconcile).
|
|
21239
21282
|
//
|
|
@@ -21342,6 +21385,7 @@ function planJsx(
|
|
|
21342
21385
|
rtAlias(forHelper),
|
|
21343
21386
|
fc.keyHelper,
|
|
21344
21387
|
fc.bodyHelper,
|
|
21388
|
+
fc.selectionHelper,
|
|
21345
21389
|
fc.emptyHelper,
|
|
21346
21390
|
]);
|
|
21347
21391
|
registerClauseOrigin(ctx, fc.emptyKeyword, [fc.emptyHelper]);
|
|
@@ -21366,7 +21410,8 @@ function planJsx(
|
|
|
21366
21410
|
(fc.requiresScope ? 32 : 0) |
|
|
21367
21411
|
(fc.keyedSelectionIndex >= 0 ? fc.keyedSelectionIndex << 6 : 0);
|
|
21368
21412
|
// Arg layout: forBlock(__s, slot, host, items, keyFn, body, flags?, deps?,
|
|
21369
|
-
// emptyBody?, anchor?, ownEnd?).
|
|
21413
|
+
// emptyBody?, anchor?, ownEnd?, selectionBody?). The final argument is
|
|
21414
|
+
// emitted only for a certified keyed-selection call.
|
|
21370
21415
|
// Optional args backfill positionally: `flags`/`deps` placeholders
|
|
21371
21416
|
// (`0`/`undefined`) when only `emptyHelper` (`null` when no `@empty`
|
|
21372
21417
|
// branch) or the anchor is present, and a `null` empty-body placeholder
|
|
@@ -21418,6 +21463,12 @@ function planJsx(
|
|
|
21418
21463
|
// list's trailing boundary. Let forBlock reuse it as its end marker instead
|
|
21419
21464
|
// of retaining it beside a newly-created `/for` comment.
|
|
21420
21465
|
if (fc.anchorVar) tailArgs.push(b.literal(true));
|
|
21466
|
+
if (fc.selectionHelper != null) {
|
|
21467
|
+
// tailArgs starts at argument 5; preserve the optional positions through
|
|
21468
|
+
// ownEnd before supplying the selection updater as argument 12.
|
|
21469
|
+
while (tailArgs.length < 7) tailArgs.push(undefinedNode());
|
|
21470
|
+
tailArgs.push(helperRefNode(fc.selectionHelper));
|
|
21471
|
+
}
|
|
21421
21472
|
if (isMappedList) {
|
|
21422
21473
|
const nativeName = allocCompilerName(ctx, '__mapNative');
|
|
21423
21474
|
if (fc.autoMemoDeps !== null) {
|
|
@@ -24999,6 +25050,7 @@ function hoistBodyHelper(
|
|
|
24999
25050
|
cssHash,
|
|
25000
25051
|
envNames,
|
|
25001
25052
|
idOrigin = null,
|
|
25053
|
+
keyedSelection = null,
|
|
25002
25054
|
) {
|
|
25003
25055
|
const helperName = `${prefix}$${ctx.nextHelperId++}`;
|
|
25004
25056
|
const ownEnvNames = envNames === null ? null : helperCaptures(ctx, stmts, params);
|
|
@@ -25066,7 +25118,14 @@ function hoistBodyHelper(
|
|
|
25066
25118
|
);
|
|
25067
25119
|
let helperFn;
|
|
25068
25120
|
try {
|
|
25069
|
-
helperFn = compileFunctionBody(
|
|
25121
|
+
helperFn = compileFunctionBody(
|
|
25122
|
+
fake,
|
|
25123
|
+
ctx,
|
|
25124
|
+
helperName,
|
|
25125
|
+
parentNs,
|
|
25126
|
+
cssHash,
|
|
25127
|
+
keyedSelection === null ? null : { keyedSelection },
|
|
25128
|
+
);
|
|
25070
25129
|
} finally {
|
|
25071
25130
|
ctx.currentComponentLocals = prevLocals;
|
|
25072
25131
|
ctx.currentInvariantLocals = prevInvariantLocals;
|
|
@@ -25075,6 +25134,35 @@ function hoistBodyHelper(
|
|
|
25075
25134
|
// Module-scope placement: the compiled helper joins the module AST as a
|
|
25076
25135
|
// hoisted statement node (M2 AST emit).
|
|
25077
25136
|
ctx.hoistedHelpers.push(helperFn);
|
|
25137
|
+
if (keyedSelection?.update != null) {
|
|
25138
|
+
const selectionName = allocCompilerName(ctx, `__select$${ctx.nextHelperId++}`);
|
|
25139
|
+
const origin = keyedSelection.update;
|
|
25140
|
+
const selectionBody = [
|
|
25141
|
+
inheritOriginLoc(
|
|
25142
|
+
b.const(
|
|
25143
|
+
keyedSelection.selectedName,
|
|
25144
|
+
b.member(b.id('__extra'), b.literal(keyedSelection.selectedIndex), true),
|
|
25145
|
+
),
|
|
25146
|
+
origin,
|
|
25147
|
+
),
|
|
25148
|
+
inheritOriginLoc(
|
|
25149
|
+
b.const('_b', b.member(b.member(b.id('__s'), 'slots'), b.literal(0), true)),
|
|
25150
|
+
origin,
|
|
25151
|
+
),
|
|
25152
|
+
keyedSelection.update,
|
|
25153
|
+
];
|
|
25154
|
+
ctx.hoistedHelpers.push(
|
|
25155
|
+
inheritOriginLoc(
|
|
25156
|
+
b.function_declaration(
|
|
25157
|
+
b.id(selectionName, idOrigin ?? fakeOrigin ?? undefined),
|
|
25158
|
+
[...params, b.id('__s'), b.id('__extra')],
|
|
25159
|
+
b.block(selectionBody),
|
|
25160
|
+
),
|
|
25161
|
+
fakeOrigin,
|
|
25162
|
+
),
|
|
25163
|
+
);
|
|
25164
|
+
keyedSelection.helper = selectionName;
|
|
25165
|
+
}
|
|
25078
25166
|
return helperName;
|
|
25079
25167
|
}
|
|
25080
25168
|
|
|
@@ -25984,14 +26072,17 @@ function makeSwitchCall(node, ctx, inlinedSubs, parentNs = 'html', cssHash = nul
|
|
|
25984
26072
|
* snapshot remain unchanged.
|
|
25985
26073
|
*
|
|
25986
26074
|
* This recognizes `selected === item.id` (or its reverse) under `key item.id`,
|
|
25987
|
-
*
|
|
26075
|
+
* optionally through one preceding `const id = item.id`, and the same proof
|
|
26076
|
+
* for any other explicit, noncomputed item property. The authored declaration
|
|
26077
|
+
* stays in the full item body, preserving its read position and event captures.
|
|
25988
26078
|
* Dynamic ternary arms, extra references to
|
|
25989
26079
|
* `selected` anywhere in the row (including deferred event callbacks), spreads,
|
|
25990
26080
|
* and anything other than one direct host root all fail closed.
|
|
25991
26081
|
*/
|
|
25992
26082
|
function keyedSelectionDepIndex(itemName, keyBody, subStmts, runtimeDepNames, ctx) {
|
|
25993
|
-
if (subStmts.length !== 1
|
|
25994
|
-
const root = subStmts[
|
|
26083
|
+
if (subStmts.length !== 1 && subStmts.length !== 2) return -1;
|
|
26084
|
+
const root = subStmts[subStmts.length - 1];
|
|
26085
|
+
if (!isPlainHostRoot(root)) return -1;
|
|
25995
26086
|
const attrs = root.attributes || root.openingElement?.attributes || [];
|
|
25996
26087
|
if (attrs.some((attr) => attr.type !== 'Attribute' && attr.type !== 'JSXAttribute')) {
|
|
25997
26088
|
return -1;
|
|
@@ -26043,12 +26134,33 @@ function keyedSelectionDepIndex(itemName, keyBody, subStmts, runtimeDepNames, ct
|
|
|
26043
26134
|
member.property.name === keyProperty
|
|
26044
26135
|
);
|
|
26045
26136
|
};
|
|
26137
|
+
let keyAlias = null;
|
|
26138
|
+
if (subStmts.length === 2) {
|
|
26139
|
+
const declaration = subStmts[0];
|
|
26140
|
+
const binding = declaration.declarations?.[0];
|
|
26141
|
+
if (
|
|
26142
|
+
declaration.type !== 'VariableDeclaration' ||
|
|
26143
|
+
declaration.kind !== 'const' ||
|
|
26144
|
+
declaration.declare === true ||
|
|
26145
|
+
declaration.declarations?.length !== 1 ||
|
|
26146
|
+
binding?.id?.type !== 'Identifier' ||
|
|
26147
|
+
binding.id.name === itemName ||
|
|
26148
|
+
!isItemKey(binding.init)
|
|
26149
|
+
) {
|
|
26150
|
+
return -1;
|
|
26151
|
+
}
|
|
26152
|
+
keyAlias = binding.id.name;
|
|
26153
|
+
}
|
|
26154
|
+
const isComparedKey = (expression) =>
|
|
26155
|
+
isItemKey(expression) ||
|
|
26156
|
+
(keyAlias !== null && expression?.type === 'Identifier' && expression.name === keyAlias);
|
|
26046
26157
|
const left = unwrapTsExpr(test.left);
|
|
26047
26158
|
const right = unwrapTsExpr(test.right);
|
|
26048
|
-
const selected =
|
|
26159
|
+
const selected = isComparedKey(left) ? right : isComparedKey(right) ? left : null;
|
|
26049
26160
|
if (
|
|
26050
26161
|
selected?.type !== 'Identifier' ||
|
|
26051
26162
|
selected.name === itemName ||
|
|
26163
|
+
selected.name === keyAlias ||
|
|
26052
26164
|
!ctx.currentComponentLocals?.has(selected.name)
|
|
26053
26165
|
) {
|
|
26054
26166
|
return -1;
|
|
@@ -26493,18 +26605,6 @@ function makeForCall(node, ctx, inlinedSubs, parentNs = 'html', cssHash = null)
|
|
|
26493
26605
|
node.emptyKeyword ?? null,
|
|
26494
26606
|
);
|
|
26495
26607
|
}
|
|
26496
|
-
const itemHelperName = hoistBodyHelper(
|
|
26497
|
-
ctx,
|
|
26498
|
-
inlinedSubs,
|
|
26499
|
-
'__item',
|
|
26500
|
-
itemAllStmts,
|
|
26501
|
-
itemParams,
|
|
26502
|
-
parentNs,
|
|
26503
|
-
cssHash,
|
|
26504
|
-
envNames,
|
|
26505
|
-
directiveKeywordOrigin(ctx, node),
|
|
26506
|
-
);
|
|
26507
|
-
|
|
26508
26608
|
// Single-root detection: when the body emits exactly one Element root and
|
|
26509
26609
|
// no other JSX siblings (no Fragment, no Component, no top-level if/for/try),
|
|
26510
26610
|
// the runtime can skip per-item Comment markers and use the row element
|
|
@@ -26576,6 +26676,31 @@ function makeForCall(node, ctx, inlinedSubs, parentNs = 'html', cssHash = null)
|
|
|
26576
26676
|
!containsRenderCall(subStmts) &&
|
|
26577
26677
|
!containsAutoMemoUnsafeStructure(subStmts) &&
|
|
26578
26678
|
isHostMountSafeTree(subStmts[0]);
|
|
26679
|
+
// Class-only updates need the stricter host-lifecycle proof as well as the
|
|
26680
|
+
// existing equality proof. The item planner fills this compiler-owned result
|
|
26681
|
+
// only when the root class survives as one ordinary cached binding.
|
|
26682
|
+
const keyedSelection =
|
|
26683
|
+
hostMountSafe && keyedSelectionIndex >= 0 && envNames !== null
|
|
26684
|
+
? {
|
|
26685
|
+
itemName,
|
|
26686
|
+
selectedName: runtimeDepNames[keyedSelectionIndex],
|
|
26687
|
+
selectedIndex: keyedSelectionIndex,
|
|
26688
|
+
update: null,
|
|
26689
|
+
helper: null,
|
|
26690
|
+
}
|
|
26691
|
+
: null;
|
|
26692
|
+
const itemHelperName = hoistBodyHelper(
|
|
26693
|
+
ctx,
|
|
26694
|
+
inlinedSubs,
|
|
26695
|
+
'__item',
|
|
26696
|
+
itemAllStmts,
|
|
26697
|
+
itemParams,
|
|
26698
|
+
parentNs,
|
|
26699
|
+
cssHash,
|
|
26700
|
+
envNames,
|
|
26701
|
+
directiveKeywordOrigin(ctx, node),
|
|
26702
|
+
keyedSelection,
|
|
26703
|
+
);
|
|
26579
26704
|
|
|
26580
26705
|
const mapCall = node.nativeArrayMap || null;
|
|
26581
26706
|
return {
|
|
@@ -26606,6 +26731,7 @@ function makeForCall(node, ctx, inlinedSubs, parentNs = 'html', cssHash = null)
|
|
|
26606
26731
|
keyHelper,
|
|
26607
26732
|
inlineKey: inlineKey ? keyFn : null,
|
|
26608
26733
|
bodyHelper: itemHelperName,
|
|
26734
|
+
selectionHelper: keyedSelection?.helper ?? null,
|
|
26609
26735
|
hasPerItemEventClosure,
|
|
26610
26736
|
pure,
|
|
26611
26737
|
singleRoot,
|
package/dist/runtime.d.ts
CHANGED
|
@@ -1480,11 +1480,11 @@ export declare function forBlock<T>(parentScope: Scope, slotKey: number, domPare
|
|
|
1480
1480
|
* forBlock lets applications without a proven selection tree-shake its cost.
|
|
1481
1481
|
* This entry point identifies the proof; bits 6+ hold its dependency index.
|
|
1482
1482
|
*/
|
|
1483
|
-
export declare function keyedForBlock<T>(parentScope: Scope, slotKey: number, domParent: Node, items: ArrayLike<T>, getKey: (item: T, index: number) => any, itemBody: (item: T, scope: Scope) => void, flags: number, deps: any[], emptyBody?: ComponentBody | null, anchor?: Node | null, ownEnd?: boolean): void;
|
|
1483
|
+
export declare function keyedForBlock<T>(parentScope: Scope, slotKey: number, domParent: Node, items: ArrayLike<T>, getKey: (item: T, index: number) => any, itemBody: (item: T, scope: Scope) => void, flags: number, deps: any[], emptyBody?: ComponentBody | null, anchor?: Node | null, ownEnd?: boolean, selectionBody?: ComponentBody<T, any[]>): void;
|
|
1484
1484
|
/** Compiler-only direct host-row entry; ordinary list bundles do not retain it. */
|
|
1485
1485
|
export declare function fastForBlock<T>(parentScope: Scope, slotKey: number, domParent: Node, items: ArrayLike<T>, getKey: (item: T, index: number) => any, itemBody: (item: T, scope: Scope) => void, flags?: number, deps?: any[], emptyBody?: ComponentBody | null, anchor?: Node | null, ownEnd?: boolean): void;
|
|
1486
1486
|
/** Direct host-row mounts composed with the independent keyed-selection proof. */
|
|
1487
|
-
export declare function fastKeyedForBlock<T>(parentScope: Scope, slotKey: number, domParent: Node, items: ArrayLike<T>, getKey: (item: T, index: number) => any, itemBody: (item: T, scope: Scope) => void, flags: number, deps: any[], emptyBody?: ComponentBody | null, anchor?: Node | null, ownEnd?: boolean): void;
|
|
1487
|
+
export declare function fastKeyedForBlock<T>(parentScope: Scope, slotKey: number, domParent: Node, items: ArrayLike<T>, getKey: (item: T, index: number) => any, itemBody: (item: T, scope: Scope) => void, flags: number, deps: any[], emptyBody?: ComponentBody | null, anchor?: Node | null, ownEnd?: boolean, selectionBody?: ComponentBody<T, any[]>): void;
|
|
1488
1488
|
/** Direct host-row mounts for compiler-proven, guarded native JSX map rows. */
|
|
1489
1489
|
export declare function fastMapSlot(scopeOrItems: any, slotOrMethod: any, domParent?: Node, items?: any, method?: any, native?: boolean | ((...args: any[]) => any), callback?: (...args: any[]) => any, getKey?: (item: any, index: number) => any, itemBody?: (item: any, scope: Scope) => void, flags?: number, deps?: any[], anchor?: Node | null, ownEnd?: boolean | 1): boolean | void;
|
|
1490
1490
|
export interface Root {
|
package/dist/runtime.js
CHANGED
|
@@ -325,18 +325,19 @@ function stagedTransitionValue(slot) {
|
|
|
325
325
|
function stageTransitionValue(slot, block, operation, value, forceRender = false) {
|
|
326
326
|
const batch = transitionActionBatchForUpdate();
|
|
327
327
|
if (batch === null) return false;
|
|
328
|
+
const replay = typeof operation === "function" ? operation : () => operation;
|
|
328
329
|
const current = batch.updates.get(slot);
|
|
329
330
|
if (current === void 0) {
|
|
330
331
|
batch.updates.set(slot, {
|
|
331
332
|
slot,
|
|
332
333
|
block,
|
|
333
|
-
operations: [
|
|
334
|
+
operations: [replay],
|
|
334
335
|
baseValue: slot.value,
|
|
335
336
|
value,
|
|
336
337
|
forceRender
|
|
337
338
|
});
|
|
338
339
|
} else {
|
|
339
|
-
current.operations.push(
|
|
340
|
+
current.operations.push(replay);
|
|
340
341
|
current.value = value;
|
|
341
342
|
current.forceRender ||= forceRender;
|
|
342
343
|
}
|
|
@@ -1307,12 +1308,21 @@ function flush() {
|
|
|
1307
1308
|
}
|
|
1308
1309
|
return;
|
|
1309
1310
|
}
|
|
1311
|
+
if (!hasPendingWork() && refDetachQueue.length === 0 && refAttachQueue.length === 0 && activeFragments.size === 0 && FLUSHED_TRANSITION_UPDATES.length === 0 && VIEW_TRANSITION_DRIVER === null) {
|
|
1312
|
+
if (typeof __OCTANE_PROFILE_ENABLED__ !== "undefined" && __OCTANE_PROFILE_ENABLED__)
|
|
1313
|
+
__devtoolsNotifyFlush();
|
|
1314
|
+
return;
|
|
1315
|
+
}
|
|
1310
1316
|
if (VIEW_TRANSITION_DRIVER?.routeFlush() === true) return;
|
|
1311
1317
|
flushWork();
|
|
1312
1318
|
}
|
|
1313
1319
|
function activeElementForDocument(doc) {
|
|
1314
1320
|
try {
|
|
1315
1321
|
let focused = doc.activeElement;
|
|
1322
|
+
if (focused === doc.body) {
|
|
1323
|
+
focused = focused?.shadowRoot?.activeElement ?? null;
|
|
1324
|
+
if (focused === null) return null;
|
|
1325
|
+
}
|
|
1316
1326
|
while (focused !== null) {
|
|
1317
1327
|
if (focused.localName === "iframe") {
|
|
1318
1328
|
let nested;
|
|
@@ -2968,10 +2978,9 @@ function useState(initial, slot) {
|
|
|
2968
2978
|
value: initVal,
|
|
2969
2979
|
setter: (next) => {
|
|
2970
2980
|
const previous = stagedTransitionValue(s);
|
|
2971
|
-
const
|
|
2972
|
-
const computed = operation(previous);
|
|
2981
|
+
const computed = typeof next === "function" ? next(previous) : next;
|
|
2973
2982
|
if (Object.is(computed, previous)) return;
|
|
2974
|
-
if (stageTransitionValue(s, block,
|
|
2983
|
+
if (stageTransitionValue(s, block, next, computed)) {
|
|
2975
2984
|
if (typeof __OCTANE_PROFILE_ENABLED__ !== "undefined" && __OCTANE_PROFILE_ENABLED__) {
|
|
2976
2985
|
const update = s.pendingActionBatch?.updates.get(s);
|
|
2977
2986
|
if (update !== void 0) {
|
|
@@ -4488,6 +4497,10 @@ function activateHydrateBoundary(state) {
|
|
|
4488
4497
|
renderBlock(block);
|
|
4489
4498
|
drainHydrationRenderPhaseUpdates(block);
|
|
4490
4499
|
if (state.hydrated) {
|
|
4500
|
+
const adoptedSlot = block.slots[0];
|
|
4501
|
+
if (adoptedSlot?.__kind === "trySlotSlot") {
|
|
4502
|
+
hydration.claimRootRemainder(adoptedSlot.end.nextSibling);
|
|
4503
|
+
}
|
|
4491
4504
|
hydration.flushClassWrites();
|
|
4492
4505
|
hydration.flushTextWarnings();
|
|
4493
4506
|
hydration.finishRoot();
|
|
@@ -14833,7 +14846,7 @@ function forBlock(parentScope, slotKey, domParent, items, getKey, itemBody, flag
|
|
|
14833
14846
|
hydration.node = state.end.nextSibling;
|
|
14834
14847
|
}
|
|
14835
14848
|
}
|
|
14836
|
-
function keyedForBlock(parentScope, slotKey, domParent, items, getKey, itemBody, flags, deps, emptyBody, anchor, ownEnd) {
|
|
14849
|
+
function keyedForBlock(parentScope, slotKey, domParent, items, getKey, itemBody, flags, deps, emptyBody, anchor, ownEnd, selectionBody) {
|
|
14837
14850
|
const state = parentScope.slots[slotKey];
|
|
14838
14851
|
if (TRANSITION_JOURNAL !== null) {
|
|
14839
14852
|
if (state !== void 0) {
|
|
@@ -14841,7 +14854,15 @@ function keyedForBlock(parentScope, slotKey, domParent, items, getKey, itemBody,
|
|
|
14841
14854
|
state.selectionItems = void 0;
|
|
14842
14855
|
}
|
|
14843
14856
|
flags &= ~4;
|
|
14844
|
-
} else if (state !== void 0 && activeHydration() === null && state.cachedDeps !== null && tryUpdateKeyedSelection(
|
|
14857
|
+
} else if (state !== void 0 && activeHydration() === null && state.cachedDeps !== null && tryUpdateKeyedSelection(
|
|
14858
|
+
state,
|
|
14859
|
+
items,
|
|
14860
|
+
itemBody,
|
|
14861
|
+
state.cachedDeps,
|
|
14862
|
+
deps,
|
|
14863
|
+
flags >>> 6,
|
|
14864
|
+
selectionBody
|
|
14865
|
+
)) {
|
|
14845
14866
|
return;
|
|
14846
14867
|
}
|
|
14847
14868
|
forBlock(
|
|
@@ -14965,7 +14986,7 @@ function fastForBlock(parentScope, slotKey, domParent, items, getKey, itemBody,
|
|
|
14965
14986
|
}
|
|
14966
14987
|
mountFastHostItems(parentScope, state, parent, items, getKey, itemBody, flags, deps, false);
|
|
14967
14988
|
}
|
|
14968
|
-
function fastKeyedForBlock(parentScope, slotKey, domParent, items, getKey, itemBody, flags, deps, emptyBody, anchor, ownEnd) {
|
|
14989
|
+
function fastKeyedForBlock(parentScope, slotKey, domParent, items, getKey, itemBody, flags, deps, emptyBody, anchor, ownEnd, selectionBody) {
|
|
14969
14990
|
const state = parentScope.slots[slotKey];
|
|
14970
14991
|
const parent = fastHostListParent(state, items, flags);
|
|
14971
14992
|
if (parent === null) {
|
|
@@ -14980,7 +15001,8 @@ function fastKeyedForBlock(parentScope, slotKey, domParent, items, getKey, itemB
|
|
|
14980
15001
|
deps,
|
|
14981
15002
|
emptyBody,
|
|
14982
15003
|
anchor,
|
|
14983
|
-
ownEnd
|
|
15004
|
+
ownEnd,
|
|
15005
|
+
selectionBody
|
|
14984
15006
|
);
|
|
14985
15007
|
return;
|
|
14986
15008
|
}
|
|
@@ -15052,7 +15074,7 @@ function depsEqual(a, b) {
|
|
|
15052
15074
|
}
|
|
15053
15075
|
return true;
|
|
15054
15076
|
}
|
|
15055
|
-
function tryUpdateKeyedSelection(state, items, itemBody, previousDeps, deps, selectionIndex) {
|
|
15077
|
+
function tryUpdateKeyedSelection(state, items, itemBody, previousDeps, deps, selectionIndex, selectionBody) {
|
|
15056
15078
|
if (state.selectionItems !== items || state.size !== items.length || state.items.size !== state.size || previousDeps.length !== deps.length || selectionIndex >= deps.length) {
|
|
15057
15079
|
return false;
|
|
15058
15080
|
}
|
|
@@ -15075,12 +15097,20 @@ function tryUpdateKeyedSelection(state, items, itemBody, previousDeps, deps, sel
|
|
|
15075
15097
|
if (first !== void 0) {
|
|
15076
15098
|
first.body = itemBody;
|
|
15077
15099
|
first.extra = deps;
|
|
15078
|
-
|
|
15100
|
+
if (selectionBody !== void 0 && first._slots === null) {
|
|
15101
|
+
selectionBody(first.props, first, deps);
|
|
15102
|
+
} else {
|
|
15103
|
+
itemBody(first.props, first, deps);
|
|
15104
|
+
}
|
|
15079
15105
|
}
|
|
15080
15106
|
if (second !== void 0) {
|
|
15081
15107
|
second.body = itemBody;
|
|
15082
15108
|
second.extra = deps;
|
|
15083
|
-
|
|
15109
|
+
if (selectionBody !== void 0 && second._slots === null) {
|
|
15110
|
+
selectionBody(second.props, second, deps);
|
|
15111
|
+
} else {
|
|
15112
|
+
itemBody(second.props, second, deps);
|
|
15113
|
+
}
|
|
15084
15114
|
}
|
|
15085
15115
|
return true;
|
|
15086
15116
|
}
|
package/dist/version.js
CHANGED