babel-plugin-react-compiler 0.0.0-experimental-b4db8c3-20241001 → 0.0.0-experimental-734b737-20241003

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
@@ -119602,6 +119602,17 @@ function getOrInsertDefault(m, key, defaultValue) {
119602
119602
  return defaultValue;
119603
119603
  }
119604
119604
  }
119605
+ function Set_equal(a, b) {
119606
+ if (a.size !== b.size) {
119607
+ return false;
119608
+ }
119609
+ for (const item of a) {
119610
+ if (!b.has(item)) {
119611
+ return false;
119612
+ }
119613
+ }
119614
+ return true;
119615
+ }
119605
119616
  function Set_union(a, b) {
119606
119617
  const union = new Set(a);
119607
119618
  for (const item of b) {
@@ -119635,6 +119646,15 @@ function Iterable_some(iter, pred) {
119635
119646
  }
119636
119647
  return false;
119637
119648
  }
119649
+ function Set_filter(source, fn) {
119650
+ const result = new Set();
119651
+ for (const entry of source) {
119652
+ if (fn(entry)) {
119653
+ result.add(entry);
119654
+ }
119655
+ }
119656
+ return result;
119657
+ }
119638
119658
  function hasNode(input) {
119639
119659
  return input.node != null;
119640
119660
  }
@@ -144922,7 +144942,7 @@ class ReactiveScopeDependencyTree {
144922
144942
  }
144923
144943
  const depType = inConditional
144924
144944
  ? PropertyAccessType$1.ConditionalDependency
144925
- : isOptional(currNode.accessType)
144945
+ : isOptional$1(currNode.accessType)
144926
144946
  ? PropertyAccessType$1.OptionalDependency
144927
144947
  : PropertyAccessType$1.UnconditionalDependency;
144928
144948
  currNode.accessType = merge$1(currNode.accessType, depType);
@@ -144934,7 +144954,7 @@ class ReactiveScopeDependencyTree {
144934
144954
  _ReactiveScopeDependencyTree_roots,
144935
144955
  'f'
144936
144956
  ).entries()) {
144937
- const deps = deriveMinimalDependenciesInSubtree$1(rootNode, null);
144957
+ const deps = deriveMinimalDependenciesInSubtree(rootNode, null);
144938
144958
  CompilerError.invariant(
144939
144959
  deps.every(
144940
144960
  dep =>
@@ -145092,7 +145112,7 @@ var PropertyAccessType$1;
145092
145112
  PropertyAccessType['OptionalDependency'] = 'OptionalDependency';
145093
145113
  PropertyAccessType['UnconditionalDependency'] = 'UnconditionalDependency';
145094
145114
  })(PropertyAccessType$1 || (PropertyAccessType$1 = {}));
145095
- const MIN_ACCESS_TYPE$1 = PropertyAccessType$1.ConditionalAccess;
145115
+ const MIN_ACCESS_TYPE = PropertyAccessType$1.ConditionalAccess;
145096
145116
  function isUnconditional(access) {
145097
145117
  return (
145098
145118
  access === PropertyAccessType$1.UnconditionalAccess ||
@@ -145106,7 +145126,7 @@ function isDependency$1(access) {
145106
145126
  access === PropertyAccessType$1.UnconditionalDependency
145107
145127
  );
145108
145128
  }
145109
- function isOptional(access) {
145129
+ function isOptional$1(access) {
145110
145130
  return (
145111
145131
  access === PropertyAccessType$1.OptionalAccess ||
145112
145132
  access === PropertyAccessType$1.OptionalDependency
@@ -145116,7 +145136,7 @@ function merge$1(access1, access2) {
145116
145136
  const resultIsUnconditional =
145117
145137
  isUnconditional(access1) || isUnconditional(access2);
145118
145138
  const resultIsDependency = isDependency$1(access1) || isDependency$1(access2);
145119
- const resultIsOptional = isOptional(access1) || isOptional(access2);
145139
+ const resultIsOptional = isOptional$1(access1) || isOptional$1(access2);
145120
145140
  if (resultIsUnconditional) {
145121
145141
  if (resultIsDependency) {
145122
145142
  return PropertyAccessType$1.UnconditionalDependency;
@@ -145153,10 +145173,10 @@ function prependPath(results, path) {
145153
145173
  relativePath: [path, ...result.relativePath],
145154
145174
  }));
145155
145175
  }
145156
- function deriveMinimalDependenciesInSubtree$1(dep, property) {
145176
+ function deriveMinimalDependenciesInSubtree(dep, property) {
145157
145177
  const results = [];
145158
145178
  for (const [childName, childNode] of dep.properties) {
145159
- const childResult = deriveMinimalDependenciesInSubtree$1(
145179
+ const childResult = deriveMinimalDependenciesInSubtree(
145160
145180
  childNode,
145161
145181
  childName
145162
145182
  );
@@ -145322,7 +145342,7 @@ function printSubtree$1(node, includeAccesses) {
145322
145342
  function getOrMakeProperty(node, property) {
145323
145343
  let child = node.properties.get(property);
145324
145344
  if (child == null) {
145325
- child = {properties: new Map(), accessType: MIN_ACCESS_TYPE$1};
145345
+ child = {properties: new Map(), accessType: MIN_ACCESS_TYPE};
145326
145346
  node.properties.set(property, child);
145327
145347
  }
145328
145348
  return child;
@@ -154219,20 +154239,232 @@ function validateNoJSXInTryStatement(fn) {
154219
154239
  throw errors;
154220
154240
  }
154221
154241
  }
154222
- function collectHoistablePropertyLoads(fn, temporaries) {
154242
+ function collectOptionalChainSidemap(fn) {
154243
+ const context = {
154244
+ blocks: fn.body.blocks,
154245
+ seenOptionals: new Set(),
154246
+ processedInstrsInOptional: new Set(),
154247
+ temporariesReadInOptional: new Map(),
154248
+ hoistableObjects: new Map(),
154249
+ };
154250
+ for (const [_, block] of fn.body.blocks) {
154251
+ if (
154252
+ block.terminal.kind === 'optional' &&
154253
+ !context.seenOptionals.has(block.id)
154254
+ ) {
154255
+ traverseOptionalBlock(block, context, null);
154256
+ }
154257
+ }
154258
+ return {
154259
+ temporariesReadInOptional: context.temporariesReadInOptional,
154260
+ processedInstrsInOptional: context.processedInstrsInOptional,
154261
+ hoistableObjects: context.hoistableObjects,
154262
+ };
154263
+ }
154264
+ function matchOptionalTestBlock(terminal, blocks) {
154265
+ const consequentBlock = assertNonNull(blocks.get(terminal.consequent));
154266
+ if (
154267
+ consequentBlock.instructions.length === 2 &&
154268
+ consequentBlock.instructions[0].value.kind === 'PropertyLoad' &&
154269
+ consequentBlock.instructions[1].value.kind === 'StoreLocal'
154270
+ ) {
154271
+ const propertyLoad = consequentBlock.instructions[0];
154272
+ const storeLocal = consequentBlock.instructions[1].value;
154273
+ const storeLocalInstrId = consequentBlock.instructions[1].id;
154274
+ CompilerError.invariant(
154275
+ propertyLoad.value.object.identifier.id === terminal.test.identifier.id,
154276
+ {
154277
+ reason:
154278
+ '[OptionalChainDeps] Inconsistent optional chaining property load',
154279
+ description: `Test=${printIdentifier(terminal.test.identifier)} PropertyLoad base=${printIdentifier(propertyLoad.value.object.identifier)}`,
154280
+ loc: propertyLoad.loc,
154281
+ }
154282
+ );
154283
+ CompilerError.invariant(
154284
+ storeLocal.value.identifier.id === propertyLoad.lvalue.identifier.id,
154285
+ {
154286
+ reason: '[OptionalChainDeps] Unexpected storeLocal',
154287
+ loc: propertyLoad.loc,
154288
+ }
154289
+ );
154290
+ if (
154291
+ consequentBlock.terminal.kind !== 'goto' ||
154292
+ consequentBlock.terminal.variant !== GotoVariant.Break
154293
+ ) {
154294
+ return null;
154295
+ }
154296
+ const alternate = assertNonNull(blocks.get(terminal.alternate));
154297
+ CompilerError.invariant(
154298
+ alternate.instructions.length === 2 &&
154299
+ alternate.instructions[0].value.kind === 'Primitive' &&
154300
+ alternate.instructions[1].value.kind === 'StoreLocal',
154301
+ {reason: 'Unexpected alternate structure', loc: terminal.loc}
154302
+ );
154303
+ return {
154304
+ consequentId: storeLocal.lvalue.place.identifier.id,
154305
+ property: propertyLoad.value.property,
154306
+ propertyId: propertyLoad.lvalue.identifier.id,
154307
+ storeLocalInstrId: storeLocalInstrId,
154308
+ consequentGoto: consequentBlock.terminal.block,
154309
+ };
154310
+ }
154311
+ return null;
154312
+ }
154313
+ function traverseOptionalBlock(optional, context, outerAlternate) {
154314
+ context.seenOptionals.add(optional.id);
154315
+ const maybeTest = context.blocks.get(optional.terminal.test);
154316
+ let test;
154317
+ let baseObject;
154318
+ if (maybeTest.terminal.kind === 'branch') {
154319
+ CompilerError.invariant(optional.terminal.optional, {
154320
+ reason: '[OptionalChainDeps] Expect base case to be always optional',
154321
+ loc: optional.terminal.loc,
154322
+ });
154323
+ if (
154324
+ maybeTest.instructions.length === 0 ||
154325
+ maybeTest.instructions[0].value.kind !== 'LoadLocal'
154326
+ ) {
154327
+ return null;
154328
+ }
154329
+ const path = [];
154330
+ for (let i = 1; i < maybeTest.instructions.length; i++) {
154331
+ const instrVal = maybeTest.instructions[i].value;
154332
+ const prevInstr = maybeTest.instructions[i - 1];
154333
+ if (
154334
+ instrVal.kind === 'PropertyLoad' &&
154335
+ instrVal.object.identifier.id === prevInstr.lvalue.identifier.id
154336
+ ) {
154337
+ path.push({property: instrVal.property, optional: false});
154338
+ } else {
154339
+ return null;
154340
+ }
154341
+ }
154342
+ CompilerError.invariant(
154343
+ maybeTest.terminal.test.identifier.id ===
154344
+ maybeTest.instructions.at(-1).lvalue.identifier.id,
154345
+ {
154346
+ reason: '[OptionalChainDeps] Unexpected test expression',
154347
+ loc: maybeTest.terminal.loc,
154348
+ }
154349
+ );
154350
+ baseObject = {
154351
+ identifier: maybeTest.instructions[0].value.place.identifier,
154352
+ path: path,
154353
+ };
154354
+ test = maybeTest.terminal;
154355
+ } else if (maybeTest.terminal.kind === 'optional') {
154356
+ const testBlock = context.blocks.get(maybeTest.terminal.fallthrough);
154357
+ if (testBlock.terminal.kind !== 'branch') {
154358
+ CompilerError.throwTodo({
154359
+ reason: `Unexpected terminal kind \`${testBlock.terminal.kind}\` for optional fallthrough block`,
154360
+ loc: maybeTest.terminal.loc,
154361
+ });
154362
+ }
154363
+ const innerOptional = traverseOptionalBlock(
154364
+ maybeTest,
154365
+ context,
154366
+ testBlock.terminal.alternate
154367
+ );
154368
+ if (innerOptional == null) {
154369
+ return null;
154370
+ }
154371
+ if (testBlock.terminal.test.identifier.id !== innerOptional) {
154372
+ return null;
154373
+ }
154374
+ if (!optional.terminal.optional) {
154375
+ context.hoistableObjects.set(
154376
+ optional.id,
154377
+ assertNonNull(context.temporariesReadInOptional.get(innerOptional))
154378
+ );
154379
+ }
154380
+ baseObject = assertNonNull(
154381
+ context.temporariesReadInOptional.get(innerOptional)
154382
+ );
154383
+ test = testBlock.terminal;
154384
+ } else {
154385
+ return null;
154386
+ }
154387
+ if (test.alternate === outerAlternate) {
154388
+ CompilerError.invariant(optional.instructions.length === 0, {
154389
+ reason:
154390
+ '[OptionalChainDeps] Unexpected instructions an inner optional block. ' +
154391
+ 'This indicates that the compiler may be incorrectly concatenating two unrelated optional chains',
154392
+ loc: optional.terminal.loc,
154393
+ });
154394
+ }
154395
+ const matchConsequentResult = matchOptionalTestBlock(test, context.blocks);
154396
+ if (!matchConsequentResult) {
154397
+ return null;
154398
+ }
154399
+ CompilerError.invariant(
154400
+ matchConsequentResult.consequentGoto === optional.terminal.fallthrough,
154401
+ {
154402
+ reason: '[OptionalChainDeps] Unexpected optional goto-fallthrough',
154403
+ description: `${matchConsequentResult.consequentGoto} != ${optional.terminal.fallthrough}`,
154404
+ loc: optional.terminal.loc,
154405
+ }
154406
+ );
154407
+ const load = {
154408
+ identifier: baseObject.identifier,
154409
+ path: [
154410
+ ...baseObject.path,
154411
+ {
154412
+ property: matchConsequentResult.property,
154413
+ optional: optional.terminal.optional,
154414
+ },
154415
+ ],
154416
+ };
154417
+ context.processedInstrsInOptional.add(
154418
+ matchConsequentResult.storeLocalInstrId
154419
+ );
154420
+ context.processedInstrsInOptional.add(test.id);
154421
+ context.temporariesReadInOptional.set(
154422
+ matchConsequentResult.consequentId,
154423
+ load
154424
+ );
154425
+ context.temporariesReadInOptional.set(matchConsequentResult.propertyId, load);
154426
+ return matchConsequentResult.consequentId;
154427
+ }
154428
+ function collectHoistablePropertyLoads(
154429
+ fn,
154430
+ temporaries,
154431
+ hoistableFromOptionals,
154432
+ nestedFnImmutableContext
154433
+ ) {
154223
154434
  const registry = new PropertyPathRegistry();
154224
- const nodes = collectNonNullsInBlocks(fn, temporaries, registry);
154225
- propagateNonNull(fn, nodes);
154226
- const nodesKeyedByScopeId = new Map();
154435
+ const functionExpressionLoads = collectFunctionExpressionFakeLoads(fn);
154436
+ const actuallyEvaluatedTemporaries = new Map(
154437
+ [...temporaries].filter(([id]) => !functionExpressionLoads.has(id))
154438
+ );
154439
+ const knownImmutableIdentifiers = new Set();
154440
+ if (fn.fnType === 'Component' || fn.fnType === 'Hook') {
154441
+ for (const p of fn.params) {
154442
+ if (p.kind === 'Identifier') {
154443
+ knownImmutableIdentifiers.add(p.identifier.id);
154444
+ }
154445
+ }
154446
+ }
154447
+ const nodes = collectNonNullsInBlocks(fn, {
154448
+ temporaries: actuallyEvaluatedTemporaries,
154449
+ knownImmutableIdentifiers: knownImmutableIdentifiers,
154450
+ hoistableFromOptionals: hoistableFromOptionals,
154451
+ registry: registry,
154452
+ nestedFnImmutableContext: nestedFnImmutableContext,
154453
+ });
154454
+ propagateNonNull(fn, nodes, registry);
154455
+ return nodes;
154456
+ }
154457
+ function keyByScopeId(fn, source) {
154458
+ const keyedByScopeId = new Map();
154227
154459
  for (const [_, block] of fn.body.blocks) {
154228
154460
  if (block.terminal.kind === 'scope') {
154229
- nodesKeyedByScopeId.set(
154461
+ keyedByScopeId.set(
154230
154462
  block.terminal.scope.id,
154231
- nodes.get(block.terminal.block)
154463
+ source.get(block.terminal.block)
154232
154464
  );
154233
154465
  }
154234
154466
  }
154235
- return nodesKeyedByScopeId;
154467
+ return keyedByScopeId;
154236
154468
  }
154237
154469
  class PropertyPathRegistry {
154238
154470
  constructor() {
@@ -154244,7 +154476,9 @@ class PropertyPathRegistry {
154244
154476
  rootNode = {
154245
154477
  root: identifier.id,
154246
154478
  properties: new Map(),
154479
+ optionalProperties: new Map(),
154247
154480
  fullPath: {identifier: identifier, path: []},
154481
+ hasOptional: false,
154248
154482
  parent: null,
154249
154483
  };
154250
154484
  this.roots.set(identifier.id, rootNode);
@@ -154252,23 +154486,20 @@ class PropertyPathRegistry {
154252
154486
  return rootNode;
154253
154487
  }
154254
154488
  static getOrCreatePropertyEntry(parent, entry) {
154255
- if (entry.optional) {
154256
- CompilerError.throwTodo({
154257
- reason: 'handle optional nodes',
154258
- loc: GeneratedSource,
154259
- });
154260
- }
154261
- let child = parent.properties.get(entry.property);
154489
+ const map = entry.optional ? parent.optionalProperties : parent.properties;
154490
+ let child = map.get(entry.property);
154262
154491
  if (child == null) {
154263
154492
  child = {
154264
154493
  properties: new Map(),
154494
+ optionalProperties: new Map(),
154265
154495
  parent: parent,
154266
154496
  fullPath: {
154267
154497
  identifier: parent.fullPath.identifier,
154268
154498
  path: parent.fullPath.path.concat(entry),
154269
154499
  },
154500
+ hasOptional: parent.hasOptional || entry.optional,
154270
154501
  };
154271
- parent.properties.set(entry.property, child);
154502
+ map.set(entry.property, child);
154272
154503
  }
154273
154504
  return child;
154274
154505
  }
@@ -154289,34 +154520,45 @@ class PropertyPathRegistry {
154289
154520
  );
154290
154521
  }
154291
154522
  }
154292
- function addNonNullPropertyPath(
154293
- source,
154294
- sourceNode,
154295
- instrId,
154296
- knownImmutableIdentifiers,
154297
- result
154298
- ) {
154299
- const isMutableAtInstr =
154300
- source.mutableRange.end > source.mutableRange.start + 1 &&
154301
- source.scope != null &&
154302
- inRange({id: instrId}, source.scope.range);
154303
- if (
154304
- !isMutableAtInstr ||
154305
- knownImmutableIdentifiers.has(sourceNode.fullPath.identifier.id)
154306
- ) {
154307
- result.add(sourceNode);
154523
+ function getMaybeNonNullInInstruction(instr, context) {
154524
+ var _a, _b, _c;
154525
+ let path = null;
154526
+ if (instr.kind === 'PropertyLoad') {
154527
+ path =
154528
+ (_a = context.temporaries.get(instr.object.identifier.id)) !== null &&
154529
+ _a !== void 0
154530
+ ? _a
154531
+ : {identifier: instr.object.identifier, path: []};
154532
+ } else if (instr.kind === 'Destructure') {
154533
+ path =
154534
+ (_b = context.temporaries.get(instr.value.identifier.id)) !== null &&
154535
+ _b !== void 0
154536
+ ? _b
154537
+ : null;
154538
+ } else if (instr.kind === 'ComputedLoad') {
154539
+ path =
154540
+ (_c = context.temporaries.get(instr.object.identifier.id)) !== null &&
154541
+ _c !== void 0
154542
+ ? _c
154543
+ : null;
154308
154544
  }
154545
+ return path != null ? context.registry.getOrCreateProperty(path) : null;
154309
154546
  }
154310
- function collectNonNullsInBlocks(fn, temporaries, registry) {
154311
- var _a;
154312
- const knownImmutableIdentifiers = new Set();
154313
- if (fn.fnType === 'Component' || fn.fnType === 'Hook') {
154314
- for (const p of fn.params) {
154315
- if (p.kind === 'Identifier') {
154316
- knownImmutableIdentifiers.add(p.identifier.id);
154317
- }
154318
- }
154547
+ function isImmutableAtInstr(identifier, instr, context) {
154548
+ if (context.nestedFnImmutableContext != null) {
154549
+ return context.nestedFnImmutableContext.has(identifier.id);
154550
+ } else {
154551
+ const mutableAtInstr =
154552
+ identifier.mutableRange.end > identifier.mutableRange.start + 1 &&
154553
+ identifier.scope != null &&
154554
+ inRange({id: instr}, identifier.scope.range);
154555
+ return (
154556
+ !mutableAtInstr || context.knownImmutableIdentifiers.has(identifier.id)
154557
+ );
154319
154558
  }
154559
+ }
154560
+ function collectNonNullsInBlocks(fn, context) {
154561
+ var _a;
154320
154562
  const knownNonNullIdentifiers = new Set();
154321
154563
  if (
154322
154564
  fn.fnType === 'Component' &&
@@ -154324,48 +154566,56 @@ function collectNonNullsInBlocks(fn, temporaries, registry) {
154324
154566
  fn.params[0].kind === 'Identifier'
154325
154567
  ) {
154326
154568
  const identifier = fn.params[0].identifier;
154327
- knownNonNullIdentifiers.add(registry.getOrCreateIdentifier(identifier));
154569
+ knownNonNullIdentifiers.add(
154570
+ context.registry.getOrCreateIdentifier(identifier)
154571
+ );
154328
154572
  }
154329
154573
  const nodes = new Map();
154330
154574
  for (const [_, block] of fn.body.blocks) {
154331
154575
  const assumedNonNullObjects = new Set(knownNonNullIdentifiers);
154576
+ const maybeOptionalChain = context.hoistableFromOptionals.get(block.id);
154577
+ if (maybeOptionalChain != null) {
154578
+ assumedNonNullObjects.add(
154579
+ context.registry.getOrCreateProperty(maybeOptionalChain)
154580
+ );
154581
+ }
154332
154582
  for (const instr of block.instructions) {
154333
- if (instr.value.kind === 'PropertyLoad') {
154334
- const source =
154335
- (_a = temporaries.get(instr.value.object.identifier.id)) !== null &&
154336
- _a !== void 0
154583
+ const maybeNonNull = getMaybeNonNullInInstruction(instr.value, context);
154584
+ if (
154585
+ maybeNonNull != null &&
154586
+ isImmutableAtInstr(maybeNonNull.fullPath.identifier, instr.id, context)
154587
+ ) {
154588
+ assumedNonNullObjects.add(maybeNonNull);
154589
+ }
154590
+ if (
154591
+ instr.value.kind === 'FunctionExpression' &&
154592
+ !fn.env.config.enableTreatFunctionDepsAsConditional
154593
+ ) {
154594
+ const innerFn = instr.value.loweredFunc;
154595
+ const innerTemporaries = collectTemporariesSidemap(
154596
+ innerFn.func,
154597
+ new Set()
154598
+ );
154599
+ const innerOptionals = collectOptionalChainSidemap(innerFn.func);
154600
+ const innerHoistableMap = collectHoistablePropertyLoads(
154601
+ innerFn.func,
154602
+ innerTemporaries,
154603
+ innerOptionals.hoistableObjects,
154604
+ (_a = context.nestedFnImmutableContext) !== null && _a !== void 0
154337
154605
  ? _a
154338
- : {identifier: instr.value.object.identifier, path: []};
154339
- addNonNullPropertyPath(
154340
- instr.value.object.identifier,
154341
- registry.getOrCreateProperty(source),
154342
- instr.id,
154343
- knownImmutableIdentifiers,
154344
- assumedNonNullObjects
154606
+ : new Set(
154607
+ innerFn.func.context
154608
+ .filter(place =>
154609
+ isImmutableAtInstr(place.identifier, instr.id, context)
154610
+ )
154611
+ .map(place => place.identifier.id)
154612
+ )
154345
154613
  );
154346
- } else if (instr.value.kind === 'Destructure') {
154347
- const source = instr.value.value.identifier.id;
154348
- const sourceNode = temporaries.get(source);
154349
- if (sourceNode != null) {
154350
- addNonNullPropertyPath(
154351
- instr.value.value.identifier,
154352
- registry.getOrCreateProperty(sourceNode),
154353
- instr.id,
154354
- knownImmutableIdentifiers,
154355
- assumedNonNullObjects
154356
- );
154357
- }
154358
- } else if (instr.value.kind === 'ComputedLoad') {
154359
- const source = instr.value.object.identifier.id;
154360
- const sourceNode = temporaries.get(source);
154361
- if (sourceNode != null) {
154362
- addNonNullPropertyPath(
154363
- instr.value.object.identifier,
154364
- registry.getOrCreateProperty(sourceNode),
154365
- instr.id,
154366
- knownImmutableIdentifiers,
154367
- assumedNonNullObjects
154368
- );
154614
+ const innerHoistables = assertNonNull(
154615
+ innerHoistableMap.get(innerFn.func.body.entry)
154616
+ );
154617
+ for (const entry of innerHoistables.assumedNonNullObjects) {
154618
+ assumedNonNullObjects.add(entry);
154369
154619
  }
154370
154620
  }
154371
154621
  }
@@ -154376,7 +154626,7 @@ function collectNonNullsInBlocks(fn, temporaries, registry) {
154376
154626
  }
154377
154627
  return nodes;
154378
154628
  }
154379
- function propagateNonNull(fn, nodes) {
154629
+ function propagateNonNull(fn, nodes, registry) {
154380
154630
  const blockSuccessors = new Map();
154381
154631
  const terminalPreds = new Set();
154382
154632
  for (const [blockId, block] of fn.body.blocks) {
@@ -154425,9 +154675,10 @@ function propagateNonNull(fn, nodes) {
154425
154675
  );
154426
154676
  const prevObjects = assertNonNull(nodes.get(nodeId)).assumedNonNullObjects;
154427
154677
  const mergedObjects = Set_union(prevObjects, neighborAccesses);
154678
+ reduceMaybeOptionalChains(mergedObjects, registry);
154428
154679
  assertNonNull(nodes.get(nodeId)).assumedNonNullObjects = mergedObjects;
154429
154680
  traversalState.set(nodeId, 'done');
154430
- changed || (changed = prevObjects.size !== mergedObjects.size);
154681
+ changed || (changed = !Set_equal(prevObjects, mergedObjects));
154431
154682
  return changed;
154432
154683
  }
154433
154684
  const traversalState = new Map();
@@ -154470,70 +154721,176 @@ function assertNonNull(value, source) {
154470
154721
  });
154471
154722
  return value;
154472
154723
  }
154473
- var _ReactiveScopeDependencyTreeHIR_instances,
154474
- _ReactiveScopeDependencyTreeHIR_roots,
154475
- _ReactiveScopeDependencyTreeHIR_getOrCreateRoot;
154724
+ function reduceMaybeOptionalChains(nodes, registry) {
154725
+ let optionalChainNodes = Set_filter(nodes, n => n.hasOptional);
154726
+ if (optionalChainNodes.size === 0) {
154727
+ return;
154728
+ }
154729
+ let changed;
154730
+ do {
154731
+ changed = false;
154732
+ for (const original of optionalChainNodes) {
154733
+ let {identifier: identifier, path: origPath} = original.fullPath;
154734
+ let currNode = registry.getOrCreateIdentifier(identifier);
154735
+ for (let i = 0; i < origPath.length; i++) {
154736
+ const entry = origPath[i];
154737
+ const nextEntry =
154738
+ entry.optional && nodes.has(currNode)
154739
+ ? {property: entry.property, optional: false}
154740
+ : entry;
154741
+ currNode = PropertyPathRegistry.getOrCreatePropertyEntry(
154742
+ currNode,
154743
+ nextEntry
154744
+ );
154745
+ }
154746
+ if (currNode !== original) {
154747
+ changed = true;
154748
+ optionalChainNodes.delete(original);
154749
+ optionalChainNodes.add(currNode);
154750
+ nodes.delete(original);
154751
+ nodes.add(currNode);
154752
+ }
154753
+ }
154754
+ } while (changed);
154755
+ }
154756
+ function collectFunctionExpressionFakeLoads(fn) {
154757
+ const sources = new Map();
154758
+ const functionExpressionReferences = new Set();
154759
+ for (const [_, block] of fn.body.blocks) {
154760
+ for (const {lvalue: lvalue, value: value} of block.instructions) {
154761
+ if (value.kind === 'FunctionExpression') {
154762
+ for (const reference of value.loweredFunc.dependencies) {
154763
+ let curr = reference.identifier.id;
154764
+ while (curr != null) {
154765
+ functionExpressionReferences.add(curr);
154766
+ curr = sources.get(curr);
154767
+ }
154768
+ }
154769
+ } else if (value.kind === 'PropertyLoad') {
154770
+ sources.set(lvalue.identifier.id, value.object.identifier.id);
154771
+ }
154772
+ }
154773
+ }
154774
+ return functionExpressionReferences;
154775
+ }
154776
+ var _a,
154777
+ _ReactiveScopeDependencyTreeHIR_hoistableObjects,
154778
+ _ReactiveScopeDependencyTreeHIR_deps,
154779
+ _ReactiveScopeDependencyTreeHIR_getOrCreateRoot,
154780
+ _ReactiveScopeDependencyTreeHIR_debugImpl;
154476
154781
  class ReactiveScopeDependencyTreeHIR {
154477
- constructor() {
154478
- _ReactiveScopeDependencyTreeHIR_instances.add(this);
154479
- _ReactiveScopeDependencyTreeHIR_roots.set(this, new Map());
154782
+ constructor(hoistableObjects) {
154783
+ var _b;
154784
+ _ReactiveScopeDependencyTreeHIR_hoistableObjects.set(this, new Map());
154785
+ _ReactiveScopeDependencyTreeHIR_deps.set(this, new Map());
154786
+ for (const {path: path, identifier: identifier} of hoistableObjects) {
154787
+ let currNode = __classPrivateFieldGet(
154788
+ _a,
154789
+ _a,
154790
+ 'm',
154791
+ _ReactiveScopeDependencyTreeHIR_getOrCreateRoot
154792
+ ).call(
154793
+ _a,
154794
+ identifier,
154795
+ __classPrivateFieldGet(
154796
+ this,
154797
+ _ReactiveScopeDependencyTreeHIR_hoistableObjects,
154798
+ 'f'
154799
+ ),
154800
+ path.length > 0 && path[0].optional ? 'Optional' : 'NonNull'
154801
+ );
154802
+ for (let i = 0; i < path.length; i++) {
154803
+ const prevAccessType =
154804
+ (_b = currNode.properties.get(path[i].property)) === null ||
154805
+ _b === void 0
154806
+ ? void 0
154807
+ : _b.accessType;
154808
+ const accessType =
154809
+ i + 1 < path.length && path[i + 1].optional ? 'Optional' : 'NonNull';
154810
+ CompilerError.invariant(
154811
+ prevAccessType == null || prevAccessType === accessType,
154812
+ {reason: 'Conflicting access types', loc: GeneratedSource}
154813
+ );
154814
+ let nextNode = currNode.properties.get(path[i].property);
154815
+ if (nextNode == null) {
154816
+ nextNode = {properties: new Map(), accessType: accessType};
154817
+ currNode.properties.set(path[i].property, nextNode);
154818
+ }
154819
+ currNode = nextNode;
154820
+ }
154821
+ }
154480
154822
  }
154481
154823
  addDependency(dep) {
154482
- const {path: path} = dep;
154483
- let currNode = __classPrivateFieldGet(
154484
- this,
154485
- _ReactiveScopeDependencyTreeHIR_instances,
154824
+ const {identifier: identifier, path: path} = dep;
154825
+ let depCursor = __classPrivateFieldGet(
154826
+ _a,
154827
+ _a,
154486
154828
  'm',
154487
154829
  _ReactiveScopeDependencyTreeHIR_getOrCreateRoot
154488
- ).call(this, dep.identifier, MIN_ACCESS_TYPE);
154489
- const accessType = PropertyAccessType.Access;
154490
- currNode.accessType = merge(currNode.accessType, accessType);
154491
- for (const property of path) {
154492
- let currChild = makeOrMergeProperty(
154493
- currNode,
154494
- property.property,
154495
- accessType
154496
- );
154497
- currNode = currChild;
154498
- }
154499
- currNode.accessType = merge(
154500
- currNode.accessType,
154501
- PropertyAccessType.Dependency
154830
+ ).call(
154831
+ _a,
154832
+ identifier,
154833
+ __classPrivateFieldGet(this, _ReactiveScopeDependencyTreeHIR_deps, 'f'),
154834
+ PropertyAccessType.UnconditionalAccess
154502
154835
  );
154503
- }
154504
- markNodesNonNull(dep) {
154505
- const accessType = PropertyAccessType.NonNullAccess;
154506
- let currNode = __classPrivateFieldGet(
154836
+ let hoistableCursor = __classPrivateFieldGet(
154507
154837
  this,
154508
- _ReactiveScopeDependencyTreeHIR_roots,
154838
+ _ReactiveScopeDependencyTreeHIR_hoistableObjects,
154509
154839
  'f'
154510
- ).get(dep.identifier);
154511
- let cursor = 0;
154512
- while (currNode != null && cursor < dep.path.length) {
154513
- currNode.accessType = merge(currNode.accessType, accessType);
154514
- currNode = currNode.properties.get(dep.path[cursor++].property);
154515
- }
154516
- if (currNode != null) {
154517
- currNode.accessType = merge(currNode.accessType, accessType);
154840
+ ).get(identifier);
154841
+ for (const entry of path) {
154842
+ let nextHoistableCursor;
154843
+ let nextDepCursor;
154844
+ if (entry.optional) {
154845
+ if (hoistableCursor != null) {
154846
+ nextHoistableCursor =
154847
+ hoistableCursor === null || hoistableCursor === void 0
154848
+ ? void 0
154849
+ : hoistableCursor.properties.get(entry.property);
154850
+ }
154851
+ let accessType;
154852
+ if (
154853
+ hoistableCursor != null &&
154854
+ hoistableCursor.accessType === 'NonNull'
154855
+ ) {
154856
+ accessType = PropertyAccessType.UnconditionalAccess;
154857
+ } else {
154858
+ accessType = PropertyAccessType.OptionalAccess;
154859
+ }
154860
+ nextDepCursor = makeOrMergeProperty(
154861
+ depCursor,
154862
+ entry.property,
154863
+ accessType
154864
+ );
154865
+ } else if (
154866
+ hoistableCursor != null &&
154867
+ hoistableCursor.accessType === 'NonNull'
154868
+ ) {
154869
+ nextHoistableCursor = hoistableCursor.properties.get(entry.property);
154870
+ nextDepCursor = makeOrMergeProperty(
154871
+ depCursor,
154872
+ entry.property,
154873
+ PropertyAccessType.UnconditionalAccess
154874
+ );
154875
+ } else {
154876
+ break;
154877
+ }
154878
+ depCursor = nextDepCursor;
154879
+ hoistableCursor = nextHoistableCursor;
154518
154880
  }
154881
+ depCursor.accessType = merge(
154882
+ depCursor.accessType,
154883
+ PropertyAccessType.OptionalDependency
154884
+ );
154519
154885
  }
154520
154886
  deriveMinimalDependencies() {
154521
154887
  const results = new Set();
154522
154888
  for (const [rootId, rootNode] of __classPrivateFieldGet(
154523
154889
  this,
154524
- _ReactiveScopeDependencyTreeHIR_roots,
154890
+ _ReactiveScopeDependencyTreeHIR_deps,
154525
154891
  'f'
154526
154892
  ).entries()) {
154527
- {
154528
- assertWellFormedTree(rootNode);
154529
- }
154530
- const deps = deriveMinimalDependenciesInSubtree(rootNode, []);
154531
- for (const dep of deps) {
154532
- results.add({
154533
- identifier: rootId,
154534
- path: dep.path.map(s => ({property: s, optional: false})),
154535
- });
154536
- }
154893
+ collectMinimalDependenciesInSubtree(rootNode, rootId, [], results);
154537
154894
  }
154538
154895
  return results;
154539
154896
  }
@@ -154541,7 +154898,7 @@ class ReactiveScopeDependencyTreeHIR {
154541
154898
  let res = [];
154542
154899
  for (const [rootId, rootNode] of __classPrivateFieldGet(
154543
154900
  this,
154544
- _ReactiveScopeDependencyTreeHIR_roots,
154901
+ _ReactiveScopeDependencyTreeHIR_deps,
154545
154902
  'f'
154546
154903
  ).entries()) {
154547
154904
  const rootResults = printSubtree(rootNode, includeAccesses).map(
@@ -154551,95 +154908,106 @@ class ReactiveScopeDependencyTreeHIR {
154551
154908
  }
154552
154909
  return res.flat().join('\n');
154553
154910
  }
154911
+ static debug(roots) {
154912
+ const buf = [`tree() [`];
154913
+ for (const [rootId, rootNode] of roots) {
154914
+ buf.push(`${printIdentifier(rootId)} (${rootNode.accessType}):`);
154915
+ __classPrivateFieldGet(
154916
+ this,
154917
+ _a,
154918
+ 'm',
154919
+ _ReactiveScopeDependencyTreeHIR_debugImpl
154920
+ ).call(this, buf, rootNode, 1);
154921
+ }
154922
+ buf.push(']');
154923
+ return buf.length > 2 ? buf.join('\n') : buf.join('');
154924
+ }
154554
154925
  }
154555
- (_ReactiveScopeDependencyTreeHIR_roots = new WeakMap()),
154556
- (_ReactiveScopeDependencyTreeHIR_instances = new WeakSet()),
154926
+ (_a = ReactiveScopeDependencyTreeHIR),
154927
+ (_ReactiveScopeDependencyTreeHIR_hoistableObjects = new WeakMap()),
154928
+ (_ReactiveScopeDependencyTreeHIR_deps = new WeakMap()),
154557
154929
  (_ReactiveScopeDependencyTreeHIR_getOrCreateRoot =
154558
154930
  function _ReactiveScopeDependencyTreeHIR_getOrCreateRoot(
154559
154931
  identifier,
154560
- accessType
154932
+ roots,
154933
+ defaultAccessType
154561
154934
  ) {
154562
- let rootNode = __classPrivateFieldGet(
154563
- this,
154564
- _ReactiveScopeDependencyTreeHIR_roots,
154565
- 'f'
154566
- ).get(identifier);
154935
+ let rootNode = roots.get(identifier);
154567
154936
  if (rootNode === undefined) {
154568
- rootNode = {properties: new Map(), accessType: accessType};
154937
+ rootNode = {properties: new Map(), accessType: defaultAccessType};
154938
+ roots.set(identifier, rootNode);
154939
+ }
154940
+ return rootNode;
154941
+ }),
154942
+ (_ReactiveScopeDependencyTreeHIR_debugImpl =
154943
+ function _ReactiveScopeDependencyTreeHIR_debugImpl(buf, node, depth = 0) {
154944
+ for (const [property, childNode] of node.properties) {
154945
+ buf.push(
154946
+ `${' '.repeat(depth)}.${property} (${childNode.accessType}):`
154947
+ );
154569
154948
  __classPrivateFieldGet(
154570
154949
  this,
154571
- _ReactiveScopeDependencyTreeHIR_roots,
154572
- 'f'
154573
- ).set(identifier, rootNode);
154950
+ _a,
154951
+ 'm',
154952
+ _ReactiveScopeDependencyTreeHIR_debugImpl
154953
+ ).call(this, buf, childNode, depth + 1);
154574
154954
  }
154575
- return rootNode;
154576
154955
  });
154577
154956
  var PropertyAccessType;
154578
154957
  (function (PropertyAccessType) {
154579
- PropertyAccessType['Access'] = 'Access';
154580
- PropertyAccessType['NonNullAccess'] = 'NonNullAccess';
154581
- PropertyAccessType['Dependency'] = 'Dependency';
154582
- PropertyAccessType['NonNullDependency'] = 'NonNullDependency';
154958
+ PropertyAccessType['OptionalAccess'] = 'OptionalAccess';
154959
+ PropertyAccessType['UnconditionalAccess'] = 'UnconditionalAccess';
154960
+ PropertyAccessType['OptionalDependency'] = 'OptionalDependency';
154961
+ PropertyAccessType['UnconditionalDependency'] = 'UnconditionalDependency';
154583
154962
  })(PropertyAccessType || (PropertyAccessType = {}));
154584
- const MIN_ACCESS_TYPE = PropertyAccessType.Access;
154585
- function isNonNull(access) {
154963
+ function isOptional(access) {
154586
154964
  return (
154587
- access === PropertyAccessType.NonNullAccess ||
154588
- access === PropertyAccessType.NonNullDependency
154965
+ access === PropertyAccessType.OptionalAccess ||
154966
+ access === PropertyAccessType.OptionalDependency
154589
154967
  );
154590
154968
  }
154591
154969
  function isDependency(access) {
154592
154970
  return (
154593
- access === PropertyAccessType.Dependency ||
154594
- access === PropertyAccessType.NonNullDependency
154971
+ access === PropertyAccessType.OptionalDependency ||
154972
+ access === PropertyAccessType.UnconditionalDependency
154595
154973
  );
154596
154974
  }
154597
154975
  function merge(access1, access2) {
154598
- const resultisNonNull = isNonNull(access1) || isNonNull(access2);
154976
+ const resultIsUnconditional = !(isOptional(access1) && isOptional(access2));
154599
154977
  const resultIsDependency = isDependency(access1) || isDependency(access2);
154600
- if (resultisNonNull) {
154978
+ if (resultIsUnconditional) {
154601
154979
  if (resultIsDependency) {
154602
- return PropertyAccessType.NonNullDependency;
154980
+ return PropertyAccessType.UnconditionalDependency;
154603
154981
  } else {
154604
- return PropertyAccessType.NonNullAccess;
154982
+ return PropertyAccessType.UnconditionalAccess;
154605
154983
  }
154606
154984
  } else {
154607
154985
  if (resultIsDependency) {
154608
- return PropertyAccessType.Dependency;
154986
+ return PropertyAccessType.OptionalDependency;
154609
154987
  } else {
154610
- return PropertyAccessType.Access;
154988
+ return PropertyAccessType.OptionalAccess;
154611
154989
  }
154612
154990
  }
154613
154991
  }
154614
- function assertWellFormedTree(node) {
154615
- let nonNullInChildren = false;
154616
- for (const childNode of node.properties.values()) {
154617
- assertWellFormedTree(childNode);
154618
- nonNullInChildren || (nonNullInChildren = isNonNull(childNode.accessType));
154619
- }
154620
- if (nonNullInChildren) {
154621
- CompilerError.invariant(isNonNull(node.accessType), {
154622
- reason:
154623
- '[DeriveMinimialDependencies] Not well formed tree, unexpected non-null node',
154624
- description: node.accessType,
154625
- loc: GeneratedSource,
154626
- });
154627
- }
154628
- }
154629
- function deriveMinimalDependenciesInSubtree(node, path) {
154992
+ function collectMinimalDependenciesInSubtree(
154993
+ node,
154994
+ rootIdentifier,
154995
+ path,
154996
+ results
154997
+ ) {
154630
154998
  if (isDependency(node.accessType)) {
154631
- return [{path: path}];
154999
+ results.add({identifier: rootIdentifier, path: path});
154632
155000
  } else {
154633
- if (isNonNull(node.accessType)) {
154634
- const result = [];
154635
- for (const [childName, childNode] of node.properties) {
154636
- result.push(
154637
- ...deriveMinimalDependenciesInSubtree(childNode, [...path, childName])
154638
- );
154639
- }
154640
- return result;
154641
- } else {
154642
- return [{path: path}];
155001
+ for (const [childName, childNode] of node.properties) {
155002
+ collectMinimalDependenciesInSubtree(
155003
+ childNode,
155004
+ rootIdentifier,
155005
+ [
155006
+ ...path,
155007
+ {property: childName, optional: isOptional(childNode.accessType)},
155008
+ ],
155009
+ results
155010
+ );
154643
155011
  }
154644
155012
  }
154645
155013
  }
@@ -154677,18 +155045,36 @@ function propagateScopeDependenciesHIR(fn) {
154677
155045
  const usedOutsideDeclaringScope =
154678
155046
  findTemporariesUsedOutsideDeclaringScope(fn);
154679
155047
  const temporaries = collectTemporariesSidemap(fn, usedOutsideDeclaringScope);
154680
- const hoistablePropertyLoads = collectHoistablePropertyLoads(fn, temporaries);
155048
+ const {
155049
+ temporariesReadInOptional: temporariesReadInOptional,
155050
+ processedInstrsInOptional: processedInstrsInOptional,
155051
+ hoistableObjects: hoistableObjects,
155052
+ } = collectOptionalChainSidemap(fn);
155053
+ const hoistablePropertyLoads = keyByScopeId(
155054
+ fn,
155055
+ collectHoistablePropertyLoads(fn, temporaries, hoistableObjects, null)
155056
+ );
154681
155057
  const scopeDeps = collectDependencies(
154682
155058
  fn,
154683
155059
  usedOutsideDeclaringScope,
154684
- temporaries
155060
+ new Map([...temporaries, ...temporariesReadInOptional]),
155061
+ processedInstrsInOptional
154685
155062
  );
154686
155063
  for (const [scope, deps] of scopeDeps) {
154687
- const tree = new ReactiveScopeDependencyTreeHIR();
155064
+ if (deps.length === 0) {
155065
+ continue;
155066
+ }
155067
+ const hoistables = hoistablePropertyLoads.get(scope.id);
155068
+ CompilerError.invariant(hoistables != null, {
155069
+ reason: '[PropagateScopeDependencies] Scope not found in tracked blocks',
155070
+ loc: GeneratedSource,
155071
+ });
155072
+ const tree = new ReactiveScopeDependencyTreeHIR(
155073
+ [...hoistables.assumedNonNullObjects].map(o => o.fullPath)
155074
+ );
154688
155075
  for (const dep of deps) {
154689
155076
  tree.addDependency(Object.assign({}, dep));
154690
155077
  }
154691
- recordHoistablePropertyReads(hoistablePropertyLoads, scope.id, tree);
154692
155078
  const candidates = tree.deriveMinimalDependencies();
154693
155079
  for (const candidateDep of candidates) {
154694
155080
  if (
@@ -154765,7 +155151,12 @@ function collectTemporariesSidemap(fn, usedOutsideDeclaringScope) {
154765
155151
  lvalue.identifier.declarationId
154766
155152
  );
154767
155153
  if (value.kind === 'PropertyLoad' && !usedOutside) {
154768
- const property = getProperty(value.object, value.property, temporaries);
155154
+ const property = getProperty(
155155
+ value.object,
155156
+ value.property,
155157
+ false,
155158
+ temporaries
155159
+ );
154769
155160
  temporaries.set(lvalue.identifier.id, property);
154770
155161
  } else if (
154771
155162
  value.kind === 'LoadLocal' &&
@@ -154782,20 +155173,20 @@ function collectTemporariesSidemap(fn, usedOutsideDeclaringScope) {
154782
155173
  }
154783
155174
  return temporaries;
154784
155175
  }
154785
- function getProperty(object, propertyName, temporaries) {
155176
+ function getProperty(object, propertyName, optional, temporaries) {
154786
155177
  const resolvedDependency = temporaries.get(object.identifier.id);
154787
155178
  let property;
154788
155179
  if (resolvedDependency == null) {
154789
155180
  property = {
154790
155181
  identifier: object.identifier,
154791
- path: [{property: propertyName, optional: false}],
155182
+ path: [{property: propertyName, optional: optional}],
154792
155183
  };
154793
155184
  } else {
154794
155185
  property = {
154795
155186
  identifier: resolvedDependency.identifier,
154796
155187
  path: [
154797
155188
  ...resolvedDependency.path,
154798
- {property: propertyName, optional: false},
155189
+ {property: propertyName, optional: optional},
154799
155190
  ],
154800
155191
  };
154801
155192
  }
@@ -154914,10 +155305,11 @@ class Context {
154914
155305
  : {identifier: place.identifier, path: []}
154915
155306
  );
154916
155307
  }
154917
- visitProperty(object, property) {
155308
+ visitProperty(object, property, optional) {
154918
155309
  const nextDependency = getProperty(
154919
155310
  object,
154920
155311
  property,
155312
+ optional,
154921
155313
  __classPrivateFieldGet(this, _Context_temporaries, 'f')
154922
155314
  );
154923
155315
  this.visitDependency(nextDependency);
@@ -155048,7 +155440,7 @@ function handleInstruction(instr, context) {
155048
155440
  }
155049
155441
  } else if (value.kind === 'PropertyLoad') {
155050
155442
  if (context.isUsedOutsideDeclaringScope(lvalue)) {
155051
- context.visitProperty(value.object, value.property);
155443
+ context.visitProperty(value.object, value.property, false);
155052
155444
  }
155053
155445
  } else if (value.kind === 'StoreLocal') {
155054
155446
  context.visitOperand(value.value);
@@ -155079,7 +155471,12 @@ function handleInstruction(instr, context) {
155079
155471
  }
155080
155472
  context.declare(lvalue.identifier, {id: id, scope: context.currentScope});
155081
155473
  }
155082
- function collectDependencies(fn, usedOutsideDeclaringScope, temporaries) {
155474
+ function collectDependencies(
155475
+ fn,
155476
+ usedOutsideDeclaringScope,
155477
+ temporaries,
155478
+ processedInstrsInOptional
155479
+ ) {
155083
155480
  const context = new Context(usedOutsideDeclaringScope, temporaries);
155084
155481
  for (const param of fn.params) {
155085
155482
  if (param.kind === 'Identifier') {
@@ -155116,25 +155513,27 @@ function collectDependencies(fn, usedOutsideDeclaringScope, temporaries) {
155116
155513
  : scopeBlockInfo.pruned
155117
155514
  );
155118
155515
  }
155516
+ for (const phi of block.phis) {
155517
+ for (const operand of phi.operands) {
155518
+ const maybeOptionalChain = temporaries.get(operand[1].id);
155519
+ if (maybeOptionalChain) {
155520
+ context.visitDependency(maybeOptionalChain);
155521
+ }
155522
+ }
155523
+ }
155119
155524
  for (const instr of block.instructions) {
155120
- handleInstruction(instr, context);
155525
+ if (!processedInstrsInOptional.has(instr.id)) {
155526
+ handleInstruction(instr, context);
155527
+ }
155121
155528
  }
155122
- for (const place of eachTerminalOperand(block.terminal)) {
155123
- context.visitOperand(place);
155529
+ if (!processedInstrsInOptional.has(block.terminal.id)) {
155530
+ for (const place of eachTerminalOperand(block.terminal)) {
155531
+ context.visitOperand(place);
155532
+ }
155124
155533
  }
155125
155534
  }
155126
155535
  return context.deps;
155127
155536
  }
155128
- function recordHoistablePropertyReads(nodes, scopeId, tree) {
155129
- const node = nodes.get(scopeId);
155130
- CompilerError.invariant(node != null, {
155131
- reason: '[PropagateScopeDependencies] Scope not found in tracked blocks',
155132
- loc: GeneratedSource,
155133
- });
155134
- for (const item of node.assumedNonNullObjects) {
155135
- tree.markNodesNonNull(Object.assign({}, item.fullPath));
155136
- }
155137
- }
155138
155537
  function* run(
155139
155538
  func,
155140
155539
  config,