metro-runtime 0.71.0 → 0.71.3
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/package.json +1 -1
- package/src/polyfills/require.js +102 -65
- package/src/polyfills/require.js.flow +117 -70
package/package.json
CHANGED
package/src/polyfills/require.js
CHANGED
|
@@ -19,6 +19,7 @@ var modules = clear(); // Don't use a Symbol here, it would pull in an extra pol
|
|
|
19
19
|
// additional stuff (e.g. Array.from).
|
|
20
20
|
|
|
21
21
|
const EMPTY = {};
|
|
22
|
+
const CYCLE_DETECTED = {};
|
|
22
23
|
const { hasOwnProperty } = {};
|
|
23
24
|
|
|
24
25
|
if (__DEV__) {
|
|
@@ -110,14 +111,17 @@ function metroRequire(moduleId) {
|
|
|
110
111
|
if (initializingIndex !== -1) {
|
|
111
112
|
const cycle = initializingModuleIds
|
|
112
113
|
.slice(initializingIndex)
|
|
113
|
-
.map((id) => (modules[id] ? modules[id].verboseName : "[unknown]"));
|
|
114
|
+
.map((id) => (modules[id] ? modules[id].verboseName : "[unknown]"));
|
|
114
115
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
116
|
+
if (shouldPrintRequireCycle(cycle)) {
|
|
117
|
+
cycle.push(cycle[0]); // We want to print A -> B -> A:
|
|
118
|
+
|
|
119
|
+
console.warn(
|
|
120
|
+
`Require cycle: ${cycle.join(" -> ")}\n\n` +
|
|
121
|
+
"Require cycles are allowed, but can result in uninitialized values. " +
|
|
122
|
+
"Consider refactoring to remove the need for a cycle."
|
|
123
|
+
);
|
|
124
|
+
}
|
|
121
125
|
}
|
|
122
126
|
}
|
|
123
127
|
|
|
@@ -125,6 +129,21 @@ function metroRequire(moduleId) {
|
|
|
125
129
|
return module && module.isInitialized
|
|
126
130
|
? module.publicModule.exports
|
|
127
131
|
: guardedLoadModule(moduleIdReallyIsNumber, module);
|
|
132
|
+
} // We print require cycles unless they match a pattern in the
|
|
133
|
+
// `requireCycleIgnorePatterns` configuration.
|
|
134
|
+
|
|
135
|
+
function shouldPrintRequireCycle(modules) {
|
|
136
|
+
const regExps =
|
|
137
|
+
global[__METRO_GLOBAL_PREFIX__ + "__requireCycleIgnorePatterns"];
|
|
138
|
+
|
|
139
|
+
if (!Array.isArray(regExps)) {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const isIgnored = (module) =>
|
|
144
|
+
module != null && regExps.some((regExp) => regExp.test(module)); // Print the cycle unless any part of it is ignored
|
|
145
|
+
|
|
146
|
+
return modules.every((module) => !isIgnored(module));
|
|
128
147
|
}
|
|
129
148
|
|
|
130
149
|
function metroImportDefault(moduleId) {
|
|
@@ -473,63 +492,76 @@ if (__DEV__) {
|
|
|
473
492
|
// have side effects and lead to confusing and meaningless crashes.
|
|
474
493
|
|
|
475
494
|
let didBailOut = false;
|
|
476
|
-
|
|
477
|
-
[id], // Start with the changed module and go upwards
|
|
478
|
-
(pendingID) => {
|
|
479
|
-
const pendingModule = modules[pendingID];
|
|
480
|
-
|
|
481
|
-
if (pendingModule == null) {
|
|
482
|
-
// Nothing to do.
|
|
483
|
-
return [];
|
|
484
|
-
}
|
|
495
|
+
let updatedModuleIDs;
|
|
485
496
|
|
|
486
|
-
|
|
497
|
+
try {
|
|
498
|
+
updatedModuleIDs = topologicalSort(
|
|
499
|
+
[id], // Start with the changed module and go upwards
|
|
500
|
+
(pendingID) => {
|
|
501
|
+
const pendingModule = modules[pendingID];
|
|
502
|
+
|
|
503
|
+
if (pendingModule == null) {
|
|
504
|
+
// Nothing to do.
|
|
505
|
+
return [];
|
|
506
|
+
}
|
|
487
507
|
|
|
488
|
-
|
|
489
|
-
throw new Error(
|
|
490
|
-
"[Refresh] Expected module.hot to always exist in DEV."
|
|
491
|
-
);
|
|
492
|
-
} // A module can be accepted manually from within itself.
|
|
508
|
+
const pendingHot = pendingModule.hot;
|
|
493
509
|
|
|
494
|
-
|
|
510
|
+
if (pendingHot == null) {
|
|
511
|
+
throw new Error(
|
|
512
|
+
"[Refresh] Expected module.hot to always exist in DEV."
|
|
513
|
+
);
|
|
514
|
+
} // A module can be accepted manually from within itself.
|
|
495
515
|
|
|
496
|
-
|
|
497
|
-
// Or React Refresh may mark it accepted based on exports.
|
|
498
|
-
const isBoundary = isReactRefreshBoundary(
|
|
499
|
-
Refresh,
|
|
500
|
-
pendingModule.publicModule.exports
|
|
501
|
-
);
|
|
516
|
+
let canAccept = pendingHot._didAccept;
|
|
502
517
|
|
|
503
|
-
if (
|
|
504
|
-
|
|
505
|
-
|
|
518
|
+
if (!canAccept && Refresh != null) {
|
|
519
|
+
// Or React Refresh may mark it accepted based on exports.
|
|
520
|
+
const isBoundary = isReactRefreshBoundary(
|
|
521
|
+
Refresh,
|
|
522
|
+
pendingModule.publicModule.exports
|
|
523
|
+
);
|
|
524
|
+
|
|
525
|
+
if (isBoundary) {
|
|
526
|
+
canAccept = true;
|
|
527
|
+
refreshBoundaryIDs.add(pendingID);
|
|
528
|
+
}
|
|
506
529
|
}
|
|
507
|
-
}
|
|
508
530
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
531
|
+
if (canAccept) {
|
|
532
|
+
// Don't look at parents.
|
|
533
|
+
return [];
|
|
534
|
+
} // If we bubble through the roof, there is no way to do a hot update.
|
|
535
|
+
// Bail out altogether. This is the failure case.
|
|
536
|
+
|
|
537
|
+
const parentIDs = inverseDependencies[pendingID];
|
|
538
|
+
|
|
539
|
+
if (parentIDs.length === 0) {
|
|
540
|
+
// Reload the app because the hot reload can't succeed.
|
|
541
|
+
// This should work both on web and React Native.
|
|
542
|
+
performFullRefresh("No root boundary", {
|
|
543
|
+
source: mod,
|
|
544
|
+
failed: pendingModule,
|
|
545
|
+
});
|
|
546
|
+
didBailOut = true;
|
|
547
|
+
return [];
|
|
548
|
+
} // This module can't handle the update but maybe all its parents can?
|
|
549
|
+
// Put them all in the queue to run the same set of checks.
|
|
550
|
+
|
|
551
|
+
return parentIDs;
|
|
552
|
+
},
|
|
553
|
+
() => didBailOut // Should we stop?
|
|
554
|
+
).reverse();
|
|
555
|
+
} catch (e) {
|
|
556
|
+
if (e === CYCLE_DETECTED) {
|
|
557
|
+
performFullRefresh("Dependency cycle", {
|
|
558
|
+
source: mod,
|
|
559
|
+
});
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
throw e;
|
|
564
|
+
}
|
|
533
565
|
|
|
534
566
|
if (didBailOut) {
|
|
535
567
|
return;
|
|
@@ -539,7 +571,6 @@ if (__DEV__) {
|
|
|
539
571
|
const seenModuleIDs = new Set();
|
|
540
572
|
|
|
541
573
|
for (let i = 0; i < updatedModuleIDs.length; i++) {
|
|
542
|
-
// Don't process twice if we have a cycle.
|
|
543
574
|
const updatedID = updatedModuleIDs[i];
|
|
544
575
|
|
|
545
576
|
if (seenModuleIDs.has(updatedID)) {
|
|
@@ -651,29 +682,35 @@ if (__DEV__) {
|
|
|
651
682
|
const topologicalSort = function (roots, getEdges, earlyStop) {
|
|
652
683
|
const result = [];
|
|
653
684
|
const visited = new Set();
|
|
685
|
+
const stack = new Set();
|
|
654
686
|
|
|
655
687
|
function traverseDependentNodes(node) {
|
|
688
|
+
if (stack.has(node)) {
|
|
689
|
+
throw CYCLE_DETECTED;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
if (visited.has(node)) {
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
|
|
656
696
|
visited.add(node);
|
|
697
|
+
stack.add(node);
|
|
657
698
|
const dependentNodes = getEdges(node);
|
|
658
699
|
|
|
659
700
|
if (earlyStop(node)) {
|
|
701
|
+
stack.delete(node);
|
|
660
702
|
return;
|
|
661
703
|
}
|
|
662
704
|
|
|
663
705
|
dependentNodes.forEach((dependent) => {
|
|
664
|
-
if (visited.has(dependent)) {
|
|
665
|
-
return;
|
|
666
|
-
}
|
|
667
|
-
|
|
668
706
|
traverseDependentNodes(dependent);
|
|
669
707
|
});
|
|
708
|
+
stack.delete(node);
|
|
670
709
|
result.push(node);
|
|
671
710
|
}
|
|
672
711
|
|
|
673
712
|
roots.forEach((root) => {
|
|
674
|
-
|
|
675
|
-
traverseDependentNodes(root);
|
|
676
|
-
}
|
|
713
|
+
traverseDependentNodes(root);
|
|
677
714
|
});
|
|
678
715
|
return result;
|
|
679
716
|
};
|
|
@@ -74,6 +74,7 @@ var modules = clear();
|
|
|
74
74
|
// Don't use a Symbol here, it would pull in an extra polyfill with all sorts of
|
|
75
75
|
// additional stuff (e.g. Array.from).
|
|
76
76
|
const EMPTY = {};
|
|
77
|
+
const CYCLE_DETECTED = {};
|
|
77
78
|
const {hasOwnProperty} = {};
|
|
78
79
|
|
|
79
80
|
if (__DEV__) {
|
|
@@ -176,13 +177,15 @@ function metroRequire(moduleId: ModuleID | VerboseModuleNameForDev): Exports {
|
|
|
176
177
|
.map((id: number) =>
|
|
177
178
|
modules[id] ? modules[id].verboseName : '[unknown]',
|
|
178
179
|
);
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
180
|
+
|
|
181
|
+
if (shouldPrintRequireCycle(cycle)) {
|
|
182
|
+
cycle.push(cycle[0]); // We want to print A -> B -> A:
|
|
183
|
+
console.warn(
|
|
184
|
+
`Require cycle: ${cycle.join(' -> ')}\n\n` +
|
|
185
|
+
'Require cycles are allowed, but can result in uninitialized values. ' +
|
|
186
|
+
'Consider refactoring to remove the need for a cycle.',
|
|
187
|
+
);
|
|
188
|
+
}
|
|
186
189
|
}
|
|
187
190
|
}
|
|
188
191
|
|
|
@@ -193,6 +196,22 @@ function metroRequire(moduleId: ModuleID | VerboseModuleNameForDev): Exports {
|
|
|
193
196
|
: guardedLoadModule(moduleIdReallyIsNumber, module);
|
|
194
197
|
}
|
|
195
198
|
|
|
199
|
+
// We print require cycles unless they match a pattern in the
|
|
200
|
+
// `requireCycleIgnorePatterns` configuration.
|
|
201
|
+
function shouldPrintRequireCycle(modules: $ReadOnlyArray<?string>): boolean {
|
|
202
|
+
const regExps =
|
|
203
|
+
global[__METRO_GLOBAL_PREFIX__ + '__requireCycleIgnorePatterns'];
|
|
204
|
+
if (!Array.isArray(regExps)) {
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const isIgnored = (module: ?string) =>
|
|
209
|
+
module != null && regExps.some(regExp => regExp.test(module));
|
|
210
|
+
|
|
211
|
+
// Print the cycle unless any part of it is ignored
|
|
212
|
+
return modules.every(module => !isIgnored(module));
|
|
213
|
+
}
|
|
214
|
+
|
|
196
215
|
function metroImportDefault(moduleId: ModuleID | VerboseModuleNameForDev) {
|
|
197
216
|
if (__DEV__ && typeof moduleId === 'string') {
|
|
198
217
|
const verboseName = moduleId;
|
|
@@ -542,56 +561,67 @@ if (__DEV__) {
|
|
|
542
561
|
// have side effects and lead to confusing and meaningless crashes.
|
|
543
562
|
|
|
544
563
|
let didBailOut = false;
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
if (pendingHot == null) {
|
|
555
|
-
throw new Error(
|
|
556
|
-
'[Refresh] Expected module.hot to always exist in DEV.',
|
|
557
|
-
);
|
|
558
|
-
}
|
|
559
|
-
// A module can be accepted manually from within itself.
|
|
560
|
-
let canAccept = pendingHot._didAccept;
|
|
561
|
-
if (!canAccept && Refresh != null) {
|
|
562
|
-
// Or React Refresh may mark it accepted based on exports.
|
|
563
|
-
const isBoundary = isReactRefreshBoundary(
|
|
564
|
-
Refresh,
|
|
565
|
-
pendingModule.publicModule.exports,
|
|
566
|
-
);
|
|
567
|
-
if (isBoundary) {
|
|
568
|
-
canAccept = true;
|
|
569
|
-
refreshBoundaryIDs.add(pendingID);
|
|
564
|
+
let updatedModuleIDs;
|
|
565
|
+
try {
|
|
566
|
+
updatedModuleIDs = topologicalSort(
|
|
567
|
+
[id], // Start with the changed module and go upwards
|
|
568
|
+
pendingID => {
|
|
569
|
+
const pendingModule = modules[pendingID];
|
|
570
|
+
if (pendingModule == null) {
|
|
571
|
+
// Nothing to do.
|
|
572
|
+
return [];
|
|
570
573
|
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
574
|
+
const pendingHot = pendingModule.hot;
|
|
575
|
+
if (pendingHot == null) {
|
|
576
|
+
throw new Error(
|
|
577
|
+
'[Refresh] Expected module.hot to always exist in DEV.',
|
|
578
|
+
);
|
|
579
|
+
}
|
|
580
|
+
// A module can be accepted manually from within itself.
|
|
581
|
+
let canAccept = pendingHot._didAccept;
|
|
582
|
+
if (!canAccept && Refresh != null) {
|
|
583
|
+
// Or React Refresh may mark it accepted based on exports.
|
|
584
|
+
const isBoundary = isReactRefreshBoundary(
|
|
585
|
+
Refresh,
|
|
586
|
+
pendingModule.publicModule.exports,
|
|
587
|
+
);
|
|
588
|
+
if (isBoundary) {
|
|
589
|
+
canAccept = true;
|
|
590
|
+
refreshBoundaryIDs.add(pendingID);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
if (canAccept) {
|
|
594
|
+
// Don't look at parents.
|
|
595
|
+
return [];
|
|
596
|
+
}
|
|
597
|
+
// If we bubble through the roof, there is no way to do a hot update.
|
|
598
|
+
// Bail out altogether. This is the failure case.
|
|
599
|
+
const parentIDs = inverseDependencies[pendingID];
|
|
600
|
+
if (parentIDs.length === 0) {
|
|
601
|
+
// Reload the app because the hot reload can't succeed.
|
|
602
|
+
// This should work both on web and React Native.
|
|
603
|
+
performFullRefresh('No root boundary', {
|
|
604
|
+
source: mod,
|
|
605
|
+
failed: pendingModule,
|
|
606
|
+
});
|
|
607
|
+
didBailOut = true;
|
|
608
|
+
return [];
|
|
609
|
+
}
|
|
610
|
+
// This module can't handle the update but maybe all its parents can?
|
|
611
|
+
// Put them all in the queue to run the same set of checks.
|
|
612
|
+
return parentIDs;
|
|
613
|
+
},
|
|
614
|
+
() => didBailOut, // Should we stop?
|
|
615
|
+
).reverse();
|
|
616
|
+
} catch (e) {
|
|
617
|
+
if (e === CYCLE_DETECTED) {
|
|
618
|
+
performFullRefresh('Dependency cycle', {
|
|
619
|
+
source: mod,
|
|
620
|
+
});
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
throw e;
|
|
624
|
+
}
|
|
595
625
|
|
|
596
626
|
if (didBailOut) {
|
|
597
627
|
return;
|
|
@@ -601,7 +631,6 @@ if (__DEV__) {
|
|
|
601
631
|
// Run the actual factories.
|
|
602
632
|
const seenModuleIDs = new Set();
|
|
603
633
|
for (let i = 0; i < updatedModuleIDs.length; i++) {
|
|
604
|
-
// Don't process twice if we have a cycle.
|
|
605
634
|
const updatedID = updatedModuleIDs[i];
|
|
606
635
|
if (seenModuleIDs.has(updatedID)) {
|
|
607
636
|
continue;
|
|
@@ -709,24 +738,29 @@ if (__DEV__) {
|
|
|
709
738
|
): Array<T> {
|
|
710
739
|
const result = [];
|
|
711
740
|
const visited = new Set();
|
|
741
|
+
const stack = new Set();
|
|
712
742
|
function traverseDependentNodes(node: T) {
|
|
743
|
+
if (stack.has(node)) {
|
|
744
|
+
throw CYCLE_DETECTED;
|
|
745
|
+
}
|
|
746
|
+
if (visited.has(node)) {
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
713
749
|
visited.add(node);
|
|
750
|
+
stack.add(node);
|
|
714
751
|
const dependentNodes = getEdges(node);
|
|
715
752
|
if (earlyStop(node)) {
|
|
753
|
+
stack.delete(node);
|
|
716
754
|
return;
|
|
717
755
|
}
|
|
718
756
|
dependentNodes.forEach(dependent => {
|
|
719
|
-
if (visited.has(dependent)) {
|
|
720
|
-
return;
|
|
721
|
-
}
|
|
722
757
|
traverseDependentNodes(dependent);
|
|
723
758
|
});
|
|
759
|
+
stack.delete(node);
|
|
724
760
|
result.push(node);
|
|
725
761
|
}
|
|
726
762
|
roots.forEach(root => {
|
|
727
|
-
|
|
728
|
-
traverseDependentNodes(root);
|
|
729
|
-
}
|
|
763
|
+
traverseDependentNodes(root);
|
|
730
764
|
});
|
|
731
765
|
return result;
|
|
732
766
|
};
|
|
@@ -806,7 +840,10 @@ if (__DEV__) {
|
|
|
806
840
|
|
|
807
841
|
const performFullRefresh = (
|
|
808
842
|
reason: string,
|
|
809
|
-
modules: $ReadOnly<{
|
|
843
|
+
modules: $ReadOnly<{
|
|
844
|
+
source?: ModuleDefinition,
|
|
845
|
+
failed?: ModuleDefinition,
|
|
846
|
+
}>,
|
|
810
847
|
) => {
|
|
811
848
|
/* global window */
|
|
812
849
|
if (
|
|
@@ -830,7 +867,10 @@ if (__DEV__) {
|
|
|
830
867
|
};
|
|
831
868
|
|
|
832
869
|
// Modules that only export components become React Refresh boundaries.
|
|
833
|
-
var isReactRefreshBoundary = function (
|
|
870
|
+
var isReactRefreshBoundary = function (
|
|
871
|
+
Refresh: any,
|
|
872
|
+
moduleExports: Exports,
|
|
873
|
+
): boolean {
|
|
834
874
|
if (Refresh.isLikelyComponentType(moduleExports)) {
|
|
835
875
|
return true;
|
|
836
876
|
}
|
|
@@ -859,9 +899,9 @@ if (__DEV__) {
|
|
|
859
899
|
};
|
|
860
900
|
|
|
861
901
|
var shouldInvalidateReactRefreshBoundary = (
|
|
862
|
-
Refresh,
|
|
863
|
-
prevExports,
|
|
864
|
-
nextExports,
|
|
902
|
+
Refresh: any,
|
|
903
|
+
prevExports: Exports,
|
|
904
|
+
nextExports: Exports,
|
|
865
905
|
) => {
|
|
866
906
|
const prevSignature = getRefreshBoundarySignature(Refresh, prevExports);
|
|
867
907
|
const nextSignature = getRefreshBoundarySignature(Refresh, nextExports);
|
|
@@ -877,7 +917,10 @@ if (__DEV__) {
|
|
|
877
917
|
};
|
|
878
918
|
|
|
879
919
|
// When this signature changes, it's unsafe to stop at this refresh boundary.
|
|
880
|
-
var getRefreshBoundarySignature = (
|
|
920
|
+
var getRefreshBoundarySignature = (
|
|
921
|
+
Refresh: any,
|
|
922
|
+
moduleExports: Exports,
|
|
923
|
+
): Array<mixed> => {
|
|
881
924
|
const signature = [];
|
|
882
925
|
signature.push(Refresh.getFamilyByType(moduleExports));
|
|
883
926
|
if (moduleExports == null || typeof moduleExports !== 'object') {
|
|
@@ -900,7 +943,11 @@ if (__DEV__) {
|
|
|
900
943
|
return signature;
|
|
901
944
|
};
|
|
902
945
|
|
|
903
|
-
var registerExportsForReactRefresh = (
|
|
946
|
+
var registerExportsForReactRefresh = (
|
|
947
|
+
Refresh: any,
|
|
948
|
+
moduleExports: Exports,
|
|
949
|
+
moduleID: ModuleID,
|
|
950
|
+
) => {
|
|
904
951
|
Refresh.register(moduleExports, moduleID + ' %exports%');
|
|
905
952
|
if (moduleExports == null || typeof moduleExports !== 'object') {
|
|
906
953
|
// Exit if we can't iterate over exports.
|