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 | */
|
---|
9 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
---|
10 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
---|
11 | };
|
---|
12 | Object.defineProperty(exports, "__esModule", { value: true });
|
---|
13 | const remapping_1 = __importDefault(require("@ampproject/remapping"));
|
---|
14 | const linker_1 = require("@angular/compiler-cli/linker");
|
---|
15 | const babel_loader_1 = require("babel-loader");
|
---|
16 | const typescript_1 = require("typescript");
|
---|
17 | function requiresLinking(path, source) {
|
---|
18 | // @angular/core and @angular/compiler will cause false positives
|
---|
19 | // Also, TypeScript files do not require linking
|
---|
20 | if (/[\\\/]@angular[\\\/](?:compiler|core)|\.tsx?$/.test(path)) {
|
---|
21 | return false;
|
---|
22 | }
|
---|
23 | return linker_1.needsLinking(path, source);
|
---|
24 | }
|
---|
25 | exports.default = babel_loader_1.custom(() => {
|
---|
26 | const baseOptions = Object.freeze({
|
---|
27 | babelrc: false,
|
---|
28 | configFile: false,
|
---|
29 | compact: false,
|
---|
30 | cacheCompression: false,
|
---|
31 | sourceType: 'unambiguous',
|
---|
32 | inputSourceMap: false,
|
---|
33 | });
|
---|
34 | return {
|
---|
35 | async customOptions({ i18n, scriptTarget, aot, optimize, ...rawOptions }, { source }) {
|
---|
36 | var _a, _b;
|
---|
37 | // Must process file if plugins are added
|
---|
38 | let shouldProcess = Array.isArray(rawOptions.plugins) && rawOptions.plugins.length > 0;
|
---|
39 | const customOptions = {
|
---|
40 | forceAsyncTransformation: false,
|
---|
41 | forceES5: false,
|
---|
42 | angularLinker: undefined,
|
---|
43 | i18n: undefined,
|
---|
44 | };
|
---|
45 | // Analyze file for linking
|
---|
46 | if (await requiresLinking(this.resourcePath, source)) {
|
---|
47 | customOptions.angularLinker = {
|
---|
48 | shouldLink: true,
|
---|
49 | jitMode: aot !== true,
|
---|
50 | };
|
---|
51 | shouldProcess = true;
|
---|
52 | }
|
---|
53 | // Analyze for ES target processing
|
---|
54 | const esTarget = scriptTarget;
|
---|
55 | if (esTarget !== undefined) {
|
---|
56 | if (esTarget < typescript_1.ScriptTarget.ES2015) {
|
---|
57 | // TypeScript files will have already been downlevelled
|
---|
58 | customOptions.forceES5 = !/\.tsx?$/.test(this.resourcePath);
|
---|
59 | }
|
---|
60 | else if (esTarget >= typescript_1.ScriptTarget.ES2017 || /\.[cm]?js$/.test(this.resourcePath)) {
|
---|
61 | // Application code (TS files) will only contain native async if target is ES2017+.
|
---|
62 | // However, third-party libraries can regardless of the target option.
|
---|
63 | // APF packages with code in [f]esm2015 directories is downlevelled to ES2015 and
|
---|
64 | // will not have native async.
|
---|
65 | customOptions.forceAsyncTransformation =
|
---|
66 | !/[\\\/][_f]?esm2015[\\\/]/.test(this.resourcePath) && source.includes('async');
|
---|
67 | }
|
---|
68 | shouldProcess || (shouldProcess = customOptions.forceAsyncTransformation || customOptions.forceES5);
|
---|
69 | }
|
---|
70 | // Analyze for i18n inlining
|
---|
71 | if (i18n &&
|
---|
72 | !/[\\\/]@angular[\\\/](?:compiler|localize)/.test(this.resourcePath) &&
|
---|
73 | source.includes('$localize')) {
|
---|
74 | customOptions.i18n = i18n;
|
---|
75 | shouldProcess = true;
|
---|
76 | }
|
---|
77 | if (optimize) {
|
---|
78 | const angularPackage = /[\\\/]node_modules[\\\/]@angular[\\\/]/.test(this.resourcePath);
|
---|
79 | customOptions.optimize = {
|
---|
80 | // Angular packages provide additional tested side effects guarantees and can use
|
---|
81 | // otherwise unsafe optimizations.
|
---|
82 | looseEnums: angularPackage,
|
---|
83 | pureTopLevel: angularPackage,
|
---|
84 | // JavaScript modules that are marked as side effect free are considered to have
|
---|
85 | // no decorators that contain non-local effects.
|
---|
86 | wrapDecorators: !!((_b = (_a = this._module) === null || _a === void 0 ? void 0 : _a.factoryMeta) === null || _b === void 0 ? void 0 : _b.sideEffectFree),
|
---|
87 | };
|
---|
88 | shouldProcess = true;
|
---|
89 | }
|
---|
90 | // Add provided loader options to default base options
|
---|
91 | const loaderOptions = {
|
---|
92 | ...baseOptions,
|
---|
93 | ...rawOptions,
|
---|
94 | cacheIdentifier: JSON.stringify({
|
---|
95 | buildAngular: require('../../package.json').version,
|
---|
96 | customOptions,
|
---|
97 | baseOptions,
|
---|
98 | rawOptions,
|
---|
99 | }),
|
---|
100 | };
|
---|
101 | // Skip babel processing if no actions are needed
|
---|
102 | if (!shouldProcess) {
|
---|
103 | // Force the current file to be ignored
|
---|
104 | loaderOptions.ignore = [() => true];
|
---|
105 | }
|
---|
106 | return { custom: customOptions, loader: loaderOptions };
|
---|
107 | },
|
---|
108 | config(configuration, { customOptions }) {
|
---|
109 | var _a;
|
---|
110 | const plugins = (_a = configuration.options.plugins) !== null && _a !== void 0 ? _a : [];
|
---|
111 | if (customOptions.optimize) {
|
---|
112 | if (customOptions.optimize.pureTopLevel) {
|
---|
113 | plugins.push(require('./plugins/pure-toplevel-functions').default);
|
---|
114 | }
|
---|
115 | plugins.push(require('./plugins/elide-angular-metadata').default, [
|
---|
116 | require('./plugins/adjust-typescript-enums').default,
|
---|
117 | { loose: customOptions.optimize.looseEnums },
|
---|
118 | ], [
|
---|
119 | require('./plugins/adjust-static-class-members').default,
|
---|
120 | { wrapDecorators: customOptions.optimize.wrapDecorators },
|
---|
121 | ]);
|
---|
122 | }
|
---|
123 | return {
|
---|
124 | ...configuration.options,
|
---|
125 | // Using `false` disables babel from attempting to locate sourcemaps or process any inline maps.
|
---|
126 | // The babel types do not include the false option even though it is valid
|
---|
127 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
---|
128 | inputSourceMap: false,
|
---|
129 | plugins,
|
---|
130 | presets: [
|
---|
131 | ...(configuration.options.presets || []),
|
---|
132 | [
|
---|
133 | require('./presets/application').default,
|
---|
134 | {
|
---|
135 | ...customOptions,
|
---|
136 | diagnosticReporter: (type, message) => {
|
---|
137 | switch (type) {
|
---|
138 | case 'error':
|
---|
139 | this.emitError(message);
|
---|
140 | break;
|
---|
141 | case 'info':
|
---|
142 | // Webpack does not currently have an informational diagnostic
|
---|
143 | case 'warning':
|
---|
144 | this.emitWarning(message);
|
---|
145 | break;
|
---|
146 | }
|
---|
147 | },
|
---|
148 | },
|
---|
149 | ],
|
---|
150 | ],
|
---|
151 | };
|
---|
152 | },
|
---|
153 | result(result, { map: inputSourceMap }) {
|
---|
154 | if (result.map && inputSourceMap) {
|
---|
155 | // Merge the intermediate sourcemap generated by babel with the input source map.
|
---|
156 | // The casting is required due to slight differences in the types for babel and
|
---|
157 | // `@ampproject/remapping` source map objects but both are compatible with Webpack.
|
---|
158 | // This method for merging is used because it provides more accurate output
|
---|
159 | // and is faster while using less memory.
|
---|
160 | result.map = {
|
---|
161 | // Convert the SourceMap back to simple plain object.
|
---|
162 | // This is needed because otherwise code-coverage will fail with `don't know how to turn this value into a node`
|
---|
163 | // Which is throw by Babel when it is invoked again from `istanbul-lib-instrument`.
|
---|
164 | // https://github.com/babel/babel/blob/780aa48d2a34dc55f556843074b6aed45e7eabeb/packages/babel-types/src/converters/valueToNode.ts#L115-L130
|
---|
165 | ...remapping_1.default([result.map, inputSourceMap], () => null),
|
---|
166 | };
|
---|
167 | }
|
---|
168 | return result;
|
---|
169 | },
|
---|
170 | };
|
---|
171 | });
|
---|