@expo/metro-file-map 56.0.1 → 56.0.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/build/cache/DiskCacheManager.d.ts +7 -0
- package/build/cache/DiskCacheManager.js +6 -1
- package/build/crawlers/node/fallback.js +2 -1
- package/build/crawlers/node/index.js +8 -2
- package/build/crawlers/watchman/index.js +2 -2
- package/build/lib/RootPathUtils.js +5 -4
- package/build/lib/TreeFS.js +215 -186
- package/build/lib/isWatcherExcluded.d.ts +1 -0
- package/build/lib/isWatcherExcluded.js +7 -0
- package/build/watchers/AbstractWatcher.js +3 -3
- package/package.json +2 -2
- package/build/lib/isVcsPath.d.ts +0 -1
- package/build/lib/isVcsPath.js +0 -7
|
@@ -5,6 +5,13 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import type { BuildParameters, CacheData, CacheManager, CacheManagerFactoryOptions, CacheManagerWriteOptions } from '../types';
|
|
8
|
+
declare global {
|
|
9
|
+
namespace NodeJS {
|
|
10
|
+
interface Process {
|
|
11
|
+
isBun?: boolean;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
8
15
|
interface AutoSaveOptions {
|
|
9
16
|
readonly debounceMs: number;
|
|
10
17
|
}
|
|
@@ -17,7 +17,12 @@ const timers_1 = require("timers");
|
|
|
17
17
|
const v8_1 = require("v8");
|
|
18
18
|
const rootRelativeCacheKeys_1 = __importDefault(require("../lib/rootRelativeCacheKeys"));
|
|
19
19
|
const debug = require('debug')('Metro:FileMapCache');
|
|
20
|
-
|
|
20
|
+
let DEFAULT_PREFIX = 'metro-file-map';
|
|
21
|
+
if (process.isBun) {
|
|
22
|
+
// NOTE(@kitten): The v8 serialize/deserialize format isn't 100% compatible between
|
|
23
|
+
// Node and Bun and therefore we should fork the cache file
|
|
24
|
+
DEFAULT_PREFIX += '-bun';
|
|
25
|
+
}
|
|
21
26
|
const DEFAULT_DIRECTORY = (0, os_1.tmpdir)();
|
|
22
27
|
const DEFAULT_AUTO_SAVE_DEBOUNCE_MS = 5000;
|
|
23
28
|
// NOTE(@kitten): We're incompatible with Metro, so need our own naming
|
|
@@ -68,7 +68,8 @@ function createFallbackFilesystem(opts) {
|
|
|
68
68
|
}
|
|
69
69
|
if (entry.isDirectory()) {
|
|
70
70
|
// NOTE(@kitten): ".git" and ".hg" check replace the VCS_DIRECTORIES ignore pattern
|
|
71
|
-
|
|
71
|
+
// NOTE(@kitten): `.cxx` is ephemeral and should always be safe to ignore
|
|
72
|
+
if (!result.has(name) && name !== '.git' && name !== '.hg' && name !== '.cxx') {
|
|
72
73
|
const childDir = new Map();
|
|
73
74
|
markDir(childDir, FallbackFlag.VISITED);
|
|
74
75
|
result.set(name, childDir);
|
|
@@ -58,15 +58,21 @@ function find(roots, extensions, ignore, includeSymlinks, rootDir, console, prev
|
|
|
58
58
|
fs.readdir(directory, { withFileTypes: true }, (err, entries) => {
|
|
59
59
|
activeCalls--;
|
|
60
60
|
if (err) {
|
|
61
|
-
|
|
61
|
+
// NOTE(@kitten): This isn't necessarily a problem and we can ignore this
|
|
62
|
+
/*
|
|
63
|
+
console.warn(
|
|
64
|
+
`Error "${(err as any).code ?? err.message}" reading contents of "${directory}", skipping. Add this directory to your ignore list to exclude it.`
|
|
65
|
+
);
|
|
66
|
+
*/
|
|
62
67
|
}
|
|
63
68
|
else {
|
|
64
69
|
for (let idx = 0; idx < entries.length; idx++) {
|
|
65
70
|
const entry = entries[idx];
|
|
66
71
|
const name = entry.name;
|
|
67
72
|
// NOTE(@kitten): This replaces the VCS_DIRECTORIES ignore pattern
|
|
73
|
+
// NOTE(@kitten): `.cxx` is ephemeral and should always be safe to ignore
|
|
68
74
|
const isDirectory = entry.isDirectory();
|
|
69
|
-
if (isDirectory && (name === '.git' || name === '.hg')) {
|
|
75
|
+
if (isDirectory && (name === '.git' || name === '.hg' || name === '.cxx')) {
|
|
70
76
|
continue;
|
|
71
77
|
}
|
|
72
78
|
const file = directory + path.sep + name;
|
|
@@ -49,7 +49,7 @@ const path = __importStar(require("path"));
|
|
|
49
49
|
const perf_hooks_1 = require("perf_hooks");
|
|
50
50
|
const planQuery_1 = require("./planQuery");
|
|
51
51
|
const RootPathUtils_1 = require("../../lib/RootPathUtils");
|
|
52
|
-
const
|
|
52
|
+
const isWatcherExcluded_1 = __importDefault(require("../../lib/isWatcherExcluded"));
|
|
53
53
|
const normalizePathSeparatorsToPosix_1 = __importDefault(require("../../lib/normalizePathSeparatorsToPosix"));
|
|
54
54
|
const normalizePathSeparatorsToSystem_1 = __importDefault(require("../../lib/normalizePathSeparatorsToSystem"));
|
|
55
55
|
const WATCHMAN_WARNING_INITIAL_DELAY_MILLISECONDS = 10000;
|
|
@@ -248,7 +248,7 @@ async function watchmanCrawl({ abortSignal, computeSha1, extensions, ignore, inc
|
|
|
248
248
|
// Whether watchman can return exists: false in a fresh instance
|
|
249
249
|
// response is unknown, but there's nothing we need to do in that case.
|
|
250
250
|
}
|
|
251
|
-
else if (!(0,
|
|
251
|
+
else if (!(0, isWatcherExcluded_1.default)(fileData.name) && !ignore(filePath)) {
|
|
252
252
|
const { mtime_ms, size } = fileData;
|
|
253
253
|
(0, invariant_1.default)(mtime_ms != null && size != null, 'missing file data in watchman response');
|
|
254
254
|
const mtime = typeof mtime_ms === 'number' ? mtime_ms : mtime_ms.toNumber();
|
|
@@ -130,10 +130,11 @@ class RootPathUtils {
|
|
|
130
130
|
if (right.length === 0) {
|
|
131
131
|
return left;
|
|
132
132
|
}
|
|
133
|
-
else if (pos > this.#rootDepth * UP_FRAGMENT_SEP_LENGTH) {
|
|
134
|
-
//
|
|
135
|
-
//
|
|
136
|
-
//
|
|
133
|
+
else if (IS_WIN32 && pos > this.#rootDepth * UP_FRAGMENT_SEP_LENGTH) {
|
|
134
|
+
// On a real file system, navigating to `..` at the top level (posix `/`
|
|
135
|
+
// or Windows drive) is a no-op, but we can't respect that on Windows
|
|
136
|
+
// because Metro uses e.g. `..\..\D:\foo` to represent cross-drive
|
|
137
|
+
// relative paths.
|
|
137
138
|
return right;
|
|
138
139
|
}
|
|
139
140
|
// left may already end in a path separator only if it is a filesystem root,
|
package/build/lib/TreeFS.js
CHANGED
|
@@ -13,16 +13,19 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
13
13
|
const invariant_1 = __importDefault(require("invariant"));
|
|
14
14
|
const path_1 = __importDefault(require("path"));
|
|
15
15
|
const constants_1 = __importDefault(require("../constants"));
|
|
16
|
+
const RootPathUtils_1 = require("./RootPathUtils");
|
|
16
17
|
const normalizePathSeparatorsToPosix_1 = __importDefault(require("./normalizePathSeparatorsToPosix"));
|
|
17
18
|
const normalizePathSeparatorsToSystem_1 = __importDefault(require("./normalizePathSeparatorsToSystem"));
|
|
18
19
|
const fallback_1 = require("../crawlers/node/fallback");
|
|
19
|
-
const RootPathUtils_1 = require("./RootPathUtils");
|
|
20
20
|
function isDirectory(node) {
|
|
21
|
-
return node
|
|
21
|
+
return node != null && typeof node.get === 'function';
|
|
22
22
|
}
|
|
23
23
|
function isRegularFile(node) {
|
|
24
24
|
return node != null && node[constants_1.default.SYMLINK] === 0;
|
|
25
25
|
}
|
|
26
|
+
// POSIX SYMLOOP_MAX. Bounded counter instead of a per-walk `Set` of
|
|
27
|
+
// visited targets — cycles are rare; bailing after N follows is enough.
|
|
28
|
+
const SYMLOOP_MAX = 40;
|
|
26
29
|
/**
|
|
27
30
|
* OVERVIEW:
|
|
28
31
|
*
|
|
@@ -81,6 +84,32 @@ class TreeFS {
|
|
|
81
84
|
#rootPattern;
|
|
82
85
|
#roots;
|
|
83
86
|
#rootNode = new Map();
|
|
87
|
+
#followScratch = {
|
|
88
|
+
parentNode: new Map(),
|
|
89
|
+
ancestorOfRootIdx: undefined,
|
|
90
|
+
targetNormalPath: '',
|
|
91
|
+
fromIdx: 0,
|
|
92
|
+
unseenPathFromIdx: 0,
|
|
93
|
+
followedSymlinks: 0,
|
|
94
|
+
};
|
|
95
|
+
// Hier isn't recursive; pool entries are mutated in place per call.
|
|
96
|
+
#hierAncestorsBuf = [];
|
|
97
|
+
#hierAncestorsPool = [];
|
|
98
|
+
#pushHierAncestor = (node, normalPath, segmentName, ancestorOfRootIdx) => {
|
|
99
|
+
const i = this.#hierAncestorsBuf.length;
|
|
100
|
+
let entry = this.#hierAncestorsPool[i];
|
|
101
|
+
if (entry === undefined) {
|
|
102
|
+
entry = { ancestorOfRootIdx, node, normalPath, segmentName };
|
|
103
|
+
this.#hierAncestorsPool[i] = entry;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
entry.ancestorOfRootIdx = ancestorOfRootIdx;
|
|
107
|
+
entry.node = node;
|
|
108
|
+
entry.normalPath = normalPath;
|
|
109
|
+
entry.segmentName = segmentName;
|
|
110
|
+
}
|
|
111
|
+
this.#hierAncestorsBuf.push(entry);
|
|
112
|
+
};
|
|
84
113
|
constructor(opts) {
|
|
85
114
|
const { rootDir, files, processFile, fallbackFilesystem, roots, serverRoot } = opts;
|
|
86
115
|
this.#rootDir = rootDir;
|
|
@@ -468,15 +497,151 @@ class TreeFS {
|
|
|
468
497
|
* `opts.X` branches. Thin convenience wrappers below (`#lookup`,
|
|
469
498
|
* `#lookupNoFollow`, `#lookupFromNode`, `#walkAndStream`) cover the
|
|
470
499
|
* common call shapes.
|
|
500
|
+
*
|
|
501
|
+
* Symlink-follow logic is shared via `#followSymlink`.
|
|
471
502
|
*/
|
|
472
|
-
|
|
473
|
-
|
|
503
|
+
/**
|
|
504
|
+
* For `..`-prefixed symlink targets: match remainder's leading segments
|
|
505
|
+
* against root parts (`/A/B/C/D` + remainder `B/C/foo.js` collapses two
|
|
506
|
+
* `..`s away). TreeFS has no downward back-links, so we climb up once
|
|
507
|
+
* from `#rootNode` to build a stack, then index into it.
|
|
508
|
+
*/
|
|
509
|
+
#collapseAgainstRootParts(ancestorOfRootIdx, parentNode, remainder, onSegment) {
|
|
510
|
+
const ancestors = [this.#rootNode];
|
|
511
|
+
{
|
|
512
|
+
let n = this.#rootNode;
|
|
513
|
+
for (let k = 1; k <= ancestorOfRootIdx; k++) {
|
|
514
|
+
n = n.get('..') ?? new Map();
|
|
515
|
+
if (!isDirectory(n))
|
|
516
|
+
break;
|
|
517
|
+
ancestors.push(n);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
const rootParts = this.#pathUtils.getParts();
|
|
521
|
+
let cursorIdx = 0;
|
|
522
|
+
// Trimmed by `'/..'` per step; `'..'.slice(0, -3) === ''` covers K=1→0.
|
|
523
|
+
let collapsedPath;
|
|
524
|
+
while (ancestorOfRootIdx > 0 &&
|
|
525
|
+
cursorIdx < remainder.length &&
|
|
526
|
+
ancestors.length > ancestorOfRootIdx - 1) {
|
|
527
|
+
const nextSep = remainder.indexOf(path_1.default.sep, cursorIdx);
|
|
528
|
+
const segEnd = nextSep === -1 ? remainder.length : nextSep;
|
|
529
|
+
const segName = remainder.slice(cursorIdx, segEnd);
|
|
530
|
+
const expectedPart = rootParts[rootParts.length - ancestorOfRootIdx];
|
|
531
|
+
if (segName !== expectedPart) {
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
534
|
+
ancestorOfRootIdx--;
|
|
535
|
+
parentNode = ancestors[ancestorOfRootIdx];
|
|
536
|
+
cursorIdx = nextSep === -1 ? remainder.length : nextSep + 1;
|
|
537
|
+
if (onSegment != null) {
|
|
538
|
+
if (collapsedPath === undefined) {
|
|
539
|
+
collapsedPath = '';
|
|
540
|
+
for (let k = 0; k < ancestorOfRootIdx; k++) {
|
|
541
|
+
collapsedPath = k === 0 ? '..' : collapsedPath + path_1.default.sep + '..';
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
else {
|
|
545
|
+
collapsedPath = collapsedPath.slice(0, -3);
|
|
546
|
+
}
|
|
547
|
+
onSegment(parentNode, collapsedPath, segName, ancestorOfRootIdx);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
return { ancestorOfRootIdx, parentNode, cursorIdx };
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Resolve an interior symlink. Returns a `WalkResult` to return
|
|
554
|
+
* immediately, or `undefined` after writing continue-state to
|
|
555
|
+
* `#followScratch` for the caller to read.
|
|
556
|
+
*/
|
|
557
|
+
#followSymlink(symlinkNode, currentPath, segmentName, remainingTargetPath, followedSymlinks, onSegment, collectLinkPaths) {
|
|
558
|
+
const normalSymlinkTarget = this.#resolveSymlinkTargetToNormalPath(symlinkNode, currentPath);
|
|
559
|
+
if (normalSymlinkTarget == null) {
|
|
560
|
+
return {
|
|
561
|
+
canonicalMissingPath: currentPath,
|
|
562
|
+
exists: false,
|
|
563
|
+
missingSegmentName: segmentName,
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
else if (++followedSymlinks >= SYMLOOP_MAX) {
|
|
567
|
+
return {
|
|
568
|
+
canonicalMissingPath: normalSymlinkTarget,
|
|
569
|
+
exists: false,
|
|
570
|
+
missingSegmentName: segmentName,
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
else if (collectLinkPaths != null) {
|
|
574
|
+
collectLinkPaths.add(this.#pathUtils.normalToAbsolute(currentPath));
|
|
575
|
+
}
|
|
576
|
+
// `onSegment: undefined` so target's interior dirs aren't emitted;
|
|
577
|
+
// only the destination is emitted (manually, below).
|
|
578
|
+
const subResult = this.#walkLookup(this.#rootNode, 0, 0, normalSymlinkTarget, undefined, collectLinkPaths, followedSymlinks);
|
|
579
|
+
if (!subResult.exists || remainingTargetPath === '') {
|
|
580
|
+
return subResult;
|
|
581
|
+
}
|
|
582
|
+
else if (!isDirectory(subResult.node)) {
|
|
583
|
+
return {
|
|
584
|
+
exists: false,
|
|
585
|
+
canonicalMissingPath: subResult.canonicalPath,
|
|
586
|
+
missingSegmentName: segmentName,
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
let parentNode = subResult.node;
|
|
590
|
+
let ancestorOfRootIdx = subResult.ancestorOfRootIdx;
|
|
591
|
+
if (onSegment != null) {
|
|
592
|
+
const subBaseStart = subResult.canonicalPath.lastIndexOf(path_1.default.sep) + 1;
|
|
593
|
+
const subBaseName = subResult.canonicalPath.slice(subBaseStart);
|
|
594
|
+
onSegment(parentNode, subResult.canonicalPath, subBaseName, ancestorOfRootIdx);
|
|
595
|
+
}
|
|
596
|
+
let cursorIdx = 0;
|
|
597
|
+
if (ancestorOfRootIdx != null && ancestorOfRootIdx > 0) {
|
|
598
|
+
const collapsed = this.#collapseAgainstRootParts(ancestorOfRootIdx, parentNode, remainingTargetPath, onSegment);
|
|
599
|
+
ancestorOfRootIdx = collapsed.ancestorOfRootIdx;
|
|
600
|
+
parentNode = collapsed.parentNode;
|
|
601
|
+
cursorIdx = collapsed.cursorIdx;
|
|
602
|
+
}
|
|
603
|
+
// Canonical-to-parentNode: `..`-string above root, empty at root, or
|
|
604
|
+
// sub-walk's canonical path inside the tree.
|
|
605
|
+
const realRemainder = remainingTargetPath.slice(cursorIdx);
|
|
606
|
+
let canonicalToParent;
|
|
607
|
+
if (ancestorOfRootIdx != null && ancestorOfRootIdx > 0) {
|
|
608
|
+
canonicalToParent = '..';
|
|
609
|
+
for (let k = 1; k < ancestorOfRootIdx; k++) {
|
|
610
|
+
canonicalToParent += path_1.default.sep + '..';
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
else if (ancestorOfRootIdx === 0) {
|
|
614
|
+
canonicalToParent = '';
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
canonicalToParent = subResult.canonicalPath;
|
|
618
|
+
}
|
|
619
|
+
const scratch = this.#followScratch;
|
|
620
|
+
scratch.parentNode = parentNode;
|
|
621
|
+
scratch.ancestorOfRootIdx = ancestorOfRootIdx;
|
|
622
|
+
scratch.followedSymlinks = followedSymlinks;
|
|
623
|
+
if (canonicalToParent === '') {
|
|
624
|
+
scratch.targetNormalPath = realRemainder;
|
|
625
|
+
scratch.fromIdx = 0;
|
|
626
|
+
scratch.unseenPathFromIdx = 0;
|
|
627
|
+
}
|
|
628
|
+
else if (realRemainder === '') {
|
|
629
|
+
scratch.targetNormalPath = canonicalToParent;
|
|
630
|
+
scratch.fromIdx = canonicalToParent.length;
|
|
631
|
+
scratch.unseenPathFromIdx = canonicalToParent.length;
|
|
632
|
+
}
|
|
633
|
+
else {
|
|
634
|
+
scratch.targetNormalPath = canonicalToParent + path_1.default.sep + realRemainder;
|
|
635
|
+
scratch.fromIdx = canonicalToParent.length + 1;
|
|
636
|
+
scratch.unseenPathFromIdx = canonicalToParent.length + 1;
|
|
637
|
+
}
|
|
638
|
+
return undefined;
|
|
639
|
+
}
|
|
640
|
+
#walkLookup(startNode, startPathIdx, startAncestorOfRootIdx, requestedNormalPath, onSegment, collectLinkPaths, initialFollows) {
|
|
641
|
+
// Cycle counter as a local — faster than an instance-field read in
|
|
642
|
+
// the per-segment loop. Recursive sub-walk inherits via `initialFollows`.
|
|
474
643
|
let targetNormalPath = requestedNormalPath;
|
|
475
|
-
|
|
476
|
-
let seen;
|
|
477
|
-
// Set when a symlink is followed, to allow fallback population outside
|
|
478
|
-
// the boundary for paths reachable transitively through symlinks.
|
|
479
|
-
let followedSymlink = false;
|
|
644
|
+
let followedSymlinks = initialFollows;
|
|
480
645
|
let fromIdx = startPathIdx;
|
|
481
646
|
let parentNode = startNode;
|
|
482
647
|
let ancestorOfRootIdx = startAncestorOfRootIdx;
|
|
@@ -508,7 +673,7 @@ class TreeFS {
|
|
|
508
673
|
? fromIdx - segmentName.length - 1
|
|
509
674
|
: fromIdx - segmentName.length - 2;
|
|
510
675
|
const parentCanonicalPath = parentEnd > 0 ? targetNormalPath.slice(0, parentEnd) : '';
|
|
511
|
-
segmentNode = this.#populateFromFilesystem(parentNode, segmentName, parentCanonicalPath,
|
|
676
|
+
segmentNode = this.#populateFromFilesystem(parentNode, segmentName, parentCanonicalPath, followedSymlinks > 0);
|
|
512
677
|
if (segmentNode != null) {
|
|
513
678
|
ancestorOfRootIdx = undefined;
|
|
514
679
|
}
|
|
@@ -567,87 +732,17 @@ class TreeFS {
|
|
|
567
732
|
missingSegmentName: segmentName,
|
|
568
733
|
};
|
|
569
734
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
return {
|
|
574
|
-
canonicalMissingPath: currentPath,
|
|
575
|
-
exists: false,
|
|
576
|
-
missingSegmentName: segmentName,
|
|
577
|
-
};
|
|
578
|
-
}
|
|
579
|
-
if (collectLinkPaths != null) {
|
|
580
|
-
collectLinkPaths.add(this.#pathUtils.normalToAbsolute(currentPath));
|
|
581
|
-
}
|
|
582
|
-
const remainingTargetPath = isLastSegment ? '' : targetNormalPath.slice(fromIdx);
|
|
583
|
-
// Append any subsequent path segments to the symlink target, and reset
|
|
584
|
-
// with our new target.
|
|
585
|
-
const joinedResult = this.#pathUtils.joinNormalToRelative(normalSymlinkTarget, remainingTargetPath);
|
|
586
|
-
targetNormalPath = joinedResult.normalPath;
|
|
587
|
-
// Two special cases (covered by unit tests):
|
|
588
|
-
//
|
|
589
|
-
// If the symlink target is the root, the root should be counted as an
|
|
590
|
-
// ancestor. We'd otherwise miss it because new ancestors are only
|
|
591
|
-
// streamed when entering a directory.
|
|
592
|
-
//
|
|
593
|
-
// If the symlink target is an ancestor of the root *and* joining it
|
|
594
|
-
// with the remaining path results in collapsing segments, e.g:
|
|
595
|
-
// '../..' + 'parentofroot/root/foo.js' = 'foo.js', then we must yield
|
|
596
|
-
// parentofroot and root as ancestors.
|
|
597
|
-
if (onSegment != null &&
|
|
598
|
-
!isLastSegment &&
|
|
599
|
-
// No-op optimisation to bail out the common case of nothing to do.
|
|
600
|
-
((ancestorOfRootIdx =
|
|
601
|
-
this.#pathUtils.getAncestorOfRootIdx(normalSymlinkTarget) ?? undefined) === 0 ||
|
|
602
|
-
joinedResult.collapsedSegments > 0)) {
|
|
603
|
-
let node = this.#rootNode;
|
|
604
|
-
let collapsedPath = '';
|
|
605
|
-
const reverseAncestors = [];
|
|
606
|
-
for (let i = 0; i <= joinedResult.collapsedSegments && isDirectory(node); i++) {
|
|
607
|
-
if (
|
|
608
|
-
// Add the root only if the target is the root or we have
|
|
609
|
-
// collapsed segments.
|
|
610
|
-
i > 0 ||
|
|
611
|
-
ancestorOfRootIdx === 0 ||
|
|
612
|
-
joinedResult.collapsedSegments > 0) {
|
|
613
|
-
reverseAncestors.push({
|
|
614
|
-
ancestorOfRootIdx: i,
|
|
615
|
-
node,
|
|
616
|
-
normalPath: collapsedPath,
|
|
617
|
-
segmentName: this.#pathUtils.getBasenameOfNthAncestor(i),
|
|
618
|
-
});
|
|
619
|
-
}
|
|
620
|
-
node = node.get('..') ?? new Map();
|
|
621
|
-
collapsedPath = collapsedPath === '' ? '..' : collapsedPath + path_1.default.sep + '..';
|
|
622
|
-
}
|
|
623
|
-
// Emit in shallowest-first order, matching today's
|
|
624
|
-
// collectAncestors.push(...reverseAncestors.reverse()).
|
|
625
|
-
for (let i = reverseAncestors.length - 1; i >= 0; i--) {
|
|
626
|
-
const a = reverseAncestors[i];
|
|
627
|
-
onSegment(a.node, a.normalPath, a.segmentName, a.ancestorOfRootIdx);
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
// For the purpose of streaming ancestors: Ignore the traversal to the
|
|
631
|
-
// symlink target, and start yielding ancestors only from the target
|
|
632
|
-
// itself (i.e. the basename of the normal target path) onwards.
|
|
633
|
-
unseenPathFromIdx = normalSymlinkTarget.lastIndexOf(path_1.default.sep) + 1;
|
|
634
|
-
if (seen == null) {
|
|
635
|
-
// Optimisation: set this lazily only when we've encountered a symlink
|
|
636
|
-
seen = new Set([requestedNormalPath]);
|
|
735
|
+
const followResult = this.#followSymlink(segmentNode, currentPath, segmentName, isLastSegment ? '' : targetNormalPath.slice(fromIdx), followedSymlinks, onSegment, collectLinkPaths);
|
|
736
|
+
if (followResult !== undefined) {
|
|
737
|
+
return followResult;
|
|
637
738
|
}
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
}
|
|
646
|
-
seen.add(targetNormalPath);
|
|
647
|
-
followedSymlink = true;
|
|
648
|
-
fromIdx = 0;
|
|
649
|
-
parentNode = this.#rootNode;
|
|
650
|
-
ancestorOfRootIdx = 0;
|
|
739
|
+
const scratch = this.#followScratch;
|
|
740
|
+
parentNode = scratch.parentNode;
|
|
741
|
+
ancestorOfRootIdx = scratch.ancestorOfRootIdx;
|
|
742
|
+
targetNormalPath = scratch.targetNormalPath;
|
|
743
|
+
fromIdx = scratch.fromIdx;
|
|
744
|
+
unseenPathFromIdx = scratch.unseenPathFromIdx;
|
|
745
|
+
followedSymlinks = scratch.followedSymlinks;
|
|
651
746
|
}
|
|
652
747
|
}
|
|
653
748
|
(0, invariant_1.default)(parentNode === this.#rootNode, 'Unexpectedly escaped traversal');
|
|
@@ -668,8 +763,7 @@ class TreeFS {
|
|
|
668
763
|
*/
|
|
669
764
|
#walkLookupNoFollow(startNode, startPathIdx, startAncestorOfRootIdx, requestedNormalPath, onSegment, skipFallback) {
|
|
670
765
|
let targetNormalPath = requestedNormalPath;
|
|
671
|
-
let
|
|
672
|
-
let followedSymlink = false;
|
|
766
|
+
let followedSymlinks = 0;
|
|
673
767
|
let fromIdx = startPathIdx;
|
|
674
768
|
let parentNode = startNode;
|
|
675
769
|
let ancestorOfRootIdx = startAncestorOfRootIdx;
|
|
@@ -699,7 +793,7 @@ class TreeFS {
|
|
|
699
793
|
? fromIdx - segmentName.length - 1
|
|
700
794
|
: fromIdx - segmentName.length - 2;
|
|
701
795
|
const parentCanonicalPath = parentEnd > 0 ? targetNormalPath.slice(0, parentEnd) : '';
|
|
702
|
-
segmentNode = this.#populateFromFilesystem(parentNode, segmentName, parentCanonicalPath,
|
|
796
|
+
segmentNode = this.#populateFromFilesystem(parentNode, segmentName, parentCanonicalPath, followedSymlinks > 0);
|
|
703
797
|
if (segmentNode != null) {
|
|
704
798
|
ancestorOfRootIdx = undefined;
|
|
705
799
|
}
|
|
@@ -750,59 +844,17 @@ class TreeFS {
|
|
|
750
844
|
missingSegmentName: segmentName,
|
|
751
845
|
};
|
|
752
846
|
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
if (normalSymlinkTarget == null) {
|
|
757
|
-
return {
|
|
758
|
-
canonicalMissingPath: currentPath,
|
|
759
|
-
exists: false,
|
|
760
|
-
missingSegmentName: segmentName,
|
|
761
|
-
};
|
|
847
|
+
const followResult = this.#followSymlink(segmentNode, currentPath, segmentName, targetNormalPath.slice(fromIdx), followedSymlinks, onSegment, undefined);
|
|
848
|
+
if (followResult !== undefined) {
|
|
849
|
+
return followResult;
|
|
762
850
|
}
|
|
763
|
-
const
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
let node = this.#rootNode;
|
|
771
|
-
let collapsedPath = '';
|
|
772
|
-
const reverseAncestors = [];
|
|
773
|
-
for (let i = 0; i <= joinedResult.collapsedSegments && isDirectory(node); i++) {
|
|
774
|
-
if (i > 0 || ancestorOfRootIdx === 0 || joinedResult.collapsedSegments > 0) {
|
|
775
|
-
reverseAncestors.push({
|
|
776
|
-
ancestorOfRootIdx: i,
|
|
777
|
-
node,
|
|
778
|
-
normalPath: collapsedPath,
|
|
779
|
-
segmentName: this.#pathUtils.getBasenameOfNthAncestor(i),
|
|
780
|
-
});
|
|
781
|
-
}
|
|
782
|
-
node = node.get('..') ?? new Map();
|
|
783
|
-
collapsedPath = collapsedPath === '' ? '..' : collapsedPath + path_1.default.sep + '..';
|
|
784
|
-
}
|
|
785
|
-
for (let i = reverseAncestors.length - 1; i >= 0; i--) {
|
|
786
|
-
const a = reverseAncestors[i];
|
|
787
|
-
onSegment(a.node, a.normalPath, a.segmentName, a.ancestorOfRootIdx);
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
unseenPathFromIdx = normalSymlinkTarget.lastIndexOf(path_1.default.sep) + 1;
|
|
791
|
-
if (seen == null) {
|
|
792
|
-
seen = new Set([requestedNormalPath]);
|
|
793
|
-
}
|
|
794
|
-
if (seen.has(targetNormalPath)) {
|
|
795
|
-
return {
|
|
796
|
-
canonicalMissingPath: targetNormalPath,
|
|
797
|
-
exists: false,
|
|
798
|
-
missingSegmentName: segmentName,
|
|
799
|
-
};
|
|
800
|
-
}
|
|
801
|
-
seen.add(targetNormalPath);
|
|
802
|
-
followedSymlink = true;
|
|
803
|
-
fromIdx = 0;
|
|
804
|
-
parentNode = this.#rootNode;
|
|
805
|
-
ancestorOfRootIdx = 0;
|
|
851
|
+
const scratch = this.#followScratch;
|
|
852
|
+
parentNode = scratch.parentNode;
|
|
853
|
+
ancestorOfRootIdx = scratch.ancestorOfRootIdx;
|
|
854
|
+
targetNormalPath = scratch.targetNormalPath;
|
|
855
|
+
fromIdx = scratch.fromIdx;
|
|
856
|
+
unseenPathFromIdx = scratch.unseenPathFromIdx;
|
|
857
|
+
followedSymlinks = scratch.followedSymlinks;
|
|
806
858
|
}
|
|
807
859
|
}
|
|
808
860
|
(0, invariant_1.default)(parentNode === this.#rootNode, 'Unexpectedly escaped traversal');
|
|
@@ -823,7 +875,7 @@ class TreeFS {
|
|
|
823
875
|
*/
|
|
824
876
|
#walkAndMakeDirectories(startNode, startPathIdx, startAncestorOfRootIdx, requestedNormalPath, followLeaf, onSegment) {
|
|
825
877
|
let targetNormalPath = requestedNormalPath;
|
|
826
|
-
let
|
|
878
|
+
let followedSymlinks = 0;
|
|
827
879
|
let fromIdx = startPathIdx;
|
|
828
880
|
let parentNode = startNode;
|
|
829
881
|
let ancestorOfRootIdx = startAncestorOfRootIdx;
|
|
@@ -888,33 +940,17 @@ class TreeFS {
|
|
|
888
940
|
missingSegmentName: segmentName,
|
|
889
941
|
};
|
|
890
942
|
}
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
return {
|
|
895
|
-
canonicalMissingPath: currentPath,
|
|
896
|
-
exists: false,
|
|
897
|
-
missingSegmentName: segmentName,
|
|
898
|
-
};
|
|
899
|
-
}
|
|
900
|
-
const remainingTargetPath = isLastSegment ? '' : targetNormalPath.slice(fromIdx);
|
|
901
|
-
const joinedResult = this.#pathUtils.joinNormalToRelative(normalSymlinkTarget, remainingTargetPath);
|
|
902
|
-
targetNormalPath = joinedResult.normalPath;
|
|
903
|
-
unseenPathFromIdx = normalSymlinkTarget.lastIndexOf(path_1.default.sep) + 1;
|
|
904
|
-
if (seen == null) {
|
|
905
|
-
seen = new Set([requestedNormalPath]);
|
|
943
|
+
const followResult = this.#followSymlink(segmentNode, currentPath, segmentName, isLastSegment ? '' : targetNormalPath.slice(fromIdx), followedSymlinks, undefined, undefined);
|
|
944
|
+
if (followResult !== undefined) {
|
|
945
|
+
return followResult;
|
|
906
946
|
}
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
seen.add(targetNormalPath);
|
|
915
|
-
fromIdx = 0;
|
|
916
|
-
parentNode = this.#rootNode;
|
|
917
|
-
ancestorOfRootIdx = 0;
|
|
947
|
+
const scratch = this.#followScratch;
|
|
948
|
+
parentNode = scratch.parentNode;
|
|
949
|
+
ancestorOfRootIdx = scratch.ancestorOfRootIdx;
|
|
950
|
+
targetNormalPath = scratch.targetNormalPath;
|
|
951
|
+
fromIdx = scratch.fromIdx;
|
|
952
|
+
unseenPathFromIdx = scratch.unseenPathFromIdx;
|
|
953
|
+
followedSymlinks = scratch.followedSymlinks;
|
|
918
954
|
}
|
|
919
955
|
}
|
|
920
956
|
(0, invariant_1.default)(parentNode === this.#rootNode, 'Unexpectedly escaped traversal');
|
|
@@ -926,18 +962,18 @@ class TreeFS {
|
|
|
926
962
|
parentNode: undefined,
|
|
927
963
|
};
|
|
928
964
|
}
|
|
929
|
-
// Convenience wrappers
|
|
965
|
+
// Convenience wrappers. Top-level entries pass `0` for `initialFollows`.
|
|
930
966
|
#lookup(normalPath, collectLinkPaths) {
|
|
931
|
-
return this.#walkLookup(this.#rootNode, 0, 0, normalPath, undefined, collectLinkPaths);
|
|
967
|
+
return this.#walkLookup(this.#rootNode, 0, 0, normalPath, undefined, collectLinkPaths, 0);
|
|
932
968
|
}
|
|
933
969
|
#lookupNoFollow(normalPath) {
|
|
934
970
|
return this.#walkLookupNoFollow(this.#rootNode, 0, 0, normalPath, undefined, false);
|
|
935
971
|
}
|
|
936
972
|
#lookupFromNode(startNode, startPathIdx, startAncestorOfRootIdx, target, collectLinkPaths) {
|
|
937
|
-
return this.#walkLookup(startNode, startPathIdx, startAncestorOfRootIdx, target, undefined, collectLinkPaths);
|
|
973
|
+
return this.#walkLookup(startNode, startPathIdx, startAncestorOfRootIdx, target, undefined, collectLinkPaths, 0);
|
|
938
974
|
}
|
|
939
975
|
#walkAndStream(normalPath, onSegment, collectLinkPaths) {
|
|
940
|
-
return this.#walkLookup(this.#rootNode, 0, 0, normalPath, onSegment, collectLinkPaths);
|
|
976
|
+
return this.#walkLookup(this.#rootNode, 0, 0, normalPath, onSegment, collectLinkPaths, 0);
|
|
941
977
|
}
|
|
942
978
|
/**
|
|
943
979
|
* Given a start path (which need not exist), a subpath and type, and
|
|
@@ -963,18 +999,11 @@ class TreeFS {
|
|
|
963
999
|
* (subpath: node_modules/pkg, type: d) in Node.js resolution.
|
|
964
1000
|
*/
|
|
965
1001
|
hierarchicalLookup(mixedStartPath, subpath, opts) {
|
|
966
|
-
const ancestorsOfInput =
|
|
1002
|
+
const ancestorsOfInput = this.#hierAncestorsBuf;
|
|
1003
|
+
ancestorsOfInput.length = 0;
|
|
967
1004
|
const normalPath = this.#normalizePath(mixedStartPath);
|
|
968
1005
|
const invalidatedBy = opts.invalidatedBy ?? undefined;
|
|
969
|
-
const
|
|
970
|
-
ancestorsOfInput.push({
|
|
971
|
-
ancestorOfRootIdx,
|
|
972
|
-
node,
|
|
973
|
-
normalPath: normalPathOfDir,
|
|
974
|
-
segmentName,
|
|
975
|
-
});
|
|
976
|
-
};
|
|
977
|
-
const closestLookup = this.#walkAndStream(normalPath, onSegment, invalidatedBy);
|
|
1006
|
+
const closestLookup = this.#walkAndStream(normalPath, this.#pushHierAncestor, invalidatedBy);
|
|
978
1007
|
if (closestLookup.exists && isDirectory(closestLookup.node)) {
|
|
979
1008
|
const maybeAbsolutePathMatch = this.#checkCandidateHasSubpath(closestLookup.canonicalPath, subpath, opts.subpathType, invalidatedBy, {
|
|
980
1009
|
ancestorOfRootIdx: closestLookup.ancestorOfRootIdx,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function isWatcherExcluded(filePath: string): boolean;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = isWatcherExcluded;
|
|
4
|
+
const EXCLUDED_DIR_SEGMENT = /(?:^|[/\\])\.(?:git|hg|cxx)[/\\]/;
|
|
5
|
+
function isWatcherExcluded(filePath) {
|
|
6
|
+
return EXCLUDED_DIR_SEGMENT.test(filePath);
|
|
7
|
+
}
|
|
@@ -45,7 +45,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
45
45
|
exports.AbstractWatcher = void 0;
|
|
46
46
|
const events_1 = __importDefault(require("events"));
|
|
47
47
|
const path = __importStar(require("path"));
|
|
48
|
-
const
|
|
48
|
+
const isWatcherExcluded_1 = __importDefault(require("../lib/isWatcherExcluded"));
|
|
49
49
|
const common_1 = require("./common");
|
|
50
50
|
class AbstractWatcher {
|
|
51
51
|
root;
|
|
@@ -60,8 +60,8 @@ class AbstractWatcher {
|
|
|
60
60
|
this.ignored = ignored;
|
|
61
61
|
this.globs = globs;
|
|
62
62
|
this.doIgnore = ignored
|
|
63
|
-
? (filePath) => (0,
|
|
64
|
-
:
|
|
63
|
+
? (filePath) => (0, isWatcherExcluded_1.default)(filePath) || (0, common_1.posixPathMatchesPattern)(ignored, filePath)
|
|
64
|
+
: isWatcherExcluded_1.default;
|
|
65
65
|
this.root = path.resolve(dir);
|
|
66
66
|
}
|
|
67
67
|
onFileEvent(listener) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expo/metro-file-map",
|
|
3
|
-
"version": "56.0.
|
|
3
|
+
"version": "56.0.3",
|
|
4
4
|
"description": "A metro-file-map fork for Expo used with the Metro bundler",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"publishConfig": {
|
|
43
43
|
"access": "public"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "f26be3dd9396bf7c399a1d607865d0fabdbc0d64",
|
|
46
46
|
"scripts": {
|
|
47
47
|
"build": "expo-module tsc",
|
|
48
48
|
"clean": "expo-module clean",
|
package/build/lib/isVcsPath.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default function isVcsPath(filePath: string): boolean;
|
package/build/lib/isVcsPath.js
DELETED