octane 0.13.3 → 0.13.4

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.
@@ -21,7 +21,7 @@ __export(version_exports, {
21
21
  version: () => version
22
22
  });
23
23
  module.exports = __toCommonJS(version_exports);
24
- const version = "0.13.3";
24
+ const version = "0.13.4";
25
25
  // Annotate the CommonJS export names for ESM import in node:
26
26
  0 && (module.exports = {
27
27
  version
@@ -3880,7 +3880,7 @@ const CALCULATION_VALUE_PROOFS = [
3880
3880
  * Returns null when nothing moves; otherwise the copy-on-write render nodes,
3881
3881
  * the declarations to append, and their names.
3882
3882
  */
3883
- function hoistStrongRenderCalculations(jsxNodes, ctx, immutableStates) {
3883
+ function hoistStrongRenderCalculations(jsxNodes, ctx, immutableStates, literalsOnly = false) {
3884
3884
  if ((!ctx.strongMemo && !ctx.strongLiteralMemo) || ctx.nativeReads || !ctx.currentComponentLocals)
3885
3885
  return null;
3886
3886
  if (renderTreeWrites(jsxNodes)) return null;
@@ -3973,7 +3973,7 @@ function hoistStrongRenderCalculations(jsxNodes, ctx, immutableStates) {
3973
3973
  );
3974
3974
  if (
3975
3975
  calculation === null ||
3976
- (!ctx.strongMemo && !calculation.literal) ||
3976
+ ((literalsOnly || !ctx.strongMemo) && !calculation.literal) ||
3977
3977
  (calculation.literal && !prop)
3978
3978
  ) {
3979
3979
  return container;
@@ -17920,9 +17920,11 @@ function compileFunctionBody(node, ctx, name, parentNs = 'html', cssHash = null,
17920
17920
  let warmThunk = null;
17921
17921
  let staticChildOnly = false;
17922
17922
  let hoistedCalculations = null;
17923
- if (options && options.autoCallback) {
17924
- const creations = [];
17925
- const warmChildren = [];
17923
+ const componentBody = options?.autoCallback === true;
17924
+ const literalsOnly = !componentBody && options?.memoizeRenderLiterals === true;
17925
+ const creations = [];
17926
+ const warmChildren = [];
17927
+ if (componentBody) {
17926
17928
  // Pass A′ first: use()-fed const chains memoize at their declarations,
17927
17929
  // so Pass A then sees their trivial identifier arguments as already
17928
17930
  // stable and the warm plan includes the chain heads. Param names feed
@@ -17938,62 +17940,75 @@ function compileFunctionBody(node, ctx, name, parentNs = 'html', cssHash = null,
17938
17940
  creations,
17939
17941
  puParamNames,
17940
17942
  );
17941
- // Auto-calculation runs AFTER Pass A′ so use()-fed chains keep their
17942
- // Symbol-slot treatment (their rewritten inits are hook-shaped and are
17943
- // skipped here), and BEFORE Pass A/B so the numeric-slot useMemo it mints is
17944
- // lowered by the authored inline tier rather than re-wrapped. Client only:
17945
- // a server render evaluates each body once, so a cache is pure overhead.
17946
- if (ctx.currentComponentLocals && ctx.mode !== 'server') {
17947
- // Strong inline render expressions become calculations too (#1610). A
17948
- // returned-output body lowers its JSX into a record whose holes may be
17949
- // evaluated later, so it keeps them inline.
17950
- const hoisted = returnedOutput
17951
- ? null
17952
- : hoistStrongRenderCalculations(jsxNodes, ctx, immutableStateProvenance);
17953
- if (hoisted !== null) {
17954
- jsxNodes = hoisted.jsxNodes;
17955
- hoistedCalculations = hoisted.declarations;
17956
- workingStatements = [...workingStatements, ...hoistedCalculations];
17957
- ctx.currentComponentLocals = new Set([...ctx.currentComponentLocals, ...hoisted.names]);
17958
- }
17959
- const renderReadNames = closeCalculationReads(
17960
- workingStatements,
17961
- collectRenderReadNames(jsxNodes, ctx),
17962
- ctx.currentComponentLocals,
17963
- ctx,
17964
- immutableStateProvenance,
17965
- hoisted?.literalReads,
17966
- jsxNodes,
17967
- );
17968
- if (renderReadNames.size > 0) {
17969
- workingStatements = workingStatements.map((statement) => {
17970
- const rewritten = rewriteAutoCalculation(
17943
+ }
17944
+ // Auto-calculation runs AFTER Pass A′ so use()-fed chains keep their
17945
+ // Symbol-slot treatment (their rewritten inits are hook-shaped and are
17946
+ // skipped here), and BEFORE Pass A/B so the numeric-slot useMemo it mints is
17947
+ // lowered by the authored inline tier rather than re-wrapped. Client only:
17948
+ // a server render evaluates each body once, so a cache is pure overhead.
17949
+ if (
17950
+ (componentBody || (literalsOnly && ctx.strongLiteralMemo)) &&
17951
+ ctx.currentComponentLocals &&
17952
+ ctx.mode !== 'server'
17953
+ ) {
17954
+ // Strong inline render expressions become calculations too (#1610). A
17955
+ // returned-output body lowers its JSX into a record whose holes may be
17956
+ // evaluated later, so it keeps them inline.
17957
+ const hoisted = returnedOutput
17958
+ ? null
17959
+ : hoistStrongRenderCalculations(jsxNodes, ctx, immutableStateProvenance, literalsOnly);
17960
+ if (hoisted !== null) {
17961
+ jsxNodes = hoisted.jsxNodes;
17962
+ hoistedCalculations = hoisted.declarations;
17963
+ workingStatements = [...workingStatements, ...hoistedCalculations];
17964
+ ctx.currentComponentLocals = new Set([...ctx.currentComponentLocals, ...hoisted.names]);
17965
+ }
17966
+ const renderReadNames = closeCalculationReads(
17967
+ workingStatements,
17968
+ collectRenderReadNames(jsxNodes, ctx),
17969
+ ctx.currentComponentLocals,
17970
+ ctx,
17971
+ immutableStateProvenance,
17972
+ hoisted?.literalReads,
17973
+ jsxNodes,
17974
+ );
17975
+ if (renderReadNames.size > 0) {
17976
+ workingStatements = workingStatements.map((statement) => {
17977
+ // A construct helper inherits only the literal cache. Ordinary
17978
+ // calculations and callback stability still require component ownership.
17979
+ if (literalsOnly) {
17980
+ const init = unwrapTsExpr(calculationDeclarator(statement)?.init);
17981
+ if (init?.type !== 'ObjectExpression' && init?.type !== 'ArrayExpression')
17982
+ return statement;
17983
+ }
17984
+ const rewritten = rewriteAutoCalculation(
17985
+ statement,
17986
+ ctx.currentComponentLocals,
17987
+ renderReadNames,
17988
+ ctx,
17989
+ immutableStateProvenance,
17990
+ );
17991
+ if (
17992
+ rewritten !== statement &&
17993
+ rewritten.declarations[0].init.callee._octaneImmutableArrayFilter !== undefined
17994
+ ) {
17995
+ hasImmutableArrayProjection = true;
17996
+ }
17997
+ if (ctx.autoMemo && rewritten !== statement) {
17998
+ (autoCalculatedDeclarations ??= new Map()).set(
17999
+ statement.declarations[0].id.name,
17971
18000
  statement,
17972
- ctx.currentComponentLocals,
17973
- renderReadNames,
17974
- ctx,
17975
- immutableStateProvenance,
17976
- );
17977
- if (
17978
- rewritten !== statement &&
17979
- rewritten.declarations[0].init.callee._octaneImmutableArrayFilter !== undefined
17980
- ) {
17981
- hasImmutableArrayProjection = true;
17982
- }
17983
- if (ctx.autoMemo && rewritten !== statement) {
17984
- (autoCalculatedDeclarations ??= new Map()).set(
17985
- statement.declarations[0].id.name,
17986
- statement,
17987
- );
17988
- }
17989
- return rewritten;
17990
- });
17991
- if (ctx.nativeReads)
17992
- workingStatements = workingStatements.flatMap(
17993
- (statement) => lowerNativeAutoCalculation(statement, ctx, name) ?? [statement],
17994
18001
  );
17995
- }
18002
+ }
18003
+ return rewritten;
18004
+ });
18005
+ if (ctx.nativeReads)
18006
+ workingStatements = workingStatements.flatMap(
18007
+ (statement) => lowerNativeAutoCalculation(statement, ctx, name) ?? [statement],
18008
+ );
17996
18009
  }
18010
+ }
18011
+ if (componentBody) {
17997
18012
  workingStatements = parallelUseMemoizePass(workingStatements, ctx, name, creations, [], null);
17998
18013
  jsxNodes = parallelUseWalkJsx(jsxNodes, ctx, name, creations, warmChildren, [], new Set());
17999
18014
  const warm = buildWarmArtifacts(node, ctx, name, creations, warmChildren);
@@ -33741,6 +33756,9 @@ function hoistBodyHelper(
33741
33756
  if (!free.has('arguments') && !free.has('eval')) inheritedEnvNames = envNames;
33742
33757
  }
33743
33758
  const helperOptions = {
33759
+ // Only construct blocks provide an entered render scope. Component
33760
+ // children have envNames === null and may be evaluated by their caller.
33761
+ memoizeRenderLiterals: envNames !== null && !mappedItem,
33744
33762
  keyedSelection,
33745
33763
  inlineBindingGuards,
33746
33764
  mappedItem,
@@ -1,4 +1,4 @@
1
- const version = "0.13.3";
1
+ const version = "0.13.4";
2
2
  export {
3
3
  version
4
4
  };
package/dist/version.js CHANGED
@@ -1,4 +1,4 @@
1
- const version = "0.13.3";
1
+ const version = "0.13.4";
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.13.3",
3
+ "version": "0.13.4",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "sideEffects": [