octane 0.1.38 → 0.1.39

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.
@@ -11553,7 +11553,8 @@ function childSlot(parentScope, slotKey, domParent, value, anchor, ownEnd, ownsH
11553
11553
  cachedDeps: null,
11554
11554
  emptyBlock: null,
11555
11555
  env: void 0,
11556
- adopt: null
11556
+ adopt: null,
11557
+ plainDeopt: false
11557
11558
  };
11558
11559
  if (upgradeArmed) {
11559
11560
  state.forSlot.adopt = buildDeoptAdoptQueue(upgradeChildren, state.start, state.end);
@@ -11624,8 +11625,10 @@ function childSlot(parentScope, slotKey, domParent, value, anchor, ownEnd, ownsH
11624
11625
  descriptorBody(item, scope);
11625
11626
  };
11626
11627
  }
11628
+ const plainDeopt = compiledMapBody === void 0 && mappedFallback !== true;
11629
+ state.forSlot.plainDeopt = plainDeopt;
11627
11630
  const fastFlags = compiledMapFlags || 0;
11628
- const ssrMarkerless = compiledMapBody === void 0 ? markerlessMappedFallback || body === deoptItemBody : (fastFlags & 16) !== 0;
11631
+ const ssrMarkerless = compiledMapBody === void 0 ? markerlessMappedFallback || plainDeopt : (fastFlags & 16) !== 0;
11629
11632
  let pure = (fastFlags & 1) !== 0;
11630
11633
  let lite = false;
11631
11634
  if (compiledMapBody !== void 0) {
@@ -14722,7 +14725,11 @@ function forBlock(parentScope, slotKey, domParent, items, getKey, itemBody, flag
14722
14725
  cachedDeps: null,
14723
14726
  emptyBlock: null,
14724
14727
  env: void 0,
14725
- adopt: null
14728
+ adopt: null,
14729
+ // Compiled `@for` slots never read this — they never pass the de-opt
14730
+ // sentinel — but both ForSlot literals declare it so every slot shares
14731
+ // one hidden class and the stamp in childSlot transitions nothing.
14732
+ plainDeopt: false
14726
14733
  };
14727
14734
  parentScope.slots[slotKey] = state;
14728
14735
  registerSlot(parentScope, state);
@@ -15532,8 +15539,8 @@ function batchClearItems(state, oldItems) {
15532
15539
  function mountItem(parentBlock, parentNode, anchor, item, index, body, forSlot, singleRoot, ssrMarkerless, adoptNode = null) {
15533
15540
  const hydration = activeHydration();
15534
15541
  if (hydration !== null) {
15535
- if (ssrMarkerless && !hydration.isOpen(hydration.node) && (singleRoot !== 2 || body !== deoptItemBody || isHostDescriptor(item) && !descNeedsBlocks(item))) {
15536
- if (hydration.node !== null && hydration.node !== forSlot.end && (singleRoot !== 2 || body !== deoptItemBody || hydration.node.nodeType === 1 && hydration.node.parentNode === parentNode)) {
15542
+ if (ssrMarkerless && !hydration.isOpen(hydration.node) && (singleRoot !== 2 || forSlot.plainDeopt !== true || isHostDescriptor(item) && !descNeedsBlocks(item))) {
15543
+ if (hydration.node !== null && hydration.node !== forSlot.end && (singleRoot !== 2 || forSlot.plainDeopt !== true || hydration.node.nodeType === 1 && hydration.node.parentNode === parentNode)) {
15537
15544
  const root = hydration.node;
15538
15545
  const block3 = createBlock(
15539
15546
  "control-flow",
@@ -15547,7 +15554,7 @@ function mountItem(parentBlock, parentNode, anchor, item, index, body, forSlot,
15547
15554
  );
15548
15555
  block3.forSlot = forSlot;
15549
15556
  block3.itemIndex = index;
15550
- if (singleRoot === 2 && body === deoptItemBody) block3.deoptNode = root;
15557
+ if (singleRoot === 2 && forSlot.plainDeopt === true) block3.deoptNode = root;
15551
15558
  renderBlock(block3);
15552
15559
  hydration.node = block3.endMarker?.nextSibling ?? root.nextSibling;
15553
15560
  return block3;
@@ -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.38";
24
+ const version = "0.1.39";
25
25
  // Annotate the CommonJS export names for ESM import in node:
26
26
  0 && (module.exports = {
27
27
  version
@@ -272,6 +272,7 @@ const UNIVERSAL_RUNTIME_IMPORTS = new Set([
272
272
  // ordinary renderers while allowing native first-screen programs to erase
273
273
  // background-owned callbacks from their render-only specialization.
274
274
  const MAIN_THREAD_RENDER_ONLY_CAPABILITY = 'main-thread-render-only';
275
+ const COMPONENT_SCOPE_FOR_CAPABILITY = 'component-scope-for';
275
276
  const THREAD_FUNCTION_CAPABILITY = 'thread-functions';
276
277
  const THREAD_DIRECTIVES = new Map([
277
278
  ['main thread', 'main-thread'],
@@ -2453,7 +2454,8 @@ function templateProgramForHost(node, state) {
2453
2454
  function templateProgramForComponent(node, state) {
2454
2455
  if (
2455
2456
  node.empty != null ||
2456
- !rendererHasCapability(state, 'template-program-mount') ||
2457
+ (!rendererHasCapability(state, 'template-program-mount') &&
2458
+ !rendererHasCapability(state, COMPONENT_SCOPE_FOR_CAPABILITY)) ||
2457
2459
  !isOwnerFreeForExpression(node.right) ||
2458
2460
  !isOwnerFreeForExpression(node.key)
2459
2461
  ) {
@@ -8640,6 +8640,29 @@ function compileInternal(source, filename, options, analyzedAst, mode, bundlerMe
8640
8640
  return true;
8641
8641
  }
8642
8642
  }
8643
+ // METHOD-style custom hooks — `route.useLoaderData()`, `api.useSearch()`,
8644
+ // `SomeContext.useSelector(fn)`. The free-identifier sweep above only sees
8645
+ // bare names, and the unknown-call rule above only inspects Identifier
8646
+ // callees, so without this a component whose ONLY hook is member-form
8647
+ // looks hookless: it takes the lite path, gets no block of its own, and
8648
+ // its hook state lands on the parent — an update from that hook then
8649
+ // re-renders the parent and every sibling.
8650
+ //
8651
+ // Same `use[A-Z]` convention, applied to the PROPERTY name, that the
8652
+ // slot-injection pass already uses for these calls. `useContext` is
8653
+ // included rather than excluded: it is not lite-safe either (the sweep
8654
+ // above rejects the bare name for the same reason).
8655
+ if (
8656
+ t === 'CallExpression' &&
8657
+ n.callee &&
8658
+ n.callee.type === 'MemberExpression' &&
8659
+ !n.callee.computed &&
8660
+ n.callee.property &&
8661
+ n.callee.property.type === 'Identifier' &&
8662
+ /^use[A-Z]/.test(n.callee.property.name)
8663
+ ) {
8664
+ return true;
8665
+ }
8643
8666
  for (const k in n) {
8644
8667
  if (AST_WALK_SKIP_KEYS.has(k)) continue;
8645
8668
  if (walk(n[k])) return true;
package/dist/runtime.d.ts CHANGED
@@ -1442,6 +1442,7 @@ interface ForSlot {
1442
1442
  node: Node;
1443
1443
  }> | null;
1444
1444
  mappedNative?: boolean;
1445
+ plainDeopt: boolean;
1445
1446
  selectionItems?: ArrayLike<any>;
1446
1447
  }
1447
1448
  export declare function forBlock<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;
package/dist/runtime.js CHANGED
@@ -11421,7 +11421,8 @@ function childSlot(parentScope, slotKey, domParent, value, anchor, ownEnd, ownsH
11421
11421
  cachedDeps: null,
11422
11422
  emptyBlock: null,
11423
11423
  env: void 0,
11424
- adopt: null
11424
+ adopt: null,
11425
+ plainDeopt: false
11425
11426
  };
11426
11427
  if (upgradeArmed) {
11427
11428
  state.forSlot.adopt = buildDeoptAdoptQueue(upgradeChildren, state.start, state.end);
@@ -11492,8 +11493,10 @@ function childSlot(parentScope, slotKey, domParent, value, anchor, ownEnd, ownsH
11492
11493
  descriptorBody(item, scope);
11493
11494
  };
11494
11495
  }
11496
+ const plainDeopt = compiledMapBody === void 0 && mappedFallback !== true;
11497
+ state.forSlot.plainDeopt = plainDeopt;
11495
11498
  const fastFlags = compiledMapFlags || 0;
11496
- const ssrMarkerless = compiledMapBody === void 0 ? markerlessMappedFallback || body === deoptItemBody : (fastFlags & 16) !== 0;
11499
+ const ssrMarkerless = compiledMapBody === void 0 ? markerlessMappedFallback || plainDeopt : (fastFlags & 16) !== 0;
11497
11500
  let pure = (fastFlags & 1) !== 0;
11498
11501
  let lite = false;
11499
11502
  if (compiledMapBody !== void 0) {
@@ -14590,7 +14593,11 @@ function forBlock(parentScope, slotKey, domParent, items, getKey, itemBody, flag
14590
14593
  cachedDeps: null,
14591
14594
  emptyBlock: null,
14592
14595
  env: void 0,
14593
- adopt: null
14596
+ adopt: null,
14597
+ // Compiled `@for` slots never read this — they never pass the de-opt
14598
+ // sentinel — but both ForSlot literals declare it so every slot shares
14599
+ // one hidden class and the stamp in childSlot transitions nothing.
14600
+ plainDeopt: false
14594
14601
  };
14595
14602
  parentScope.slots[slotKey] = state;
14596
14603
  registerSlot(parentScope, state);
@@ -15400,8 +15407,8 @@ function batchClearItems(state, oldItems) {
15400
15407
  function mountItem(parentBlock, parentNode, anchor, item, index, body, forSlot, singleRoot, ssrMarkerless, adoptNode = null) {
15401
15408
  const hydration = activeHydration();
15402
15409
  if (hydration !== null) {
15403
- if (ssrMarkerless && !hydration.isOpen(hydration.node) && (singleRoot !== 2 || body !== deoptItemBody || isHostDescriptor(item) && !descNeedsBlocks(item))) {
15404
- if (hydration.node !== null && hydration.node !== forSlot.end && (singleRoot !== 2 || body !== deoptItemBody || hydration.node.nodeType === 1 && hydration.node.parentNode === parentNode)) {
15410
+ if (ssrMarkerless && !hydration.isOpen(hydration.node) && (singleRoot !== 2 || forSlot.plainDeopt !== true || isHostDescriptor(item) && !descNeedsBlocks(item))) {
15411
+ if (hydration.node !== null && hydration.node !== forSlot.end && (singleRoot !== 2 || forSlot.plainDeopt !== true || hydration.node.nodeType === 1 && hydration.node.parentNode === parentNode)) {
15405
15412
  const root = hydration.node;
15406
15413
  const block3 = createBlock(
15407
15414
  "control-flow",
@@ -15415,7 +15422,7 @@ function mountItem(parentBlock, parentNode, anchor, item, index, body, forSlot,
15415
15422
  );
15416
15423
  block3.forSlot = forSlot;
15417
15424
  block3.itemIndex = index;
15418
- if (singleRoot === 2 && body === deoptItemBody) block3.deoptNode = root;
15425
+ if (singleRoot === 2 && forSlot.plainDeopt === true) block3.deoptNode = root;
15419
15426
  renderBlock(block3);
15420
15427
  hydration.node = block3.endMarker?.nextSibling ?? root.nextSibling;
15421
15428
  return block3;
package/dist/version.js CHANGED
@@ -1,4 +1,4 @@
1
- const version = "0.1.38";
1
+ const version = "0.1.39";
2
2
  export {
3
3
  version
4
4
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "octane",
3
- "version": "0.1.38",
3
+ "version": "0.1.39",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "sideEffects": [