UNPKG

4.52 kBJavaScriptView Raw
1"use strict";
2/**
3 * @license
4 * Copyright Google LLC All Rights Reserved.
5 *
6 * Use of this source code is governed by an MIT-style license that can be
7 * found in the LICENSE file at https://angular.io/license
8 */
9Object.defineProperty(exports, "__esModule", { value: true });
10exports.BundleActionExecutor = void 0;
11const jest_worker_1 = require("jest-worker");
12const os = require("os");
13const path = require("path");
14const v8_1 = require("v8");
15const action_cache_1 = require("./action-cache");
16const environment_options_1 = require("./environment-options");
17let workerFile = require.resolve('./process-bundle');
18workerFile =
19 path.extname(workerFile) === '.ts' ? require.resolve('./process-bundle-bootstrap') : workerFile;
20class BundleActionExecutor {
21 constructor(workerOptions, integrityAlgorithm, sizeThreshold = 32 * 1024) {
22 this.workerOptions = workerOptions;
23 this.sizeThreshold = sizeThreshold;
24 if (workerOptions.cachePath) {
25 this.cache = new action_cache_1.BundleActionCache(workerOptions.cachePath, integrityAlgorithm);
26 }
27 }
28 static executeMethod(worker, method, input) {
29 return worker[method](input);
30 }
31 ensureLarge() {
32 if (this.largeWorker) {
33 return this.largeWorker;
34 }
35 // larger files are processed in a separate process to limit memory usage in the main process
36 return (this.largeWorker = new jest_worker_1.default(workerFile, {
37 exposedMethods: ['process', 'inlineLocales'],
38 setupArgs: [[...v8_1.serialize(this.workerOptions)]],
39 numWorkers: environment_options_1.maxWorkers,
40 }));
41 }
42 ensureSmall() {
43 if (this.smallWorker) {
44 return this.smallWorker;
45 }
46 // small files are processed in a limited number of threads to improve speed
47 // The limited number also prevents a large increase in memory usage for an otherwise short operation
48 return (this.smallWorker = new jest_worker_1.default(workerFile, {
49 exposedMethods: ['process', 'inlineLocales'],
50 setupArgs: [this.workerOptions],
51 numWorkers: os.cpus().length < 2 ? 1 : 2,
52 enableWorkerThreads: true,
53 }));
54 }
55 executeAction(method, action) {
56 // code.length is not an exact byte count but close enough for this
57 if (action.code.length > this.sizeThreshold) {
58 return BundleActionExecutor.executeMethod(this.ensureLarge(), method, action);
59 }
60 else {
61 return BundleActionExecutor.executeMethod(this.ensureSmall(), method, action);
62 }
63 }
64 async process(action) {
65 if (this.cache) {
66 const cacheKeys = this.cache.generateCacheKeys(action);
67 action.cacheKeys = cacheKeys;
68 // Try to get cached data, if it fails fallback to processing
69 try {
70 const cachedResult = await this.cache.getCachedBundleResult(action);
71 if (cachedResult) {
72 return cachedResult;
73 }
74 }
75 catch { }
76 }
77 return this.executeAction('process', action);
78 }
79 processAll(actions) {
80 return BundleActionExecutor.executeAll(actions, (action) => this.process(action));
81 }
82 async inline(action) {
83 return this.executeAction('inlineLocales', action);
84 }
85 inlineAll(actions) {
86 return BundleActionExecutor.executeAll(actions, (action) => this.inline(action));
87 }
88 static async *executeAll(actions, executor) {
89 const executions = new Map();
90 for (const action of actions) {
91 const execution = executor(action);
92 executions.set(execution, execution.then((result) => {
93 executions.delete(execution);
94 return result;
95 }));
96 }
97 while (executions.size > 0) {
98 yield Promise.race(executions.values());
99 }
100 }
101 stop() {
102 // Floating promises are intentional here
103 // https://github.com/facebook/jest/tree/56079a5aceacf32333089cea50c64385885fee26/packages/jest-worker#end
104 if (this.largeWorker) {
105 // eslint-disable-next-line @typescript-eslint/no-floating-promises
106 this.largeWorker.end();
107 }
108 if (this.smallWorker) {
109 // eslint-disable-next-line @typescript-eslint/no-floating-promises
110 this.smallWorker.end();
111 }
112 }
113}
114exports.BundleActionExecutor = BundleActionExecutor;