babel-plugin-react-compiler 0.0.0-experimental-de2cfda-20240912 → 0.0.0-experimental-ca8e0be-20240916

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
@@ -139601,6 +139601,8 @@ var InstructionKind;
139601
139601
  InstructionKind['Catch'] = 'Catch';
139602
139602
  InstructionKind['HoistedConst'] = 'HoistedConst';
139603
139603
  InstructionKind['HoistedLet'] = 'HoistedLet';
139604
+ InstructionKind['HoistedFunction'] = 'HoistedFunction';
139605
+ InstructionKind['Function'] = 'Function';
139604
139606
  })(InstructionKind || (InstructionKind = {}));
139605
139607
  function makeTemporaryIdentifier(id, loc) {
139606
139608
  return {
@@ -144017,7 +144019,14 @@ function lowerStatement(builder, stmtPath, label = null) {
144017
144019
  if (builder.environment.isHoistedIdentifier(binding.identifier)) {
144018
144020
  continue;
144019
144021
  }
144020
- if (!binding.path.isVariableDeclarator()) {
144022
+ let kind;
144023
+ if (binding.kind === 'const' || binding.kind === 'var') {
144024
+ kind = InstructionKind.HoistedConst;
144025
+ } else if (binding.kind === 'let') {
144026
+ kind = InstructionKind.HoistedLet;
144027
+ } else if (binding.path.isFunctionDeclaration()) {
144028
+ kind = InstructionKind.HoistedFunction;
144029
+ } else if (!binding.path.isVariableDeclarator()) {
144021
144030
  builder.errors.push({
144022
144031
  severity: exports.ErrorSeverity.Todo,
144023
144032
  reason: 'Unsupported declaration type for hoisting',
@@ -144029,11 +144038,7 @@ function lowerStatement(builder, stmtPath, label = null) {
144029
144038
  : GeneratedSource,
144030
144039
  });
144031
144040
  continue;
144032
- } else if (
144033
- binding.kind !== 'const' &&
144034
- binding.kind !== 'var' &&
144035
- binding.kind !== 'let'
144036
- ) {
144041
+ } else {
144037
144042
  builder.errors.push({
144038
144043
  severity: exports.ErrorSeverity.Todo,
144039
144044
  reason: 'Handle non-const declarations for hoisting',
@@ -144065,12 +144070,6 @@ function lowerStatement(builder, stmtPath, label = null) {
144065
144070
  ? _j
144066
144071
  : GeneratedSource,
144067
144072
  };
144068
- const kind =
144069
- binding.kind === 'const' || binding.kind === 'var'
144070
- ? InstructionKind.HoistedConst
144071
- : binding.kind === 'let'
144072
- ? InstructionKind.HoistedLet
144073
- : assertExhaustive(binding.kind, 'Unexpected binding kind');
144074
144073
  lowerValueToTemporary(builder, {
144075
144074
  kind: 'DeclareContext',
144076
144075
  lvalue: {kind: kind, place: place},
@@ -144615,7 +144614,7 @@ function lowerStatement(builder, stmtPath, label = null) {
144615
144614
  (_10 = stmt.node.loc) !== null && _10 !== void 0
144616
144615
  ? _10
144617
144616
  : GeneratedSource,
144618
- InstructionKind.Let,
144617
+ InstructionKind.Function,
144619
144618
  id,
144620
144619
  fn,
144621
144620
  'Assignment'
@@ -150159,6 +150158,17 @@ const REACT_APIS = [
150159
150158
  returnValueKind: exports.ValueKind.Mutable,
150160
150159
  }),
150161
150160
  ],
150161
+ [
150162
+ 'useImperativeHandle',
150163
+ addHook(DEFAULT_SHAPES, {
150164
+ positionalParams: [],
150165
+ restParam: exports.Effect.Freeze,
150166
+ returnType: {kind: 'Primitive'},
150167
+ calleeEffect: exports.Effect.Read,
150168
+ hookKind: 'useImperativeHandle',
150169
+ returnValueKind: exports.ValueKind.Frozen,
150170
+ }),
150171
+ ],
150162
150172
  [
150163
150173
  'useMemo',
150164
150174
  addHook(DEFAULT_SHAPES, {
@@ -157991,22 +158001,12 @@ function codegenTerminal(cx, terminal) {
157991
158001
  suggestions: null,
157992
158002
  });
157993
158003
  case InstructionKind.Catch:
157994
- CompilerError.invariant(false, {
157995
- reason: 'Unexpected catch variable as for..in collection',
157996
- description: null,
157997
- loc: iterableItem.loc,
157998
- suggestions: null,
157999
- });
158000
158004
  case InstructionKind.HoistedConst:
158001
- CompilerError.invariant(false, {
158002
- reason: 'Unexpected HoistedConst variable in for..in collection',
158003
- description: null,
158004
- loc: iterableItem.loc,
158005
- suggestions: null,
158006
- });
158007
158005
  case InstructionKind.HoistedLet:
158006
+ case InstructionKind.HoistedFunction:
158007
+ case InstructionKind.Function:
158008
158008
  CompilerError.invariant(false, {
158009
- reason: 'Unexpected HoistedLet variable in for..in collection',
158009
+ reason: `Unexpected ${iterableItem.value.lvalue.kind} variable in for..in collection`,
158010
158010
  description: null,
158011
158011
  loc: iterableItem.loc,
158012
158012
  suggestions: null,
@@ -158080,30 +158080,13 @@ function codegenTerminal(cx, terminal) {
158080
158080
  varDeclKind = 'let';
158081
158081
  break;
158082
158082
  case InstructionKind.Reassign:
158083
- CompilerError.invariant(false, {
158084
- reason:
158085
- 'Destructure should never be Reassign as it would be an Object/ArrayPattern',
158086
- description: null,
158087
- loc: iterableItem.loc,
158088
- suggestions: null,
158089
- });
158090
158083
  case InstructionKind.Catch:
158091
- CompilerError.invariant(false, {
158092
- reason: 'Unexpected catch variable as for..of collection',
158093
- description: null,
158094
- loc: iterableItem.loc,
158095
- suggestions: null,
158096
- });
158097
158084
  case InstructionKind.HoistedConst:
158098
- CompilerError.invariant(false, {
158099
- reason: 'Unexpected HoistedConst variable in for..of collection',
158100
- description: null,
158101
- loc: iterableItem.loc,
158102
- suggestions: null,
158103
- });
158104
158085
  case InstructionKind.HoistedLet:
158086
+ case InstructionKind.HoistedFunction:
158087
+ case InstructionKind.Function:
158105
158088
  CompilerError.invariant(false, {
158106
- reason: 'Unexpected HoistedLet variable in for..of collection',
158089
+ reason: `Unexpected ${iterableItem.value.lvalue.kind} variable in for..of collection`,
158107
158090
  description: null,
158108
158091
  loc: iterableItem.loc,
158109
158092
  suggestions: null,
@@ -158262,6 +158245,39 @@ function codegenInstructionNullable(cx, instr) {
158262
158245
  t__namespace.variableDeclarator(codegenLValue(cx, lvalue), value),
158263
158246
  ]);
158264
158247
  }
158248
+ case InstructionKind.Function: {
158249
+ CompilerError.invariant(instr.lvalue === null, {
158250
+ reason: `Function declaration cannot be referenced as an expression`,
158251
+ description: null,
158252
+ loc: instr.value.loc,
158253
+ suggestions: null,
158254
+ });
158255
+ const genLvalue = codegenLValue(cx, lvalue);
158256
+ CompilerError.invariant(genLvalue.type === 'Identifier', {
158257
+ reason: 'Expected an identifier as a function declaration lvalue',
158258
+ description: null,
158259
+ loc: instr.value.loc,
158260
+ suggestions: null,
158261
+ });
158262
+ CompilerError.invariant(
158263
+ (value === null || value === void 0 ? void 0 : value.type) ===
158264
+ 'FunctionExpression',
158265
+ {
158266
+ reason: 'Expected a function as a function declaration value',
158267
+ description: null,
158268
+ loc: instr.value.loc,
158269
+ suggestions: null,
158270
+ }
158271
+ );
158272
+ return createFunctionDeclaration(
158273
+ instr.loc,
158274
+ genLvalue,
158275
+ value.params,
158276
+ value.body,
158277
+ value.generator,
158278
+ value.async
158279
+ );
158280
+ }
158265
158281
  case InstructionKind.Let: {
158266
158282
  CompilerError.invariant(instr.lvalue === null, {
158267
158283
  reason: `Const declaration cannot be referenced as an expression`,
@@ -158303,19 +158319,11 @@ function codegenInstructionNullable(cx, instr) {
158303
158319
  case InstructionKind.Catch: {
158304
158320
  return t__namespace.emptyStatement();
158305
158321
  }
158306
- case InstructionKind.HoistedLet: {
158307
- CompilerError.invariant(false, {
158308
- reason:
158309
- 'Expected HoistedLet to have been pruned in PruneHoistedContexts',
158310
- description: null,
158311
- loc: instr.loc,
158312
- suggestions: null,
158313
- });
158314
- }
158315
- case InstructionKind.HoistedConst: {
158322
+ case InstructionKind.HoistedLet:
158323
+ case InstructionKind.HoistedConst:
158324
+ case InstructionKind.HoistedFunction: {
158316
158325
  CompilerError.invariant(false, {
158317
- reason:
158318
- 'Expected HoistedConsts to have been pruned in PruneHoistedContexts',
158326
+ reason: `Expected ${kind} to have been pruned in PruneHoistedContexts`,
158319
158327
  description: null,
158320
158328
  loc: instr.loc,
158321
158329
  suggestions: null,
@@ -158463,6 +158471,7 @@ function withLoc(fn) {
158463
158471
  const createBinaryExpression = withLoc(t__namespace.binaryExpression);
158464
158472
  const createExpressionStatement = withLoc(t__namespace.expressionStatement);
158465
158473
  const createVariableDeclaration = withLoc(t__namespace.variableDeclaration);
158474
+ const createFunctionDeclaration = withLoc(t__namespace.functionDeclaration);
158466
158475
  const createTaggedTemplateExpression = withLoc(
158467
158476
  t__namespace.taggedTemplateExpression
158468
158477
  );
@@ -162063,6 +162072,16 @@ let Visitor$8 = class Visitor extends ReactiveFunctionTransform {
162063
162072
  );
162064
162073
  return {kind: 'remove'};
162065
162074
  }
162075
+ if (
162076
+ instruction.value.kind === 'DeclareContext' &&
162077
+ instruction.value.lvalue.kind === 'HoistedFunction'
162078
+ ) {
162079
+ state.set(
162080
+ instruction.value.lvalue.place.identifier.declarationId,
162081
+ InstructionKind.Function
162082
+ );
162083
+ return {kind: 'remove'};
162084
+ }
162066
162085
  if (
162067
162086
  instruction.value.kind === 'StoreContext' &&
162068
162087
  state.has(instruction.value.lvalue.place.identifier.declarationId)
@@ -162090,6 +162109,248 @@ let Visitor$8 = class Visitor extends ReactiveFunctionTransform {
162090
162109
  return {kind: 'keep'};
162091
162110
  }
162092
162111
  };
162112
+ function inferOperandEffect(state, place) {
162113
+ const value = state.kind(place);
162114
+ CompilerError.invariant(value != null, {
162115
+ reason: 'Expected operand to have a kind',
162116
+ loc: null,
162117
+ });
162118
+ switch (place.effect) {
162119
+ case exports.Effect.Store:
162120
+ case exports.Effect.Mutate: {
162121
+ if (isRefOrRefValue(place.identifier)) {
162122
+ break;
162123
+ } else if (value.kind === exports.ValueKind.Context) {
162124
+ return {
162125
+ kind: 'ContextMutation',
162126
+ loc: place.loc,
162127
+ effect: place.effect,
162128
+ places: value.context.size === 0 ? new Set([place]) : value.context,
162129
+ };
162130
+ } else if (
162131
+ value.kind !== exports.ValueKind.Mutable &&
162132
+ value.kind !== exports.ValueKind.Primitive
162133
+ ) {
162134
+ let reason = getWriteErrorReason(value);
162135
+ return {
162136
+ kind:
162137
+ value.reason.size === 1 && value.reason.has(ValueReason.Global)
162138
+ ? 'GlobalMutation'
162139
+ : 'ReactMutation',
162140
+ error: {
162141
+ reason: reason,
162142
+ description:
162143
+ place.identifier.name !== null &&
162144
+ place.identifier.name.kind === 'named'
162145
+ ? `Found mutation of \`${place.identifier.name.value}\``
162146
+ : null,
162147
+ loc: place.loc,
162148
+ suggestions: null,
162149
+ severity: exports.ErrorSeverity.InvalidReact,
162150
+ },
162151
+ };
162152
+ }
162153
+ break;
162154
+ }
162155
+ }
162156
+ return null;
162157
+ }
162158
+ function inheritFunctionEffects(state, place) {
162159
+ const effects = inferFunctionInstrEffects(state, place);
162160
+ return effects
162161
+ .flatMap(effect => {
162162
+ if (effect.kind === 'GlobalMutation' || effect.kind === 'ReactMutation') {
162163
+ return [effect];
162164
+ } else {
162165
+ const effects = [];
162166
+ CompilerError.invariant(effect.kind === 'ContextMutation', {
162167
+ reason: 'Expected ContextMutation',
162168
+ loc: null,
162169
+ });
162170
+ for (const place of effect.places) {
162171
+ if (state.isDefined(place)) {
162172
+ const replayedEffect = inferOperandEffect(
162173
+ state,
162174
+ Object.assign(Object.assign({}, place), {
162175
+ loc: effect.loc,
162176
+ effect: effect.effect,
162177
+ })
162178
+ );
162179
+ if (replayedEffect != null) {
162180
+ if (replayedEffect.kind === 'ContextMutation') {
162181
+ effects.push(effect);
162182
+ } else {
162183
+ effects.push(replayedEffect);
162184
+ }
162185
+ }
162186
+ }
162187
+ }
162188
+ return effects;
162189
+ }
162190
+ })
162191
+ .filter(effect => effect != null);
162192
+ }
162193
+ function inferFunctionInstrEffects(state, place) {
162194
+ const effects = [];
162195
+ const instrs = state.values(place);
162196
+ CompilerError.invariant(instrs != null, {
162197
+ reason: 'Expected operand to have instructions',
162198
+ loc: null,
162199
+ });
162200
+ for (const instr of instrs) {
162201
+ if (
162202
+ (instr.kind === 'FunctionExpression' || instr.kind === 'ObjectMethod') &&
162203
+ instr.loweredFunc.func.effects != null
162204
+ ) {
162205
+ effects.push(...instr.loweredFunc.func.effects);
162206
+ }
162207
+ }
162208
+ return effects;
162209
+ }
162210
+ function operandEffects(state, place, filterRenderSafe) {
162211
+ const functionEffects = [];
162212
+ const effect = inferOperandEffect(state, place);
162213
+ effect && functionEffects.push(effect);
162214
+ functionEffects.push(...inheritFunctionEffects(state, place));
162215
+ if (filterRenderSafe) {
162216
+ return functionEffects.filter(effect => !isEffectSafeOutsideRender(effect));
162217
+ } else {
162218
+ return functionEffects;
162219
+ }
162220
+ }
162221
+ function inferInstructionFunctionEffects(env, state, instr) {
162222
+ var _a, _b;
162223
+ var _c;
162224
+ const functionEffects = [];
162225
+ switch (instr.value.kind) {
162226
+ case 'JsxExpression': {
162227
+ if (instr.value.tag.kind === 'Identifier') {
162228
+ functionEffects.push(...operandEffects(state, instr.value.tag, false));
162229
+ }
162230
+ (_a = instr.value.children) === null || _a === void 0
162231
+ ? void 0
162232
+ : _a.forEach(child =>
162233
+ functionEffects.push(...operandEffects(state, child, false))
162234
+ );
162235
+ for (const attr of instr.value.props) {
162236
+ if (attr.kind === 'JsxSpreadAttribute') {
162237
+ functionEffects.push(...operandEffects(state, attr.argument, false));
162238
+ } else {
162239
+ functionEffects.push(...operandEffects(state, attr.place, true));
162240
+ }
162241
+ }
162242
+ break;
162243
+ }
162244
+ case 'ObjectMethod':
162245
+ case 'FunctionExpression': {
162246
+ for (const operand of eachInstructionOperand(instr)) {
162247
+ (_b = (_c = instr.value.loweredFunc.func).effects) !== null &&
162248
+ _b !== void 0
162249
+ ? _b
162250
+ : (_c.effects = []);
162251
+ instr.value.loweredFunc.func.effects.push(
162252
+ ...inferFunctionInstrEffects(state, operand)
162253
+ );
162254
+ }
162255
+ break;
162256
+ }
162257
+ case 'MethodCall':
162258
+ case 'CallExpression': {
162259
+ let callee;
162260
+ if (instr.value.kind === 'MethodCall') {
162261
+ callee = instr.value.property;
162262
+ functionEffects.push(
162263
+ ...operandEffects(state, instr.value.receiver, false)
162264
+ );
162265
+ } else {
162266
+ callee = instr.value.callee;
162267
+ }
162268
+ functionEffects.push(...operandEffects(state, callee, false));
162269
+ let isHook = getHookKind(env, callee.identifier) != null;
162270
+ for (const arg of instr.value.args) {
162271
+ const place = arg.kind === 'Identifier' ? arg : arg.place;
162272
+ functionEffects.push(...operandEffects(state, place, isHook));
162273
+ }
162274
+ break;
162275
+ }
162276
+ case 'StartMemoize':
162277
+ case 'FinishMemoize':
162278
+ case 'LoadLocal':
162279
+ case 'StoreLocal': {
162280
+ break;
162281
+ }
162282
+ case 'StoreGlobal': {
162283
+ functionEffects.push({
162284
+ kind: 'GlobalMutation',
162285
+ error: {
162286
+ reason:
162287
+ 'Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)',
162288
+ loc: instr.loc,
162289
+ suggestions: null,
162290
+ severity: exports.ErrorSeverity.InvalidReact,
162291
+ },
162292
+ });
162293
+ break;
162294
+ }
162295
+ default: {
162296
+ for (const operand of eachInstructionOperand(instr)) {
162297
+ functionEffects.push(...operandEffects(state, operand, false));
162298
+ }
162299
+ }
162300
+ }
162301
+ return functionEffects;
162302
+ }
162303
+ function inferTerminalFunctionEffects(state, block) {
162304
+ const functionEffects = [];
162305
+ for (const operand of eachTerminalOperand(block.terminal)) {
162306
+ functionEffects.push(...operandEffects(state, operand, true));
162307
+ }
162308
+ return functionEffects;
162309
+ }
162310
+ function raiseFunctionEffectErrors(functionEffects) {
162311
+ functionEffects.forEach(eff => {
162312
+ switch (eff.kind) {
162313
+ case 'ReactMutation':
162314
+ case 'GlobalMutation': {
162315
+ CompilerError.throw(eff.error);
162316
+ }
162317
+ case 'ContextMutation': {
162318
+ CompilerError.throw({
162319
+ severity: exports.ErrorSeverity.Invariant,
162320
+ reason: `Unexpected ContextMutation in top-level function effects`,
162321
+ loc: eff.loc,
162322
+ });
162323
+ }
162324
+ default:
162325
+ assertExhaustive(
162326
+ eff,
162327
+ `Unexpected function effect kind \`${eff.kind}\``
162328
+ );
162329
+ }
162330
+ });
162331
+ }
162332
+ function isEffectSafeOutsideRender(effect) {
162333
+ return effect.kind === 'GlobalMutation';
162334
+ }
162335
+ function getWriteErrorReason(abstractValue) {
162336
+ if (abstractValue.reason.has(ValueReason.Global)) {
162337
+ return 'Writing to a variable defined outside a component or hook is not allowed. Consider using an effect';
162338
+ } else if (abstractValue.reason.has(ValueReason.JsxCaptured)) {
162339
+ return 'Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX';
162340
+ } else if (abstractValue.reason.has(ValueReason.Context)) {
162341
+ return `Mutating a value returned from 'useContext()', which should not be mutated`;
162342
+ } else if (abstractValue.reason.has(ValueReason.KnownReturnSignature)) {
162343
+ return 'Mutating a value returned from a function whose return value should not be mutated';
162344
+ } else if (abstractValue.reason.has(ValueReason.ReactiveFunctionArgument)) {
162345
+ return 'Mutating component props or hook arguments is not allowed. Consider using a local variable instead';
162346
+ } else if (abstractValue.reason.has(ValueReason.State)) {
162347
+ return "Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead";
162348
+ } else if (abstractValue.reason.has(ValueReason.ReducerState)) {
162349
+ return "Mutating a value returned from 'useReducer()', which should not be mutated. Use the dispatch function to update instead";
162350
+ } else {
162351
+ return 'This mutates a variable that React considers immutable';
162352
+ }
162353
+ }
162093
162354
  var _InferenceState_env, _InferenceState_values, _InferenceState_variables;
162094
162355
  const UndefinedValue = {
162095
162356
  kind: 'Primitive',
@@ -162189,35 +162450,16 @@ function inferReferenceEffects(fn, options = {isFunctionExpression: false}) {
162189
162450
  }
162190
162451
  statesByBlock.set(blockId, incomingState);
162191
162452
  const state = incomingState.clone();
162192
- inferBlock(fn.env, functionEffects, state, block);
162453
+ inferBlock(fn.env, state, block, functionEffects);
162193
162454
  for (const nextBlockId of eachTerminalSuccessor(block.terminal)) {
162194
162455
  queue(nextBlockId, state);
162195
162456
  }
162196
162457
  }
162197
162458
  }
162198
- if (!options.isFunctionExpression) {
162199
- functionEffects.forEach(eff => {
162200
- switch (eff.kind) {
162201
- case 'ReactMutation':
162202
- case 'GlobalMutation': {
162203
- CompilerError.throw(eff.error);
162204
- }
162205
- case 'ContextMutation': {
162206
- CompilerError.throw({
162207
- severity: exports.ErrorSeverity.Invariant,
162208
- reason: `Unexpected ContextMutation in top-level function effects`,
162209
- loc: eff.loc,
162210
- });
162211
- }
162212
- default:
162213
- assertExhaustive(
162214
- eff,
162215
- `Unexpected function effect kind \`${eff.kind}\``
162216
- );
162217
- }
162218
- });
162219
- } else {
162459
+ if (options.isFunctionExpression) {
162220
162460
  fn.effects = functionEffects;
162461
+ } else {
162462
+ raiseFunctionEffectErrors(functionEffects);
162221
162463
  }
162222
162464
  }
162223
162465
  class InferenceState {
@@ -162323,7 +162565,7 @@ class InferenceState {
162323
162565
  place.identifier.id
162324
162566
  );
162325
162567
  }
162326
- referenceAndRecordEffects(place, effectKind, reason, functionEffects) {
162568
+ referenceAndRecordEffects(freezeActions, place, effectKind, reason) {
162327
162569
  const values = __classPrivateFieldGet(
162328
162570
  this,
162329
162571
  _InferenceState_variables,
@@ -162342,43 +162584,8 @@ class InferenceState {
162342
162584
  : exports.Effect.Read;
162343
162585
  return;
162344
162586
  }
162345
- for (const value of values) {
162346
- if (
162347
- (value.kind === 'FunctionExpression' ||
162348
- value.kind === 'ObjectMethod') &&
162349
- value.loweredFunc.func.effects != null
162350
- ) {
162351
- for (const effect of value.loweredFunc.func.effects) {
162352
- if (
162353
- effect.kind === 'GlobalMutation' ||
162354
- effect.kind === 'ReactMutation'
162355
- ) {
162356
- functionEffects.push(effect);
162357
- } else {
162358
- for (const place of effect.places) {
162359
- if (this.isDefined(place)) {
162360
- const replayedEffect = this.reference(
162361
- Object.assign(Object.assign({}, place), {loc: effect.loc}),
162362
- effect.effect,
162363
- reason
162364
- );
162365
- if (replayedEffect != null) {
162366
- if (replayedEffect.kind === 'ContextMutation') {
162367
- functionEffects.push(effect);
162368
- } else {
162369
- functionEffects.push(replayedEffect);
162370
- }
162371
- }
162372
- }
162373
- }
162374
- }
162375
- }
162376
- }
162377
- }
162378
- const functionEffect = this.reference(place, effectKind, reason);
162379
- if (functionEffect !== null) {
162380
- functionEffects.push(functionEffect);
162381
- }
162587
+ const action = this.reference(place, effectKind, reason);
162588
+ action && freezeActions.push(action);
162382
162589
  }
162383
162590
  freezeValues(values, reason) {
162384
162591
  for (const value of values) {
@@ -162424,7 +162631,7 @@ class InferenceState {
162424
162631
  });
162425
162632
  let valueKind = this.kind(place);
162426
162633
  let effect = null;
162427
- let functionEffect = null;
162634
+ let freeze = null;
162428
162635
  switch (effectKind) {
162429
162636
  case exports.Effect.Freeze: {
162430
162637
  if (
@@ -162439,7 +162646,7 @@ class InferenceState {
162439
162646
  reason: reasonSet,
162440
162647
  context: new Set(),
162441
162648
  };
162442
- this.freezeValues(values, reasonSet);
162649
+ freeze = {values: values, reason: reasonSet};
162443
162650
  } else {
162444
162651
  effect = exports.Effect.Read;
162445
162652
  }
@@ -162457,80 +162664,10 @@ class InferenceState {
162457
162664
  break;
162458
162665
  }
162459
162666
  case exports.Effect.Mutate: {
162460
- if (isRefOrRefValue(place.identifier));
162461
- else if (valueKind.kind === exports.ValueKind.Context) {
162462
- functionEffect = {
162463
- kind: 'ContextMutation',
162464
- loc: place.loc,
162465
- effect: effectKind,
162466
- places:
162467
- valueKind.context.size === 0
162468
- ? new Set([place])
162469
- : valueKind.context,
162470
- };
162471
- } else if (
162472
- valueKind.kind !== exports.ValueKind.Mutable &&
162473
- valueKind.kind !== exports.ValueKind.Primitive
162474
- ) {
162475
- let reason = getWriteErrorReason(valueKind);
162476
- functionEffect = {
162477
- kind:
162478
- valueKind.reason.size === 1 &&
162479
- valueKind.reason.has(ValueReason.Global)
162480
- ? 'GlobalMutation'
162481
- : 'ReactMutation',
162482
- error: {
162483
- reason: reason,
162484
- description:
162485
- place.identifier.name !== null &&
162486
- place.identifier.name.kind === 'named'
162487
- ? `Found mutation of \`${place.identifier.name.value}\``
162488
- : null,
162489
- loc: place.loc,
162490
- suggestions: null,
162491
- severity: exports.ErrorSeverity.InvalidReact,
162492
- },
162493
- };
162494
- }
162495
162667
  effect = exports.Effect.Mutate;
162496
162668
  break;
162497
162669
  }
162498
162670
  case exports.Effect.Store: {
162499
- if (isRefOrRefValue(place.identifier));
162500
- else if (valueKind.kind === exports.ValueKind.Context) {
162501
- functionEffect = {
162502
- kind: 'ContextMutation',
162503
- loc: place.loc,
162504
- effect: effectKind,
162505
- places:
162506
- valueKind.context.size === 0
162507
- ? new Set([place])
162508
- : valueKind.context,
162509
- };
162510
- } else if (
162511
- valueKind.kind !== exports.ValueKind.Mutable &&
162512
- valueKind.kind !== exports.ValueKind.Primitive
162513
- ) {
162514
- let reason = getWriteErrorReason(valueKind);
162515
- functionEffect = {
162516
- kind:
162517
- valueKind.reason.size === 1 &&
162518
- valueKind.reason.has(ValueReason.Global)
162519
- ? 'GlobalMutation'
162520
- : 'ReactMutation',
162521
- error: {
162522
- reason: reason,
162523
- description:
162524
- place.identifier.name !== null &&
162525
- place.identifier.name.kind === 'named'
162526
- ? `Found mutation of \`${place.identifier.name.value}\``
162527
- : null,
162528
- loc: place.loc,
162529
- suggestions: null,
162530
- severity: exports.ErrorSeverity.InvalidReact,
162531
- },
162532
- };
162533
- }
162534
162671
  effect = isObjectType(place.identifier)
162535
162672
  ? exports.Effect.Store
162536
162673
  : exports.Effect.Mutate;
@@ -162576,7 +162713,7 @@ class InferenceState {
162576
162713
  suggestions: null,
162577
162714
  });
162578
162715
  place.effect = effect;
162579
- return functionEffect;
162716
+ return freeze;
162580
162717
  }
162581
162718
  merge(other) {
162582
162719
  let nextValues = null;
@@ -162831,29 +162968,31 @@ function mergeAbstractValues(a, b) {
162831
162968
  }
162832
162969
  return {kind: kind, reason: reason, context: context};
162833
162970
  }
162834
- function inferBlock(env, functionEffects, state, block) {
162971
+ function inferBlock(env, state, block, functionEffects) {
162835
162972
  var _a, _b, _c, _d;
162836
- var _e;
162837
162973
  for (const phi of block.phis) {
162838
162974
  state.inferPhi(phi);
162839
162975
  }
162840
162976
  for (const instr of block.instructions) {
162841
162977
  const instrValue = instr.value;
162842
- let effect = null;
162843
- let lvalueEffect = exports.Effect.ConditionallyMutate;
162844
- let valueKind;
162978
+ const defaultLvalueEffect = exports.Effect.ConditionallyMutate;
162979
+ let continuation;
162980
+ const freezeActions = [];
162845
162981
  switch (instrValue.kind) {
162846
162982
  case 'BinaryExpression': {
162847
- valueKind = {
162848
- kind: exports.ValueKind.Primitive,
162849
- reason: new Set([ValueReason.Other]),
162850
- context: new Set(),
162983
+ continuation = {
162984
+ kind: 'initialize',
162985
+ valueKind: {
162986
+ kind: exports.ValueKind.Primitive,
162987
+ reason: new Set([ValueReason.Other]),
162988
+ context: new Set(),
162989
+ },
162990
+ effect: {kind: exports.Effect.Read, reason: ValueReason.Other},
162851
162991
  };
162852
- effect = {kind: exports.Effect.Read, reason: ValueReason.Other};
162853
162992
  break;
162854
162993
  }
162855
162994
  case 'ArrayExpression': {
162856
- valueKind = hasContextRefOperand(state, instrValue)
162995
+ const valueKind = hasContextRefOperand(state, instrValue)
162857
162996
  ? {
162858
162997
  kind: exports.ValueKind.Context,
162859
162998
  reason: new Set([ValueReason.Other]),
@@ -162864,37 +163003,42 @@ function inferBlock(env, functionEffects, state, block) {
162864
163003
  reason: new Set([ValueReason.Other]),
162865
163004
  context: new Set(),
162866
163005
  };
162867
- effect = {kind: exports.Effect.Capture, reason: ValueReason.Other};
162868
- lvalueEffect = exports.Effect.Store;
163006
+ continuation = {
163007
+ kind: 'initialize',
163008
+ valueKind: valueKind,
163009
+ effect: {kind: exports.Effect.Capture, reason: ValueReason.Other},
163010
+ lvalueEffect: exports.Effect.Store,
163011
+ };
162869
163012
  break;
162870
163013
  }
162871
163014
  case 'NewExpression': {
162872
- valueKind = {
163015
+ const valueKind = {
162873
163016
  kind: exports.ValueKind.Mutable,
162874
163017
  reason: new Set([ValueReason.Other]),
162875
163018
  context: new Set(),
162876
163019
  };
162877
163020
  state.referenceAndRecordEffects(
163021
+ freezeActions,
162878
163022
  instrValue.callee,
162879
163023
  exports.Effect.Read,
162880
- ValueReason.Other,
162881
- functionEffects
163024
+ ValueReason.Other
162882
163025
  );
162883
163026
  for (const operand of eachCallArgument(instrValue.args)) {
162884
163027
  state.referenceAndRecordEffects(
163028
+ freezeActions,
162885
163029
  operand,
162886
163030
  exports.Effect.ConditionallyMutate,
162887
- ValueReason.Other,
162888
- functionEffects
163031
+ ValueReason.Other
162889
163032
  );
162890
163033
  }
162891
163034
  state.initialize(instrValue, valueKind);
162892
163035
  state.define(instr.lvalue, instrValue);
162893
- instr.lvalue.effect = lvalueEffect;
162894
- continue;
163036
+ instr.lvalue.effect = exports.Effect.ConditionallyMutate;
163037
+ continuation = {kind: 'funeffects'};
163038
+ break;
162895
163039
  }
162896
163040
  case 'ObjectExpression': {
162897
- valueKind = hasContextRefOperand(state, instrValue)
163041
+ const valueKind = hasContextRefOperand(state, instrValue)
162898
163042
  ? {
162899
163043
  kind: exports.ValueKind.Context,
162900
163044
  reason: new Set([ValueReason.Other]),
@@ -162910,26 +163054,26 @@ function inferBlock(env, functionEffects, state, block) {
162910
163054
  case 'ObjectProperty': {
162911
163055
  if (property.key.kind === 'computed') {
162912
163056
  state.referenceAndRecordEffects(
163057
+ freezeActions,
162913
163058
  property.key.name,
162914
163059
  exports.Effect.Freeze,
162915
- ValueReason.Other,
162916
- functionEffects
163060
+ ValueReason.Other
162917
163061
  );
162918
163062
  }
162919
163063
  state.referenceAndRecordEffects(
163064
+ freezeActions,
162920
163065
  property.place,
162921
163066
  exports.Effect.Capture,
162922
- ValueReason.Other,
162923
- functionEffects
163067
+ ValueReason.Other
162924
163068
  );
162925
163069
  break;
162926
163070
  }
162927
163071
  case 'Spread': {
162928
163072
  state.referenceAndRecordEffects(
163073
+ freezeActions,
162929
163074
  property.place,
162930
163075
  exports.Effect.Capture,
162931
- ValueReason.Other,
162932
- functionEffects
163076
+ ValueReason.Other
162933
163077
  );
162934
163078
  break;
162935
163079
  }
@@ -162944,64 +163088,66 @@ function inferBlock(env, functionEffects, state, block) {
162944
163088
  state.initialize(instrValue, valueKind);
162945
163089
  state.define(instr.lvalue, instrValue);
162946
163090
  instr.lvalue.effect = exports.Effect.Store;
162947
- continue;
163091
+ continuation = {kind: 'funeffects'};
163092
+ break;
162948
163093
  }
162949
163094
  case 'UnaryExpression': {
162950
- valueKind = {
162951
- kind: exports.ValueKind.Primitive,
162952
- reason: new Set([ValueReason.Other]),
162953
- context: new Set(),
163095
+ continuation = {
163096
+ kind: 'initialize',
163097
+ valueKind: {
163098
+ kind: exports.ValueKind.Primitive,
163099
+ reason: new Set([ValueReason.Other]),
163100
+ context: new Set(),
163101
+ },
163102
+ effect: {kind: exports.Effect.Read, reason: ValueReason.Other},
162954
163103
  };
162955
- effect = {kind: exports.Effect.Read, reason: ValueReason.Other};
162956
163104
  break;
162957
163105
  }
162958
163106
  case 'UnsupportedNode': {
162959
- valueKind = {
162960
- kind: exports.ValueKind.Mutable,
162961
- reason: new Set([ValueReason.Other]),
162962
- context: new Set(),
163107
+ continuation = {
163108
+ kind: 'initialize',
163109
+ valueKind: {
163110
+ kind: exports.ValueKind.Mutable,
163111
+ reason: new Set([ValueReason.Other]),
163112
+ context: new Set(),
163113
+ },
163114
+ effect: null,
162963
163115
  };
162964
163116
  break;
162965
163117
  }
162966
163118
  case 'JsxExpression': {
162967
163119
  if (instrValue.tag.kind === 'Identifier') {
162968
163120
  state.referenceAndRecordEffects(
163121
+ freezeActions,
162969
163122
  instrValue.tag,
162970
163123
  exports.Effect.Freeze,
162971
- ValueReason.JsxCaptured,
162972
- functionEffects
163124
+ ValueReason.JsxCaptured
162973
163125
  );
162974
163126
  }
162975
163127
  if (instrValue.children !== null) {
162976
163128
  for (const child of instrValue.children) {
162977
163129
  state.referenceAndRecordEffects(
163130
+ freezeActions,
162978
163131
  child,
162979
163132
  exports.Effect.Freeze,
162980
- ValueReason.JsxCaptured,
162981
- functionEffects
163133
+ ValueReason.JsxCaptured
162982
163134
  );
162983
163135
  }
162984
163136
  }
162985
163137
  for (const attr of instrValue.props) {
162986
163138
  if (attr.kind === 'JsxSpreadAttribute') {
162987
163139
  state.referenceAndRecordEffects(
163140
+ freezeActions,
162988
163141
  attr.argument,
162989
163142
  exports.Effect.Freeze,
162990
- ValueReason.JsxCaptured,
162991
- functionEffects
163143
+ ValueReason.JsxCaptured
162992
163144
  );
162993
163145
  } else {
162994
- const propEffects = [];
162995
163146
  state.referenceAndRecordEffects(
163147
+ freezeActions,
162996
163148
  attr.place,
162997
163149
  exports.Effect.Freeze,
162998
- ValueReason.JsxCaptured,
162999
- propEffects
163000
- );
163001
- functionEffects.push(
163002
- ...propEffects.filter(
163003
- effect => !isEffectSafeOutsideRender(effect)
163004
- )
163150
+ ValueReason.JsxCaptured
163005
163151
  );
163006
163152
  }
163007
163153
  }
@@ -163012,63 +163158,86 @@ function inferBlock(env, functionEffects, state, block) {
163012
163158
  });
163013
163159
  state.define(instr.lvalue, instrValue);
163014
163160
  instr.lvalue.effect = exports.Effect.ConditionallyMutate;
163015
- continue;
163161
+ continuation = {kind: 'funeffects'};
163162
+ break;
163016
163163
  }
163017
163164
  case 'JsxFragment': {
163018
- valueKind = {
163019
- kind: exports.ValueKind.Frozen,
163020
- reason: new Set([ValueReason.Other]),
163021
- context: new Set(),
163165
+ continuation = {
163166
+ kind: 'initialize',
163167
+ valueKind: {
163168
+ kind: exports.ValueKind.Frozen,
163169
+ reason: new Set([ValueReason.Other]),
163170
+ context: new Set(),
163171
+ },
163172
+ effect: {kind: exports.Effect.Freeze, reason: ValueReason.Other},
163022
163173
  };
163023
- effect = {kind: exports.Effect.Freeze, reason: ValueReason.Other};
163024
163174
  break;
163025
163175
  }
163026
163176
  case 'TemplateLiteral': {
163027
- valueKind = {
163028
- kind: exports.ValueKind.Primitive,
163029
- reason: new Set([ValueReason.Other]),
163030
- context: new Set(),
163177
+ continuation = {
163178
+ kind: 'initialize',
163179
+ valueKind: {
163180
+ kind: exports.ValueKind.Primitive,
163181
+ reason: new Set([ValueReason.Other]),
163182
+ context: new Set(),
163183
+ },
163184
+ effect: {kind: exports.Effect.Read, reason: ValueReason.Other},
163031
163185
  };
163032
- effect = {kind: exports.Effect.Read, reason: ValueReason.Other};
163033
163186
  break;
163034
163187
  }
163035
163188
  case 'RegExpLiteral': {
163036
- valueKind = {
163037
- kind: exports.ValueKind.Mutable,
163038
- reason: new Set([ValueReason.Other]),
163039
- context: new Set(),
163040
- };
163041
- effect = {
163042
- kind: exports.Effect.ConditionallyMutate,
163043
- reason: ValueReason.Other,
163189
+ continuation = {
163190
+ kind: 'initialize',
163191
+ valueKind: {
163192
+ kind: exports.ValueKind.Mutable,
163193
+ reason: new Set([ValueReason.Other]),
163194
+ context: new Set(),
163195
+ },
163196
+ effect: {
163197
+ kind: exports.Effect.ConditionallyMutate,
163198
+ reason: ValueReason.Other,
163199
+ },
163044
163200
  };
163045
163201
  break;
163046
163202
  }
163047
163203
  case 'MetaProperty': {
163048
163204
  if (instrValue.meta !== 'import' || instrValue.property !== 'meta') {
163049
- continue;
163205
+ continuation = {kind: 'funeffects'};
163206
+ break;
163050
163207
  }
163051
- valueKind = {
163052
- kind: exports.ValueKind.Global,
163053
- reason: new Set([ValueReason.Global]),
163054
- context: new Set(),
163208
+ continuation = {
163209
+ kind: 'initialize',
163210
+ valueKind: {
163211
+ kind: exports.ValueKind.Global,
163212
+ reason: new Set([ValueReason.Global]),
163213
+ context: new Set(),
163214
+ },
163215
+ effect: null,
163055
163216
  };
163056
163217
  break;
163057
163218
  }
163058
163219
  case 'LoadGlobal':
163059
- valueKind = {
163060
- kind: exports.ValueKind.Global,
163061
- reason: new Set([ValueReason.Global]),
163062
- context: new Set(),
163220
+ continuation = {
163221
+ kind: 'initialize',
163222
+ valueKind: {
163223
+ kind: exports.ValueKind.Global,
163224
+ reason: new Set([ValueReason.Global]),
163225
+ context: new Set(),
163226
+ },
163227
+ effect: null,
163063
163228
  };
163064
163229
  break;
163065
163230
  case 'Debugger':
163066
163231
  case 'JSXText':
163067
163232
  case 'Primitive': {
163068
- valueKind = {
163069
- kind: exports.ValueKind.Primitive,
163070
- reason: new Set([ValueReason.Other]),
163071
- context: new Set(),
163233
+ continuation = {
163234
+ kind: 'initialize',
163235
+ valueKind: {
163236
+ kind: exports.ValueKind.Primitive,
163237
+ reason: new Set([ValueReason.Other]),
163238
+ context: new Set(),
163239
+ },
163240
+ effect: null,
163072
163241
  };
163073
163242
  break;
163074
163243
  }
@@ -163077,32 +163246,16 @@ function inferBlock(env, functionEffects, state, block) {
163077
163246
  let hasMutableOperand = false;
163078
163247
  for (const operand of eachInstructionOperand(instr)) {
163079
163248
  state.referenceAndRecordEffects(
163249
+ freezeActions,
163080
163250
  operand,
163081
163251
  operand.effect === exports.Effect.Unknown
163082
163252
  ? exports.Effect.Read
163083
163253
  : operand.effect,
163084
- ValueReason.Other,
163085
- []
163254
+ ValueReason.Other
163086
163255
  );
163087
163256
  if (isMutableEffect(operand.effect, operand.loc));
163088
163257
  hasMutableOperand ||
163089
163258
  (hasMutableOperand = isMutableEffect(operand.effect, operand.loc));
163090
- const values = state.values(operand);
163091
- for (const value of values) {
163092
- if (
163093
- (value.kind === 'ObjectMethod' ||
163094
- value.kind === 'FunctionExpression') &&
163095
- value.loweredFunc.func.effects !== null
163096
- ) {
163097
- (_a = (_e = instrValue.loweredFunc.func).effects) !== null &&
163098
- _a !== void 0
163099
- ? _a
163100
- : (_e.effects = []);
163101
- instrValue.loweredFunc.func.effects.push(
163102
- ...value.loweredFunc.func.effects
163103
- );
163104
- }
163105
- }
163106
163259
  }
163107
163260
  state.initialize(instrValue, {
163108
163261
  kind: hasMutableOperand
@@ -163113,7 +163266,8 @@ function inferBlock(env, functionEffects, state, block) {
163113
163266
  });
163114
163267
  state.define(instr.lvalue, instrValue);
163115
163268
  instr.lvalue.effect = exports.Effect.Store;
163116
- continue;
163269
+ continuation = {kind: 'funeffects'};
163270
+ break;
163117
163271
  }
163118
163272
  case 'TaggedTemplateExpression': {
163119
163273
  const operands = [...eachInstructionValueOperand(instrValue)];
@@ -163128,19 +163282,19 @@ function inferBlock(env, functionEffects, state, block) {
163128
163282
  instrValue.tag.identifier.type
163129
163283
  );
163130
163284
  let calleeEffect =
163131
- (_b =
163285
+ (_a =
163132
163286
  signature === null || signature === void 0
163133
163287
  ? void 0
163134
- : signature.calleeEffect) !== null && _b !== void 0
163135
- ? _b
163288
+ : signature.calleeEffect) !== null && _a !== void 0
163289
+ ? _a
163136
163290
  : exports.Effect.ConditionallyMutate;
163137
163291
  const returnValueKind =
163138
163292
  signature !== null
163139
163293
  ? {
163140
163294
  kind: signature.returnValueKind,
163141
163295
  reason: new Set([
163142
- (_c = signature.returnValueReason) !== null && _c !== void 0
163143
- ? _c
163296
+ (_b = signature.returnValueReason) !== null && _b !== void 0
163297
+ ? _b
163144
163298
  : ValueReason.KnownReturnSignature,
163145
163299
  ]),
163146
163300
  context: new Set(),
@@ -163151,15 +163305,16 @@ function inferBlock(env, functionEffects, state, block) {
163151
163305
  context: new Set(),
163152
163306
  };
163153
163307
  state.referenceAndRecordEffects(
163308
+ freezeActions,
163154
163309
  instrValue.tag,
163155
163310
  calleeEffect,
163156
- ValueReason.Other,
163157
- functionEffects
163311
+ ValueReason.Other
163158
163312
  );
163159
163313
  state.initialize(instrValue, returnValueKind);
163160
163314
  state.define(instr.lvalue, instrValue);
163161
163315
  instr.lvalue.effect = exports.Effect.ConditionallyMutate;
163162
- continue;
163316
+ continuation = {kind: 'funeffects'};
163317
+ break;
163163
163318
  }
163164
163319
  case 'CallExpression': {
163165
163320
  const signature = getFunctionCallSignature(
@@ -163173,8 +163328,8 @@ function inferBlock(env, functionEffects, state, block) {
163173
163328
  ? {
163174
163329
  kind: signature.returnValueKind,
163175
163330
  reason: new Set([
163176
- (_d = signature.returnValueReason) !== null && _d !== void 0
163177
- ? _d
163331
+ (_c = signature.returnValueReason) !== null && _c !== void 0
163332
+ ? _c
163178
163333
  : ValueReason.KnownReturnSignature,
163179
163334
  ]),
163180
163335
  context: new Set(),
@@ -163185,47 +163340,40 @@ function inferBlock(env, functionEffects, state, block) {
163185
163340
  context: new Set(),
163186
163341
  };
163187
163342
  let hasCaptureArgument = false;
163188
- let isHook = getHookKind(env, instrValue.callee.identifier) != null;
163189
163343
  for (let i = 0; i < instrValue.args.length; i++) {
163190
- const argumentEffects = [];
163191
163344
  const arg = instrValue.args[i];
163192
163345
  const place = arg.kind === 'Identifier' ? arg : arg.place;
163193
163346
  if (effects !== null) {
163194
163347
  state.referenceAndRecordEffects(
163348
+ freezeActions,
163195
163349
  place,
163196
163350
  effects[i],
163197
- ValueReason.Other,
163198
- argumentEffects
163351
+ ValueReason.Other
163199
163352
  );
163200
163353
  } else {
163201
163354
  state.referenceAndRecordEffects(
163355
+ freezeActions,
163202
163356
  place,
163203
163357
  exports.Effect.ConditionallyMutate,
163204
- ValueReason.Other,
163205
- argumentEffects
163358
+ ValueReason.Other
163206
163359
  );
163207
163360
  }
163208
- functionEffects.push(
163209
- ...argumentEffects.filter(
163210
- argEffect => !isHook || !isEffectSafeOutsideRender(argEffect)
163211
- )
163212
- );
163213
163361
  hasCaptureArgument ||
163214
163362
  (hasCaptureArgument = place.effect === exports.Effect.Capture);
163215
163363
  }
163216
163364
  if (signature !== null) {
163217
163365
  state.referenceAndRecordEffects(
163366
+ freezeActions,
163218
163367
  instrValue.callee,
163219
163368
  signature.calleeEffect,
163220
- ValueReason.Other,
163221
- functionEffects
163369
+ ValueReason.Other
163222
163370
  );
163223
163371
  } else {
163224
163372
  state.referenceAndRecordEffects(
163373
+ freezeActions,
163225
163374
  instrValue.callee,
163226
163375
  exports.Effect.ConditionallyMutate,
163227
- ValueReason.Other,
163228
- functionEffects
163376
+ ValueReason.Other
163229
163377
  );
163230
163378
  }
163231
163379
  hasCaptureArgument ||
@@ -163236,7 +163384,8 @@ function inferBlock(env, functionEffects, state, block) {
163236
163384
  instr.lvalue.effect = hasCaptureArgument
163237
163385
  ? exports.Effect.Store
163238
163386
  : exports.Effect.ConditionallyMutate;
163239
- continue;
163387
+ continuation = {kind: 'funeffects'};
163388
+ break;
163240
163389
  }
163241
163390
  case 'MethodCall': {
163242
163391
  CompilerError.invariant(state.isDefined(instrValue.receiver), {
@@ -163247,10 +163396,10 @@ function inferBlock(env, functionEffects, state, block) {
163247
163396
  suggestions: null,
163248
163397
  });
163249
163398
  state.referenceAndRecordEffects(
163399
+ freezeActions,
163250
163400
  instrValue.property,
163251
163401
  exports.Effect.Read,
163252
- ValueReason.Other,
163253
- functionEffects
163402
+ ValueReason.Other
163254
163403
  );
163255
163404
  const signature = getFunctionCallSignature(
163256
163405
  env,
@@ -163276,17 +163425,17 @@ function inferBlock(env, functionEffects, state, block) {
163276
163425
  for (const arg of instrValue.args) {
163277
163426
  const place = arg.kind === 'Identifier' ? arg : arg.place;
163278
163427
  state.referenceAndRecordEffects(
163428
+ freezeActions,
163279
163429
  place,
163280
163430
  exports.Effect.Read,
163281
- ValueReason.Other,
163282
- functionEffects
163431
+ ValueReason.Other
163283
163432
  );
163284
163433
  }
163285
163434
  state.referenceAndRecordEffects(
163435
+ freezeActions,
163286
163436
  instrValue.receiver,
163287
163437
  exports.Effect.Capture,
163288
- ValueReason.Other,
163289
- functionEffects
163438
+ ValueReason.Other
163290
163439
  );
163291
163440
  state.initialize(instrValue, returnValueKind);
163292
163441
  state.define(instr.lvalue, instrValue);
@@ -163294,52 +163443,46 @@ function inferBlock(env, functionEffects, state, block) {
163294
163443
  instrValue.receiver.effect === exports.Effect.Capture
163295
163444
  ? exports.Effect.Store
163296
163445
  : exports.Effect.ConditionallyMutate;
163297
- continue;
163446
+ continuation = {kind: 'funeffects'};
163447
+ break;
163298
163448
  }
163299
163449
  const effects =
163300
163450
  signature !== null ? getFunctionEffects(instrValue, signature) : null;
163301
163451
  let hasCaptureArgument = false;
163302
- let isHook = getHookKind(env, instrValue.property.identifier) != null;
163303
163452
  for (let i = 0; i < instrValue.args.length; i++) {
163304
- const argumentEffects = [];
163305
163453
  const arg = instrValue.args[i];
163306
163454
  const place = arg.kind === 'Identifier' ? arg : arg.place;
163307
163455
  if (effects !== null) {
163308
163456
  state.referenceAndRecordEffects(
163457
+ freezeActions,
163309
163458
  place,
163310
163459
  effects[i],
163311
- ValueReason.Other,
163312
- argumentEffects
163460
+ ValueReason.Other
163313
163461
  );
163314
163462
  } else {
163315
163463
  state.referenceAndRecordEffects(
163464
+ freezeActions,
163316
163465
  place,
163317
163466
  exports.Effect.ConditionallyMutate,
163318
- ValueReason.Other,
163319
- argumentEffects
163467
+ ValueReason.Other
163320
163468
  );
163321
163469
  }
163322
- functionEffects.push(
163323
- ...argumentEffects.filter(
163324
- argEffect => !isHook || !isEffectSafeOutsideRender(argEffect)
163325
- )
163326
- );
163327
163470
  hasCaptureArgument ||
163328
163471
  (hasCaptureArgument = place.effect === exports.Effect.Capture);
163329
163472
  }
163330
163473
  if (signature !== null) {
163331
163474
  state.referenceAndRecordEffects(
163475
+ freezeActions,
163332
163476
  instrValue.receiver,
163333
163477
  signature.calleeEffect,
163334
- ValueReason.Other,
163335
- functionEffects
163478
+ ValueReason.Other
163336
163479
  );
163337
163480
  } else {
163338
163481
  state.referenceAndRecordEffects(
163482
+ freezeActions,
163339
163483
  instrValue.receiver,
163340
163484
  exports.Effect.ConditionallyMutate,
163341
- ValueReason.Other,
163342
- functionEffects
163485
+ ValueReason.Other
163343
163486
  );
163344
163487
  }
163345
163488
  hasCaptureArgument ||
@@ -163350,7 +163493,8 @@ function inferBlock(env, functionEffects, state, block) {
163350
163493
  instr.lvalue.effect = hasCaptureArgument
163351
163494
  ? exports.Effect.Store
163352
163495
  : exports.Effect.ConditionallyMutate;
163353
- continue;
163496
+ continuation = {kind: 'funeffects'};
163497
+ break;
163354
163498
  }
163355
163499
  case 'PropertyStore': {
163356
163500
  const effect =
@@ -163358,43 +163502,48 @@ function inferBlock(env, functionEffects, state, block) {
163358
163502
  ? exports.Effect.ConditionallyMutate
163359
163503
  : exports.Effect.Capture;
163360
163504
  state.referenceAndRecordEffects(
163505
+ freezeActions,
163361
163506
  instrValue.value,
163362
163507
  effect,
163363
- ValueReason.Other,
163364
- functionEffects
163508
+ ValueReason.Other
163365
163509
  );
163366
163510
  state.referenceAndRecordEffects(
163511
+ freezeActions,
163367
163512
  instrValue.object,
163368
163513
  exports.Effect.Store,
163369
- ValueReason.Other,
163370
- functionEffects
163514
+ ValueReason.Other
163371
163515
  );
163372
163516
  const lvalue = instr.lvalue;
163373
163517
  state.alias(lvalue, instrValue.value);
163374
163518
  lvalue.effect = exports.Effect.Store;
163375
- continue;
163519
+ continuation = {kind: 'funeffects'};
163520
+ break;
163376
163521
  }
163377
163522
  case 'PropertyDelete': {
163378
- valueKind = {
163379
- kind: exports.ValueKind.Primitive,
163380
- reason: new Set([ValueReason.Other]),
163381
- context: new Set(),
163523
+ continuation = {
163524
+ kind: 'initialize',
163525
+ valueKind: {
163526
+ kind: exports.ValueKind.Primitive,
163527
+ reason: new Set([ValueReason.Other]),
163528
+ context: new Set(),
163529
+ },
163530
+ effect: {kind: exports.Effect.Mutate, reason: ValueReason.Other},
163382
163531
  };
163383
- effect = {kind: exports.Effect.Mutate, reason: ValueReason.Other};
163384
163532
  break;
163385
163533
  }
163386
163534
  case 'PropertyLoad': {
163387
163535
  state.referenceAndRecordEffects(
163536
+ freezeActions,
163388
163537
  instrValue.object,
163389
163538
  exports.Effect.Read,
163390
- ValueReason.Other,
163391
- functionEffects
163539
+ ValueReason.Other
163392
163540
  );
163393
163541
  const lvalue = instr.lvalue;
163394
163542
  lvalue.effect = exports.Effect.ConditionallyMutate;
163395
163543
  state.initialize(instrValue, state.kind(instrValue.object));
163396
163544
  state.define(lvalue, instrValue);
163397
- continue;
163545
+ continuation = {kind: 'funeffects'};
163546
+ break;
163398
163547
  }
163399
163548
  case 'ComputedStore': {
163400
163549
  const effect =
@@ -163402,40 +163551,41 @@ function inferBlock(env, functionEffects, state, block) {
163402
163551
  ? exports.Effect.ConditionallyMutate
163403
163552
  : exports.Effect.Capture;
163404
163553
  state.referenceAndRecordEffects(
163554
+ freezeActions,
163405
163555
  instrValue.value,
163406
163556
  effect,
163407
- ValueReason.Other,
163408
- functionEffects
163557
+ ValueReason.Other
163409
163558
  );
163410
163559
  state.referenceAndRecordEffects(
163560
+ freezeActions,
163411
163561
  instrValue.property,
163412
163562
  exports.Effect.Capture,
163413
- ValueReason.Other,
163414
- functionEffects
163563
+ ValueReason.Other
163415
163564
  );
163416
163565
  state.referenceAndRecordEffects(
163566
+ freezeActions,
163417
163567
  instrValue.object,
163418
163568
  exports.Effect.Store,
163419
- ValueReason.Other,
163420
- functionEffects
163569
+ ValueReason.Other
163421
163570
  );
163422
163571
  const lvalue = instr.lvalue;
163423
163572
  state.alias(lvalue, instrValue.value);
163424
163573
  lvalue.effect = exports.Effect.Store;
163425
- continue;
163574
+ continuation = {kind: 'funeffects'};
163575
+ break;
163426
163576
  }
163427
163577
  case 'ComputedDelete': {
163428
163578
  state.referenceAndRecordEffects(
163579
+ freezeActions,
163429
163580
  instrValue.object,
163430
163581
  exports.Effect.Mutate,
163431
- ValueReason.Other,
163432
- functionEffects
163582
+ ValueReason.Other
163433
163583
  );
163434
163584
  state.referenceAndRecordEffects(
163585
+ freezeActions,
163435
163586
  instrValue.property,
163436
163587
  exports.Effect.Read,
163437
- ValueReason.Other,
163438
- functionEffects
163588
+ ValueReason.Other
163439
163589
  );
163440
163590
  state.initialize(instrValue, {
163441
163591
  kind: exports.ValueKind.Primitive,
@@ -163444,69 +163594,73 @@ function inferBlock(env, functionEffects, state, block) {
163444
163594
  });
163445
163595
  state.define(instr.lvalue, instrValue);
163446
163596
  instr.lvalue.effect = exports.Effect.Mutate;
163447
- continue;
163597
+ continuation = {kind: 'funeffects'};
163598
+ break;
163448
163599
  }
163449
163600
  case 'ComputedLoad': {
163450
163601
  state.referenceAndRecordEffects(
163602
+ freezeActions,
163451
163603
  instrValue.object,
163452
163604
  exports.Effect.Read,
163453
- ValueReason.Other,
163454
- functionEffects
163605
+ ValueReason.Other
163455
163606
  );
163456
163607
  state.referenceAndRecordEffects(
163608
+ freezeActions,
163457
163609
  instrValue.property,
163458
163610
  exports.Effect.Read,
163459
- ValueReason.Other,
163460
- functionEffects
163611
+ ValueReason.Other
163461
163612
  );
163462
163613
  const lvalue = instr.lvalue;
163463
163614
  lvalue.effect = exports.Effect.ConditionallyMutate;
163464
163615
  state.initialize(instrValue, state.kind(instrValue.object));
163465
163616
  state.define(lvalue, instrValue);
163466
- continue;
163617
+ continuation = {kind: 'funeffects'};
163618
+ break;
163467
163619
  }
163468
163620
  case 'Await': {
163469
163621
  state.initialize(instrValue, state.kind(instrValue.value));
163470
163622
  state.referenceAndRecordEffects(
163623
+ freezeActions,
163471
163624
  instrValue.value,
163472
163625
  exports.Effect.ConditionallyMutate,
163473
- ValueReason.Other,
163474
- functionEffects
163626
+ ValueReason.Other
163475
163627
  );
163476
163628
  const lvalue = instr.lvalue;
163477
163629
  lvalue.effect = exports.Effect.ConditionallyMutate;
163478
163630
  state.alias(lvalue, instrValue.value);
163479
- continue;
163631
+ continuation = {kind: 'funeffects'};
163632
+ break;
163480
163633
  }
163481
163634
  case 'TypeCastExpression': {
163482
163635
  state.initialize(instrValue, state.kind(instrValue.value));
163483
163636
  state.referenceAndRecordEffects(
163637
+ freezeActions,
163484
163638
  instrValue.value,
163485
163639
  exports.Effect.Read,
163486
- ValueReason.Other,
163487
- functionEffects
163640
+ ValueReason.Other
163488
163641
  );
163489
163642
  const lvalue = instr.lvalue;
163490
163643
  lvalue.effect = exports.Effect.ConditionallyMutate;
163491
163644
  state.alias(lvalue, instrValue.value);
163492
- continue;
163645
+ continuation = {kind: 'funeffects'};
163646
+ break;
163493
163647
  }
163494
163648
  case 'StartMemoize':
163495
163649
  case 'FinishMemoize': {
163496
163650
  for (const val of eachInstructionValueOperand(instrValue)) {
163497
163651
  if (env.config.enablePreserveExistingMemoizationGuarantees) {
163498
163652
  state.referenceAndRecordEffects(
163653
+ freezeActions,
163499
163654
  val,
163500
163655
  exports.Effect.Freeze,
163501
- ValueReason.Other,
163502
- []
163656
+ ValueReason.Other
163503
163657
  );
163504
163658
  } else {
163505
163659
  state.referenceAndRecordEffects(
163660
+ freezeActions,
163506
163661
  val,
163507
163662
  exports.Effect.Read,
163508
- ValueReason.Other,
163509
- []
163663
+ ValueReason.Other
163510
163664
  );
163511
163665
  }
163512
163666
  }
@@ -163518,7 +163672,8 @@ function inferBlock(env, functionEffects, state, block) {
163518
163672
  context: new Set(),
163519
163673
  });
163520
163674
  state.define(lvalue, instrValue);
163521
- continue;
163675
+ continuation = {kind: 'funeffects'};
163676
+ break;
163522
163677
  }
163523
163678
  case 'LoadLocal': {
163524
163679
  const lvalue = instr.lvalue;
@@ -163528,28 +163683,30 @@ function inferBlock(env, functionEffects, state, block) {
163528
163683
  ? exports.Effect.ConditionallyMutate
163529
163684
  : exports.Effect.Capture;
163530
163685
  state.referenceAndRecordEffects(
163686
+ freezeActions,
163531
163687
  instrValue.place,
163532
163688
  effect,
163533
- ValueReason.Other,
163534
- []
163689
+ ValueReason.Other
163535
163690
  );
163536
163691
  lvalue.effect = exports.Effect.ConditionallyMutate;
163537
163692
  state.alias(lvalue, instrValue.place);
163538
- continue;
163693
+ continuation = {kind: 'funeffects'};
163694
+ break;
163539
163695
  }
163540
163696
  case 'LoadContext': {
163541
163697
  state.referenceAndRecordEffects(
163698
+ freezeActions,
163542
163699
  instrValue.place,
163543
163700
  exports.Effect.Capture,
163544
- ValueReason.Other,
163545
- functionEffects
163701
+ ValueReason.Other
163546
163702
  );
163547
163703
  const lvalue = instr.lvalue;
163548
163704
  lvalue.effect = exports.Effect.ConditionallyMutate;
163549
163705
  const valueKind = state.kind(instrValue.place);
163550
163706
  state.initialize(instrValue, valueKind);
163551
163707
  state.define(lvalue, instrValue);
163552
- continue;
163708
+ continuation = {kind: 'funeffects'};
163709
+ break;
163553
163710
  }
163554
163711
  case 'DeclareLocal': {
163555
163712
  const value = UndefinedValue;
@@ -163568,7 +163725,8 @@ function inferBlock(env, functionEffects, state, block) {
163568
163725
  }
163569
163726
  );
163570
163727
  state.define(instrValue.lvalue.place, value);
163571
- continue;
163728
+ continuation = {kind: 'funeffects'};
163729
+ break;
163572
163730
  }
163573
163731
  case 'DeclareContext': {
163574
163732
  state.initialize(instrValue, {
@@ -163577,7 +163735,8 @@ function inferBlock(env, functionEffects, state, block) {
163577
163735
  context: new Set(),
163578
163736
  });
163579
163737
  state.define(instrValue.lvalue.place, instrValue);
163580
- continue;
163738
+ continuation = {kind: 'funeffects'};
163739
+ break;
163581
163740
  }
163582
163741
  case 'PostfixUpdate':
163583
163742
  case 'PrefixUpdate': {
@@ -163587,17 +163746,18 @@ function inferBlock(env, functionEffects, state, block) {
163587
163746
  ? exports.Effect.ConditionallyMutate
163588
163747
  : exports.Effect.Capture;
163589
163748
  state.referenceAndRecordEffects(
163749
+ freezeActions,
163590
163750
  instrValue.value,
163591
163751
  effect,
163592
- ValueReason.Other,
163593
- functionEffects
163752
+ ValueReason.Other
163594
163753
  );
163595
163754
  const lvalue = instr.lvalue;
163596
163755
  state.alias(lvalue, instrValue.value);
163597
163756
  lvalue.effect = exports.Effect.Store;
163598
163757
  state.alias(instrValue.lvalue, instrValue.value);
163599
163758
  instrValue.lvalue.effect = exports.Effect.Store;
163600
- continue;
163759
+ continuation = {kind: 'funeffects'};
163760
+ break;
163601
163761
  }
163602
163762
  case 'StoreLocal': {
163603
163763
  const effect =
@@ -163606,56 +163766,49 @@ function inferBlock(env, functionEffects, state, block) {
163606
163766
  ? exports.Effect.ConditionallyMutate
163607
163767
  : exports.Effect.Capture;
163608
163768
  state.referenceAndRecordEffects(
163769
+ freezeActions,
163609
163770
  instrValue.value,
163610
163771
  effect,
163611
- ValueReason.Other,
163612
- []
163772
+ ValueReason.Other
163613
163773
  );
163614
163774
  const lvalue = instr.lvalue;
163615
163775
  state.alias(lvalue, instrValue.value);
163616
163776
  lvalue.effect = exports.Effect.Store;
163617
163777
  state.alias(instrValue.lvalue.place, instrValue.value);
163618
163778
  instrValue.lvalue.place.effect = exports.Effect.Store;
163619
- continue;
163779
+ continuation = {kind: 'funeffects'};
163780
+ break;
163620
163781
  }
163621
163782
  case 'StoreContext': {
163622
163783
  state.referenceAndRecordEffects(
163784
+ freezeActions,
163623
163785
  instrValue.value,
163624
163786
  exports.Effect.ConditionallyMutate,
163625
- ValueReason.Other,
163626
- functionEffects
163787
+ ValueReason.Other
163627
163788
  );
163628
163789
  state.referenceAndRecordEffects(
163790
+ freezeActions,
163629
163791
  instrValue.lvalue.place,
163630
163792
  exports.Effect.Mutate,
163631
- ValueReason.Other,
163632
- functionEffects
163793
+ ValueReason.Other
163633
163794
  );
163634
163795
  const lvalue = instr.lvalue;
163635
163796
  state.alias(lvalue, instrValue.value);
163636
163797
  lvalue.effect = exports.Effect.Store;
163637
- continue;
163798
+ continuation = {kind: 'funeffects'};
163799
+ break;
163638
163800
  }
163639
163801
  case 'StoreGlobal': {
163640
163802
  state.referenceAndRecordEffects(
163803
+ freezeActions,
163641
163804
  instrValue.value,
163642
163805
  exports.Effect.Capture,
163643
- ValueReason.Other,
163644
- functionEffects
163806
+ ValueReason.Other
163645
163807
  );
163646
163808
  const lvalue = instr.lvalue;
163647
163809
  lvalue.effect = exports.Effect.Store;
163648
- functionEffects.push({
163649
- kind: 'GlobalMutation',
163650
- error: {
163651
- reason:
163652
- 'Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)',
163653
- loc: instr.loc,
163654
- suggestions: null,
163655
- severity: exports.ErrorSeverity.InvalidReact,
163656
- },
163657
- });
163658
- continue;
163810
+ continuation = {kind: 'funeffects'};
163811
+ break;
163659
163812
  }
163660
163813
  case 'Destructure': {
163661
163814
  let effect = exports.Effect.Capture;
@@ -163669,10 +163822,10 @@ function inferBlock(env, functionEffects, state, block) {
163669
163822
  }
163670
163823
  }
163671
163824
  state.referenceAndRecordEffects(
163825
+ freezeActions,
163672
163826
  instrValue.value,
163673
163827
  effect,
163674
- ValueReason.Other,
163675
- functionEffects
163828
+ ValueReason.Other
163676
163829
  );
163677
163830
  const lvalue = instr.lvalue;
163678
163831
  state.alias(lvalue, instrValue.value);
@@ -163681,13 +163834,16 @@ function inferBlock(env, functionEffects, state, block) {
163681
163834
  state.alias(place, instrValue.value);
163682
163835
  place.effect = exports.Effect.Store;
163683
163836
  }
163684
- continue;
163837
+ continuation = {kind: 'funeffects'};
163838
+ break;
163685
163839
  }
163686
163840
  case 'GetIterator': {
163687
163841
  const kind = state.kind(instrValue.collection).kind;
163688
163842
  const isMutable =
163689
163843
  kind === exports.ValueKind.Mutable ||
163690
163844
  kind === exports.ValueKind.Context;
163845
+ let effect;
163846
+ let valueKind;
163691
163847
  if (!isMutable || isArrayType(instrValue.collection.identifier)) {
163692
163848
  effect = {kind: exports.Effect.Read, reason: ValueReason.Other};
163693
163849
  valueKind = {
@@ -163699,34 +163855,43 @@ function inferBlock(env, functionEffects, state, block) {
163699
163855
  effect = {kind: exports.Effect.Capture, reason: ValueReason.Other};
163700
163856
  valueKind = state.kind(instrValue.collection);
163701
163857
  }
163702
- lvalueEffect = exports.Effect.Store;
163858
+ continuation = {
163859
+ kind: 'initialize',
163860
+ effect: effect,
163861
+ valueKind: valueKind,
163862
+ lvalueEffect: exports.Effect.Store,
163863
+ };
163703
163864
  break;
163704
163865
  }
163705
163866
  case 'IteratorNext': {
163706
163867
  state.referenceAndRecordEffects(
163868
+ freezeActions,
163707
163869
  instrValue.iterator,
163708
163870
  exports.Effect.ConditionallyMutate,
163709
- ValueReason.Other,
163710
- functionEffects
163871
+ ValueReason.Other
163711
163872
  );
163712
163873
  state.referenceAndRecordEffects(
163874
+ freezeActions,
163713
163875
  instrValue.collection,
163714
163876
  exports.Effect.Capture,
163715
- ValueReason.Other,
163716
- functionEffects
163877
+ ValueReason.Other
163717
163878
  );
163718
163879
  state.initialize(instrValue, state.kind(instrValue.collection));
163719
163880
  state.define(instr.lvalue, instrValue);
163720
163881
  instr.lvalue.effect = exports.Effect.Store;
163721
- continue;
163882
+ continuation = {kind: 'funeffects'};
163883
+ break;
163722
163884
  }
163723
163885
  case 'NextPropertyOf': {
163724
- effect = {kind: exports.Effect.Read, reason: ValueReason.Other};
163725
- lvalueEffect = exports.Effect.Store;
163726
- valueKind = {
163727
- kind: exports.ValueKind.Primitive,
163728
- reason: new Set([ValueReason.Other]),
163729
- context: new Set(),
163886
+ continuation = {
163887
+ kind: 'initialize',
163888
+ effect: {kind: exports.Effect.Read, reason: ValueReason.Other},
163889
+ lvalueEffect: exports.Effect.Store,
163890
+ valueKind: {
163891
+ kind: exports.ValueKind.Primitive,
163892
+ reason: new Set([ValueReason.Other]),
163893
+ context: new Set(),
163894
+ },
163730
163895
  };
163731
163896
  break;
163732
163897
  }
@@ -163734,24 +163899,34 @@ function inferBlock(env, functionEffects, state, block) {
163734
163899
  assertExhaustive(instrValue, 'Unexpected instruction kind');
163735
163900
  }
163736
163901
  }
163737
- for (const operand of eachInstructionOperand(instr)) {
163738
- CompilerError.invariant(effect != null, {
163739
- reason: `effectKind must be set for instruction value \`${instrValue.kind}\``,
163740
- description: null,
163741
- loc: instrValue.loc,
163742
- suggestions: null,
163743
- });
163744
- state.referenceAndRecordEffects(
163745
- operand,
163746
- effect.kind,
163747
- effect.reason,
163748
- functionEffects
163749
- );
163750
- }
163751
- state.initialize(instrValue, valueKind);
163752
- state.define(instr.lvalue, instrValue);
163753
- instr.lvalue.effect = lvalueEffect;
163902
+ if (continuation.kind === 'initialize') {
163903
+ for (const operand of eachInstructionOperand(instr)) {
163904
+ CompilerError.invariant(continuation.effect != null, {
163905
+ reason: `effectKind must be set for instruction value \`${instrValue.kind}\``,
163906
+ description: null,
163907
+ loc: instrValue.loc,
163908
+ suggestions: null,
163909
+ });
163910
+ state.referenceAndRecordEffects(
163911
+ freezeActions,
163912
+ operand,
163913
+ continuation.effect.kind,
163914
+ continuation.effect.reason
163915
+ );
163916
+ }
163917
+ state.initialize(instrValue, continuation.valueKind);
163918
+ state.define(instr.lvalue, instrValue);
163919
+ instr.lvalue.effect =
163920
+ (_d = continuation.lvalueEffect) !== null && _d !== void 0
163921
+ ? _d
163922
+ : defaultLvalueEffect;
163923
+ }
163924
+ functionEffects.push(...inferInstructionFunctionEffects(env, state, instr));
163925
+ freezeActions.forEach(({values: values, reason: reason}) =>
163926
+ state.freezeValues(values, reason)
163927
+ );
163754
163928
  }
163929
+ const terminalFreezeActions = [];
163755
163930
  for (const operand of eachTerminalOperand(block.terminal)) {
163756
163931
  let effect;
163757
163932
  if (block.terminal.kind === 'return' || block.terminal.kind === 'throw') {
@@ -163766,17 +163941,17 @@ function inferBlock(env, functionEffects, state, block) {
163766
163941
  } else {
163767
163942
  effect = exports.Effect.Read;
163768
163943
  }
163769
- const propEffects = [];
163770
163944
  state.referenceAndRecordEffects(
163945
+ terminalFreezeActions,
163771
163946
  operand,
163772
163947
  effect,
163773
- ValueReason.Other,
163774
- propEffects
163775
- );
163776
- functionEffects.push(
163777
- ...propEffects.filter(effect => !isEffectSafeOutsideRender(effect))
163948
+ ValueReason.Other
163778
163949
  );
163779
163950
  }
163951
+ functionEffects.push(...inferTerminalFunctionEffects(state, block));
163952
+ terminalFreezeActions.forEach(({values: values, reason: reason}) =>
163953
+ state.freezeValues(values, reason)
163954
+ );
163780
163955
  }
163781
163956
  function hasContextRefOperand(state, instrValue) {
163782
163957
  for (const place of eachInstructionValueOperand(instrValue)) {
@@ -163843,28 +164018,6 @@ function areArgumentsImmutableAndNonMutating(state, args) {
163843
164018
  }
163844
164019
  return true;
163845
164020
  }
163846
- function isEffectSafeOutsideRender(effect) {
163847
- return effect.kind === 'GlobalMutation';
163848
- }
163849
- function getWriteErrorReason(abstractValue) {
163850
- if (abstractValue.reason.has(ValueReason.Global)) {
163851
- return 'Writing to a variable defined outside a component or hook is not allowed. Consider using an effect';
163852
- } else if (abstractValue.reason.has(ValueReason.JsxCaptured)) {
163853
- return 'Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX';
163854
- } else if (abstractValue.reason.has(ValueReason.Context)) {
163855
- return `Mutating a value returned from 'useContext()', which should not be mutated`;
163856
- } else if (abstractValue.reason.has(ValueReason.KnownReturnSignature)) {
163857
- return 'Mutating a value returned from a function whose return value should not be mutated';
163858
- } else if (abstractValue.reason.has(ValueReason.ReactiveFunctionArgument)) {
163859
- return 'Mutating component props or hook arguments is not allowed. Consider using a local variable instead';
163860
- } else if (abstractValue.reason.has(ValueReason.State)) {
163861
- return "Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead";
163862
- } else if (abstractValue.reason.has(ValueReason.ReducerState)) {
163863
- return "Mutating a value returned from 'useReducer()', which should not be mutated. Use the dispatch function to update instead";
163864
- } else {
163865
- return 'This mutates a variable that React considers immutable';
163866
- }
163867
- }
163868
164021
  function pruneNonEscapingScopes(fn) {
163869
164022
  const state = new State(fn.env);
163870
164023
  for (const param of fn.params) {
@@ -167038,7 +167191,7 @@ function equation(left, right) {
167038
167191
  return {left: left, right: right};
167039
167192
  }
167040
167193
  function* generate(func) {
167041
- if (func.env.fnType === 'Component') {
167194
+ if (func.fnType === 'Component') {
167042
167195
  const [props, ref] = func.params;
167043
167196
  if (props && props.kind === 'Identifier') {
167044
167197
  yield equation(props.identifier.type, {
@@ -168070,16 +168223,131 @@ function validateNoCapitalizedCalls(fn) {
168070
168223
  }
168071
168224
  }
168072
168225
  }
168226
+ var _Env_changed;
168227
+ class Env extends Map {
168228
+ constructor() {
168229
+ super(...arguments);
168230
+ _Env_changed.set(this, false);
168231
+ }
168232
+ resetChanged() {
168233
+ __classPrivateFieldSet(this, _Env_changed, false, 'f');
168234
+ }
168235
+ hasChanged() {
168236
+ return __classPrivateFieldGet(this, _Env_changed, 'f');
168237
+ }
168238
+ set(key, value) {
168239
+ const cur = this.get(key);
168240
+ const widenedValue = joinRefAccessTypes(
168241
+ value,
168242
+ cur !== null && cur !== void 0 ? cur : {kind: 'None'}
168243
+ );
168244
+ if (
168245
+ !(cur == null && widenedValue.kind === 'None') &&
168246
+ (cur == null || !tyEqual(cur, widenedValue))
168247
+ ) {
168248
+ __classPrivateFieldSet(this, _Env_changed, true, 'f');
168249
+ }
168250
+ return super.set(key, widenedValue);
168251
+ }
168252
+ }
168253
+ _Env_changed = new WeakMap();
168073
168254
  function validateNoRefAccessInRender(fn) {
168074
- const state = {
168075
- refs: new Set(),
168076
- refValues: new Map(),
168077
- refAccessingFunctions: new Set(),
168078
- };
168079
- validateNoRefAccessInRenderImpl(fn, state).unwrap();
168255
+ const env = new Env();
168256
+ validateNoRefAccessInRenderImpl(fn, env).unwrap();
168257
+ }
168258
+ function refTypeOfType(identifier) {
168259
+ if (isRefValueType(identifier)) {
168260
+ return {kind: 'RefValue'};
168261
+ } else if (isUseRefType(identifier)) {
168262
+ return {kind: 'Ref'};
168263
+ } else {
168264
+ return {kind: 'None'};
168265
+ }
168080
168266
  }
168081
- function validateNoRefAccessInRenderImpl(fn, state) {
168082
- var _a, _b;
168267
+ function tyEqual(a, b) {
168268
+ if (a.kind !== b.kind) {
168269
+ return false;
168270
+ }
168271
+ switch (a.kind) {
168272
+ case 'None':
168273
+ return true;
168274
+ case 'Ref':
168275
+ return true;
168276
+ case 'RefValue':
168277
+ CompilerError.invariant(b.kind === 'RefValue', {
168278
+ reason: 'Expected ref value',
168279
+ loc: null,
168280
+ });
168281
+ return a.loc == b.loc;
168282
+ case 'Structure': {
168283
+ CompilerError.invariant(b.kind === 'Structure', {
168284
+ reason: 'Expected structure',
168285
+ loc: null,
168286
+ });
168287
+ const fnTypesEqual =
168288
+ (a.fn === null && b.fn === null) ||
168289
+ (a.fn !== null &&
168290
+ b.fn !== null &&
168291
+ a.fn.readRefEffect === b.fn.readRefEffect &&
168292
+ tyEqual(a.fn.returnType, b.fn.returnType));
168293
+ return (
168294
+ fnTypesEqual &&
168295
+ (a.value === b.value ||
168296
+ (a.value !== null && b.value !== null && tyEqual(a.value, b.value)))
168297
+ );
168298
+ }
168299
+ }
168300
+ }
168301
+ function joinRefAccessTypes(...types) {
168302
+ function joinRefAccessRefTypes(a, b) {
168303
+ if (a.kind === 'RefValue') {
168304
+ return a;
168305
+ } else if (b.kind === 'RefValue') {
168306
+ return b;
168307
+ } else if (a.kind === 'Ref' || b.kind === 'Ref') {
168308
+ return {kind: 'Ref'};
168309
+ } else {
168310
+ CompilerError.invariant(
168311
+ a.kind === 'Structure' && b.kind === 'Structure',
168312
+ {reason: 'Expected structure', loc: null}
168313
+ );
168314
+ const fn =
168315
+ a.fn === null
168316
+ ? b.fn
168317
+ : b.fn === null
168318
+ ? a.fn
168319
+ : {
168320
+ readRefEffect: a.fn.readRefEffect || b.fn.readRefEffect,
168321
+ returnType: joinRefAccessTypes(
168322
+ a.fn.returnType,
168323
+ b.fn.returnType
168324
+ ),
168325
+ };
168326
+ const value =
168327
+ a.value === null
168328
+ ? b.value
168329
+ : b.value === null
168330
+ ? a.value
168331
+ : joinRefAccessRefTypes(a.value, b.value);
168332
+ return {kind: 'Structure', fn: fn, value: value};
168333
+ }
168334
+ }
168335
+ return types.reduce(
168336
+ (a, b) => {
168337
+ if (a.kind === 'None') {
168338
+ return b;
168339
+ } else if (b.kind === 'None') {
168340
+ return a;
168341
+ } else {
168342
+ return joinRefAccessRefTypes(a, b);
168343
+ }
168344
+ },
168345
+ {kind: 'None'}
168346
+ );
168347
+ }
168348
+ function validateNoRefAccessInRenderImpl(fn, env) {
168349
+ var _a, _b, _c, _d, _e, _f;
168350
+ let returnValues = [];
168083
168351
  let place;
168084
168352
  for (const param of fn.params) {
168085
168353
  if (param.kind === 'Identifier') {
@@ -168087,291 +168355,293 @@ function validateNoRefAccessInRenderImpl(fn, state) {
168087
168355
  } else {
168088
168356
  place = param.place;
168089
168357
  }
168090
- if (isRefValueType(place.identifier)) {
168091
- state.refValues.set(place.identifier.id, null);
168092
- }
168093
- if (isUseRefType(place.identifier)) {
168094
- state.refs.add(place.identifier.id);
168095
- }
168358
+ const type = refTypeOfType(place.identifier);
168359
+ env.set(place.identifier.id, type);
168096
168360
  }
168097
- const errors = new CompilerError();
168098
- for (const [, block] of fn.body.blocks) {
168099
- for (const phi of block.phis) {
168100
- phi.operands.forEach(operand => {
168101
- var _a;
168102
- if (state.refs.has(operand.id) || isUseRefType(phi.id)) {
168103
- state.refs.add(phi.id.id);
168104
- }
168105
- const refValue = state.refValues.get(operand.id);
168106
- if (refValue !== undefined || isRefValueType(operand)) {
168107
- state.refValues.set(
168108
- phi.id.id,
168109
- (_a =
168110
- refValue !== null && refValue !== void 0
168111
- ? refValue
168112
- : state.refValues.get(phi.id.id)) !== null && _a !== void 0
168113
- ? _a
168114
- : null
168115
- );
168116
- }
168117
- if (state.refAccessingFunctions.has(operand.id)) {
168118
- state.refAccessingFunctions.add(phi.id.id);
168119
- }
168120
- });
168121
- }
168122
- for (const instr of block.instructions) {
168123
- for (const operand of eachInstructionValueOperand(instr.value)) {
168124
- if (isRefValueType(operand.identifier)) {
168125
- CompilerError.invariant(state.refValues.has(operand.identifier.id), {
168126
- reason: 'Expected ref value to be in state',
168127
- loc: operand.loc,
168128
- });
168129
- }
168130
- if (isUseRefType(operand.identifier)) {
168131
- CompilerError.invariant(state.refs.has(operand.identifier.id), {
168132
- reason: 'Expected ref to be in state',
168133
- loc: operand.loc,
168134
- });
168135
- }
168361
+ for (let i = 0; (i == 0 || env.hasChanged()) && i < 10; i++) {
168362
+ env.resetChanged();
168363
+ returnValues = [];
168364
+ const errors = new CompilerError();
168365
+ for (const [, block] of fn.body.blocks) {
168366
+ for (const phi of block.phis) {
168367
+ env.set(
168368
+ phi.id.id,
168369
+ joinRefAccessTypes(
168370
+ ...Array(...phi.operands.values()).map(operand => {
168371
+ var _a;
168372
+ return (_a = env.get(operand.id)) !== null && _a !== void 0
168373
+ ? _a
168374
+ : {kind: 'None'};
168375
+ })
168376
+ )
168377
+ );
168136
168378
  }
168137
- switch (instr.value.kind) {
168138
- case 'JsxExpression':
168139
- case 'JsxFragment': {
168140
- for (const operand of eachInstructionValueOperand(instr.value)) {
168141
- validateNoDirectRefValueAccess(errors, operand, state);
168142
- }
168143
- break;
168144
- }
168145
- case 'ComputedLoad':
168146
- case 'PropertyLoad': {
168147
- if (typeof instr.value.property !== 'string') {
168148
- validateNoRefValueAccess(errors, state, instr.value.property);
168149
- }
168150
- if (
168151
- state.refAccessingFunctions.has(instr.value.object.identifier.id)
168152
- ) {
168153
- state.refAccessingFunctions.add(instr.lvalue.identifier.id);
168154
- }
168155
- if (state.refs.has(instr.value.object.identifier.id)) {
168156
- state.refs.add(instr.lvalue.identifier.id);
168157
- state.refValues.set(instr.lvalue.identifier.id, instr.loc);
168158
- }
168159
- break;
168160
- }
168161
- case 'LoadContext':
168162
- case 'LoadLocal': {
168163
- if (
168164
- state.refAccessingFunctions.has(instr.value.place.identifier.id)
168165
- ) {
168166
- state.refAccessingFunctions.add(instr.lvalue.identifier.id);
168167
- }
168168
- const refValue = state.refValues.get(instr.value.place.identifier.id);
168169
- if (refValue !== undefined) {
168170
- state.refValues.set(instr.lvalue.identifier.id, refValue);
168379
+ for (const instr of block.instructions) {
168380
+ switch (instr.value.kind) {
168381
+ case 'JsxExpression':
168382
+ case 'JsxFragment': {
168383
+ for (const operand of eachInstructionValueOperand(instr.value)) {
168384
+ validateNoDirectRefValueAccess(errors, operand, env);
168385
+ }
168386
+ break;
168171
168387
  }
168172
- if (state.refs.has(instr.value.place.identifier.id)) {
168173
- state.refs.add(instr.lvalue.identifier.id);
168388
+ case 'ComputedLoad':
168389
+ case 'PropertyLoad': {
168390
+ if (typeof instr.value.property !== 'string') {
168391
+ validateNoDirectRefValueAccess(errors, instr.value.property, env);
168392
+ }
168393
+ const objType = env.get(instr.value.object.identifier.id);
168394
+ let lookupType = null;
168395
+ if (
168396
+ (objType === null || objType === void 0
168397
+ ? void 0
168398
+ : objType.kind) === 'Structure'
168399
+ ) {
168400
+ lookupType = objType.value;
168401
+ } else if (
168402
+ (objType === null || objType === void 0
168403
+ ? void 0
168404
+ : objType.kind) === 'Ref'
168405
+ ) {
168406
+ lookupType = {kind: 'RefValue', loc: instr.loc};
168407
+ }
168408
+ env.set(
168409
+ instr.lvalue.identifier.id,
168410
+ lookupType !== null && lookupType !== void 0
168411
+ ? lookupType
168412
+ : refTypeOfType(instr.lvalue.identifier)
168413
+ );
168414
+ break;
168174
168415
  }
168175
- break;
168176
- }
168177
- case 'StoreContext':
168178
- case 'StoreLocal': {
168179
- if (
168180
- state.refAccessingFunctions.has(instr.value.value.identifier.id)
168181
- ) {
168182
- state.refAccessingFunctions.add(
168183
- instr.value.lvalue.place.identifier.id
168416
+ case 'LoadContext':
168417
+ case 'LoadLocal': {
168418
+ env.set(
168419
+ instr.lvalue.identifier.id,
168420
+ (_a = env.get(instr.value.place.identifier.id)) !== null &&
168421
+ _a !== void 0
168422
+ ? _a
168423
+ : refTypeOfType(instr.lvalue.identifier)
168184
168424
  );
168185
- state.refAccessingFunctions.add(instr.lvalue.identifier.id);
168425
+ break;
168186
168426
  }
168187
- const refValue = state.refValues.get(instr.value.value.identifier.id);
168188
- if (
168189
- refValue !== undefined ||
168190
- isRefValueType(instr.value.lvalue.place.identifier)
168191
- ) {
168192
- state.refValues.set(
168427
+ case 'StoreContext':
168428
+ case 'StoreLocal': {
168429
+ env.set(
168193
168430
  instr.value.lvalue.place.identifier.id,
168194
- refValue !== null && refValue !== void 0 ? refValue : null
168431
+ (_b = env.get(instr.value.value.identifier.id)) !== null &&
168432
+ _b !== void 0
168433
+ ? _b
168434
+ : refTypeOfType(instr.value.lvalue.place.identifier)
168195
168435
  );
168196
- state.refValues.set(
168436
+ env.set(
168197
168437
  instr.lvalue.identifier.id,
168198
- refValue !== null && refValue !== void 0 ? refValue : null
168438
+ (_c = env.get(instr.value.value.identifier.id)) !== null &&
168439
+ _c !== void 0
168440
+ ? _c
168441
+ : refTypeOfType(instr.lvalue.identifier)
168199
168442
  );
168443
+ break;
168200
168444
  }
168201
- if (state.refs.has(instr.value.value.identifier.id)) {
168202
- state.refs.add(instr.value.lvalue.place.identifier.id);
168203
- state.refs.add(instr.lvalue.identifier.id);
168204
- }
168205
- break;
168206
- }
168207
- case 'Destructure': {
168208
- const destructuredFunction = state.refAccessingFunctions.has(
168209
- instr.value.value.identifier.id
168210
- );
168211
- const destructuredRef = state.refs.has(
168212
- instr.value.value.identifier.id
168213
- );
168214
- for (const lval of eachPatternOperand(instr.value.lvalue.pattern)) {
168215
- if (isUseRefType(lval.identifier)) {
168216
- state.refs.add(lval.identifier.id);
168217
- }
168218
- if (destructuredRef || isRefValueType(lval.identifier)) {
168219
- state.refs.add(lval.identifier.id);
168220
- state.refValues.set(lval.identifier.id, null);
168445
+ case 'Destructure': {
168446
+ const objType = env.get(instr.value.value.identifier.id);
168447
+ let lookupType = null;
168448
+ if (
168449
+ (objType === null || objType === void 0
168450
+ ? void 0
168451
+ : objType.kind) === 'Structure'
168452
+ ) {
168453
+ lookupType = objType.value;
168221
168454
  }
168222
- if (destructuredFunction) {
168223
- state.refAccessingFunctions.add(lval.identifier.id);
168455
+ env.set(
168456
+ instr.lvalue.identifier.id,
168457
+ lookupType !== null && lookupType !== void 0
168458
+ ? lookupType
168459
+ : refTypeOfType(instr.lvalue.identifier)
168460
+ );
168461
+ for (const lval of eachPatternOperand(instr.value.lvalue.pattern)) {
168462
+ env.set(
168463
+ lval.identifier.id,
168464
+ lookupType !== null && lookupType !== void 0
168465
+ ? lookupType
168466
+ : refTypeOfType(lval.identifier)
168467
+ );
168224
168468
  }
168469
+ break;
168225
168470
  }
168226
- break;
168227
- }
168228
- case 'ObjectMethod':
168229
- case 'FunctionExpression': {
168230
- if (
168231
- [...eachInstructionValueOperand(instr.value)].some(
168232
- operand =>
168233
- state.refValues.has(operand.identifier.id) ||
168234
- state.refAccessingFunctions.has(operand.identifier.id)
168235
- ) ||
168236
- ([...eachInstructionValueOperand(instr.value)].some(operand =>
168237
- state.refs.has(operand.identifier.id)
168238
- ) &&
168239
- validateNoRefAccessInRenderImpl(
168240
- instr.value.loweredFunc.func,
168241
- state
168242
- ).isErr())
168243
- ) {
168244
- state.refAccessingFunctions.add(instr.lvalue.identifier.id);
168471
+ case 'ObjectMethod':
168472
+ case 'FunctionExpression': {
168473
+ let returnType = {kind: 'None'};
168474
+ let readRefEffect = false;
168475
+ const result = validateNoRefAccessInRenderImpl(
168476
+ instr.value.loweredFunc.func,
168477
+ env
168478
+ );
168479
+ if (result.isOk()) {
168480
+ returnType = result.unwrap();
168481
+ } else if (result.isErr()) {
168482
+ readRefEffect = true;
168483
+ }
168484
+ env.set(instr.lvalue.identifier.id, {
168485
+ kind: 'Structure',
168486
+ fn: {readRefEffect: readRefEffect, returnType: returnType},
168487
+ value: null,
168488
+ });
168489
+ break;
168245
168490
  }
168246
- break;
168247
- }
168248
- case 'MethodCall': {
168249
- if (!isEffectHook(instr.value.property.identifier)) {
168491
+ case 'MethodCall':
168492
+ case 'CallExpression': {
168493
+ const callee =
168494
+ instr.value.kind === 'CallExpression'
168495
+ ? instr.value.callee
168496
+ : instr.value.property;
168497
+ const hookKind = getHookKindForType(fn.env, callee.identifier.type);
168498
+ let returnType = {kind: 'None'};
168499
+ const fnType = env.get(callee.identifier.id);
168500
+ if (
168501
+ (fnType === null || fnType === void 0 ? void 0 : fnType.kind) ===
168502
+ 'Structure' &&
168503
+ fnType.fn !== null
168504
+ ) {
168505
+ returnType = fnType.fn.returnType;
168506
+ if (fnType.fn.readRefEffect) {
168507
+ errors.push({
168508
+ severity: exports.ErrorSeverity.InvalidReact,
168509
+ reason:
168510
+ 'This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef)',
168511
+ loc: callee.loc,
168512
+ description:
168513
+ callee.identifier.name !== null &&
168514
+ callee.identifier.name.kind === 'named'
168515
+ ? `Function \`${callee.identifier.name.value}\` accesses a ref`
168516
+ : null,
168517
+ suggestions: null,
168518
+ });
168519
+ }
168520
+ }
168250
168521
  for (const operand of eachInstructionValueOperand(instr.value)) {
168251
- validateNoRefAccess(errors, state, operand, operand.loc);
168522
+ if (hookKind != null) {
168523
+ validateNoDirectRefValueAccess(errors, operand, env);
168524
+ } else {
168525
+ validateNoRefAccess(errors, env, operand, operand.loc);
168526
+ }
168252
168527
  }
168528
+ env.set(instr.lvalue.identifier.id, returnType);
168529
+ break;
168253
168530
  }
168254
- break;
168255
- }
168256
- case 'CallExpression': {
168257
- const callee = instr.value.callee;
168258
- const isUseEffect = isEffectHook(callee.identifier);
168259
- if (!isUseEffect) {
168260
- if (state.refAccessingFunctions.has(callee.identifier.id)) {
168261
- errors.push({
168262
- severity: exports.ErrorSeverity.InvalidReact,
168263
- reason:
168264
- 'This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef)',
168265
- loc: callee.loc,
168266
- description:
168267
- callee.identifier.name !== null &&
168268
- callee.identifier.name.kind === 'named'
168269
- ? `Function \`${callee.identifier.name.value}\` accesses a ref`
168270
- : null,
168271
- suggestions: null,
168272
- });
168273
- }
168531
+ case 'ObjectExpression':
168532
+ case 'ArrayExpression': {
168533
+ const types = [];
168274
168534
  for (const operand of eachInstructionValueOperand(instr.value)) {
168275
- validateNoRefAccess(
168276
- errors,
168277
- state,
168278
- operand,
168279
- (_a = state.refValues.get(operand.identifier.id)) !== null &&
168280
- _a !== void 0
168281
- ? _a
168282
- : operand.loc
168535
+ validateNoDirectRefValueAccess(errors, operand, env);
168536
+ types.push(
168537
+ (_d = env.get(operand.identifier.id)) !== null && _d !== void 0
168538
+ ? _d
168539
+ : {kind: 'None'}
168283
168540
  );
168284
168541
  }
168285
- }
168286
- break;
168287
- }
168288
- case 'ObjectExpression':
168289
- case 'ArrayExpression': {
168290
- for (const operand of eachInstructionValueOperand(instr.value)) {
168291
- validateNoDirectRefValueAccess(errors, operand, state);
168292
- if (state.refAccessingFunctions.has(operand.identifier.id)) {
168293
- state.refAccessingFunctions.add(instr.lvalue.identifier.id);
168542
+ const value = joinRefAccessTypes(...types);
168543
+ if (value.kind === 'None') {
168544
+ env.set(instr.lvalue.identifier.id, {kind: 'None'});
168545
+ } else {
168546
+ env.set(instr.lvalue.identifier.id, {
168547
+ kind: 'Structure',
168548
+ value: value,
168549
+ fn: null,
168550
+ });
168294
168551
  }
168295
- if (state.refs.has(operand.identifier.id)) {
168296
- state.refs.add(instr.lvalue.identifier.id);
168552
+ break;
168553
+ }
168554
+ case 'PropertyDelete':
168555
+ case 'PropertyStore':
168556
+ case 'ComputedDelete':
168557
+ case 'ComputedStore': {
168558
+ validateNoRefAccess(errors, env, instr.value.object, instr.loc);
168559
+ for (const operand of eachInstructionValueOperand(instr.value)) {
168560
+ if (operand === instr.value.object) {
168561
+ continue;
168562
+ }
168563
+ validateNoRefValueAccess(errors, env, operand);
168297
168564
  }
168298
- const refValue = state.refValues.get(operand.identifier.id);
168299
- if (refValue !== undefined) {
168300
- state.refValues.set(instr.lvalue.identifier.id, refValue);
168565
+ break;
168566
+ }
168567
+ case 'StartMemoize':
168568
+ case 'FinishMemoize':
168569
+ break;
168570
+ default: {
168571
+ for (const operand of eachInstructionValueOperand(instr.value)) {
168572
+ validateNoRefValueAccess(errors, env, operand);
168301
168573
  }
168574
+ break;
168302
168575
  }
168303
- break;
168304
168576
  }
168305
- case 'PropertyDelete':
168306
- case 'PropertyStore':
168307
- case 'ComputedDelete':
168308
- case 'ComputedStore': {
168309
- validateNoRefAccess(
168310
- errors,
168311
- state,
168312
- instr.value.object,
168313
- (_b = state.refValues.get(instr.value.object.identifier.id)) !==
168314
- null && _b !== void 0
168315
- ? _b
168316
- : instr.loc
168577
+ if (isUseRefType(instr.lvalue.identifier)) {
168578
+ env.set(
168579
+ instr.lvalue.identifier.id,
168580
+ joinRefAccessTypes(
168581
+ (_e = env.get(instr.lvalue.identifier.id)) !== null &&
168582
+ _e !== void 0
168583
+ ? _e
168584
+ : {kind: 'None'},
168585
+ {kind: 'Ref'}
168586
+ )
168317
168587
  );
168318
- for (const operand of eachInstructionValueOperand(instr.value)) {
168319
- if (operand === instr.value.object) {
168320
- continue;
168321
- }
168322
- validateNoRefValueAccess(errors, state, operand);
168323
- }
168324
- break;
168325
168588
  }
168326
- case 'StartMemoize':
168327
- case 'FinishMemoize':
168328
- break;
168329
- default: {
168330
- for (const operand of eachInstructionValueOperand(instr.value)) {
168331
- validateNoRefValueAccess(errors, state, operand);
168332
- }
168333
- break;
168589
+ if (isRefValueType(instr.lvalue.identifier)) {
168590
+ env.set(
168591
+ instr.lvalue.identifier.id,
168592
+ joinRefAccessTypes(
168593
+ (_f = env.get(instr.lvalue.identifier.id)) !== null &&
168594
+ _f !== void 0
168595
+ ? _f
168596
+ : {kind: 'None'},
168597
+ {kind: 'RefValue', loc: instr.loc}
168598
+ )
168599
+ );
168334
168600
  }
168335
168601
  }
168336
- if (isUseRefType(instr.lvalue.identifier)) {
168337
- state.refs.add(instr.lvalue.identifier.id);
168338
- }
168339
- if (
168340
- isRefValueType(instr.lvalue.identifier) &&
168341
- !state.refValues.has(instr.lvalue.identifier.id)
168342
- ) {
168343
- state.refValues.set(instr.lvalue.identifier.id, instr.loc);
168602
+ for (const operand of eachTerminalOperand(block.terminal)) {
168603
+ if (block.terminal.kind !== 'return') {
168604
+ validateNoRefValueAccess(errors, env, operand);
168605
+ } else {
168606
+ validateNoDirectRefValueAccess(errors, operand, env);
168607
+ returnValues.push(env.get(operand.identifier.id));
168608
+ }
168344
168609
  }
168345
168610
  }
168346
- for (const operand of eachTerminalOperand(block.terminal)) {
168347
- if (block.terminal.kind !== 'return') {
168348
- validateNoRefValueAccess(errors, state, operand);
168349
- } else {
168350
- validateNoDirectRefValueAccess(errors, operand, state);
168351
- }
168611
+ if (errors.hasErrors()) {
168612
+ return Err(errors);
168352
168613
  }
168353
168614
  }
168354
- if (errors.hasErrors()) {
168355
- return Err(errors);
168356
- } else {
168357
- return Ok(undefined);
168615
+ CompilerError.invariant(!env.hasChanged(), {
168616
+ reason: 'Ref type environment did not converge',
168617
+ loc: null,
168618
+ });
168619
+ return Ok(
168620
+ joinRefAccessTypes(...returnValues.filter(env => env !== undefined))
168621
+ );
168622
+ }
168623
+ function destructure(type) {
168624
+ if (
168625
+ (type === null || type === void 0 ? void 0 : type.kind) === 'Structure' &&
168626
+ type.value !== null
168627
+ ) {
168628
+ return destructure(type.value);
168358
168629
  }
168630
+ return type;
168359
168631
  }
168360
- function validateNoRefValueAccess(errors, state, operand) {
168632
+ function validateNoRefValueAccess(errors, env, operand) {
168361
168633
  var _a;
168634
+ const type = destructure(env.get(operand.identifier.id));
168362
168635
  if (
168363
- state.refValues.has(operand.identifier.id) ||
168364
- state.refAccessingFunctions.has(operand.identifier.id)
168636
+ (type === null || type === void 0 ? void 0 : type.kind) === 'RefValue' ||
168637
+ ((type === null || type === void 0 ? void 0 : type.kind) === 'Structure' &&
168638
+ ((_a = type.fn) === null || _a === void 0 ? void 0 : _a.readRefEffect))
168365
168639
  ) {
168366
168640
  errors.push({
168367
168641
  severity: exports.ErrorSeverity.InvalidReact,
168368
168642
  reason:
168369
168643
  'Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)',
168370
- loc:
168371
- (_a = state.refValues.get(operand.identifier.id)) !== null &&
168372
- _a !== void 0
168373
- ? _a
168374
- : operand.loc,
168644
+ loc: (type.kind === 'RefValue' && type.loc) || operand.loc,
168375
168645
  description:
168376
168646
  operand.identifier.name !== null &&
168377
168647
  operand.identifier.name.kind === 'named'
@@ -168381,17 +168651,20 @@ function validateNoRefValueAccess(errors, state, operand) {
168381
168651
  });
168382
168652
  }
168383
168653
  }
168384
- function validateNoRefAccess(errors, state, operand, loc) {
168654
+ function validateNoRefAccess(errors, env, operand, loc) {
168655
+ var _a;
168656
+ const type = destructure(env.get(operand.identifier.id));
168385
168657
  if (
168386
- state.refs.has(operand.identifier.id) ||
168387
- state.refValues.has(operand.identifier.id) ||
168388
- state.refAccessingFunctions.has(operand.identifier.id)
168658
+ (type === null || type === void 0 ? void 0 : type.kind) === 'Ref' ||
168659
+ (type === null || type === void 0 ? void 0 : type.kind) === 'RefValue' ||
168660
+ ((type === null || type === void 0 ? void 0 : type.kind) === 'Structure' &&
168661
+ ((_a = type.fn) === null || _a === void 0 ? void 0 : _a.readRefEffect))
168389
168662
  ) {
168390
168663
  errors.push({
168391
168664
  severity: exports.ErrorSeverity.InvalidReact,
168392
168665
  reason:
168393
168666
  'Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)',
168394
- loc: loc,
168667
+ loc: (type.kind === 'RefValue' && type.loc) || loc,
168395
168668
  description:
168396
168669
  operand.identifier.name !== null &&
168397
168670
  operand.identifier.name.kind === 'named'
@@ -168401,18 +168674,15 @@ function validateNoRefAccess(errors, state, operand, loc) {
168401
168674
  });
168402
168675
  }
168403
168676
  }
168404
- function validateNoDirectRefValueAccess(errors, operand, state) {
168677
+ function validateNoDirectRefValueAccess(errors, operand, env) {
168405
168678
  var _a;
168406
- if (state.refValues.has(operand.identifier.id)) {
168679
+ const type = destructure(env.get(operand.identifier.id));
168680
+ if ((type === null || type === void 0 ? void 0 : type.kind) === 'RefValue') {
168407
168681
  errors.push({
168408
168682
  severity: exports.ErrorSeverity.InvalidReact,
168409
168683
  reason:
168410
168684
  'Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)',
168411
- loc:
168412
- (_a = state.refValues.get(operand.identifier.id)) !== null &&
168413
- _a !== void 0
168414
- ? _a
168415
- : operand.loc,
168685
+ loc: (_a = type.loc) !== null && _a !== void 0 ? _a : operand.loc,
168416
168686
  description:
168417
168687
  operand.identifier.name !== null &&
168418
168688
  operand.identifier.name.kind === 'named'