8000 fix(@ngtools/webpack): handle promise rejection during Angular progra… · angular-robot/angular-cli@ceaef08 · GitHub
[go: up one dir, main page]

Skip to content

Commit ceaef08

Browse files
alan-agius4filipesilva
authored andcommitted
fix(@ngtools/webpack): handle promise rejection during Angular program analyzes
Currently, when `analyzeAsync` promise is rejected, the build fails with an `UnhandledPromiseRejectionWarning`. Example: ``` (node:69086) UnhandledPromiseRejectionWarning: Error: Cannot use a JavaScript or TypeScript file (/Users/error-testing/src/app/app.component.ts) in a component's styleUrls or templateUrl. at WebpackResourceLoader._compile (/Users/error-testing/node_modules/@ngtools/webpack/src/resource_loader.js:107:19) at WebpackResourceLoader.get (/Users/error-testing/node_modules/@ngtools/webpack/src/resource_loader.js:266:44) at Object.resourceHost.readResource (/Users/error-testing/node_modules/@ngtools/webpack/src/ivy/host.js:48:35) at AdapterResourceLoader.preload (file:///Users/error-testing/node_modules/@angular/compiler-cli/bundles/index.js:12177:31) at resolveStyleUrl (file:///Users/error-testing/node_modules/@angular/compiler-cli/bundles/index.js:9593:36) at file:///Users/error-testing/node_modules/@angular/compiler-cli/bundles/index.js:9621:47 at Array.map (<anonymous>) at ComponentDecoratorHandler.preanalyze (file:///Users/error-testing/node_modules/@angular/compiler-cli/bundles/index.js:9621:29) at TraitCompiler.analyzeClass (file:///Users/error-testing/node_modules/@angular/compiler-cli/bundles/index.js:6647:39) at visit2 (file:///Users/error-testing/node_modules/@angular/compiler-cli/bundles/index.js:6494:14) ``` With this change we handle such error and also hide stacktraces ``` ./src/app/app.module.ts - Error: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js): Error: Cannot use a JavaScript or TypeScript file (/Users/error-testing/src/app/app.component.ts) in a component's styleUrls or templateUrl. at /Users/error-testing/node_modules/@ngtools/webpack/src/ivy/loader.js:75:34 at processTicksAndRejections (internal/process/task_queues.js:95:5) ``` (cherry picked from commit 10d4ede)
1 parent 1441af7 commit ceaef08

File tree

2 files changed

+65
-60
lines changed

2 files changed

+65
-60
lines changed

packages/ngtools/webpack/src/ivy/loader.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ export function angularWebpackLoader(this: LoaderContext<unknown>, content: stri
6565
callback(undefined, resultContent, resultMap);
6666
})
6767
.catch((err) => {
68-
callback(err);
68+
// The below is needed to hide stacktraces from users.
69+
const message = err instanceof Error ? err.message : err;
70+
callback(new Error(message));
6971
});
7072
}
7173

packages/ngtools/webpack/src/ivy/plugin.ts

Lines changed: 62 additions & 59 deletions
< 579F td data-grid-cell-id="diff-9c7ca60aad39fc0d92fc425a1e82ce3aa951179305575e44816323d1f57d110c-597-589-1" data-selected="false" role="gridcell" style="background-color:var(--diffBlob-deletionNum-bgColor, var(--diffBlob-deletion-bgColor-num));text-align:center" tabindex="-1" valign="top" class="focusable-grid-cell diff-line-number position-relative left-side">
Original file line numberDiff line numberDiff line change
@@ -553,74 +553,77 @@ export class AngularWebpackPlugin {
553553

554554
// Required to support asynchronous resource loading
555555
// Must be done before creating transformers or getting template diagnostics
556-
const pendingAnalysis = angularCompiler.analyzeAsync().then(() => {
557-
this.requiredFilesToEmit.clear();
556+
const pendingAnalysis = angularCompiler
557+
.analyzeAsync()
558+
.then(() => {
559+
this.requiredFilesToEmit.clear();
558560

559-
for (const sourceFile of builder.getSourceFiles()) {
560-
if (sourceFile.isDeclarationFile) {
561-
continue;
562-
}
561+
for (const sourceFile of builder.getSourceFiles()) {
562+
if (sourceFile.isDeclarationFile) {
563+
continue;
564+
}
563565

564-
// Collect sources that are required to be emitted
565-
if (
566-
!ignoreForEmit.has(sourceFile) &&
567-
!angularCompiler.incrementalDriver.safeToSkipEmit(sourceFile)
568-
) {
569-
this.requiredFilesToEmit.add(normalizePath(sourceFile.fileName));
566+
// Collect sources that are required to be emitted
567+
if (
568+
!ignoreForEmit.has(sourceFile) &&
569+
!angularCompiler.incrementalDriver.safeToSkipEmit(sourceFile)
570+
) {
571+
this.requiredFilesToEmit.add(normalizePath(sourceFile.fileName));
570572

571-
// If required to emit, diagnostics may have also changed
572-
if (!ignoreForDiagnostics.has(sourceFile)) {
573-
affectedFiles.add(sourceFile);
574-
}
575-
} else if (
576-
this.sourceFileCache &&
577-
!affectedFiles.has(sourceFile) &&
578-
!ignoreForDiagnostics.has(sourceFile)
579-
) {
580-
// Use cached Angular diagnostics for unchanged and unaffected files
581-
const angularDiagnostics = this.sourceFileCache.getAngularDiagnostics(sourceFile);
582-
if (angularDiagnostics) {
583-
diagnosticsReporter(angularDiagnostics);
573+
// If required to emit, diagnostics may have also changed
574+
if (!ignoreForDiagnostics.has(sourceFile)) {
575+
affectedFiles.add(sourceFile);
576+
}
577+
} else if (
578+
this.sourceFileCache &&
579+
!affectedFiles.has(sourceFile) &&
580+
!ignoreForDiagnostics.has(sourceFile)
581+
) {
582+
// Use cached Angular diagnostics for unchanged and unaffected files
583+
const angularDiagnostics = this.sourceFileCache.getAngularDiagnostics(sourceFile);
584+
if (angularDiagnostics) {
585+
diagnosticsReporter(angularDiagnostics);
586+
}
584587
}
585588
}
586-
}
587589

588-
// Temporary workaround during transition to ESM-only @angular/compiler-cli
589-
// TODO_ESM: This workaround should be removed prior to the final release of v13
590-
// and replaced with only `this.compilerCli.OptimizeFor`.
591-
const OptimizeFor =
592-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
593-
(this.compilerCli as any).OptimizeFor ??
594-
require('@angular/compiler-cli/src/ngtsc/typecheck/api').OptimizeFor;
595-
596-
// Collect new Angular diagnostics for files affected by changes
597-
const optimizeDiagnosticsFor =
598-
affectedFiles.size <= DIAGNOSTICS_AFFECTED_THRESHOLD
599-
? OptimizeFor.SingleFile
600-
: OptimizeFor.WholeProgram;
601-
for (const affectedFile of affectedFiles) {
602-
const angularDiagnostics = angularCompiler.getDiagnosticsForFile(
603-
affectedFile,
604-
optimizeDiagnosticsFor,
605-
);
606-
diagnosticsReporter(angularDiagnostics);
607-
this.sourceFileCache?.updateAngularDiagnostics(affectedFile, angularDiagnostics);
608-
}
590+
// Collect new Angular diagnostics for files affected by changes
591+
const OptimizeFor = this.compilerCli.OptimizeFor;
592+
const optimizeDiagnosticsFor =
593+
affectedFiles.size <= DIAGNOSTICS_AFFECTED_THRESHOLD
594+
? OptimizeFor.SingleFile
595+
: OptimizeFor.WholeProgram;
596+
for (const affectedFile of affectedFiles) {
597+
const angularDiagnostics = angularCompiler.getDiagnosticsForFile(
598+
affectedFile,
599+
optimizeDiagnosticsFor,
600+
);
601+
diagnosticsReporter(angularDiagnostics);
602+
this.sourceFileCache?.updateAngularDiagnostics(affectedFile, angularDiagnostics);
603+
}
604+
605+
return {
606+
emitter: this.createFileEmitter(
607+
builder,
608+
mergeTransformers(angularCompiler.prepareEmit().transformers, transformers),
609+
getDependencies,
610+
(sourceFile) => {
611+
this.requiredFilesToEmit.delete(normalizePath(sourceFile.fileName));
612+
angularCompiler.incrementalDriver.recordSuccessfulEmit(sourceFile);
613+
},
614+
),
615+
};
616+
})
617+
.catch((err) => ({ errorMessage: err instanceof Error ? err.message : `${err}` }));
609618

610-
return this.createFileEmitter(
611-
builder,
612-
mergeTransformers(angularCompiler.prepareEmit().transformers, transformers),
613-
getDependencies,
614-
(sourceFile) => {
615-
this.requiredFilesToEmit.delete(normalizePath(sourceFile.fileName));
616-
angularCompiler.incrementalDriver.recordSuccessfulEmit(sourceFile);
617-
},
618-
);
619-
});
620619
const analyzingFileEmitter: FileEmitter = async (file) => {
621-
const innerFileEmitter = await pendingAnalysis;
620+
const analysis = await pendingAnalysis;
621+
622+
if ('errorMessage' in analysis) {
623+
throw new Error(analysis.errorMessage);
624+
}
622625

623-
return innerFileEmitter(file);
626+
return analysis.emitter(file);
624627
};
625628

626629
return {

0 commit comments

Comments
 (0)
0