Compare commits

...

16 Commits

Author SHA1 Message Date
Paul Gschwendtner 47d674055a docs: properly link to developer preview section
Fixes an invalid link to the developer preview section.
2024-05-07 14:32:01 +02:00
AleksanderBodurri 77ae5a391b refactor(devtools): remove git sha stamping from devtools build (#55694)
This stamping is interfering with publishing to the Firefox addons store by brining in the entirety of the `.git` directory as part of the source code necessary for a reproducible build, which Firefox requires as part of it's approval process.

In it's place, we are now using the extension version pulled from the manifest.

PR Close #55694
2024-05-06 16:02:36 -07:00
Andrew Scott 76f2c4fe1a refactor(core): private export token that indicates if zone scheduling is provided (#55690)
This is needed internally to determine whether to provide zone or
zoneless by default.

PR Close #55690
2024-05-06 16:01:48 -07:00
Andrew Scott 9366e170e9 refactor(router): resolve view transition promise in a timeout when unsupported (#55327)
Related to #51131, this change ensures that the router navigation exits
the current event loop before rendering the route when the view transition
feature is enabled, when the browser does not support view transitions.

PR Close #55327
2024-05-06 16:00:53 -07:00
Rahat Ahmed 879537466e refactor(core): Remove unused JSNAMESPACE_SUPPORT from event-dispatch (#55619)
The usage of this option has been removed from google3 code, so we don't
need to keep it around anymore.

PR Close #55619
2024-05-06 14:58:25 -07:00
Andrew Scott 7330b6944d fix(core): TestBed should not override NgZone from initTestEnvironment (#55226)
Prior to this change, `NgZone` was provided by default in TestBed in a
location that would override anything configured in
`TestBed.initTestEnvironment`. This change moves the default `NgZone`
provider to the `RootScopeModule` and these providers can be overridden
by the ones in `additionalModuleTypes`, which are assigned from the
first argument of `initTestEnvironment`. This makes it possible to
configure Zone globally for all tests as opposed to needing to repeat it
in `configureTestingModule` of each suite.

PR Close #55226
2024-05-06 13:33:16 -07:00
Alan Agius 3e1d6e9d6e fix(compiler): maintain multiline CSS selectors during CSS scoping (#55509)
Previously, multiline selectors were being converted into single lines, resulting in sourcemap disruptions due to shifts in line numbers.

Closes #55508

PR Close #55509
2024-05-06 12:39:50 -07:00
Andrew Kushnir 9d3cd9bc83 refactor(animations): make async animations code compatible with Closure compiler (#55686)
Closure compiler optimizations in g3 require `.then` to be present for a dynamic import (or an import should be `await`ed) to detect the set of imported symbols. Currently, the `.then` is located at a later stage in the file, which confuses static code analysis. This change adds the `.then((m) => m)` workaround to satisfy Closure compiler constraints.

PR Close #55686
2024-05-06 12:35:23 -07:00
Alan Agius b3e61ba63f ci: update Renovate configuration: replace matchPackagePatterns with matchDepPatterns (#55683)
This commit addresses a warning in Renovate regarding a deprecated behavior that will be phased out in the future.

```
WARNING: To prevent future issues, replace the usage of matchPackagePatterns with matchDepPatterns (repository=angular/angular, baseBranch=main)
       "packageRule": {
         "matchPackagePatterns": ["^@bazel/.*", "^build_bazel.*"],
         "groupName": "bazel setup",
         "schedule": ["at any time"]
       },
       "packageName": "bazelbuild/rules_nodejs",
       "depName": "build_bazel_rules_nodejs"
```

PR Close #55683
2024-05-06 12:34:09 -07:00
Alan Agius 15e0600521 ci: remove stopUpdatingLabel setting (#55683)
This commit removes the 'stopUpdatingLabel' option from Renovate settings. This option caused pull requests to not automatically rebase when  conflicting.

PR Close #55683
2024-05-06 12:34:09 -07:00
Alan Agius cf84acf44c fix(platform-server): remove event dispatch script from HTML when hydration is disabled (#55681)
Prior to this commit, the included event dispatcher remained in the HTML even when hydration was disabled.

PR Close #55681
2024-05-06 12:33:09 -07:00
Angular Robot 7898957b9d build: lock file maintenance (#55680)
See associated pull request for more information.

PR Close #55680
2024-05-06 12:32:18 -07:00
Alan Agius 73a17904aa build: remove mermaid from deps (#55664)
This dependency is now pulled via `@angular/docs`

PR Close #55664
2024-05-06 12:31:27 -07:00
Alan Agius 9ddb003b6c fix(http): resolve withRequestsMadeViaParent behavior with withFetch (#55652)
This commit addresses dependency injection defects when using the `withFetch` API. Formerly, utilizing `withFetch` led to the automatic setting of `HttpBackend` to `FetchBackend`, which proved problematic in certain scenarios. Notably, conflicts arose when integrating `withRequestsMadeViaParent` and manually overriding tokens, as observed in instances like `InMemoryWebApiModule`.

PR Close #55652
2024-05-06 12:29:53 -07:00
cexbrayat 7a2efd442d fix(migrations): handle more cases in HttpClientModule migration (#55640)
This commit handles two cases that were breaking applications when using the new migration:

- tests using `HttpClientModule` in `TestBed.configureTestingModule` were broken as the import was removed, but the module is still present in the test configuration. It now properly adds `provideHttpClient(withInterceptorsFromDi())` and related imports to the test.
- tests using `HttpClientTestingModule` were migrated to use `provideHttpClient(withInterceptorsFromDi())` but the necessary imports were not added. They are now added by the migration.

PR Close #55640
2024-05-06 12:29:17 -07:00
Andrew Scott 464dae94ee docs: small updates to zoneless docs (#55636)
PR Close #55636
2024-05-06 12:28:36 -07:00
43 changed files with 1873 additions and 1647 deletions
@@ -14,8 +14,7 @@ import {InMemoryDataService} from './in-memory-data.service';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
// TODO: Enable using Fetch API when disabling `HttpClientInMemoryWebApiModule`.
provideHttpClient(/* withFetch()*/),
provideHttpClient(withFetch()),
provideClientHydration(),
provideProtractorTestingSupport(), // essential for e2e testing
@@ -3,7 +3,7 @@
The `output()` function declares an output in a directive or component.
Outputs allow you to emit values to parent components.
HELPFUL: The `output()` function is currently in [developer preview](/guide/releases#developer-preview).
HELPFUL: The `output()` function is currently in [developer preview](/reference/releases#developer-preview).
<docs-code language="ts" highlight="[[5], [8]]">
import {Component, output} from '@angular/core';
+3 -1
View File
@@ -7,7 +7,7 @@ The main advantages to removing ZoneJS as a dependency are:
- **Improved performance**: ZoneJS uses DOM events and async tasks as indicators of when application state _might_ have updated and subsequently triggers application synchronization to run change detection on the application's views. ZoneJS does not have any insight into whether application state actually changed and so this synchronization is triggered more frequently than necessary.
- **Improved Core Web Vitals**: ZoneJS brings a fair amount of overhead, both in payload size and in startup time cost.
- **Improved debugging experience**: ZoneJS makes debugging code more difficult. Stack traces are harder to understand with ZoneJS. It's also difficult to understand when code breaks as a result of being outside the Angular Zone.
- **Better ecosystem compatibility**: (new browser APIs, native async await, patching can conflict with libraries and other frameworks, maintainability, etc)
- **Better ecosystem compatibility**: ZoneJS works by patching browser APIs but does not automatically have patches for every new browser API. Some APIs simply cannot be patched effectively, such as `async`/`await`, and have to be downleveled to work with ZoneJS. Sometimes libraries in the ecosystem are also incompatible with the way ZoneJS patches the native APIs. Removing ZoneJS as a dependency ensures better long-term compatibility by removing a source of complexity, monkey patching, and ongoing maintenance.
## Enabling Zoneless in an application
@@ -83,9 +83,11 @@ familiar and have similar timing to what was needed. More straightforward or dir
such as `MutationObserver` when code needs to wait for certain DOM state (rather than waiting for it indirectly
through Angular's render hooks).
<docs-callout title="NgZone.run and NgZone.runOutsideAngular are compatible with Zoneless">
`NgZone.run` and `NgZone.runOutsideAngular` do not need to be removed in order for code to be compatible with
Zoneless applications. In fact, removing these calls can lead to performance regressions for libraries that
are used in applications that still rely on ZoneJS.
</docs-callout>
### `ExperimentalPendingTasks` for Server Side Rendering (SSR)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -70,13 +70,6 @@ pkg_web(
":bundle",
"@npm//:node_modules/tslib/tslib.js",
],
# Currently, ibazel doesn't allow passing in flags to bazel run.
# This means we are not able to use --config snapshot-build
# to access the current commit SHA.
# Since we still want to be able to use ibazel to speed up
# local development, we supply an empty string for the SHA substitution.
# This does not effect production builds.
substitutions = {"BUILD_SCM_COMMIT_SHA": ""},
)
http_server(
@@ -8,5 +8,4 @@
export const environment = {
production: false,
LATEST_SHA: 'BUILD_SCM_COMMIT_SHA', // Stamped at build time by bazel
};
@@ -6,13 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
interface Env {
LATEST_SHA: string;
}
export interface Environment {
production: boolean;
LATEST_SHA: string;
}
export const TOP_LEVEL_FRAME_ID = 0;
@@ -51,9 +51,7 @@
</span>
}
@if (latestSHA) {
| DevTools SHA: {{ latestSHA }}
}
| DevTools: {{ extensionVersion }}
</section>
}
</nav>
@@ -90,6 +90,8 @@ export class DevToolsTabsComponent implements OnInit, AfterViewInit {
return parseInt(version.toString().split('.')[0], 10);
});
extensionVersion = 'Development Build';
constructor(
public tabUpdate: TabUpdate,
public themeService: ThemeService,
@@ -111,6 +113,10 @@ export class DevToolsTabsComponent implements OnInit, AfterViewInit {
ngOnInit(): void {
this.navbar.stretchTabs = false;
if (chrome !== undefined && chrome.runtime !== undefined) {
this.extensionVersion = chrome.runtime.getManifest().version;
}
}
get tabs(): Tabs[] {
@@ -122,10 +128,6 @@ export class DevToolsTabsComponent implements OnInit, AfterViewInit {
this.navbar.disablePagination = true;
}
get latestSHA(): string {
return this.applicationEnvironment.environment.LATEST_SHA.slice(0, 8);
}
changeTab(tab: Tabs): void {
this.activeTab = tab;
this.tabUpdate.notify();
@@ -151,5 +151,4 @@ pkg_web(
additional_root_paths = [
"projects/ng-devtools/src/lib",
],
substitutions = {"BUILD_SCM_COMMIT_SHA": "{BUILD_SCM_COMMIT_SHA}"},
)
@@ -8,5 +8,4 @@
export const environment = {
production: true,
LATEST_SHA: 'BUILD_SCM_COMMIT_SHA', // Stamped at build time by bazel
};
-7
View File
@@ -73,13 +73,6 @@ pkg_web(
":bundle",
"@npm//:node_modules/tslib/tslib.js",
],
# Currently, ibazel doesn't allow passing in flags to bazel run.
# This means we are not able to use --config snapshot-build
# to access the current commit SHA.
# Since we still want to be able to use ibazel to speed up
# local development, we supply an empty string for the SHA substitution.
# This does not effect production builds.
substitutions = {"BUILD_SCM_COMMIT_SHA": ""},
)
http_server(
-1
View File
@@ -8,5 +8,4 @@
export const environment = {
production: false,
LATEST_SHA: 'BUILD_SCM_COMMIT_SHA', // Stamped at build time by bazel
};
@@ -44,8 +44,6 @@ export class EventContract implements UnrenamedEventContract {
exportAddA11yClickSupport(): void;
handler(eventType: string): EventHandler | undefined;
// (undocumented)
static JSNAMESPACE_SUPPORT: boolean;
// (undocumented)
static MOUSE_SPECIAL_SUPPORT: boolean;
registerDispatcher(dispatcher: Dispatcher_2, restriction: Restriction): void;
replayEarlyEvents(earlyJsactionContainer?: EarlyJsactionDataContainer): void;
-1
View File
@@ -210,7 +210,6 @@
"karma-sauce-launcher": "^4.3.6",
"madge": "^7.0.0",
"marked": "^12.0.0",
"mermaid": "^10.8.0",
"ogl": "^1.0.3",
"patch-package": "^7.0.0",
"playwright-core": "^1.41.2",
-13
View File
@@ -215,13 +215,6 @@ export const HTTP_ROOT_INTERCEPTOR_FNS = new InjectionToken<readonly HttpInterce
ngDevMode ? 'HTTP_ROOT_INTERCEPTOR_FNS' : '',
);
/**
* A provider to set a global primary http backend. If set, it will override the default one
*/
export const PRIMARY_HTTP_BACKEND = new InjectionToken<HttpBackend>(
ngDevMode ? 'PRIMARY_HTTP_BACKEND' : '',
);
// TODO(atscott): We need a larger discussion about stability and what should contribute to stability.
// Should the whole interceptor chain contribute to stability or just the backend request #55075?
// Should HttpClient contribute to stability automatically at all?
@@ -280,12 +273,6 @@ export class HttpInterceptorHandler extends HttpHandler {
) {
super();
// Check if there is a preferred HTTP backend configured and use it if that's the case.
// This is needed to enable `FetchBackend` globally for all HttpClient's when `withFetch`
// is used.
const primaryHttpBackend = inject(PRIMARY_HTTP_BACKEND, {optional: true});
this.backend = primaryHttpBackend ?? backend;
// We strongly recommend using fetch backend for HTTP calls when SSR is used
// for an application. The logic below checks if that's the case and produces
// a warning otherwise.
@@ -8,6 +8,5 @@
export {
HTTP_ROOT_INTERCEPTOR_FNS as ɵHTTP_ROOT_INTERCEPTOR_FNS,
PRIMARY_HTTP_BACKEND as ɵPRIMARY_HTTP_BACKEND,
REQUESTS_CONTRIBUTE_TO_STABILITY as ɵREQUESTS_CONTRIBUTE_TO_STABILITY,
} from './interceptor';
+6 -15
View File
@@ -22,7 +22,6 @@ import {
HttpInterceptorFn,
HttpInterceptorHandler,
legacyInterceptorFnFactory,
PRIMARY_HTTP_BACKEND,
} from './interceptor';
import {
jsonpCallbackContext,
@@ -126,7 +125,12 @@ export function provideHttpClient(
HttpXhrBackend,
HttpInterceptorHandler,
{provide: HttpHandler, useExisting: HttpInterceptorHandler},
{provide: HttpBackend, useExisting: HttpXhrBackend},
{
provide: HttpBackend,
useFactory: () => {
return inject(FetchBackend, {optional: true}) ?? inject(HttpXhrBackend);
},
},
{
provide: HTTP_INTERCEPTOR_FNS,
useValue: xsrfInterceptorFn,
@@ -294,26 +298,13 @@ export function withRequestsMadeViaParent(): HttpFeature<HttpFeatureKind.Request
/**
* Configures the current `HttpClient` instance to make requests using the fetch API.
*
* This `FetchBackend` requires the support of the Fetch API which is available on all evergreen
* browsers and on NodeJS from v18 onward.
*
* Note: The Fetch API doesn't support progress report on uploads.
*
* @publicApi
*/
export function withFetch(): HttpFeature<HttpFeatureKind.Fetch> {
if ((typeof ngDevMode === 'undefined' || ngDevMode) && typeof fetch !== 'function') {
// TODO: Create a runtime error
// TODO: Use ENVIRONMENT_INITIALIZER to contextualize the error message (browser or server)
throw new Error(
'The `withFetch` feature of HttpClient requires the `fetch` API to be available. ' +
'If you run the code in a Node environment, make sure you use Node v18.10 or later.',
);
}
return makeHttpFeature(HttpFeatureKind.Fetch, [
FetchBackend,
{provide: HttpBackend, useExisting: FetchBackend},
{provide: PRIMARY_HTTP_BACKEND, useExisting: FetchBackend},
]);
}
+118 -90
View File
@@ -40,6 +40,8 @@ import {EMPTY, Observable, from} from 'rxjs';
import {HttpInterceptorFn, resetFetchBackendWarningFlag} from '../src/interceptor';
import {
HttpFeature,
HttpFeatureKind,
provideHttpClient,
withFetch,
withInterceptors,
@@ -339,94 +341,107 @@ describe('provideHttpClient', () => {
});
describe('withRequestsMadeViaParent()', () => {
it('should have independent HTTP setups if not explicitly specified', async () => {
TestBed.configureTestingModule({
providers: [provideHttpClient(), provideHttpClientTesting()],
});
for (const backend of ['fetch', 'xhr']) {
describe(`given '${backend}' backend`, () => {
const commonHttpFeatures: HttpFeature<HttpFeatureKind>[] = [];
if (backend === 'fetch') {
commonHttpFeatures.push(withFetch());
}
const child = createEnvironmentInjector(
[
provideHttpClient(),
{
provide: XhrFactory,
useValue: {
build: () => {
throw new Error('Request reached the "backend".');
it('should have independent HTTP setups if not explicitly specified', async () => {
TestBed.configureTestingModule({
providers: [provideHttpClient(...commonHttpFeatures), provideHttpClientTesting()],
});
const child = createEnvironmentInjector(
[
provideHttpClient(),
{
provide: XhrFactory,
useValue: {
build: () => {
throw new Error('Request reached the "backend".');
},
},
},
},
},
],
TestBed.inject(EnvironmentInjector),
);
],
TestBed.inject(EnvironmentInjector),
);
// Because `child` is an entirely independent HTTP context, it is not connected to the
// HTTP testing backend from the parent injector, and requests attempted via the child's
// `HttpClient` will fail.
await expectAsync(child.get(HttpClient).get('/test').toPromise()).toBeRejected();
});
// Because `child` is an entirely independent HTTP context, it is not connected to the
// HTTP testing backend from the parent injector, and requests attempted via the child's
// `HttpClient` will fail.
await expectAsync(child.get(HttpClient).get('/test').toPromise()).toBeRejected();
});
it('should connect child to parent configuration if specified', () => {
TestBed.configureTestingModule({
providers: [provideHttpClient(), provideHttpClientTesting()],
it('should connect child to parent configuration if specified', () => {
TestBed.configureTestingModule({
providers: [provideHttpClient(...commonHttpFeatures), provideHttpClientTesting()],
});
const child = createEnvironmentInjector(
[provideHttpClient(withRequestsMadeViaParent())],
TestBed.inject(EnvironmentInjector),
);
// `child` is now to the parent HTTP context and therefore the testing backend, and so a
// request made via its `HttpClient` can be made.
child.get(HttpClient).get('/test', {responseType: 'text'}).subscribe();
const req = TestBed.inject(HttpTestingController).expectOne('/test');
req.flush('');
});
it('should include interceptors from both parent and child contexts', () => {
TestBed.configureTestingModule({
providers: [
provideHttpClient(
...commonHttpFeatures,
withInterceptors([makeLiteralTagInterceptorFn('parent')]),
),
provideHttpClientTesting(),
],
});
const child = createEnvironmentInjector(
[
provideHttpClient(
withRequestsMadeViaParent(),
withInterceptors([makeLiteralTagInterceptorFn('child')]),
),
],
TestBed.inject(EnvironmentInjector),
);
child.get(HttpClient).get('/test', {responseType: 'text'}).subscribe();
const req = TestBed.inject(HttpTestingController).expectOne('/test');
expect(req.request.headers.get('X-Tag')).toEqual('child,parent');
req.flush('');
});
it('should be able to connect to a legacy-provided HttpClient context', () => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [provideLegacyInterceptor('parent')],
});
const child = createEnvironmentInjector(
[
provideHttpClient(
...commonHttpFeatures,
withRequestsMadeViaParent(),
withInterceptors([makeLiteralTagInterceptorFn('child')]),
),
],
TestBed.inject(EnvironmentInjector),
);
child.get(HttpClient).get('/test', {responseType: 'text'}).subscribe();
const req = TestBed.inject(HttpTestingController).expectOne('/test');
expect(req.request.headers.get('X-Tag')).toEqual('child,parent');
req.flush('');
});
});
const child = createEnvironmentInjector(
[provideHttpClient(withRequestsMadeViaParent())],
TestBed.inject(EnvironmentInjector),
);
// `child` is now to the parent HTTP context and therefore the testing backend, and so a
// request made via its `HttpClient` can be made.
child.get(HttpClient).get('/test', {responseType: 'text'}).subscribe();
const req = TestBed.inject(HttpTestingController).expectOne('/test');
req.flush('');
});
it('should include interceptors from both parent and child contexts', () => {
TestBed.configureTestingModule({
providers: [
provideHttpClient(withInterceptors([makeLiteralTagInterceptorFn('parent')])),
provideHttpClientTesting(),
],
});
const child = createEnvironmentInjector(
[
provideHttpClient(
withRequestsMadeViaParent(),
withInterceptors([makeLiteralTagInterceptorFn('child')]),
),
],
TestBed.inject(EnvironmentInjector),
);
child.get(HttpClient).get('/test', {responseType: 'text'}).subscribe();
const req = TestBed.inject(HttpTestingController).expectOne('/test');
expect(req.request.headers.get('X-Tag')).toEqual('child,parent');
req.flush('');
});
it('should be able to connect to a legacy-provided HttpClient context', () => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [provideLegacyInterceptor('parent')],
});
const child = createEnvironmentInjector(
[
provideHttpClient(
withRequestsMadeViaParent(),
withInterceptors([makeLiteralTagInterceptorFn('child')]),
),
],
TestBed.inject(EnvironmentInjector),
);
child.get(HttpClient).get('/test', {responseType: 'text'}).subscribe();
const req = TestBed.inject(HttpTestingController).expectOne('/test');
expect(req.request.headers.get('X-Tag')).toEqual('child,parent');
req.flush('');
});
}
});
describe('compatibility with Http NgModules', () => {
@@ -472,20 +487,33 @@ describe('provideHttpClient', () => {
expect(consoleWarnSpy.calls.count()).toBe(0);
});
it('withFetch should always override the backend', () => {
it(`'withFetch' should not override provided backend`, () => {
class CustomBackendExtends extends HttpXhrBackend {}
TestBed.resetTestingModule();
TestBed.configureTestingModule({
providers: [
provideHttpClient(withFetch()),
// This emulates a situation when `provideHttpClient()` is used
// later in a different part of an app. We want to make sure that
// the `FetchBackend` is enabled in that case as well.
{provide: HttpBackend, useClass: HttpXhrBackend},
{provide: HttpBackend, useClass: CustomBackendExtends},
],
});
const handler = TestBed.inject(HttpHandler);
expect((handler as any).backend).toBeInstanceOf(FetchBackend);
const backend = TestBed.inject(HttpBackend);
expect(backend).toBeInstanceOf(CustomBackendExtends);
});
it(`fetch API should be used in child when 'withFetch' was used in parent injector`, () => {
TestBed.configureTestingModule({
providers: [provideHttpClient(withFetch()), provideHttpClientTesting()],
});
const child = createEnvironmentInjector(
[provideHttpClient()],
TestBed.inject(EnvironmentInjector),
);
const backend = child.get(HttpBackend);
expect(backend).toBeInstanceOf(FetchBackend);
});
it('should not warn if fetch is not configured when running in a browser', () => {
+13 -8
View File
@@ -658,8 +658,8 @@ export class ShadowCss {
private _scopeSelector(selector: string, scopeSelector: string, hostSelector: string): string {
return selector
.split(',')
.map((part) => part.trim().split(_shadowDeepSelectors))
.split(/ ?, ?/)
.map((part) => part.split(_shadowDeepSelectors))
.map((deepParts) => {
const [shallowPart, ...otherParts] = deepParts;
const applyScope = (shallowPart: string) => {
@@ -727,10 +727,10 @@ export class ShadowCss {
let scopedP = p.trim();
if (!scopedP) {
return '';
return p;
}
if (p.indexOf(_polyfillHostNoCombinator) > -1) {
if (p.includes(_polyfillHostNoCombinator)) {
scopedP = this._applySimpleSelectorScope(p, scopeSelector, hostSelector);
} else {
// remove :host since it should be unnecessary
@@ -765,13 +765,18 @@ export class ShadowCss {
// - `tag:host` -> `tag[h]` (this is to avoid breaking legacy apps, should not match anything)
// - `tag :host` -> `tag [h]` (`tag` is not scoped because it's considered part of a
// `:host-context(tag)`)
const hasHost = selector.indexOf(_polyfillHostNoCombinator) > -1;
const hasHost = selector.includes(_polyfillHostNoCombinator);
// Only scope parts after the first `-shadowcsshost-no-combinator` when it is present
let shouldScope = !hasHost;
while ((res = sep.exec(selector)) !== null) {
const separator = res[1];
const part = selector.slice(startIndex, res.index).trim();
// Do not trim the selector, as otherwise this will break sourcemaps
// when they are defined on multiple lines
// Example:
// div,
// p { color: red}
const part = selector.slice(startIndex, res.index);
// A space following an escaped hex value and followed by another hex character
// (ie: ".\fc ber" for ".über") is not a separator between 2 selectors
@@ -781,14 +786,14 @@ export class ShadowCss {
continue;
}
shouldScope = shouldScope || part.indexOf(_polyfillHostNoCombinator) > -1;
shouldScope = shouldScope || part.includes(_polyfillHostNoCombinator);
const scopedPart = shouldScope ? _scopeSelectorPart(part) : part;
scopedSelector += `${scopedPart} ${separator} `;
startIndex = sep.lastIndex;
}
const part = selector.substring(startIndex);
shouldScope = shouldScope || part.indexOf(_polyfillHostNoCombinator) > -1;
shouldScope = shouldScope || part.includes(_polyfillHostNoCombinator);
scopedSelector += shouldScope ? _scopeSelectorPart(part) : part;
// replace the placeholders with their original values
@@ -117,6 +117,13 @@ describe('ShadowCss', () => {
expect(css).toEqualCss('div[contenta]::after { content:"{}"}');
});
it('should keep retain multiline selectors', () => {
// This is needed as shifting in line number will cause sourcemaps to break.
const styleStr = '.foo,\n.bar { color: red;}';
const css = shim(styleStr, 'contenta');
expect(css).toEqual('.foo[contenta], \n.bar[contenta] { color: red;}');
});
describe('comments', () => {
// Comments should be kept in the same position as otherwise inline sourcemaps break due to
// shift in lines.
@@ -33,7 +33,6 @@ const DEFAULT_EVENT_TYPE: string = EventType.CLICK;
export class ActionResolver {
private a11yClickSupport: boolean = false;
private readonly customEventSupport: boolean;
private readonly jsnamespaceSupport: boolean;
private readonly syntheticMouseEventSupport: boolean;
private updateEventInfoForA11yClick?: (eventInfo: eventInfoLib.EventInfo) => void = undefined;
@@ -48,15 +47,12 @@ export class ActionResolver {
constructor({
customEventSupport = false,
jsnamespaceSupport = false,
syntheticMouseEventSupport = false,
}: {
customEventSupport?: boolean;
jsnamespaceSupport?: boolean;
syntheticMouseEventSupport?: boolean;
} = {}) {
this.customEventSupport = customEventSupport;
this.jsnamespaceSupport = jsnamespaceSupport;
this.syntheticMouseEventSupport = syntheticMouseEventSupport;
}
@@ -214,17 +210,14 @@ export class ActionResolver {
* action the given event is mapped to, if any. It parses the
* attribute value and stores it in a property on the node for
* subsequent retrieval without re-parsing and re-accessing the
* attribute. In order to fully qualify jsaction names using a
* namespace, the DOM is searched starting at the current node and
* going through ancestor nodes until a jsnamespace attribute is
* found.
* attribute.
*
* @param actionElement The DOM node to retrieve the jsaction map from.
* @param eventInfo `EventInfo` to set `action` and `actionElement` if an
* action is found on the `actionElement`.
*/
private populateActionOnElement(actionElement: Element, eventInfo: eventInfoLib.EventInfo) {
const actionMap = this.parseActions(actionElement, eventInfoLib.getContainer(eventInfo));
const actionMap = this.parseActions(actionElement);
const actionName = actionMap[eventInfoLib.getEventType(eventInfo)];
if (actionName !== undefined) {
@@ -242,11 +235,9 @@ export class ActionResolver {
* This is primarily for internal use.
*
* @param actionElement The DOM node to retrieve the jsaction map from.
* @param container The node which limits the namespace lookup for a jsaction
* name. The container node itself will not be searched.
* @return Map from event to qualified name of the jsaction bound to it.
*/
private parseActions(actionElement: Element, container: Node): {[key: string]: string} {
private parseActions(actionElement: Element): {[key: string]: string} {
let actionMap: {[key: string]: string} | undefined = cache.get(actionElement);
if (!actionMap) {
const jsactionAttribute = actionElement.getAttribute(Attribute.JSACTION);
@@ -271,58 +262,12 @@ export class ActionResolver {
}
cache.setParsed(jsactionAttribute, actionMap);
}
// If namespace support is active we need to augment the (potentially
// cached) jsaction mapping with the namespace.
if (this.jsnamespaceSupport) {
const noNs = actionMap;
actionMap = {};
for (const type in noNs) {
actionMap[type] = this.getFullyQualifiedAction(noNs[type], actionElement, container);
}
}
cache.set(actionElement, actionMap);
}
}
return actionMap;
}
/**
* Returns the fully qualified jsaction action. If the given jsaction
* name doesn't already contain the namespace, the function iterates
* over ancestor nodes until a jsnamespace attribute is found, and
* uses the value of that attribute as the namespace.
*
* @param action The jsaction action to resolve.
* @param start The node from which to start searching for a jsnamespace
* attribute.
* @param container The node which limits the search for a jsnamespace
* attribute. This node will be searched.
* @return The fully qualified name of the jsaction. If no namespace is found,
* returns the unqualified name in case it exists in the global namespace.
*/
private getFullyQualifiedAction(action: string, start: Element, container: Node): string {
if (isNamespacedAction(action)) {
return action;
}
let node: Node | null = start;
while (node && node.nodeType === Node.ELEMENT_NODE) {
const namespace = getNamespaceFromElement(node as Element);
if (namespace) {
return namespace + Char.NAMESPACE_ACTION_SEPARATOR + action;
}
// If this node is the container, stop.
if (node === container) {
break;
}
node = node.parentNode;
}
return action;
}
addA11yClickSupport(
updateEventInfoForA11yClick: typeof a11yClick.updateEventInfoForA11yClick,
preventDefaultForA11yClick: typeof a11yClick.preventDefaultForA11yClick,
@@ -334,29 +279,3 @@ export class ActionResolver {
this.populateClickOnlyAction = populateClickOnlyAction;
}
}
/**
* Checks if a jsaction action contains a namespace part.
*/
function isNamespacedAction(action: string): boolean {
return action.indexOf(Char.NAMESPACE_ACTION_SEPARATOR) >= 0;
}
/**
* Returns the value of the jsnamespace attribute of the given node.
* Also caches the value for subsequent lookups.
* @param element The node whose jsnamespace attribute is being asked for.
* @return The value of the jsnamespace attribute, or null if not found.
*/
function getNamespaceFromElement(element: Element): string | null {
let namespace = cache.getNamespace(element);
// Only query for the attribute if it has not been queried for
// before. getAttribute() returns null if an attribute is not present. Thus,
// namespace is string|null if the query took place in the past, or
// undefined if the query did not take place.
if (namespace === undefined) {
namespace = element.getAttribute(Attribute.JSNAMESPACE);
cache.setNamespace(element, namespace);
}
return namespace;
}
@@ -6,12 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/
/**
* @define Support for jsnamespace attribute. This flag can be overridden in a
* build rule to trim down the EventContract's binary size.
*/
export const JSNAMESPACE_SUPPORT = false;
/**
* @define Support for accessible click actions. This flag can be overridden in
* a build rule.
@@ -38,7 +38,6 @@ import {EventContractContainerManager} from './event_contract_container';
import {
A11Y_CLICK_SUPPORT,
CUSTOM_EVENT_SUPPORT,
JSNAMESPACE_SUPPORT,
MOUSE_SPECIAL_SUPPORT,
} from './event_contract_defines';
import * as eventInfoLib from './event_info';
@@ -91,13 +90,11 @@ export class EventContract implements UnrenamedEventContract {
static CUSTOM_EVENT_SUPPORT = CUSTOM_EVENT_SUPPORT;
static A11Y_CLICK_SUPPORT = A11Y_CLICK_SUPPORT;
static MOUSE_SPECIAL_SUPPORT = MOUSE_SPECIAL_SUPPORT;
static JSNAMESPACE_SUPPORT = JSNAMESPACE_SUPPORT;
private containerManager: EventContractContainerManager | null;
private readonly actionResolver = new ActionResolver({
customEventSupport: EventContract.CUSTOM_EVENT_SUPPORT,
jsnamespaceSupport: EventContract.JSNAMESPACE_SUPPORT,
syntheticMouseEventSupport: EventContract.MOUSE_SPECIAL_SUPPORT,
});
@@ -1781,113 +1781,6 @@ describe('EventContract', () => {
});
});
describe('jsnamespace', () => {
beforeEach(() => {
EventContract.JSNAMESPACE_SUPPORT = true;
});
it('dispatches event', () => {
const container = getRequiredElementById('jsnamespace-container');
const actionElement = getRequiredElementById('jsnamespace-action-element');
const targetElement = getRequiredElementById('jsnamespace-target-element');
const dispatcher = jasmine.createSpy<Dispatcher>('dispatcher');
createEventContract({
eventContractContainerManager: new EventContractContainer(container),
eventTypes: ['click'],
dispatcher,
});
const clickEvent = dispatchMouseEvent(targetElement);
expect(dispatcher).toHaveBeenCalledTimes(2);
const eventInfoWrapper = getLastDispatchedEventInfoWrapper(dispatcher);
expect(eventInfoWrapper.getEventType()).toBe('click');
expect(eventInfoWrapper.getEvent()).toBe(clickEvent);
expect(eventInfoWrapper.getTargetElement()).toBe(targetElement);
expect(eventInfoWrapper.getAction()?.name).toBe('namespace.handleClick');
expect(eventInfoWrapper.getAction()?.element).toBe(actionElement);
});
it('caches namespace attribute', () => {
const container = getRequiredElementById('jsnamespace-container');
const namespaceElement = getRequiredElementById('jsnamespace-namespace-element');
const actionElement = getRequiredElementById('jsnamespace-action-element');
const targetElement = getRequiredElementById('jsnamespace-target-element');
const dispatcher = jasmine.createSpy<Dispatcher>('dispatcher');
createEventContract({
eventContractContainerManager: new EventContractContainer(container),
eventTypes: ['click'],
dispatcher,
});
let clickEvent = dispatchMouseEvent(targetElement);
expect(dispatcher).toHaveBeenCalledTimes(2);
let eventInfoWrapper = getLastDispatchedEventInfoWrapper(dispatcher);
expect(eventInfoWrapper.getEventType()).toBe('click');
expect(eventInfoWrapper.getEvent()).toBe(clickEvent);
expect(eventInfoWrapper.getTargetElement()).toBe(targetElement);
expect(eventInfoWrapper.getAction()?.name).toBe('namespace.handleClick');
expect(eventInfoWrapper.getAction()?.element).toBe(actionElement);
namespaceElement.setAttribute('jsnamespace', 'renamedNamespace');
dispatcher.calls.reset();
clickEvent = dispatchMouseEvent(targetElement);
expect(dispatcher).toHaveBeenCalledTimes(2);
eventInfoWrapper = getLastDispatchedEventInfoWrapper(dispatcher);
expect(eventInfoWrapper.getEventType()).toBe('click');
expect(eventInfoWrapper.getEvent()).toBe(clickEvent);
expect(eventInfoWrapper.getTargetElement()).toBe(targetElement);
expect(eventInfoWrapper.getAction()?.name).toBe('namespace.handleClick');
expect(eventInfoWrapper.getAction()?.element).toBe(actionElement);
});
it('re-parses jsaction attribute if the action cache is cleared', () => {
const container = getRequiredElementById('jsnamespace-container');
const namespaceElement = getRequiredElementById('jsnamespace-namespace-element');
const actionElement = getRequiredElementById('jsnamespace-action-element');
const targetElement = getRequiredElementById('jsnamespace-target-element');
const dispatcher = jasmine.createSpy<Dispatcher>('dispatcher');
createEventContract({
eventContractContainerManager: new EventContractContainer(container),
eventTypes: ['click'],
dispatcher,
});
let clickEvent = dispatchMouseEvent(targetElement);
expect(dispatcher).toHaveBeenCalledTimes(2);
let eventInfoWrapper = getLastDispatchedEventInfoWrapper(dispatcher);
expect(eventInfoWrapper.getEventType()).toBe('click');
expect(eventInfoWrapper.getEvent()).toBe(clickEvent);
expect(eventInfoWrapper.getTargetElement()).toBe(targetElement);
expect(eventInfoWrapper.getAction()?.name).toBe('namespace.handleClick');
expect(eventInfoWrapper.getAction()?.element).toBe(actionElement);
namespaceElement.setAttribute('jsnamespace', 'renamedNamespace');
// Clear namespace cache.
cache.clearNamespace(namespaceElement);
// Clear action cache.
cache.clear(actionElement);
dispatcher.calls.reset();
clickEvent = dispatchMouseEvent(targetElement);
expect(dispatcher).toHaveBeenCalledTimes(2);
eventInfoWrapper = getLastDispatchedEventInfoWrapper(dispatcher);
expect(eventInfoWrapper.getEventType()).toBe('click');
expect(eventInfoWrapper.getEvent()).toBe(clickEvent);
expect(eventInfoWrapper.getTargetElement()).toBe(targetElement);
expect(eventInfoWrapper.getAction()?.name).toBe('renamedNamespace.handleClick');
expect(eventInfoWrapper.getAction()?.element).toBe(actionElement);
});
});
describe('early events', () => {
let removeEventListenerSpy: jasmine.Spy;
@@ -13,7 +13,7 @@ This migration updates any `@NgModule`, `@Component`, `@Directive` that imports
import { HttpClientModule, HttpClientJsonpModule, HttpClientXsrfModule } from '@angular/common/http';
@NgModule({
imports: [CommonModule, HttpClientModule,HttpClientJsonpModule, HttpClientXsrfModule)],
imports: [CommonModule, HttpClientModule, HttpClientJsonpModule, HttpClientXsrfModule]
})
export class AppModule {}
```
@@ -33,30 +33,61 @@ export class AppModule {}
#### Before
```
import { HttpClientTestingModule } from '@not-angular/common/http/testing';
```ts
import { HttpClientTestingModule } from '@angular/common/http/testing';
describe('some test') {
describe('some test', () => {
it('...', () => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
});
imports: [HttpClientTestingModule]
})
})
}
})
```
#### After
```ts
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
describe('some test', () => {
it('...', () => {
TestBed.configureTestingModule({
providers: [provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()]
})
})
})
```
#### Before
```
import { provideHttpClientTesting } from '@not-angular/common/http/testing';
```ts
import { HttpClientTesting } from '@angular/common/http';
describe('some test') {
describe('some test', () => {
it('...', () => {
TestBed.configureTestingModule({
providers: [provideHttpClientTesting()],
});
imports: [HttpClientTesting],
})
})
}
});
```
#### After
```ts
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
describe('some test', () => {
it('...', () => {
TestBed.configureTestingModule({
providers: [provideHttpClient(withInterceptorsFromDi())]
})
})
})
```
@@ -67,7 +67,13 @@ export function migrateFile(
});
}
migrateTestingModuleImports(node, commonHttpTestingIdentifiers, addedImports, changeTracker);
migrateTestingModuleImports(
node,
commonHttpIdentifiers,
commonHttpTestingIdentifiers,
addedImports,
changeTracker,
);
});
// Imports are for the whole file
@@ -90,6 +96,13 @@ export function migrateFile(
]);
changeTracker.replaceNode(commonHttpImports, newImports);
}
// If there are no imports for common/http, and we need to add some
else if (addedImports.get(COMMON_HTTP)?.size) {
// Then we add a new import statement for common/http
addedImports.get(COMMON_HTTP)?.forEach((entry) => {
changeTracker.addImport(sourceFile, entry, COMMON_HTTP);
});
}
// Remove the HttpModules imports from common/http/testing
const commonHttpTestingImports = getNamedImports(sourceFile, COMMON_HTTP_TESTING);
@@ -156,22 +169,23 @@ function migrateDecorator(
const addedProviders = new Set<ts.CallExpression>();
// Handle the different imported Http modules
const commonHttpAddedImports = addedImports.get(COMMON_HTTP);
if (importedModules.client) {
addedImports.get(COMMON_HTTP)?.add(WITH_INTERCEPTORS_FROM_DI);
commonHttpAddedImports?.add(WITH_INTERCEPTORS_FROM_DI);
addedProviders.add(createCallExpression(WITH_INTERCEPTORS_FROM_DI));
}
if (importedModules.clientJsonp) {
addedImports.get(COMMON_HTTP)?.add(WITH_JSONP_SUPPORT);
commonHttpAddedImports?.add(WITH_JSONP_SUPPORT);
addedProviders.add(createCallExpression(WITH_JSONP_SUPPORT));
}
if (importedModules.xsrf) {
// HttpClientXsrfModule is the only module with Class methods.
// They correspond to different provider functions
if (importedModules.xsrfOptions === 'disable') {
addedImports.get(COMMON_HTTP)?.add(WITH_NOXSRF_PROTECTION);
commonHttpAddedImports?.add(WITH_NOXSRF_PROTECTION);
addedProviders.add(createCallExpression(WITH_NOXSRF_PROTECTION));
} else {
addedImports.get(COMMON_HTTP)?.add(WITH_XSRF_CONFIGURATION);
commonHttpAddedImports?.add(WITH_XSRF_CONFIGURATION);
addedProviders.add(
createCallExpression(
WITH_XSRF_CONFIGURATION,
@@ -192,20 +206,23 @@ function migrateDecorator(
]);
// Adding the new providers
addedImports.get(COMMON_HTTP)?.add(PROVIDE_HTTP_CLIENT);
commonHttpAddedImports?.add(PROVIDE_HTTP_CLIENT);
const providers = getProvidersFromLiteralExpr(metadata);
const provideHttpExpr = createCallExpression(PROVIDE_HTTP_CLIENT, [...addedProviders]);
let newProviders: ts.ArrayLiteralExpression;
if (!providers) {
// No existing providers, we add an property to the literal
// No existing providers, we add a property to the literal
newProviders = ts.factory.createArrayLiteralExpression([provideHttpExpr]);
} else {
// We add the provider to the existing provider array
newProviders = ts.factory.createArrayLiteralExpression([
...providers.elements,
provideHttpExpr,
]);
newProviders = ts.factory.updateArrayLiteralExpression(
providers,
ts.factory.createNodeArray(
[...providers.elements, provideHttpExpr],
providers.elements.hasTrailingComma,
),
);
}
// Replacing the existing decorator with the new one (with the new imports and providers)
@@ -219,6 +236,7 @@ function migrateDecorator(
function migrateTestingModuleImports(
node: ts.Node,
commonHttpIdentifiers: Set<string>,
commonHttpTestingIdentifiers: Set<string>,
addedImports: Map<string, Set<string>>,
changeTracker: ChangeTracker,
@@ -248,51 +266,98 @@ function migrateTestingModuleImports(
return;
}
const commonHttpAddedImports = addedImports.get(COMMON_HTTP);
// Does the imports array contain the HttpClientModule?
const httpClient = importsArray.elements.find((elt) => elt.getText() === HTTP_CLIENT_MODULE);
if (httpClient && commonHttpIdentifiers.has(HTTP_CLIENT_MODULE)) {
// We add the imports for provideHttpClient(withInterceptorsFromDi())
commonHttpAddedImports?.add(PROVIDE_HTTP_CLIENT);
commonHttpAddedImports?.add(WITH_INTERCEPTORS_FROM_DI);
const newImports = ts.factory.createArrayLiteralExpression([
...importsArray.elements.filter((item) => item !== httpClient),
]);
const provideHttpClient = createCallExpression(PROVIDE_HTTP_CLIENT, [
createCallExpression(WITH_INTERCEPTORS_FROM_DI),
]);
// Adding the new provider
const providers = getProvidersFromLiteralExpr(configureTestingModuleArgs);
let newProviders: ts.ArrayLiteralExpression;
if (!providers) {
// No existing providers, we add a property to the literal
newProviders = ts.factory.createArrayLiteralExpression([provideHttpClient]);
} else {
// We add the provider to the existing provider array
newProviders = ts.factory.updateArrayLiteralExpression(
providers,
ts.factory.createNodeArray(
[...providers.elements, provideHttpClient],
providers.elements.hasTrailingComma,
),
);
}
// Replacing the existing configuration with the new one (with the new imports and providers)
const newTestingModuleArgs = updateTestBedConfiguration(
configureTestingModuleArgs,
newImports,
newProviders,
);
changeTracker.replaceNode(configureTestingModuleArgs, newTestingModuleArgs);
}
// Does the imports array contain the HttpClientTestingModule?
const httpClientTesting = importsArray.elements.find(
(elt) => elt.getText() === HTTP_CLIENT_TESTING_MODULE,
);
if (!httpClientTesting || !commonHttpTestingIdentifiers.has(HTTP_CLIENT_TESTING_MODULE)) {
return;
}
if (httpClientTesting && commonHttpTestingIdentifiers.has(HTTP_CLIENT_TESTING_MODULE)) {
// We add the imports for provideHttpClient(withInterceptorsFromDi()) and provideHttpClientTesting()
commonHttpAddedImports?.add(PROVIDE_HTTP_CLIENT);
commonHttpAddedImports?.add(WITH_INTERCEPTORS_FROM_DI);
addedImports.get(COMMON_HTTP_TESTING)?.add(PROVIDE_HTTP_CLIENT_TESTING);
addedImports.get(COMMON_HTTP_TESTING)?.add(PROVIDE_HTTP_CLIENT_TESTING);
const newImports = ts.factory.createArrayLiteralExpression([
...importsArray.elements.filter((item) => item !== httpClientTesting),
]);
const provideHttpClient = createCallExpression(PROVIDE_HTTP_CLIENT, [
createCallExpression(WITH_INTERCEPTORS_FROM_DI),
]);
const provideHttpClientTesting = createCallExpression(PROVIDE_HTTP_CLIENT_TESTING);
// Adding the new providers
const providers = getProvidersFromLiteralExpr(configureTestingModuleArgs);
let newProviders: ts.ArrayLiteralExpression;
if (!providers) {
// No existing providers, we add an property to the literal
newProviders = ts.factory.createArrayLiteralExpression([
provideHttpClient,
provideHttpClientTesting,
const newImports = ts.factory.createArrayLiteralExpression([
...importsArray.elements.filter((item) => item !== httpClientTesting),
]);
} else {
// We add the provider to the existing provider array
newProviders = ts.factory.createArrayLiteralExpression([
...providers.elements,
provideHttpClient,
provideHttpClientTesting,
]);
}
// Replacing the existing decorator with the new one (with the new imports and providers)
const newTestingModuleArgs = ts.factory.createObjectLiteralExpression([
...configureTestingModuleArgs.properties.filter((p) => p.getText() === 'imports'),
ts.factory.createPropertyAssignment('imports', newImports),
ts.factory.createPropertyAssignment('providers', newProviders),
]);
changeTracker.replaceNode(configureTestingModuleArgs, newTestingModuleArgs);
const provideHttpClient = createCallExpression(PROVIDE_HTTP_CLIENT, [
createCallExpression(WITH_INTERCEPTORS_FROM_DI),
]);
const provideHttpClientTesting = createCallExpression(PROVIDE_HTTP_CLIENT_TESTING);
// Adding the new providers
const providers = getProvidersFromLiteralExpr(configureTestingModuleArgs);
let newProviders: ts.ArrayLiteralExpression;
if (!providers) {
// No existing providers, we add a property to the literal
newProviders = ts.factory.createArrayLiteralExpression([
provideHttpClient,
provideHttpClientTesting,
]);
} else {
// We add the provider to the existing provider array
newProviders = ts.factory.updateArrayLiteralExpression(
providers,
ts.factory.createNodeArray(
[...providers.elements, provideHttpClient, provideHttpClientTesting],
providers.elements.hasTrailingComma,
),
);
}
// Replacing the existing configuration with the new one (with the new imports and providers)
const newTestingModuleArgs = updateTestBedConfiguration(
configureTestingModuleArgs,
newImports,
newProviders,
);
changeTracker.replaceNode(configureTestingModuleArgs, newTestingModuleArgs);
}
}
function getImportsProp(literal: ts.ObjectLiteralExpression) {
@@ -387,3 +452,14 @@ function createCallExpression(functionName: string, args: ts.Expression[] = [])
args,
);
}
function updateTestBedConfiguration(
configureTestingModuleArgs: ts.ObjectLiteralExpression,
newImports: ts.ArrayLiteralExpression,
newProviders: ts.ArrayLiteralExpression,
): ts.ObjectLiteralExpression {
return ts.factory.updateObjectLiteralExpression(configureTestingModuleArgs, [
ts.factory.createPropertyAssignment('imports', newImports),
ts.factory.createPropertyAssignment('providers', newProviders),
]);
}
@@ -241,7 +241,7 @@ describe('Http providers migration', () => {
);
});
it('should handle a migration for acomponent ', async () => {
it('should handle a migration for a component', async () => {
writeFile(
'/index.ts',
`
@@ -264,6 +264,32 @@ describe('Http providers migration', () => {
expect(content).toContain(`provideHttpClient(withInterceptorsFromDi(), withJsonpSupport())`);
});
it('should handle a migration of HttpClientModule in a test', async () => {
writeFile(
'/index.ts',
`
import { HttpClientModule } from '@angular/common/http';
describe('MyComponent', () => {
beforeEach(() =>
TestBed.configureTestingModule({
imports: [HttpClientModule]
})
);
});
`,
);
await runMigration();
const content = tree.readContent('/index.ts');
expect(content).not.toContain(`'@angular/common/http/testing'`);
expect(content).toContain(`'@angular/common/http'`);
expect(content).toMatch(/import.*provideHttpClient.*withInterceptorsFromDi.*from/);
expect(content).not.toContain(`HttpClientModule`);
expect(content).toContain(`provideHttpClient(withInterceptorsFromDi())`);
});
it('should not migrate HttpClientModule from another package', async () => {
writeFile(
'/index.ts',
@@ -318,7 +344,9 @@ describe('Http providers migration', () => {
await runMigration();
const content = tree.readContent('/index.ts');
expect(content).toContain(`@angular/common/http/testing`);
expect(content).toContain(`'@angular/common/http/testing'`);
expect(content).toContain(`'@angular/common/http'`);
expect(content).toMatch(/import.*provideHttpClient.*withInterceptorsFromDi.*from/);
expect(content).not.toContain(`HttpClientTestingModule`);
expect(content).toMatch(/import.*provideHttpClientTesting/);
expect(content).toContain(
@@ -347,7 +375,7 @@ describe('Http providers migration', () => {
expect(content).not.toContain('provideHttpClientTesting');
});
it('shouldmigrate NgModule + TestBed.configureTestingModule in the same file', async () => {
it('should migrate NgModule + TestBed.configureTestingModule in the same file', async () => {
writeFile(
'/index.ts',
`
@@ -110,6 +110,8 @@ export class ChangeTracker {
* @param sourceFile File to which to add the import.
* @param symbolName Symbol being imported.
* @param moduleName Module from which the symbol is imported.
* @param alias Alias to use for the import.
* @param keepSymbolName Whether to keep the symbol name in the import.
*/
addImport(
sourceFile: ts.SourceFile,
+1
View File
@@ -26,6 +26,7 @@ export {
NotificationSource as ɵNotificationSource,
ZONELESS_ENABLED as ɵZONELESS_ENABLED,
} from './change_detection/scheduling/zoneless_scheduling';
export {PROVIDED_NG_ZONE as ɵPROVIDED_NG_ZONE} from './change_detection/scheduling/ng_zone_scheduling';
export {Console as ɵConsole} from './console';
export {
DeferBlockDetails as ɵDeferBlockDetails,
@@ -927,11 +927,10 @@ export class TestBedCompiler {
private compileTestModule(): void {
class RootScopeModule {}
compileNgModuleDefs(RootScopeModule as NgModuleType<any>, {
providers: [...this.rootProviderOverrides],
providers: [...this.rootProviderOverrides, provideZoneChangeDetection()],
});
const providers = [
provideZoneChangeDetection(),
{provide: Compiler, useFactory: () => new R3TestCompiler(this)},
{provide: DEFER_BLOCK_CONFIG, useValue: {behavior: this.deferBlockBehavior}},
...this.providers,
@@ -7,7 +7,7 @@
*/
import {XhrFactory} from '@angular/common';
import {HttpBackend, ɵPRIMARY_HTTP_BACKEND as PRIMARY_HTTP_BACKEND} from '@angular/common/http';
import {HttpBackend} from '@angular/common/http';
import {ModuleWithProviders, NgModule, Type} from '@angular/core';
import {HttpClientBackendService} from './http-client-backend-service';
@@ -57,7 +57,6 @@ export class HttpClientInMemoryWebApiModule {
useFactory: httpClientInMemBackendServiceFactory,
deps: [InMemoryDbService, InMemoryBackendConfig, XhrFactory],
},
{provide: PRIMARY_HTTP_BACKEND, useExisting: HttpBackend},
],
};
}
@@ -7,7 +7,7 @@
*/
import {XhrFactory} from '@angular/common';
import {HttpBackend, ɵPRIMARY_HTTP_BACKEND as PRIMARY_HTTP_BACKEND} from '@angular/common/http';
import {HttpBackend} from '@angular/common/http';
import {ModuleWithProviders, NgModule, Type} from '@angular/core';
import {httpClientInMemBackendServiceFactory} from './http-client-in-memory-web-api-module';
@@ -47,7 +47,6 @@ export class InMemoryWebApiModule {
useFactory: httpClientInMemBackendServiceFactory,
deps: [InMemoryDbService, InMemoryBackendConfig, XhrFactory],
},
{provide: PRIMARY_HTTP_BACKEND, useExisting: HttpBackend},
],
};
}
@@ -65,7 +65,10 @@ export class AsyncAnimationRendererFactory implements OnDestroy, RendererFactory
* @internal
*/
private loadImpl(): Promise<AnimationRendererFactory> {
const moduleImpl = this.moduleImpl ?? import('@angular/animations/browser');
// Note on the `.then(m => m)` part below: Closure compiler optimizations in g3 require
// `.then` to be present for a dynamic import (or an import should be `await`ed) to detect
// the set of imported symbols.
const moduleImpl = this.moduleImpl ?? import('@angular/animations/browser').then((m) => m);
return moduleImpl
.catch((e) => {
+34 -19
View File
@@ -71,6 +71,38 @@ function removeEventDispatchScript(doc: Document) {
findEventDispatchScript(doc)?.remove();
}
/**
* Annotate nodes for hydration and remove event dispatch script when not needed.
*/
function prepareForHydration(platformState: PlatformState, applicationRef: ApplicationRef): void {
const environmentInjector = applicationRef.injector;
const doc = platformState.getDocument();
if (!environmentInjector.get(IS_HYDRATION_DOM_REUSE_ENABLED, false)) {
// Hydration is diabled, remove inlined event dispatch script.
// (which was injected by the build process) from the HTML.
removeEventDispatchScript(doc);
return;
}
appendSsrContentIntegrityMarker(doc);
const eventTypesToBeReplayed = annotateForHydration(applicationRef, doc);
if (eventTypesToBeReplayed) {
insertEventRecordScript(
environmentInjector.get(APP_ID),
doc,
eventTypesToBeReplayed,
environmentInjector.get(CSP_NONCE, null),
);
} else {
// No events to replay, we should remove inlined event dispatch script
// (which was injected by the build process) from the HTML.
removeEventDispatchScript(doc);
}
}
/**
* Creates a marker comment node and append it into the `<body>`.
* Some CDNs have mechanisms to remove all comment node from HTML.
@@ -124,31 +156,14 @@ function insertEventRecordScript(
}
async function _render(platformRef: PlatformRef, applicationRef: ApplicationRef): Promise<string> {
const environmentInjector = applicationRef.injector;
// Block until application is stable.
await whenStable(applicationRef);
const platformState = platformRef.injector.get(PlatformState);
if (environmentInjector.get(IS_HYDRATION_DOM_REUSE_ENABLED, false)) {
const doc = platformState.getDocument();
appendSsrContentIntegrityMarker(doc);
const eventTypesToBeReplayed = annotateForHydration(applicationRef, doc);
if (eventTypesToBeReplayed) {
insertEventRecordScript(
environmentInjector.get(APP_ID),
doc,
eventTypesToBeReplayed,
environmentInjector.get(CSP_NONCE, null),
);
} else {
// No events to replay, we should remove inlined event dispatch script
// (which was injected by the build process) from the HTML.
removeEventDispatchScript(doc);
}
}
prepareForHydration(platformState, applicationRef);
// Run any BEFORE_APP_SERIALIZED callbacks just before rendering to string.
const environmentInjector = applicationRef.injector;
const callbacks = environmentInjector.get(BEFORE_APP_SERIALIZED, null);
if (callbacks) {
const asyncCallbacks: Promise<void>[] = [];
@@ -54,19 +54,27 @@ describe('event replay', () => {
*/
async function ssr(
component: Type<unknown>,
options?: {doc?: string; enableEventReplay?: boolean},
options: {doc?: string; enableEventReplay?: boolean; hydrationDisabled?: boolean} = {},
): Promise<string> {
const enableEventReplay = options?.enableEventReplay ?? true;
const defaultHtml = `<html><head></head><body>${EVENT_DISPATCH_SCRIPT}<app></app></body></html>`;
const hydrationProviders = enableEventReplay
? provideClientHydration(withEventReplay())
: provideClientHydration();
const providers = [provideServerRendering(), hydrationProviders];
const {
enableEventReplay = true,
hydrationDisabled,
doc = `<html><head></head><body>${EVENT_DISPATCH_SCRIPT}<app></app></body></html>`,
} = options;
const bootstrap = () => bootstrapApplication(component, {providers});
const hydrationProviders = hydrationDisabled
? []
: enableEventReplay
? provideClientHydration(withEventReplay())
: provideClientHydration();
const bootstrap = () =>
bootstrapApplication(component, {
providers: [provideServerRendering(), hydrationProviders],
});
return renderApplication(bootstrap, {
document: options?.doc ?? defaultHtml,
document: doc,
});
}
@@ -208,6 +216,24 @@ describe('event replay', () => {
});
describe('event dispatch script', () => {
it('should not be present on a page when hydration is disabled', async () => {
@Component({
standalone: true,
selector: 'app',
template: '<input (click)="onClick()" />',
})
class SimpleComponent {
onClick() {}
}
const doc = `<html><head></head><body>${EVENT_DISPATCH_SCRIPT}<app></app></body></html>`;
const html = await ssr(SimpleComponent, {doc, hydrationDisabled: true});
const ssrContents = getAppContents(html);
expect(hasJSActionAttrs(ssrContents)).toBeFalse();
expect(hasEventDispatchScript(ssrContents)).toBeFalse();
});
it('should not be present on a page if there are no events to replay', async () => {
@Component({
standalone: true,
+4 -1
View File
@@ -108,7 +108,10 @@ export function createViewTransition(
return injector.get(NgZone).runOutsideAngular(() => {
if (!document.startViewTransition || transitionOptions.skipNextTransition) {
transitionOptions.skipNextTransition = false;
return Promise.resolve();
// The timing of `startViewTransition` is closer to a macrotask. It won't be called
// until the current event loop exits so we use a promise resolved in a timeout instead
// of Promise.resolve().
return new Promise((resolve) => setTimeout(resolve));
}
let resolveViewTransitionStarted: () => void;
+88 -88
View File
@@ -10,7 +10,7 @@
"@jridgewell/gen-mapping" "^0.3.5"
"@jridgewell/trace-mapping" "^0.3.24"
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.1", "@babel/code-frame@^7.24.2":
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.2":
version "7.24.2"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae"
integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==
@@ -24,32 +24,32 @@
integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==
"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9":
version "7.24.4"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.4.tgz#1f758428e88e0d8c563874741bc4ffc4f71a4717"
integrity sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==
version "7.24.5"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.5.tgz#15ab5b98e101972d171aeef92ac70d8d6718f06a"
integrity sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==
dependencies:
"@ampproject/remapping" "^2.2.0"
"@babel/code-frame" "^7.24.2"
"@babel/generator" "^7.24.4"
"@babel/generator" "^7.24.5"
"@babel/helper-compilation-targets" "^7.23.6"
"@babel/helper-module-transforms" "^7.23.3"
"@babel/helpers" "^7.24.4"
"@babel/parser" "^7.24.4"
"@babel/helper-module-transforms" "^7.24.5"
"@babel/helpers" "^7.24.5"
"@babel/parser" "^7.24.5"
"@babel/template" "^7.24.0"
"@babel/traverse" "^7.24.1"
"@babel/types" "^7.24.0"
"@babel/traverse" "^7.24.5"
"@babel/types" "^7.24.5"
convert-source-map "^2.0.0"
debug "^4.1.0"
gensync "^1.0.0-beta.2"
json5 "^2.2.3"
semver "^6.3.1"
"@babel/generator@^7.24.1", "@babel/generator@^7.24.4", "@babel/generator@^7.7.2":
version "7.24.4"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.4.tgz#1fc55532b88adf952025d5d2d1e71f946cb1c498"
integrity sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==
"@babel/generator@^7.24.5", "@babel/generator@^7.7.2":
version "7.24.5"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.5.tgz#e5afc068f932f05616b66713e28d0f04e99daeb3"
integrity sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==
dependencies:
"@babel/types" "^7.24.0"
"@babel/types" "^7.24.5"
"@jridgewell/gen-mapping" "^0.3.5"
"@jridgewell/trace-mapping" "^0.3.25"
jsesc "^2.5.1"
@@ -85,81 +85,81 @@
dependencies:
"@babel/types" "^7.22.5"
"@babel/helper-module-imports@^7.22.15":
"@babel/helper-module-imports@^7.24.3":
version "7.24.3"
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz#6ac476e6d168c7c23ff3ba3cf4f7841d46ac8128"
integrity sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==
dependencies:
"@babel/types" "^7.24.0"
"@babel/helper-module-transforms@^7.23.3":
version "7.23.3"
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1"
integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==
"@babel/helper-module-transforms@^7.24.5":
version "7.24.5"
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz#ea6c5e33f7b262a0ae762fd5986355c45f54a545"
integrity sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==
dependencies:
"@babel/helper-environment-visitor" "^7.22.20"
"@babel/helper-module-imports" "^7.22.15"
"@babel/helper-simple-access" "^7.22.5"
"@babel/helper-split-export-declaration" "^7.22.6"
"@babel/helper-validator-identifier" "^7.22.20"
"@babel/helper-module-imports" "^7.24.3"
"@babel/helper-simple-access" "^7.24.5"
"@babel/helper-split-export-declaration" "^7.24.5"
"@babel/helper-validator-identifier" "^7.24.5"
"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.8.0":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a"
integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==
version "7.24.5"
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz#a924607dd254a65695e5bd209b98b902b3b2f11a"
integrity sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==
"@babel/helper-simple-access@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de"
integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==
"@babel/helper-simple-access@^7.24.5":
version "7.24.5"
resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz#50da5b72f58c16b07fbd992810be6049478e85ba"
integrity sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==
dependencies:
"@babel/types" "^7.22.5"
"@babel/types" "^7.24.5"
"@babel/helper-split-export-declaration@^7.22.6":
version "7.22.6"
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c"
integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==
"@babel/helper-split-export-declaration@^7.24.5":
version "7.24.5"
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz#b9a67f06a46b0b339323617c8c6213b9055a78b6"
integrity sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==
dependencies:
"@babel/types" "^7.22.5"
"@babel/types" "^7.24.5"
"@babel/helper-string-parser@^7.23.4":
"@babel/helper-string-parser@^7.24.1":
version "7.24.1"
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz#f99c36d3593db9540705d0739a1f10b5e20c696e"
integrity sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==
"@babel/helper-validator-identifier@^7.22.20":
version "7.22.20"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
"@babel/helper-validator-identifier@^7.24.5":
version "7.24.5"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz#918b1a7fa23056603506370089bd990d8720db62"
integrity sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==
"@babel/helper-validator-option@^7.23.5":
version "7.23.5"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307"
integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==
"@babel/helpers@^7.24.4":
version "7.24.4"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.4.tgz#dc00907fd0d95da74563c142ef4cd21f2cb856b6"
integrity sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==
"@babel/helpers@^7.24.5":
version "7.24.5"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.5.tgz#fedeb87eeafa62b621160402181ad8585a22a40a"
integrity sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==
dependencies:
"@babel/template" "^7.24.0"
"@babel/traverse" "^7.24.1"
"@babel/types" "^7.24.0"
"@babel/traverse" "^7.24.5"
"@babel/types" "^7.24.5"
"@babel/highlight@^7.24.2":
version "7.24.2"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.2.tgz#3f539503efc83d3c59080a10e6634306e0370d26"
integrity sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==
version "7.24.5"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.5.tgz#bc0613f98e1dd0720e99b2a9ee3760194a704b6e"
integrity sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==
dependencies:
"@babel/helper-validator-identifier" "^7.22.20"
"@babel/helper-validator-identifier" "^7.24.5"
chalk "^2.4.2"
js-tokens "^4.0.0"
picocolors "^1.0.0"
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.24.0", "@babel/parser@^7.24.1", "@babel/parser@^7.24.4":
version "7.24.4"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.4.tgz#234487a110d89ad5a3ed4a8a566c36b9453e8c88"
integrity sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.24.0", "@babel/parser@^7.24.5":
version "7.24.5"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.5.tgz#4a4d5ab4315579e5398a82dcf636ca80c3392790"
integrity sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==
"@babel/plugin-syntax-async-generators@^7.8.4":
version "7.8.4"
@@ -268,29 +268,29 @@
"@babel/parser" "^7.24.0"
"@babel/types" "^7.24.0"
"@babel/traverse@^7.24.1":
version "7.24.1"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.1.tgz#d65c36ac9dd17282175d1e4a3c49d5b7988f530c"
integrity sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==
"@babel/traverse@^7.24.5":
version "7.24.5"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.5.tgz#972aa0bc45f16983bf64aa1f877b2dd0eea7e6f8"
integrity sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==
dependencies:
"@babel/code-frame" "^7.24.1"
"@babel/generator" "^7.24.1"
"@babel/code-frame" "^7.24.2"
"@babel/generator" "^7.24.5"
"@babel/helper-environment-visitor" "^7.22.20"
"@babel/helper-function-name" "^7.23.0"
"@babel/helper-hoist-variables" "^7.22.5"
"@babel/helper-split-export-declaration" "^7.22.6"
"@babel/parser" "^7.24.1"
"@babel/types" "^7.24.0"
"@babel/helper-split-export-declaration" "^7.24.5"
"@babel/parser" "^7.24.5"
"@babel/types" "^7.24.5"
debug "^4.3.1"
globals "^11.1.0"
"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.24.0", "@babel/types@^7.3.3":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf"
integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==
"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.24.0", "@babel/types@^7.24.5", "@babel/types@^7.3.3":
version "7.24.5"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.5.tgz#7661930afc638a5383eb0c4aee59b74f38db84d7"
integrity sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==
dependencies:
"@babel/helper-string-parser" "^7.23.4"
"@babel/helper-validator-identifier" "^7.22.20"
"@babel/helper-string-parser" "^7.24.1"
"@babel/helper-validator-identifier" "^7.24.5"
to-fast-properties "^2.0.0"
"@bcoe/v8-coverage@^0.2.3":
@@ -636,9 +636,9 @@
parse5 "^7.0.0"
"@types/node@*":
version "20.12.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.7.tgz#04080362fa3dd6c5822061aa3124f5c152cff384"
integrity sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==
version "20.12.8"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.8.tgz#35897bf2bfe3469847ab04634636de09552e8256"
integrity sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==
dependencies:
undici-types "~5.26.4"
@@ -895,9 +895,9 @@ camelcase@^6.0.0, camelcase@^6.2.0:
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
caniuse-lite@^1.0.30001587:
version "1.0.30001614"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001614.tgz#f894b4209376a0bf923d67d9c361d96b1dfebe39"
integrity sha512-jmZQ1VpmlRwHgdP1/uiKzgiAuGOfLEJsYFP4+GBou/QQ4U6IOJCB4NP1c+1p9RGLpwObcT94jA5/uO+F1vBbog==
version "1.0.30001616"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001616.tgz#4342712750d35f71ebba9fcac65e2cf8870013c3"
integrity sha512-RHVYKov7IcdNjVHJFNY/78RdG4oGVjbayxv8u5IO74Wv7Hlq4PnJE6mo/OjFijjVFNy5ijnCt6H3IIo4t+wfEw==
chalk@4.x, chalk@^4.0.0, chalk@^4.1.0:
version "4.1.2"
@@ -1151,9 +1151,9 @@ domexception@^4.0.0:
resolved "https://github.com/angular/domino.git#8f228f8862540c6ccd14f76b5a1d9bb5458618af"
electron-to-chromium@^1.4.668:
version "1.4.750"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.750.tgz#d278a619af727ed069de1317115187282b1131ee"
integrity sha512-9ItEpeu15hW5m8jKdriL+BQrgwDTXEL9pn4SkillWFu73ZNNNQ2BKKLS+ZHv2vC9UkNhosAeyfxOf/5OSeTCPA==
version "1.4.756"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.756.tgz#7b872ed8c8c5bee571be771730225d6d2a37fe45"
integrity sha512-RJKZ9+vEBMeiPAvKNWyZjuYyUqMndcP1f335oHqn3BEQbs2NFtVrnK5+6Xg5wSM9TknNNpWghGDUCKGYF+xWXw==
emittery@^0.13.1:
version "0.13.1"
@@ -1177,7 +1177,7 @@ error-ex@^1.3.1:
dependencies:
is-arrayish "^0.2.1"
escalade@^3.1.1:
escalade@^3.1.1, escalade@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27"
integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==
@@ -2707,9 +2707,9 @@ to-regex-range@^5.0.1:
is-number "^7.0.0"
tough-cookie@^4.1.2:
version "4.1.3"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf"
integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==
version "4.1.4"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36"
integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==
dependencies:
psl "^1.1.33"
punycode "^2.1.1"
@@ -2749,11 +2749,11 @@ universalify@^0.2.0:
integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==
update-browserslist-db@^1.0.13:
version "1.0.13"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4"
integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==
version "1.0.15"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.15.tgz#60ed9f8cba4a728b7ecf7356f641a31e3a691d97"
integrity sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==
dependencies:
escalade "^3.1.1"
escalade "^3.1.2"
picocolors "^1.0.0"
url-parse@^1.5.3:
+11 -5
View File
@@ -2,7 +2,6 @@
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"baseBranches": ["main"],
"enabledManagers": ["npm", "bazel", "github-actions"],
"stopUpdatingLabel": "action: merge",
"rangeStrategy": "replace",
"pinDigests": true,
"semanticCommits": "enabled",
@@ -51,14 +50,14 @@
],
"packageRules": [
{
"matchPackagePatterns": ["*"],
"matchDepPatterns": ["*"],
"matchUpdateTypes": ["minor", "patch"],
"groupName": "all non-major dependencies",
"schedule": ["after 10:00pm on monday", "before 04:00am on tuesday"]
},
{
"matchPackagePatterns": ["^@bazel/.*", "^build_bazel.*"],
"matchDepPatterns": ["^@bazel/.*", "^build_bazel.*"],
"groupName": "bazel setup",
"schedule": ["at any time"]
},
@@ -72,7 +71,11 @@
{
"matchPackagePrefixes": ["@angular/", "angular/", "@angular-devkit", "@schematics/"],
"matchPaths": ["packages/**", "aio/tools/examples/shared/**", "adev/src/content/tutorials/**"],
"matchPaths": [
"packages/**",
"aio/tools/examples/shared/**",
"adev/src/content/tutorials/**"
],
"followTag": null
},
@@ -107,6 +110,9 @@
{"matchCurrentVersion": "0.0.0-PLACEHOLDER", "enabled": false},
{"matchPaths": ["integration/**", "packages/zone.js/test/typings/package.json"], "enabled": false}
{
"matchPaths": ["integration/**", "packages/zone.js/test/typings/package.json"],
"enabled": false
}
]
}
+65 -54
View File
@@ -2205,9 +2205,9 @@
"@lezer/lr" "^1.0.0"
"@lezer/javascript@^1.0.0", "@lezer/javascript@^1.4.10":
version "1.4.15"
resolved "https://registry.yarnpkg.com/@lezer/javascript/-/javascript-1.4.15.tgz#e248c0e62ffdb913b5fcfff97b0b60e6f098c39c"
integrity sha512-B082ZdjI0vo2AgLqD834GlRTE9gwRX8NzHzKq5uDwEnQ9Dq+A/CEhd3nf68tiNA2f9O+8jS1NeSTUYT9IAqcTw==
version "1.4.16"
resolved "https://registry.yarnpkg.com/@lezer/javascript/-/javascript-1.4.16.tgz#20f0ba832b7bf4f1333513549f2f7ca459a9dc93"
integrity sha512-84UXR3N7s11MPQHWgMnjb9571fr19MmXnr5zTv2XX0gHXXUvW3uPJ8GCjKrfTXmSdfktjRK0ayKklw+A13rk4g==
dependencies:
"@lezer/common" "^1.2.0"
"@lezer/highlight" "^1.1.3"
@@ -3031,9 +3031,9 @@
semver "^7.3.5"
"@npmcli/git@^5.0.0":
version "5.0.6"
resolved "https://registry.yarnpkg.com/@npmcli/git/-/git-5.0.6.tgz#d7b24eb2cff98754c8868faab40405abfa1abe28"
integrity sha512-4x/182sKXmQkf0EtXxT26GEsaOATpD7WVtza5hrYivWZeo6QefC6xq9KAXrnjtFKBZ4rZwR7aX/zClYYXgtwLw==
version "5.0.7"
resolved "https://registry.yarnpkg.com/@npmcli/git/-/git-5.0.7.tgz#7ff675e33b4dc0b0adb1f0c4aa302109efc06463"
integrity sha512-WaOVvto604d5IpdCRV2KjQu8PzkfE96d50CQGKgywXh2GxXmDeUO5EWcBC4V57uFyrNqx83+MewuJh3WTR3xPA==
dependencies:
"@npmcli/promise-spawn" "^7.0.0"
lru-cache "^10.0.1"
@@ -3071,9 +3071,9 @@
semver "^7.5.3"
"@npmcli/promise-spawn@^7.0.0":
version "7.0.1"
resolved "https://registry.yarnpkg.com/@npmcli/promise-spawn/-/promise-spawn-7.0.1.tgz#a836de2f42a2245d629cf6fbb8dd6c74c74c55af"
integrity sha512-P4KkF9jX3y+7yFUxgcUdDtLy+t4OlDGuEBLNs57AZsfSfg+uV6MLndqGpnl4831ggaEdXwR50XFoZP4VFtHolg==
version "7.0.2"
resolved "https://registry.yarnpkg.com/@npmcli/promise-spawn/-/promise-spawn-7.0.2.tgz#1d53d34ffeb5d151bfa8ec661bcccda8bbdfd532"
integrity sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==
dependencies:
which "^4.0.0"
@@ -4212,7 +4212,6 @@
"@types/node" "*"
"@types/selenium-webdriver4@npm:@types/selenium-webdriver@4.1.22", "@types/selenium-webdriver@^4.1.21":
name "@types/selenium-webdriver4"
version "4.1.22"
resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-4.1.22.tgz#344519b90727eb713e1ce6d2e0198eb0b4f8f316"
integrity sha512-MCL4l7q8dwxejr2Q2NXLyNwHWMPdlWE0Kpn6fFwJtvkJF7PTkG5jkvbH/X1IAAQxgt/L1dA8u2GtDeekvSKvOA==
@@ -5579,9 +5578,9 @@ c8@~7.5.0:
yargs-parser "^20.0.0"
cacache@^18.0.0:
version "18.0.2"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-18.0.2.tgz#fd527ea0f03a603be5c0da5805635f8eef00c60c"
integrity sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==
version "18.0.3"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-18.0.3.tgz#864e2c18414e1e141ae8763f31e46c2cb96d1b21"
integrity sha512-qXCd4rh6I07cnDqh8V48/94Tc/WSfj+o3Gn6NZ0aZovS255bUx8O13uKxRFd2eWG0xgsco7+YItQNPaa5E85hg==
dependencies:
"@npmcli/fs" "^3.1.0"
fs-minipass "^3.0.0"
@@ -5654,9 +5653,9 @@ camelcase@^6.2.0:
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
caniuse-lite@^1.0.30001587, caniuse-lite@^1.0.30001599:
version "1.0.30001615"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001615.tgz#7c2c8772db681b6dee74d81d6550db68f2d28842"
integrity sha512-1IpazM5G3r38meiae0bHRnPhz+CBQ3ZLqbQMtrg+AsTPKAXgW38JNsXkyZ+v8waCsDmPq87lmfun5Q2AGysNEQ==
version "1.0.30001616"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001616.tgz#4342712750d35f71ebba9fcac65e2cf8870013c3"
integrity sha512-RHVYKov7IcdNjVHJFNY/78RdG4oGVjbayxv8u5IO74Wv7Hlq4PnJE6mo/OjFijjVFNy5ijnCt6H3IIo4t+wfEw==
canonical-path@1.0.0:
version "1.0.0"
@@ -7311,7 +7310,8 @@ domhandler@^5.0.2, domhandler@^5.0.3:
domelementtype "^2.3.0"
"domino@https://github.com/angular/domino.git#8f228f8862540c6ccd14f76b5a1d9bb5458618af":
version "2.1.6"
version "2.1.6+git"
uid "8f228f8862540c6ccd14f76b5a1d9bb5458618af"
resolved "https://github.com/angular/domino.git#8f228f8862540c6ccd14f76b5a1d9bb5458618af"
dompurify@^3.0.5:
@@ -7409,9 +7409,9 @@ ee-first@1.1.1:
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
electron-to-chromium@^1.4.668:
version "1.4.755"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.755.tgz#e26b3f5955b9de75a24048587521bde22fa4e0a0"
integrity sha512-9nop+3jZxSHIxe1EzEUcjDXzK+3qOv3fY5w0sE88nIZUntbv1aXWmoxGWlklX5XSO4txCpLssWkUSh8RQPovBg==
version "1.4.756"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.756.tgz#7b872ed8c8c5bee571be771730225d6d2a37fe45"
integrity sha512-RJKZ9+vEBMeiPAvKNWyZjuYyUqMndcP1f335oHqn3BEQbs2NFtVrnK5+6Xg5wSM9TknNNpWghGDUCKGYF+xWXw==
elkjs@^0.9.0:
version "0.9.3"
@@ -8616,9 +8616,9 @@ get-symbol-description@^1.0.2:
get-intrinsic "^1.2.4"
get-tsconfig@^4.7.3:
version "4.7.3"
resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.3.tgz#0498163d98f7b58484dd4906999c0c9d5f103f83"
integrity sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==
version "4.7.4"
resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.4.tgz#228e1a3e37125aeb4467e9b992b92c4533093bd2"
integrity sha512-ofbkKj+0pjXjhejr007J/fLf+sW+8H7K5GCm+msC8q3IpvgjobpyPqSRFemNyIMxklC0zeJpi7VDFna19FacvQ==
dependencies:
resolve-pkg-maps "^1.0.0"
@@ -9165,9 +9165,9 @@ homedir-polyfill@^1.0.1:
parse-passwd "^1.0.0"
hosted-git-info@^7.0.0:
version "7.0.1"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-7.0.1.tgz#9985fcb2700467fecf7f33a4d4874e30680b5322"
integrity sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==
version "7.0.2"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-7.0.2.tgz#9b751acac097757667f30114607ef7b661ff4f17"
integrity sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==
dependencies:
lru-cache "^10.0.1"
@@ -9382,9 +9382,9 @@ ieee754@^1.1.13, ieee754@^1.2.1:
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
ignore-walk@^6.0.4:
version "6.0.4"
resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-6.0.4.tgz#89950be94b4f522225eb63a13c56badb639190e9"
integrity sha512-t7sv42WkwFkyKbivUCglsQW5YWMskWtbEf4MNKX5u/CCWHKSPzN4FtBQGsQZgCLbxOzpVlcbWVK5KB3auIOjSw==
version "6.0.5"
resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-6.0.5.tgz#ef8d61eab7da169078723d1f82833b36e200b0dd"
integrity sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==
dependencies:
minimatch "^9.0.0"
@@ -10326,9 +10326,9 @@ json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1:
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
json-parse-even-better-errors@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz#02bb29fb5da90b5444581749c22cedd3597c6cb0"
integrity sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==
version "3.0.2"
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz#b43d35e89c0f3be6b5fbbe9dc6c82467b30c28da"
integrity sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==
json-parse-helpfulerror@^1.0.3:
version "1.0.3"
@@ -11582,9 +11582,9 @@ minipass-collect@^2.0.1:
minipass "^7.0.3"
minipass-fetch@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-3.0.4.tgz#4d4d9b9f34053af6c6e597a64be8e66e42bf45b7"
integrity sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==
version "3.0.5"
resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-3.0.5.tgz#f0f97e40580affc4a35cc4a1349f05ae36cb1e4c"
integrity sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==
dependencies:
minipass "^7.0.3"
minipass-sized "^1.0.3"
@@ -11634,9 +11634,9 @@ minipass@^5.0.0:
integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==
"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.2, minipass@^7.0.3, minipass@^7.0.4:
version "7.0.4"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c"
integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==
version "7.1.0"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.0.tgz#b545f84af94e567386770159302ca113469c80b8"
integrity sha512-oGZRv2OT1lO2UF1zUcwdTb3wqUwI0kBGTgt/T7OdSj6M6N5m3o5uPf0AIW6lVxGGoiWUR7e2AwTE+xiwK8WQig==
minizlib@^2.1.1, minizlib@^2.1.2:
version "2.1.2"
@@ -11896,16 +11896,16 @@ non-layered-tidy-tree-layout@^2.0.2:
integrity sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==
nopt@^7.0.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-7.2.0.tgz#067378c68116f602f552876194fd11f1292503d7"
integrity sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==
version "7.2.1"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-7.2.1.tgz#1cac0eab9b8e97c9093338446eddd40b2c8ca1e7"
integrity sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==
dependencies:
abbrev "^2.0.0"
normalize-package-data@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-6.0.0.tgz#68a96b3c11edd462af7189c837b6b1064a484196"
integrity sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==
version "6.0.1"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-6.0.1.tgz#fa69e9452210f0fabf4d79ee08d0c2870c51ed88"
integrity sha512-6rvCfeRW+OEZagAB4lMLSNuTNYZWLVtKccK79VSTf//yTY5VOCgcpH80O+bZK8Neps7pUnd5G+QlMg1yV/2iZQ==
dependencies:
hosted-git-info "^7.0.0"
is-core-module "^2.8.1"
@@ -11970,7 +11970,7 @@ npm-packlist@^8.0.0:
dependencies:
ignore-walk "^6.0.4"
npm-pick-manifest@9.0.0, npm-pick-manifest@^9.0.0:
npm-pick-manifest@9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-9.0.0.tgz#f87a4c134504a2c7931f2bb8733126e3c3bb7e8f"
integrity sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg==
@@ -11980,6 +11980,16 @@ npm-pick-manifest@9.0.0, npm-pick-manifest@^9.0.0:
npm-package-arg "^11.0.0"
semver "^7.3.5"
npm-pick-manifest@^9.0.0:
version "9.0.1"
resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-9.0.1.tgz#c90658bd726fe5bca9d2869f3e99359b8fcda046"
integrity sha512-Udm1f0l2nXb3wxDpKjfohwgdFUSV50UVwzEIpDXVsbDMXVIEF81a/i0UhuQbhrPMMmdiq3+YMFLFIRVLs3hxQw==
dependencies:
npm-install-checks "^6.0.0"
npm-normalize-package-bin "^3.0.0"
npm-package-arg "^11.0.0"
semver "^7.3.5"
npm-registry-fetch@^17.0.0:
version "17.0.1"
resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-17.0.1.tgz#c13cfd4c022713f09d23af5fba8b6ec59a17609e"
@@ -13854,6 +13864,7 @@ sass@1.76.0:
"sauce-connect@https://saucelabs.com/downloads/sc-4.9.1-linux.tar.gz":
version "0.0.0"
uid "9310bc860f7870a1f872b11c4dc6073a1ad34e5e"
resolved "https://saucelabs.com/downloads/sc-4.9.1-linux.tar.gz#9310bc860f7870a1f872b11c4dc6073a1ad34e5e"
saucelabs@7.5.0, saucelabs@^1.5.0, saucelabs@^4.6.3:
@@ -14539,9 +14550,9 @@ sshpk@^1.7.0:
tweetnacl "~0.14.0"
ssri@^10.0.0:
version "10.0.5"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.5.tgz#e49efcd6e36385196cb515d3a2ad6c3f0265ef8c"
integrity sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==
version "10.0.6"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.6.tgz#a8aade2de60ba2bce8688e3fa349bad05c7dc1e5"
integrity sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==
dependencies:
minipass "^7.0.3"
@@ -15244,9 +15255,9 @@ tsutils@^2.29.0:
tslib "^1.8.1"
tsx@^4.7.2:
version "4.9.0"
resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.9.0.tgz#08d7ea58df19d87416d26cce8caf93d0c3619852"
integrity sha512-UY0UUhDPL6MkqkZU4xTEjEBOLfV+RIt4xeeJ1qwK73xai4/zveG+X6+tieILa7rjtegUW2LE4p7fw7gAoLuytA==
version "4.9.3"
resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.9.3.tgz#801ca18ca22b3d2f7acd89d4b888aa2425ea1302"
integrity sha512-czVbetlILiyJZI5zGlj2kw9vFiSeyra9liPD4nG+Thh4pKTi0AmMEQ8zdV/L2xbIVKrIqif4sUNrsMAOksx9Zg==
dependencies:
esbuild "~0.20.2"
get-tsconfig "^4.7.3"
@@ -15599,9 +15610,9 @@ unpipe@1.0.0, unpipe@~1.0.0:
integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
update-browserslist-db@^1.0.13:
version "1.0.14"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.14.tgz#46a9367c323f8ade9a9dddb7f3ae7814b3a0b31c"
integrity sha512-JixKH8GR2pWYshIPUg/NujK3JO7JiqEEUiNArE86NQyrgUuZeTlZQN3xuS/yiV5Kb48ev9K6RqNkaJjXsdg7Jw==
version "1.0.15"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.15.tgz#60ed9f8cba4a728b7ecf7356f641a31e3a691d97"
integrity sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==
dependencies:
escalade "^3.1.2"
picocolors "^1.0.0"