@angular/build 21.0.0-next.4 → 21.0.0-next.6
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 +8 -8
- package/src/builders/karma/application_builder.js +5 -1
- package/src/builders/karma/coverage.js +1 -1
- package/src/builders/karma/find-tests.d.ts +1 -9
- package/src/builders/karma/find-tests.js +6 -106
- package/src/builders/unit-test/builder.js +20 -2
- package/src/builders/unit-test/options.d.ts +16 -2
- package/src/builders/unit-test/options.js +37 -4
- package/src/builders/unit-test/runners/karma/executor.js +26 -3
- package/src/builders/unit-test/runners/karma/index.js +1 -1
- package/src/builders/unit-test/runners/vitest/browser-provider.d.ts +4 -1
- package/src/builders/unit-test/runners/vitest/browser-provider.js +6 -2
- package/src/builders/unit-test/runners/vitest/build-options.js +6 -6
- package/src/builders/unit-test/runners/vitest/executor.js +30 -8
- package/src/builders/unit-test/runners/vitest/index.js +1 -1
- package/src/builders/unit-test/schema.d.ts +93 -13
- package/src/builders/unit-test/schema.js +12 -12
- package/src/builders/unit-test/schema.json +126 -33
- package/src/builders/unit-test/test-discovery.d.ts +25 -1
- package/src/builders/unit-test/test-discovery.js +194 -5
- package/src/tools/angular/transformers/jit-bootstrap-transformer.js +1 -1
- package/src/tools/angular/transformers/jit-resource-transformer.js +1 -1
- package/src/tools/babel/plugins/pure-toplevel-functions.d.ts +0 -1
- package/src/tools/babel/plugins/pure-toplevel-functions.js +21 -5
- package/src/tools/esbuild/angular/compiler-plugin.js +38 -14
- package/src/tools/esbuild/javascript-transformer-worker.js +2 -8
- package/src/tools/esbuild/stylesheets/less-language.js +2 -26
- package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.js +2 -1
- package/src/utils/normalize-cache.js +1 -1
- package/src/utils/server-rendering/utils.d.ts +1 -1
- package/src/utils/service-worker.d.ts +1 -1
|
@@ -141,7 +141,7 @@ function visitComponentMetadata(nodeFactory, node, styleReplacements, resourceIm
|
|
|
141
141
|
function createResourceImport(nodeFactory, url, resourceImportDeclarations) {
|
|
142
142
|
const urlLiteral = nodeFactory.createStringLiteral(url);
|
|
143
143
|
const importName = nodeFactory.createIdentifier(`__NG_CLI_RESOURCE__${resourceImportDeclarations.length}`);
|
|
144
|
-
resourceImportDeclarations.push(nodeFactory.createImportDeclaration(undefined, nodeFactory.createImportClause(
|
|
144
|
+
resourceImportDeclarations.push(nodeFactory.createImportDeclaration(undefined, nodeFactory.createImportClause(undefined, importName, undefined), urlLiteral));
|
|
145
145
|
return importName;
|
|
146
146
|
}
|
|
147
147
|
function getDecoratorOrigin(decorator, typeChecker) {
|
|
@@ -47,7 +47,11 @@ exports.default = default_1;
|
|
|
47
47
|
const helper_annotate_as_pure_1 = __importDefault(require("@babel/helper-annotate-as-pure"));
|
|
48
48
|
const tslib = __importStar(require("tslib"));
|
|
49
49
|
/**
|
|
50
|
-
* A
|
|
50
|
+
* A set of constructor names that are considered to be side-effect free.
|
|
51
|
+
*/
|
|
52
|
+
const sideEffectFreeConstructors = new Set(['InjectionToken']);
|
|
53
|
+
/**
|
|
54
|
+
* A set of TypeScript helper function names used by the helper name matcher utility function.
|
|
51
55
|
*/
|
|
52
56
|
const tslibHelpers = new Set(Object.keys(tslib).filter((h) => h.startsWith('__')));
|
|
53
57
|
/**
|
|
@@ -76,13 +80,16 @@ function isBabelHelperName(name) {
|
|
|
76
80
|
}
|
|
77
81
|
/**
|
|
78
82
|
* A babel plugin factory function for adding the PURE annotation to top-level new and call expressions.
|
|
79
|
-
*
|
|
80
83
|
* @returns A babel plugin object instance.
|
|
81
84
|
*/
|
|
82
85
|
function default_1() {
|
|
83
86
|
return {
|
|
84
87
|
visitor: {
|
|
85
|
-
CallExpression(path) {
|
|
88
|
+
CallExpression(path, state) {
|
|
89
|
+
const { topLevelSafeMode = false } = state.opts;
|
|
90
|
+
if (topLevelSafeMode) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
86
93
|
// If the expression has a function parent, it is not top-level
|
|
87
94
|
if (path.getFunctionParent()) {
|
|
88
95
|
return;
|
|
@@ -100,9 +107,18 @@ function default_1() {
|
|
|
100
107
|
}
|
|
101
108
|
(0, helper_annotate_as_pure_1.default)(path);
|
|
102
109
|
},
|
|
103
|
-
NewExpression(path) {
|
|
110
|
+
NewExpression(path, state) {
|
|
104
111
|
// If the expression has a function parent, it is not top-level
|
|
105
|
-
if (
|
|
112
|
+
if (path.getFunctionParent()) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const { topLevelSafeMode = false } = state.opts;
|
|
116
|
+
if (!topLevelSafeMode) {
|
|
117
|
+
(0, helper_annotate_as_pure_1.default)(path);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const callee = path.get('callee');
|
|
121
|
+
if (callee.isIdentifier() && sideEffectFreeConstructors.has(callee.node.name)) {
|
|
106
122
|
(0, helper_annotate_as_pure_1.default)(path);
|
|
107
123
|
}
|
|
108
124
|
},
|
|
@@ -46,6 +46,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
46
46
|
exports.createCompilerPlugin = createCompilerPlugin;
|
|
47
47
|
const node_assert_1 = __importDefault(require("node:assert"));
|
|
48
48
|
const node_crypto_1 = require("node:crypto");
|
|
49
|
+
const promises_1 = require("node:fs/promises");
|
|
49
50
|
const path = __importStar(require("node:path"));
|
|
50
51
|
const environment_options_1 = require("../../../utils/environment-options");
|
|
51
52
|
const compilation_1 = require("../../angular/compilation");
|
|
@@ -344,11 +345,21 @@ function createCompilerPlugin(pluginOptions, compilationOrFactory, stylesheetBun
|
|
|
344
345
|
if (!shouldTsIgnoreJs && isJS) {
|
|
345
346
|
return undefined;
|
|
346
347
|
}
|
|
348
|
+
const diangosticRoot = build.initialOptions.absWorkingDir ?? '';
|
|
349
|
+
// Evaluate whether the file requires the Angular compiler transpilation.
|
|
350
|
+
// If not, issue a warning but allow bundler to process the file (no type-checking).
|
|
351
|
+
const directContents = await (0, promises_1.readFile)(request, 'utf-8');
|
|
352
|
+
if (!requiresAngularCompiler(directContents)) {
|
|
353
|
+
return {
|
|
354
|
+
warnings: [createMissingFileDiagnostic(request, args.path, diangosticRoot, false)],
|
|
355
|
+
contents,
|
|
356
|
+
loader: 'ts',
|
|
357
|
+
resolveDir: path.dirname(request),
|
|
358
|
+
};
|
|
359
|
+
}
|
|
347
360
|
// Otherwise return an error
|
|
348
361
|
return {
|
|
349
|
-
errors: [
|
|
350
|
-
createMissingFileError(request, args.path, build.initialOptions.absWorkingDir ?? ''),
|
|
351
|
-
],
|
|
362
|
+
errors: [createMissingFileDiagnostic(request, args.path, diangosticRoot, true)],
|
|
352
363
|
};
|
|
353
364
|
}
|
|
354
365
|
else if (typeof contents === 'string' && (useTypeScriptTranspilation || isJS)) {
|
|
@@ -585,21 +596,34 @@ function bundleWebWorker(build, pluginOptions, workerFile) {
|
|
|
585
596
|
throw error;
|
|
586
597
|
}
|
|
587
598
|
}
|
|
588
|
-
function
|
|
599
|
+
function createMissingFileDiagnostic(request, original, root, angular) {
|
|
589
600
|
const relativeRequest = path.relative(root, request);
|
|
590
|
-
const
|
|
591
|
-
|
|
592
|
-
notes
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
601
|
+
const notes = [];
|
|
602
|
+
if (angular) {
|
|
603
|
+
notes.push({
|
|
604
|
+
text: `Files containing Angular metadata ('@Component'/'@Directive'/etc.) must be part of the TypeScript compilation.` +
|
|
605
|
+
` You can ensure the file is part of the TypeScript program via the 'files' or 'include' property.`,
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
else {
|
|
609
|
+
notes.push({
|
|
610
|
+
text: `The file will be bundled and included in the output but will not be type-checked at build time.` +
|
|
611
|
+
` To remove this message you can add the file to the TypeScript program via the 'files' or 'include' property.`,
|
|
612
|
+
});
|
|
613
|
+
}
|
|
598
614
|
const relativeOriginal = path.relative(root, original);
|
|
599
615
|
if (relativeRequest !== relativeOriginal) {
|
|
600
|
-
|
|
616
|
+
notes.push({
|
|
601
617
|
text: `File is requested from a file replacement of '${relativeOriginal}'.`,
|
|
602
618
|
});
|
|
603
619
|
}
|
|
604
|
-
|
|
620
|
+
const diagnostic = {
|
|
621
|
+
text: `File '${relativeRequest}' not found in TypeScript compilation.`,
|
|
622
|
+
notes,
|
|
623
|
+
};
|
|
624
|
+
return diagnostic;
|
|
625
|
+
}
|
|
626
|
+
const POTENTIAL_METADATA_REGEX = /@angular\/core|@Component|@Directive|@Injectable|@Pipe|@NgModule/;
|
|
627
|
+
function requiresAngularCompiler(contents) {
|
|
628
|
+
return POTENTIAL_METADATA_REGEX.test(contents);
|
|
605
629
|
}
|
|
@@ -84,16 +84,10 @@ async function transformWithBabel(filename, data, options) {
|
|
|
84
84
|
plugins.push(linkerPlugin);
|
|
85
85
|
}
|
|
86
86
|
if (options.advancedOptimizations) {
|
|
87
|
+
const { adjustStaticMembers, adjustTypeScriptEnums, elideAngularMetadata, markTopLevelPure } = await Promise.resolve().then(() => __importStar(require('../babel/plugins')));
|
|
87
88
|
const sideEffectFree = options.sideEffects === false;
|
|
88
89
|
const safeAngularPackage = sideEffectFree && /[\\/]node_modules[\\/]@angular[\\/]/.test(filename);
|
|
89
|
-
|
|
90
|
-
if (safeAngularPackage) {
|
|
91
|
-
plugins.push(markTopLevelPure);
|
|
92
|
-
}
|
|
93
|
-
plugins.push(elideAngularMetadata, adjustTypeScriptEnums, [
|
|
94
|
-
adjustStaticMembers,
|
|
95
|
-
{ wrapDecorators: sideEffectFree },
|
|
96
|
-
]);
|
|
90
|
+
plugins.push([markTopLevelPure, { topLevelSafeMode: !safeAngularPackage }], elideAngularMetadata, adjustTypeScriptEnums, [adjustStaticMembers, { wrapDecorators: sideEffectFree }]);
|
|
97
91
|
}
|
|
98
92
|
// If no additional transformations are needed, return the data directly
|
|
99
93
|
if (plugins.length === 0) {
|
|
@@ -55,11 +55,10 @@ exports.LessStylesheetLanguage = Object.freeze({
|
|
|
55
55
|
componentFilter: /^less;/,
|
|
56
56
|
fileFilter: /\.less$/,
|
|
57
57
|
process(data, file, _, options, build) {
|
|
58
|
-
return compileString(data, file, options, build.resolve.bind(build)
|
|
59
|
-
/* unsafeInlineJavaScript */ false);
|
|
58
|
+
return compileString(data, file, options, build.resolve.bind(build));
|
|
60
59
|
},
|
|
61
60
|
});
|
|
62
|
-
async function compileString(data, filename, options, resolver
|
|
61
|
+
async function compileString(data, filename, options, resolver) {
|
|
63
62
|
try {
|
|
64
63
|
lessPreprocessor ??= (await Promise.resolve().then(() => __importStar(require('less')))).default;
|
|
65
64
|
}
|
|
@@ -120,7 +119,6 @@ async function compileString(data, filename, options, resolver, unsafeInlineJava
|
|
|
120
119
|
paths: options.includePaths,
|
|
121
120
|
plugins: [resolverPlugin],
|
|
122
121
|
rewriteUrls: 'all',
|
|
123
|
-
javascriptEnabled: unsafeInlineJavaScript,
|
|
124
122
|
sourceMap: options.sourcemap
|
|
125
123
|
? {
|
|
126
124
|
sourceMapFileInline: true,
|
|
@@ -137,28 +135,6 @@ async function compileString(data, filename, options, resolver, unsafeInlineJava
|
|
|
137
135
|
catch (error) {
|
|
138
136
|
if (isLessException(error)) {
|
|
139
137
|
const location = convertExceptionLocation(error);
|
|
140
|
-
// Retry with a warning for less files requiring the deprecated inline JavaScript option
|
|
141
|
-
if (error.message.includes('Inline JavaScript is not enabled.')) {
|
|
142
|
-
const withJsResult = await compileString(data, filename, options, resolver,
|
|
143
|
-
/* unsafeInlineJavaScript */ true);
|
|
144
|
-
withJsResult.warnings = [
|
|
145
|
-
{
|
|
146
|
-
text: 'Deprecated inline execution of JavaScript has been enabled ("javascriptEnabled")',
|
|
147
|
-
location,
|
|
148
|
-
notes: [
|
|
149
|
-
{
|
|
150
|
-
location: null,
|
|
151
|
-
text: 'JavaScript found within less stylesheets may be executed at build time. [https://lesscss.org/usage/#less-options]',
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
location: null,
|
|
155
|
-
text: 'Support for "javascriptEnabled" may be removed from the Angular CLI starting with Angular v19.',
|
|
156
|
-
},
|
|
157
|
-
],
|
|
158
|
-
},
|
|
159
|
-
];
|
|
160
|
-
return withJsResult;
|
|
161
|
-
}
|
|
162
138
|
return {
|
|
163
139
|
errors: [
|
|
164
140
|
{
|
|
@@ -152,7 +152,8 @@ class StylesheetPluginFactory {
|
|
|
152
152
|
postcssProcessor = postcss();
|
|
153
153
|
const postCssPluginRequire = (0, node_module_1.createRequire)((0, node_path_1.dirname)(configPath) + '/');
|
|
154
154
|
for (const [pluginName, pluginOptions] of config.plugins) {
|
|
155
|
-
const
|
|
155
|
+
const pluginMod = postCssPluginRequire(pluginName);
|
|
156
|
+
const plugin = pluginMod.__esModule ? pluginMod['default'] : pluginMod;
|
|
156
157
|
if (typeof plugin !== 'function' || plugin.postcss !== true) {
|
|
157
158
|
throw new Error(`Attempted to load invalid Postcss plugin: "${pluginName}"`);
|
|
158
159
|
}
|
|
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.normalizeCacheOptions = normalizeCacheOptions;
|
|
11
11
|
const node_path_1 = require("node:path");
|
|
12
12
|
/** Version placeholder is replaced during the build process with actual package version */
|
|
13
|
-
const VERSION = '21.0.0-next.
|
|
13
|
+
const VERSION = '21.0.0-next.6';
|
|
14
14
|
function hasCacheMetadata(value) {
|
|
15
15
|
return (!!value &&
|
|
16
16
|
typeof value === 'object' &&
|
|
@@ -6,6 +6,6 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
8
|
import type { createRequestHandler } from '@angular/ssr';
|
|
9
|
-
import type { createNodeRequestHandler } from '@angular/ssr/node';
|
|
9
|
+
import type { createNodeRequestHandler } from '@angular/ssr/node' with { 'resolution-mode': 'import' };
|
|
10
10
|
export declare function isSsrNodeRequestHandler(value: unknown): value is ReturnType<typeof createNodeRequestHandler>;
|
|
11
11
|
export declare function isSsrRequestHandler(value: unknown): value is ReturnType<typeof createRequestHandler>;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
|
-
import type { Config, Filesystem } from '@angular/service-worker/config';
|
|
8
|
+
import type { Config, Filesystem } from '@angular/service-worker/config' with { 'resolution-mode': 'import' };
|
|
9
9
|
import { promises as fsPromises } from 'node:fs';
|
|
10
10
|
import { BuildOutputFile } from '../tools/esbuild/bundler-context';
|
|
11
11
|
import { BuildOutputAsset } from '../tools/esbuild/bundler-execution-result';
|