@atlaspack/core 2.12.1-canary.3354
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/LICENSE +201 -0
- package/index.d.ts +22 -0
- package/lib/AssetGraph.js +518 -0
- package/lib/Atlaspack.js +587 -0
- package/lib/AtlaspackConfig.js +298 -0
- package/lib/AtlaspackConfig.schema.js +125 -0
- package/lib/BundleGraph.js +1445 -0
- package/lib/CommittedAsset.js +133 -0
- package/lib/Dependency.js +88 -0
- package/lib/Environment.js +128 -0
- package/lib/InternalConfig.js +48 -0
- package/lib/PackagerRunner.js +519 -0
- package/lib/ReporterRunner.js +151 -0
- package/lib/RequestTracker.js +1089 -0
- package/lib/SymbolPropagation.js +625 -0
- package/lib/TargetDescriptor.schema.js +115 -0
- package/lib/Transformation.js +536 -0
- package/lib/UncommittedAsset.js +342 -0
- package/lib/Validation.js +215 -0
- package/lib/applyRuntimes.js +279 -0
- package/lib/assetUtils.js +189 -0
- package/lib/atlaspack-v3/AtlaspackV3.js +74 -0
- package/lib/atlaspack-v3/fs.js +30 -0
- package/lib/atlaspack-v3/index.js +19 -0
- package/lib/atlaspack-v3/jsCallable.js +15 -0
- package/lib/atlaspack-v3/plugins/Resolver.js +12 -0
- package/lib/atlaspack-v3/plugins/index.js +16 -0
- package/lib/atlaspack-v3/worker/index.js +3 -0
- package/lib/atlaspack-v3/worker/worker.js +30 -0
- package/lib/buildCache.js +18 -0
- package/lib/constants.js +21 -0
- package/lib/dumpGraphToGraphViz.js +206 -0
- package/lib/index.js +106 -0
- package/lib/loadAtlaspackPlugin.js +148 -0
- package/lib/loadDotEnv.js +54 -0
- package/lib/projectPath.js +86 -0
- package/lib/public/Asset.js +259 -0
- package/lib/public/Bundle.js +231 -0
- package/lib/public/BundleGraph.js +193 -0
- package/lib/public/BundleGroup.js +44 -0
- package/lib/public/Config.js +202 -0
- package/lib/public/Dependency.js +131 -0
- package/lib/public/Environment.js +244 -0
- package/lib/public/MutableBundleGraph.js +184 -0
- package/lib/public/PluginOptions.js +71 -0
- package/lib/public/Symbols.js +247 -0
- package/lib/public/Target.js +64 -0
- package/lib/registerCoreWithSerializer.js +45 -0
- package/lib/requests/AssetGraphRequest.js +427 -0
- package/lib/requests/AssetGraphRequestRust.js +187 -0
- package/lib/requests/AssetRequest.js +137 -0
- package/lib/requests/AtlaspackBuildRequest.js +78 -0
- package/lib/requests/AtlaspackConfigRequest.js +473 -0
- package/lib/requests/BundleGraphRequest.js +419 -0
- package/lib/requests/ConfigRequest.js +198 -0
- package/lib/requests/DevDepRequest.js +166 -0
- package/lib/requests/EntryRequest.js +295 -0
- package/lib/requests/PackageRequest.js +88 -0
- package/lib/requests/PathRequest.js +349 -0
- package/lib/requests/TargetRequest.js +1177 -0
- package/lib/requests/ValidationRequest.js +66 -0
- package/lib/requests/WriteBundleRequest.js +252 -0
- package/lib/requests/WriteBundlesRequest.js +153 -0
- package/lib/resolveOptions.js +234 -0
- package/lib/serializer.js +216 -0
- package/lib/serializerCore.browser.js +29 -0
- package/lib/serializerCore.js +16 -0
- package/lib/summarizeRequest.js +55 -0
- package/lib/types.js +35 -0
- package/lib/utils.js +160 -0
- package/lib/worker.js +170 -0
- package/package.json +59 -0
- package/src/AssetGraph.js +646 -0
- package/src/Atlaspack.js +632 -0
- package/src/AtlaspackConfig.js +490 -0
- package/src/AtlaspackConfig.schema.js +141 -0
- package/src/BundleGraph.js +2193 -0
- package/src/CommittedAsset.js +143 -0
- package/src/Dependency.js +142 -0
- package/src/Environment.js +151 -0
- package/src/InternalConfig.js +72 -0
- package/src/PackagerRunner.js +790 -0
- package/src/ReporterRunner.js +158 -0
- package/src/RequestTracker.js +1697 -0
- package/src/SymbolPropagation.js +794 -0
- package/src/TargetDescriptor.schema.js +136 -0
- package/src/Transformation.js +752 -0
- package/src/UncommittedAsset.js +426 -0
- package/src/Validation.js +223 -0
- package/src/applyRuntimes.js +341 -0
- package/src/assetUtils.js +254 -0
- package/src/atlaspack-v3/AtlaspackV3.js +73 -0
- package/src/atlaspack-v3/fs.js +36 -0
- package/src/atlaspack-v3/index.js +5 -0
- package/src/atlaspack-v3/jsCallable.js +13 -0
- package/src/atlaspack-v3/plugins/Resolver.js +9 -0
- package/src/atlaspack-v3/plugins/index.js +3 -0
- package/src/atlaspack-v3/worker/index.js +8 -0
- package/src/atlaspack-v3/worker/worker.js +14 -0
- package/src/buildCache.js +15 -0
- package/src/constants.js +22 -0
- package/src/dumpGraphToGraphViz.js +244 -0
- package/src/index.js +22 -0
- package/src/loadAtlaspackPlugin.js +239 -0
- package/src/loadDotEnv.js +56 -0
- package/src/projectPath.js +87 -0
- package/src/public/Asset.js +359 -0
- package/src/public/Bundle.js +337 -0
- package/src/public/BundleGraph.js +335 -0
- package/src/public/BundleGroup.js +55 -0
- package/src/public/Config.js +261 -0
- package/src/public/Dependency.js +176 -0
- package/src/public/Environment.js +316 -0
- package/src/public/MutableBundleGraph.js +320 -0
- package/src/public/PluginOptions.js +99 -0
- package/src/public/Symbols.js +315 -0
- package/src/public/Target.js +71 -0
- package/src/registerCoreWithSerializer.js +34 -0
- package/src/requests/AssetGraphRequest.js +577 -0
- package/src/requests/AssetGraphRequestRust.js +222 -0
- package/src/requests/AssetRequest.js +179 -0
- package/src/requests/AtlaspackBuildRequest.js +109 -0
- package/src/requests/AtlaspackConfigRequest.js +709 -0
- package/src/requests/BundleGraphRequest.js +547 -0
- package/src/requests/ConfigRequest.js +287 -0
- package/src/requests/DevDepRequest.js +246 -0
- package/src/requests/EntryRequest.js +385 -0
- package/src/requests/PackageRequest.js +105 -0
- package/src/requests/PathRequest.js +454 -0
- package/src/requests/TargetRequest.js +1632 -0
- package/src/requests/ValidationRequest.js +79 -0
- package/src/requests/WriteBundleRequest.js +362 -0
- package/src/requests/WriteBundlesRequest.js +209 -0
- package/src/resolveOptions.js +278 -0
- package/src/serializer.js +255 -0
- package/src/serializerCore.browser.js +8 -0
- package/src/serializerCore.js +5 -0
- package/src/summarizeRequest.js +47 -0
- package/src/types.js +581 -0
- package/src/utils.js +211 -0
- package/src/worker.js +189 -0
- package/test/AssetGraph.test.js +679 -0
- package/test/Atlaspack.test.js +142 -0
- package/test/AtlaspackConfig.test.js +405 -0
- package/test/AtlaspackConfigRequest.test.js +993 -0
- package/test/BundleGraph.test.js +121 -0
- package/test/EntryRequest.test.js +215 -0
- package/test/Environment.test.js +99 -0
- package/test/InternalAsset.test.js +76 -0
- package/test/PackagerRunner.test.js +27 -0
- package/test/PublicAsset.test.js +40 -0
- package/test/PublicBundle.test.js +68 -0
- package/test/PublicDependency.test.js +22 -0
- package/test/PublicEnvironment.test.js +27 -0
- package/test/PublicMutableBundleGraph.test.js +192 -0
- package/test/RequestTracker.test.js +448 -0
- package/test/SymbolPropagation.test.js +716 -0
- package/test/TargetRequest.test.js +1715 -0
- package/test/fixtures/application-targets/package.json +3 -0
- package/test/fixtures/atlaspack/index.js +1 -0
- package/test/fixtures/atlaspack/other.js +3 -0
- package/test/fixtures/atlaspack/package.json +1 -0
- package/test/fixtures/atlaspack/yarn.lock +0 -0
- package/test/fixtures/bundle.js +10 -0
- package/test/fixtures/common-targets/package.json +24 -0
- package/test/fixtures/common-targets-ignore/package.json +13 -0
- package/test/fixtures/config/.atlaspackrc +6 -0
- package/test/fixtures/config/subfolder/.atlaspackrc +6 -0
- package/test/fixtures/config-extends-not-found/.atlaspackrc +3 -0
- package/test/fixtures/config-extends-not-found/.atlaspackrc-json5 +3 -0
- package/test/fixtures/config-extends-not-found/.atlaspackrc-multiple +3 -0
- package/test/fixtures/config-extends-not-found/.atlaspackrc-node-modules +3 -0
- package/test/fixtures/config-malformed/.atlaspackrc +3 -0
- package/test/fixtures/config-node-pipeline/.atlaspackrc +6 -0
- package/test/fixtures/config-plugin-not-found/.atlaspackrc +6 -0
- package/test/fixtures/context/package.json +8 -0
- package/test/fixtures/custom-format-infer-ext/package.json +6 -0
- package/test/fixtures/custom-format-infer-type/package.json +7 -0
- package/test/fixtures/custom-format-mismatch/package.json +8 -0
- package/test/fixtures/custom-targets/package.json +20 -0
- package/test/fixtures/custom-targets-distdir/package.json +11 -0
- package/test/fixtures/duplicate-targets/package.json +4 -0
- package/test/fixtures/glob-like/[entry].js +0 -0
- package/test/fixtures/invalid-distpath/package.json +11 -0
- package/test/fixtures/invalid-engines/package.json +12 -0
- package/test/fixtures/invalid-source-missing/package.json +5 -0
- package/test/fixtures/invalid-source-not-file/package.json +5 -0
- package/test/fixtures/invalid-source-not-file/src/index.js +1 -0
- package/test/fixtures/invalid-target-source-missing/package.json +9 -0
- package/test/fixtures/invalid-target-source-not-file/package.json +9 -0
- package/test/fixtures/invalid-target-source-not-file/src/index.js +1 -0
- package/test/fixtures/invalid-targets/package.json +19 -0
- package/test/fixtures/library-custom-scopehoist/package.json +9 -0
- package/test/fixtures/library-scopehoist/package.json +8 -0
- package/test/fixtures/local-plugin-config-pkg/.atlaspackrc +3 -0
- package/test/fixtures/local-plugin-config-pkg/node_modules/atlaspack-config-local/index.json +8 -0
- package/test/fixtures/local-plugin-config-pkg/node_modules/atlaspack-config-local/local-plugin.js +7 -0
- package/test/fixtures/local-plugin-config-pkg/node_modules/atlaspack-config-local/package.json +7 -0
- package/test/fixtures/main-format-mismatch/package.json +8 -0
- package/test/fixtures/main-global/package.json +8 -0
- package/test/fixtures/main-mjs/package.json +8 -0
- package/test/fixtures/module-a.js +1 -0
- package/test/fixtures/module-b.js +1 -0
- package/test/fixtures/plugins/local-plugin.js +7 -0
- package/test/fixtures/plugins/node_modules/atlaspack-transformer-bad-engines/index.js +7 -0
- package/test/fixtures/plugins/node_modules/atlaspack-transformer-bad-engines/package.json +7 -0
- package/test/fixtures/plugins/node_modules/atlaspack-transformer-no-engines/index.js +7 -0
- package/test/fixtures/plugins/node_modules/atlaspack-transformer-no-engines/package.json +4 -0
- package/test/fixtures/targets-default-distdir-none/package.json +5 -0
- package/test/fixtures/targets-default-distdir-one/package.json +8 -0
- package/test/fixtures/targets-default-distdir-two/package.json +18 -0
- package/test/requests/ConfigRequest.test.js +254 -0
- package/test/serializer.test.js +302 -0
- package/test/test-utils.js +80 -0
- package/test/utils.test.js +43 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// @flow strict-local
|
|
2
|
+
import type {Async} from '@atlaspack/types';
|
|
3
|
+
import type {SharedReference} from '@atlaspack/workers';
|
|
4
|
+
import type {StaticRunOpts} from '../RequestTracker';
|
|
5
|
+
import type {AssetGroup} from '../types';
|
|
6
|
+
import type {ConfigAndCachePath} from './AtlaspackConfigRequest';
|
|
7
|
+
|
|
8
|
+
import nullthrows from 'nullthrows';
|
|
9
|
+
import AtlaspackConfig from '../AtlaspackConfig';
|
|
10
|
+
import {report} from '../ReporterRunner';
|
|
11
|
+
import Validation from '../Validation';
|
|
12
|
+
import createAtlaspackConfigRequest from './AtlaspackConfigRequest';
|
|
13
|
+
import {requestTypes} from '../RequestTracker';
|
|
14
|
+
|
|
15
|
+
type ValidationRequest = {|
|
|
16
|
+
id: string,
|
|
17
|
+
+type: typeof requestTypes.validation_request,
|
|
18
|
+
run: (RunOpts<void>) => Async<void>,
|
|
19
|
+
input: ValidationRequestInput,
|
|
20
|
+
|};
|
|
21
|
+
|
|
22
|
+
type RunOpts<TResult> = {|
|
|
23
|
+
input: ValidationRequestInput,
|
|
24
|
+
...StaticRunOpts<TResult>,
|
|
25
|
+
|};
|
|
26
|
+
|
|
27
|
+
type ValidationRequestInput = {|
|
|
28
|
+
assetRequests: Array<AssetGroup>,
|
|
29
|
+
optionsRef: SharedReference,
|
|
30
|
+
|};
|
|
31
|
+
|
|
32
|
+
export default function createValidationRequest(
|
|
33
|
+
input: ValidationRequestInput,
|
|
34
|
+
): ValidationRequest {
|
|
35
|
+
return {
|
|
36
|
+
id: 'validation',
|
|
37
|
+
type: requestTypes.validation_request,
|
|
38
|
+
run: async ({input: {assetRequests, optionsRef}, api, options, farm}) => {
|
|
39
|
+
let {config: processedConfig, cachePath} = nullthrows(
|
|
40
|
+
await api.runRequest<null, ConfigAndCachePath>(
|
|
41
|
+
createAtlaspackConfigRequest(),
|
|
42
|
+
),
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
let config = new AtlaspackConfig(processedConfig, options);
|
|
46
|
+
let trackedRequestsDesc = assetRequests.filter(request => {
|
|
47
|
+
return config.getValidatorNames(request.filePath).length > 0;
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Schedule validations on workers for all plugins that implement the one-asset-at-a-time "validate" method.
|
|
51
|
+
let promises = trackedRequestsDesc.map(
|
|
52
|
+
async request =>
|
|
53
|
+
((await farm.createHandle('runValidate'))({
|
|
54
|
+
requests: [request],
|
|
55
|
+
optionsRef: optionsRef,
|
|
56
|
+
configCachePath: cachePath,
|
|
57
|
+
}): void),
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
// Skip sending validation requests if no validators were configured
|
|
61
|
+
if (trackedRequestsDesc.length === 0) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Schedule validations on the main thread for all validation plugins that implement "validateAll".
|
|
66
|
+
promises.push(
|
|
67
|
+
new Validation({
|
|
68
|
+
requests: trackedRequestsDesc,
|
|
69
|
+
options,
|
|
70
|
+
config,
|
|
71
|
+
report,
|
|
72
|
+
dedicatedThread: true,
|
|
73
|
+
}).run(),
|
|
74
|
+
);
|
|
75
|
+
await Promise.all(promises);
|
|
76
|
+
},
|
|
77
|
+
input,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
// @flow strict-local
|
|
2
|
+
|
|
3
|
+
import type {FileSystem, FileOptions} from '@atlaspack/fs';
|
|
4
|
+
import type {ContentKey} from '@atlaspack/graph';
|
|
5
|
+
import type {Async, FilePath, Compressor} from '@atlaspack/types';
|
|
6
|
+
|
|
7
|
+
import type {RunAPI, StaticRunOpts} from '../RequestTracker';
|
|
8
|
+
import type {Bundle, PackagedBundleInfo, AtlaspackOptions} from '../types';
|
|
9
|
+
import type BundleGraph from '../BundleGraph';
|
|
10
|
+
import type {BundleInfo} from '../PackagerRunner';
|
|
11
|
+
import type {ConfigAndCachePath} from './AtlaspackConfigRequest';
|
|
12
|
+
import type {LoadedPlugin} from '../AtlaspackConfig';
|
|
13
|
+
import type {ProjectPath} from '../projectPath';
|
|
14
|
+
|
|
15
|
+
import {HASH_REF_HASH_LEN, HASH_REF_PREFIX} from '../constants';
|
|
16
|
+
import nullthrows from 'nullthrows';
|
|
17
|
+
import path from 'path';
|
|
18
|
+
import {NamedBundle} from '../public/Bundle';
|
|
19
|
+
import {blobToStream, TapStream} from '@atlaspack/utils';
|
|
20
|
+
import {Readable, Transform, pipeline} from 'stream';
|
|
21
|
+
import {
|
|
22
|
+
fromProjectPath,
|
|
23
|
+
fromProjectPathRelative,
|
|
24
|
+
toProjectPath,
|
|
25
|
+
joinProjectPath,
|
|
26
|
+
toProjectPathUnsafe,
|
|
27
|
+
} from '../projectPath';
|
|
28
|
+
import createAtlaspackConfigRequest, {
|
|
29
|
+
getCachedAtlaspackConfig,
|
|
30
|
+
} from './AtlaspackConfigRequest';
|
|
31
|
+
import PluginOptions from '../public/PluginOptions';
|
|
32
|
+
import {PluginLogger} from '@atlaspack/logger';
|
|
33
|
+
import {
|
|
34
|
+
getDevDepRequests,
|
|
35
|
+
invalidateDevDeps,
|
|
36
|
+
createDevDependency,
|
|
37
|
+
runDevDepRequest,
|
|
38
|
+
} from './DevDepRequest';
|
|
39
|
+
import AtlaspackConfig from '../AtlaspackConfig';
|
|
40
|
+
import ThrowableDiagnostic, {errorToDiagnostic} from '@atlaspack/diagnostic';
|
|
41
|
+
import {PluginTracer, tracer} from '@atlaspack/profiler';
|
|
42
|
+
import {requestTypes} from '../RequestTracker';
|
|
43
|
+
|
|
44
|
+
const HASH_REF_PREFIX_LEN = HASH_REF_PREFIX.length;
|
|
45
|
+
const BOUNDARY_LENGTH = HASH_REF_PREFIX.length + 32 - 1;
|
|
46
|
+
|
|
47
|
+
type WriteBundleRequestInput = {|
|
|
48
|
+
bundleGraph: BundleGraph,
|
|
49
|
+
bundle: Bundle,
|
|
50
|
+
info: BundleInfo,
|
|
51
|
+
hashRefToNameHash: Map<string, string>,
|
|
52
|
+
|};
|
|
53
|
+
|
|
54
|
+
export type WriteBundleRequestResult = PackagedBundleInfo;
|
|
55
|
+
|
|
56
|
+
type RunInput<TResult> = {|
|
|
57
|
+
input: WriteBundleRequestInput,
|
|
58
|
+
...StaticRunOpts<TResult>,
|
|
59
|
+
|};
|
|
60
|
+
|
|
61
|
+
export type WriteBundleRequest = {|
|
|
62
|
+
id: ContentKey,
|
|
63
|
+
+type: typeof requestTypes.write_bundle_request,
|
|
64
|
+
run: (RunInput<PackagedBundleInfo>) => Async<PackagedBundleInfo>,
|
|
65
|
+
input: WriteBundleRequestInput,
|
|
66
|
+
|};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Writes a bundle to the dist directory, replacing hash references with the final content hashes.
|
|
70
|
+
*/
|
|
71
|
+
export default function createWriteBundleRequest(
|
|
72
|
+
input: WriteBundleRequestInput,
|
|
73
|
+
): WriteBundleRequest {
|
|
74
|
+
let name = nullthrows(input.bundle.name);
|
|
75
|
+
let nameHash = nullthrows(
|
|
76
|
+
input.hashRefToNameHash.get(input.bundle.hashReference),
|
|
77
|
+
);
|
|
78
|
+
return {
|
|
79
|
+
id: `${input.bundle.id}:${input.info.hash}:${nameHash}:${name}`,
|
|
80
|
+
type: requestTypes.write_bundle_request,
|
|
81
|
+
run,
|
|
82
|
+
input,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function run({input, options, api}) {
|
|
87
|
+
let {bundleGraph, bundle, info, hashRefToNameHash} = input;
|
|
88
|
+
let {inputFS, outputFS} = options;
|
|
89
|
+
let name = nullthrows(bundle.name);
|
|
90
|
+
let thisHashReference = bundle.hashReference;
|
|
91
|
+
|
|
92
|
+
if (info.type !== bundle.type) {
|
|
93
|
+
name = name.slice(0, -path.extname(name).length) + '.' + info.type;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (name.includes(thisHashReference)) {
|
|
97
|
+
let thisNameHash = nullthrows(hashRefToNameHash.get(thisHashReference));
|
|
98
|
+
name = name.replace(thisHashReference, thisNameHash);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let filePath = joinProjectPath(bundle.target.distDir, name);
|
|
102
|
+
|
|
103
|
+
// Watch the bundle and source map for deletion.
|
|
104
|
+
// Also watch the dist dir because invalidateOnFileDelete does not currently
|
|
105
|
+
// invalidate when a parent directory is deleted.
|
|
106
|
+
// TODO: do we want to also watch for file edits?
|
|
107
|
+
api.invalidateOnFileDelete(bundle.target.distDir);
|
|
108
|
+
api.invalidateOnFileDelete(filePath);
|
|
109
|
+
|
|
110
|
+
let cacheKeys = info.cacheKeys;
|
|
111
|
+
let mapKey = cacheKeys.map;
|
|
112
|
+
let fullPath = fromProjectPath(options.projectRoot, filePath);
|
|
113
|
+
if (mapKey && bundle.env.sourceMap && !bundle.env.sourceMap.inline) {
|
|
114
|
+
api.invalidateOnFileDelete(
|
|
115
|
+
toProjectPath(options.projectRoot, fullPath + '.map'),
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
let dir = path.dirname(fullPath);
|
|
120
|
+
await outputFS.mkdirp(dir); // ? Got rid of dist exists, is this an expensive operation
|
|
121
|
+
|
|
122
|
+
// Use the file mode from the entry asset as the file mode for the bundle.
|
|
123
|
+
// Don't do this for browser builds, as the executable bit in particular is unnecessary.
|
|
124
|
+
let publicBundle = NamedBundle.get(bundle, bundleGraph, options);
|
|
125
|
+
let mainEntry = publicBundle.getMainEntry();
|
|
126
|
+
let writeOptions =
|
|
127
|
+
publicBundle.env.isBrowser() || !mainEntry
|
|
128
|
+
? undefined
|
|
129
|
+
: {
|
|
130
|
+
mode: (await inputFS.stat(mainEntry.filePath)).mode,
|
|
131
|
+
};
|
|
132
|
+
let contentStream: Readable;
|
|
133
|
+
if (info.isLargeBlob) {
|
|
134
|
+
contentStream = options.cache.getStream(cacheKeys.content);
|
|
135
|
+
} else {
|
|
136
|
+
contentStream = blobToStream(
|
|
137
|
+
await options.cache.getBlob(cacheKeys.content),
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
let size = 0;
|
|
141
|
+
contentStream = contentStream.pipe(
|
|
142
|
+
new TapStream(buf => {
|
|
143
|
+
size += buf.length;
|
|
144
|
+
}),
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
let configResult = nullthrows(
|
|
148
|
+
await api.runRequest<null, ConfigAndCachePath>(
|
|
149
|
+
createAtlaspackConfigRequest(),
|
|
150
|
+
),
|
|
151
|
+
);
|
|
152
|
+
let config = getCachedAtlaspackConfig(configResult, options);
|
|
153
|
+
|
|
154
|
+
let {devDeps, invalidDevDeps} = await getDevDepRequests(api);
|
|
155
|
+
invalidateDevDeps(invalidDevDeps, options, config);
|
|
156
|
+
|
|
157
|
+
await writeFiles(
|
|
158
|
+
contentStream,
|
|
159
|
+
info,
|
|
160
|
+
hashRefToNameHash,
|
|
161
|
+
options,
|
|
162
|
+
config,
|
|
163
|
+
outputFS,
|
|
164
|
+
filePath,
|
|
165
|
+
writeOptions,
|
|
166
|
+
devDeps,
|
|
167
|
+
api,
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
if (
|
|
171
|
+
mapKey &&
|
|
172
|
+
bundle.env.sourceMap &&
|
|
173
|
+
!bundle.env.sourceMap.inline &&
|
|
174
|
+
(await options.cache.has(mapKey))
|
|
175
|
+
) {
|
|
176
|
+
await writeFiles(
|
|
177
|
+
blobToStream(await options.cache.getBlob(mapKey)),
|
|
178
|
+
info,
|
|
179
|
+
hashRefToNameHash,
|
|
180
|
+
options,
|
|
181
|
+
config,
|
|
182
|
+
outputFS,
|
|
183
|
+
toProjectPathUnsafe(fromProjectPathRelative(filePath) + '.map'),
|
|
184
|
+
writeOptions,
|
|
185
|
+
devDeps,
|
|
186
|
+
api,
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
let res = {
|
|
191
|
+
filePath,
|
|
192
|
+
type: info.type,
|
|
193
|
+
stats: {
|
|
194
|
+
size,
|
|
195
|
+
time: info.time ?? 0,
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
api.storeResult(res);
|
|
200
|
+
return res;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async function writeFiles(
|
|
204
|
+
inputStream: stream$Readable,
|
|
205
|
+
info: BundleInfo,
|
|
206
|
+
hashRefToNameHash: Map<string, string>,
|
|
207
|
+
options: AtlaspackOptions,
|
|
208
|
+
config: AtlaspackConfig,
|
|
209
|
+
outputFS: FileSystem,
|
|
210
|
+
filePath: ProjectPath,
|
|
211
|
+
writeOptions: ?FileOptions,
|
|
212
|
+
devDeps: Map<string, string>,
|
|
213
|
+
api: RunAPI<PackagedBundleInfo>,
|
|
214
|
+
) {
|
|
215
|
+
let compressors = await config.getCompressors(
|
|
216
|
+
fromProjectPathRelative(filePath),
|
|
217
|
+
);
|
|
218
|
+
let fullPath = fromProjectPath(options.projectRoot, filePath);
|
|
219
|
+
|
|
220
|
+
let stream = info.hashReferences.length
|
|
221
|
+
? inputStream.pipe(replaceStream(hashRefToNameHash))
|
|
222
|
+
: inputStream;
|
|
223
|
+
|
|
224
|
+
let promises = [];
|
|
225
|
+
for (let compressor of compressors) {
|
|
226
|
+
promises.push(
|
|
227
|
+
runCompressor(
|
|
228
|
+
compressor,
|
|
229
|
+
cloneStream(stream),
|
|
230
|
+
options,
|
|
231
|
+
outputFS,
|
|
232
|
+
fullPath,
|
|
233
|
+
writeOptions,
|
|
234
|
+
devDeps,
|
|
235
|
+
api,
|
|
236
|
+
),
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
await Promise.all(promises);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async function runCompressor(
|
|
244
|
+
compressor: LoadedPlugin<Compressor>,
|
|
245
|
+
stream: stream$Readable,
|
|
246
|
+
options: AtlaspackOptions,
|
|
247
|
+
outputFS: FileSystem,
|
|
248
|
+
filePath: FilePath,
|
|
249
|
+
writeOptions: ?FileOptions,
|
|
250
|
+
devDeps: Map<string, string>,
|
|
251
|
+
api: RunAPI<PackagedBundleInfo>,
|
|
252
|
+
) {
|
|
253
|
+
let measurement;
|
|
254
|
+
try {
|
|
255
|
+
measurement = tracer.createMeasurement(
|
|
256
|
+
compressor.name,
|
|
257
|
+
'compress',
|
|
258
|
+
path.relative(options.projectRoot, filePath),
|
|
259
|
+
);
|
|
260
|
+
let res = await compressor.plugin.compress({
|
|
261
|
+
stream,
|
|
262
|
+
options: new PluginOptions(options),
|
|
263
|
+
logger: new PluginLogger({origin: compressor.name}),
|
|
264
|
+
tracer: new PluginTracer({origin: compressor.name, category: 'compress'}),
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
if (res != null) {
|
|
268
|
+
await new Promise((resolve, reject) =>
|
|
269
|
+
pipeline(
|
|
270
|
+
res.stream,
|
|
271
|
+
outputFS.createWriteStream(
|
|
272
|
+
filePath + (res.type != null ? '.' + res.type : ''),
|
|
273
|
+
writeOptions,
|
|
274
|
+
),
|
|
275
|
+
err => {
|
|
276
|
+
if (err) reject(err);
|
|
277
|
+
else resolve();
|
|
278
|
+
},
|
|
279
|
+
),
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
} catch (err) {
|
|
283
|
+
throw new ThrowableDiagnostic({
|
|
284
|
+
diagnostic: errorToDiagnostic(err, {
|
|
285
|
+
origin: compressor.name,
|
|
286
|
+
}),
|
|
287
|
+
});
|
|
288
|
+
} finally {
|
|
289
|
+
measurement && measurement.end();
|
|
290
|
+
// Add dev deps for compressor plugins AFTER running them, to account for lazy require().
|
|
291
|
+
let devDepRequest = await createDevDependency(
|
|
292
|
+
{
|
|
293
|
+
specifier: compressor.name,
|
|
294
|
+
resolveFrom: compressor.resolveFrom,
|
|
295
|
+
},
|
|
296
|
+
devDeps,
|
|
297
|
+
options,
|
|
298
|
+
);
|
|
299
|
+
await runDevDepRequest(api, devDepRequest);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function replaceStream(hashRefToNameHash) {
|
|
304
|
+
let boundaryStr = Buffer.alloc(0);
|
|
305
|
+
let replaced = Buffer.alloc(0);
|
|
306
|
+
return new Transform({
|
|
307
|
+
transform(chunk, encoding, cb) {
|
|
308
|
+
let str = Buffer.concat([boundaryStr, Buffer.from(chunk)]);
|
|
309
|
+
let lastMatchI = 0;
|
|
310
|
+
if (replaced.length < str.byteLength) {
|
|
311
|
+
replaced = Buffer.alloc(str.byteLength);
|
|
312
|
+
}
|
|
313
|
+
let replacedLength = 0;
|
|
314
|
+
|
|
315
|
+
while (lastMatchI < str.byteLength) {
|
|
316
|
+
let matchI = str.indexOf(HASH_REF_PREFIX, lastMatchI);
|
|
317
|
+
if (matchI === -1) {
|
|
318
|
+
replaced.set(
|
|
319
|
+
str.subarray(lastMatchI, str.byteLength),
|
|
320
|
+
replacedLength,
|
|
321
|
+
);
|
|
322
|
+
replacedLength += str.byteLength - lastMatchI;
|
|
323
|
+
break;
|
|
324
|
+
} else {
|
|
325
|
+
let match = str
|
|
326
|
+
.subarray(matchI, matchI + HASH_REF_PREFIX_LEN + HASH_REF_HASH_LEN)
|
|
327
|
+
.toString();
|
|
328
|
+
let replacement = Buffer.from(hashRefToNameHash.get(match) ?? match);
|
|
329
|
+
replaced.set(str.subarray(lastMatchI, matchI), replacedLength);
|
|
330
|
+
replacedLength += matchI - lastMatchI;
|
|
331
|
+
replaced.set(replacement, replacedLength);
|
|
332
|
+
replacedLength += replacement.byteLength;
|
|
333
|
+
lastMatchI = matchI + HASH_REF_PREFIX_LEN + HASH_REF_HASH_LEN;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
boundaryStr = replaced.subarray(
|
|
338
|
+
replacedLength - BOUNDARY_LENGTH,
|
|
339
|
+
replacedLength,
|
|
340
|
+
);
|
|
341
|
+
let strUpToBoundary = replaced.subarray(
|
|
342
|
+
0,
|
|
343
|
+
replacedLength - BOUNDARY_LENGTH,
|
|
344
|
+
);
|
|
345
|
+
cb(null, strUpToBoundary);
|
|
346
|
+
},
|
|
347
|
+
|
|
348
|
+
flush(cb) {
|
|
349
|
+
cb(null, boundaryStr);
|
|
350
|
+
},
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function cloneStream(readable) {
|
|
355
|
+
let res = new Readable();
|
|
356
|
+
// $FlowFixMe
|
|
357
|
+
res._read = () => {};
|
|
358
|
+
readable.on('data', chunk => res.push(chunk));
|
|
359
|
+
readable.on('end', () => res.push(null));
|
|
360
|
+
readable.on('error', err => res.emit('error', err));
|
|
361
|
+
return res;
|
|
362
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
// @flow strict-local
|
|
2
|
+
|
|
3
|
+
import type {ContentKey} from '@atlaspack/graph';
|
|
4
|
+
import type {Async} from '@atlaspack/types';
|
|
5
|
+
import type {SharedReference} from '@atlaspack/workers';
|
|
6
|
+
import type {StaticRunOpts} from '../RequestTracker';
|
|
7
|
+
import {requestTypes} from '../RequestTracker';
|
|
8
|
+
import type {PackagedBundleInfo} from '../types';
|
|
9
|
+
import type BundleGraph from '../BundleGraph';
|
|
10
|
+
import type {BundleInfo} from '../PackagerRunner';
|
|
11
|
+
|
|
12
|
+
import {HASH_REF_PREFIX} from '../constants';
|
|
13
|
+
import {joinProjectPath} from '../projectPath';
|
|
14
|
+
import nullthrows from 'nullthrows';
|
|
15
|
+
import {hashString} from '@atlaspack/rust';
|
|
16
|
+
import {createPackageRequest} from './PackageRequest';
|
|
17
|
+
import createWriteBundleRequest from './WriteBundleRequest';
|
|
18
|
+
|
|
19
|
+
type WriteBundlesRequestInput = {|
|
|
20
|
+
bundleGraph: BundleGraph,
|
|
21
|
+
optionsRef: SharedReference,
|
|
22
|
+
|};
|
|
23
|
+
|
|
24
|
+
export type WriteBundlesRequestResult = Map<string, PackagedBundleInfo>;
|
|
25
|
+
|
|
26
|
+
type RunInput<TResult> = {|
|
|
27
|
+
input: WriteBundlesRequestInput,
|
|
28
|
+
...StaticRunOpts<TResult>,
|
|
29
|
+
|};
|
|
30
|
+
|
|
31
|
+
export type WriteBundlesRequest = {|
|
|
32
|
+
id: ContentKey,
|
|
33
|
+
+type: typeof requestTypes.write_bundles_request,
|
|
34
|
+
run: (
|
|
35
|
+
RunInput<WriteBundlesRequestResult>,
|
|
36
|
+
) => Async<WriteBundlesRequestResult>,
|
|
37
|
+
input: WriteBundlesRequestInput,
|
|
38
|
+
|};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Packages, optimizes, and writes all bundles to the dist directory.
|
|
42
|
+
*/
|
|
43
|
+
export default function createWriteBundlesRequest(
|
|
44
|
+
input: WriteBundlesRequestInput,
|
|
45
|
+
): WriteBundlesRequest {
|
|
46
|
+
return {
|
|
47
|
+
type: requestTypes.write_bundles_request,
|
|
48
|
+
id: 'write_bundles:' + input.bundleGraph.getBundleGraphHash(),
|
|
49
|
+
run,
|
|
50
|
+
input,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function run({input, api, farm, options}) {
|
|
55
|
+
let {bundleGraph, optionsRef} = input;
|
|
56
|
+
let {ref, dispose} = await farm.createSharedReference(bundleGraph);
|
|
57
|
+
|
|
58
|
+
api.invalidateOnOptionChange('shouldContentHash');
|
|
59
|
+
|
|
60
|
+
let res = new Map();
|
|
61
|
+
let bundleInfoMap: {|
|
|
62
|
+
[string]: BundleInfo,
|
|
63
|
+
|} = {};
|
|
64
|
+
let writeEarlyPromises = {};
|
|
65
|
+
let hashRefToNameHash = new Map();
|
|
66
|
+
let bundles = bundleGraph.getBundles().filter(bundle => {
|
|
67
|
+
// Do not package and write placeholder bundles to disk. We just
|
|
68
|
+
// need to update the name so other bundles can reference it.
|
|
69
|
+
if (bundle.isPlaceholder) {
|
|
70
|
+
let hash = bundle.id.slice(-8);
|
|
71
|
+
hashRefToNameHash.set(bundle.hashReference, hash);
|
|
72
|
+
let name = nullthrows(
|
|
73
|
+
bundle.name,
|
|
74
|
+
`Expected ${bundle.type} bundle to have a name`,
|
|
75
|
+
).replace(bundle.hashReference, hash);
|
|
76
|
+
res.set(bundle.id, {
|
|
77
|
+
filePath: joinProjectPath(bundle.target.distDir, name),
|
|
78
|
+
type: bundle.type, // FIXME: this is wrong if the packager changes the type...
|
|
79
|
+
stats: {
|
|
80
|
+
time: 0,
|
|
81
|
+
size: 0,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return true;
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Package on the main thread if there is only one bundle to package.
|
|
91
|
+
// This avoids the cost of serializing the bundle graph for single file change builds.
|
|
92
|
+
let useMainThread =
|
|
93
|
+
bundles.length === 1 ||
|
|
94
|
+
bundles.filter(b => !api.canSkipSubrequest(bundleGraph.getHash(b)))
|
|
95
|
+
.length === 1;
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
await Promise.all(
|
|
99
|
+
bundles.map(async bundle => {
|
|
100
|
+
let request = createPackageRequest({
|
|
101
|
+
bundle,
|
|
102
|
+
bundleGraph,
|
|
103
|
+
bundleGraphReference: ref,
|
|
104
|
+
optionsRef,
|
|
105
|
+
useMainThread,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
let info = await api.runRequest(request);
|
|
109
|
+
|
|
110
|
+
if (!useMainThread) {
|
|
111
|
+
// Force a refresh of the cache to avoid a race condition
|
|
112
|
+
// between threaded reads and writes that can result in an LMDB cache miss:
|
|
113
|
+
// 1. The main thread has read some value from cache, necessitating a read transaction.
|
|
114
|
+
// 2. Concurrently, Thread A finishes a packaging request.
|
|
115
|
+
// 3. Subsequently, the main thread is tasked with this request, but fails because the read transaction is stale.
|
|
116
|
+
// This only occurs if the reading thread has a transaction that was created before the writing thread committed,
|
|
117
|
+
// and the transaction is still live when the reading thread attempts to get the written value.
|
|
118
|
+
// See https://github.com/parcel-bundler/parcel/issues/9121
|
|
119
|
+
options.cache.refresh();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
bundleInfoMap[bundle.id] = info;
|
|
123
|
+
if (!info.hashReferences.length) {
|
|
124
|
+
hashRefToNameHash.set(
|
|
125
|
+
bundle.hashReference,
|
|
126
|
+
options.shouldContentHash
|
|
127
|
+
? info.hash.slice(-8)
|
|
128
|
+
: bundle.id.slice(-8),
|
|
129
|
+
);
|
|
130
|
+
let writeBundleRequest = createWriteBundleRequest({
|
|
131
|
+
bundle,
|
|
132
|
+
info,
|
|
133
|
+
hashRefToNameHash,
|
|
134
|
+
bundleGraph,
|
|
135
|
+
});
|
|
136
|
+
let promise = api.runRequest(writeBundleRequest);
|
|
137
|
+
// If the promise rejects before we await it (below), we don't want to crash the build.
|
|
138
|
+
promise.catch(() => {});
|
|
139
|
+
writeEarlyPromises[bundle.id] = promise;
|
|
140
|
+
}
|
|
141
|
+
}),
|
|
142
|
+
);
|
|
143
|
+
assignComplexNameHashes(hashRefToNameHash, bundles, bundleInfoMap, options);
|
|
144
|
+
await Promise.all(
|
|
145
|
+
bundles.map(bundle => {
|
|
146
|
+
let promise =
|
|
147
|
+
writeEarlyPromises[bundle.id] ??
|
|
148
|
+
api.runRequest(
|
|
149
|
+
createWriteBundleRequest({
|
|
150
|
+
bundle,
|
|
151
|
+
info: bundleInfoMap[bundle.id],
|
|
152
|
+
hashRefToNameHash,
|
|
153
|
+
bundleGraph,
|
|
154
|
+
}),
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
return promise.then(r => res.set(bundle.id, r));
|
|
158
|
+
}),
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
api.storeResult(res);
|
|
162
|
+
return res;
|
|
163
|
+
} finally {
|
|
164
|
+
await dispose();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function assignComplexNameHashes(
|
|
169
|
+
hashRefToNameHash,
|
|
170
|
+
bundles,
|
|
171
|
+
bundleInfoMap,
|
|
172
|
+
options,
|
|
173
|
+
) {
|
|
174
|
+
for (let bundle of bundles) {
|
|
175
|
+
if (hashRefToNameHash.get(bundle.hashReference) != null) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
hashRefToNameHash.set(
|
|
179
|
+
bundle.hashReference,
|
|
180
|
+
options.shouldContentHash
|
|
181
|
+
? hashString(
|
|
182
|
+
[...getBundlesIncludedInHash(bundle.id, bundleInfoMap)]
|
|
183
|
+
.map(bundleId => bundleInfoMap[bundleId].hash)
|
|
184
|
+
.join(':'),
|
|
185
|
+
).slice(-8)
|
|
186
|
+
: bundle.id.slice(-8),
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function getBundlesIncludedInHash(
|
|
192
|
+
bundleId,
|
|
193
|
+
bundleInfoMap,
|
|
194
|
+
included = new Set(),
|
|
195
|
+
) {
|
|
196
|
+
included.add(bundleId);
|
|
197
|
+
for (let hashRef of bundleInfoMap[bundleId].hashReferences) {
|
|
198
|
+
let referencedId = getIdFromHashRef(hashRef);
|
|
199
|
+
if (!included.has(referencedId)) {
|
|
200
|
+
getBundlesIncludedInHash(referencedId, bundleInfoMap, included);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return included;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function getIdFromHashRef(hashRef: string) {
|
|
208
|
+
return hashRef.slice(HASH_REF_PREFIX.length);
|
|
209
|
+
}
|