@angular-devkit/build-angular 15.0.0 → 15.1.0-next.0
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/package.json +15 -16
- package/src/builders/browser/index.js +0 -9
- package/src/builders/browser-esbuild/angular-compilation.d.ts +26 -0
- package/src/builders/browser-esbuild/angular-compilation.js +172 -0
- package/src/builders/browser-esbuild/angular-host.d.ts +25 -0
- package/src/builders/browser-esbuild/angular-host.js +61 -0
- package/src/builders/browser-esbuild/compiler-plugin.js +56 -236
- package/src/builders/browser-esbuild/javascript-transformer-worker.d.ts +18 -0
- package/src/builders/browser-esbuild/javascript-transformer-worker.js +70 -0
- package/src/builders/browser-esbuild/javascript-transformer.d.ts +48 -0
- package/src/builders/browser-esbuild/javascript-transformer.js +95 -0
- package/src/builders/browser-esbuild/sass-plugin.js +30 -30
- package/src/builders/server/index.js +44 -10
- package/src/builders/server/schema.d.ts +28 -0
- package/src/builders/server/schema.json +46 -0
- package/src/sass/rebasing-importer.d.ts +12 -6
- package/src/sass/rebasing-importer.js +227 -62
- package/src/utils/normalize-asset-patterns.js +4 -5
- package/src/webpack/utils/stats.js +10 -1
|
@@ -34,16 +34,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
34
34
|
};
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.createCompilerPlugin = exports.SourceFileCache = void 0;
|
|
37
|
-
const core_1 = require("@babel/core");
|
|
38
37
|
const assert = __importStar(require("node:assert"));
|
|
39
|
-
const fs = __importStar(require("node:fs/promises"));
|
|
40
38
|
const node_os_1 = require("node:os");
|
|
41
39
|
const path = __importStar(require("node:path"));
|
|
42
40
|
const node_url_1 = require("node:url");
|
|
43
41
|
const typescript_1 = __importDefault(require("typescript"));
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
const
|
|
42
|
+
const environment_options_1 = require("../../utils/environment-options");
|
|
43
|
+
const angular_compilation_1 = require("./angular-compilation");
|
|
44
|
+
const javascript_transformer_1 = require("./javascript-transformer");
|
|
47
45
|
const profiling_1 = require("./profiling");
|
|
48
46
|
const stylesheets_1 = require("./stylesheets");
|
|
49
47
|
/**
|
|
@@ -51,11 +49,11 @@ const stylesheets_1 = require("./stylesheets");
|
|
|
51
49
|
* Related information is a subset of a full TypeScript Diagnostic and also used for diagnostic
|
|
52
50
|
* notes associated with the main Diagnostic.
|
|
53
51
|
* @param info The TypeScript diagnostic relative information to convert.
|
|
54
|
-
* @param host A TypeScript FormatDiagnosticsHost instance to use during conversion.
|
|
55
52
|
* @returns An esbuild diagnostic message as a PartialMessage object
|
|
56
53
|
*/
|
|
57
|
-
function convertTypeScriptDiagnosticInfo(info,
|
|
58
|
-
|
|
54
|
+
function convertTypeScriptDiagnosticInfo(info, textPrefix) {
|
|
55
|
+
const newLine = (0, node_os_1.platform)() === 'win32' ? '\r\n' : '\n';
|
|
56
|
+
let text = typescript_1.default.flattenDiagnosticMessageText(info.messageText, newLine);
|
|
59
57
|
if (textPrefix) {
|
|
60
58
|
text = textPrefix + text;
|
|
61
59
|
}
|
|
@@ -87,10 +85,9 @@ function convertTypeScriptDiagnosticInfo(info, host, textPrefix) {
|
|
|
87
85
|
/**
|
|
88
86
|
* Converts a TypeScript Diagnostic message into an esbuild compatible message object.
|
|
89
87
|
* @param diagnostic The TypeScript diagnostic to convert.
|
|
90
|
-
* @param host A TypeScript FormatDiagnosticsHost instance to use during conversion.
|
|
91
88
|
* @returns An esbuild diagnostic message as a PartialMessage object
|
|
92
89
|
*/
|
|
93
|
-
function convertTypeScriptDiagnostic(diagnostic
|
|
90
|
+
function convertTypeScriptDiagnostic(diagnostic) {
|
|
94
91
|
var _a;
|
|
95
92
|
let codePrefix = 'TS';
|
|
96
93
|
let code = `${diagnostic.code}`;
|
|
@@ -100,12 +97,12 @@ function convertTypeScriptDiagnostic(diagnostic, host) {
|
|
|
100
97
|
code = code.slice(3);
|
|
101
98
|
}
|
|
102
99
|
const message = {
|
|
103
|
-
...convertTypeScriptDiagnosticInfo(diagnostic,
|
|
100
|
+
...convertTypeScriptDiagnosticInfo(diagnostic, `${codePrefix}${code}: `),
|
|
104
101
|
// Store original diagnostic for reference if needed downstream
|
|
105
102
|
detail: diagnostic,
|
|
106
103
|
};
|
|
107
104
|
if ((_a = diagnostic.relatedInformation) === null || _a === void 0 ? void 0 : _a.length) {
|
|
108
|
-
message.notes = diagnostic.relatedInformation.map((info) => convertTypeScriptDiagnosticInfo(info
|
|
105
|
+
message.notes = diagnostic.relatedInformation.map((info) => convertTypeScriptDiagnosticInfo(info));
|
|
109
106
|
}
|
|
110
107
|
return message;
|
|
111
108
|
}
|
|
@@ -133,7 +130,6 @@ class SourceFileCache extends Map {
|
|
|
133
130
|
}
|
|
134
131
|
}
|
|
135
132
|
exports.SourceFileCache = SourceFileCache;
|
|
136
|
-
// This is a non-watch version of the compiler code from `@ngtools/webpack` augmented for esbuild
|
|
137
133
|
// eslint-disable-next-line max-lines-per-function
|
|
138
134
|
function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
139
135
|
return {
|
|
@@ -143,11 +139,9 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
143
139
|
var _a, _b;
|
|
144
140
|
var _c;
|
|
145
141
|
let setupWarnings;
|
|
146
|
-
//
|
|
147
|
-
|
|
148
|
-
const { GLOBAL_DEFS_FOR_TERSER_WITH_AOT,
|
|
149
|
-
// Temporary deep import for transformer support
|
|
150
|
-
const { mergeTransformers, replaceBootstrap, } = require('@ngtools/webpack/src/ivy/transformation');
|
|
142
|
+
// Initialize a worker pool for JavaScript transformations
|
|
143
|
+
const javascriptTransformer = new javascript_transformer_1.JavaScriptTransformer(pluginOptions, environment_options_1.maxWorkers);
|
|
144
|
+
const { GLOBAL_DEFS_FOR_TERSER_WITH_AOT, readConfiguration } = await angular_compilation_1.AngularCompilation.loadCompilerCli();
|
|
151
145
|
// Setup defines based on the values provided by the Angular compiler-cli
|
|
152
146
|
(_a = (_c = build.initialOptions).define) !== null && _a !== void 0 ? _a : (_c.define = {});
|
|
153
147
|
for (const [key, value] of Object.entries(GLOBAL_DEFS_FOR_TERSER_WITH_AOT)) {
|
|
@@ -198,11 +192,9 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
198
192
|
let fileEmitter;
|
|
199
193
|
// The stylesheet resources from component stylesheets that will be added to the build results output files
|
|
200
194
|
let stylesheetResourceFiles;
|
|
201
|
-
let
|
|
202
|
-
let previousAngularProgram;
|
|
203
|
-
const babelDataCache = new Map();
|
|
204
|
-
const diagnosticCache = new WeakMap();
|
|
195
|
+
let compilation;
|
|
205
196
|
build.onStart(async () => {
|
|
197
|
+
var _a;
|
|
206
198
|
const result = {
|
|
207
199
|
warnings: setupWarnings,
|
|
208
200
|
};
|
|
@@ -212,111 +204,50 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
212
204
|
(0, profiling_1.resetCumulativeDurations)();
|
|
213
205
|
// Reset stylesheet resource output files
|
|
214
206
|
stylesheetResourceFiles = [];
|
|
215
|
-
// Create
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
const { contents, resourceFiles, errors, warnings } = await (0, stylesheets_1.bundleStylesheetText)(data, {
|
|
243
|
-
resolvePath: path.dirname(file),
|
|
244
|
-
virtualName: file,
|
|
245
|
-
}, styleOptions);
|
|
246
|
-
((_b = result.errors) !== null && _b !== void 0 ? _b : (result.errors = [])).push(...errors);
|
|
247
|
-
((_c = result.warnings) !== null && _c !== void 0 ? _c : (result.warnings = [])).push(...warnings);
|
|
248
|
-
stylesheetResourceFiles.push(...resourceFiles);
|
|
249
|
-
return { content: contents };
|
|
207
|
+
// Create Angular compiler host options
|
|
208
|
+
const hostOptions = {
|
|
209
|
+
fileReplacements: pluginOptions.fileReplacements,
|
|
210
|
+
modifiedFiles: (_a = pluginOptions.sourceFileCache) === null || _a === void 0 ? void 0 : _a.modifiedFiles,
|
|
211
|
+
sourceFileCache: pluginOptions.sourceFileCache,
|
|
212
|
+
async transformStylesheet(data, containingFile, stylesheetFile) {
|
|
213
|
+
var _a, _b;
|
|
214
|
+
// Stylesheet file only exists for external stylesheets
|
|
215
|
+
const filename = stylesheetFile !== null && stylesheetFile !== void 0 ? stylesheetFile : containingFile;
|
|
216
|
+
// Temporary workaround for lack of virtual file support in the Sass plugin.
|
|
217
|
+
// External Sass stylesheets are transformed using the file instead of the already read content.
|
|
218
|
+
let stylesheetResult;
|
|
219
|
+
if (filename.endsWith('.scss') || filename.endsWith('.sass')) {
|
|
220
|
+
stylesheetResult = await (0, stylesheets_1.bundleStylesheetFile)(filename, styleOptions);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
stylesheetResult = await (0, stylesheets_1.bundleStylesheetText)(data, {
|
|
224
|
+
resolvePath: path.dirname(filename),
|
|
225
|
+
virtualName: filename,
|
|
226
|
+
}, styleOptions);
|
|
227
|
+
}
|
|
228
|
+
const { contents, resourceFiles, errors, warnings } = stylesheetResult;
|
|
229
|
+
((_a = result.errors) !== null && _a !== void 0 ? _a : (result.errors = [])).push(...errors);
|
|
230
|
+
((_b = result.warnings) !== null && _b !== void 0 ? _b : (result.warnings = [])).push(...warnings);
|
|
231
|
+
stylesheetResourceFiles.push(...resourceFiles);
|
|
232
|
+
return contents;
|
|
233
|
+
},
|
|
250
234
|
};
|
|
251
|
-
//
|
|
252
|
-
|
|
253
|
-
//
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
// Augment TypeScript Host with source file caching if provided
|
|
258
|
-
if (pluginOptions.sourceFileCache) {
|
|
259
|
-
augmentHostWithCaching(host, pluginOptions.sourceFileCache);
|
|
260
|
-
// Allow the AOT compiler to request the set of changed templates and styles
|
|
261
|
-
host.getModifiedResourceFiles = function () {
|
|
262
|
-
var _a;
|
|
263
|
-
return (_a = pluginOptions.sourceFileCache) === null || _a === void 0 ? void 0 : _a.modifiedFiles;
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
// Create the Angular specific program that contains the Angular compiler
|
|
267
|
-
const angularProgram = (0, profiling_1.profileSync)('NG_CREATE_PROGRAM', () => new NgtscProgram(rootNames, compilerOptions, host, previousAngularProgram));
|
|
268
|
-
previousAngularProgram = angularProgram;
|
|
269
|
-
const angularCompiler = angularProgram.compiler;
|
|
270
|
-
const typeScriptProgram = angularProgram.getTsProgram();
|
|
271
|
-
augmentProgramWithVersioning(typeScriptProgram);
|
|
272
|
-
const builder = typescript_1.default.createEmitAndSemanticDiagnosticsBuilderProgram(typeScriptProgram, host, previousBuilder, configurationDiagnostics);
|
|
273
|
-
previousBuilder = builder;
|
|
274
|
-
await (0, profiling_1.profileAsync)('NG_ANALYZE_PROGRAM', () => angularCompiler.analyzeAsync());
|
|
275
|
-
const affectedFiles = (0, profiling_1.profileSync)('NG_FIND_AFFECTED', () => findAffectedFiles(builder, angularCompiler));
|
|
235
|
+
// Create new compilation if first build; otherwise, use existing for rebuilds
|
|
236
|
+
compilation !== null && compilation !== void 0 ? compilation : (compilation = new angular_compilation_1.AngularCompilation());
|
|
237
|
+
// Initialize the Angular compilation for the current build.
|
|
238
|
+
// In watch mode, previous build state will be reused.
|
|
239
|
+
const { affectedFiles } = await compilation.initialize(rootNames, compilerOptions, hostOptions, configurationDiagnostics);
|
|
240
|
+
// Clear affected files from the cache (if present)
|
|
276
241
|
if (pluginOptions.sourceFileCache) {
|
|
277
242
|
for (const affected of affectedFiles) {
|
|
278
243
|
pluginOptions.sourceFileCache.typeScriptFileCache.delete((0, node_url_1.pathToFileURL)(affected.fileName).href);
|
|
279
244
|
}
|
|
280
245
|
}
|
|
281
|
-
function* collectDiagnostics() {
|
|
282
|
-
// Collect program level diagnostics
|
|
283
|
-
yield* builder.getConfigFileParsingDiagnostics();
|
|
284
|
-
yield* angularCompiler.getOptionDiagnostics();
|
|
285
|
-
yield* builder.getOptionsDiagnostics();
|
|
286
|
-
yield* builder.getGlobalDiagnostics();
|
|
287
|
-
// Collect source file specific diagnostics
|
|
288
|
-
const optimizeFor = affectedFiles.size > 1 ? OptimizeFor.WholeProgram : OptimizeFor.SingleFile;
|
|
289
|
-
for (const sourceFile of builder.getSourceFiles()) {
|
|
290
|
-
if (angularCompiler.ignoreForDiagnostics.has(sourceFile)) {
|
|
291
|
-
continue;
|
|
292
|
-
}
|
|
293
|
-
// TypeScript will use cached diagnostics for files that have not been
|
|
294
|
-
// changed or affected for this build when using incremental building.
|
|
295
|
-
yield* (0, profiling_1.profileSync)('NG_DIAGNOSTICS_SYNTACTIC', () => builder.getSyntacticDiagnostics(sourceFile), true);
|
|
296
|
-
yield* (0, profiling_1.profileSync)('NG_DIAGNOSTICS_SEMANTIC', () => builder.getSemanticDiagnostics(sourceFile), true);
|
|
297
|
-
// Declaration files cannot have template diagnostics
|
|
298
|
-
if (sourceFile.isDeclarationFile) {
|
|
299
|
-
continue;
|
|
300
|
-
}
|
|
301
|
-
// Only request Angular template diagnostics for affected files to avoid
|
|
302
|
-
// overhead of template diagnostics for unchanged files.
|
|
303
|
-
if (affectedFiles.has(sourceFile)) {
|
|
304
|
-
const angularDiagnostics = (0, profiling_1.profileSync)('NG_DIAGNOSTICS_TEMPLATE', () => angularCompiler.getDiagnosticsForFile(sourceFile, optimizeFor), true);
|
|
305
|
-
diagnosticCache.set(sourceFile, angularDiagnostics);
|
|
306
|
-
yield* angularDiagnostics;
|
|
307
|
-
}
|
|
308
|
-
else {
|
|
309
|
-
const angularDiagnostics = diagnosticCache.get(sourceFile);
|
|
310
|
-
if (angularDiagnostics) {
|
|
311
|
-
yield* angularDiagnostics;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
246
|
(0, profiling_1.profileSync)('NG_DIAGNOSTICS_TOTAL', () => {
|
|
317
247
|
var _a, _b;
|
|
318
|
-
|
|
319
|
-
|
|
248
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
249
|
+
for (const diagnostic of compilation.collectDiagnostics()) {
|
|
250
|
+
const message = convertTypeScriptDiagnostic(diagnostic);
|
|
320
251
|
if (diagnostic.category === typescript_1.default.DiagnosticCategory.Error) {
|
|
321
252
|
((_a = result.errors) !== null && _a !== void 0 ? _a : (result.errors = [])).push(message);
|
|
322
253
|
}
|
|
@@ -325,13 +256,11 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
325
256
|
}
|
|
326
257
|
}
|
|
327
258
|
});
|
|
328
|
-
fileEmitter = createFileEmitter(
|
|
329
|
-
before: [replaceBootstrap(() => builder.getProgram().getTypeChecker())],
|
|
330
|
-
}), (sourceFile) => angularCompiler.incrementalCompilation.recordSuccessfulEmit(sourceFile));
|
|
259
|
+
fileEmitter = compilation.createFileEmitter();
|
|
331
260
|
return result;
|
|
332
261
|
});
|
|
333
262
|
build.onLoad({ filter: compilerOptions.allowJs ? /\.[cm]?[jt]sx?$/ : /\.[cm]?tsx?$/ }, (args) => (0, profiling_1.profileAsync)('NG_EMIT_TS*', async () => {
|
|
334
|
-
var _a, _b, _c, _d, _e
|
|
263
|
+
var _a, _b, _c, _d, _e;
|
|
335
264
|
assert.ok(fileEmitter, 'Invalid plugin execution order');
|
|
336
265
|
const request = (_b = (_a = pluginOptions.fileReplacements) === null || _a === void 0 ? void 0 : _a[args.path]) !== null && _b !== void 0 ? _b : args.path;
|
|
337
266
|
// The filename is currently used as a cache key. Since the cache is memory only,
|
|
@@ -341,7 +270,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
341
270
|
let contents = (_c = pluginOptions.sourceFileCache) === null || _c === void 0 ? void 0 : _c.typeScriptFileCache.get((0, node_url_1.pathToFileURL)(request).href);
|
|
342
271
|
if (contents === undefined) {
|
|
343
272
|
const typescriptResult = await fileEmitter(request);
|
|
344
|
-
if (!typescriptResult) {
|
|
273
|
+
if (!(typescriptResult === null || typescriptResult === void 0 ? void 0 : typescriptResult.content)) {
|
|
345
274
|
// No TS result indicates the file is not part of the TypeScript program.
|
|
346
275
|
// If allowJs is enabled and the file is JS then defer to the next load hook.
|
|
347
276
|
if (compilerOptions.allowJs && /\.[cm]?js$/.test(request)) {
|
|
@@ -354,18 +283,8 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
354
283
|
],
|
|
355
284
|
};
|
|
356
285
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
// the options cannot change and do not need to be represented in the key. If the
|
|
360
|
-
// cache is later stored to disk, then the options that affect transform output
|
|
361
|
-
// would need to be added to the key as well.
|
|
362
|
-
contents = babelDataCache.get(data);
|
|
363
|
-
if (contents === undefined) {
|
|
364
|
-
const transformedData = await transformWithBabel(request, data, pluginOptions);
|
|
365
|
-
contents = Buffer.from(transformedData, 'utf-8');
|
|
366
|
-
babelDataCache.set(data, contents);
|
|
367
|
-
}
|
|
368
|
-
(_f = pluginOptions.sourceFileCache) === null || _f === void 0 ? void 0 : _f.typeScriptFileCache.set((0, node_url_1.pathToFileURL)(request).href, contents);
|
|
286
|
+
contents = await javascriptTransformer.transformData(request, typescriptResult.content, true /* skipLinker */);
|
|
287
|
+
(_e = pluginOptions.sourceFileCache) === null || _e === void 0 ? void 0 : _e.typeScriptFileCache.set((0, node_url_1.pathToFileURL)(request).href, contents);
|
|
369
288
|
}
|
|
370
289
|
return {
|
|
371
290
|
contents,
|
|
@@ -380,9 +299,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
380
299
|
// would need to be added to the key as well as a check for any change of content.
|
|
381
300
|
let contents = (_a = pluginOptions.sourceFileCache) === null || _a === void 0 ? void 0 : _a.babelFileCache.get(args.path);
|
|
382
301
|
if (contents === undefined) {
|
|
383
|
-
|
|
384
|
-
const transformedData = await transformWithBabel(args.path, data, pluginOptions);
|
|
385
|
-
contents = Buffer.from(transformedData, 'utf-8');
|
|
302
|
+
contents = await javascriptTransformer.transformFile(args.path);
|
|
386
303
|
(_b = pluginOptions.sourceFileCache) === null || _b === void 0 ? void 0 : _b.babelFileCache.set(args.path, contents);
|
|
387
304
|
}
|
|
388
305
|
return {
|
|
@@ -401,103 +318,6 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
401
318
|
};
|
|
402
319
|
}
|
|
403
320
|
exports.createCompilerPlugin = createCompilerPlugin;
|
|
404
|
-
function createFileEmitter(program, transformers = {}, onAfterEmit) {
|
|
405
|
-
return async (file) => {
|
|
406
|
-
const sourceFile = program.getSourceFile(file);
|
|
407
|
-
if (!sourceFile) {
|
|
408
|
-
return undefined;
|
|
409
|
-
}
|
|
410
|
-
let content;
|
|
411
|
-
program.emit(sourceFile, (filename, data) => {
|
|
412
|
-
if (/\.[cm]?js$/.test(filename)) {
|
|
413
|
-
content = data;
|
|
414
|
-
}
|
|
415
|
-
}, undefined /* cancellationToken */, undefined /* emitOnlyDtsFiles */, transformers);
|
|
416
|
-
onAfterEmit === null || onAfterEmit === void 0 ? void 0 : onAfterEmit(sourceFile);
|
|
417
|
-
return { content, dependencies: [] };
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
async function transformWithBabel(filename, data, pluginOptions) {
|
|
421
|
-
var _a;
|
|
422
|
-
const forceAsyncTransformation = !/[\\/][_f]?esm2015[\\/]/.test(filename) && /async\s+function\s*\*/.test(data);
|
|
423
|
-
const shouldLink = await (0, webpack_loader_1.requiresLinking)(filename, data);
|
|
424
|
-
const useInputSourcemap = pluginOptions.sourcemap &&
|
|
425
|
-
(!!pluginOptions.thirdPartySourcemaps || !/[\\/]node_modules[\\/]/.test(filename));
|
|
426
|
-
// If no additional transformations are needed, return the data directly
|
|
427
|
-
if (!forceAsyncTransformation && !pluginOptions.advancedOptimizations && !shouldLink) {
|
|
428
|
-
// Strip sourcemaps if they should not be used
|
|
429
|
-
return useInputSourcemap ? data : data.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, '');
|
|
430
|
-
}
|
|
431
|
-
const angularPackage = /[\\/]node_modules[\\/]@angular[\\/]/.test(filename);
|
|
432
|
-
const linkerPluginCreator = shouldLink
|
|
433
|
-
? (await (0, load_esm_1.loadEsmModule)('@angular/compiler-cli/linker/babel')).createEs2015LinkerPlugin
|
|
434
|
-
: undefined;
|
|
435
|
-
const result = await (0, core_1.transformAsync)(data, {
|
|
436
|
-
filename,
|
|
437
|
-
inputSourceMap: (useInputSourcemap ? undefined : false),
|
|
438
|
-
sourceMaps: pluginOptions.sourcemap ? 'inline' : false,
|
|
439
|
-
compact: false,
|
|
440
|
-
configFile: false,
|
|
441
|
-
babelrc: false,
|
|
442
|
-
browserslistConfigFile: false,
|
|
443
|
-
plugins: [],
|
|
444
|
-
presets: [
|
|
445
|
-
[
|
|
446
|
-
application_1.default,
|
|
447
|
-
{
|
|
448
|
-
angularLinker: {
|
|
449
|
-
shouldLink,
|
|
450
|
-
jitMode: false,
|
|
451
|
-
linkerPluginCreator,
|
|
452
|
-
},
|
|
453
|
-
forceAsyncTransformation,
|
|
454
|
-
optimize: pluginOptions.advancedOptimizations && {
|
|
455
|
-
looseEnums: angularPackage,
|
|
456
|
-
pureTopLevel: angularPackage,
|
|
457
|
-
},
|
|
458
|
-
},
|
|
459
|
-
],
|
|
460
|
-
],
|
|
461
|
-
});
|
|
462
|
-
return (_a = result === null || result === void 0 ? void 0 : result.code) !== null && _a !== void 0 ? _a : data;
|
|
463
|
-
}
|
|
464
|
-
function findAffectedFiles(builder, { ignoreForDiagnostics, ignoreForEmit, incrementalCompilation }) {
|
|
465
|
-
const affectedFiles = new Set();
|
|
466
|
-
// eslint-disable-next-line no-constant-condition
|
|
467
|
-
while (true) {
|
|
468
|
-
const result = builder.getSemanticDiagnosticsOfNextAffectedFile(undefined, (sourceFile) => {
|
|
469
|
-
// If the affected file is a TTC shim, add the shim's original source file.
|
|
470
|
-
// This ensures that changes that affect TTC are typechecked even when the changes
|
|
471
|
-
// are otherwise unrelated from a TS perspective and do not result in Ivy codegen changes.
|
|
472
|
-
// For example, changing @Input property types of a directive used in another component's
|
|
473
|
-
// template.
|
|
474
|
-
// A TTC shim is a file that has been ignored for diagnostics and has a filename ending in `.ngtypecheck.ts`.
|
|
475
|
-
if (ignoreForDiagnostics.has(sourceFile) && sourceFile.fileName.endsWith('.ngtypecheck.ts')) {
|
|
476
|
-
// This file name conversion relies on internal compiler logic and should be converted
|
|
477
|
-
// to an official method when available. 15 is length of `.ngtypecheck.ts`
|
|
478
|
-
const originalFilename = sourceFile.fileName.slice(0, -15) + '.ts';
|
|
479
|
-
const originalSourceFile = builder.getSourceFile(originalFilename);
|
|
480
|
-
if (originalSourceFile) {
|
|
481
|
-
affectedFiles.add(originalSourceFile);
|
|
482
|
-
}
|
|
483
|
-
return true;
|
|
484
|
-
}
|
|
485
|
-
return false;
|
|
486
|
-
});
|
|
487
|
-
if (!result) {
|
|
488
|
-
break;
|
|
489
|
-
}
|
|
490
|
-
affectedFiles.add(result.affected);
|
|
491
|
-
}
|
|
492
|
-
// A file is also affected if the Angular compiler requires it to be emitted
|
|
493
|
-
for (const sourceFile of builder.getSourceFiles()) {
|
|
494
|
-
if (ignoreForEmit.has(sourceFile) || incrementalCompilation.safeToSkipEmit(sourceFile)) {
|
|
495
|
-
continue;
|
|
496
|
-
}
|
|
497
|
-
affectedFiles.add(sourceFile);
|
|
498
|
-
}
|
|
499
|
-
return affectedFiles;
|
|
500
|
-
}
|
|
501
321
|
function createMissingFileError(request, original, root) {
|
|
502
322
|
const error = {
|
|
503
323
|
text: `File '${path.relative(root, request)}' is missing from the TypeScript compilation.`,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
interface JavaScriptTransformRequest {
|
|
9
|
+
filename: string;
|
|
10
|
+
data: string;
|
|
11
|
+
sourcemap: boolean;
|
|
12
|
+
thirdPartySourcemaps: boolean;
|
|
13
|
+
advancedOptimizations: boolean;
|
|
14
|
+
forceAsyncTransformation?: boolean;
|
|
15
|
+
skipLinker: boolean;
|
|
16
|
+
}
|
|
17
|
+
export default function transformJavaScript(request: JavaScriptTransformRequest): Promise<Uint8Array>;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
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 core_1 = require("@babel/core");
|
|
14
|
+
const promises_1 = require("node:fs/promises");
|
|
15
|
+
const application_1 = __importDefault(require("../../babel/presets/application"));
|
|
16
|
+
const webpack_loader_1 = require("../../babel/webpack-loader");
|
|
17
|
+
const load_esm_1 = require("../../utils/load-esm");
|
|
18
|
+
async function transformJavaScript(request) {
|
|
19
|
+
var _a;
|
|
20
|
+
(_a = request.data) !== null && _a !== void 0 ? _a : (request.data = await (0, promises_1.readFile)(request.filename, 'utf-8'));
|
|
21
|
+
const transformedData = await transformWithBabel(request);
|
|
22
|
+
return Buffer.from(transformedData, 'utf-8');
|
|
23
|
+
}
|
|
24
|
+
exports.default = transformJavaScript;
|
|
25
|
+
let linkerPluginCreator;
|
|
26
|
+
async function transformWithBabel({ filename, data, ...options }) {
|
|
27
|
+
var _a, _b;
|
|
28
|
+
const forceAsyncTransformation = (_a = options.forceAsyncTransformation) !== null && _a !== void 0 ? _a : (!/[\\/][_f]?esm2015[\\/]/.test(filename) && /async\s+function\s*\*/.test(data));
|
|
29
|
+
const shouldLink = !options.skipLinker && (await (0, webpack_loader_1.requiresLinking)(filename, data));
|
|
30
|
+
const useInputSourcemap = options.sourcemap &&
|
|
31
|
+
(!!options.thirdPartySourcemaps || !/[\\/]node_modules[\\/]/.test(filename));
|
|
32
|
+
// If no additional transformations are needed, return the data directly
|
|
33
|
+
if (!forceAsyncTransformation && !options.advancedOptimizations && !shouldLink) {
|
|
34
|
+
// Strip sourcemaps if they should not be used
|
|
35
|
+
return useInputSourcemap ? data : data.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, '');
|
|
36
|
+
}
|
|
37
|
+
const angularPackage = /[\\/]node_modules[\\/]@angular[\\/]/.test(filename);
|
|
38
|
+
// Lazy load the linker plugin only when linking is required
|
|
39
|
+
if (shouldLink) {
|
|
40
|
+
linkerPluginCreator !== null && linkerPluginCreator !== void 0 ? linkerPluginCreator : (linkerPluginCreator = (await (0, load_esm_1.loadEsmModule)('@angular/compiler-cli/linker/babel')).createEs2015LinkerPlugin);
|
|
41
|
+
}
|
|
42
|
+
const result = await (0, core_1.transformAsync)(data, {
|
|
43
|
+
filename,
|
|
44
|
+
inputSourceMap: (useInputSourcemap ? undefined : false),
|
|
45
|
+
sourceMaps: options.sourcemap ? 'inline' : false,
|
|
46
|
+
compact: false,
|
|
47
|
+
configFile: false,
|
|
48
|
+
babelrc: false,
|
|
49
|
+
browserslistConfigFile: false,
|
|
50
|
+
plugins: [],
|
|
51
|
+
presets: [
|
|
52
|
+
[
|
|
53
|
+
application_1.default,
|
|
54
|
+
{
|
|
55
|
+
angularLinker: linkerPluginCreator && {
|
|
56
|
+
shouldLink,
|
|
57
|
+
jitMode: false,
|
|
58
|
+
linkerPluginCreator,
|
|
59
|
+
},
|
|
60
|
+
forceAsyncTransformation,
|
|
61
|
+
optimize: options.advancedOptimizations && {
|
|
62
|
+
looseEnums: angularPackage,
|
|
63
|
+
pureTopLevel: angularPackage,
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
],
|
|
68
|
+
});
|
|
69
|
+
return (_b = result === null || result === void 0 ? void 0 : result.code) !== null && _b !== void 0 ? _b : data;
|
|
70
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Transformation options that should apply to all transformed files and data.
|
|
10
|
+
*/
|
|
11
|
+
export interface JavaScriptTransformerOptions {
|
|
12
|
+
sourcemap: boolean;
|
|
13
|
+
thirdPartySourcemaps?: boolean;
|
|
14
|
+
advancedOptimizations?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A class that performs transformation of JavaScript files and raw data.
|
|
18
|
+
* A worker pool is used to distribute the transformation actions and allow
|
|
19
|
+
* parallel processing. Transformation behavior is based on the filename and
|
|
20
|
+
* data. Transformations may include: async downleveling, Angular linking,
|
|
21
|
+
* and advanced optimizations.
|
|
22
|
+
*/
|
|
23
|
+
export declare class JavaScriptTransformer {
|
|
24
|
+
#private;
|
|
25
|
+
private options;
|
|
26
|
+
constructor(options: JavaScriptTransformerOptions, maxThreads?: number);
|
|
27
|
+
/**
|
|
28
|
+
* Performs JavaScript transformations on a file from the filesystem.
|
|
29
|
+
* If no transformations are required, the data for the original file will be returned.
|
|
30
|
+
* @param filename The full path to the file.
|
|
31
|
+
* @returns A promise that resolves to a UTF-8 encoded Uint8Array containing the result.
|
|
32
|
+
*/
|
|
33
|
+
transformFile(filename: string): Promise<Uint8Array>;
|
|
34
|
+
/**
|
|
35
|
+
* Performs JavaScript transformations on the provided data of a file. The file does not need
|
|
36
|
+
* to exist on the filesystem.
|
|
37
|
+
* @param filename The full path of the file represented by the data.
|
|
38
|
+
* @param data The data of the file that should be transformed.
|
|
39
|
+
* @param skipLinker If true, bypass all Angular linker processing; if false, attempt linking.
|
|
40
|
+
* @returns A promise that resolves to a UTF-8 encoded Uint8Array containing the result.
|
|
41
|
+
*/
|
|
42
|
+
transformData(filename: string, data: string, skipLinker: boolean): Promise<Uint8Array>;
|
|
43
|
+
/**
|
|
44
|
+
* Stops all active transformation tasks and shuts down all workers.
|
|
45
|
+
* @returns A void promise that resolves when closing is complete.
|
|
46
|
+
*/
|
|
47
|
+
close(): Promise<void>;
|
|
48
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
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 __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
10
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
11
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
12
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
13
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
14
|
+
};
|
|
15
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
16
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
17
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
18
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
19
|
+
};
|
|
20
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
21
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
|
+
};
|
|
23
|
+
var _JavaScriptTransformer_workerPool;
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.JavaScriptTransformer = void 0;
|
|
26
|
+
const piscina_1 = __importDefault(require("piscina"));
|
|
27
|
+
/**
|
|
28
|
+
* A class that performs transformation of JavaScript files and raw data.
|
|
29
|
+
* A worker pool is used to distribute the transformation actions and allow
|
|
30
|
+
* parallel processing. Transformation behavior is based on the filename and
|
|
31
|
+
* data. Transformations may include: async downleveling, Angular linking,
|
|
32
|
+
* and advanced optimizations.
|
|
33
|
+
*/
|
|
34
|
+
class JavaScriptTransformer {
|
|
35
|
+
constructor(options, maxThreads) {
|
|
36
|
+
this.options = options;
|
|
37
|
+
_JavaScriptTransformer_workerPool.set(this, void 0);
|
|
38
|
+
__classPrivateFieldSet(this, _JavaScriptTransformer_workerPool, new piscina_1.default({
|
|
39
|
+
filename: require.resolve('./javascript-transformer-worker'),
|
|
40
|
+
maxThreads,
|
|
41
|
+
}), "f");
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Performs JavaScript transformations on a file from the filesystem.
|
|
45
|
+
* If no transformations are required, the data for the original file will be returned.
|
|
46
|
+
* @param filename The full path to the file.
|
|
47
|
+
* @returns A promise that resolves to a UTF-8 encoded Uint8Array containing the result.
|
|
48
|
+
*/
|
|
49
|
+
transformFile(filename) {
|
|
50
|
+
// Always send the request to a worker. Files are almost always from node modules which measn
|
|
51
|
+
// they may need linking. The data is also not yet available to perform most transformation checks.
|
|
52
|
+
return __classPrivateFieldGet(this, _JavaScriptTransformer_workerPool, "f").run({
|
|
53
|
+
filename,
|
|
54
|
+
...this.options,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Performs JavaScript transformations on the provided data of a file. The file does not need
|
|
59
|
+
* to exist on the filesystem.
|
|
60
|
+
* @param filename The full path of the file represented by the data.
|
|
61
|
+
* @param data The data of the file that should be transformed.
|
|
62
|
+
* @param skipLinker If true, bypass all Angular linker processing; if false, attempt linking.
|
|
63
|
+
* @returns A promise that resolves to a UTF-8 encoded Uint8Array containing the result.
|
|
64
|
+
*/
|
|
65
|
+
async transformData(filename, data, skipLinker) {
|
|
66
|
+
// Perform a quick test to determine if the data needs any transformations.
|
|
67
|
+
// This allows directly returning the data without the worker communication overhead.
|
|
68
|
+
let forceAsyncTransformation;
|
|
69
|
+
if (skipLinker && !this.options.advancedOptimizations) {
|
|
70
|
+
// If the linker is being skipped and no optimizations are needed, only async transformation is left.
|
|
71
|
+
// This checks for async generator functions. All other async transformation is handled by esbuild.
|
|
72
|
+
forceAsyncTransformation = data.includes('async') && /async\s+function\s*\*/.test(data);
|
|
73
|
+
if (!forceAsyncTransformation) {
|
|
74
|
+
return Buffer.from(data, 'utf-8');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return __classPrivateFieldGet(this, _JavaScriptTransformer_workerPool, "f").run({
|
|
78
|
+
filename,
|
|
79
|
+
data,
|
|
80
|
+
// Send the async check result if present to avoid rechecking in the worker
|
|
81
|
+
forceAsyncTransformation,
|
|
82
|
+
skipLinker,
|
|
83
|
+
...this.options,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Stops all active transformation tasks and shuts down all workers.
|
|
88
|
+
* @returns A void promise that resolves when closing is complete.
|
|
89
|
+
*/
|
|
90
|
+
close() {
|
|
91
|
+
return __classPrivateFieldGet(this, _JavaScriptTransformer_workerPool, "f").destroy();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.JavaScriptTransformer = JavaScriptTransformer;
|
|
95
|
+
_JavaScriptTransformer_workerPool = new WeakMap();
|