babel-plugin-react-compiler 0.0.0-experimental-3feb7e4-20240930 → 0.0.0-experimental-27e0f40-20241002

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
  }
@@ -144911,7 +144931,7 @@ class ReactiveScopeDependencyTree {
144911
144931
  _ReactiveScopeDependencyTree_getOrCreateRoot
144912
144932
  ).call(this, dep.identifier);
144913
144933
  for (const item of path) {
144914
- let currChild = getOrMakeProperty$1(currNode, item.property);
144934
+ let currChild = getOrMakeProperty(currNode, item.property);
144915
144935
  const accessType = inConditional
144916
144936
  ? PropertyAccessType$1.ConditionalAccess
144917
144937
  : item.optional
@@ -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
  );
@@ -145319,10 +145339,10 @@ function printSubtree$1(node, includeAccesses) {
145319
145339
  }
145320
145340
  return results;
145321
145341
  }
145322
- function getOrMakeProperty$1(node, property) {
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,10 +154239,19 @@ function validateNoJSXInTryStatement(fn) {
154219
154239
  throw errors;
154220
154240
  }
154221
154241
  }
154222
- var _Tree_instances, _a, _Tree_getOrCreateRoot, _Tree_getOrCreateProperty;
154223
- function collectHoistablePropertyLoads(fn, temporaries) {
154224
- const nodes = collectPropertyLoadsInBlocks(fn, temporaries);
154225
- propagateNonNull(fn, nodes);
154242
+ function collectHoistablePropertyLoads(
154243
+ fn,
154244
+ temporaries,
154245
+ hoistableFromOptionals
154246
+ ) {
154247
+ const registry = new PropertyPathRegistry();
154248
+ const nodes = collectNonNullsInBlocks(
154249
+ fn,
154250
+ temporaries,
154251
+ hoistableFromOptionals,
154252
+ registry
154253
+ );
154254
+ propagateNonNull(fn, nodes, registry);
154226
154255
  const nodesKeyedByScopeId = new Map();
154227
154256
  for (const [_, block] of fn.body.blocks) {
154228
154257
  if (block.terminal.kind === 'scope') {
@@ -154234,122 +154263,148 @@ function collectHoistablePropertyLoads(fn, temporaries) {
154234
154263
  }
154235
154264
  return nodesKeyedByScopeId;
154236
154265
  }
154237
- function getProperty(object, propertyName, temporaries) {
154238
- const resolvedDependency = temporaries.get(object.identifier.id);
154239
- let property;
154240
- if (resolvedDependency == null) {
154241
- property = {
154242
- identifier: object.identifier,
154243
- path: [{property: propertyName, optional: false}],
154244
- };
154245
- } else {
154246
- property = {
154247
- identifier: resolvedDependency.identifier,
154248
- path: [
154249
- ...resolvedDependency.path,
154250
- {property: propertyName, optional: false},
154251
- ],
154252
- };
154253
- }
154254
- return property;
154255
- }
154256
- class Tree {
154266
+ class PropertyPathRegistry {
154257
154267
  constructor() {
154258
- _Tree_instances.add(this);
154259
154268
  this.roots = new Map();
154260
154269
  }
154261
- getPropertyLoadNode(n) {
154262
- CompilerError.invariant(n.path.length > 0, {
154263
- reason:
154264
- '[CollectHoistablePropertyLoads] Expected property node, found root node',
154265
- loc: GeneratedSource,
154266
- });
154267
- let currNode = __classPrivateFieldGet(
154268
- this,
154269
- _Tree_instances,
154270
- 'm',
154271
- _Tree_getOrCreateRoot
154272
- ).call(this, n.identifier);
154273
- for (let i = 0; i < n.path.length - 1; i++) {
154274
- currNode = assertNonNull(currNode.properties.get(n.path[i].property));
154275
- }
154276
- return __classPrivateFieldGet(_a, _a, 'm', _Tree_getOrCreateProperty).call(
154277
- _a,
154278
- currNode,
154279
- n.path.at(-1).property
154280
- );
154281
- }
154282
- }
154283
- (_a = Tree),
154284
- (_Tree_instances = new WeakSet()),
154285
- (_Tree_getOrCreateRoot = function _Tree_getOrCreateRoot(identifier) {
154286
- let rootNode = this.roots.get(identifier);
154270
+ getOrCreateIdentifier(identifier) {
154271
+ let rootNode = this.roots.get(identifier.id);
154287
154272
  if (rootNode === undefined) {
154288
154273
  rootNode = {
154289
- root: identifier,
154274
+ root: identifier.id,
154290
154275
  properties: new Map(),
154276
+ optionalProperties: new Map(),
154291
154277
  fullPath: {identifier: identifier, path: []},
154278
+ hasOptional: false,
154292
154279
  parent: null,
154293
154280
  };
154294
- this.roots.set(identifier, rootNode);
154281
+ this.roots.set(identifier.id, rootNode);
154295
154282
  }
154296
154283
  return rootNode;
154297
- }),
154298
- (_Tree_getOrCreateProperty = function _Tree_getOrCreateProperty(
154299
- node,
154300
- property
154301
- ) {
154302
- let child = node.properties.get(property);
154284
+ }
154285
+ static getOrCreatePropertyEntry(parent, entry) {
154286
+ const map = entry.optional ? parent.optionalProperties : parent.properties;
154287
+ let child = map.get(entry.property);
154303
154288
  if (child == null) {
154304
154289
  child = {
154305
154290
  properties: new Map(),
154306
- parent: node,
154291
+ optionalProperties: new Map(),
154292
+ parent: parent,
154307
154293
  fullPath: {
154308
- identifier: node.fullPath.identifier,
154309
- path: node.fullPath.path.concat([
154310
- {property: property, optional: false},
154311
- ]),
154294
+ identifier: parent.fullPath.identifier,
154295
+ path: parent.fullPath.path.concat(entry),
154312
154296
  },
154297
+ hasOptional: parent.hasOptional || entry.optional,
154313
154298
  };
154314
- node.properties.set(property, child);
154299
+ map.set(entry.property, child);
154315
154300
  }
154316
154301
  return child;
154317
- });
154318
- function collectPropertyLoadsInBlocks(fn, temporaries) {
154302
+ }
154303
+ getOrCreateProperty(n) {
154304
+ let currNode = this.getOrCreateIdentifier(n.identifier);
154305
+ if (n.path.length === 0) {
154306
+ return currNode;
154307
+ }
154308
+ for (let i = 0; i < n.path.length - 1; i++) {
154309
+ currNode = PropertyPathRegistry.getOrCreatePropertyEntry(
154310
+ currNode,
154311
+ n.path[i]
154312
+ );
154313
+ }
154314
+ return PropertyPathRegistry.getOrCreatePropertyEntry(
154315
+ currNode,
154316
+ n.path.at(-1)
154317
+ );
154318
+ }
154319
+ }
154320
+ function addNonNullPropertyPath(
154321
+ source,
154322
+ sourceNode,
154323
+ instrId,
154324
+ knownImmutableIdentifiers,
154325
+ result
154326
+ ) {
154327
+ const isMutableAtInstr =
154328
+ source.mutableRange.end > source.mutableRange.start + 1 &&
154329
+ source.scope != null &&
154330
+ inRange({id: instrId}, source.scope.range);
154331
+ if (
154332
+ !isMutableAtInstr ||
154333
+ knownImmutableIdentifiers.has(sourceNode.fullPath.identifier.id)
154334
+ ) {
154335
+ result.add(sourceNode);
154336
+ }
154337
+ }
154338
+ function collectNonNullsInBlocks(
154339
+ fn,
154340
+ temporaries,
154341
+ hoistableFromOptionals,
154342
+ registry
154343
+ ) {
154344
+ var _a;
154319
154345
  const knownImmutableIdentifiers = new Set();
154320
154346
  if (fn.fnType === 'Component' || fn.fnType === 'Hook') {
154321
154347
  for (const p of fn.params) {
154322
154348
  if (p.kind === 'Identifier') {
154323
- knownImmutableIdentifiers.add(p.identifier);
154349
+ knownImmutableIdentifiers.add(p.identifier.id);
154324
154350
  }
154325
154351
  }
154326
154352
  }
154327
- const tree = new Tree();
154353
+ const knownNonNullIdentifiers = new Set();
154354
+ if (
154355
+ fn.fnType === 'Component' &&
154356
+ fn.params.length > 0 &&
154357
+ fn.params[0].kind === 'Identifier'
154358
+ ) {
154359
+ const identifier = fn.params[0].identifier;
154360
+ knownNonNullIdentifiers.add(registry.getOrCreateIdentifier(identifier));
154361
+ }
154328
154362
  const nodes = new Map();
154329
154363
  for (const [_, block] of fn.body.blocks) {
154330
- const assumedNonNullObjects = new Set();
154364
+ const assumedNonNullObjects = new Set(knownNonNullIdentifiers);
154365
+ const maybeOptionalChain = hoistableFromOptionals.get(block.id);
154366
+ if (maybeOptionalChain != null) {
154367
+ assumedNonNullObjects.add(
154368
+ registry.getOrCreateProperty(maybeOptionalChain)
154369
+ );
154370
+ }
154331
154371
  for (const instr of block.instructions) {
154332
154372
  if (instr.value.kind === 'PropertyLoad') {
154333
- const property = getProperty(
154334
- instr.value.object,
154335
- instr.value.property,
154336
- temporaries
154373
+ const source =
154374
+ (_a = temporaries.get(instr.value.object.identifier.id)) !== null &&
154375
+ _a !== void 0
154376
+ ? _a
154377
+ : {identifier: instr.value.object.identifier, path: []};
154378
+ addNonNullPropertyPath(
154379
+ instr.value.object.identifier,
154380
+ registry.getOrCreateProperty(source),
154381
+ instr.id,
154382
+ knownImmutableIdentifiers,
154383
+ assumedNonNullObjects
154337
154384
  );
154338
- const propertyNode = tree.getPropertyLoadNode(property);
154339
- const object = instr.value.object.identifier;
154340
- const isMutableAtInstr =
154341
- object.mutableRange.end > object.mutableRange.start + 1 &&
154342
- object.scope != null &&
154343
- inRange(instr, object.scope.range);
154344
- if (
154345
- !isMutableAtInstr ||
154346
- knownImmutableIdentifiers.has(propertyNode.fullPath.identifier)
154347
- ) {
154348
- let curr = propertyNode.parent;
154349
- while (curr != null) {
154350
- assumedNonNullObjects.add(curr);
154351
- curr = curr.parent;
154352
- }
154385
+ } else if (instr.value.kind === 'Destructure') {
154386
+ const source = instr.value.value.identifier.id;
154387
+ const sourceNode = temporaries.get(source);
154388
+ if (sourceNode != null) {
154389
+ addNonNullPropertyPath(
154390
+ instr.value.value.identifier,
154391
+ registry.getOrCreateProperty(sourceNode),
154392
+ instr.id,
154393
+ knownImmutableIdentifiers,
154394
+ assumedNonNullObjects
154395
+ );
154396
+ }
154397
+ } else if (instr.value.kind === 'ComputedLoad') {
154398
+ const source = instr.value.object.identifier.id;
154399
+ const sourceNode = temporaries.get(source);
154400
+ if (sourceNode != null) {
154401
+ addNonNullPropertyPath(
154402
+ instr.value.object.identifier,
154403
+ registry.getOrCreateProperty(sourceNode),
154404
+ instr.id,
154405
+ knownImmutableIdentifiers,
154406
+ assumedNonNullObjects
154407
+ );
154353
154408
  }
154354
154409
  }
154355
154410
  }
@@ -154360,7 +154415,7 @@ function collectPropertyLoadsInBlocks(fn, temporaries) {
154360
154415
  }
154361
154416
  return nodes;
154362
154417
  }
154363
- function propagateNonNull(fn, nodes) {
154418
+ function propagateNonNull(fn, nodes, registry) {
154364
154419
  const blockSuccessors = new Map();
154365
154420
  const terminalPreds = new Set();
154366
154421
  for (const [blockId, block] of fn.body.blocks) {
@@ -154371,13 +154426,8 @@ function propagateNonNull(fn, nodes) {
154371
154426
  terminalPreds.add(blockId);
154372
154427
  }
154373
154428
  }
154374
- function recursivelyPropagateNonNull(
154375
- nodeId,
154376
- direction,
154377
- traversalState,
154378
- nonNullObjectsByBlock
154379
- ) {
154380
- var _b;
154429
+ function recursivelyPropagateNonNull(nodeId, direction, traversalState) {
154430
+ var _a;
154381
154431
  if (traversalState.has(nodeId)) {
154382
154432
  return false;
154383
154433
  }
@@ -154391,8 +154441,8 @@ function propagateNonNull(fn, nodes) {
154391
154441
  }
154392
154442
  const neighbors = Array.from(
154393
154443
  direction === 'backward'
154394
- ? (_b = blockSuccessors.get(nodeId)) !== null && _b !== void 0
154395
- ? _b
154444
+ ? (_a = blockSuccessors.get(nodeId)) !== null && _a !== void 0
154445
+ ? _a
154396
154446
  : []
154397
154447
  : node.block.preds
154398
154448
  );
@@ -154402,8 +154452,7 @@ function propagateNonNull(fn, nodes) {
154402
154452
  const neighborChanged = recursivelyPropagateNonNull(
154403
154453
  pred,
154404
154454
  direction,
154405
- traversalState,
154406
- nonNullObjectsByBlock
154455
+ traversalState
154407
154456
  );
154408
154457
  changed || (changed = neighborChanged);
154409
154458
  }
@@ -154411,35 +154460,33 @@ function propagateNonNull(fn, nodes) {
154411
154460
  const neighborAccesses = Set_intersect(
154412
154461
  Array.from(neighbors)
154413
154462
  .filter(n => traversalState.get(n) === 'done')
154414
- .map(n => assertNonNull(nonNullObjectsByBlock.get(n)))
154463
+ .map(n => assertNonNull(nodes.get(n)).assumedNonNullObjects)
154415
154464
  );
154416
- const prevObjects = assertNonNull(nonNullObjectsByBlock.get(nodeId));
154417
- const newObjects = Set_union(prevObjects, neighborAccesses);
154418
- nonNullObjectsByBlock.set(nodeId, newObjects);
154465
+ const prevObjects = assertNonNull(nodes.get(nodeId)).assumedNonNullObjects;
154466
+ const mergedObjects = Set_union(prevObjects, neighborAccesses);
154467
+ reduceMaybeOptionalChains(mergedObjects, registry);
154468
+ assertNonNull(nodes.get(nodeId)).assumedNonNullObjects = mergedObjects;
154419
154469
  traversalState.set(nodeId, 'done');
154420
- changed || (changed = prevObjects.size !== newObjects.size);
154470
+ changed || (changed = !Set_equal(prevObjects, mergedObjects));
154421
154471
  return changed;
154422
154472
  }
154423
- const fromEntry = new Map();
154424
- const fromExit = new Map();
154425
- for (const [blockId, blockInfo] of nodes) {
154426
- fromEntry.set(blockId, blockInfo.assumedNonNullObjects);
154427
- fromExit.set(blockId, blockInfo.assumedNonNullObjects);
154428
- }
154429
154473
  const traversalState = new Map();
154430
154474
  const reversedBlocks = [...fn.body.blocks];
154431
154475
  reversedBlocks.reverse();
154432
- let i = 0;
154433
154476
  let changed;
154477
+ let i = 0;
154434
154478
  do {
154435
- i++;
154479
+ CompilerError.invariant(i++ < 100, {
154480
+ reason:
154481
+ '[CollectHoistablePropertyLoads] fixed point iteration did not terminate after 100 loops',
154482
+ loc: GeneratedSource,
154483
+ });
154436
154484
  changed = false;
154437
154485
  for (const [blockId] of fn.body.blocks) {
154438
154486
  const forwardChanged = recursivelyPropagateNonNull(
154439
154487
  blockId,
154440
154488
  'forward',
154441
- traversalState,
154442
- fromEntry
154489
+ traversalState
154443
154490
  );
154444
154491
  changed || (changed = forwardChanged);
154445
154492
  }
@@ -154448,33 +154495,12 @@ function propagateNonNull(fn, nodes) {
154448
154495
  const backwardChanged = recursivelyPropagateNonNull(
154449
154496
  blockId,
154450
154497
  'backward',
154451
- traversalState,
154452
- fromExit
154498
+ traversalState
154453
154499
  );
154454
154500
  changed || (changed = backwardChanged);
154455
154501
  }
154456
154502
  traversalState.clear();
154457
154503
  } while (changed);
154458
- CompilerError.invariant(i <= 2, {
154459
- reason: 'require fixed-point iteration',
154460
- description: `#iterations = ${i}`,
154461
- loc: GeneratedSource,
154462
- });
154463
- CompilerError.invariant(
154464
- fromEntry.size === fromExit.size && fromEntry.size === nodes.size,
154465
- {
154466
- reason:
154467
- 'bad sizes after calculating fromEntry + fromExit ' +
154468
- `${fromEntry.size} ${fromExit.size} ${nodes.size}`,
154469
- loc: GeneratedSource,
154470
- }
154471
- );
154472
- for (const [id, node] of nodes) {
154473
- node.assumedNonNullObjects = Set_union(
154474
- assertNonNull(fromEntry.get(id)),
154475
- assertNonNull(fromExit.get(id))
154476
- );
154477
- }
154478
154504
  }
154479
154505
  function assertNonNull(value, source) {
154480
154506
  CompilerError.invariant(value != null, {
@@ -154484,67 +154510,156 @@ function assertNonNull(value, source) {
154484
154510
  });
154485
154511
  return value;
154486
154512
  }
154487
- var _ReactiveScopeDependencyTreeHIR_instances,
154488
- _ReactiveScopeDependencyTreeHIR_roots,
154489
- _ReactiveScopeDependencyTreeHIR_getOrCreateRoot;
154513
+ function reduceMaybeOptionalChains(nodes, registry) {
154514
+ let optionalChainNodes = Set_filter(nodes, n => n.hasOptional);
154515
+ if (optionalChainNodes.size === 0) {
154516
+ return;
154517
+ }
154518
+ let changed;
154519
+ do {
154520
+ changed = false;
154521
+ for (const original of optionalChainNodes) {
154522
+ let {identifier: identifier, path: origPath} = original.fullPath;
154523
+ let currNode = registry.getOrCreateIdentifier(identifier);
154524
+ for (let i = 0; i < origPath.length; i++) {
154525
+ const entry = origPath[i];
154526
+ const nextEntry =
154527
+ entry.optional && nodes.has(currNode)
154528
+ ? {property: entry.property, optional: false}
154529
+ : entry;
154530
+ currNode = PropertyPathRegistry.getOrCreatePropertyEntry(
154531
+ currNode,
154532
+ nextEntry
154533
+ );
154534
+ }
154535
+ if (currNode !== original) {
154536
+ changed = true;
154537
+ optionalChainNodes.delete(original);
154538
+ optionalChainNodes.add(currNode);
154539
+ nodes.delete(original);
154540
+ nodes.add(currNode);
154541
+ }
154542
+ }
154543
+ } while (changed);
154544
+ }
154545
+ var _a,
154546
+ _ReactiveScopeDependencyTreeHIR_hoistableObjects,
154547
+ _ReactiveScopeDependencyTreeHIR_deps,
154548
+ _ReactiveScopeDependencyTreeHIR_getOrCreateRoot,
154549
+ _ReactiveScopeDependencyTreeHIR_debugImpl;
154490
154550
  class ReactiveScopeDependencyTreeHIR {
154491
- constructor() {
154492
- _ReactiveScopeDependencyTreeHIR_instances.add(this);
154493
- _ReactiveScopeDependencyTreeHIR_roots.set(this, new Map());
154551
+ constructor(hoistableObjects) {
154552
+ var _b;
154553
+ _ReactiveScopeDependencyTreeHIR_hoistableObjects.set(this, new Map());
154554
+ _ReactiveScopeDependencyTreeHIR_deps.set(this, new Map());
154555
+ for (const {path: path, identifier: identifier} of hoistableObjects) {
154556
+ let currNode = __classPrivateFieldGet(
154557
+ _a,
154558
+ _a,
154559
+ 'm',
154560
+ _ReactiveScopeDependencyTreeHIR_getOrCreateRoot
154561
+ ).call(
154562
+ _a,
154563
+ identifier,
154564
+ __classPrivateFieldGet(
154565
+ this,
154566
+ _ReactiveScopeDependencyTreeHIR_hoistableObjects,
154567
+ 'f'
154568
+ ),
154569
+ path.length > 0 && path[0].optional ? 'Optional' : 'NonNull'
154570
+ );
154571
+ for (let i = 0; i < path.length; i++) {
154572
+ const prevAccessType =
154573
+ (_b = currNode.properties.get(path[i].property)) === null ||
154574
+ _b === void 0
154575
+ ? void 0
154576
+ : _b.accessType;
154577
+ const accessType =
154578
+ i + 1 < path.length && path[i + 1].optional ? 'Optional' : 'NonNull';
154579
+ CompilerError.invariant(
154580
+ prevAccessType == null || prevAccessType === accessType,
154581
+ {reason: 'Conflicting access types', loc: GeneratedSource}
154582
+ );
154583
+ let nextNode = currNode.properties.get(path[i].property);
154584
+ if (nextNode == null) {
154585
+ nextNode = {properties: new Map(), accessType: accessType};
154586
+ currNode.properties.set(path[i].property, nextNode);
154587
+ }
154588
+ currNode = nextNode;
154589
+ }
154590
+ }
154494
154591
  }
154495
154592
  addDependency(dep) {
154496
- const {path: path} = dep;
154497
- let currNode = __classPrivateFieldGet(
154498
- this,
154499
- _ReactiveScopeDependencyTreeHIR_instances,
154593
+ const {identifier: identifier, path: path} = dep;
154594
+ let depCursor = __classPrivateFieldGet(
154595
+ _a,
154596
+ _a,
154500
154597
  'm',
154501
154598
  _ReactiveScopeDependencyTreeHIR_getOrCreateRoot
154502
- ).call(this, dep.identifier, false);
154503
- const accessType = PropertyAccessType.Access;
154504
- currNode.accessType = merge(currNode.accessType, accessType);
154505
- for (const property of path) {
154506
- let currChild = getOrMakeProperty(currNode, property.property);
154507
- currChild.accessType = merge(currChild.accessType, accessType);
154508
- currNode = currChild;
154509
- }
154510
- currNode.accessType = merge(
154511
- currNode.accessType,
154512
- PropertyAccessType.Dependency
154599
+ ).call(
154600
+ _a,
154601
+ identifier,
154602
+ __classPrivateFieldGet(this, _ReactiveScopeDependencyTreeHIR_deps, 'f'),
154603
+ PropertyAccessType.UnconditionalAccess
154513
154604
  );
154514
- }
154515
- markNodesNonNull(dep) {
154516
- const accessType = PropertyAccessType.NonNullAccess;
154517
- let currNode = __classPrivateFieldGet(
154605
+ let hoistableCursor = __classPrivateFieldGet(
154518
154606
  this,
154519
- _ReactiveScopeDependencyTreeHIR_roots,
154607
+ _ReactiveScopeDependencyTreeHIR_hoistableObjects,
154520
154608
  'f'
154521
- ).get(dep.identifier);
154522
- let cursor = 0;
154523
- while (currNode != null && cursor < dep.path.length) {
154524
- currNode.accessType = merge(currNode.accessType, accessType);
154525
- currNode = currNode.properties.get(dep.path[cursor++].property);
154526
- }
154527
- if (currNode != null) {
154528
- currNode.accessType = merge(currNode.accessType, accessType);
154609
+ ).get(identifier);
154610
+ for (const entry of path) {
154611
+ let nextHoistableCursor;
154612
+ let nextDepCursor;
154613
+ if (entry.optional) {
154614
+ if (hoistableCursor != null) {
154615
+ nextHoistableCursor =
154616
+ hoistableCursor === null || hoistableCursor === void 0
154617
+ ? void 0
154618
+ : hoistableCursor.properties.get(entry.property);
154619
+ }
154620
+ let accessType;
154621
+ if (
154622
+ hoistableCursor != null &&
154623
+ hoistableCursor.accessType === 'NonNull'
154624
+ ) {
154625
+ accessType = PropertyAccessType.UnconditionalAccess;
154626
+ } else {
154627
+ accessType = PropertyAccessType.OptionalAccess;
154628
+ }
154629
+ nextDepCursor = makeOrMergeProperty(
154630
+ depCursor,
154631
+ entry.property,
154632
+ accessType
154633
+ );
154634
+ } else if (
154635
+ hoistableCursor != null &&
154636
+ hoistableCursor.accessType === 'NonNull'
154637
+ ) {
154638
+ nextHoistableCursor = hoistableCursor.properties.get(entry.property);
154639
+ nextDepCursor = makeOrMergeProperty(
154640
+ depCursor,
154641
+ entry.property,
154642
+ PropertyAccessType.UnconditionalAccess
154643
+ );
154644
+ } else {
154645
+ break;
154646
+ }
154647
+ depCursor = nextDepCursor;
154648
+ hoistableCursor = nextHoistableCursor;
154529
154649
  }
154650
+ depCursor.accessType = merge(
154651
+ depCursor.accessType,
154652
+ PropertyAccessType.OptionalDependency
154653
+ );
154530
154654
  }
154531
154655
  deriveMinimalDependencies() {
154532
154656
  const results = new Set();
154533
154657
  for (const [rootId, rootNode] of __classPrivateFieldGet(
154534
154658
  this,
154535
- _ReactiveScopeDependencyTreeHIR_roots,
154659
+ _ReactiveScopeDependencyTreeHIR_deps,
154536
154660
  'f'
154537
154661
  ).entries()) {
154538
- {
154539
- assertWellFormedTree(rootNode);
154540
- }
154541
- const deps = deriveMinimalDependenciesInSubtree(rootNode, []);
154542
- for (const dep of deps) {
154543
- results.add({
154544
- identifier: rootId,
154545
- path: dep.path.map(s => ({property: s, optional: false})),
154546
- });
154547
- }
154662
+ collectMinimalDependenciesInSubtree(rootNode, rootId, [], results);
154548
154663
  }
154549
154664
  return results;
154550
154665
  }
@@ -154552,7 +154667,7 @@ class ReactiveScopeDependencyTreeHIR {
154552
154667
  let res = [];
154553
154668
  for (const [rootId, rootNode] of __classPrivateFieldGet(
154554
154669
  this,
154555
- _ReactiveScopeDependencyTreeHIR_roots,
154670
+ _ReactiveScopeDependencyTreeHIR_deps,
154556
154671
  'f'
154557
154672
  ).entries()) {
154558
154673
  const rootResults = printSubtree(rootNode, includeAccesses).map(
@@ -154562,100 +154677,106 @@ class ReactiveScopeDependencyTreeHIR {
154562
154677
  }
154563
154678
  return res.flat().join('\n');
154564
154679
  }
154680
+ static debug(roots) {
154681
+ const buf = [`tree() [`];
154682
+ for (const [rootId, rootNode] of roots) {
154683
+ buf.push(`${printIdentifier(rootId)} (${rootNode.accessType}):`);
154684
+ __classPrivateFieldGet(
154685
+ this,
154686
+ _a,
154687
+ 'm',
154688
+ _ReactiveScopeDependencyTreeHIR_debugImpl
154689
+ ).call(this, buf, rootNode, 1);
154690
+ }
154691
+ buf.push(']');
154692
+ return buf.length > 2 ? buf.join('\n') : buf.join('');
154693
+ }
154565
154694
  }
154566
- (_ReactiveScopeDependencyTreeHIR_roots = new WeakMap()),
154567
- (_ReactiveScopeDependencyTreeHIR_instances = new WeakSet()),
154695
+ (_a = ReactiveScopeDependencyTreeHIR),
154696
+ (_ReactiveScopeDependencyTreeHIR_hoistableObjects = new WeakMap()),
154697
+ (_ReactiveScopeDependencyTreeHIR_deps = new WeakMap()),
154568
154698
  (_ReactiveScopeDependencyTreeHIR_getOrCreateRoot =
154569
154699
  function _ReactiveScopeDependencyTreeHIR_getOrCreateRoot(
154570
154700
  identifier,
154571
- isNonNull
154701
+ roots,
154702
+ defaultAccessType
154572
154703
  ) {
154573
- let rootNode = __classPrivateFieldGet(
154574
- this,
154575
- _ReactiveScopeDependencyTreeHIR_roots,
154576
- 'f'
154577
- ).get(identifier);
154704
+ let rootNode = roots.get(identifier);
154578
154705
  if (rootNode === undefined) {
154579
- rootNode = {
154580
- properties: new Map(),
154581
- accessType: isNonNull
154582
- ? PropertyAccessType.NonNullAccess
154583
- : PropertyAccessType.Access,
154584
- };
154706
+ rootNode = {properties: new Map(), accessType: defaultAccessType};
154707
+ roots.set(identifier, rootNode);
154708
+ }
154709
+ return rootNode;
154710
+ }),
154711
+ (_ReactiveScopeDependencyTreeHIR_debugImpl =
154712
+ function _ReactiveScopeDependencyTreeHIR_debugImpl(buf, node, depth = 0) {
154713
+ for (const [property, childNode] of node.properties) {
154714
+ buf.push(
154715
+ `${' '.repeat(depth)}.${property} (${childNode.accessType}):`
154716
+ );
154585
154717
  __classPrivateFieldGet(
154586
154718
  this,
154587
- _ReactiveScopeDependencyTreeHIR_roots,
154588
- 'f'
154589
- ).set(identifier, rootNode);
154719
+ _a,
154720
+ 'm',
154721
+ _ReactiveScopeDependencyTreeHIR_debugImpl
154722
+ ).call(this, buf, childNode, depth + 1);
154590
154723
  }
154591
- return rootNode;
154592
154724
  });
154593
154725
  var PropertyAccessType;
154594
154726
  (function (PropertyAccessType) {
154595
- PropertyAccessType['Access'] = 'Access';
154596
- PropertyAccessType['NonNullAccess'] = 'NonNullAccess';
154597
- PropertyAccessType['Dependency'] = 'Dependency';
154598
- PropertyAccessType['NonNullDependency'] = 'NonNullDependency';
154727
+ PropertyAccessType['OptionalAccess'] = 'OptionalAccess';
154728
+ PropertyAccessType['UnconditionalAccess'] = 'UnconditionalAccess';
154729
+ PropertyAccessType['OptionalDependency'] = 'OptionalDependency';
154730
+ PropertyAccessType['UnconditionalDependency'] = 'UnconditionalDependency';
154599
154731
  })(PropertyAccessType || (PropertyAccessType = {}));
154600
- const MIN_ACCESS_TYPE = PropertyAccessType.Access;
154601
- function isNonNull(access) {
154732
+ function isOptional(access) {
154602
154733
  return (
154603
- access === PropertyAccessType.NonNullAccess ||
154604
- access === PropertyAccessType.NonNullDependency
154734
+ access === PropertyAccessType.OptionalAccess ||
154735
+ access === PropertyAccessType.OptionalDependency
154605
154736
  );
154606
154737
  }
154607
154738
  function isDependency(access) {
154608
154739
  return (
154609
- access === PropertyAccessType.Dependency ||
154610
- access === PropertyAccessType.NonNullDependency
154740
+ access === PropertyAccessType.OptionalDependency ||
154741
+ access === PropertyAccessType.UnconditionalDependency
154611
154742
  );
154612
154743
  }
154613
154744
  function merge(access1, access2) {
154614
- const resultisNonNull = isNonNull(access1) || isNonNull(access2);
154745
+ const resultIsUnconditional = !(isOptional(access1) && isOptional(access2));
154615
154746
  const resultIsDependency = isDependency(access1) || isDependency(access2);
154616
- if (resultisNonNull) {
154747
+ if (resultIsUnconditional) {
154617
154748
  if (resultIsDependency) {
154618
- return PropertyAccessType.NonNullDependency;
154749
+ return PropertyAccessType.UnconditionalDependency;
154619
154750
  } else {
154620
- return PropertyAccessType.NonNullAccess;
154751
+ return PropertyAccessType.UnconditionalAccess;
154621
154752
  }
154622
154753
  } else {
154623
154754
  if (resultIsDependency) {
154624
- return PropertyAccessType.Dependency;
154755
+ return PropertyAccessType.OptionalDependency;
154625
154756
  } else {
154626
- return PropertyAccessType.Access;
154757
+ return PropertyAccessType.OptionalAccess;
154627
154758
  }
154628
154759
  }
154629
154760
  }
154630
- function assertWellFormedTree(node) {
154631
- let nonNullInChildren = false;
154632
- for (const childNode of node.properties.values()) {
154633
- assertWellFormedTree(childNode);
154634
- nonNullInChildren || (nonNullInChildren = isNonNull(childNode.accessType));
154635
- }
154636
- if (nonNullInChildren) {
154637
- CompilerError.invariant(isNonNull(node.accessType), {
154638
- reason:
154639
- '[DeriveMinimialDependencies] Not well formed tree, unexpected non-null node',
154640
- description: node.accessType,
154641
- loc: GeneratedSource,
154642
- });
154643
- }
154644
- }
154645
- function deriveMinimalDependenciesInSubtree(node, path) {
154761
+ function collectMinimalDependenciesInSubtree(
154762
+ node,
154763
+ rootIdentifier,
154764
+ path,
154765
+ results
154766
+ ) {
154646
154767
  if (isDependency(node.accessType)) {
154647
- return [{path: path}];
154768
+ results.add({identifier: rootIdentifier, path: path});
154648
154769
  } else {
154649
- if (isNonNull(node.accessType)) {
154650
- const result = [];
154651
- for (const [childName, childNode] of node.properties) {
154652
- result.push(
154653
- ...deriveMinimalDependenciesInSubtree(childNode, [...path, childName])
154654
- );
154655
- }
154656
- return result;
154657
- } else {
154658
- return [{path: path}];
154770
+ for (const [childName, childNode] of node.properties) {
154771
+ collectMinimalDependenciesInSubtree(
154772
+ childNode,
154773
+ rootIdentifier,
154774
+ [
154775
+ ...path,
154776
+ {property: childName, optional: isOptional(childNode.accessType)},
154777
+ ],
154778
+ results
154779
+ );
154659
154780
  }
154660
154781
  }
154661
154782
  }
@@ -154670,14 +154791,202 @@ function printSubtree(node, includeAccesses) {
154670
154791
  }
154671
154792
  return results;
154672
154793
  }
154673
- function getOrMakeProperty(node, property) {
154794
+ function makeOrMergeProperty(node, property, accessType) {
154674
154795
  let child = node.properties.get(property);
154675
154796
  if (child == null) {
154676
- child = {properties: new Map(), accessType: MIN_ACCESS_TYPE};
154797
+ child = {properties: new Map(), accessType: accessType};
154677
154798
  node.properties.set(property, child);
154799
+ } else {
154800
+ child.accessType = merge(child.accessType, accessType);
154678
154801
  }
154679
154802
  return child;
154680
154803
  }
154804
+ function collectOptionalChainSidemap(fn) {
154805
+ const context = {
154806
+ blocks: fn.body.blocks,
154807
+ seenOptionals: new Set(),
154808
+ processedInstrsInOptional: new Set(),
154809
+ temporariesReadInOptional: new Map(),
154810
+ hoistableObjects: new Map(),
154811
+ };
154812
+ for (const [_, block] of fn.body.blocks) {
154813
+ if (
154814
+ block.terminal.kind === 'optional' &&
154815
+ !context.seenOptionals.has(block.id)
154816
+ ) {
154817
+ traverseOptionalBlock(block, context, null);
154818
+ }
154819
+ }
154820
+ return {
154821
+ temporariesReadInOptional: context.temporariesReadInOptional,
154822
+ processedInstrsInOptional: context.processedInstrsInOptional,
154823
+ hoistableObjects: context.hoistableObjects,
154824
+ };
154825
+ }
154826
+ function matchOptionalTestBlock(terminal, blocks) {
154827
+ const consequentBlock = assertNonNull(blocks.get(terminal.consequent));
154828
+ if (
154829
+ consequentBlock.instructions.length === 2 &&
154830
+ consequentBlock.instructions[0].value.kind === 'PropertyLoad' &&
154831
+ consequentBlock.instructions[1].value.kind === 'StoreLocal'
154832
+ ) {
154833
+ const propertyLoad = consequentBlock.instructions[0];
154834
+ const storeLocal = consequentBlock.instructions[1].value;
154835
+ const storeLocalInstrId = consequentBlock.instructions[1].id;
154836
+ CompilerError.invariant(
154837
+ propertyLoad.value.object.identifier.id === terminal.test.identifier.id,
154838
+ {
154839
+ reason:
154840
+ '[OptionalChainDeps] Inconsistent optional chaining property load',
154841
+ description: `Test=${printIdentifier(terminal.test.identifier)} PropertyLoad base=${printIdentifier(propertyLoad.value.object.identifier)}`,
154842
+ loc: propertyLoad.loc,
154843
+ }
154844
+ );
154845
+ CompilerError.invariant(
154846
+ storeLocal.value.identifier.id === propertyLoad.lvalue.identifier.id,
154847
+ {
154848
+ reason: '[OptionalChainDeps] Unexpected storeLocal',
154849
+ loc: propertyLoad.loc,
154850
+ }
154851
+ );
154852
+ if (
154853
+ consequentBlock.terminal.kind !== 'goto' ||
154854
+ consequentBlock.terminal.variant !== GotoVariant.Break
154855
+ ) {
154856
+ return null;
154857
+ }
154858
+ const alternate = assertNonNull(blocks.get(terminal.alternate));
154859
+ CompilerError.invariant(
154860
+ alternate.instructions.length === 2 &&
154861
+ alternate.instructions[0].value.kind === 'Primitive' &&
154862
+ alternate.instructions[1].value.kind === 'StoreLocal',
154863
+ {reason: 'Unexpected alternate structure', loc: terminal.loc}
154864
+ );
154865
+ return {
154866
+ consequentId: storeLocal.lvalue.place.identifier.id,
154867
+ property: propertyLoad.value.property,
154868
+ propertyId: propertyLoad.lvalue.identifier.id,
154869
+ storeLocalInstrId: storeLocalInstrId,
154870
+ consequentGoto: consequentBlock.terminal.block,
154871
+ };
154872
+ }
154873
+ return null;
154874
+ }
154875
+ function traverseOptionalBlock(optional, context, outerAlternate) {
154876
+ context.seenOptionals.add(optional.id);
154877
+ const maybeTest = context.blocks.get(optional.terminal.test);
154878
+ let test;
154879
+ let baseObject;
154880
+ if (maybeTest.terminal.kind === 'branch') {
154881
+ CompilerError.invariant(optional.terminal.optional, {
154882
+ reason: '[OptionalChainDeps] Expect base case to be always optional',
154883
+ loc: optional.terminal.loc,
154884
+ });
154885
+ if (
154886
+ maybeTest.instructions.length === 0 ||
154887
+ maybeTest.instructions[0].value.kind !== 'LoadLocal'
154888
+ ) {
154889
+ return null;
154890
+ }
154891
+ const path = [];
154892
+ for (let i = 1; i < maybeTest.instructions.length; i++) {
154893
+ const instrVal = maybeTest.instructions[i].value;
154894
+ const prevInstr = maybeTest.instructions[i - 1];
154895
+ if (
154896
+ instrVal.kind === 'PropertyLoad' &&
154897
+ instrVal.object.identifier.id === prevInstr.lvalue.identifier.id
154898
+ ) {
154899
+ path.push({property: instrVal.property, optional: false});
154900
+ } else {
154901
+ return null;
154902
+ }
154903
+ }
154904
+ CompilerError.invariant(
154905
+ maybeTest.terminal.test.identifier.id ===
154906
+ maybeTest.instructions.at(-1).lvalue.identifier.id,
154907
+ {
154908
+ reason: '[OptionalChainDeps] Unexpected test expression',
154909
+ loc: maybeTest.terminal.loc,
154910
+ }
154911
+ );
154912
+ baseObject = {
154913
+ identifier: maybeTest.instructions[0].value.place.identifier,
154914
+ path: path,
154915
+ };
154916
+ test = maybeTest.terminal;
154917
+ } else if (maybeTest.terminal.kind === 'optional') {
154918
+ const testBlock = context.blocks.get(maybeTest.terminal.fallthrough);
154919
+ if (testBlock.terminal.kind !== 'branch') {
154920
+ CompilerError.throwTodo({
154921
+ reason: `Unexpected terminal kind \`${testBlock.terminal.kind}\` for optional fallthrough block`,
154922
+ loc: maybeTest.terminal.loc,
154923
+ });
154924
+ }
154925
+ const innerOptional = traverseOptionalBlock(
154926
+ maybeTest,
154927
+ context,
154928
+ testBlock.terminal.alternate
154929
+ );
154930
+ if (innerOptional == null) {
154931
+ return null;
154932
+ }
154933
+ if (testBlock.terminal.test.identifier.id !== innerOptional) {
154934
+ return null;
154935
+ }
154936
+ if (!optional.terminal.optional) {
154937
+ context.hoistableObjects.set(
154938
+ optional.id,
154939
+ assertNonNull(context.temporariesReadInOptional.get(innerOptional))
154940
+ );
154941
+ }
154942
+ baseObject = assertNonNull(
154943
+ context.temporariesReadInOptional.get(innerOptional)
154944
+ );
154945
+ test = testBlock.terminal;
154946
+ } else {
154947
+ return null;
154948
+ }
154949
+ if (test.alternate === outerAlternate) {
154950
+ CompilerError.invariant(optional.instructions.length === 0, {
154951
+ reason:
154952
+ '[OptionalChainDeps] Unexpected instructions an inner optional block. ' +
154953
+ 'This indicates that the compiler may be incorrectly concatenating two unrelated optional chains',
154954
+ loc: optional.terminal.loc,
154955
+ });
154956
+ }
154957
+ const matchConsequentResult = matchOptionalTestBlock(test, context.blocks);
154958
+ if (!matchConsequentResult) {
154959
+ return null;
154960
+ }
154961
+ CompilerError.invariant(
154962
+ matchConsequentResult.consequentGoto === optional.terminal.fallthrough,
154963
+ {
154964
+ reason: '[OptionalChainDeps] Unexpected optional goto-fallthrough',
154965
+ description: `${matchConsequentResult.consequentGoto} != ${optional.terminal.fallthrough}`,
154966
+ loc: optional.terminal.loc,
154967
+ }
154968
+ );
154969
+ const load = {
154970
+ identifier: baseObject.identifier,
154971
+ path: [
154972
+ ...baseObject.path,
154973
+ {
154974
+ property: matchConsequentResult.property,
154975
+ optional: optional.terminal.optional,
154976
+ },
154977
+ ],
154978
+ };
154979
+ context.processedInstrsInOptional.add(
154980
+ matchConsequentResult.storeLocalInstrId
154981
+ );
154982
+ context.processedInstrsInOptional.add(test.id);
154983
+ context.temporariesReadInOptional.set(
154984
+ matchConsequentResult.consequentId,
154985
+ load
154986
+ );
154987
+ context.temporariesReadInOptional.set(matchConsequentResult.propertyId, load);
154988
+ return matchConsequentResult.consequentId;
154989
+ }
154681
154990
  var _Context_instances,
154682
154991
  _Context_declarations,
154683
154992
  _Context_reassignments,
@@ -154691,18 +155000,37 @@ function propagateScopeDependenciesHIR(fn) {
154691
155000
  const usedOutsideDeclaringScope =
154692
155001
  findTemporariesUsedOutsideDeclaringScope(fn);
154693
155002
  const temporaries = collectTemporariesSidemap(fn, usedOutsideDeclaringScope);
154694
- const hoistablePropertyLoads = collectHoistablePropertyLoads(fn, temporaries);
155003
+ const {
155004
+ temporariesReadInOptional: temporariesReadInOptional,
155005
+ processedInstrsInOptional: processedInstrsInOptional,
155006
+ hoistableObjects: hoistableObjects,
155007
+ } = collectOptionalChainSidemap(fn);
155008
+ const hoistablePropertyLoads = collectHoistablePropertyLoads(
155009
+ fn,
155010
+ temporaries,
155011
+ hoistableObjects
155012
+ );
154695
155013
  const scopeDeps = collectDependencies(
154696
155014
  fn,
154697
155015
  usedOutsideDeclaringScope,
154698
- temporaries
155016
+ new Map([...temporaries, ...temporariesReadInOptional]),
155017
+ processedInstrsInOptional
154699
155018
  );
154700
155019
  for (const [scope, deps] of scopeDeps) {
154701
- const tree = new ReactiveScopeDependencyTreeHIR();
155020
+ if (deps.length === 0) {
155021
+ continue;
155022
+ }
155023
+ const hoistables = hoistablePropertyLoads.get(scope.id);
155024
+ CompilerError.invariant(hoistables != null, {
155025
+ reason: '[PropagateScopeDependencies] Scope not found in tracked blocks',
155026
+ loc: GeneratedSource,
155027
+ });
155028
+ const tree = new ReactiveScopeDependencyTreeHIR(
155029
+ [...hoistables.assumedNonNullObjects].map(o => o.fullPath)
155030
+ );
154702
155031
  for (const dep of deps) {
154703
155032
  tree.addDependency(Object.assign({}, dep));
154704
155033
  }
154705
- recordHoistablePropertyReads(hoistablePropertyLoads, scope.id, tree);
154706
155034
  const candidates = tree.deriveMinimalDependencies();
154707
155035
  for (const candidateDep of candidates) {
154708
155036
  if (
@@ -154779,7 +155107,12 @@ function collectTemporariesSidemap(fn, usedOutsideDeclaringScope) {
154779
155107
  lvalue.identifier.declarationId
154780
155108
  );
154781
155109
  if (value.kind === 'PropertyLoad' && !usedOutside) {
154782
- const property = getProperty(value.object, value.property, temporaries);
155110
+ const property = getProperty(
155111
+ value.object,
155112
+ value.property,
155113
+ false,
155114
+ temporaries
155115
+ );
154783
155116
  temporaries.set(lvalue.identifier.id, property);
154784
155117
  } else if (
154785
155118
  value.kind === 'LoadLocal' &&
@@ -154796,6 +155129,25 @@ function collectTemporariesSidemap(fn, usedOutsideDeclaringScope) {
154796
155129
  }
154797
155130
  return temporaries;
154798
155131
  }
155132
+ function getProperty(object, propertyName, optional, temporaries) {
155133
+ const resolvedDependency = temporaries.get(object.identifier.id);
155134
+ let property;
155135
+ if (resolvedDependency == null) {
155136
+ property = {
155137
+ identifier: object.identifier,
155138
+ path: [{property: propertyName, optional: optional}],
155139
+ };
155140
+ } else {
155141
+ property = {
155142
+ identifier: resolvedDependency.identifier,
155143
+ path: [
155144
+ ...resolvedDependency.path,
155145
+ {property: propertyName, optional: optional},
155146
+ ],
155147
+ };
155148
+ }
155149
+ return property;
155150
+ }
154799
155151
  class Context {
154800
155152
  constructor(temporariesUsedOutsideScope, temporaries) {
154801
155153
  _Context_instances.add(this);
@@ -154909,10 +155261,11 @@ class Context {
154909
155261
  : {identifier: place.identifier, path: []}
154910
155262
  );
154911
155263
  }
154912
- visitProperty(object, property) {
155264
+ visitProperty(object, property, optional) {
154913
155265
  const nextDependency = getProperty(
154914
155266
  object,
154915
155267
  property,
155268
+ optional,
154916
155269
  __classPrivateFieldGet(this, _Context_temporaries, 'f')
154917
155270
  );
154918
155271
  this.visitDependency(nextDependency);
@@ -155043,7 +155396,7 @@ function handleInstruction(instr, context) {
155043
155396
  }
155044
155397
  } else if (value.kind === 'PropertyLoad') {
155045
155398
  if (context.isUsedOutsideDeclaringScope(lvalue)) {
155046
- context.visitProperty(value.object, value.property);
155399
+ context.visitProperty(value.object, value.property, false);
155047
155400
  }
155048
155401
  } else if (value.kind === 'StoreLocal') {
155049
155402
  context.visitOperand(value.value);
@@ -155074,7 +155427,12 @@ function handleInstruction(instr, context) {
155074
155427
  }
155075
155428
  context.declare(lvalue.identifier, {id: id, scope: context.currentScope});
155076
155429
  }
155077
- function collectDependencies(fn, usedOutsideDeclaringScope, temporaries) {
155430
+ function collectDependencies(
155431
+ fn,
155432
+ usedOutsideDeclaringScope,
155433
+ temporaries,
155434
+ processedInstrsInOptional
155435
+ ) {
155078
155436
  const context = new Context(usedOutsideDeclaringScope, temporaries);
155079
155437
  for (const param of fn.params) {
155080
155438
  if (param.kind === 'Identifier') {
@@ -155111,25 +155469,27 @@ function collectDependencies(fn, usedOutsideDeclaringScope, temporaries) {
155111
155469
  : scopeBlockInfo.pruned
155112
155470
  );
155113
155471
  }
155472
+ for (const phi of block.phis) {
155473
+ for (const operand of phi.operands) {
155474
+ const maybeOptionalChain = temporaries.get(operand[1].id);
155475
+ if (maybeOptionalChain) {
155476
+ context.visitDependency(maybeOptionalChain);
155477
+ }
155478
+ }
155479
+ }
155114
155480
  for (const instr of block.instructions) {
155115
- handleInstruction(instr, context);
155481
+ if (!processedInstrsInOptional.has(instr.id)) {
155482
+ handleInstruction(instr, context);
155483
+ }
155116
155484
  }
155117
- for (const place of eachTerminalOperand(block.terminal)) {
155118
- context.visitOperand(place);
155485
+ if (!processedInstrsInOptional.has(block.terminal.id)) {
155486
+ for (const place of eachTerminalOperand(block.terminal)) {
155487
+ context.visitOperand(place);
155488
+ }
155119
155489
  }
155120
155490
  }
155121
155491
  return context.deps;
155122
155492
  }
155123
- function recordHoistablePropertyReads(nodes, scopeId, tree) {
155124
- const node = nodes.get(scopeId);
155125
- CompilerError.invariant(node != null, {
155126
- reason: '[PropagateScopeDependencies] Scope not found in tracked blocks',
155127
- loc: GeneratedSource,
155128
- });
155129
- for (const item of node.assumedNonNullObjects) {
155130
- tree.markNodesNonNull(Object.assign({}, item.fullPath));
155131
- }
155132
- }
155133
155493
  function* run(
155134
155494
  func,
155135
155495
  config,