@parcel/utils 2.0.0-beta.1 → 2.0.0-nightly.1002
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/.eslintrc.js +6 -6
- package/lib/index.js +35850 -337
- package/lib/index.js.map +1 -0
- package/package.json +42 -20
- package/src/DefaultMap.js +1 -1
- package/src/PromiseQueue.js +16 -12
- package/src/alternatives.js +143 -0
- package/src/ansi-html.js +2 -2
- package/src/blob.js +2 -1
- package/src/bundle-url.js +1 -1
- package/src/collection.js +14 -14
- package/src/config.js +93 -53
- package/src/countLines.js +5 -2
- package/src/debounce.js +1 -1
- package/src/dependency-location.js +11 -6
- package/src/generateBuildMetrics.js +5 -5
- package/src/generateCertificate.js +1 -1
- package/src/getCertificate.js +1 -1
- package/src/getExisting.js +1 -4
- package/src/getRootDir.js +1 -2
- package/src/glob.js +36 -5
- package/src/hash.js +34 -0
- package/src/http-server.js +4 -11
- package/src/index.js +47 -20
- package/src/is-url.js +1 -1
- package/src/isDirectoryInside.js +4 -1
- package/src/openInBrowser.js +3 -1
- package/src/path.js +17 -2
- package/src/prettyDiagnostic.js +39 -27
- package/src/relativeBundlePath.js +5 -7
- package/src/replaceBundleReferences.js +50 -34
- package/src/schema.js +96 -42
- package/src/shared-buffer.js +24 -0
- package/src/sourcemap.js +84 -10
- package/src/urlJoin.js +3 -1
- package/test/DefaultMap.test.js +7 -4
- package/test/config.test.js +50 -0
- package/test/input/config/config.json +3 -0
- package/test/input/config/empty.json +0 -0
- package/test/input/config/empty.toml +0 -0
- package/test/input/sourcemap/referenced-min.js +1 -1
- package/test/replaceBundleReferences.test.js +268 -0
- package/test/sourcemap.test.js +5 -9
- package/test/throttle.test.js +1 -2
- package/test/urlJoin.test.js +37 -0
- package/lib/DefaultMap.js +0 -64
- package/lib/Deferred.js +0 -26
- package/lib/PromiseQueue.js +0 -133
- package/lib/TapStream.js +0 -38
- package/lib/ansi-html.js +0 -16
- package/lib/blob.js +0 -31
- package/lib/bundle-url.js +0 -43
- package/lib/collection.js +0 -62
- package/lib/config.js +0 -109
- package/lib/countLines.js +0 -18
- package/lib/debounce.js +0 -20
- package/lib/dependency-location.js +0 -21
- package/lib/escape-html.js +0 -24
- package/lib/escape-markdown.js +0 -15
- package/lib/generateBuildMetrics.js +0 -124
- package/lib/generateCertificate.js +0 -124
- package/lib/getCertificate.js +0 -19
- package/lib/getExisting.js +0 -23
- package/lib/getRootDir.js +0 -55
- package/lib/glob.js +0 -69
- package/lib/http-server.js +0 -81
- package/lib/is-url.js +0 -17
- package/lib/isDirectoryInside.js +0 -16
- package/lib/md5.js +0 -40
- package/lib/objectHash.js +0 -26
- package/lib/openInBrowser.js +0 -70
- package/lib/parseCSSImport.js +0 -16
- package/lib/path.js +0 -30
- package/lib/prettifyTime.js +0 -10
- package/lib/prettyDiagnostic.js +0 -75
- package/lib/promisify.js +0 -13
- package/lib/relativeBundlePath.js +0 -18
- package/lib/relativeUrl.js +0 -16
- package/lib/replaceBundleReferences.js +0 -166
- package/lib/resolve.js +0 -108
- package/lib/schema.js +0 -321
- package/lib/serializeObject.js +0 -28
- package/lib/sourcemap.js +0 -58
- package/lib/stream.js +0 -78
- package/lib/throttle.js +0 -16
- package/lib/urlJoin.js +0 -27
- package/src/.babelrc +0 -3
- package/src/escape-markdown.js +0 -10
- package/src/md5.js +0 -49
- package/src/promisify.js +0 -13
- package/src/resolve.js +0 -216
- package/src/serializeObject.js +0 -22
- package/test/escapeMarkdown.test.js +0 -29
package/package.json
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parcel/utils",
|
|
3
|
-
"version": "2.0.0-
|
|
3
|
+
"version": "2.0.0-nightly.1002+5530a6ef",
|
|
4
4
|
"description": "Blazing fast, zero configuration web application bundler",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
9
|
+
"funding": {
|
|
10
|
+
"type": "opencollective",
|
|
11
|
+
"url": "https://opencollective.com/parcel"
|
|
12
|
+
},
|
|
9
13
|
"repository": {
|
|
10
14
|
"type": "git",
|
|
11
15
|
"url": "https://github.com/parcel-bundler/parcel.git"
|
|
@@ -13,34 +17,52 @@
|
|
|
13
17
|
"main": "lib/index.js",
|
|
14
18
|
"source": "src/index.js",
|
|
15
19
|
"engines": {
|
|
16
|
-
"node": ">=
|
|
20
|
+
"node": ">= 12.0.0"
|
|
21
|
+
},
|
|
22
|
+
"targets": {
|
|
23
|
+
"main": {
|
|
24
|
+
"includeNodeModules": {
|
|
25
|
+
"@parcel/codeframe": false,
|
|
26
|
+
"@parcel/diagnostic": false,
|
|
27
|
+
"@parcel/hash": false,
|
|
28
|
+
"@parcel/logger": false,
|
|
29
|
+
"@parcel/markdown-ansi": false,
|
|
30
|
+
"@parcel/source-map": false,
|
|
31
|
+
"chalk": false
|
|
32
|
+
}
|
|
33
|
+
}
|
|
17
34
|
},
|
|
18
35
|
"dependencies": {
|
|
36
|
+
"@parcel/codeframe": "2.0.0-nightly.1002+5530a6ef",
|
|
37
|
+
"@parcel/diagnostic": "2.0.0-nightly.1002+5530a6ef",
|
|
38
|
+
"@parcel/hash": "2.3.2-nightly.2625+5530a6ef",
|
|
39
|
+
"@parcel/logger": "2.0.0-nightly.1002+5530a6ef",
|
|
40
|
+
"@parcel/markdown-ansi": "2.0.0-nightly.1002+5530a6ef",
|
|
41
|
+
"@parcel/source-map": "^2.0.0",
|
|
42
|
+
"chalk": "^4.1.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@babel/plugin-transform-flow-strip-types": "^7.2.0",
|
|
19
46
|
"@iarna/toml": "^2.2.0",
|
|
20
|
-
"
|
|
21
|
-
"@parcel/diagnostic": "2.0.0-beta.1",
|
|
22
|
-
"@parcel/logger": "2.0.0-beta.1",
|
|
23
|
-
"@parcel/markdown-ansi": "2.0.0-beta.1",
|
|
24
|
-
"@parcel/source-map": "2.0.0-alpha.4.13",
|
|
25
|
-
"ansi-html": "^0.0.7",
|
|
26
|
-
"chalk": "^2.4.2",
|
|
47
|
+
"ansi-html-community": "0.0.8",
|
|
27
48
|
"clone": "^2.1.1",
|
|
28
49
|
"fast-glob": "3.1.1",
|
|
50
|
+
"fastest-levenshtein": "^1.0.8",
|
|
29
51
|
"is-glob": "^4.0.0",
|
|
30
52
|
"is-url": "^1.2.2",
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"micromatch": "^4.0.
|
|
34
|
-
"node-forge": "^
|
|
53
|
+
"json5": "^2.2.0",
|
|
54
|
+
"lru-cache": "^6.0.0",
|
|
55
|
+
"micromatch": "^4.0.4",
|
|
56
|
+
"node-forge": "^1.2.1",
|
|
35
57
|
"nullthrows": "^1.1.1",
|
|
36
58
|
"open": "^7.0.3",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"terser": "^3.7.3"
|
|
59
|
+
"random-int": "^1.0.0",
|
|
60
|
+
"terminal-link": "^2.1.1"
|
|
40
61
|
},
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
62
|
+
"browser": {
|
|
63
|
+
"./src/generateCertificate.js": false,
|
|
64
|
+
"./src/http-server.js": false,
|
|
65
|
+
"./src/openInBrowser.js": false
|
|
44
66
|
},
|
|
45
|
-
"gitHead": "
|
|
67
|
+
"gitHead": "5530a6eff8b619873353baeb0457ae4ec591e9fa"
|
|
46
68
|
}
|
package/src/DefaultMap.js
CHANGED
|
@@ -24,7 +24,7 @@ export class DefaultMap<K, V> extends Map<K, V> {
|
|
|
24
24
|
|
|
25
25
|
// Duplicated from DefaultMap implementation for Flow
|
|
26
26
|
// Roughly mirrors https://github.com/facebook/flow/blob/2eb5a78d92c167117ba9caae070afd2b9f598599/lib/core.js#L617
|
|
27
|
-
export class DefaultWeakMap<K: {
|
|
27
|
+
export class DefaultWeakMap<K: interface {}, V> extends WeakMap<K, V> {
|
|
28
28
|
_getDefault: K => V;
|
|
29
29
|
|
|
30
30
|
constructor(getDefault: K => V, entries?: Iterable<[K, V]>) {
|
package/src/PromiseQueue.js
CHANGED
|
@@ -10,6 +10,7 @@ export default class PromiseQueue<T> {
|
|
|
10
10
|
_numRunning: number = 0;
|
|
11
11
|
_queue: Array<() => Promise<void>> = [];
|
|
12
12
|
_runPromise: ?Promise<Array<T>> = null;
|
|
13
|
+
_error: mixed;
|
|
13
14
|
_count: number = 0;
|
|
14
15
|
_results: Array<T> = [];
|
|
15
16
|
|
|
@@ -74,7 +75,7 @@ export default class PromiseQueue<T> {
|
|
|
74
75
|
if (this._queue.length) {
|
|
75
76
|
this._next();
|
|
76
77
|
} else if (this._numRunning === 0) {
|
|
77
|
-
this.
|
|
78
|
+
this._done();
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
81
|
|
|
@@ -82,10 +83,15 @@ export default class PromiseQueue<T> {
|
|
|
82
83
|
this._numRunning++;
|
|
83
84
|
try {
|
|
84
85
|
await fn();
|
|
85
|
-
this._numRunning--;
|
|
86
86
|
} catch (e) {
|
|
87
|
-
|
|
88
|
-
//
|
|
87
|
+
// Only store the first error that occurs.
|
|
88
|
+
// We don't reject immediately so that any other concurrent
|
|
89
|
+
// requests have time to complete.
|
|
90
|
+
if (this._error == null) {
|
|
91
|
+
this._error = e;
|
|
92
|
+
}
|
|
93
|
+
} finally {
|
|
94
|
+
this._numRunning--;
|
|
89
95
|
}
|
|
90
96
|
}
|
|
91
97
|
|
|
@@ -98,17 +104,15 @@ export default class PromiseQueue<T> {
|
|
|
98
104
|
this._deferred = null;
|
|
99
105
|
}
|
|
100
106
|
|
|
101
|
-
|
|
107
|
+
_done(): void {
|
|
102
108
|
if (this._deferred != null) {
|
|
103
|
-
this.
|
|
109
|
+
if (this._error != null) {
|
|
110
|
+
this._deferred.reject(this._error);
|
|
111
|
+
} else {
|
|
112
|
+
this._deferred.resolve(this._results);
|
|
113
|
+
}
|
|
104
114
|
}
|
|
105
|
-
this._resetState();
|
|
106
|
-
}
|
|
107
115
|
|
|
108
|
-
_resolve(): void {
|
|
109
|
-
if (this._deferred != null) {
|
|
110
|
-
this._deferred.resolve(this._results);
|
|
111
|
-
}
|
|
112
116
|
this._resetState();
|
|
113
117
|
}
|
|
114
118
|
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import type {FileSystem} from '@parcel/fs';
|
|
4
|
+
import {fuzzySearch} from './schema';
|
|
5
|
+
import {relativePath} from './path';
|
|
6
|
+
import {resolveConfig} from './config';
|
|
7
|
+
|
|
8
|
+
export async function findAlternativeNodeModules(
|
|
9
|
+
fs: FileSystem,
|
|
10
|
+
moduleName: string,
|
|
11
|
+
dir: string,
|
|
12
|
+
): Promise<Array<string>> {
|
|
13
|
+
let potentialModules: Array<string> = [];
|
|
14
|
+
let root = path.parse(dir).root;
|
|
15
|
+
let isOrganisationModule = moduleName.startsWith('@');
|
|
16
|
+
|
|
17
|
+
while (dir !== root) {
|
|
18
|
+
// Skip node_modules directories
|
|
19
|
+
if (path.basename(dir) === 'node_modules') {
|
|
20
|
+
dir = path.dirname(dir);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
let modulesDir = path.join(dir, 'node_modules');
|
|
25
|
+
let stats = await fs.stat(modulesDir);
|
|
26
|
+
if (stats.isDirectory()) {
|
|
27
|
+
let dirContent = (await fs.readdir(modulesDir)).sort();
|
|
28
|
+
|
|
29
|
+
// Filter out the modules that interest us
|
|
30
|
+
let modules = dirContent.filter(i =>
|
|
31
|
+
isOrganisationModule ? i.startsWith('@') : !i.startsWith('@'),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
// If it's an organisation module, loop through all the modules of that organisation
|
|
35
|
+
if (isOrganisationModule) {
|
|
36
|
+
await Promise.all(
|
|
37
|
+
modules.map(async item => {
|
|
38
|
+
let orgDirPath = path.join(modulesDir, item);
|
|
39
|
+
let orgDirContent = (await fs.readdir(orgDirPath)).sort();
|
|
40
|
+
|
|
41
|
+
// Add all org packages
|
|
42
|
+
potentialModules.push(...orgDirContent.map(i => `${item}/${i}`));
|
|
43
|
+
}),
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
} catch (err) {
|
|
48
|
+
// ignore
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Move up a directory
|
|
52
|
+
dir = path.dirname(dir);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return fuzzySearch(potentialModules.sort(), moduleName).slice(0, 2);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function findAllFilesUp({
|
|
59
|
+
fs,
|
|
60
|
+
dir,
|
|
61
|
+
root,
|
|
62
|
+
basedir,
|
|
63
|
+
maxlength,
|
|
64
|
+
collected,
|
|
65
|
+
leadingDotSlash = true,
|
|
66
|
+
includeDirectories = true,
|
|
67
|
+
}: {|
|
|
68
|
+
fs: FileSystem,
|
|
69
|
+
dir: string,
|
|
70
|
+
root: string,
|
|
71
|
+
basedir: string,
|
|
72
|
+
maxlength: number,
|
|
73
|
+
collected: Array<string>,
|
|
74
|
+
leadingDotSlash?: boolean,
|
|
75
|
+
includeDirectories?: boolean,
|
|
76
|
+
|}): Promise<mixed> {
|
|
77
|
+
let dirContent = (await fs.readdir(dir)).sort();
|
|
78
|
+
return Promise.all(
|
|
79
|
+
dirContent.map(async item => {
|
|
80
|
+
let fullPath = path.join(dir, item);
|
|
81
|
+
let relativeFilePath = relativePath(basedir, fullPath, leadingDotSlash);
|
|
82
|
+
if (relativeFilePath.length < maxlength) {
|
|
83
|
+
let stats = await fs.stat(fullPath);
|
|
84
|
+
let isDir = stats.isDirectory();
|
|
85
|
+
if ((isDir && includeDirectories) || stats.isFile()) {
|
|
86
|
+
collected.push(relativeFilePath);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// If it's a directory, run over each item within said directory...
|
|
90
|
+
if (isDir) {
|
|
91
|
+
return findAllFilesUp({
|
|
92
|
+
fs,
|
|
93
|
+
dir: fullPath,
|
|
94
|
+
root,
|
|
95
|
+
basedir,
|
|
96
|
+
maxlength,
|
|
97
|
+
collected,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}),
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export async function findAlternativeFiles(
|
|
106
|
+
fs: FileSystem,
|
|
107
|
+
fileSpecifier: string,
|
|
108
|
+
dir: string,
|
|
109
|
+
projectRoot: string,
|
|
110
|
+
leadingDotSlash?: boolean = true,
|
|
111
|
+
includeDirectories?: boolean = true,
|
|
112
|
+
includeExtension?: boolean = false,
|
|
113
|
+
): Promise<Array<string>> {
|
|
114
|
+
let potentialFiles: Array<string> = [];
|
|
115
|
+
// Find our root, we won't recommend files above the package root as that's bad practise
|
|
116
|
+
let pkg = await resolveConfig(
|
|
117
|
+
fs,
|
|
118
|
+
path.join(dir, 'index'),
|
|
119
|
+
['package.json'],
|
|
120
|
+
projectRoot,
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
let pkgRoot = pkg ? path.dirname(pkg) : projectRoot;
|
|
124
|
+
await findAllFilesUp({
|
|
125
|
+
fs,
|
|
126
|
+
dir: pkgRoot,
|
|
127
|
+
root: pkgRoot,
|
|
128
|
+
basedir: dir,
|
|
129
|
+
maxlength: fileSpecifier.length + 10,
|
|
130
|
+
collected: potentialFiles,
|
|
131
|
+
leadingDotSlash,
|
|
132
|
+
includeDirectories,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
if (path.extname(fileSpecifier) === '' && !includeExtension) {
|
|
136
|
+
potentialFiles = potentialFiles.map(p => {
|
|
137
|
+
let ext = path.extname(p);
|
|
138
|
+
return ext.length > 0 ? p.slice(0, -ext.length) : p;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return fuzzySearch(potentialFiles, fileSpecifier).slice(0, 2);
|
|
143
|
+
}
|
package/src/ansi-html.js
CHANGED
package/src/blob.js
CHANGED
package/src/bundle-url.js
CHANGED
package/src/collection.js
CHANGED
|
@@ -4,28 +4,16 @@ export function unique<T>(array: Array<T>): Array<T> {
|
|
|
4
4
|
return [...new Set(array)];
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
export function flatMap<T, U>(
|
|
8
|
-
array: Array<T>,
|
|
9
|
-
projectFn: (T, number, Array<T>) => Array<U>,
|
|
10
|
-
): Array<U> {
|
|
11
|
-
let out = [];
|
|
12
|
-
|
|
13
|
-
for (let arr of array.map(projectFn)) {
|
|
14
|
-
out.push(...arr);
|
|
15
|
-
}
|
|
16
|
-
return out;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
7
|
export function objectSortedEntries(obj: {
|
|
20
8
|
+[string]: mixed,
|
|
21
|
-
|
|
9
|
+
...
|
|
22
10
|
}): Array<[string, mixed]> {
|
|
23
11
|
return Object.entries(obj).sort(([keyA], [keyB]) => keyA.localeCompare(keyB));
|
|
24
12
|
}
|
|
25
13
|
|
|
26
14
|
export function objectSortedEntriesDeep(object: {
|
|
27
15
|
+[string]: mixed,
|
|
28
|
-
|
|
16
|
+
...
|
|
29
17
|
}): Array<[string, mixed]> {
|
|
30
18
|
let sortedEntries = objectSortedEntries(object);
|
|
31
19
|
for (let i = 0; i < sortedEntries.length; i++) {
|
|
@@ -55,3 +43,15 @@ export function setDifference<T>(a: Set<T>, b: Set<T>): Set<T> {
|
|
|
55
43
|
}
|
|
56
44
|
return difference;
|
|
57
45
|
}
|
|
46
|
+
|
|
47
|
+
export function setIntersect<T>(a: Set<T>, b: Set<T>): void {
|
|
48
|
+
for (let entry of a) {
|
|
49
|
+
if (!b.has(entry)) {
|
|
50
|
+
a.delete(entry);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function setUnion<T>(a: Iterable<T>, b: Iterable<T>): Set<T> {
|
|
56
|
+
return new Set([...a, ...b]);
|
|
57
|
+
}
|
package/src/config.js
CHANGED
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
import type {ConfigResult, File, FilePath} from '@parcel/types';
|
|
4
4
|
import type {FileSystem} from '@parcel/fs';
|
|
5
|
+
import ThrowableDiagnostic from '@parcel/diagnostic';
|
|
5
6
|
import path from 'path';
|
|
6
7
|
import clone from 'clone';
|
|
8
|
+
import json5 from 'json5';
|
|
9
|
+
import {parse as toml} from '@iarna/toml';
|
|
10
|
+
import LRU from 'lru-cache';
|
|
7
11
|
|
|
8
12
|
export type ConfigOutput = {|
|
|
9
13
|
config: ConfigResult,
|
|
@@ -12,100 +16,121 @@ export type ConfigOutput = {|
|
|
|
12
16
|
|
|
13
17
|
export type ConfigOptions = {|
|
|
14
18
|
parse?: boolean,
|
|
19
|
+
parser?: string => any,
|
|
15
20
|
|};
|
|
16
21
|
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
toml: require('@iarna/toml').parse,
|
|
20
|
-
};
|
|
22
|
+
const configCache = new LRU<FilePath, ConfigOutput>({max: 500});
|
|
23
|
+
const resolveCache = new Map();
|
|
21
24
|
|
|
22
|
-
export
|
|
25
|
+
export function resolveConfig(
|
|
23
26
|
fs: FileSystem,
|
|
24
27
|
filepath: FilePath,
|
|
25
28
|
filenames: Array<FilePath>,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (
|
|
33
|
-
return
|
|
29
|
+
projectRoot: FilePath,
|
|
30
|
+
): Promise<?FilePath> {
|
|
31
|
+
// Cache the result of resolving config for this directory.
|
|
32
|
+
// This is automatically invalidated at the end of the current build.
|
|
33
|
+
let key = path.dirname(filepath) + filenames.join(',');
|
|
34
|
+
let cached = resolveCache.get(key);
|
|
35
|
+
if (cached !== undefined) {
|
|
36
|
+
return Promise.resolve(cached);
|
|
34
37
|
}
|
|
35
38
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (filepath === root) {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return resolveConfig(fs, filepath, filenames, opts);
|
|
39
|
+
let resolved = fs.findAncestorFile(
|
|
40
|
+
filenames,
|
|
41
|
+
path.dirname(filepath),
|
|
42
|
+
projectRoot,
|
|
43
|
+
);
|
|
44
|
+
resolveCache.set(key, resolved);
|
|
45
|
+
return Promise.resolve(resolved);
|
|
48
46
|
}
|
|
49
47
|
|
|
50
48
|
export function resolveConfigSync(
|
|
51
49
|
fs: FileSystem,
|
|
52
50
|
filepath: FilePath,
|
|
53
51
|
filenames: Array<FilePath>,
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
filepath = fs.realpathSync(path.dirname(filepath));
|
|
58
|
-
|
|
59
|
-
// Don't traverse above the module root
|
|
60
|
-
if (filepath === root || path.basename(filepath) === 'node_modules') {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
for (const filename of filenames) {
|
|
65
|
-
let file = path.join(filepath, filename);
|
|
66
|
-
if (fs.existsSync(file) && fs.statSync(file).isFile()) {
|
|
67
|
-
return file;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return resolveConfigSync(fs, filepath, filenames, opts);
|
|
52
|
+
projectRoot: FilePath,
|
|
53
|
+
): ?FilePath {
|
|
54
|
+
return fs.findAncestorFile(filenames, path.dirname(filepath), projectRoot);
|
|
72
55
|
}
|
|
73
56
|
|
|
74
57
|
export async function loadConfig(
|
|
75
58
|
fs: FileSystem,
|
|
76
59
|
filepath: FilePath,
|
|
77
60
|
filenames: Array<FilePath>,
|
|
61
|
+
projectRoot: FilePath,
|
|
78
62
|
opts: ?ConfigOptions,
|
|
79
63
|
): Promise<ConfigOutput | null> {
|
|
80
|
-
let
|
|
64
|
+
let parse = opts?.parse ?? true;
|
|
65
|
+
let configFile = await resolveConfig(fs, filepath, filenames, projectRoot);
|
|
81
66
|
if (configFile) {
|
|
67
|
+
let cachedOutput = configCache.get(String(parse) + configFile);
|
|
68
|
+
if (cachedOutput) {
|
|
69
|
+
return cachedOutput;
|
|
70
|
+
}
|
|
71
|
+
|
|
82
72
|
try {
|
|
83
73
|
let extname = path.extname(configFile).slice(1);
|
|
84
74
|
if (extname === 'js') {
|
|
85
|
-
|
|
75
|
+
let output = {
|
|
86
76
|
// $FlowFixMe
|
|
87
77
|
config: clone(require(configFile)),
|
|
88
78
|
files: [{filePath: configFile}],
|
|
89
79
|
};
|
|
80
|
+
|
|
81
|
+
configCache.set(configFile, output);
|
|
82
|
+
return output;
|
|
90
83
|
}
|
|
91
84
|
|
|
92
85
|
let configContent = await fs.readFile(configFile, 'utf8');
|
|
93
|
-
if (!configContent) {
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
86
|
|
|
97
87
|
let config;
|
|
98
|
-
if (
|
|
88
|
+
if (parse === false) {
|
|
99
89
|
config = configContent;
|
|
100
90
|
} else {
|
|
101
|
-
let parse =
|
|
102
|
-
|
|
91
|
+
let parse = opts?.parser ?? getParser(extname);
|
|
92
|
+
try {
|
|
93
|
+
config = parse(configContent);
|
|
94
|
+
} catch (e) {
|
|
95
|
+
if (extname !== '' && extname !== 'json') {
|
|
96
|
+
throw e;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let pos = {
|
|
100
|
+
line: e.lineNumber,
|
|
101
|
+
column: e.columnNumber,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
throw new ThrowableDiagnostic({
|
|
105
|
+
diagnostic: {
|
|
106
|
+
message: `Failed to parse ${path.basename(configFile)}`,
|
|
107
|
+
origin: '@parcel/utils',
|
|
108
|
+
codeFrames: [
|
|
109
|
+
{
|
|
110
|
+
language: 'json5',
|
|
111
|
+
filePath: configFile,
|
|
112
|
+
code: configContent,
|
|
113
|
+
codeHighlights: [
|
|
114
|
+
{
|
|
115
|
+
start: pos,
|
|
116
|
+
end: pos,
|
|
117
|
+
message: e.message,
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
}
|
|
103
125
|
}
|
|
104
126
|
|
|
105
|
-
|
|
106
|
-
config
|
|
127
|
+
let output = {
|
|
128
|
+
config,
|
|
107
129
|
files: [{filePath: configFile}],
|
|
108
130
|
};
|
|
131
|
+
|
|
132
|
+
configCache.set(String(parse) + configFile, output);
|
|
133
|
+
return output;
|
|
109
134
|
} catch (err) {
|
|
110
135
|
if (err.code === 'MODULE_NOT_FOUND' || err.code === 'ENOENT') {
|
|
111
136
|
return null;
|
|
@@ -117,3 +142,18 @@ export async function loadConfig(
|
|
|
117
142
|
|
|
118
143
|
return null;
|
|
119
144
|
}
|
|
145
|
+
|
|
146
|
+
loadConfig.clear = () => {
|
|
147
|
+
configCache.reset();
|
|
148
|
+
resolveCache.clear();
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
function getParser(extname) {
|
|
152
|
+
switch (extname) {
|
|
153
|
+
case 'toml':
|
|
154
|
+
return toml;
|
|
155
|
+
case 'json':
|
|
156
|
+
default:
|
|
157
|
+
return json5.parse;
|
|
158
|
+
}
|
|
159
|
+
}
|
package/src/countLines.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
// @flow strict-local
|
|
2
2
|
|
|
3
|
-
export default function countLines(
|
|
3
|
+
export default function countLines(
|
|
4
|
+
string: string,
|
|
5
|
+
startIndex: number = 0,
|
|
6
|
+
): number {
|
|
4
7
|
let lines = 1;
|
|
5
|
-
for (let i =
|
|
8
|
+
for (let i = startIndex; i < string.length; i++) {
|
|
6
9
|
if (string.charAt(i) === '\n') {
|
|
7
10
|
lines++;
|
|
8
11
|
}
|
package/src/debounce.js
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
// @flow
|
|
2
|
+
|
|
2
3
|
export default function createDependencyLocation(
|
|
3
|
-
start: {
|
|
4
|
+
start: interface {
|
|
4
5
|
line: number,
|
|
5
6
|
column: number,
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
},
|
|
8
|
+
specifier: string,
|
|
8
9
|
lineOffset: number = 0,
|
|
9
10
|
columnOffset: number = 0,
|
|
10
11
|
// Imports are usually wrapped in quotes
|
|
11
12
|
importWrapperLength: number = 2,
|
|
12
|
-
) {
|
|
13
|
+
): {|
|
|
14
|
+
end: {|column: number, line: number|},
|
|
15
|
+
filePath: string,
|
|
16
|
+
start: {|column: number, line: number|},
|
|
17
|
+
|} {
|
|
13
18
|
return {
|
|
14
|
-
filePath:
|
|
19
|
+
filePath: specifier,
|
|
15
20
|
start: {
|
|
16
21
|
line: start.line + lineOffset,
|
|
17
22
|
column: start.column + columnOffset,
|
|
@@ -20,7 +25,7 @@ export default function createDependencyLocation(
|
|
|
20
25
|
line: start.line + lineOffset,
|
|
21
26
|
column:
|
|
22
27
|
start.column +
|
|
23
|
-
|
|
28
|
+
specifier.length -
|
|
24
29
|
1 +
|
|
25
30
|
importWrapperLength +
|
|
26
31
|
columnOffset,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
|
|
3
|
-
import type {FilePath,
|
|
3
|
+
import type {FilePath, PackagedBundle} from '@parcel/types';
|
|
4
4
|
import type {FileSystem} from '@parcel/fs';
|
|
5
5
|
import SourceMap from '@parcel/source-map';
|
|
6
6
|
import nullthrows from 'nullthrows';
|
|
@@ -37,8 +37,8 @@ async function getSourcemapSizes(
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
let rawMap = mapUrlData.map;
|
|
40
|
-
let sourceMap = new SourceMap();
|
|
41
|
-
sourceMap.
|
|
40
|
+
let sourceMap = new SourceMap(projectRoot);
|
|
41
|
+
sourceMap.addVLQMap(rawMap);
|
|
42
42
|
let parsedMapData = sourceMap.getMap();
|
|
43
43
|
|
|
44
44
|
if (parsedMapData.mappings.length > 2) {
|
|
@@ -97,7 +97,7 @@ async function getSourcemapSizes(
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
async function createBundleStats(
|
|
100
|
-
bundle:
|
|
100
|
+
bundle: PackagedBundle,
|
|
101
101
|
fs: FileSystem,
|
|
102
102
|
projectRoot: FilePath,
|
|
103
103
|
) {
|
|
@@ -144,7 +144,7 @@ async function createBundleStats(
|
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
export default async function generateBuildMetrics(
|
|
147
|
-
bundles: Array<
|
|
147
|
+
bundles: Array<PackagedBundle>,
|
|
148
148
|
fs: FileSystem,
|
|
149
149
|
projectRoot: FilePath,
|
|
150
150
|
): Promise<BuildMetrics> {
|