1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
10 | if (k2 === undefined) k2 = k;
|
11 | var desc = Object.getOwnPropertyDescriptor(m, k);
|
12 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
13 | desc = { enumerable: true, get: function() { return m[k]; } };
|
14 | }
|
15 | Object.defineProperty(o, k2, desc);
|
16 | }) : (function(o, m, k, k2) {
|
17 | if (k2 === undefined) k2 = k;
|
18 | o[k2] = m[k];
|
19 | }));
|
20 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
21 | Object.defineProperty(o, "default", { enumerable: true, value: v });
|
22 | }) : function(o, v) {
|
23 | o["default"] = v;
|
24 | });
|
25 | var __importStar = (this && this.__importStar) || function (mod) {
|
26 | if (mod && mod.__esModule) return mod;
|
27 | var result = {};
|
28 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
29 | __setModuleDefault(result, mod);
|
30 | return result;
|
31 | };
|
32 | Object.defineProperty(exports, "__esModule", { value: true });
|
33 | exports.AngularWebpackPlugin = void 0;
|
34 | const assert_1 = require("assert");
|
35 | const ts = __importStar(require("typescript"));
|
36 | const ngcc_processor_1 = require("../ngcc_processor");
|
37 | const paths_plugin_1 = require("../paths-plugin");
|
38 | const resource_loader_1 = require("../resource_loader");
|
39 | const cache_1 = require("./cache");
|
40 | const diagnostics_1 = require("./diagnostics");
|
41 | const host_1 = require("./host");
|
42 | const paths_1 = require("./paths");
|
43 | const symbol_1 = require("./symbol");
|
44 | const system_1 = require("./system");
|
45 | const transformation_1 = require("./transformation");
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 | const DIAGNOSTICS_AFFECTED_THRESHOLD = 1;
|
52 | function initializeNgccProcessor(compiler, tsconfig, compilerNgccModule) {
|
53 | var _a, _b, _c;
|
54 | const { inputFileSystem, options: webpackOptions } = compiler;
|
55 | const mainFields = (_c = (_b = (_a = webpackOptions.resolve) === null || _a === void 0 ? void 0 : _a.mainFields) === null || _b === void 0 ? void 0 : _b.flat()) !== null && _c !== void 0 ? _c : [];
|
56 | const errors = [];
|
57 | const warnings = [];
|
58 | const resolver = compiler.resolverFactory.get('normal', {
|
59 |
|
60 | cache: false,
|
61 | extensions: ['.json'],
|
62 | useSyncFileSystemCalls: true,
|
63 | });
|
64 |
|
65 |
|
66 |
|
67 | assert_1.strict.ok(compilerNgccModule, `'@angular/compiler-cli/ngcc' used prior to Webpack compilation.`);
|
68 | const processor = new ngcc_processor_1.NgccProcessor(compilerNgccModule, mainFields, warnings, errors, compiler.context, tsconfig, inputFileSystem, resolver);
|
69 | return { processor, errors, warnings };
|
70 | }
|
71 | const PLUGIN_NAME = 'angular-compiler';
|
72 | const compilationFileEmitters = new WeakMap();
|
73 | class AngularWebpackPlugin {
|
74 | constructor(options = {}) {
|
75 | this.fileDependencies = new Map();
|
76 | this.requiredFilesToEmit = new Set();
|
77 | this.requiredFilesToEmitCache = new Map();
|
78 | this.fileEmitHistory = new Map();
|
79 | this.pluginOptions = {
|
80 | emitClassMetadata: false,
|
81 | emitNgModuleScope: false,
|
82 | jitMode: false,
|
83 | fileReplacements: {},
|
84 | substitutions: {},
|
85 | directTemplateLoading: true,
|
86 | tsconfig: 'tsconfig.json',
|
87 | ...options,
|
88 | };
|
89 | }
|
90 | get compilerCli() {
|
91 |
|
92 |
|
93 |
|
94 | assert_1.strict.ok(this.compilerCliModule, `'@angular/compiler-cli' used prior to Webpack compilation.`);
|
95 | return this.compilerCliModule;
|
96 | }
|
97 | get options() {
|
98 | return this.pluginOptions;
|
99 | }
|
100 | apply(compiler) {
|
101 | const { NormalModuleReplacementPlugin, WebpackError, util } = compiler.webpack;
|
102 | this.webpackCreateHash = util.createHash;
|
103 |
|
104 | for (const [key, value] of Object.entries(this.pluginOptions.fileReplacements)) {
|
105 | new NormalModuleReplacementPlugin(new RegExp('^' + key.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&') + '$'), value).apply(compiler);
|
106 | }
|
107 |
|
108 | const pathsPlugin = new paths_plugin_1.TypeScriptPathsPlugin();
|
109 | compiler.hooks.afterResolvers.tap(PLUGIN_NAME, (compiler) => {
|
110 |
|
111 |
|
112 |
|
113 |
|
114 | compiler.resolverFactory.hooks.resolveOptions
|
115 | .for('normal')
|
116 | .tap(PLUGIN_NAME, (resolveOptions) => {
|
117 | var _a, _b;
|
118 | const originalMainFields = resolveOptions.mainFields;
|
119 | const ivyMainFields = (_a = originalMainFields === null || originalMainFields === void 0 ? void 0 : originalMainFields.flat().map((f) => `${f}_ivy_ngcc`)) !== null && _a !== void 0 ? _a : [];
|
120 | (_b = resolveOptions.plugins) !== null && _b !== void 0 ? _b : (resolveOptions.plugins = []);
|
121 | resolveOptions.plugins.push(pathsPlugin);
|
122 |
|
123 | return util.cleverMerge(resolveOptions, { mainFields: [...ivyMainFields, '...'] });
|
124 | });
|
125 | });
|
126 |
|
127 | compiler.hooks.beforeCompile.tapPromise(PLUGIN_NAME, () => this.initializeCompilerCli());
|
128 | const compilationState = { pathsPlugin };
|
129 | compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
|
130 | try {
|
131 | this.setupCompilation(compilation, compilationState);
|
132 | }
|
133 | catch (error) {
|
134 | compilation.errors.push(new WebpackError(`Failed to initialize Angular compilation - ${error instanceof Error ? error.message : error}`));
|
135 | }
|
136 | });
|
137 | }
|
138 | setupCompilation(compilation, state) {
|
139 | const compiler = compilation.compiler;
|
140 |
|
141 | const emitRegistration = this.registerWithCompilation(compilation);
|
142 | this.watchMode = compiler.watchMode;
|
143 |
|
144 | if (!this.webpackCache && compilation.options.cache) {
|
145 | this.webpackCache = compilation.getCache(PLUGIN_NAME);
|
146 | }
|
147 |
|
148 | if (!state.resourceLoader) {
|
149 | state.resourceLoader = new resource_loader_1.WebpackResourceLoader(this.watchMode);
|
150 | }
|
151 |
|
152 | if (!state.ngccProcessor) {
|
153 | const { processor, errors, warnings } = initializeNgccProcessor(compiler, this.pluginOptions.tsconfig, this.compilerNgccModule);
|
154 | processor.process();
|
155 | warnings.forEach((warning) => (0, diagnostics_1.addWarning)(compilation, warning));
|
156 | errors.forEach((error) => (0, diagnostics_1.addError)(compilation, error));
|
157 | state.ngccProcessor = processor;
|
158 | }
|
159 |
|
160 | const { compilerOptions, rootNames, errors } = this.loadConfiguration();
|
161 |
|
162 | const diagnosticsReporter = (0, diagnostics_1.createDiagnosticsReporter)(compilation, (diagnostic) => this.compilerCli.formatDiagnostics([diagnostic]));
|
163 | diagnosticsReporter(errors);
|
164 |
|
165 | state.pathsPlugin.update(compilerOptions);
|
166 |
|
167 | const system = (0, system_1.createWebpackSystem)(
|
168 |
|
169 | compiler.inputFileSystem, (0, paths_1.normalizePath)(compiler.context));
|
170 | const host = ts.createIncrementalCompilerHost(compilerOptions, system);
|
171 |
|
172 | let cache = this.sourceFileCache;
|
173 | let changedFiles;
|
174 | if (cache) {
|
175 | changedFiles = new Set();
|
176 | for (const changedFile of [...compiler.modifiedFiles, ...compiler.removedFiles]) {
|
177 | const normalizedChangedFile = (0, paths_1.normalizePath)(changedFile);
|
178 |
|
179 | this.fileDependencies.delete(normalizedChangedFile);
|
180 |
|
181 | cache.invalidate(normalizedChangedFile);
|
182 | changedFiles.add(normalizedChangedFile);
|
183 | }
|
184 | }
|
185 | else {
|
186 |
|
187 | cache = new cache_1.SourceFileCache();
|
188 |
|
189 | if (this.watchMode) {
|
190 | this.sourceFileCache = cache;
|
191 | }
|
192 | }
|
193 | (0, host_1.augmentHostWithCaching)(host, cache);
|
194 | const moduleResolutionCache = ts.createModuleResolutionCache(host.getCurrentDirectory(), host.getCanonicalFileName.bind(host), compilerOptions);
|
195 |
|
196 | (0, host_1.augmentHostWithDependencyCollection)(host, this.fileDependencies, moduleResolutionCache);
|
197 |
|
198 | (0, host_1.augmentHostWithNgcc)(host, state.ngccProcessor, moduleResolutionCache);
|
199 |
|
200 | state.resourceLoader.update(compilation, changedFiles);
|
201 | (0, host_1.augmentHostWithResources)(host, state.resourceLoader, {
|
202 | directTemplateLoading: this.pluginOptions.directTemplateLoading,
|
203 | inlineStyleFileExtension: this.pluginOptions.inlineStyleFileExtension,
|
204 | });
|
205 |
|
206 | (0, host_1.augmentHostWithReplacements)(host, this.pluginOptions.fileReplacements, moduleResolutionCache);
|
207 | (0, host_1.augmentHostWithSubstitutions)(host, this.pluginOptions.substitutions);
|
208 |
|
209 | const { fileEmitter, builder, internalFiles } = this.pluginOptions.jitMode
|
210 | ? this.updateJitProgram(compilerOptions, rootNames, host, diagnosticsReporter)
|
211 | : this.updateAotProgram(compilerOptions, rootNames, host, diagnosticsReporter, state.resourceLoader);
|
212 |
|
213 | const currentUnused = new Set();
|
214 | for (const sourceFile of builder.getSourceFiles()) {
|
215 | if (internalFiles === null || internalFiles === void 0 ? void 0 : internalFiles.has(sourceFile)) {
|
216 | continue;
|
217 | }
|
218 |
|
219 |
|
220 | compilation.fileDependencies.add((0, paths_1.externalizePath)(sourceFile.fileName));
|
221 |
|
222 |
|
223 | if (!sourceFile.isDeclarationFile) {
|
224 | currentUnused.add((0, paths_1.normalizePath)(sourceFile.fileName));
|
225 | }
|
226 | }
|
227 | compilation.hooks.finishModules.tapPromise(PLUGIN_NAME, async (modules) => {
|
228 | var _a, _b;
|
229 |
|
230 | await this.rebuildRequiredFiles(modules, compilation, fileEmitter);
|
231 |
|
232 | (_a = state.resourceLoader) === null || _a === void 0 ? void 0 : _a.clearParentCompilation();
|
233 |
|
234 | if (compilation.errors.length > 0) {
|
235 | return;
|
236 | }
|
237 | for (const webpackModule of modules) {
|
238 | const resource = webpackModule.resource;
|
239 | if (resource) {
|
240 | this.markResourceUsed((0, paths_1.normalizePath)(resource), currentUnused);
|
241 | }
|
242 | }
|
243 | for (const unused of currentUnused) {
|
244 | if ((_b = state.previousUnused) === null || _b === void 0 ? void 0 : _b.has(unused)) {
|
245 | continue;
|
246 | }
|
247 | (0, diagnostics_1.addWarning)(compilation, `${unused} is part of the TypeScript compilation but it's unused.\n` +
|
248 | `Add only entry points to the 'files' or 'include' properties in your tsconfig.`);
|
249 | }
|
250 | state.previousUnused = currentUnused;
|
251 | });
|
252 |
|
253 | emitRegistration.update(fileEmitter);
|
254 | }
|
255 | registerWithCompilation(compilation) {
|
256 | let fileEmitters = compilationFileEmitters.get(compilation);
|
257 | if (!fileEmitters) {
|
258 | fileEmitters = new symbol_1.FileEmitterCollection();
|
259 | compilationFileEmitters.set(compilation, fileEmitters);
|
260 | compilation.compiler.webpack.NormalModule.getCompilationHooks(compilation).loader.tap(PLUGIN_NAME, (loaderContext) => {
|
261 | loaderContext[symbol_1.AngularPluginSymbol] = fileEmitters;
|
262 | });
|
263 | }
|
264 | const emitRegistration = fileEmitters.register();
|
265 | return emitRegistration;
|
266 | }
|
267 | markResourceUsed(normalizedResourcePath, currentUnused) {
|
268 | if (!currentUnused.has(normalizedResourcePath)) {
|
269 | return;
|
270 | }
|
271 | currentUnused.delete(normalizedResourcePath);
|
272 | const dependencies = this.fileDependencies.get(normalizedResourcePath);
|
273 | if (!dependencies) {
|
274 | return;
|
275 | }
|
276 | for (const dependency of dependencies) {
|
277 | this.markResourceUsed((0, paths_1.normalizePath)(dependency), currentUnused);
|
278 | }
|
279 | }
|
280 | async rebuildRequiredFiles(modules, compilation, fileEmitter) {
|
281 | if (this.requiredFilesToEmit.size === 0) {
|
282 | return;
|
283 | }
|
284 | const filesToRebuild = new Set();
|
285 | for (const requiredFile of this.requiredFilesToEmit) {
|
286 | const history = await this.getFileEmitHistory(requiredFile);
|
287 | if (history) {
|
288 | const emitResult = await fileEmitter(requiredFile);
|
289 | if ((emitResult === null || emitResult === void 0 ? void 0 : emitResult.content) === undefined ||
|
290 | history.length !== emitResult.content.length ||
|
291 | emitResult.hash === undefined ||
|
292 | Buffer.compare(history.hash, emitResult.hash) !== 0) {
|
293 |
|
294 | this.requiredFilesToEmitCache.set(requiredFile, emitResult);
|
295 | filesToRebuild.add(requiredFile);
|
296 | }
|
297 | }
|
298 | else {
|
299 |
|
300 | filesToRebuild.add(requiredFile);
|
301 | }
|
302 | }
|
303 | if (filesToRebuild.size > 0) {
|
304 | const rebuild = (webpackModule) => new Promise((resolve) => compilation.rebuildModule(webpackModule, () => resolve()));
|
305 | const modulesToRebuild = [];
|
306 | for (const webpackModule of modules) {
|
307 | const resource = webpackModule.resource;
|
308 | if (resource && filesToRebuild.has((0, paths_1.normalizePath)(resource))) {
|
309 | modulesToRebuild.push(webpackModule);
|
310 | }
|
311 | }
|
312 | await Promise.all(modulesToRebuild.map((webpackModule) => rebuild(webpackModule)));
|
313 | }
|
314 | this.requiredFilesToEmit.clear();
|
315 | this.requiredFilesToEmitCache.clear();
|
316 | }
|
317 | loadConfiguration() {
|
318 | const { options: compilerOptions, rootNames, errors, } = this.compilerCli.readConfiguration(this.pluginOptions.tsconfig, this.pluginOptions.compilerOptions);
|
319 | compilerOptions.enableIvy = true;
|
320 | compilerOptions.noEmitOnError = false;
|
321 | compilerOptions.suppressOutputPathCheck = true;
|
322 | compilerOptions.outDir = undefined;
|
323 | compilerOptions.inlineSources = compilerOptions.sourceMap;
|
324 | compilerOptions.inlineSourceMap = false;
|
325 | compilerOptions.mapRoot = undefined;
|
326 | compilerOptions.sourceRoot = undefined;
|
327 | compilerOptions.allowEmptyCodegenFiles = false;
|
328 | compilerOptions.annotationsAs = 'decorators';
|
329 | compilerOptions.enableResourceInlining = false;
|
330 | return { compilerOptions, rootNames, errors };
|
331 | }
|
332 | updateAotProgram(compilerOptions, rootNames, host, diagnosticsReporter, resourceLoader) {
|
333 |
|
334 | const angularProgram = new this.compilerCli.NgtscProgram(rootNames, compilerOptions, host, this.ngtscNextProgram);
|
335 | const angularCompiler = angularProgram.compiler;
|
336 |
|
337 |
|
338 |
|
339 |
|
340 |
|
341 |
|
342 | const { ignoreForDiagnostics, ignoreForEmit } = angularCompiler;
|
343 |
|
344 |
|
345 | const typeScriptProgram = angularProgram.getTsProgram();
|
346 | (0, host_1.augmentProgramWithVersioning)(typeScriptProgram);
|
347 | let builder;
|
348 | if (this.watchMode) {
|
349 | builder = this.builder = ts.createEmitAndSemanticDiagnosticsBuilderProgram(typeScriptProgram, host, this.builder);
|
350 | this.ngtscNextProgram = angularProgram;
|
351 | }
|
352 | else {
|
353 |
|
354 |
|
355 | builder = ts.createAbstractBuilder(typeScriptProgram, host);
|
356 | }
|
357 |
|
358 | const affectedFiles = new Set();
|
359 |
|
360 | if ('getSemanticDiagnosticsOfNextAffectedFile' in builder) {
|
361 |
|
362 | while (true) {
|
363 | const result = builder.getSemanticDiagnosticsOfNextAffectedFile(undefined, (sourceFile) => {
|
364 |
|
365 |
|
366 |
|
367 |
|
368 |
|
369 | if (ignoreForDiagnostics.has(sourceFile) &&
|
370 | sourceFile.fileName.endsWith('.ngtypecheck.ts')) {
|
371 |
|
372 |
|
373 | const originalFilename = sourceFile.fileName.slice(0, -15) + '.ts';
|
374 | const originalSourceFile = builder.getSourceFile(originalFilename);
|
375 | if (originalSourceFile) {
|
376 | affectedFiles.add(originalSourceFile);
|
377 | }
|
378 | return true;
|
379 | }
|
380 | return false;
|
381 | });
|
382 | if (!result) {
|
383 | break;
|
384 | }
|
385 | affectedFiles.add(result.affected);
|
386 | }
|
387 | }
|
388 |
|
389 | const diagnostics = [
|
390 | ...angularCompiler.getOptionDiagnostics(),
|
391 | ...builder.getOptionsDiagnostics(),
|
392 | ...builder.getGlobalDiagnostics(),
|
393 | ];
|
394 | diagnosticsReporter(diagnostics);
|
395 |
|
396 | for (const sourceFile of builder.getSourceFiles()) {
|
397 | if (!ignoreForDiagnostics.has(sourceFile)) {
|
398 | diagnosticsReporter(builder.getSyntacticDiagnostics(sourceFile));
|
399 | diagnosticsReporter(builder.getSemanticDiagnostics(sourceFile));
|
400 | }
|
401 | }
|
402 | const transformers = (0, transformation_1.createAotTransformers)(builder, this.pluginOptions);
|
403 | const getDependencies = (sourceFile) => {
|
404 | const dependencies = [];
|
405 | for (const resourcePath of angularCompiler.getResourceDependencies(sourceFile)) {
|
406 | dependencies.push(resourcePath,
|
407 |
|
408 | ...resourceLoader.getResourceDependencies(resourcePath));
|
409 | }
|
410 | return dependencies;
|
411 | };
|
412 |
|
413 |
|
414 | const pendingAnalysis = angularCompiler
|
415 | .analyzeAsync()
|
416 | .then(() => {
|
417 | var _a;
|
418 | this.requiredFilesToEmit.clear();
|
419 | for (const sourceFile of builder.getSourceFiles()) {
|
420 | if (sourceFile.isDeclarationFile) {
|
421 | continue;
|
422 | }
|
423 |
|
424 | if (!ignoreForEmit.has(sourceFile) &&
|
425 | !angularCompiler.incrementalDriver.safeToSkipEmit(sourceFile)) {
|
426 | this.requiredFilesToEmit.add((0, paths_1.normalizePath)(sourceFile.fileName));
|
427 |
|
428 | if (!ignoreForDiagnostics.has(sourceFile)) {
|
429 | affectedFiles.add(sourceFile);
|
430 | }
|
431 | }
|
432 | else if (this.sourceFileCache &&
|
433 | !affectedFiles.has(sourceFile) &&
|
434 | !ignoreForDiagnostics.has(sourceFile)) {
|
435 |
|
436 | const angularDiagnostics = this.sourceFileCache.getAngularDiagnostics(sourceFile);
|
437 | if (angularDiagnostics) {
|
438 | diagnosticsReporter(angularDiagnostics);
|
439 | }
|
440 | }
|
441 | }
|
442 |
|
443 | const OptimizeFor = this.compilerCli.OptimizeFor;
|
444 | const optimizeDiagnosticsFor = affectedFiles.size <= DIAGNOSTICS_AFFECTED_THRESHOLD
|
445 | ? OptimizeFor.SingleFile
|
446 | : OptimizeFor.WholeProgram;
|
447 | for (const affectedFile of affectedFiles) {
|
448 | const angularDiagnostics = angularCompiler.getDiagnosticsForFile(affectedFile, optimizeDiagnosticsFor);
|
449 | diagnosticsReporter(angularDiagnostics);
|
450 | (_a = this.sourceFileCache) === null || _a === void 0 ? void 0 : _a.updateAngularDiagnostics(affectedFile, angularDiagnostics);
|
451 | }
|
452 | return {
|
453 | emitter: this.createFileEmitter(builder, (0, transformation_1.mergeTransformers)(angularCompiler.prepareEmit().transformers, transformers), getDependencies, (sourceFile) => {
|
454 | this.requiredFilesToEmit.delete((0, paths_1.normalizePath)(sourceFile.fileName));
|
455 | angularCompiler.incrementalDriver.recordSuccessfulEmit(sourceFile);
|
456 | }),
|
457 | };
|
458 | })
|
459 | .catch((err) => ({ errorMessage: err instanceof Error ? err.message : `${err}` }));
|
460 | const analyzingFileEmitter = async (file) => {
|
461 | const analysis = await pendingAnalysis;
|
462 | if ('errorMessage' in analysis) {
|
463 | throw new Error(analysis.errorMessage);
|
464 | }
|
465 | return analysis.emitter(file);
|
466 | };
|
467 | return {
|
468 | fileEmitter: analyzingFileEmitter,
|
469 | builder,
|
470 | internalFiles: ignoreForEmit,
|
471 | };
|
472 | }
|
473 | updateJitProgram(compilerOptions, rootNames, host, diagnosticsReporter) {
|
474 | let builder;
|
475 | if (this.watchMode) {
|
476 | builder = this.builder = ts.createEmitAndSemanticDiagnosticsBuilderProgram(rootNames, compilerOptions, host, this.builder);
|
477 | }
|
478 | else {
|
479 |
|
480 |
|
481 | builder = ts.createAbstractBuilder(rootNames, compilerOptions, host);
|
482 | }
|
483 | const diagnostics = [
|
484 | ...builder.getOptionsDiagnostics(),
|
485 | ...builder.getGlobalDiagnostics(),
|
486 | ...builder.getSyntacticDiagnostics(),
|
487 |
|
488 | ...builder.getSemanticDiagnostics(),
|
489 | ];
|
490 | diagnosticsReporter(diagnostics);
|
491 | const transformers = (0, transformation_1.createJitTransformers)(builder, this.compilerCli, this.pluginOptions);
|
492 | return {
|
493 | fileEmitter: this.createFileEmitter(builder, transformers, () => []),
|
494 | builder,
|
495 | internalFiles: undefined,
|
496 | };
|
497 | }
|
498 | createFileEmitter(program, transformers = {}, getExtraDependencies, onAfterEmit) {
|
499 | return async (file) => {
|
500 | const filePath = (0, paths_1.normalizePath)(file);
|
501 | if (this.requiredFilesToEmitCache.has(filePath)) {
|
502 | return this.requiredFilesToEmitCache.get(filePath);
|
503 | }
|
504 | const sourceFile = program.getSourceFile(filePath);
|
505 | if (!sourceFile) {
|
506 | return undefined;
|
507 | }
|
508 | let content;
|
509 | let map;
|
510 | program.emit(sourceFile, (filename, data) => {
|
511 | if (filename.endsWith('.map')) {
|
512 | map = data;
|
513 | }
|
514 | else if (filename.endsWith('.js')) {
|
515 | content = data;
|
516 | }
|
517 | }, undefined, undefined, transformers);
|
518 | onAfterEmit === null || onAfterEmit === void 0 ? void 0 : onAfterEmit(sourceFile);
|
519 |
|
520 | const hash = content ? (await this.addFileEmitHistory(filePath, content)).hash : undefined;
|
521 | const dependencies = [
|
522 | ...(this.fileDependencies.get(filePath) || []),
|
523 | ...getExtraDependencies(sourceFile),
|
524 | ].map(paths_1.externalizePath);
|
525 | return { content, map, dependencies, hash };
|
526 | };
|
527 | }
|
528 | async initializeCompilerCli() {
|
529 | if (this.compilerCliModule) {
|
530 | return;
|
531 | }
|
532 |
|
533 |
|
534 |
|
535 |
|
536 |
|
537 |
|
538 |
|
539 | this.compilerCliModule = await new Function(`return import('@angular/compiler-cli');`)();
|
540 | this.compilerNgccModule = await new Function(`return import('@angular/compiler-cli/ngcc');`)();
|
541 | }
|
542 | async addFileEmitHistory(filePath, content) {
|
543 | assert_1.strict.ok(this.webpackCreateHash, 'File emitter is used prior to Webpack compilation');
|
544 | const historyData = {
|
545 | length: content.length,
|
546 | hash: this.webpackCreateHash('xxhash64').update(content).digest(),
|
547 | };
|
548 | if (this.webpackCache) {
|
549 | const history = await this.getFileEmitHistory(filePath);
|
550 | if (!history || Buffer.compare(history.hash, historyData.hash) !== 0) {
|
551 |
|
552 | await this.webpackCache.storePromise(filePath, null, historyData);
|
553 | }
|
554 | }
|
555 | else if (this.watchMode) {
|
556 |
|
557 | this.fileEmitHistory.set(filePath, historyData);
|
558 | }
|
559 | return historyData;
|
560 | }
|
561 | async getFileEmitHistory(filePath) {
|
562 | return this.webpackCache
|
563 | ? this.webpackCache.getPromise(filePath, null)
|
564 | : this.fileEmitHistory.get(filePath);
|
565 | }
|
566 | }
|
567 | exports.AngularWebpackPlugin = AngularWebpackPlugin;
|