babel-plugin-react-compiler 0.0.0-experimental-334f00b-20240725 → 0.0.0-experimental-0dbad55-20240807

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.js CHANGED
@@ -135625,6 +135625,14 @@ function getOrInsertDefault(m, key, defaultValue) {
135625
135625
  return defaultValue;
135626
135626
  }
135627
135627
  }
135628
+ function Iterable_some(iter, pred) {
135629
+ for (const item of iter) {
135630
+ if (pred(item)) {
135631
+ return true;
135632
+ }
135633
+ }
135634
+ return false;
135635
+ }
135628
135636
  function hasNode(input) {
135629
135637
  return input.node != null;
135630
135638
  }
@@ -135902,6 +135910,17 @@ var InstructionKind;
135902
135910
  InstructionKind['Catch'] = 'Catch';
135903
135911
  InstructionKind['HoistedConst'] = 'HoistedConst';
135904
135912
  })(InstructionKind || (InstructionKind = {}));
135913
+ function makeTemporaryIdentifier(id, loc) {
135914
+ return {
135915
+ id: id,
135916
+ name: null,
135917
+ declarationId: makeDeclarationId(id),
135918
+ mutableRange: {start: makeInstructionId(0), end: makeInstructionId(0)},
135919
+ scope: null,
135920
+ type: makeType(),
135921
+ loc: loc,
135922
+ };
135923
+ }
135905
135924
  function makeIdentifierName(name) {
135906
135925
  CompilerError.invariant(t__namespace.isValidIdentifier(name), {
135907
135926
  reason: `Expected a valid identifier name`,
@@ -135918,7 +135937,7 @@ function promoteTemporary(identifier) {
135918
135937
  description: `Identifier already has a name, \`${identifier.name}\``,
135919
135938
  suggestions: null,
135920
135939
  });
135921
- identifier.name = {kind: 'promoted', value: `#t${identifier.id}`};
135940
+ identifier.name = {kind: 'promoted', value: `#t${identifier.declarationId}`};
135922
135941
  }
135923
135942
  function isPromotedTemporary(name) {
135924
135943
  return name.startsWith('#t');
@@ -135930,7 +135949,7 @@ function promoteTemporaryJsxTag(identifier) {
135930
135949
  description: `Identifier already has a name, \`${identifier.name}\``,
135931
135950
  suggestions: null,
135932
135951
  });
135933
- identifier.name = {kind: 'promoted', value: `#T${identifier.id}`};
135952
+ identifier.name = {kind: 'promoted', value: `#T${identifier.declarationId}`};
135934
135953
  }
135935
135954
  function isPromotedJsxTemporary(name) {
135936
135955
  return name.startsWith('#T');
@@ -136017,6 +136036,15 @@ function makeIdentifierId(id) {
136017
136036
  });
136018
136037
  return id;
136019
136038
  }
136039
+ function makeDeclarationId(id) {
136040
+ CompilerError.invariant(id >= 0 && Number.isInteger(id), {
136041
+ reason: 'Expected declaration id to be a non-negative integer',
136042
+ description: null,
136043
+ loc: null,
136044
+ suggestions: null,
136045
+ });
136046
+ return id;
136047
+ }
136020
136048
  function makeInstructionId(id) {
136021
136049
  CompilerError.invariant(id >= 0 && Number.isInteger(id), {
136022
136050
  reason: 'Expected instruction id to be a non-negative integer',
@@ -136078,6 +136106,11 @@ function isUseInsertionEffectHookType(id) {
136078
136106
  id.type.shapeId === 'BuiltInUseInsertionEffectHook'
136079
136107
  );
136080
136108
  }
136109
+ function isUseContextHookType(id) {
136110
+ return (
136111
+ id.type.kind === 'Function' && id.type.shapeId === 'BuiltInUseContextHook'
136112
+ );
136113
+ }
136081
136114
  function getHookKind(env, id) {
136082
136115
  return getHookKindForType(env, id.type);
136083
136116
  }
@@ -138666,6 +138699,7 @@ class HIRBuilder {
138666
138699
  _HIRBuilder_env.set(this, void 0);
138667
138700
  _HIRBuilder_exceptionHandlerStack.set(this, []);
138668
138701
  this.errors = new CompilerError();
138702
+ this.fbtDepth = 0;
138669
138703
  __classPrivateFieldSet(this, _HIRBuilder_env, env, 'f');
138670
138704
  __classPrivateFieldSet(
138671
138705
  this,
@@ -138736,14 +138770,7 @@ class HIRBuilder {
138736
138770
  }
138737
138771
  makeTemporary(loc) {
138738
138772
  const id = this.nextIdentifierId;
138739
- return {
138740
- id: id,
138741
- name: null,
138742
- mutableRange: {start: makeInstructionId(0), end: makeInstructionId(0)},
138743
- scope: null,
138744
- type: makeType(),
138745
- loc: loc,
138746
- };
138773
+ return makeTemporaryIdentifier(id, loc);
138747
138774
  }
138748
138775
  resolveIdentifier(path) {
138749
138776
  const originalName = path.node.name;
@@ -138823,7 +138850,13 @@ class HIRBuilder {
138823
138850
  }
138824
138851
  }
138825
138852
  resolveBinding(node) {
138826
- var _a;
138853
+ var _a, _b;
138854
+ if (node.name === 'fbt') {
138855
+ CompilerError.throwTodo({
138856
+ reason: 'Support local variables named "fbt"',
138857
+ loc: (_a = node.loc) !== null && _a !== void 0 ? _a : null,
138858
+ });
138859
+ }
138827
138860
  const originalName = node.name;
138828
138861
  let name = originalName;
138829
138862
  let index = 0;
@@ -138837,6 +138870,7 @@ class HIRBuilder {
138837
138870
  const id = this.nextIdentifierId;
138838
138871
  const identifier = {
138839
138872
  id: id,
138873
+ declarationId: makeDeclarationId(id),
138840
138874
  name: makeIdentifierName(name),
138841
138875
  mutableRange: {
138842
138876
  start: makeInstructionId(0),
@@ -138844,7 +138878,7 @@ class HIRBuilder {
138844
138878
  },
138845
138879
  scope: null,
138846
138880
  type: makeType(),
138847
- loc: (_a = node.loc) !== null && _a !== void 0 ? _a : GeneratedSource,
138881
+ loc: (_b = node.loc) !== null && _b !== void 0 ? _b : GeneratedSource,
138848
138882
  };
138849
138883
  __classPrivateFieldGet(this, _HIRBuilder_bindings, 'f').set(name, {
138850
138884
  node: node,
@@ -139280,19 +139314,19 @@ function removeUnnecessaryTryCatch(fn) {
139280
139314
  function createTemporaryPlace(env, loc) {
139281
139315
  return {
139282
139316
  kind: 'Identifier',
139283
- identifier: {
139284
- id: env.nextIdentifierId,
139285
- mutableRange: {start: makeInstructionId(0), end: makeInstructionId(0)},
139286
- name: null,
139287
- scope: null,
139288
- type: makeType(),
139289
- loc: loc,
139290
- },
139317
+ identifier: makeTemporaryIdentifier(env.nextIdentifierId, loc),
139291
139318
  reactive: false,
139292
139319
  effect: exports.Effect.Unknown,
139293
139320
  loc: GeneratedSource,
139294
139321
  };
139295
139322
  }
139323
+ function clonePlaceToTemporary(env, place) {
139324
+ const temp = createTemporaryPlace(env, place.loc);
139325
+ temp.effect = place.effect;
139326
+ temp.identifier.type = place.identifier.type;
139327
+ temp.reactive = place.reactive;
139328
+ return temp;
139329
+ }
139296
139330
  const PRIMITIVE_TYPE = {kind: 'Primitive'};
139297
139331
  let nextAnonId = 0;
139298
139332
  function createAnonId() {
@@ -139347,6 +139381,7 @@ const BuiltInUseInsertionEffectHookId = 'BuiltInUseInsertionEffectHook';
139347
139381
  const BuiltInUseOperatorId = 'BuiltInUseOperator';
139348
139382
  const BuiltInUseReducerId = 'BuiltInUseReducer';
139349
139383
  const BuiltInDispatchId = 'BuiltInDispatch';
139384
+ const BuiltInUseContextHookId = 'BuiltInUseContextHook';
139350
139385
  const BUILTIN_SHAPES = new Map();
139351
139386
  addObject(BUILTIN_SHAPES, BuiltInPropsId, [
139352
139387
  ['ref', {kind: 'Object', shapeId: BuiltInUseRefId}],
@@ -141660,7 +141695,6 @@ function lowerExpression(builder, exprPath) {
141660
141695
  switch (leftNode.type) {
141661
141696
  case 'Identifier': {
141662
141697
  const leftExpr = left;
141663
- const identifier = lowerIdentifier(builder, leftExpr);
141664
141698
  const leftPlace = lowerExpressionToTemporary(builder, leftExpr);
141665
141699
  const right = lowerExpressionToTemporary(builder, expr.get('right'));
141666
141700
  const binaryPlace = lowerValueToTemporary(builder, {
@@ -141670,30 +141704,42 @@ function lowerExpression(builder, exprPath) {
141670
141704
  right: right,
141671
141705
  loc: exprLoc,
141672
141706
  });
141673
- const kind = getStoreKind(builder, leftExpr);
141674
- if (kind === 'StoreLocal') {
141675
- lowerValueToTemporary(builder, {
141676
- kind: 'StoreLocal',
141677
- lvalue: {
141678
- place: Object.assign({}, identifier),
141679
- kind: InstructionKind.Reassign,
141680
- },
141681
- value: Object.assign({}, binaryPlace),
141682
- type: null,
141683
- loc: exprLoc,
141684
- });
141685
- return {kind: 'LoadLocal', place: identifier, loc: exprLoc};
141707
+ const binding = builder.resolveIdentifier(leftExpr);
141708
+ if (binding.kind === 'Identifier') {
141709
+ const identifier = lowerIdentifier(builder, leftExpr);
141710
+ const kind = getStoreKind(builder, leftExpr);
141711
+ if (kind === 'StoreLocal') {
141712
+ lowerValueToTemporary(builder, {
141713
+ kind: 'StoreLocal',
141714
+ lvalue: {
141715
+ place: Object.assign({}, identifier),
141716
+ kind: InstructionKind.Reassign,
141717
+ },
141718
+ value: Object.assign({}, binaryPlace),
141719
+ type: null,
141720
+ loc: exprLoc,
141721
+ });
141722
+ return {kind: 'LoadLocal', place: identifier, loc: exprLoc};
141723
+ } else {
141724
+ lowerValueToTemporary(builder, {
141725
+ kind: 'StoreContext',
141726
+ lvalue: {
141727
+ place: Object.assign({}, identifier),
141728
+ kind: InstructionKind.Reassign,
141729
+ },
141730
+ value: Object.assign({}, binaryPlace),
141731
+ loc: exprLoc,
141732
+ });
141733
+ return {kind: 'LoadContext', place: identifier, loc: exprLoc};
141734
+ }
141686
141735
  } else {
141687
- lowerValueToTemporary(builder, {
141688
- kind: 'StoreContext',
141689
- lvalue: {
141690
- place: Object.assign({}, identifier),
141691
- kind: InstructionKind.Reassign,
141692
- },
141736
+ const temporary = lowerValueToTemporary(builder, {
141737
+ kind: 'StoreGlobal',
141738
+ name: leftExpr.node.name,
141693
141739
  value: Object.assign({}, binaryPlace),
141694
141740
  loc: exprLoc,
141695
141741
  });
141696
- return {kind: 'LoadContext', place: identifier, loc: exprLoc};
141742
+ return {kind: 'LoadLocal', place: temporary, loc: temporary.loc};
141697
141743
  }
141698
141744
  }
141699
141745
  case 'MemberExpression': {
@@ -141856,18 +141902,17 @@ function lowerExpression(builder, exprPath) {
141856
141902
  }
141857
141903
  props.push({kind: 'JsxAttribute', name: propName, place: value});
141858
141904
  }
141859
- if (
141860
- tag.kind === 'BuiltinTag' &&
141861
- (tag.name === 'fbt' || tag.name === 'fbs')
141862
- ) {
141905
+ const isFbt =
141906
+ tag.kind === 'BuiltinTag' && (tag.name === 'fbt' || tag.name === 'fbs');
141907
+ if (isFbt) {
141863
141908
  const tagName = tag.name;
141864
141909
  const openingIdentifier = opening.get('name');
141865
141910
  const tagIdentifier = openingIdentifier.isJSXIdentifier()
141866
141911
  ? builder.resolveIdentifier(openingIdentifier)
141867
141912
  : null;
141868
- if (tagIdentifier != null && tagIdentifier.kind === 'Identifier') {
141869
- CompilerError.throwTodo({
141870
- reason: `Support <${tagName}> tags where '${tagName}' is a local variable instead of a global`,
141913
+ if (tagIdentifier != null) {
141914
+ CompilerError.invariant(tagIdentifier.kind !== 'Identifier', {
141915
+ reason: `<${tagName}> tags should be module-level imports`,
141871
141916
  loc:
141872
141917
  (_3 = openingIdentifier.node.loc) !== null && _3 !== void 0
141873
141918
  ? _3
@@ -141876,63 +141921,64 @@ function lowerExpression(builder, exprPath) {
141876
141921
  suggestions: null,
141877
141922
  });
141878
141923
  }
141879
- const fbtEnumLocations = [];
141924
+ const fbtLocations = {
141925
+ enum: new Array(),
141926
+ plural: new Array(),
141927
+ pronoun: new Array(),
141928
+ };
141880
141929
  expr.traverse({
141930
+ JSXClosingElement(path) {
141931
+ path.skip();
141932
+ },
141881
141933
  JSXNamespacedName(path) {
141882
- var _a;
141883
- if (
141884
- path.node.namespace.name === tagName &&
141885
- path.node.name.name === 'enum'
141886
- ) {
141887
- fbtEnumLocations.push(
141888
- (_a = path.node.loc) !== null && _a !== void 0
141889
- ? _a
141890
- : GeneratedSource
141891
- );
141934
+ var _a, _b, _c;
141935
+ if (path.node.namespace.name === tagName) {
141936
+ switch (path.node.name.name) {
141937
+ case 'enum':
141938
+ fbtLocations.enum.push(
141939
+ (_a = path.node.loc) !== null && _a !== void 0
141940
+ ? _a
141941
+ : GeneratedSource
141942
+ );
141943
+ break;
141944
+ case 'plural':
141945
+ fbtLocations.plural.push(
141946
+ (_b = path.node.loc) !== null && _b !== void 0
141947
+ ? _b
141948
+ : GeneratedSource
141949
+ );
141950
+ break;
141951
+ case 'pronoun':
141952
+ fbtLocations.pronoun.push(
141953
+ (_c = path.node.loc) !== null && _c !== void 0
141954
+ ? _c
141955
+ : GeneratedSource
141956
+ );
141957
+ break;
141958
+ }
141892
141959
  }
141893
141960
  },
141894
141961
  });
141895
- if (fbtEnumLocations.length > 1) {
141896
- CompilerError.throwTodo({
141897
- reason: `Support <${tagName}> tags with multiple <${tagName}:enum> values`,
141898
- loc:
141899
- (_4 = fbtEnumLocations.at(-1)) !== null && _4 !== void 0
141900
- ? _4
141901
- : GeneratedSource,
141902
- description: null,
141903
- suggestions: null,
141904
- });
141962
+ for (const [name, locations] of Object.entries(fbtLocations)) {
141963
+ if (locations.length > 1) {
141964
+ CompilerError.throwTodo({
141965
+ reason: `Support <${tagName}> tags with multiple <${tagName}:${name}> values`,
141966
+ loc:
141967
+ (_4 = locations.at(-1)) !== null && _4 !== void 0
141968
+ ? _4
141969
+ : GeneratedSource,
141970
+ description: null,
141971
+ suggestions: null,
141972
+ });
141973
+ }
141905
141974
  }
141906
141975
  }
141907
- let children;
141908
- if (
141909
- tag.kind === 'BuiltinTag' &&
141910
- (tag.name === 'fbt' || tag.name === 'fbs')
141911
- ) {
141912
- children = expr
141913
- .get('children')
141914
- .map(child => {
141915
- var _a;
141916
- if (child.isJSXText()) {
141917
- const text = child.node.value.replace(/[^\S\u00A0]+/g, ' ');
141918
- return lowerValueToTemporary(builder, {
141919
- kind: 'JSXText',
141920
- value: text,
141921
- loc:
141922
- (_a = child.node.loc) !== null && _a !== void 0
141923
- ? _a
141924
- : GeneratedSource,
141925
- });
141926
- }
141927
- return lowerJsxElement(builder, child);
141928
- })
141929
- .filter(notNull);
141930
- } else {
141931
- children = expr
141932
- .get('children')
141933
- .map(child => lowerJsxElement(builder, child))
141934
- .filter(notNull);
141935
- }
141976
+ isFbt && builder.fbtDepth++;
141977
+ const children = expr
141978
+ .get('children')
141979
+ .map(child => lowerJsxElement(builder, child))
141980
+ .filter(notNull);
141981
+ isFbt && builder.fbtDepth--;
141936
141982
  return {
141937
141983
  kind: 'JsxExpression',
141938
141984
  tag: tag,
@@ -142788,7 +142834,12 @@ function lowerJsxElement(builder, exprPath) {
142788
142834
  return lowerExpressionToTemporary(builder, expression);
142789
142835
  }
142790
142836
  } else if (exprPath.isJSXText()) {
142791
- const text = trimJsxText(exprPath.node.value);
142837
+ let text;
142838
+ if (builder.fbtDepth > 0) {
142839
+ text = exprPath.node.value;
142840
+ } else {
142841
+ text = trimJsxText(exprPath.node.value);
142842
+ }
142792
142843
  if (text === null) {
142793
142844
  return null;
142794
142845
  }
@@ -142872,7 +142923,7 @@ function lowerFunctionToValue(builder, expr) {
142872
142923
  return {
142873
142924
  kind: 'FunctionExpression',
142874
142925
  name: name,
142875
- expr: expr.node,
142926
+ type: expr.node.type,
142876
142927
  loc: exprLoc,
142877
142928
  loweredFunc: loweredFunc,
142878
142929
  };
@@ -149706,15 +149757,19 @@ const TYPED_GLOBALS = [
149706
149757
  const REACT_APIS = [
149707
149758
  [
149708
149759
  'useContext',
149709
- addHook(DEFAULT_SHAPES, {
149710
- positionalParams: [],
149711
- restParam: exports.Effect.Read,
149712
- returnType: {kind: 'Poly'},
149713
- calleeEffect: exports.Effect.Read,
149714
- hookKind: 'useContext',
149715
- returnValueKind: exports.ValueKind.Frozen,
149716
- returnValueReason: ValueReason.Context,
149717
- }),
149760
+ addHook(
149761
+ DEFAULT_SHAPES,
149762
+ {
149763
+ positionalParams: [],
149764
+ restParam: exports.Effect.Read,
149765
+ returnType: {kind: 'Poly'},
149766
+ calleeEffect: exports.Effect.Read,
149767
+ hookKind: 'useContext',
149768
+ returnValueKind: exports.ValueKind.Frozen,
149769
+ returnValueReason: ValueReason.Context,
149770
+ },
149771
+ BuiltInUseContextHookId
149772
+ ),
149718
149773
  ],
149719
149774
  [
149720
149775
  'useState',
@@ -150031,6 +150086,7 @@ const EnvironmentConfigSchema = z.object({
150031
150086
  enableCustomTypeDefinitionForReanimated: z.boolean().default(false),
150032
150087
  hookPattern: z.string().nullable().default(null),
150033
150088
  enableTreatRefLikeIdentifiersAsRefs: z.boolean().nullable().default(false),
150089
+ enableLowerContextAccess: z.boolean().nullable().default(false),
150034
150090
  });
150035
150091
  function parseConfigPragma(pragma) {
150036
150092
  const maybeConfig = {};
@@ -150055,6 +150111,10 @@ function parseConfigPragma(pragma) {
150055
150111
  };
150056
150112
  continue;
150057
150113
  }
150114
+ if (key === 'customMacros' && val) {
150115
+ maybeConfig[key] = [val];
150116
+ continue;
150117
+ }
150058
150118
  if (typeof defaultConfig[key] !== 'boolean') {
150059
150119
  continue;
150060
150120
  }
@@ -153260,6 +153320,12 @@ function mayAllocate(env, instruction) {
153260
153320
  function findDisjointMutableValues(fn) {
153261
153321
  var _a, _b;
153262
153322
  const scopeIdentifiers = new DisjointSet();
153323
+ const declarations = new Map();
153324
+ function declareIdentifier(lvalue) {
153325
+ if (!declarations.has(lvalue.identifier.declarationId)) {
153326
+ declarations.set(lvalue.identifier.declarationId, lvalue.identifier);
153327
+ }
153328
+ }
153263
153329
  for (const [_, block] of fn.body.blocks) {
153264
153330
  for (const phi of block.phis) {
153265
153331
  if (
@@ -153272,9 +153338,15 @@ function findDisjointMutableValues(fn) {
153272
153338
  ? _b
153273
153339
  : block.terminal.id)
153274
153340
  ) {
153275
- for (const [, phiId] of phi.operands) {
153276
- scopeIdentifiers.union([phi.id, phiId]);
153341
+ const operands = [phi.id];
153342
+ const declaration = declarations.get(phi.id.declarationId);
153343
+ if (declaration !== undefined) {
153344
+ operands.push(declaration);
153345
+ }
153346
+ for (const [_, phiId] of phi.operands) {
153347
+ operands.push(phiId);
153277
153348
  }
153349
+ scopeIdentifiers.union(operands);
153278
153350
  } else if (fn.env.config.enableForest) {
153279
153351
  for (const [, phiId] of phi.operands) {
153280
153352
  scopeIdentifiers.union([phi.id, phiId]);
@@ -153288,9 +153360,15 @@ function findDisjointMutableValues(fn) {
153288
153360
  operands.push(instr.lvalue.identifier);
153289
153361
  }
153290
153362
  if (
153363
+ instr.value.kind === 'DeclareLocal' ||
153364
+ instr.value.kind === 'DeclareContext'
153365
+ ) {
153366
+ declareIdentifier(instr.value.lvalue.place);
153367
+ } else if (
153291
153368
  instr.value.kind === 'StoreLocal' ||
153292
153369
  instr.value.kind === 'StoreContext'
153293
153370
  ) {
153371
+ declareIdentifier(instr.value.lvalue.place);
153294
153372
  if (
153295
153373
  instr.value.lvalue.place.identifier.mutableRange.end >
153296
153374
  instr.value.lvalue.place.identifier.mutableRange.start + 1
@@ -153305,6 +153383,7 @@ function findDisjointMutableValues(fn) {
153305
153383
  }
153306
153384
  } else if (instr.value.kind === 'Destructure') {
153307
153385
  for (const place of eachPatternOperand(instr.value.lvalue.pattern)) {
153386
+ declareIdentifier(place);
153308
153387
  if (
153309
153388
  place.identifier.mutableRange.end >
153310
153389
  place.identifier.mutableRange.start + 1
@@ -153683,7 +153762,7 @@ const defaultOptions = {
153683
153762
  noEmit: false,
153684
153763
  runtimeModule: null,
153685
153764
  eslintSuppressionRules: null,
153686
- flowSuppressions: false,
153765
+ flowSuppressions: true,
153687
153766
  ignoreUseNoForget: false,
153688
153767
  sources: filename => filename.indexOf('node_modules') === -1,
153689
153768
  enableReanimatedCheck: true,
@@ -153925,10 +154004,10 @@ function eliminateRedundantPhi(fn, sharedRewrites) {
153925
154004
  }
153926
154005
  for (const instr of block.instructions) {
153927
154006
  for (const place of eachInstructionLValue(instr)) {
153928
- rewritePlace$1(place, rewrites);
154007
+ rewritePlace(place, rewrites);
153929
154008
  }
153930
154009
  for (const place of eachInstructionOperand(instr)) {
153931
- rewritePlace$1(place, rewrites);
154010
+ rewritePlace(place, rewrites);
153932
154011
  }
153933
154012
  if (
153934
154013
  instr.value.kind === 'FunctionExpression' ||
@@ -153936,19 +154015,19 @@ function eliminateRedundantPhi(fn, sharedRewrites) {
153936
154015
  ) {
153937
154016
  const {context: context} = instr.value.loweredFunc.func;
153938
154017
  for (const place of context) {
153939
- rewritePlace$1(place, rewrites);
154018
+ rewritePlace(place, rewrites);
153940
154019
  }
153941
154020
  eliminateRedundantPhi(instr.value.loweredFunc.func, rewrites);
153942
154021
  }
153943
154022
  }
153944
154023
  const {terminal: terminal} = block;
153945
154024
  for (const place of eachTerminalOperand(terminal)) {
153946
- rewritePlace$1(place, rewrites);
154025
+ rewritePlace(place, rewrites);
153947
154026
  }
153948
154027
  }
153949
154028
  } while (rewrites.size > size && hasBackEdge);
153950
154029
  }
153951
- function rewritePlace$1(place, rewrites) {
154030
+ function rewritePlace(place, rewrites) {
153952
154031
  const rewrite = rewrites.get(place.identifier);
153953
154032
  if (rewrite != null) {
153954
154033
  place.identifier = rewrite;
@@ -154002,6 +154081,7 @@ class SSABuilder {
154002
154081
  makeId(oldId) {
154003
154082
  return {
154004
154083
  id: this.nextSsaId,
154084
+ declarationId: oldId.declarationId,
154005
154085
  name: oldId.name,
154006
154086
  mutableRange: {start: makeInstructionId(0), end: makeInstructionId(0)},
154007
154087
  scope: null,
@@ -154205,342 +154285,152 @@ function enterSSAImpl(func, builder, rootEntry) {
154205
154285
  }
154206
154286
  }
154207
154287
  }
154208
- function leaveSSA(fn) {
154209
- var _a, _b, _c;
154288
+ function rewriteInstructionKindsBasedOnReassignment(fn) {
154210
154289
  const declarations = new Map();
154211
154290
  for (const param of fn.params) {
154212
154291
  let place = param.kind === 'Identifier' ? param : param.place;
154213
154292
  if (place.identifier.name !== null) {
154214
- declarations.set(place.identifier.name.value, {
154215
- lvalue: {kind: InstructionKind.Let, place: place},
154293
+ declarations.set(place.identifier.declarationId, {
154294
+ kind: InstructionKind.Let,
154216
154295
  place: place,
154217
154296
  });
154218
154297
  }
154219
154298
  }
154220
- const rewrites = new Map();
154221
- const seen = new Set();
154222
- const backEdgePhis = new Set();
154223
- for (const [, block] of fn.body.blocks) {
154224
- for (const phi of block.phis) {
154225
- for (const [pred] of phi.operands) {
154226
- if (!seen.has(pred)) {
154227
- backEdgePhis.add(phi);
154228
- break;
154229
- }
154230
- }
154299
+ for (const place of fn.context) {
154300
+ if (place.identifier.name !== null) {
154301
+ declarations.set(place.identifier.declarationId, {
154302
+ kind: InstructionKind.Let,
154303
+ place: place,
154304
+ });
154231
154305
  }
154232
- seen.add(block.id);
154233
154306
  }
154234
154307
  for (const [, block] of fn.body.blocks) {
154235
154308
  for (const instr of block.instructions) {
154236
- const {lvalue: lvalue, value: value} = instr;
154237
- if (value.kind === 'DeclareLocal') {
154238
- const name = value.lvalue.place.identifier.name;
154239
- if (name !== null) {
154240
- CompilerError.invariant(!declarations.has(name.value), {
154241
- reason: `Unexpected duplicate declaration`,
154242
- description: `Found duplicate declaration for \`${name.value}\``,
154243
- loc: value.lvalue.place.loc,
154244
- suggestions: null,
154245
- });
154246
- declarations.set(name.value, {
154247
- lvalue: value.lvalue,
154248
- place: value.lvalue.place,
154249
- });
154250
- }
154251
- } else if (
154252
- value.kind === 'PrefixUpdate' ||
154253
- value.kind === 'PostfixUpdate'
154254
- ) {
154255
- CompilerError.invariant(value.lvalue.identifier.name !== null, {
154256
- reason: `Expected update expression to be applied to a named variable`,
154257
- description: null,
154258
- loc: value.lvalue.loc,
154259
- suggestions: null,
154260
- });
154261
- const originalLVal = declarations.get(
154262
- value.lvalue.identifier.name.value
154263
- );
154264
- CompilerError.invariant(originalLVal !== undefined, {
154265
- reason: `Expected update expression to be applied to a previously defined variable`,
154266
- description: null,
154267
- loc: value.lvalue.loc,
154268
- suggestions: null,
154269
- });
154270
- originalLVal.lvalue.kind = InstructionKind.Let;
154271
- } else if (value.kind === 'StoreLocal') {
154272
- if (value.lvalue.place.identifier.name != null) {
154273
- const originalLVal = declarations.get(
154274
- value.lvalue.place.identifier.name.value
154309
+ const {value: value} = instr;
154310
+ switch (value.kind) {
154311
+ case 'DeclareLocal': {
154312
+ const lvalue = value.lvalue;
154313
+ CompilerError.invariant(
154314
+ !declarations.has(lvalue.place.identifier.declarationId),
154315
+ {
154316
+ reason: `Expected variable not to be defined prior to declaration`,
154317
+ description: `${printPlace(lvalue.place)} was already defined`,
154318
+ loc: lvalue.place.loc,
154319
+ }
154275
154320
  );
154276
- if (
154277
- originalLVal === undefined ||
154278
- originalLVal.lvalue === value.lvalue
154279
- ) {
154280
- CompilerError.invariant(
154281
- originalLVal !== undefined ||
154282
- block.kind === 'block' ||
154283
- block.kind === 'catch',
154284
- {
154285
- reason: `TODO: Handle reassignment in a value block where the original declaration was removed by dead code elimination (DCE)`,
154286
- description: null,
154287
- loc: value.lvalue.place.loc,
154288
- suggestions: null,
154289
- }
154290
- );
154291
- declarations.set(value.lvalue.place.identifier.name.value, {
154292
- lvalue: value.lvalue,
154293
- place: value.lvalue.place,
154294
- });
154295
- value.lvalue.kind = InstructionKind.Const;
154296
- } else {
154297
- originalLVal.lvalue.kind = InstructionKind.Let;
154298
- value.lvalue.kind = InstructionKind.Reassign;
154299
- }
154300
- } else if (rewrites.has(value.lvalue.place.identifier)) {
154301
- value.lvalue.kind = InstructionKind.Const;
154321
+ declarations.set(lvalue.place.identifier.declarationId, lvalue);
154322
+ break;
154302
154323
  }
154303
- } else if (value.kind === 'Destructure') {
154304
- let kind = null;
154305
- for (const place of eachPatternOperand(value.lvalue.pattern)) {
154306
- if (place.identifier.name == null) {
154307
- CompilerError.invariant(
154308
- kind === null || kind === InstructionKind.Const,
154309
- {
154310
- reason: `Expected consistent kind for destructuring`,
154311
- description: `other places were \`${kind}\` but '${printPlace(place)}' is const`,
154312
- loc: place.loc,
154313
- suggestions: null,
154314
- }
154324
+ case 'StoreLocal': {
154325
+ const lvalue = value.lvalue;
154326
+ if (lvalue.place.identifier.name !== null) {
154327
+ const declaration = declarations.get(
154328
+ lvalue.place.identifier.declarationId
154315
154329
  );
154316
- kind = InstructionKind.Const;
154317
- } else {
154318
- const originalLVal = declarations.get(place.identifier.name.value);
154319
- if (
154320
- originalLVal === undefined ||
154321
- originalLVal.lvalue === value.lvalue
154322
- ) {
154330
+ if (declaration === undefined) {
154323
154331
  CompilerError.invariant(
154324
- originalLVal !== undefined || block.kind !== 'value',
154332
+ !declarations.has(lvalue.place.identifier.declarationId),
154325
154333
  {
154326
- reason: `TODO: Handle reassignment in a value block where the original declaration was removed by dead code elimination (DCE)`,
154327
- description: null,
154328
- loc: place.loc,
154329
- suggestions: null,
154334
+ reason: `Expected variable not to be defined prior to declaration`,
154335
+ description: `${printPlace(lvalue.place)} was already defined`,
154336
+ loc: lvalue.place.loc,
154330
154337
  }
154331
154338
  );
154332
- declarations.set(place.identifier.name.value, {
154333
- lvalue: value.lvalue,
154334
- place: place,
154335
- });
154339
+ declarations.set(lvalue.place.identifier.declarationId, lvalue);
154340
+ lvalue.kind = InstructionKind.Const;
154341
+ } else {
154342
+ declaration.kind = InstructionKind.Let;
154343
+ lvalue.kind = InstructionKind.Reassign;
154344
+ }
154345
+ }
154346
+ break;
154347
+ }
154348
+ case 'Destructure': {
154349
+ const lvalue = value.lvalue;
154350
+ let kind = null;
154351
+ for (const place of eachPatternOperand(lvalue.pattern)) {
154352
+ if (place.identifier.name === null) {
154336
154353
  CompilerError.invariant(
154337
154354
  kind === null || kind === InstructionKind.Const,
154338
154355
  {
154339
154356
  reason: `Expected consistent kind for destructuring`,
154340
- description: `Other places were \`${kind}\` but '${printPlace(place)}' is const`,
154357
+ description: `other places were \`${kind}\` but '${printPlace(place)}' is const`,
154341
154358
  loc: place.loc,
154342
154359
  suggestions: null,
154343
154360
  }
154344
154361
  );
154345
154362
  kind = InstructionKind.Const;
154346
154363
  } else {
154347
- CompilerError.invariant(
154348
- kind === null || kind === InstructionKind.Reassign,
154349
- {
154350
- reason: `Expected consistent kind for destructuring`,
154351
- description: `Other places were \`${kind}\` but '${printPlace(place)}' is reassigned`,
154364
+ const declaration = declarations.get(
154365
+ place.identifier.declarationId
154366
+ );
154367
+ if (declaration === undefined) {
154368
+ CompilerError.invariant(block.kind !== 'value', {
154369
+ reason: `TODO: Handle reassignment in a value block where the original declaration was removed by dead code elimination (DCE)`,
154370
+ description: null,
154352
154371
  loc: place.loc,
154353
154372
  suggestions: null,
154354
- }
154355
- );
154356
- kind = InstructionKind.Reassign;
154357
- originalLVal.lvalue.kind = InstructionKind.Let;
154373
+ });
154374
+ declarations.set(place.identifier.declarationId, lvalue);
154375
+ CompilerError.invariant(
154376
+ kind === null || kind === InstructionKind.Const,
154377
+ {
154378
+ reason: `Expected consistent kind for destructuring`,
154379
+ description: `Other places were \`${kind}\` but '${printPlace(place)}' is const`,
154380
+ loc: place.loc,
154381
+ suggestions: null,
154382
+ }
154383
+ );
154384
+ kind = InstructionKind.Const;
154385
+ } else {
154386
+ CompilerError.invariant(
154387
+ kind === null || kind === InstructionKind.Reassign,
154388
+ {
154389
+ reason: `Expected consistent kind for destructuring`,
154390
+ description: `Other places were \`${kind}\` but '${printPlace(place)}' is reassigned`,
154391
+ loc: place.loc,
154392
+ suggestions: null,
154393
+ }
154394
+ );
154395
+ kind = InstructionKind.Reassign;
154396
+ declaration.kind = InstructionKind.Let;
154397
+ }
154358
154398
  }
154359
154399
  }
154400
+ CompilerError.invariant(kind !== null, {
154401
+ reason: 'Expected at least one operand',
154402
+ description: null,
154403
+ loc: null,
154404
+ suggestions: null,
154405
+ });
154406
+ lvalue.kind = kind;
154407
+ break;
154360
154408
  }
154361
- CompilerError.invariant(kind !== null, {
154362
- reason: 'Expected at least one operand',
154363
- description: null,
154364
- loc: null,
154365
- suggestions: null,
154366
- });
154367
- value.lvalue.kind = kind;
154368
- }
154369
- rewritePlace(lvalue, rewrites, declarations);
154370
- for (const operand of eachInstructionLValue(instr)) {
154371
- rewritePlace(operand, rewrites, declarations);
154372
- }
154373
- for (const operand of eachInstructionValueOperand(instr.value)) {
154374
- rewritePlace(operand, rewrites, declarations);
154375
- }
154376
- }
154377
- const terminal = block.terminal;
154378
- for (const operand of eachTerminalOperand(terminal)) {
154379
- rewritePlace(operand, rewrites, declarations);
154380
- }
154381
- const reassignmentPhis = [];
154382
- const rewritePhis = [];
154383
- function pushPhis(phiBlock) {
154384
- for (const phi of phiBlock.phis) {
154385
- if (phi.id.name === null) {
154386
- rewritePhis.push({phi: phi, block: phiBlock});
154387
- } else {
154388
- reassignmentPhis.push({phi: phi, block: phiBlock});
154409
+ case 'PostfixUpdate':
154410
+ case 'PrefixUpdate': {
154411
+ const lvalue = value.lvalue;
154412
+ const declaration = declarations.get(lvalue.identifier.declarationId);
154413
+ CompilerError.invariant(declaration !== undefined, {
154414
+ reason: `Expected variable to have been defined`,
154415
+ description: `No declaration for ${printPlace(lvalue)}`,
154416
+ loc: lvalue.loc,
154417
+ });
154418
+ declaration.kind = InstructionKind.Let;
154419
+ break;
154389
154420
  }
154390
154421
  }
154391
154422
  }
154392
- const fallthroughId = terminalFallthrough(terminal);
154393
- if (fallthroughId !== null) {
154394
- const fallthrough = fn.body.blocks.get(fallthroughId);
154395
- pushPhis(fallthrough);
154396
- }
154397
- if (terminal.kind === 'while' || terminal.kind === 'for') {
154398
- const test = fn.body.blocks.get(terminal.test);
154399
- pushPhis(test);
154400
- const loop = fn.body.blocks.get(terminal.loop);
154401
- pushPhis(loop);
154402
- }
154403
- if (
154404
- terminal.kind === 'for' ||
154405
- terminal.kind === 'for-of' ||
154406
- terminal.kind === 'for-in'
154407
- ) {
154408
- let init = fn.body.blocks.get(terminal.init);
154409
- pushPhis(init);
154410
- let initContinuation =
154411
- terminal.kind === 'for' ? terminal.test : terminal.loop;
154412
- const queue = [init.id];
154413
- while (queue.length !== 0) {
154414
- const blockId = queue.shift();
154415
- if (blockId === initContinuation) {
154416
- break;
154417
- }
154418
- const block = fn.body.blocks.get(blockId);
154419
- for (const instr of block.instructions) {
154420
- if (
154421
- instr.value.kind === 'StoreLocal' &&
154422
- instr.value.lvalue.kind !== InstructionKind.Reassign
154423
- ) {
154424
- const value = instr.value;
154425
- if (value.lvalue.place.identifier.name !== null) {
154426
- const originalLVal = declarations.get(
154427
- value.lvalue.place.identifier.name.value
154428
- );
154429
- if (originalLVal === undefined) {
154430
- declarations.set(value.lvalue.place.identifier.name.value, {
154431
- lvalue: value.lvalue,
154432
- place: value.lvalue.place,
154433
- });
154434
- value.lvalue.kind = InstructionKind.Const;
154435
- }
154436
- }
154437
- }
154438
- }
154439
- switch (block.terminal.kind) {
154440
- case 'maybe-throw': {
154441
- queue.push(block.terminal.continuation);
154442
- break;
154443
- }
154444
- case 'goto': {
154445
- queue.push(block.terminal.block);
154446
- break;
154447
- }
154448
- case 'branch':
154449
- case 'logical':
154450
- case 'optional':
154451
- case 'ternary':
154452
- case 'label': {
154453
- for (const successor of eachTerminalSuccessor(block.terminal)) {
154454
- queue.push(successor);
154455
- }
154456
- break;
154457
- }
154458
- }
154459
- }
154460
- if (terminal.kind === 'for' && terminal.update !== null) {
154461
- const update = fn.body.blocks.get(terminal.update);
154462
- pushPhis(update);
154463
- }
154464
- }
154465
- for (const {phi: phi, block: phiBlock} of reassignmentPhis) {
154466
- for (const [, operand] of phi.operands) {
154467
- if (operand.mutableRange.start < terminal.id);
154468
- }
154469
- const isPhiMutatedAfterCreation =
154470
- phi.id.mutableRange.end >
154471
- ((_b =
154472
- (_a = phiBlock.instructions.at(0)) === null || _a === void 0
154473
- ? void 0
154474
- : _a.id) !== null && _b !== void 0
154475
- ? _b
154476
- : phiBlock.terminal.id);
154477
- CompilerError.invariant(phi.id.name != null, {
154478
- reason: 'Expected reassignment phis to have a name',
154479
- description: null,
154480
- loc: null,
154481
- suggestions: null,
154482
- });
154483
- const declaration = declarations.get(phi.id.name.value);
154484
- CompilerError.invariant(declaration != null, {
154485
- loc: null,
154486
- reason: 'Expected a declaration for all variables',
154487
- description: `${printIdentifier(phi.id)} in block bb${phiBlock.id}`,
154488
- suggestions: null,
154489
- });
154490
- if (isPhiMutatedAfterCreation) {
154491
- declaration.place.identifier.mutableRange.end = phi.id.mutableRange.end;
154492
- }
154493
- rewrites.set(phi.id, declaration.place.identifier);
154494
- }
154495
- for (const {phi: phi} of rewritePhis) {
154496
- let canonicalId = rewrites.get(phi.id);
154497
- if (canonicalId === undefined) {
154498
- canonicalId = phi.id;
154499
- for (const [, operand] of phi.operands) {
154500
- let canonicalOperand =
154501
- (_c = rewrites.get(operand)) !== null && _c !== void 0
154502
- ? _c
154503
- : operand;
154504
- if (canonicalOperand.id < canonicalId.id) {
154505
- canonicalId = canonicalOperand;
154506
- }
154507
- }
154508
- rewrites.set(phi.id, canonicalId);
154509
- if (canonicalId.name !== null) {
154510
- const declaration = declarations.get(canonicalId.name.value);
154511
- if (declaration !== undefined) {
154512
- declaration.lvalue.kind = InstructionKind.Let;
154513
- }
154514
- }
154515
- }
154516
- for (const [, operand] of phi.operands) {
154517
- rewrites.set(operand, canonicalId);
154518
- }
154519
- }
154520
- }
154521
- }
154522
- function rewritePlace(place, rewrites, declarations) {
154523
- const prevIdentifier = place.identifier;
154524
- const nextIdentifier = rewrites.get(prevIdentifier);
154525
- if (nextIdentifier !== undefined) {
154526
- if (nextIdentifier === prevIdentifier) return;
154527
- place.identifier = nextIdentifier;
154528
- } else if (prevIdentifier.name != null) {
154529
- const declaration = declarations.get(prevIdentifier.name.value);
154530
- if (declaration === undefined) return;
154531
- const originalIdentifier = declaration.place.identifier;
154532
- prevIdentifier.id = originalIdentifier.id;
154533
- }
154534
- }
154535
- function constantPropagation(fn) {
154536
- const constants = new Map();
154537
- constantPropagationImpl(fn, constants);
154538
- }
154539
- function constantPropagationImpl(fn, constants) {
154540
- while (true) {
154541
- const haveTerminalsChanged = applyConstantPropagation(fn, constants);
154542
- if (!haveTerminalsChanged) {
154543
- break;
154423
+ }
154424
+ }
154425
+ function constantPropagation(fn) {
154426
+ const constants = new Map();
154427
+ constantPropagationImpl(fn, constants);
154428
+ }
154429
+ function constantPropagationImpl(fn, constants) {
154430
+ while (true) {
154431
+ const haveTerminalsChanged = applyConstantPropagation(fn, constants);
154432
+ if (!haveTerminalsChanged) {
154433
+ break;
154544
154434
  }
154545
154435
  reversePostorderBlocks(fn.body);
154546
154436
  removeUnreachableForUpdates(fn.body);
@@ -156825,12 +156715,7 @@ function visit$1(fn, fbtMacroTags, fbtValues) {
156825
156715
  }
156826
156716
  for (const operand of eachReactiveValueOperand(value)) {
156827
156717
  operand.identifier.scope = fbtScope;
156828
- fbtScope.range.start = makeInstructionId(
156829
- Math.min(
156830
- fbtScope.range.start,
156831
- operand.identifier.mutableRange.start
156832
- )
156833
- );
156718
+ expandFbtScopeRange(fbtScope.range, operand.identifier.mutableRange);
156834
156719
  fbtValues.add(operand.identifier.id);
156835
156720
  }
156836
156721
  } else if (
@@ -156843,12 +156728,7 @@ function visit$1(fn, fbtMacroTags, fbtValues) {
156843
156728
  }
156844
156729
  for (const operand of eachReactiveValueOperand(value)) {
156845
156730
  operand.identifier.scope = fbtScope;
156846
- fbtScope.range.start = makeInstructionId(
156847
- Math.min(
156848
- fbtScope.range.start,
156849
- operand.identifier.mutableRange.start
156850
- )
156851
- );
156731
+ expandFbtScopeRange(fbtScope.range, operand.identifier.mutableRange);
156852
156732
  fbtValues.add(operand.identifier.id);
156853
156733
  }
156854
156734
  } else if (fbtValues.has(lvalue.identifier.id)) {
@@ -156864,12 +156744,7 @@ function visit$1(fn, fbtMacroTags, fbtValues) {
156864
156744
  continue;
156865
156745
  }
156866
156746
  operand.identifier.scope = fbtScope;
156867
- fbtScope.range.start = makeInstructionId(
156868
- Math.min(
156869
- fbtScope.range.start,
156870
- operand.identifier.mutableRange.start
156871
- )
156872
- );
156747
+ expandFbtScopeRange(fbtScope.range, operand.identifier.mutableRange);
156873
156748
  }
156874
156749
  }
156875
156750
  }
@@ -156895,6 +156770,13 @@ function isFbtJsxChild(fbtValues, lvalue, value) {
156895
156770
  fbtValues.has(lvalue.identifier.id)
156896
156771
  );
156897
156772
  }
156773
+ function expandFbtScopeRange(fbtRange, extendWith) {
156774
+ if (extendWith.start !== 0) {
156775
+ fbtRange.start = makeInstructionId(
156776
+ Math.min(fbtRange.start, extendWith.start)
156777
+ );
156778
+ }
156779
+ }
156898
156780
  var _Context_nextCacheIndex, _Context_declarations$1;
156899
156781
  const MEMO_CACHE_SENTINEL = 'react.memo_cache_sentinel';
156900
156782
  const EARLY_RETURN_SENTINEL = 'react.early_return_sentinel';
@@ -157064,7 +156946,7 @@ function codegenFunction(
157064
156946
  } of cx.env.getOutlinedFunctions()) {
157065
156947
  const reactiveFunction = buildReactiveFunction(outlinedFunction);
157066
156948
  pruneUnusedLabels(reactiveFunction);
157067
- pruneTemporaryLValues(reactiveFunction);
156949
+ pruneUnusedLValues(reactiveFunction);
157068
156950
  pruneHoistedContexts(reactiveFunction);
157069
156951
  const identifiers = renameVariables(reactiveFunction);
157070
156952
  const codegen = codegenReactiveFunction(
@@ -157089,9 +156971,9 @@ function codegenFunction(
157089
156971
  function codegenReactiveFunction(cx, fn) {
157090
156972
  for (const param of fn.params) {
157091
156973
  if (param.kind === 'Identifier') {
157092
- cx.temp.set(param.identifier.id, null);
156974
+ cx.temp.set(param.identifier.declarationId, null);
157093
156975
  } else {
157094
- cx.temp.set(param.place.identifier.id, null);
156976
+ cx.temp.set(param.place.identifier.declarationId, null);
157095
156977
  }
157096
156978
  }
157097
156979
  const params = fn.params.map(param => convertParameter(param));
@@ -157183,12 +157065,12 @@ let Context$2 = class Context {
157183
157065
  }
157184
157066
  declare(identifier) {
157185
157067
  __classPrivateFieldGet(this, _Context_declarations$1, 'f').add(
157186
- identifier.id
157068
+ identifier.declarationId
157187
157069
  );
157188
157070
  }
157189
157071
  hasDeclared(identifier) {
157190
157072
  return __classPrivateFieldGet(this, _Context_declarations$1, 'f').has(
157191
- identifier.id
157073
+ identifier.declarationId
157192
157074
  );
157193
157075
  }
157194
157076
  synthesizeName(name) {
@@ -157884,7 +157766,7 @@ function codegenTerminal(cx, terminal) {
157884
157766
  let catchParam = null;
157885
157767
  if (terminal.handlerBinding !== null) {
157886
157768
  catchParam = convertIdentifier(terminal.handlerBinding.identifier);
157887
- cx.temp.set(terminal.handlerBinding.identifier.id, null);
157769
+ cx.temp.set(terminal.handlerBinding.identifier.declarationId, null);
157888
157770
  }
157889
157771
  return t__namespace.tryStatement(
157890
157772
  codegenBlock(cx, terminal.block),
@@ -157938,7 +157820,7 @@ function codegenInstructionNullable(cx, instr) {
157938
157820
  kind !== InstructionKind.Reassign &&
157939
157821
  place.identifier.name === null
157940
157822
  ) {
157941
- cx.temp.set(place.identifier.id, null);
157823
+ cx.temp.set(place.identifier.declarationId, null);
157942
157824
  }
157943
157825
  const isDeclared = cx.hasDeclared(place.identifier);
157944
157826
  hasReasign || (hasReasign = isDeclared);
@@ -157994,7 +157876,7 @@ function codegenInstructionNullable(cx, instr) {
157994
157876
  );
157995
157877
  if (instr.lvalue !== null) {
157996
157878
  if (instr.value.kind !== 'StoreContext') {
157997
- cx.temp.set(instr.lvalue.identifier.id, expr);
157879
+ cx.temp.set(instr.lvalue.identifier.declarationId, expr);
157998
157880
  return null;
157999
157881
  } else {
158000
157882
  const statement = codegenInstruction(cx, instr, expr);
@@ -158219,7 +158101,7 @@ function codegenInstruction(cx, instr, value) {
158219
158101
  return t__namespace.expressionStatement(convertValueToExpression(value));
158220
158102
  }
158221
158103
  if (instr.lvalue.identifier.name === null) {
158222
- cx.temp.set(instr.lvalue.identifier.id, value);
158104
+ cx.temp.set(instr.lvalue.identifier.declarationId, value);
158223
158105
  return t__namespace.emptyStatement();
158224
158106
  } else {
158225
158107
  const expressionValue = convertValueToExpression(value);
@@ -158449,7 +158331,7 @@ function codegenInstructionValue(cx, instrValue) {
158449
158331
  const loweredFunc = method.loweredFunc;
158450
158332
  const reactiveFunction = buildReactiveFunction(loweredFunc.func);
158451
158333
  pruneUnusedLabels(reactiveFunction);
158452
- pruneTemporaryLValues(reactiveFunction);
158334
+ pruneUnusedLValues(reactiveFunction);
158453
158335
  const fn = codegenReactiveFunction(
158454
158336
  new Context$2(
158455
158337
  cx.env,
@@ -158647,7 +158529,7 @@ function codegenInstructionValue(cx, instrValue) {
158647
158529
  const loweredFunc = instrValue.loweredFunc.func;
158648
158530
  const reactiveFunction = buildReactiveFunction(loweredFunc);
158649
158531
  pruneUnusedLabels(reactiveFunction);
158650
- pruneTemporaryLValues(reactiveFunction);
158532
+ pruneUnusedLValues(reactiveFunction);
158651
158533
  pruneHoistedContexts(reactiveFunction);
158652
158534
  const fn = codegenReactiveFunction(
158653
158535
  new Context$2(
@@ -158661,7 +158543,7 @@ function codegenInstructionValue(cx, instrValue) {
158661
158543
  ),
158662
158544
  reactiveFunction
158663
158545
  ).unwrap();
158664
- if (instrValue.expr.type === 'ArrowFunctionExpression') {
158546
+ if (instrValue.type === 'ArrowFunctionExpression') {
158665
158547
  let body = fn.body;
158666
158548
  if (body.body.length === 1 && loweredFunc.directives.length == 0) {
158667
158549
  const stmt = body.body[0];
@@ -159093,7 +158975,7 @@ function codegenPlaceToExpression(cx, place) {
159093
158975
  return convertValueToExpression(value);
159094
158976
  }
159095
158977
  function codegenPlace(cx, place) {
159096
- let tmp = cx.temp.get(place.identifier.id);
158978
+ let tmp = cx.temp.get(place.identifier.declarationId);
159097
158979
  if (tmp != null) {
159098
158980
  return tmp;
159099
158981
  }
@@ -159132,7 +159014,7 @@ let State$1 = class State {
159132
159014
  let Visitor$b = class Visitor extends ReactiveFunctionTransform {
159133
159015
  visitScope(scope, state) {
159134
159016
  for (const [, declaration] of scope.scope.declarations) {
159135
- state.declared.add(declaration.identifier.id);
159017
+ state.declared.add(declaration.identifier.declarationId);
159136
159018
  }
159137
159019
  this.traverseScope(scope, state);
159138
159020
  }
@@ -159161,7 +159043,7 @@ function transformDestructuring(state, instr, destructure) {
159161
159043
  let reassigned = new Set();
159162
159044
  let hasDeclaration = false;
159163
159045
  for (const place of eachPatternOperand(destructure.lvalue.pattern)) {
159164
- const isDeclared = state.declared.has(place.identifier.id);
159046
+ const isDeclared = state.declared.has(place.identifier.declarationId);
159165
159047
  if (isDeclared) {
159166
159048
  reassigned.add(place.identifier.id);
159167
159049
  }
@@ -159176,13 +159058,7 @@ function transformDestructuring(state, instr, destructure) {
159176
159058
  if (!reassigned.has(place.identifier.id)) {
159177
159059
  return place;
159178
159060
  }
159179
- const tempId = state.env.nextIdentifierId;
159180
- const temporary = Object.assign(Object.assign({}, place), {
159181
- identifier: Object.assign(Object.assign({}, place.identifier), {
159182
- id: tempId,
159183
- name: null,
159184
- }),
159185
- });
159061
+ const temporary = clonePlaceToTemporary(state.env, place);
159186
159062
  promoteTemporary(temporary.identifier);
159187
159063
  renamed.set(place, temporary);
159188
159064
  return temporary;
@@ -159445,12 +159321,12 @@ class FindLastUsageVisitor extends ReactiveFunctionVisitor {
159445
159321
  this.lastUsage = new Map();
159446
159322
  }
159447
159323
  visitPlace(id, place, _state) {
159448
- const previousUsage = this.lastUsage.get(place.identifier.id);
159324
+ const previousUsage = this.lastUsage.get(place.identifier.declarationId);
159449
159325
  const lastUsage =
159450
159326
  previousUsage !== undefined
159451
159327
  ? makeInstructionId(Math.max(previousUsage, id))
159452
159328
  : id;
159453
- this.lastUsage.set(place.identifier.id, lastUsage);
159329
+ this.lastUsage.set(place.identifier.declarationId, lastUsage);
159454
159330
  }
159455
159331
  }
159456
159332
  let Transform$4 = class Transform extends ReactiveFunctionTransform {
@@ -159519,7 +159395,9 @@ let Transform$4 = class Transform extends ReactiveFunctionTransform {
159519
159395
  case 'TemplateLiteral':
159520
159396
  case 'UnaryExpression': {
159521
159397
  if (current !== null && instr.instruction.lvalue !== null) {
159522
- current.lvalues.add(instr.instruction.lvalue.identifier.id);
159398
+ current.lvalues.add(
159399
+ instr.instruction.lvalue.identifier.declarationId
159400
+ );
159523
159401
  }
159524
159402
  break;
159525
159403
  }
@@ -159531,7 +159409,7 @@ let Transform$4 = class Transform extends ReactiveFunctionTransform {
159531
159409
  for (const lvalue of eachInstructionLValue(
159532
159410
  instr.instruction
159533
159411
  )) {
159534
- current.lvalues.add(lvalue.identifier.id);
159412
+ current.lvalues.add(lvalue.identifier.declarationId);
159535
159413
  }
159536
159414
  } else {
159537
159415
  log$1(
@@ -159656,10 +159534,10 @@ let Transform$4 = class Transform extends ReactiveFunctionTransform {
159656
159534
  }
159657
159535
  };
159658
159536
  function updateScopeDeclarations(scope, lastUsage) {
159659
- for (const [key] of scope.declarations) {
159660
- const lastUsedAt = lastUsage.get(key);
159537
+ for (const [id, decl] of scope.declarations) {
159538
+ const lastUsedAt = lastUsage.get(decl.identifier.declarationId);
159661
159539
  if (lastUsedAt < scope.range.end) {
159662
- scope.declarations.delete(key);
159540
+ scope.declarations.delete(id);
159663
159541
  }
159664
159542
  }
159665
159543
  }
@@ -159698,8 +159576,12 @@ function canMergeScopes(current, next) {
159698
159576
  (next.scope.dependencies.size !== 0 &&
159699
159577
  [...next.scope.dependencies].every(
159700
159578
  dep =>
159701
- current.scope.declarations.has(dep.identifier.id) &&
159702
- isAlwaysInvalidatingType(dep.identifier.type)
159579
+ isAlwaysInvalidatingType(dep.identifier.type) &&
159580
+ Iterable_some(
159581
+ current.scope.declarations.values(),
159582
+ decl =>
159583
+ decl.identifier.declarationId === dep.identifier.declarationId
159584
+ )
159703
159585
  ))
159704
159586
  ) {
159705
159587
  return true;
@@ -159729,7 +159611,7 @@ function areEqualDependencies(a, b) {
159729
159611
  let found = false;
159730
159612
  for (const bValue of b) {
159731
159613
  if (
159732
- aValue.identifier === bValue.identifier &&
159614
+ aValue.identifier.declarationId === bValue.identifier.declarationId &&
159733
159615
  areEqualPaths(aValue.path, bValue.path)
159734
159616
  ) {
159735
159617
  found = true;
@@ -159755,7 +159637,6 @@ function scopeIsEligibleForMerging(scopeBlock) {
159755
159637
  }
159756
159638
  let Visitor$9 = class Visitor extends ReactiveFunctionVisitor {
159757
159639
  visitScope(scopeBlock, state) {
159758
- this.traverseScope(scopeBlock, state);
159759
159640
  for (const dep of scopeBlock.scope.dependencies) {
159760
159641
  const {identifier: identifier} = dep;
159761
159642
  if (identifier.name == null) {
@@ -159767,21 +159648,22 @@ let Visitor$9 = class Visitor extends ReactiveFunctionVisitor {
159767
159648
  promoteIdentifier(declaration.identifier, state);
159768
159649
  }
159769
159650
  }
159651
+ this.traverseScope(scopeBlock, state);
159770
159652
  }
159771
159653
  visitPrunedScope(scopeBlock, state) {
159772
159654
  var _a;
159773
- this.traversePrunedScope(scopeBlock, state);
159774
159655
  for (const [, declaration] of scopeBlock.scope.declarations) {
159775
159656
  if (
159776
159657
  declaration.identifier.name == null &&
159777
- ((_a = state.pruned.get(declaration.identifier.id)) === null ||
159778
- _a === void 0
159658
+ ((_a = state.pruned.get(declaration.identifier.declarationId)) ===
159659
+ null || _a === void 0
159779
159660
  ? void 0
159780
159661
  : _a.usedOutsideScope) === true
159781
159662
  ) {
159782
159663
  promoteIdentifier(declaration.identifier, state);
159783
159664
  }
159784
159665
  }
159666
+ this.traversePrunedScope(scopeBlock, state);
159785
159667
  }
159786
159668
  visitParam(place, state) {
159787
159669
  if (place.identifier.name === null) {
@@ -159804,6 +159686,56 @@ let Visitor$9 = class Visitor extends ReactiveFunctionVisitor {
159804
159686
  visitReactiveFunction(fn, this, state);
159805
159687
  }
159806
159688
  };
159689
+ class Visitor2 extends ReactiveFunctionVisitor {
159690
+ visitPlace(_id, place, state) {
159691
+ if (
159692
+ place.identifier.name === null &&
159693
+ state.promoted.has(place.identifier.declarationId)
159694
+ ) {
159695
+ promoteIdentifier(place.identifier, state);
159696
+ }
159697
+ }
159698
+ visitLValue(_id, _lvalue, _state) {
159699
+ this.visitPlace(_id, _lvalue, _state);
159700
+ }
159701
+ traverseScopeIdentifiers(scope, state) {
159702
+ for (const [, decl] of scope.declarations) {
159703
+ if (
159704
+ decl.identifier.name === null &&
159705
+ state.promoted.has(decl.identifier.declarationId)
159706
+ ) {
159707
+ promoteIdentifier(decl.identifier, state);
159708
+ }
159709
+ }
159710
+ for (const dep of scope.dependencies) {
159711
+ if (
159712
+ dep.identifier.name === null &&
159713
+ state.promoted.has(dep.identifier.declarationId)
159714
+ ) {
159715
+ promoteIdentifier(dep.identifier, state);
159716
+ }
159717
+ }
159718
+ for (const reassignment of scope.reassignments) {
159719
+ if (
159720
+ reassignment.name === null &&
159721
+ state.promoted.has(reassignment.declarationId)
159722
+ ) {
159723
+ promoteIdentifier(reassignment, state);
159724
+ }
159725
+ }
159726
+ }
159727
+ visitScope(scope, state) {
159728
+ this.traverseScope(scope, state);
159729
+ this.traverseScopeIdentifiers(scope.scope, state);
159730
+ }
159731
+ visitPrunedScope(scopeBlock, state) {
159732
+ this.traversePrunedScope(scopeBlock, state);
159733
+ this.traverseScopeIdentifiers(scopeBlock.scope, state);
159734
+ }
159735
+ visitReactiveFunctionValue(_id, _dependencies, fn, state) {
159736
+ visitReactiveFunction(fn, this, state);
159737
+ }
159738
+ }
159807
159739
  class CollectPromotableTemporaries extends ReactiveFunctionVisitor {
159808
159740
  constructor() {
159809
159741
  super(...arguments);
@@ -159812,9 +159744,9 @@ class CollectPromotableTemporaries extends ReactiveFunctionVisitor {
159812
159744
  visitPlace(_id, place, state) {
159813
159745
  if (
159814
159746
  this.activeScopes.length !== 0 &&
159815
- state.pruned.has(place.identifier.id)
159747
+ state.pruned.has(place.identifier.declarationId)
159816
159748
  ) {
159817
- const prunedPlace = state.pruned.get(place.identifier.id);
159749
+ const prunedPlace = state.pruned.get(place.identifier.declarationId);
159818
159750
  if (prunedPlace.activeScopes.indexOf(this.activeScopes.at(-1)) === -1) {
159819
159751
  prunedPlace.usedOutsideScope = true;
159820
159752
  }
@@ -159823,16 +159755,17 @@ class CollectPromotableTemporaries extends ReactiveFunctionVisitor {
159823
159755
  visitValue(id, value, state) {
159824
159756
  this.traverseValue(id, value, state);
159825
159757
  if (value.kind === 'JsxExpression' && value.tag.kind === 'Identifier') {
159826
- state.tags.add(value.tag.identifier.id);
159758
+ state.tags.add(value.tag.identifier.declarationId);
159827
159759
  }
159828
159760
  }
159829
159761
  visitPrunedScope(scopeBlock, state) {
159830
- for (const [id] of scopeBlock.scope.declarations) {
159831
- state.pruned.set(id, {
159762
+ for (const [_id, decl] of scopeBlock.scope.declarations) {
159763
+ state.pruned.set(decl.identifier.declarationId, {
159832
159764
  activeScopes: [...this.activeScopes],
159833
159765
  usedOutsideScope: false,
159834
159766
  });
159835
159767
  }
159768
+ this.visitBlock(scopeBlock.instructions, state);
159836
159769
  }
159837
159770
  visitScope(scopeBlock, state) {
159838
159771
  this.activeScopes.push(scopeBlock.scope.id);
@@ -159841,7 +159774,7 @@ class CollectPromotableTemporaries extends ReactiveFunctionVisitor {
159841
159774
  }
159842
159775
  }
159843
159776
  function promoteUsedTemporaries(fn) {
159844
- const state = {tags: new Set(), pruned: new Map()};
159777
+ const state = {tags: new Set(), promoted: new Set(), pruned: new Map()};
159845
159778
  visitReactiveFunction(fn, new CollectPromotableTemporaries(), state);
159846
159779
  for (const operand of fn.params) {
159847
159780
  const place = operand.kind === 'Identifier' ? operand : operand.place;
@@ -159850,6 +159783,7 @@ function promoteUsedTemporaries(fn) {
159850
159783
  }
159851
159784
  }
159852
159785
  visitReactiveFunction(fn, new Visitor$9(), state);
159786
+ visitReactiveFunction(fn, new Visitor2(), state);
159853
159787
  }
159854
159788
  function promoteIdentifier(identifier, state) {
159855
159789
  CompilerError.invariant(identifier.name === null, {
@@ -159859,11 +159793,12 @@ function promoteIdentifier(identifier, state) {
159859
159793
  loc: GeneratedSource,
159860
159794
  suggestions: null,
159861
159795
  });
159862
- if (state.tags.has(identifier.id)) {
159796
+ if (state.tags.has(identifier.declarationId)) {
159863
159797
  promoteTemporaryJsxTag(identifier);
159864
159798
  } else {
159865
159799
  promoteTemporary(identifier);
159866
159800
  }
159801
+ state.promoted.add(identifier.declarationId);
159867
159802
  }
159868
159803
  function propagateEarlyReturns(fn) {
159869
159804
  visitReactiveFunction(fn, new Transform$3(fn.env), {
@@ -160542,18 +160477,23 @@ class FindPromotedTemporaries extends ReactiveFunctionVisitor {
160542
160477
  case 'LoadLocal':
160543
160478
  case 'LoadContext':
160544
160479
  case 'PropertyLoad': {
160545
- state.declarations.set(instruction.lvalue.identifier.id, scope);
160480
+ state.declarations.set(
160481
+ instruction.lvalue.identifier.declarationId,
160482
+ scope
160483
+ );
160546
160484
  break;
160547
160485
  }
160548
160486
  }
160549
160487
  }
160550
160488
  visitPlace(_id, place, state) {
160551
- const declaringScope = state.declarations.get(place.identifier.id);
160489
+ const declaringScope = state.declarations.get(
160490
+ place.identifier.declarationId
160491
+ );
160552
160492
  if (declaringScope === undefined) {
160553
160493
  return;
160554
160494
  }
160555
160495
  if (this.scopes.indexOf(declaringScope) === -1) {
160556
- state.usedOutsideDeclaringScope.add(place.identifier.id);
160496
+ state.usedOutsideDeclaringScope.add(place.identifier.declarationId);
160557
160497
  }
160558
160498
  }
160559
160499
  }
@@ -160797,7 +160737,7 @@ class Context {
160797
160737
  this,
160798
160738
  _Context_temporariesUsedOutsideScope,
160799
160739
  'f'
160800
- ).has(place.identifier.id);
160740
+ ).has(place.identifier.declarationId);
160801
160741
  }
160802
160742
  printDeps(includeAccesses = false) {
160803
160743
  return __classPrivateFieldGet(this, _Context_dependencies, 'f').printDeps(
@@ -160857,11 +160797,11 @@ class Context {
160857
160797
  declare(identifier, decl) {
160858
160798
  if (
160859
160799
  !__classPrivateFieldGet(this, _Context_declarations, 'f').has(
160860
- identifier.id
160800
+ identifier.declarationId
160861
160801
  )
160862
160802
  ) {
160863
160803
  __classPrivateFieldGet(this, _Context_declarations, 'f').set(
160864
- identifier.id,
160804
+ identifier.declarationId,
160865
160805
  decl
160866
160806
  );
160867
160807
  }
@@ -160935,7 +160875,7 @@ class Context {
160935
160875
  this,
160936
160876
  _Context_declarations,
160937
160877
  'f'
160938
- ).get(maybeDependency.identifier.id);
160878
+ ).get(maybeDependency.identifier.declarationId);
160939
160879
  if (
160940
160880
  originalDeclaration !== undefined &&
160941
160881
  originalDeclaration.scope.value !== null
@@ -160947,7 +160887,13 @@ class Context {
160947
160887
  _Context_instances,
160948
160888
  'm',
160949
160889
  _Context_isScopeActive
160950
- ).call(this, scope.value)
160890
+ ).call(this, scope.value) &&
160891
+ !Iterable_some(
160892
+ scope.value.declarations.values(),
160893
+ decl =>
160894
+ decl.identifier.declarationId ===
160895
+ maybeDependency.identifier.declarationId
160896
+ )
160951
160897
  ) {
160952
160898
  scope.value.declarations.set(maybeDependency.identifier.id, {
160953
160899
  identifier: maybeDependency.identifier,
@@ -160984,8 +160930,10 @@ class Context {
160984
160930
  : _a.value;
160985
160931
  if (
160986
160932
  currentScope != null &&
160987
- !Array.from(currentScope.reassignments).some(
160988
- identifier => identifier.id === place.identifier.id
160933
+ !Iterable_some(
160934
+ currentScope.reassignments,
160935
+ identifier =>
160936
+ identifier.declarationId === place.identifier.declarationId
160989
160937
  ) &&
160990
160938
  __classPrivateFieldGet(
160991
160939
  this,
@@ -161091,7 +161039,7 @@ class Context {
161091
161039
  )) !== null && _a !== void 0
161092
161040
  ? _a
161093
161041
  : __classPrivateFieldGet(this, _Context_declarations, 'f').get(
161094
- identifier.id
161042
+ identifier.declarationId
161095
161043
  );
161096
161044
  const currentScope =
161097
161045
  (_b = this.currentScope.value) === null || _b === void 0
@@ -161126,7 +161074,19 @@ class PropagationVisitor extends ReactiveFunctionVisitor {
161126
161074
  const scopeDependencies = context.enter(scope.scope, () => {
161127
161075
  this.visitBlock(scope.instructions, context);
161128
161076
  });
161129
- scope.scope.dependencies = scopeDependencies;
161077
+ for (const candidateDep of scopeDependencies) {
161078
+ if (
161079
+ !Iterable_some(
161080
+ scope.scope.dependencies,
161081
+ existingDep =>
161082
+ existingDep.identifier.declarationId ===
161083
+ candidateDep.identifier.declarationId &&
161084
+ areEqualPaths(existingDep.path, candidateDep.path)
161085
+ )
161086
+ ) {
161087
+ scope.scope.dependencies.add(candidateDep);
161088
+ }
161089
+ }
161130
161090
  }
161131
161091
  visitPrunedScope(scopeBlock, context) {
161132
161092
  context.enter(scopeBlock.scope, () => {
@@ -161438,12 +161398,12 @@ let Visitor$8 = class Visitor extends ReactiveFunctionTransform {
161438
161398
  instruction.value.kind === 'DeclareContext' &&
161439
161399
  instruction.value.lvalue.kind === 'HoistedConst'
161440
161400
  ) {
161441
- state.add(instruction.value.lvalue.place.identifier);
161401
+ state.add(instruction.value.lvalue.place.identifier.declarationId);
161442
161402
  return {kind: 'remove'};
161443
161403
  }
161444
161404
  if (
161445
161405
  instruction.value.kind === 'StoreContext' &&
161446
- state.has(instruction.value.lvalue.place.identifier)
161406
+ state.has(instruction.value.lvalue.place.identifier.declarationId)
161447
161407
  ) {
161448
161408
  return {
161449
161409
  kind: 'replace',
@@ -161465,69 +161425,6 @@ let Visitor$8 = class Visitor extends ReactiveFunctionTransform {
161465
161425
  return {kind: 'keep'};
161466
161426
  }
161467
161427
  };
161468
- function validateMemoizedEffectDependencies(fn) {
161469
- const errors = new CompilerError();
161470
- visitReactiveFunction(fn, new Visitor$7(), errors);
161471
- if (errors.hasErrors()) {
161472
- throw errors;
161473
- }
161474
- }
161475
- let Visitor$7 = class Visitor extends ReactiveFunctionVisitor {
161476
- constructor() {
161477
- super(...arguments);
161478
- this.scopes = new Set();
161479
- }
161480
- visitScope(scopeBlock, state) {
161481
- this.traverseScope(scopeBlock, state);
161482
- let areDependenciesMemoized = true;
161483
- for (const dep of scopeBlock.scope.dependencies) {
161484
- if (isUnmemoized$1(dep.identifier, this.scopes)) {
161485
- areDependenciesMemoized = false;
161486
- break;
161487
- }
161488
- }
161489
- if (areDependenciesMemoized) {
161490
- this.scopes.add(scopeBlock.scope.id);
161491
- for (const id of scopeBlock.scope.merged) {
161492
- this.scopes.add(id);
161493
- }
161494
- }
161495
- }
161496
- visitInstruction(instruction, state) {
161497
- this.traverseInstruction(instruction, state);
161498
- if (
161499
- instruction.value.kind === 'CallExpression' &&
161500
- isEffectHook(instruction.value.callee.identifier) &&
161501
- instruction.value.args.length >= 2
161502
- ) {
161503
- const deps = instruction.value.args[1];
161504
- if (
161505
- deps.kind === 'Identifier' &&
161506
- (isMutable(instruction, deps) ||
161507
- isUnmemoized$1(deps.identifier, this.scopes))
161508
- ) {
161509
- state.push({
161510
- reason:
161511
- 'React Compiler has skipped optimizing this component because the effect dependencies could not be memoized. Unmemoized effect dependencies can trigger an infinite loop or other unexpected behavior',
161512
- description: null,
161513
- severity: exports.ErrorSeverity.CannotPreserveMemoization,
161514
- loc: typeof instruction.loc !== 'symbol' ? instruction.loc : null,
161515
- suggestions: null,
161516
- });
161517
- }
161518
- }
161519
- }
161520
- };
161521
- function isUnmemoized$1(operand, scopes) {
161522
- return operand.scope != null && !scopes.has(operand.scope.id);
161523
- }
161524
- function isEffectHook(identifier) {
161525
- return (
161526
- isUseEffectHookType(identifier) ||
161527
- isUseLayoutEffectHookType(identifier) ||
161528
- isUseInsertionEffectHookType(identifier)
161529
- );
161530
- }
161531
161428
  var _InferenceState_env, _InferenceState_values, _InferenceState_variables;
161532
161429
  const UndefinedValue = {
161533
161430
  kind: 'Primitive',
@@ -162434,7 +162331,7 @@ function inferBlock(env, functionEffects, state, block) {
162434
162331
  );
162435
162332
  functionEffects.push(
162436
162333
  ...propEffects.filter(
162437
- propEffect => propEffect.kind !== 'GlobalMutation'
162334
+ effect => !isEffectSafeOutsideRender(effect)
162438
162335
  )
162439
162336
  );
162440
162337
  }
@@ -162584,7 +162481,7 @@ function inferBlock(env, functionEffects, state, block) {
162584
162481
  context: new Set(),
162585
162482
  };
162586
162483
  let hasCaptureArgument = false;
162587
- let isUseEffect = isEffectHook(instrValue.callee.identifier);
162484
+ let isHook = getHookKind(env, instrValue.callee.identifier) != null;
162588
162485
  for (let i = 0; i < instrValue.args.length; i++) {
162589
162486
  const argumentEffects = [];
162590
162487
  const arg = instrValue.args[i];
@@ -162606,8 +162503,7 @@ function inferBlock(env, functionEffects, state, block) {
162606
162503
  }
162607
162504
  functionEffects.push(
162608
162505
  ...argumentEffects.filter(
162609
- argEffect =>
162610
- !isUseEffect || i !== 0 || argEffect.kind !== 'GlobalMutation'
162506
+ argEffect => !isHook || !isEffectSafeOutsideRender(argEffect)
162611
162507
  )
162612
162508
  );
162613
162509
  hasCaptureArgument ||
@@ -162699,7 +162595,7 @@ function inferBlock(env, functionEffects, state, block) {
162699
162595
  const effects =
162700
162596
  signature !== null ? getFunctionEffects(instrValue, signature) : null;
162701
162597
  let hasCaptureArgument = false;
162702
- let isUseEffect = isEffectHook(instrValue.property.identifier);
162598
+ let isHook = getHookKind(env, instrValue.property.identifier) != null;
162703
162599
  for (let i = 0; i < instrValue.args.length; i++) {
162704
162600
  const argumentEffects = [];
162705
162601
  const arg = instrValue.args[i];
@@ -162721,8 +162617,7 @@ function inferBlock(env, functionEffects, state, block) {
162721
162617
  }
162722
162618
  functionEffects.push(
162723
162619
  ...argumentEffects.filter(
162724
- argEffect =>
162725
- !isUseEffect || i !== 0 || argEffect.kind !== 'GlobalMutation'
162620
+ argEffect => !isHook || !isEffectSafeOutsideRender(argEffect)
162726
162621
  )
162727
162622
  );
162728
162623
  hasCaptureArgument ||
@@ -163167,11 +163062,15 @@ function inferBlock(env, functionEffects, state, block) {
163167
163062
  } else {
163168
163063
  effect = exports.Effect.Read;
163169
163064
  }
163065
+ const propEffects = [];
163170
163066
  state.referenceAndRecordEffects(
163171
163067
  operand,
163172
163068
  effect,
163173
163069
  ValueReason.Other,
163174
- functionEffects
163070
+ propEffects
163071
+ );
163072
+ functionEffects.push(
163073
+ ...propEffects.filter(effect => !isEffectSafeOutsideRender(effect))
163175
163074
  );
163176
163075
  }
163177
163076
  }
@@ -163240,6 +163139,9 @@ function areArgumentsImmutableAndNonMutating(state, args) {
163240
163139
  }
163241
163140
  return true;
163242
163141
  }
163142
+ function isEffectSafeOutsideRender(effect) {
163143
+ return effect.kind === 'GlobalMutation';
163144
+ }
163243
163145
  function getWriteErrorReason(abstractValue) {
163244
163146
  if (abstractValue.reason.has(ValueReason.Global)) {
163245
163147
  return 'Writing to a variable defined outside a component or hook is not allowed. Consider using an effect';
@@ -163263,9 +163165,9 @@ function pruneNonEscapingScopes(fn) {
163263
163165
  const state = new State(fn.env);
163264
163166
  for (const param of fn.params) {
163265
163167
  if (param.kind === 'Identifier') {
163266
- state.declare(param.identifier.id);
163168
+ state.declare(param.identifier.declarationId);
163267
163169
  } else {
163268
- state.declare(param.place.identifier.id);
163170
+ state.declare(param.place.identifier.declarationId);
163269
163171
  }
163270
163172
  }
163271
163173
  visitReactiveFunction(fn, new CollectDependenciesVisitor(fn.env), state);
@@ -163322,7 +163224,9 @@ class State {
163322
163224
  let node = this.scopes.get(scope.id);
163323
163225
  if (node === undefined) {
163324
163226
  node = {
163325
- dependencies: [...scope.dependencies].map(dep => dep.identifier.id),
163227
+ dependencies: [...scope.dependencies].map(
163228
+ dep => dep.identifier.declarationId
163229
+ ),
163326
163230
  seen: false,
163327
163231
  };
163328
163232
  this.scopes.set(scope.id, node);
@@ -163766,18 +163670,18 @@ class CollectDependenciesVisitor extends ReactiveFunctionVisitor {
163766
163670
  );
163767
163671
  for (const operand of aliasing.rvalues) {
163768
163672
  const operandId =
163769
- (_a = state.definitions.get(operand.identifier.id)) !== null &&
163770
- _a !== void 0
163673
+ (_a = state.definitions.get(operand.identifier.declarationId)) !==
163674
+ null && _a !== void 0
163771
163675
  ? _a
163772
- : operand.identifier.id;
163676
+ : operand.identifier.declarationId;
163773
163677
  state.visitOperand(instruction.id, operand, operandId);
163774
163678
  }
163775
163679
  for (const {place: lvalue, level: level} of aliasing.lvalues) {
163776
163680
  const lvalueId =
163777
- (_b = state.definitions.get(lvalue.identifier.id)) !== null &&
163778
- _b !== void 0
163681
+ (_b = state.definitions.get(lvalue.identifier.declarationId)) !==
163682
+ null && _b !== void 0
163779
163683
  ? _b
163780
- : lvalue.identifier.id;
163684
+ : lvalue.identifier.declarationId;
163781
163685
  let node = state.identifiers.get(lvalueId);
163782
163686
  if (node === undefined) {
163783
163687
  node = {
@@ -163792,10 +163696,10 @@ class CollectDependenciesVisitor extends ReactiveFunctionVisitor {
163792
163696
  node.level = joinAliases(node.level, level);
163793
163697
  for (const operand of aliasing.rvalues) {
163794
163698
  const operandId =
163795
- (_c = state.definitions.get(operand.identifier.id)) !== null &&
163796
- _c !== void 0
163699
+ (_c = state.definitions.get(operand.identifier.declarationId)) !==
163700
+ null && _c !== void 0
163797
163701
  ? _c
163798
- : operand.identifier.id;
163702
+ : operand.identifier.declarationId;
163799
163703
  if (operandId === lvalueId) {
163800
163704
  continue;
163801
163705
  }
@@ -163805,8 +163709,8 @@ class CollectDependenciesVisitor extends ReactiveFunctionVisitor {
163805
163709
  }
163806
163710
  if (instruction.value.kind === 'LoadLocal' && instruction.lvalue !== null) {
163807
163711
  state.definitions.set(
163808
- instruction.lvalue.identifier.id,
163809
- instruction.value.place.identifier.id
163712
+ instruction.lvalue.identifier.declarationId,
163713
+ instruction.value.place.identifier.declarationId
163810
163714
  );
163811
163715
  } else if (
163812
163716
  instruction.value.kind === 'CallExpression' ||
@@ -163826,7 +163730,7 @@ class CollectDependenciesVisitor extends ReactiveFunctionVisitor {
163826
163730
  }
163827
163731
  for (const operand of instruction.value.args) {
163828
163732
  const place = operand.kind === 'Spread' ? operand.place : operand;
163829
- state.escapingValues.add(place.identifier.id);
163733
+ state.escapingValues.add(place.identifier.declarationId);
163830
163734
  }
163831
163735
  }
163832
163736
  }
@@ -163834,7 +163738,7 @@ class CollectDependenciesVisitor extends ReactiveFunctionVisitor {
163834
163738
  visitTerminal(stmt, state) {
163835
163739
  this.traverseTerminal(stmt, state);
163836
163740
  if (stmt.terminal.kind === 'return') {
163837
- state.escapingValues.add(stmt.terminal.value.identifier.id);
163741
+ state.escapingValues.add(stmt.terminal.value.identifier.declarationId);
163838
163742
  }
163839
163743
  }
163840
163744
  }
@@ -163853,11 +163757,11 @@ class PruneScopesTransform extends ReactiveFunctionTransform {
163853
163757
  return {kind: 'keep'};
163854
163758
  }
163855
163759
  const hasMemoizedOutput =
163856
- Array.from(scopeBlock.scope.declarations.keys()).some(id =>
163857
- state.has(id)
163760
+ Array.from(scopeBlock.scope.declarations.values()).some(decl =>
163761
+ state.has(decl.identifier.declarationId)
163858
163762
  ) ||
163859
163763
  Array.from(scopeBlock.scope.reassignments).some(identifier =>
163860
- state.has(identifier.id)
163764
+ state.has(identifier.declarationId)
163861
163765
  );
163862
163766
  if (hasMemoizedOutput) {
163863
163767
  return {kind: 'keep'};
@@ -163880,7 +163784,7 @@ class PruneScopesTransform extends ReactiveFunctionTransform {
163880
163784
  return {kind: 'keep'};
163881
163785
  }
163882
163786
  }
163883
- let Visitor$6 = class Visitor extends ReactiveFunctionVisitor {
163787
+ let Visitor$7 = class Visitor extends ReactiveFunctionVisitor {
163884
163788
  visitLValue(id, lvalue, state) {
163885
163789
  this.visitPlace(id, lvalue, state);
163886
163790
  }
@@ -163899,16 +163803,16 @@ let Visitor$6 = class Visitor extends ReactiveFunctionVisitor {
163899
163803
  }
163900
163804
  };
163901
163805
  function collectReactiveIdentifiers(fn) {
163902
- const visitor = new Visitor$6();
163806
+ const visitor = new Visitor$7();
163903
163807
  const state = new Set();
163904
163808
  visitReactiveFunction(fn, visitor, state);
163905
163809
  return state;
163906
163810
  }
163907
163811
  function pruneNonReactiveDependencies(fn) {
163908
163812
  const reactiveIdentifiers = collectReactiveIdentifiers(fn);
163909
- visitReactiveFunction(fn, new Visitor$5(), reactiveIdentifiers);
163813
+ visitReactiveFunction(fn, new Visitor$6(), reactiveIdentifiers);
163910
163814
  }
163911
- let Visitor$5 = class Visitor extends ReactiveFunctionVisitor {
163815
+ let Visitor$6 = class Visitor extends ReactiveFunctionVisitor {
163912
163816
  visitInstruction(instruction, state) {
163913
163817
  this.traverseInstruction(instruction, state);
163914
163818
  const {lvalue: lvalue, value: value} = instruction;
@@ -163982,16 +163886,16 @@ let Visitor$5 = class Visitor extends ReactiveFunctionVisitor {
163982
163886
  }
163983
163887
  }
163984
163888
  };
163985
- function pruneTemporaryLValues(fn) {
163889
+ function pruneUnusedLValues(fn) {
163986
163890
  const lvalues = new Map();
163987
- visitReactiveFunction(fn, new Visitor$4(), lvalues);
163891
+ visitReactiveFunction(fn, new Visitor$5(), lvalues);
163988
163892
  for (const [, instr] of lvalues) {
163989
163893
  instr.lvalue = null;
163990
163894
  }
163991
163895
  }
163992
- let Visitor$4 = class Visitor extends ReactiveFunctionVisitor {
163896
+ let Visitor$5 = class Visitor extends ReactiveFunctionVisitor {
163993
163897
  visitPlace(id, place, state) {
163994
- state.delete(place.identifier);
163898
+ state.delete(place.identifier.declarationId);
163995
163899
  }
163996
163900
  visitInstruction(instruction, state) {
163997
163901
  this.traverseInstruction(instruction, state);
@@ -163999,7 +163903,7 @@ let Visitor$4 = class Visitor extends ReactiveFunctionVisitor {
163999
163903
  instruction.lvalue !== null &&
164000
163904
  instruction.lvalue.identifier.name === null
164001
163905
  ) {
164002
- state.set(instruction.lvalue.identifier, instruction);
163906
+ state.set(instruction.lvalue.identifier.declarationId, instruction);
164003
163907
  }
164004
163908
  }
164005
163909
  };
@@ -164080,10 +163984,10 @@ function hasOwnDeclaration(block) {
164080
163984
  }
164081
163985
  function collectReferencedGlobals(fn) {
164082
163986
  const identifiers = new Set();
164083
- visitReactiveFunction(fn, new Visitor$3(), identifiers);
163987
+ visitReactiveFunction(fn, new Visitor$4(), identifiers);
164084
163988
  return identifiers;
164085
163989
  }
164086
- let Visitor$3 = class Visitor extends ReactiveFunctionVisitor {
163990
+ let Visitor$4 = class Visitor extends ReactiveFunctionVisitor {
164087
163991
  visitValue(id, value, state) {
164088
163992
  this.traverseValue(id, value, state);
164089
163993
  if (value.kind === 'FunctionExpression' || value.kind === 'ObjectMethod') {
@@ -164104,7 +164008,7 @@ var _Scopes_instances,
164104
164008
  function renameVariables(fn) {
164105
164009
  const globals = collectReferencedGlobals(fn);
164106
164010
  const scopes = new Scopes(globals);
164107
- renameVariablesImpl(fn, new Visitor$2(), scopes);
164011
+ renameVariablesImpl(fn, new Visitor$3(), scopes);
164108
164012
  return new Set([...scopes.names, ...globals]);
164109
164013
  }
164110
164014
  function renameVariablesImpl(fn, visitor, scopes) {
@@ -164119,7 +164023,7 @@ function renameVariablesImpl(fn, visitor, scopes) {
164119
164023
  visitReactiveFunction(fn, visitor, scopes);
164120
164024
  });
164121
164025
  }
164122
- let Visitor$2 = class Visitor extends ReactiveFunctionVisitor {
164026
+ let Visitor$3 = class Visitor extends ReactiveFunctionVisitor {
164123
164027
  visitParam(place, state) {
164124
164028
  state.visit(place.identifier);
164125
164029
  }
@@ -164168,7 +164072,7 @@ class Scopes {
164168
164072
  return;
164169
164073
  }
164170
164074
  const mappedName = __classPrivateFieldGet(this, _Scopes_seen, 'f').get(
164171
- identifier.id
164075
+ identifier.declarationId
164172
164076
  );
164173
164077
  if (mappedName !== undefined) {
164174
164078
  identifier.name = mappedName;
@@ -164199,12 +164103,12 @@ class Scopes {
164199
164103
  const identifierName = makeIdentifierName(name);
164200
164104
  identifier.name = identifierName;
164201
164105
  __classPrivateFieldGet(this, _Scopes_seen, 'f').set(
164202
- identifier.id,
164106
+ identifier.declarationId,
164203
164107
  identifierName
164204
164108
  );
164205
164109
  __classPrivateFieldGet(this, _Scopes_stack, 'f')
164206
164110
  .at(-1)
164207
- .set(identifierName.value, identifier.id);
164111
+ .set(identifierName.value, identifier.declarationId);
164208
164112
  this.names.add(identifierName.value);
164209
164113
  }
164210
164114
  enter(fn) {
@@ -164682,7 +164586,7 @@ function lower(func) {
164682
164586
  inferReferenceEffects(func, {isFunctionExpression: true});
164683
164587
  deadCodeElimination(func);
164684
164588
  inferMutableRanges(func);
164685
- leaveSSA(func);
164589
+ rewriteInstructionKindsBasedOnReassignment(func);
164686
164590
  inferReactiveScopeVariables(func);
164687
164591
  inferMutableContextVariables(func);
164688
164592
  }
@@ -164926,6 +164830,7 @@ function extractManualMemoizationArgs(instr, kind, sidemap) {
164926
164830
  function dropManualMemoization(func) {
164927
164831
  const isValidationEnabled =
164928
164832
  func.env.config.validatePreserveExistingMemoizationGuarantees ||
164833
+ func.env.config.validateNoSetStateInRender ||
164929
164834
  func.env.config.enablePreserveExistingMemoizationGuarantees;
164930
164835
  const sidemap = {
164931
164836
  functions: new Map(),
@@ -165360,20 +165265,7 @@ function rewriteBlock(env, block, returnTarget, returnValue) {
165360
165265
  block.instructions.push({
165361
165266
  id: makeInstructionId(0),
165362
165267
  loc: terminal.loc,
165363
- lvalue: {
165364
- effect: exports.Effect.Unknown,
165365
- identifier: {
165366
- id: env.nextIdentifierId,
165367
- mutableRange: {start: makeInstructionId(0), end: makeInstructionId(0)},
165368
- name: null,
165369
- scope: null,
165370
- type: makeType(),
165371
- loc: terminal.loc,
165372
- },
165373
- kind: 'Identifier',
165374
- reactive: false,
165375
- loc: terminal.loc,
165376
- },
165268
+ lvalue: createTemporaryPlace(env, terminal.loc),
165377
165269
  value: {
165378
165270
  kind: 'StoreLocal',
165379
165271
  lvalue: {
@@ -165397,20 +165289,7 @@ function declareTemporary(env, block, result) {
165397
165289
  block.instructions.push({
165398
165290
  id: makeInstructionId(0),
165399
165291
  loc: GeneratedSource,
165400
- lvalue: {
165401
- effect: exports.Effect.Unknown,
165402
- identifier: {
165403
- id: env.nextIdentifierId,
165404
- mutableRange: {start: makeInstructionId(0), end: makeInstructionId(0)},
165405
- name: null,
165406
- scope: null,
165407
- type: makeType(),
165408
- loc: result.loc,
165409
- },
165410
- kind: 'Identifier',
165411
- reactive: false,
165412
- loc: GeneratedSource,
165413
- },
165292
+ lvalue: createTemporaryPlace(env, result.loc),
165414
165293
  value: {
165415
165294
  kind: 'DeclareLocal',
165416
165295
  lvalue: {place: result, kind: InstructionKind.Let},
@@ -166073,7 +165952,7 @@ class Transform extends ReactiveFunctionTransform {
166073
165952
  return {kind: 'keep'};
166074
165953
  }
166075
165954
  }
166076
- let Visitor$1 = class Visitor extends ReactiveFunctionVisitor {
165955
+ let Visitor$2 = class Visitor extends ReactiveFunctionVisitor {
166077
165956
  constructor(env, aliases, paths) {
166078
165957
  super();
166079
165958
  this.map = new Map();
@@ -166215,7 +166094,7 @@ let Visitor$1 = class Visitor extends ReactiveFunctionVisitor {
166215
166094
  };
166216
166095
  function pruneInitializationDependencies(fn) {
166217
166096
  const [aliases, paths] = getAliases(fn);
166218
- visitReactiveFunction(fn, new Visitor$1(fn.env, aliases, paths), 'Update');
166097
+ visitReactiveFunction(fn, new Visitor$2(fn.env, aliases, paths), 'Update');
166219
166098
  }
166220
166099
  function update(map, key, path, value) {
166221
166100
  var _a;
@@ -167120,6 +166999,69 @@ function visitFunctionExpression(errors, fn) {
167120
166999
  }
167121
167000
  }
167122
167001
  }
167002
+ function validateMemoizedEffectDependencies(fn) {
167003
+ const errors = new CompilerError();
167004
+ visitReactiveFunction(fn, new Visitor$1(), errors);
167005
+ if (errors.hasErrors()) {
167006
+ throw errors;
167007
+ }
167008
+ }
167009
+ let Visitor$1 = class Visitor extends ReactiveFunctionVisitor {
167010
+ constructor() {
167011
+ super(...arguments);
167012
+ this.scopes = new Set();
167013
+ }
167014
+ visitScope(scopeBlock, state) {
167015
+ this.traverseScope(scopeBlock, state);
167016
+ let areDependenciesMemoized = true;
167017
+ for (const dep of scopeBlock.scope.dependencies) {
167018
+ if (isUnmemoized$1(dep.identifier, this.scopes)) {
167019
+ areDependenciesMemoized = false;
167020
+ break;
167021
+ }
167022
+ }
167023
+ if (areDependenciesMemoized) {
167024
+ this.scopes.add(scopeBlock.scope.id);
167025
+ for (const id of scopeBlock.scope.merged) {
167026
+ this.scopes.add(id);
167027
+ }
167028
+ }
167029
+ }
167030
+ visitInstruction(instruction, state) {
167031
+ this.traverseInstruction(instruction, state);
167032
+ if (
167033
+ instruction.value.kind === 'CallExpression' &&
167034
+ isEffectHook(instruction.value.callee.identifier) &&
167035
+ instruction.value.args.length >= 2
167036
+ ) {
167037
+ const deps = instruction.value.args[1];
167038
+ if (
167039
+ deps.kind === 'Identifier' &&
167040
+ (isMutable(instruction, deps) ||
167041
+ isUnmemoized$1(deps.identifier, this.scopes))
167042
+ ) {
167043
+ state.push({
167044
+ reason:
167045
+ 'React Compiler has skipped optimizing this component because the effect dependencies could not be memoized. Unmemoized effect dependencies can trigger an infinite loop or other unexpected behavior',
167046
+ description: null,
167047
+ severity: exports.ErrorSeverity.CannotPreserveMemoization,
167048
+ loc: typeof instruction.loc !== 'symbol' ? instruction.loc : null,
167049
+ suggestions: null,
167050
+ });
167051
+ }
167052
+ }
167053
+ }
167054
+ };
167055
+ function isUnmemoized$1(operand, scopes) {
167056
+ return operand.scope != null && !scopes.has(operand.scope.id);
167057
+ }
167058
+ function isEffectHook(identifier) {
167059
+ return (
167060
+ isUseEffectHookType(identifier) ||
167061
+ isUseLayoutEffectHookType(identifier) ||
167062
+ isUseInsertionEffectHookType(identifier)
167063
+ );
167064
+ }
167123
167065
  function validateNoCapitalizedCalls(fn) {
167124
167066
  var _a;
167125
167067
  const envConfig = fn.env.config;
@@ -167375,59 +167317,94 @@ function validateNoSetStateInRender(fn) {
167375
167317
  }
167376
167318
  function validateNoSetStateInRenderImpl(fn, unconditionalSetStateFunctions) {
167377
167319
  const unconditionalBlocks = computeUnconditionalBlocks(fn);
167320
+ let activeManualMemoId = null;
167378
167321
  const errors = new CompilerError();
167379
167322
  for (const [, block] of fn.body.blocks) {
167380
- if (unconditionalBlocks.has(block.id)) {
167381
- for (const instr of block.instructions) {
167382
- switch (instr.value.kind) {
167383
- case 'LoadLocal': {
167384
- if (
167385
- unconditionalSetStateFunctions.has(
167386
- instr.value.place.identifier.id
167387
- )
167388
- ) {
167389
- unconditionalSetStateFunctions.add(instr.lvalue.identifier.id);
167390
- }
167391
- break;
167323
+ for (const instr of block.instructions) {
167324
+ switch (instr.value.kind) {
167325
+ case 'LoadLocal': {
167326
+ if (
167327
+ unconditionalSetStateFunctions.has(instr.value.place.identifier.id)
167328
+ ) {
167329
+ unconditionalSetStateFunctions.add(instr.lvalue.identifier.id);
167392
167330
  }
167393
- case 'StoreLocal': {
167394
- if (
167395
- unconditionalSetStateFunctions.has(
167396
- instr.value.value.identifier.id
167397
- )
167398
- ) {
167399
- unconditionalSetStateFunctions.add(
167400
- instr.value.lvalue.place.identifier.id
167401
- );
167402
- unconditionalSetStateFunctions.add(instr.lvalue.identifier.id);
167403
- }
167404
- break;
167331
+ break;
167332
+ }
167333
+ case 'StoreLocal': {
167334
+ if (
167335
+ unconditionalSetStateFunctions.has(instr.value.value.identifier.id)
167336
+ ) {
167337
+ unconditionalSetStateFunctions.add(
167338
+ instr.value.lvalue.place.identifier.id
167339
+ );
167340
+ unconditionalSetStateFunctions.add(instr.lvalue.identifier.id);
167405
167341
  }
167406
- case 'ObjectMethod':
167407
- case 'FunctionExpression': {
167408
- if (
167409
- [...eachInstructionValueOperand(instr.value)].some(
167410
- operand =>
167411
- isSetStateType(operand.identifier) ||
167412
- unconditionalSetStateFunctions.has(operand.identifier.id)
167413
- ) &&
167414
- validateNoSetStateInRenderImpl(
167415
- instr.value.loweredFunc.func,
167416
- unconditionalSetStateFunctions
167417
- ).isErr()
167418
- ) {
167419
- unconditionalSetStateFunctions.add(instr.lvalue.identifier.id);
167420
- }
167421
- break;
167342
+ break;
167343
+ }
167344
+ case 'ObjectMethod':
167345
+ case 'FunctionExpression': {
167346
+ if (
167347
+ [...eachInstructionValueOperand(instr.value)].some(
167348
+ operand =>
167349
+ isSetStateType(operand.identifier) ||
167350
+ unconditionalSetStateFunctions.has(operand.identifier.id)
167351
+ ) &&
167352
+ validateNoSetStateInRenderImpl(
167353
+ instr.value.loweredFunc.func,
167354
+ unconditionalSetStateFunctions
167355
+ ).isErr()
167356
+ ) {
167357
+ unconditionalSetStateFunctions.add(instr.lvalue.identifier.id);
167422
167358
  }
167423
- case 'CallExpression': {
167424
- validateNonSetState(
167425
- errors,
167426
- unconditionalSetStateFunctions,
167427
- instr.value.callee
167428
- );
167429
- break;
167359
+ break;
167360
+ }
167361
+ case 'StartMemoize': {
167362
+ CompilerError.invariant(activeManualMemoId === null, {
167363
+ reason: 'Unexpected nested StartMemoize instructions',
167364
+ loc: instr.value.loc,
167365
+ });
167366
+ activeManualMemoId = instr.value.manualMemoId;
167367
+ break;
167368
+ }
167369
+ case 'FinishMemoize': {
167370
+ CompilerError.invariant(
167371
+ activeManualMemoId === instr.value.manualMemoId,
167372
+ {
167373
+ reason:
167374
+ 'Expected FinishMemoize to align with previous StartMemoize instruction',
167375
+ loc: instr.value.loc,
167376
+ }
167377
+ );
167378
+ activeManualMemoId = null;
167379
+ break;
167380
+ }
167381
+ case 'CallExpression': {
167382
+ const callee = instr.value.callee;
167383
+ if (
167384
+ isSetStateType(callee.identifier) ||
167385
+ unconditionalSetStateFunctions.has(callee.identifier.id)
167386
+ ) {
167387
+ if (activeManualMemoId !== null) {
167388
+ errors.push({
167389
+ reason:
167390
+ 'Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)',
167391
+ description: null,
167392
+ severity: exports.ErrorSeverity.InvalidReact,
167393
+ loc: callee.loc,
167394
+ suggestions: null,
167395
+ });
167396
+ } else if (unconditionalBlocks.has(block.id)) {
167397
+ errors.push({
167398
+ reason:
167399
+ 'This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)',
167400
+ description: null,
167401
+ severity: exports.ErrorSeverity.InvalidReact,
167402
+ loc: callee.loc,
167403
+ suggestions: null,
167404
+ });
167405
+ }
167430
167406
  }
167407
+ break;
167431
167408
  }
167432
167409
  }
167433
167410
  }
@@ -167438,21 +167415,6 @@ function validateNoSetStateInRenderImpl(fn, unconditionalSetStateFunctions) {
167438
167415
  return Ok(undefined);
167439
167416
  }
167440
167417
  }
167441
- function validateNonSetState(errors, unconditionalSetStateFunctions, operand) {
167442
- if (
167443
- isSetStateType(operand.identifier) ||
167444
- unconditionalSetStateFunctions.has(operand.identifier.id)
167445
- ) {
167446
- errors.push({
167447
- reason:
167448
- 'This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)',
167449
- description: null,
167450
- severity: exports.ErrorSeverity.InvalidReact,
167451
- loc: typeof operand.loc !== 'symbol' ? operand.loc : null,
167452
- suggestions: null,
167453
- });
167454
- }
167455
- }
167456
167418
  function validatePreservedManualMemoization(fn) {
167457
167419
  const state = {errors: new CompilerError(), manualMemoState: null};
167458
167420
  visitReactiveFunction(fn, new Visitor(), state);
@@ -167557,7 +167519,7 @@ function validateInferredDep(
167557
167519
  for (const decl of declsWithinMemoBlock) {
167558
167520
  if (
167559
167521
  normalizedDep.root.kind === 'NamedLocal' &&
167560
- decl === normalizedDep.root.value.identifier.id
167522
+ decl === normalizedDep.root.value.identifier.declarationId
167561
167523
  ) {
167562
167524
  return;
167563
167525
  }
@@ -167622,7 +167584,7 @@ class Visitor extends ReactiveFunctionVisitor {
167622
167584
  const storeTarget = value.lvalue.place;
167623
167585
  (_a = state.manualMemoState) === null || _a === void 0
167624
167586
  ? void 0
167625
- : _a.decls.add(storeTarget.identifier.id);
167587
+ : _a.decls.add(storeTarget.identifier.declarationId);
167626
167588
  if (
167627
167589
  ((_b = storeTarget.identifier.name) === null || _b === void 0
167628
167590
  ? void 0
@@ -167642,24 +167604,23 @@ class Visitor extends ReactiveFunctionVisitor {
167642
167604
  }
167643
167605
  }
167644
167606
  recordTemporaries(instr, state) {
167645
- var _a, _b, _c;
167607
+ var _a;
167646
167608
  const temporaries = this.temporaries;
167647
- const {value: value} = instr;
167609
+ const {lvalue: lvalue, value: value} = instr;
167648
167610
  const lvalId =
167649
- (_a = instr.lvalue) === null || _a === void 0 ? void 0 : _a.identifier.id;
167611
+ lvalue === null || lvalue === void 0 ? void 0 : lvalue.identifier.id;
167650
167612
  if (lvalId != null && temporaries.has(lvalId)) {
167651
167613
  return;
167652
167614
  }
167653
167615
  const isNamedLocal =
167654
- lvalId != null &&
167655
- ((_c =
167656
- (_b = instr.lvalue) === null || _b === void 0
167616
+ ((_a =
167617
+ lvalue === null || lvalue === void 0
167657
167618
  ? void 0
167658
- : _b.identifier.name) === null || _c === void 0
167619
+ : lvalue.identifier.name) === null || _a === void 0
167659
167620
  ? void 0
167660
- : _c.kind) === 'named';
167661
- if (isNamedLocal && state.manualMemoState != null) {
167662
- state.manualMemoState.decls.add(lvalId);
167621
+ : _a.kind) === 'named';
167622
+ if (lvalue !== null && isNamedLocal && state.manualMemoState != null) {
167623
+ state.manualMemoState.decls.add(lvalue.identifier.declarationId);
167663
167624
  }
167664
167625
  const maybeDep = this.recordDepsInValue(value, state);
167665
167626
  if (lvalId != null) {
@@ -167945,7 +167906,33 @@ function getContextReassignment(
167945
167906
  break;
167946
167907
  }
167947
167908
  default: {
167948
- for (const operand of eachInstructionValueOperand(value)) {
167909
+ let operands = eachInstructionValueOperand(value);
167910
+ if (value.kind === 'CallExpression') {
167911
+ const signature = getFunctionCallSignature(
167912
+ fn.env,
167913
+ value.callee.identifier.type
167914
+ );
167915
+ if (
167916
+ signature === null || signature === void 0
167917
+ ? void 0
167918
+ : signature.noAlias
167919
+ ) {
167920
+ operands = [value.callee];
167921
+ }
167922
+ } else if (value.kind === 'MethodCall') {
167923
+ const signature = getFunctionCallSignature(
167924
+ fn.env,
167925
+ value.property.identifier.type
167926
+ );
167927
+ if (
167928
+ signature === null || signature === void 0
167929
+ ? void 0
167930
+ : signature.noAlias
167931
+ ) {
167932
+ operands = [value.receiver, value.property];
167933
+ }
167934
+ }
167935
+ for (const operand of operands) {
167949
167936
  CompilerError.invariant(operand.effect !== exports.Effect.Unknown, {
167950
167937
  reason: `Expected effects to be inferred prior to ValidateLocalsNotReassignedAfterRender`,
167951
167938
  loc: operand.loc,
@@ -167953,11 +167940,14 @@ function getContextReassignment(
167953
167940
  const reassignment = reassigningFunctions.get(
167954
167941
  operand.identifier.id
167955
167942
  );
167956
- if (
167957
- reassignment !== undefined &&
167958
- operand.effect === exports.Effect.Freeze
167959
- ) {
167960
- return reassignment;
167943
+ if (reassignment !== undefined) {
167944
+ if (operand.effect === exports.Effect.Freeze) {
167945
+ return reassignment;
167946
+ } else {
167947
+ for (const lval of eachInstructionLValue(instr)) {
167948
+ reassigningFunctions.set(lval.identifier.id, reassignment);
167949
+ }
167950
+ }
167961
167951
  }
167962
167952
  }
167963
167953
  break;
@@ -167973,21 +167963,22 @@ function getContextReassignment(
167973
167963
  }
167974
167964
  return null;
167975
167965
  }
167976
- function outlineFunctions(fn) {
167966
+ function outlineFunctions(fn, fbtOperands) {
167977
167967
  for (const [, block] of fn.body.blocks) {
167978
167968
  for (const instr of block.instructions) {
167979
- const {value: value} = instr;
167969
+ const {value: value, lvalue: lvalue} = instr;
167980
167970
  if (
167981
167971
  value.kind === 'FunctionExpression' ||
167982
167972
  value.kind === 'ObjectMethod'
167983
167973
  ) {
167984
- outlineFunctions(value.loweredFunc.func);
167974
+ outlineFunctions(value.loweredFunc.func, fbtOperands);
167985
167975
  }
167986
167976
  if (
167987
167977
  value.kind === 'FunctionExpression' &&
167988
167978
  value.loweredFunc.dependencies.length === 0 &&
167989
167979
  value.loweredFunc.func.context.length === 0 &&
167990
- value.loweredFunc.func.id === null
167980
+ value.loweredFunc.func.id === null &&
167981
+ !fbtOperands.has(lvalue.identifier.id)
167991
167982
  ) {
167992
167983
  const loweredFunc = value.loweredFunc.func;
167993
167984
  const id = fn.env.generateGloballyUniqueIdentifierName(loweredFunc.id);
@@ -168002,6 +167993,232 @@ function outlineFunctions(fn) {
168002
167993
  }
168003
167994
  }
168004
167995
  }
167996
+ function propagatePhiTypes(fn) {
167997
+ const propagated = new Set();
167998
+ for (const [, block] of fn.body.blocks) {
167999
+ for (const phi of block.phis) {
168000
+ if (phi.id.type.kind !== 'Type' || phi.id.name !== null) {
168001
+ continue;
168002
+ }
168003
+ let type = null;
168004
+ for (const [, operand] of phi.operands) {
168005
+ if (type === null) {
168006
+ type = operand.type;
168007
+ } else if (!typeEquals(type, operand.type)) {
168008
+ type = null;
168009
+ break;
168010
+ }
168011
+ }
168012
+ if (type !== null) {
168013
+ phi.id.type = type;
168014
+ phi.type = type;
168015
+ propagated.add(phi.id.id);
168016
+ }
168017
+ }
168018
+ for (const instr of block.instructions) {
168019
+ const {value: value} = instr;
168020
+ switch (value.kind) {
168021
+ case 'StoreLocal': {
168022
+ const lvalue = value.lvalue.place;
168023
+ if (
168024
+ propagated.has(value.value.identifier.id) &&
168025
+ lvalue.identifier.type.kind === 'Type' &&
168026
+ lvalue.identifier.name === null
168027
+ ) {
168028
+ lvalue.identifier.type = value.value.identifier.type;
168029
+ propagated.add(lvalue.identifier.id);
168030
+ }
168031
+ }
168032
+ }
168033
+ }
168034
+ }
168035
+ }
168036
+ function lowerContextAccess(fn) {
168037
+ const contextAccess = new Map();
168038
+ const contextKeys = new Map();
168039
+ for (const [, block] of fn.body.blocks) {
168040
+ for (const instr of block.instructions) {
168041
+ const {value: value, lvalue: lvalue} = instr;
168042
+ if (
168043
+ value.kind === 'CallExpression' &&
168044
+ isUseContextHookType(value.callee.identifier)
168045
+ ) {
168046
+ contextAccess.set(lvalue.identifier.id, value);
168047
+ continue;
168048
+ }
168049
+ if (value.kind !== 'Destructure') {
168050
+ continue;
168051
+ }
168052
+ const destructureId = value.value.identifier.id;
168053
+ if (!contextAccess.has(destructureId)) {
168054
+ continue;
168055
+ }
168056
+ const keys = getContextKeys(value);
168057
+ if (keys === null) {
168058
+ return;
168059
+ }
168060
+ if (contextKeys.has(destructureId)) {
168061
+ return;
168062
+ } else {
168063
+ contextKeys.set(destructureId, keys);
168064
+ }
168065
+ }
168066
+ }
168067
+ if (contextAccess.size > 0) {
168068
+ for (const [, block] of fn.body.blocks) {
168069
+ let nextInstructions = null;
168070
+ for (let i = 0; i < block.instructions.length; i++) {
168071
+ const instr = block.instructions[i];
168072
+ const {lvalue: lvalue, value: value} = instr;
168073
+ if (
168074
+ value.kind === 'CallExpression' &&
168075
+ isUseContextHookType(value.callee.identifier) &&
168076
+ contextKeys.has(lvalue.identifier.id)
168077
+ ) {
168078
+ const keys = contextKeys.get(lvalue.identifier.id);
168079
+ const selectorFnInstr = emitSelectorFn(fn.env, keys);
168080
+ if (nextInstructions === null) {
168081
+ nextInstructions = block.instructions.slice(0, i);
168082
+ }
168083
+ nextInstructions.push(selectorFnInstr);
168084
+ const selectorFn = selectorFnInstr.lvalue;
168085
+ value.args.push(selectorFn);
168086
+ }
168087
+ if (nextInstructions) {
168088
+ nextInstructions.push(instr);
168089
+ }
168090
+ }
168091
+ if (nextInstructions) {
168092
+ block.instructions = nextInstructions;
168093
+ }
168094
+ }
168095
+ markInstructionIds(fn.body);
168096
+ }
168097
+ }
168098
+ function getContextKeys(value) {
168099
+ const keys = [];
168100
+ const pattern = value.lvalue.pattern;
168101
+ switch (pattern.kind) {
168102
+ case 'ArrayPattern': {
168103
+ return null;
168104
+ }
168105
+ case 'ObjectPattern': {
168106
+ for (const place of pattern.properties) {
168107
+ if (
168108
+ place.kind !== 'ObjectProperty' ||
168109
+ place.type !== 'property' ||
168110
+ place.key.kind !== 'identifier' ||
168111
+ place.place.identifier.name === null ||
168112
+ place.place.identifier.name.kind !== 'named'
168113
+ ) {
168114
+ return null;
168115
+ }
168116
+ keys.push(place.key.name);
168117
+ }
168118
+ return keys;
168119
+ }
168120
+ }
168121
+ }
168122
+ function emitPropertyLoad(env, obj, property) {
168123
+ const loadObj = {kind: 'LoadLocal', place: obj, loc: GeneratedSource};
168124
+ const object = createTemporaryPlace(env, GeneratedSource);
168125
+ const loadLocalInstr = {
168126
+ lvalue: object,
168127
+ value: loadObj,
168128
+ id: makeInstructionId(0),
168129
+ loc: GeneratedSource,
168130
+ };
168131
+ const loadProp = {
168132
+ kind: 'PropertyLoad',
168133
+ object: object,
168134
+ property: property,
168135
+ loc: GeneratedSource,
168136
+ };
168137
+ const element = createTemporaryPlace(env, GeneratedSource);
168138
+ const loadPropInstr = {
168139
+ lvalue: element,
168140
+ value: loadProp,
168141
+ id: makeInstructionId(0),
168142
+ loc: GeneratedSource,
168143
+ };
168144
+ return {instructions: [loadLocalInstr, loadPropInstr], element: element};
168145
+ }
168146
+ function emitSelectorFn(env, keys) {
168147
+ const obj = createTemporaryPlace(env, GeneratedSource);
168148
+ promoteTemporary(obj.identifier);
168149
+ const instr = [];
168150
+ const elements = [];
168151
+ for (const key of keys) {
168152
+ const {instructions: instructions, element: prop} = emitPropertyLoad(
168153
+ env,
168154
+ obj,
168155
+ key
168156
+ );
168157
+ instr.push(...instructions);
168158
+ elements.push(prop);
168159
+ }
168160
+ const arrayInstr = emitArrayInstr(elements, env);
168161
+ instr.push(arrayInstr);
168162
+ const block = {
168163
+ kind: 'block',
168164
+ id: makeBlockId(0),
168165
+ instructions: instr,
168166
+ terminal: {
168167
+ id: makeInstructionId(0),
168168
+ kind: 'return',
168169
+ loc: GeneratedSource,
168170
+ value: arrayInstr.lvalue,
168171
+ },
168172
+ preds: new Set(),
168173
+ phis: new Set(),
168174
+ };
168175
+ const fn = {
168176
+ loc: GeneratedSource,
168177
+ id: null,
168178
+ fnType: 'Other',
168179
+ env: env,
168180
+ params: [obj],
168181
+ returnType: null,
168182
+ context: [],
168183
+ effects: null,
168184
+ body: {entry: block.id, blocks: new Map([[block.id, block]])},
168185
+ generator: false,
168186
+ async: false,
168187
+ directives: [],
168188
+ };
168189
+ reversePostorderBlocks(fn.body);
168190
+ markInstructionIds(fn.body);
168191
+ enterSSA(fn);
168192
+ inferTypes(fn);
168193
+ const fnInstr = {
168194
+ id: makeInstructionId(0),
168195
+ value: {
168196
+ kind: 'FunctionExpression',
168197
+ name: null,
168198
+ loweredFunc: {func: fn, dependencies: []},
168199
+ type: 'ArrowFunctionExpression',
168200
+ loc: GeneratedSource,
168201
+ },
168202
+ lvalue: createTemporaryPlace(env, GeneratedSource),
168203
+ loc: GeneratedSource,
168204
+ };
168205
+ return fnInstr;
168206
+ }
168207
+ function emitArrayInstr(elements, env) {
168208
+ const array = {
168209
+ kind: 'ArrayExpression',
168210
+ elements: elements,
168211
+ loc: GeneratedSource,
168212
+ };
168213
+ const arrayLvalue = createTemporaryPlace(env, GeneratedSource);
168214
+ const arrayInstr = {
168215
+ id: makeInstructionId(0),
168216
+ value: array,
168217
+ lvalue: arrayLvalue,
168218
+ loc: GeneratedSource,
168219
+ };
168220
+ return arrayInstr;
168221
+ }
168005
168222
  function* run(
168006
168223
  func,
168007
168224
  config,
@@ -168022,11 +168239,11 @@ function* run(
168022
168239
  code,
168023
168240
  useMemoCacheIdentifier
168024
168241
  );
168025
- yield {
168242
+ yield log({
168026
168243
  kind: 'debug',
168027
168244
  name: 'EnvironmentConfig',
168028
168245
  value: prettyFormat$1(env.config),
168029
- };
168246
+ });
168030
168247
  const ast = yield* runWithEnvironment(func, env);
168031
168248
  return ast;
168032
168249
  }
@@ -168070,6 +168287,9 @@ function* runWithEnvironment(func, env) {
168070
168287
  if (env.config.validateNoCapitalizedCalls) {
168071
168288
  validateNoCapitalizedCalls(hir);
168072
168289
  }
168290
+ if (env.config.enableLowerContextAccess) {
168291
+ lowerContextAccess(hir);
168292
+ }
168073
168293
  analyseFunctions(hir);
168074
168294
  yield log({kind: 'hir', name: 'AnalyseFunctions', value: hir});
168075
168295
  inferReferenceEffects(hir);
@@ -168096,24 +168316,30 @@ function* runWithEnvironment(func, env) {
168096
168316
  }
168097
168317
  inferReactivePlaces(hir);
168098
168318
  yield log({kind: 'hir', name: 'InferReactivePlaces', value: hir});
168099
- leaveSSA(hir);
168100
- yield log({kind: 'hir', name: 'LeaveSSA', value: hir});
168319
+ rewriteInstructionKindsBasedOnReassignment(hir);
168320
+ yield log({
168321
+ kind: 'hir',
168322
+ name: 'RewriteInstructionKindsBasedOnReassignment',
168323
+ value: hir,
168324
+ });
168325
+ propagatePhiTypes(hir);
168326
+ yield log({kind: 'hir', name: 'PropagatePhiTypes', value: hir});
168101
168327
  inferReactiveScopeVariables(hir);
168102
168328
  yield log({kind: 'hir', name: 'InferReactiveScopeVariables', value: hir});
168329
+ const fbtOperands = memoizeFbtAndMacroOperandsInSameScope(hir);
168330
+ yield log({
168331
+ kind: 'hir',
168332
+ name: 'MemoizeFbtAndMacroOperandsInSameScope',
168333
+ value: hir,
168334
+ });
168103
168335
  if (env.config.enableFunctionOutlining) {
168104
- outlineFunctions(hir);
168336
+ outlineFunctions(hir, fbtOperands);
168105
168337
  yield log({kind: 'hir', name: 'OutlineFunctions', value: hir});
168106
168338
  }
168107
168339
  alignMethodCallScopes(hir);
168108
168340
  yield log({kind: 'hir', name: 'AlignMethodCallScopes', value: hir});
168109
168341
  alignObjectMethodScopes(hir);
168110
168342
  yield log({kind: 'hir', name: 'AlignObjectMethodScopes', value: hir});
168111
- const fbtOperands = memoizeFbtAndMacroOperandsInSameScope(hir);
168112
- yield log({
168113
- kind: 'hir',
168114
- name: 'MemoizeFbtAndMacroOperandsInSameScope',
168115
- value: hir,
168116
- });
168117
168343
  if (env.config.enableReactiveScopesInHIR) {
168118
168344
  pruneUnusedLabelsHIR(hir);
168119
168345
  yield log({kind: 'hir', name: 'PruneUnusedLabelsHIR', value: hir});
@@ -168250,7 +168476,7 @@ function* runWithEnvironment(func, env) {
168250
168476
  name: 'PromoteUsedTemporaries',
168251
168477
  value: reactiveFunction,
168252
168478
  });
168253
- pruneTemporaryLValues(reactiveFunction);
168479
+ pruneUnusedLValues(reactiveFunction);
168254
168480
  yield log({
168255
168481
  kind: 'reactive',
168256
168482
  name: 'PruneUnusedLValues',