diff --git a/packages/angular/build/BUILD.bazel b/packages/angular/build/BUILD.bazel index 52eb43f9472c..4f4b8f003de0 100644 --- a/packages/angular/build/BUILD.bazel +++ b/packages/angular/build/BUILD.bazel @@ -85,6 +85,7 @@ ts_project( ":node_modules/@babel/helper-annotate-as-pure", ":node_modules/@babel/helper-split-export-declaration", ":node_modules/@inquirer/confirm", + ":node_modules/@oxc-project/types", ":node_modules/@vitejs/plugin-basic-ssl", ":node_modules/beasties", ":node_modules/browserslist", @@ -97,6 +98,7 @@ ts_project( ":node_modules/magic-string", ":node_modules/mrmime", ":node_modules/ng-packagr", + ":node_modules/oxc-parser", ":node_modules/parse5-html-rewriting-stream", ":node_modules/picomatch", ":node_modules/piscina", diff --git a/packages/angular/build/package.json b/packages/angular/build/package.json index 90d2e99c0dda..2bd38201d6ce 100644 --- a/packages/angular/build/package.json +++ b/packages/angular/build/package.json @@ -33,6 +33,7 @@ "listr2": "10.2.2", "magic-string": "0.30.21", "mrmime": "2.0.1", + "oxc-parser": "0.140.0", "parse5-html-rewriting-stream": "8.0.1", "picomatch": "4.0.5", "piscina": "5.2.0", @@ -50,6 +51,7 @@ "devDependencies": { "@angular-devkit/core": "workspace:*", "@angular/ssr": "workspace:*", + "@oxc-project/types": "0.140.0", "istanbul-lib-instrument": "6.0.3", "jsdom": "29.1.1", "less": "4.6.7", diff --git a/packages/angular/build/src/tools/babel/plugins/adjust-static-class-members_oxc_spec.ts b/packages/angular/build/src/tools/babel/plugins/adjust-static-class-members_oxc_spec.ts new file mode 100644 index 000000000000..af28ab66b264 --- /dev/null +++ b/packages/angular/build/src/tools/babel/plugins/adjust-static-class-members_oxc_spec.ts @@ -0,0 +1,1001 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { transform } from './oxc-transform'; + +const NO_CHANGE = Symbol('NO_CHANGE'); + +function cleanCode(code: string): string { + return code.replace(/\s+/g, '').replace(/,([}\])])/g, '$1'); +} + +function testCase({ + input, + expected, + options, +}: { + input: string; + expected: string | typeof NO_CHANGE; + options?: { wrapDecorators?: boolean }; +}): jasmine.ImplementationCallback { + return async () => { + const result = transform('test.js', input, { + sourcemap: false, + sideEffects: options?.wrapDecorators ? false : true, + pureAnnotate: false, + }); + if (!result?.code) { + fail('Expected oxc-transform to return a transform result.'); + } else { + const actualClean = cleanCode(result.code); + const expectedClean = cleanCode(expected === NO_CHANGE ? input : expected); + expect(actualClean).toEqual(expectedClean); + } + }; +} + +describe('adjust-static-class-members oxc-transform implementation', () => { + it( + 'elides empty ctorParameters function expression static field', + testCase({ + input: ` + export class SomeClass {} + SomeClass.ctorParameters = function () { return []; }; + `, + expected: 'export class SomeClass {}', + }), + ); + + it( + 'elides non-empty ctorParameters function expression static field', + testCase({ + input: ` + export class SomeClass {} + SomeClass.ctorParameters = function () { return [{type: Injector}]; }; + `, + expected: 'export class SomeClass {}', + }), + ); + + it( + 'elides empty ctorParameters arrow expression static field', + testCase({ + input: ` + export class SomeClass {} + SomeClass.ctorParameters = () => []; + `, + expected: 'export class SomeClass {}', + }), + ); + + it( + 'elides non-empty ctorParameters arrow expression static field', + testCase({ + input: ` + export class SomeClass {} + SomeClass.ctorParameters = () => [{type: Injector}]; + `, + expected: 'export class SomeClass {}', + }), + ); + + it( + 'keeps ctorParameters static field without arrow/function expression', + testCase({ + input: ` + export class SomeClass {} + SomeClass.ctorParameters = 42; + `, + expected: ` + export let SomeClass = /*#__PURE__*/ (() => { + class SomeClass {} + SomeClass.ctorParameters = 42; + return SomeClass; + })(); + `, + }), + ); + + it( + 'elides empty decorators static field with array literal', + testCase({ + input: ` + export class SomeClass {} + SomeClass.decorators = []; + `, + expected: 'export class SomeClass {}', + }), + ); + + it( + 'elides non-empty decorators static field with array literal', + testCase({ + input: ` + export class SomeClass {} + SomeClass.decorators = [{ type: Injectable }]; + `, + expected: 'export class SomeClass {}', + }), + ); + + it( + 'keeps decorators static field without array literal', + testCase({ + input: ` + export class SomeClass {} + SomeClass.decorators = 42; + `, + expected: ` + export let SomeClass = /*#__PURE__*/ (() => { + class SomeClass {} + SomeClass.decorators = 42; + return SomeClass; + })(); + `, + }), + ); + + it( + 'elides empty propDecorators static field with object literal', + testCase({ + input: ` + export class SomeClass {} + SomeClass.propDecorators = {}; + `, + expected: 'export class SomeClass {}', + }), + ); + + it( + 'elides non-empty propDecorators static field with object literal', + testCase({ + input: ` + export class SomeClass {} + SomeClass.propDecorators = { 'ngIf': [{ type: Input }] }; + `, + expected: 'export class SomeClass {}', + }), + ); + + it( + 'keeps propDecorators static field without object literal', + testCase({ + input: ` + export class SomeClass {} + SomeClass.propDecorators = 42; + `, + expected: ` + export let SomeClass = /*#__PURE__*/ (() => { + class SomeClass {} + SomeClass.propDecorators = 42; + return SomeClass; + })(); + `, + }), + ); + + it( + 'does not wrap default exported class with no connected siblings', + testCase({ + // NOTE: This could technically have no changes but the default export splitting detection + // does not perform class property analysis currently. + input: ` + export default class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + `, + expected: ` + class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + export { CustomComponentEffects as default }; + `, + }), + ); + + it( + 'does wrap not default exported class with only side effect fields', + testCase({ + input: ` + export default class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someFieldWithSideEffects = console.log('foo'); + `, + expected: NO_CHANGE, + }), + ); + + it( + 'does not wrap class with only side effect fields', + testCase({ + input: ` + class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someFieldWithSideEffects = console.log('foo'); + `, + expected: NO_CHANGE, + }), + ); + + it( + 'does not wrap class with only side effect native fields', + testCase({ + input: ` + class CustomComponentEffects { + static someFieldWithSideEffects = console.log('foo'); + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + `, + expected: NO_CHANGE, + }), + ); + + it( + 'does not wrap class with only instance native fields', + testCase({ + input: ` + class CustomComponentEffects { + someFieldWithSideEffects = console.log('foo'); + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + `, + expected: NO_CHANGE, + }), + ); + + it( + 'wraps class with pure annotated side effect fields (#__PURE__)', + testCase({ + input: ` + class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someFieldWithSideEffects = /*#__PURE__*/ console.log('foo'); + `, + expected: ` + let CustomComponentEffects = /*#__PURE__*/ (() => { + class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someFieldWithSideEffects = /*#__PURE__*/ console.log('foo'); + return CustomComponentEffects; + })(); + `, + }), + ); + + it( + 'wraps class with pure annotated side effect native fields (#__PURE__)', + testCase({ + input: ` + class CustomComponentEffects { + static someFieldWithSideEffects = /*#__PURE__*/ console.log('foo'); + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + `, + expected: ` + let CustomComponentEffects = /*#__PURE__*/ (() => { + class CustomComponentEffects { + static someFieldWithSideEffects = /*#__PURE__*/ console.log('foo'); + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + return CustomComponentEffects; + })(); + `, + }), + ); + + it( + 'wraps class with pure annotated side effect fields (@__PURE__)', + testCase({ + input: ` + class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someFieldWithSideEffects = /*@__PURE__*/ console.log('foo'); + `, + expected: ` + let CustomComponentEffects = /*#__PURE__*/ (() => { + class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someFieldWithSideEffects = /*@__PURE__*/ console.log('foo'); + return CustomComponentEffects; + })(); + `, + }), + ); + + it( + 'wraps class with pure annotated side effect fields (@pureOrBreakMyCode)', + testCase({ + input: ` + class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someFieldWithSideEffects = /**@pureOrBreakMyCode*/ console.log('foo'); + `, + expected: ` + let CustomComponentEffects = /*#__PURE__*/ (() => { + class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someFieldWithSideEffects = + /**@pureOrBreakMyCode*/ console.log('foo'); + return CustomComponentEffects; + })(); + `, + }), + ); + + it( + 'wraps class with closure pure annotated side effect fields', + testCase({ + input: ` + class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someFieldWithSideEffects = /* @pureOrBreakMyCode */ console.log('foo'); + `, + expected: ` + let CustomComponentEffects = /*#__PURE__*/ (() => { + class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someFieldWithSideEffects = + /* @pureOrBreakMyCode */ console.log('foo'); + return CustomComponentEffects; + })(); + `, + }), + ); + + it( + 'wraps exported class with a pure static field', + testCase({ + input: ` + export class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someField = 42; + `, + expected: ` + export let CustomComponentEffects = /*#__PURE__*/ (() => { + class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someField = 42; + return CustomComponentEffects; + })(); + `, + }), + ); + + it( + 'wraps exported class with a pure native static field', + testCase({ + input: ` + export class CustomComponentEffects { + static someField = 42; + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + `, + expected: ` + export let CustomComponentEffects = /*#__PURE__*/ (() => { + class CustomComponentEffects { + static someField = 42; + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + return CustomComponentEffects; + })(); + `, + }), + ); + + it( + 'wraps class with a basic literal static field', + testCase({ + input: ` + class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someField = 42; + `, + expected: ` + let CustomComponentEffects = /*#__PURE__*/ (() => { + class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someField = 42; + return CustomComponentEffects; + })(); + `, + }), + ); + + it( + 'wraps class with a pure static field', + testCase({ + input: ` + const SWITCH_TEMPLATE_REF_FACTORY__POST_R3__ = injectTemplateRef; + const SWITCH_TEMPLATE_REF_FACTORY = SWITCH_TEMPLATE_REF_FACTORY__POST_R3__; + class TemplateRef {} + TemplateRef.__NG_ELEMENT_ID__ = SWITCH_TEMPLATE_REF_FACTORY; + `, + expected: ` + const SWITCH_TEMPLATE_REF_FACTORY__POST_R3__ = injectTemplateRef; + const SWITCH_TEMPLATE_REF_FACTORY = SWITCH_TEMPLATE_REF_FACTORY__POST_R3__; + let TemplateRef = /*#__PURE__*/ (() => { + class TemplateRef {} + TemplateRef.__NG_ELEMENT_ID__ = SWITCH_TEMPLATE_REF_FACTORY; + return TemplateRef; + })(); + `, + }), + ); + + it( + 'wraps class with multiple pure static field', + testCase({ + input: ` + const SWITCH_TEMPLATE_REF_FACTORY__POST_R3__ = injectTemplateRef; + const SWITCH_TEMPLATE_REF_FACTORY = SWITCH_TEMPLATE_REF_FACTORY__POST_R3__; + class TemplateRef {} + TemplateRef.__NG_ELEMENT_ID__ = SWITCH_TEMPLATE_REF_FACTORY; + TemplateRef.someField = 42; + `, + expected: ` + const SWITCH_TEMPLATE_REF_FACTORY__POST_R3__ = injectTemplateRef; + const SWITCH_TEMPLATE_REF_FACTORY = SWITCH_TEMPLATE_REF_FACTORY__POST_R3__; + let TemplateRef = /*#__PURE__*/ (() => { + class TemplateRef {} + TemplateRef.__NG_ELEMENT_ID__ = SWITCH_TEMPLATE_REF_FACTORY; + TemplateRef.someField = 42; + return TemplateRef; + })(); + `, + }), + ); + + it( + 'does not wrap class with only some pure static fields', + testCase({ + input: ` + class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someField = 42; + CustomComponentEffects.someFieldWithSideEffects = console.log('foo'); + `, + expected: NO_CHANGE, + }), + ); + + it( + 'does not wrap class with only pure native static fields and some side effect static fields', + testCase({ + input: ` + class CustomComponentEffects { + static someField = 42; + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someFieldWithSideEffects = console.log('foo'); + `, + expected: NO_CHANGE, + }), + ); + + it( + 'does not wrap class with only some pure native static fields', + testCase({ + input: ` + class CustomComponentEffects { + static someField = 42; + static someFieldWithSideEffects = console.log('foo'); + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + `, + expected: NO_CHANGE, + }), + ); + + it( + 'does not wrap class with class decorators when wrapDecorators is false', + testCase({ + input: ` + let SomeClass = class SomeClass { + }; + SomeClass = __decorate([ + Dec() + ], SomeClass); + `, + expected: NO_CHANGE, + options: { wrapDecorators: false }, + }), + ); + + it( + 'wraps class with Angular ɵfac static field (esbuild)', + testCase({ + input: ` + var Comp2Component = class _Comp2Component { + static { + this.ɵfac = function Comp2Component_Factory(t) { + return new (t || _Comp2Component)(); + }; + } + }; + `, + expected: ` + var Comp2Component = /*#__PURE__*/ (() => { + let Comp2Component = class _Comp2Component { + static { + this.ɵfac = function Comp2Component_Factory(t) { + return new (t || _Comp2Component)(); + }; + } + }; + return Comp2Component; + })(); + `, + }), + ); + + it( + 'wraps class with class decorators when wrapDecorators is true (esbuild output)', + testCase({ + input: ` + var ExampleClass = class { + method() { + } + }; + __decorate([ + SomeDecorator() + ], ExampleClass.prototype, "method", null); + `, + expected: ` + var ExampleClass = /*#__PURE__*/ (() => { + let ExampleClass = class { + method() {} + }; + __decorate([SomeDecorator()], ExampleClass.prototype, "method", null); + return ExampleClass; + })(); + `, + options: { wrapDecorators: true }, + }), + ); + + it( + 'wraps class with class decorators when wrapDecorators is true', + testCase({ + input: ` + let SomeClass = class SomeClass { + }; + SomeClass = __decorate([ + SomeDecorator() + ], SomeClass); + `, + expected: ` + let SomeClass = /*#__PURE__*/ (() => { + let SomeClass = class SomeClass { + }; + SomeClass = __decorate([ + SomeDecorator() + ], SomeClass); + return SomeClass; + })(); + `, + options: { wrapDecorators: true }, + }), + ); + + it( + 'does not wrap class with constructor decorators when wrapDecorators is false', + testCase({ + input: ` + let SomeClass = class SomeClass { + constructor(foo) { } + }; + SomeClass = __decorate([ + __param(0, SomeDecorator) + ], SomeClass); + `, + expected: NO_CHANGE, + options: { wrapDecorators: false }, + }), + ); + + it( + 'wraps class with constructor decorators when wrapDecorators is true', + testCase({ + input: ` + let SomeClass = class SomeClass { + constructor(foo) { } + }; + SomeClass = __decorate([ + __param(0, SomeDecorator) + ], SomeClass); + `, + expected: ` + let SomeClass = /*#__PURE__*/ (() => { + let SomeClass = class SomeClass { + constructor(foo) { } + }; + SomeClass = __decorate([ + __param(0, SomeDecorator) + ], SomeClass); + return SomeClass; + })(); + `, + options: { wrapDecorators: true }, + }), + ); + + it( + 'does not wrap class with field decorators when wrapDecorators is false', + testCase({ + input: ` + class SomeClass { + constructor() { + this.foo = 42; + } + } + __decorate([ + SomeDecorator + ], SomeClass.prototype, "foo", void 0); + `, + expected: NO_CHANGE, + options: { wrapDecorators: false }, + }), + ); + + it( + 'wraps class with field decorators when wrapDecorators is true', + testCase({ + input: ` + class SomeClass { + constructor() { + this.foo = 42; + } + } + __decorate([ + SomeDecorator + ], SomeClass.prototype, "foo", void 0); + `, + expected: ` + let SomeClass = /*#__PURE__*/ (() => { + class SomeClass { + constructor() { + this.foo = 42; + } + } + __decorate([ + SomeDecorator + ], SomeClass.prototype, "foo", void 0); + return SomeClass; + })(); + `, + options: { wrapDecorators: true }, + }), + ); + + it( + 'wraps class with Angular ɵfac static field', + testCase({ + input: ` + class CommonModule { + } + CommonModule.ɵfac = function CommonModule_Factory(t) { return new (t || CommonModule)(); }; + `, + expected: ` + let CommonModule = /*#__PURE__*/ (() => { + class CommonModule { + } + CommonModule.ɵfac = function CommonModule_Factory(t) { return new (t || CommonModule)(); }; + return CommonModule; + })(); + `, + }), + ); + + it( + 'wraps class with Angular ɵfac static block (ES2022 + useDefineForClassFields: false)', + testCase({ + input: ` + class CommonModule { + static { this.ɵfac = function CommonModule_Factory(t) { return new (t || CommonModule)(); }; } + static { this.ɵmod = ɵngcc0.ɵɵdefineNgModule({ type: CommonModule }); } + } + `, + expected: ` + let CommonModule = /*#__PURE__*/ (() => { + class CommonModule { + static { + this.ɵfac = function CommonModule_Factory(t) { + return new (t || CommonModule)(); + }; + } + static { + this.ɵmod = ɵngcc0.ɵɵdefineNgModule({ + type: CommonModule, + }); + } + } + return CommonModule; + })(); + `, + }), + ); + + it( + 'does not wrap class with side effect full static block (ES2022 + useDefineForClassFields: false)', + testCase({ + input: ` + class CommonModule { + static { globalThis.bar = 1 } + } + `, + expected: NO_CHANGE, + }), + ); + + it( + 'wraps class with Angular ɵmod static field', + testCase({ + input: ` + class CommonModule { + } + CommonModule.ɵmod = /*@__PURE__*/ ɵngcc0.ɵɵdefineNgModule({ type: CommonModule }); + `, + expected: ` + let CommonModule = /*#__PURE__*/ (() => { + class CommonModule { + } + CommonModule.ɵmod = /*@__PURE__*/ ɵngcc0.ɵɵdefineNgModule({ type: CommonModule }); + return CommonModule; + })(); + `, + }), + ); + + it( + 'wraps class with Angular ɵinj static field', + testCase({ + input: ` + class CommonModule { + } + CommonModule.ɵinj = /*@__PURE__*/ ɵngcc0.ɵɵdefineInjector({ providers: [ + { provide: NgLocalization, useClass: NgLocaleLocalization }, + ] }); + `, + expected: ` + let CommonModule = /*#__PURE__*/ (() => { + class CommonModule { + } + CommonModule.ɵinj = /*@__PURE__*/ ɵngcc0.ɵɵdefineInjector({ providers: [ + { + provide: NgLocalization, + useClass: NgLocaleLocalization + }, + ] }); + return CommonModule; + })(); + `, + }), + ); + + it( + 'wraps class with multiple Angular static fields', + testCase({ + input: ` + class CommonModule { + } + CommonModule.ɵfac = function CommonModule_Factory(t) { return new (t || CommonModule)(); }; + CommonModule.ɵmod = /*@__PURE__*/ ɵngcc0.ɵɵdefineNgModule({ type: CommonModule }); + CommonModule.ɵinj = /*@__PURE__*/ ɵngcc0.ɵɵdefineInjector({ providers: [ + { provide: NgLocalization, useClass: NgLocaleLocalization }, + ] }); + `, + expected: ` + let CommonModule = /*#__PURE__*/ (() => { + class CommonModule { + } + CommonModule.ɵfac = function CommonModule_Factory(t) { return new (t || CommonModule)(); }; + CommonModule.ɵmod = /*@__PURE__*/ ɵngcc0.ɵɵdefineNgModule({ type: CommonModule }); + CommonModule.ɵinj = /*@__PURE__*/ ɵngcc0.ɵɵdefineInjector({ providers: [ + { + provide: NgLocalization, + useClass: NgLocaleLocalization + }, + ]}); + return CommonModule; + })(); + `, + }), + ); + + it( + 'wraps class with multiple Angular native static fields', + testCase({ + input: ` + class CommonModule { + static ɵfac = function CommonModule_Factory(t) { return new (t || CommonModule)(); }; + static ɵmod = /*@__PURE__*/ ɵngcc0.ɵɵdefineNgModule({ type: CommonModule }); + static ɵinj = ɵngcc0.ɵɵdefineInjector({ providers: [ + { provide: NgLocalization, useClass: NgLocaleLocalization }, + ] }); + } + `, + expected: ` + let CommonModule = /*#__PURE__*/ (() => { + class CommonModule { + static ɵfac = function CommonModule_Factory(t) { + return new (t || CommonModule)(); + }; + static ɵmod = /*@__PURE__*/ ɵngcc0.ɵɵdefineNgModule({ + type: CommonModule, + }); + static ɵinj = ɵngcc0.ɵɵdefineInjector({ + providers: [ + { + provide: NgLocalization, + useClass: NgLocaleLocalization, + }, + ], + }); + } + return CommonModule; + })(); + `, + }), + ); + + it( + 'wraps default exported class with pure static fields', + testCase({ + input: ` + export default class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someField = 42; + `, + expected: ` + let CustomComponentEffects = /*#__PURE__*/ (() => { + class CustomComponentEffects { + constructor(_actions) { + this._actions = _actions; + this.doThis = this._actions; + } + } + CustomComponentEffects.someField = 42; + return CustomComponentEffects; + })(); + export { CustomComponentEffects as default }; + `, + }), + ); + it( + 'supports class with empty static block and wraps pure static properties', + testCase({ + input: ` + class MyClass { + static {} + static ɵprov = 42; + } + `, + expected: ` + let MyClass = /*#__PURE__*/ (() => { + class MyClass { + static {} + static ɵprov = 42; + } + return MyClass; + })(); + `, + }), + ); + + it( + 'does not wrap class with non-empty static block', + testCase({ + input: ` + class MyClass { + static { console.log(1); } + static ɵprov = 42; + } + `, + expected: ` + class MyClass { + static { console.log(1); } + static ɵprov = 42; + } + `, + }), + ); +}); diff --git a/packages/angular/build/src/tools/babel/plugins/adjust-typescript-enums_oxc_spec.ts b/packages/angular/build/src/tools/babel/plugins/adjust-typescript-enums_oxc_spec.ts new file mode 100644 index 000000000000..fc01eecf991a --- /dev/null +++ b/packages/angular/build/src/tools/babel/plugins/adjust-typescript-enums_oxc_spec.ts @@ -0,0 +1,283 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { format } from 'prettier'; +import { transform } from './oxc-transform'; + +const NO_CHANGE = Symbol('NO_CHANGE'); + +function testCase({ + input, + expected, +}: { + input: string; + expected: string | typeof NO_CHANGE; +}): jasmine.ImplementationCallback { + return async () => { + const result = transform('test.js', input, { + sourcemap: false, + pureAnnotate: false, + }); + if (!result?.code) { + fail('Expected oxc-transform to return a transform result.'); + } else { + expect(await format(result.code, { parser: 'babel' })).toEqual( + await format(expected === NO_CHANGE ? input : expected, { parser: 'babel' }), + ); + } + }; +} + +describe('adjust-typescript-enums oxc-transform implementation', () => { + it( + 'wraps unexported TypeScript enums', + testCase({ + input: ` + var ChangeDetectionStrategy; + (function (ChangeDetectionStrategy) { + ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush"; + ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default"; + })(ChangeDetectionStrategy || (ChangeDetectionStrategy = {})); + `, + expected: ` + var ChangeDetectionStrategy = /*#__PURE__*/ (function (ChangeDetectionStrategy) { + ChangeDetectionStrategy[(ChangeDetectionStrategy["OnPush"] = 0)] = "OnPush"; + ChangeDetectionStrategy[(ChangeDetectionStrategy["Default"] = 1)] = "Default"; + return ChangeDetectionStrategy; + })(ChangeDetectionStrategy || {}); + `, + }), + ); + + it( + 'wraps exported TypeScript enums', + testCase({ + input: ` + export var ChangeDetectionStrategy; + (function (ChangeDetectionStrategy) { + ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush"; + ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default"; + })(ChangeDetectionStrategy || (ChangeDetectionStrategy = {})); + `, + expected: ` + export var ChangeDetectionStrategy = /*#__PURE__*/ (function (ChangeDetectionStrategy) { + ChangeDetectionStrategy[(ChangeDetectionStrategy["OnPush"] = 0)] = "OnPush"; + ChangeDetectionStrategy[(ChangeDetectionStrategy["Default"] = 1)] = "Default"; + return ChangeDetectionStrategy; + })(ChangeDetectionStrategy || {}); + `, + }), + ); + + it( + 'does not wrap exported TypeScript enums from CommonJS (<5.1)', + testCase({ + input: ` + var ChangeDetectionStrategy; + (function (ChangeDetectionStrategy) { + ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush"; + ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default"; + })(ChangeDetectionStrategy = exports.ChangeDetectionStrategy || (exports.ChangeDetectionStrategy = {})); + `, + expected: NO_CHANGE, + }), + ); + + it( + 'wraps exported TypeScript enums from CommonJS (5.1+)', + testCase({ + input: ` + var ChangeDetectionStrategy; + (function (ChangeDetectionStrategy) { + ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush"; + ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default"; + })(ChangeDetectionStrategy || (exports.ChangeDetectionStrategy = ChangeDetectionStrategy = {})); + `, + expected: ` + var ChangeDetectionStrategy = /*#__PURE__*/ (function (ChangeDetectionStrategy) { + ChangeDetectionStrategy[(ChangeDetectionStrategy["OnPush"] = 0)] = "OnPush"; + ChangeDetectionStrategy[(ChangeDetectionStrategy["Default"] = 1)] = "Default"; + return ChangeDetectionStrategy; + })(ChangeDetectionStrategy || (exports.ChangeDetectionStrategy = ChangeDetectionStrategy = {})); + `, + }), + ); + + it( + 'wraps TypeScript enums with custom numbering', + testCase({ + input: ` + export var ChangeDetectionStrategy; + (function (ChangeDetectionStrategy) { + ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 5] = "OnPush"; + ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 8] = "Default"; + })(ChangeDetectionStrategy || (ChangeDetectionStrategy = {})); + `, + expected: ` + export var ChangeDetectionStrategy = /*#__PURE__*/ (function (ChangeDetectionStrategy) { + ChangeDetectionStrategy[(ChangeDetectionStrategy["OnPush"] = 5)] = "OnPush"; + ChangeDetectionStrategy[(ChangeDetectionStrategy["Default"] = 8)] = "Default"; + return ChangeDetectionStrategy; + })(ChangeDetectionStrategy || {}); + `, + }), + ); + + it( + 'wraps string-based TypeScript enums', + testCase({ + input: ` + var NotificationKind; + (function (NotificationKind) { + NotificationKind["NEXT"] = "N"; + NotificationKind["ERROR"] = "E"; + NotificationKind["COMPLETE"] = "C"; + })(NotificationKind || (NotificationKind = {})); + `, + expected: ` + var NotificationKind = /*#__PURE__*/ (function (NotificationKind) { + NotificationKind["NEXT"] = "N"; + NotificationKind["ERROR"] = "E"; + NotificationKind["COMPLETE"] = "C"; + return NotificationKind; + })(NotificationKind || {}); + `, + }), + ); + + it( + 'wraps enums that were renamed due to scope hoisting', + testCase({ + input: ` + var NotificationKind$1; + (function (NotificationKind) { + NotificationKind["NEXT"] = "N"; + NotificationKind["ERROR"] = "E"; + NotificationKind["COMPLETE"] = "C"; + })(NotificationKind$1 || (NotificationKind$1 = {})); + `, + expected: ` + var NotificationKind$1 = /*#__PURE__*/ (function (NotificationKind) { + NotificationKind["NEXT"] = "N"; + NotificationKind["ERROR"] = "E"; + NotificationKind["COMPLETE"] = "C"; + return NotificationKind; + })(NotificationKind$1 || {}); + `, + }), + ); + + it( + 'maintains multi-line comments', + testCase({ + input: ` + /** + * Supported http methods. + * @deprecated use @angular/common/http instead + */ + var RequestMethod; + (function (RequestMethod) { + RequestMethod[RequestMethod["Get"] = 0] = "Get"; + RequestMethod[RequestMethod["Post"] = 1] = "Post"; + RequestMethod[RequestMethod["Put"] = 2] = "Put"; + RequestMethod[RequestMethod["Delete"] = 3] = "Delete"; + RequestMethod[RequestMethod["Options"] = 4] = "Options"; + RequestMethod[RequestMethod["Head"] = 5] = "Head"; + RequestMethod[RequestMethod["Patch"] = 6] = "Patch"; + })(RequestMethod || (RequestMethod = {})); + `, + expected: ` + /** + * Supported http methods. + * @deprecated use @angular/common/http instead + */ + var RequestMethod = /*#__PURE__*/ (function (RequestMethod) { + RequestMethod[(RequestMethod["Get"] = 0)] = "Get"; + RequestMethod[(RequestMethod["Post"] = 1)] = "Post"; + RequestMethod[(RequestMethod["Put"] = 2)] = "Put"; + RequestMethod[(RequestMethod["Delete"] = 3)] = "Delete"; + RequestMethod[(RequestMethod["Options"] = 4)] = "Options"; + RequestMethod[(RequestMethod["Head"] = 5)] = "Head"; + RequestMethod[(RequestMethod["Patch"] = 6)] = "Patch"; + return RequestMethod; + })(RequestMethod || {}); + `, + }), + ); + + it( + 'does not wrap TypeScript enums with side effect values', + testCase({ + input: ` + export var ChangeDetectionStrategy; + (function (ChangeDetectionStrategy) { + ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = console.log('foo'); + ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default"; + })(ChangeDetectionStrategy || (ChangeDetectionStrategy = {})); + `, + expected: NO_CHANGE, + }), + ); + + it( + 'does not wrap object literals similar to TypeScript enums', + testCase({ + input: ` + const RendererStyleFlags3 = { + Important: 1, + DashCase: 2, + }; + if (typeof RendererStyleFlags3 === 'object') { + RendererStyleFlags3[RendererStyleFlags3.Important] = 'DashCase'; + } + RendererStyleFlags3[RendererStyleFlags3.Important] = 'Important'; + `, + expected: NO_CHANGE, + }), + ); + + it( + 'wraps TypeScript enums', + testCase({ + input: ` + var ChangeDetectionStrategy; + (function (ChangeDetectionStrategy) { + ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush"; + ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default"; + })(ChangeDetectionStrategy || (ChangeDetectionStrategy = {})); + `, + expected: ` + var ChangeDetectionStrategy = /*#__PURE__*/ (function (ChangeDetectionStrategy) { + ChangeDetectionStrategy[(ChangeDetectionStrategy["OnPush"] = 0)] = "OnPush"; + ChangeDetectionStrategy[(ChangeDetectionStrategy["Default"] = 1)] = "Default"; + return ChangeDetectionStrategy; + })(ChangeDetectionStrategy || {}); + `, + }), + ); + + it( + 'should wrap TypeScript enums if the declaration identifier has been renamed to avoid collisions', + testCase({ + input: ` + var ChangeDetectionStrategy$1; + (function (ChangeDetectionStrategy) { + ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush"; + ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default"; + })(ChangeDetectionStrategy$1 || (ChangeDetectionStrategy$1 = {})); + `, + expected: ` + var ChangeDetectionStrategy$1 = /*#__PURE__*/ (function (ChangeDetectionStrategy) { + ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush"; + ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default"; + return ChangeDetectionStrategy; + })(ChangeDetectionStrategy$1 || {}); + `, + }), + ); +}); diff --git a/packages/angular/build/src/tools/babel/plugins/elide-angular-metadata_oxc_spec.ts b/packages/angular/build/src/tools/babel/plugins/elide-angular-metadata_oxc_spec.ts new file mode 100644 index 000000000000..f4d6c09b6c19 --- /dev/null +++ b/packages/angular/build/src/tools/babel/plugins/elide-angular-metadata_oxc_spec.ts @@ -0,0 +1,213 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { transform } from './oxc-transform'; + +function cleanCode(code: string): string { + return code + .replace(/\s+/g, '') + .replace(/"/g, "'") + .replace(/;}/g, '}') + .replace(/,([}\])])/g, '$1'); +} + +function testCase({ + input, + expected, +}: { + input: string; + expected: string; +}): jasmine.ImplementationCallback { + return async () => { + const result = transform('test.js', input, { + sourcemap: false, + pureAnnotate: false, + }); + if (!result?.code) { + fail('Expected oxc-transform to return a transform result.'); + } else { + const actualClean = cleanCode(result.code); + const expectedClean = cleanCode(expected); + expect(actualClean).toEqual(expectedClean); + } + }; +} + +describe('elide-angular-metadata oxc-transform implementation', () => { + it( + 'elides pure annotated ɵsetClassMetadata', + testCase({ + input: ` + import { Component } from '@angular/core'; + export class SomeClass {} + /*@__PURE__*/ (function () { i0.ɵsetClassMetadata(Clazz, [{ + type: Component, + args: [{ + selector: 'app-lazy', + template: 'very lazy', + styles: [] + }] + }], null, null); })(); + `, + expected: ` + import { Component } from '@angular/core'; + export class SomeClass {} + /*@__PURE__*/ (function () { void 0 })(); + `, + }), + ); + + it( + 'elides JIT mode protected ɵsetClassMetadata', + testCase({ + input: ` + import { Component } from '@angular/core'; + export class SomeClass {} + (function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵsetClassMetadata(SomeClass, [{ + type: Component, + args: [{ + selector: 'app-lazy', + template: 'very lazy', + styles: [] + }] + }], null, null); })();`, + expected: ` + import { Component } from '@angular/core'; + export class SomeClass {} + (function () { (typeof ngJitMode === "undefined" || ngJitMode) && void 0 })();`, + }), + ); + + it( + 'elides ɵsetClassMetadata inside an arrow-function-based IIFE', + testCase({ + input: ` + import { Component } from '@angular/core'; + export class SomeClass {} + /*@__PURE__*/ (() => { i0.ɵsetClassMetadata(Clazz, [{ + type: Component, + args: [{ + selector: 'app-lazy', + template: 'very lazy', + styles: [] + }] + }], null, null); })(); + `, + expected: ` + import { Component } from '@angular/core'; + export class SomeClass {} + /*@__PURE__*/ (() => { void 0 })(); + `, + }), + ); + + it( + 'elides pure annotated ɵsetClassMetadataAsync', + testCase({ + input: ` + import { Component } from '@angular/core'; + export class SomeClass {} + /*@__PURE__*/ (function () { + i0.ɵsetClassMetadataAsync(SomeClass, + function () { return [import("./cmp-a").then(function (m) { return m.CmpA; })]; }, + function (CmpA) { i0.ɵsetClassMetadata(SomeClass, [{ + type: Component, + args: [{ + selector: 'test-cmp', + standalone: true, + imports: [CmpA, LocalDep], + template: '{#defer}{/defer}', + }] + }], null, null); }); + })(); + `, + expected: ` + import { Component } from '@angular/core'; + export class SomeClass {} + /*@__PURE__*/ (function () { void 0 })(); + `, + }), + ); + + it( + 'elides JIT mode protected ɵsetClassMetadataAsync', + testCase({ + input: ` + import { Component } from '@angular/core'; + export class SomeClass {} + (function () { + (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵsetClassMetadataAsync(SomeClass, + function () { return [import("./cmp-a").then(function (m) { return m.CmpA; })]; }, + function (CmpA) { i0.ɵsetClassMetadata(SomeClass, [{ + type: Component, + args: [{ + selector: 'test-cmp', + standalone: true, + imports: [CmpA, LocalDep], + template: '{#defer}{/defer}', + }] + }], null, null); }); + })(); + `, + expected: ` + import { Component } from '@angular/core'; + export class SomeClass {} + (function () { (typeof ngJitMode === "undefined" || ngJitMode) && void 0 })(); + `, + }), + ); + + it( + 'elides arrow-function-based ɵsetClassMetadataAsync', + testCase({ + input: ` + import { Component } from '@angular/core'; + export class SomeClass {} + /*@__PURE__*/ (() => { + i0.ɵsetClassMetadataAsync(SomeClass, + () => [import("./cmp-a").then(m => m.CmpA)], + (CmpA) => { i0.ɵsetClassMetadata(SomeClass, [{ + type: Component, + args: [{ + selector: 'test-cmp', + standalone: true, + imports: [CmpA, LocalDep], + template: '{#defer}{/defer}', + }] + }], null, null); }); + })(); + `, + expected: ` + import { Component } from '@angular/core'; + export class SomeClass {} + /*@__PURE__*/ (() => { void 0 })(); + `, + }), + ); + + it( + 'elides ɵsetClassDebugInfo', + testCase({ + input: ` + import { Component } from '@angular/core'; + class SomeClass {} + (() => { + (typeof ngDevMode === 'undefined' || ngDevMode) && + i0.ɵsetClassDebugInfo(SomeClass, { className: 'SomeClass' }); + })(); + `, + expected: ` + import { Component } from "@angular/core"; + class SomeClass {} + (() => { + (typeof ngDevMode === "undefined" || ngDevMode) && void 0; + })(); + `, + }), + ); +}); diff --git a/packages/angular/build/src/tools/babel/plugins/oxc-transform.ts b/packages/angular/build/src/tools/babel/plugins/oxc-transform.ts new file mode 100644 index 000000000000..fda9da26c6be --- /dev/null +++ b/packages/angular/build/src/tools/babel/plugins/oxc-transform.ts @@ -0,0 +1,753 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import type { BindingIdentifier, Class, Node } from '@oxc-project/types'; +import MagicString from 'magic-string'; +import { Visitor, parseSync } from 'oxc-parser'; + +export interface OxcTransformOptions { + sourcemap?: boolean; + jit?: boolean; + sideEffects?: boolean; + topLevelSafeMode?: boolean; + pureAnnotate?: boolean; +} + +/** + * A set of constructor names that are considered to be side-effect free. + */ +const sideEffectFreeConstructors = new Set(['InjectionToken']); + +/** + * A set of TypeScript helper function names used by the helper name matcher utility function. + */ +const tslibHelpers = new Set([ + '__extends', + '__assign', + '__rest', + '__decorate', + '__param', + '__esDecorate', + '__runInitializers', + '__propKey', + '__setFunctionName', + '__metadata', + '__awaiter', + '__generator', + '__exportStar', + '__values', + '__read', + '__privateGet', + '__privateSet', + '__privateMethod', + '__addDisposableResource', + '__disposeResources', +]); + +/** + * Determines whether an identifier name matches one of the TypeScript helper function names. + * + * @param name The identifier name to check. + * @returns True if the name matches a TypeScript helper name; otherwise, false. + */ +function isTslibHelperName(name: string): boolean { + const nameParts = name.split('$'); + const originalName = nameParts[0]; + + if (nameParts.length > 2 || (nameParts.length === 2 && !/^\d+$/.test(nameParts[1]))) { + return false; + } + + return tslibHelpers.has(originalName); +} + +/** + * A set of Babel helper function names that are intended to cause side effects. + */ +const babelHelpers = new Set(['_defineProperty']); + +/** + * Determines whether an identifier name matches one of the Babel helper function names. + * + * @param name The identifier name to check. + * @returns True if the name matches a Babel helper name; otherwise, false. + */ +function isBabelHelperName(name: string): boolean { + return babelHelpers.has(name); +} + +/** + * A set of Angular static properties that should be wrapped in pure IIFE statements. + */ +const angularStaticsToWrap = new Set([ + 'ɵcmp', + 'ɵdir', + 'ɵfac', + 'ɵinj', + 'ɵmod', + 'ɵpipe', + 'ɵprov', + 'INJECTOR_KEY', +]); + +/** + * A set of Angular metadata decorator functions that can be elided. + */ +const angularMetadataFunctions = new Set([ + 'ɵsetClassMetadata', + 'ɵsetClassMetadataAsync', + 'ɵsetClassDebugInfo', +]); + +/** + * A map of static properties and their matcher predicate functions to check if they + * can be safely elided from class declarations. + */ +const angularStaticsToElide: Record boolean> = { + 'ctorParameters'(node) { + return node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression'; + }, + 'decorators'(node) { + return node.type === 'ArrayExpression'; + }, + 'propDecorators'(node) { + return node.type === 'ObjectExpression'; + }, +}; + +/** + * Determines whether an AST node is considered safe for pure evaluation (side-effect free). + * + * @param node The AST node to check. + * @returns True if the node is side-effect free; otherwise, false. + */ +function isPure(node: Node): boolean { + switch (node.type) { + case 'Identifier': + case 'Literal': + return true; + case 'BinaryExpression': + case 'LogicalExpression': + return isPure(node.left) && isPure(node.right); + case 'UnaryExpression': + return isPure(node.argument); + case 'MemberExpression': + return isPure(node.object) && (!node.computed || isPure(node.property)); + case 'ObjectExpression': + return node.properties.every((p) => p.type === 'Property' && isPure(p.value)); + case 'ArrayExpression': + return node.elements.every((e) => !e || isPure(e)); + case 'ParenthesizedExpression': + return isPure(node.expression); + default: + return false; + } +} + +/** + * Recursively unwraps any ParenthesizedExpression wrapper nodes to get the inner expression. + * + * @param node The potentially parenthesized AST node. + * @returns The inner non-parenthesized AST node. + */ +function unwrapParentheses(node: Node): Node { + while (node && node.type === 'ParenthesizedExpression') { + node = node.expression; + } + + return node; +} + +/** + * Determines whether a class static property assignment is safe to be wrapped in a pure IIFE. + * + * @param propertyName The name of the property. + * @param assignmentValue The AST node representing the value assigned. + * @param code The source code of the file. + * @returns True if the property can be wrapped safely; otherwise, false. + */ +function canWrapProperty(propertyName: string, assignmentValue: Node, code: string): boolean { + if (angularStaticsToWrap.has(propertyName)) { + return true; + } + + const prefix = code.substring(Math.max(0, assignmentValue.start - 100), assignmentValue.start); + if (/(\/\*[\s\S]*?(?:@__PURE__|#__PURE__|@pureOrBreakMyCode)[\s\S]*?\*\/)\s*$/.test(prefix)) { + return true; + } + + return isPure(assignmentValue); +} + +/** + * Analyzes static properties inside a class body to determine if the class has any + * side-effecting static property initializers. + * + * @param classNode The Class AST node. + * @param code The source code of the file. + * @returns True if the class static properties are pure and can be wrapped; otherwise, false. + */ +function analyzeClassStaticProperties(classNode: Node, code: string): boolean { + let shouldWrap = false; + const body = (classNode as Class).body.body; + for (const element of body) { + if (element.type === 'PropertyDefinition') { + if (!element.static) { + continue; + } + + const key = element.key; + const value = element.value; + if (key.type === 'Identifier' && (!value || canWrapProperty(key.name, value, code))) { + shouldWrap = true; + } else { + shouldWrap = false; + break; + } + } else if (element.type === 'StaticBlock') { + const blockBody = element.body; + if (blockBody.length === 0) { + continue; + } + if (blockBody.length > 1) { + shouldWrap = false; + break; + } + const expressionStatement = blockBody[0]; + if (expressionStatement && expressionStatement.type === 'ExpressionStatement') { + const assignment = expressionStatement.expression; + if ( + assignment && + assignment.type === 'AssignmentExpression' && + assignment.left.type === 'MemberExpression' + ) { + const left = assignment.left; + if (left.object.type === 'ThisExpression' && left.property.type === 'Identifier') { + if (canWrapProperty(left.property.name, assignment.right, code)) { + shouldWrap = true; + continue; + } + } + } + } + shouldWrap = false; + break; + } + } + + return shouldWrap; +} + +/** + * Executes a single-pass optimized transformation using oxc-parser and magic-string. + * Performs typescript enum wrapping, static class members elision/wrapping, angular metadata elision, + * and top-level pure function annotations. + * + * @param filename The absolute path of the file being transformed. + * @param code The string source content of the file. + * @param options Configuration options specifying which optimization steps to run. + * @returns The transformed code string and an optional source map. + */ +// eslint-disable-next-line max-lines-per-function +export function transform(filename: string, code: string, options: OxcTransformOptions) { + const { program } = parseSync(filename, code, { range: true }); + const s = new MagicString(code); + + const sideEffectFree = options.sideEffects === false; + const safeAngularPackage = sideEffectFree && /[\\/]node_modules[\\/]@angular[\\/]/.test(filename); + const topLevelSafeMode = options.topLevelSafeMode ?? false; + const wrapDecorators = sideEffectFree; + const pureAnnotate = options.pureAnnotate ?? true; + + /** + * Scans backwards from the specified start index to check if a pure comment (e.g. `/*@__PURE__*\/`) + * already precedes the node. + * + * @param start The index where the node starts. + * @returns True if a pure comment is already present; otherwise, false. + */ + function hasPureComment(start: number): boolean { + let i = start - 1; + while (i >= 0 && /\s/.test(code[i])) { + i--; + } + if (i < 1 || code[i] !== '/' || code[i - 1] !== '*') { + return false; + } + const commentEnd = i + 1; + const commentStart = code.lastIndexOf('/*', commentEnd); + if (commentStart === -1) { + return false; + } + const commentContent = code.substring(commentStart + 2, commentEnd - 2); + + return commentContent.includes('@__PURE__') || commentContent.includes('#__PURE__'); + } + + const editedRanges: { start: number; end: number }[] = []; + + /** + * Records a range in the source code that has been modified, preventing subsequent nested mutations. + * + * @param start The start index of the modified range. + * @param end The end index of the modified range. + */ + function markEdited(start: number, end: number) { + editedRanges.push({ start, end }); + } + + /** + * Checks if the specified range falls inside an already modified section of code. + * + * @param start The start index of the range. + * @param end The end index of the range. + * @returns True if the range is already edited; otherwise, false. + */ + function isAlreadyEdited(start: number, end: number): boolean { + return editedRanges.some((r) => start >= r.start && end <= r.end); + } + + // Track function nesting depth and closest function expression wrapper + let functionDepth = 0; + let classDepth = 0; + const functionStack: Node[] = []; + + /** + * Scans and rewrites TypeScript emitted enum declarations in the statement block. + * Wraps enum statements inside a pure IIFE assignable directly to the enum variable. + * + * @param body The array of statement AST nodes to process. + */ + function adjustTypeScriptEnumsInStatements(body: Node[]) { + for (let i = 0; i < body.length - 1; i++) { + const statement = body[i]; + let declStatement = statement; + if ( + statement.type === 'ExportNamedDeclaration' && + statement.declaration?.type === 'VariableDeclaration' + ) { + declStatement = statement.declaration; + } + + if ( + declStatement.type !== 'VariableDeclaration' || + declStatement.kind !== 'var' || + declStatement.declarations.length !== 1 + ) { + continue; + } + const decl = declStatement.declarations[0]; + if (decl.init || decl.id.type !== 'Identifier') { + continue; + } + + const nextStatement = body[i + 1]; + if (nextStatement.type !== 'ExpressionStatement') { + continue; + } + + const nextExpr = unwrapParentheses(nextStatement.expression); + if (nextExpr.type !== 'CallExpression' || nextExpr.arguments.length !== 1) { + continue; + } + + const arg = unwrapParentheses(nextExpr.arguments[0]); + if (arg.type !== 'LogicalExpression' || arg.operator !== '||') { + continue; + } + + const argLeft = unwrapParentheses(arg.left); + if (argLeft.type !== 'Identifier' || argLeft.name !== decl.id.name) { + continue; + } + + const rightCallArgument = unwrapParentheses(arg.right); + if (rightCallArgument.type !== 'AssignmentExpression') { + continue; + } + + const callee = unwrapParentheses(nextExpr.callee); + if ( + callee.type !== 'FunctionExpression' || + callee.params.length !== 1 || + !callee.body || + callee.body.type !== 'BlockStatement' + ) { + continue; + } + + const param = callee.params[0]; + if (param.type !== 'Identifier') { + continue; + } + const paramName = (param as BindingIdentifier).name; + + // Check if all statements in body are pure assignments + let hasElements = false; + let allPure = true; + for (const enumStatement of callee.body.body) { + if (enumStatement.type !== 'ExpressionStatement') { + allPure = false; + break; + } + + const enumValueAssignment = unwrapParentheses(enumStatement.expression); + if ( + enumValueAssignment.type !== 'AssignmentExpression' || + !isPure(enumValueAssignment.right) + ) { + allPure = false; + break; + } + + hasElements = true; + } + + if (!allPure || !hasElements) { + continue; + } + + // 1. Remove only the trailing characters/semicolon of the expression statement + s.remove(nextExpr.end, nextStatement.end); + markEdited(nextExpr.end, nextStatement.end); + + // 2. Add return statement inside IIFE body + s.appendRight(callee.body.end - 1, `; return ${paramName};`); + + // 3. Remove `Name = ` assignment in arguments if it's a simple identifier + if (rightCallArgument.left.type === 'Identifier') { + s.overwrite( + arg.right.start, + arg.right.end, + code.substring(rightCallArgument.right.start, rightCallArgument.right.end), + ); + markEdited(arg.right.start, arg.right.end); + } + + // 4. Move IIFE to the var initializer + s.move(nextExpr.start, nextExpr.end, decl.id.end); + s.appendLeft(decl.id.end, ' = /*#__PURE__*/ '); + markEdited(nextExpr.start, nextExpr.end); + } + } + + /** + * Scans and rewrites static class member initializers in the statement block. + * Groups externalized class static assignments into pure wrappers or elides them when safe. + * + * @param body The array of statement AST nodes to process. + */ + function adjustStaticMembersInStatements(body: Node[]) { + for (let i = 0; i < body.length; i++) { + const statement = body[i]; + let classNode: Node | null = null; + let isExportDefault = false; + let isExportNamed = false; + let isVariableClass = false; + let classIdName = ''; + if (statement.type === 'ClassDeclaration') { + classNode = statement; + classIdName = classNode.id?.name || ''; + } else if ( + statement.type === 'ExportNamedDeclaration' && + statement.declaration?.type === 'ClassDeclaration' + ) { + classNode = statement.declaration; + classIdName = classNode.id?.name || ''; + isExportNamed = true; + } else if ( + statement.type === 'ExportDefaultDeclaration' && + statement.declaration?.type === 'ClassDeclaration' + ) { + classNode = statement.declaration; + classIdName = classNode.id?.name || ''; + isExportDefault = true; + } else if (statement.type === 'VariableDeclaration' && statement.declarations.length === 1) { + const decl = statement.declarations[0]; + if (decl.init && decl.init.type === 'ClassExpression' && decl.id.type === 'Identifier') { + classNode = decl.init; + classIdName = decl.id.name; + isVariableClass = true; + } + } + + if (!classNode || !classIdName) { + continue; + } + + const wrapStatementPaths: { statement: Node; type: 'wrap' | 'decorate' | 'elide' }[] = []; + let hasPotentialSideEffects = false; + + for (let j = i + 1; j < body.length; j++) { + const nextStatement = body[j]; + if (nextStatement.type !== 'ExpressionStatement') { + break; + } + + const nextExpression = nextStatement.expression; + + // Case 1: __decorate(...) + if (nextExpression.type === 'CallExpression') { + if ( + nextExpression.callee.type !== 'Identifier' || + nextExpression.callee.name !== '__decorate' + ) { + break; + } + + if (wrapDecorators) { + wrapStatementPaths.push({ statement: nextStatement, type: 'decorate' }); + } else { + hasPotentialSideEffects = true; + } + continue; + } + + // Case 2: AssignmentExpression + if (nextExpression.type !== 'AssignmentExpression') { + break; + } + + const left = nextExpression.left; + + if (left.type === 'Identifier') { + if ( + left.name !== classIdName || + nextExpression.right.type !== 'CallExpression' || + nextExpression.right.callee.type !== 'Identifier' || + nextExpression.right.callee.name !== '__decorate' + ) { + break; + } + + if (wrapDecorators) { + wrapStatementPaths.push({ statement: nextStatement, type: 'decorate' }); + } else { + hasPotentialSideEffects = true; + } + continue; + } + + if ( + left.type !== 'MemberExpression' || + left.object.type !== 'Identifier' || + left.object.name !== classIdName || + left.property.type !== 'Identifier' + ) { + break; + } + + const propertyName = left.property.name; + const assignmentValue = nextExpression.right; + + if (angularStaticsToElide[propertyName]?.(assignmentValue)) { + wrapStatementPaths.push({ statement: nextStatement, type: 'elide' }); + } else if (canWrapProperty(propertyName, assignmentValue, code)) { + wrapStatementPaths.push({ statement: nextStatement, type: 'wrap' }); + } else { + hasPotentialSideEffects = true; + } + } + + // Check class body static properties + const shouldWrapClassStaticProperties = analyzeClassStaticProperties(classNode, code); + + // Perform elisions immediately + for (const item of wrapStatementPaths) { + if (item.type === 'elide') { + s.remove(item.statement.start, item.statement.end); + markEdited(item.statement.start, item.statement.end); + } + } + + const activeWrapPaths = wrapStatementPaths.filter( + (p) => p.type === 'wrap' || p.type === 'decorate', + ); + + if ( + !hasPotentialSideEffects && + (activeWrapPaths.length > 0 || shouldWrapClassStaticProperties) + ) { + const lastStatement = + activeWrapPaths.length > 0 + ? activeWrapPaths[activeWrapPaths.length - 1].statement + : classNode; + + if (isExportDefault) { + // 1. Remove `export default ` + s.overwrite(statement.start, classNode.start, ''); + // 2. Wrap in IIFE + s.appendLeft(classNode.start, `let ${classIdName} = /*#__PURE__*/ (() => {\n`); + s.appendRight( + lastStatement.end, + `\nreturn ${classIdName};\n})();\nexport { ${classIdName} as default };`, + ); + } else if (isExportNamed) { + // 1. Export is kept, turn `class` into `let ClassName = IIFE` + s.appendLeft(classNode.start, `let ${classIdName} = /*#__PURE__*/ (() => {\n`); + s.appendRight(lastStatement.end, `\nreturn ${classIdName};\n})();`); + } else if (isVariableClass) { + // Wrap class inside init: `/*#__PURE__*/ (() => { let ClassName = class ClassName {}; return ClassName; })()` + s.appendLeft(classNode.start, `/*#__PURE__*/ (() => {\nlet ${classIdName} = `); + const terminator = activeWrapPaths.length === 0 ? ';' : ''; + const iifeClosing = activeWrapPaths.length === 0 ? '})()' : '})();'; + s.appendRight(lastStatement.end, `${terminator}\nreturn ${classIdName};\n${iifeClosing}`); + } else { + // Standard ClassDeclaration + s.appendLeft(classNode.start, `let ${classIdName} = /*#__PURE__*/ (() => {\n`); + s.appendRight(lastStatement.end, `\nreturn ${classIdName};\n})();`); + } + + markEdited(statement.start, lastStatement.end); + + // Fast-forward outer loop index to skip the statements we wrapped + i += wrapStatementPaths.length; + } else if (isExportDefault && !hasPotentialSideEffects) { + // Splitting default export even when not wrapped + s.overwrite(statement.start, classNode.start, ''); + s.appendRight(classNode.end, `\nexport { ${classIdName} as default };`); + markEdited(statement.start, classNode.end); + } + } + } + + const visitor = new Visitor({ + ClassDeclaration(node) { + classDepth++; + }, + 'ClassDeclaration:exit'() { + classDepth--; + }, + ClassExpression(node) { + classDepth++; + }, + 'ClassExpression:exit'() { + classDepth--; + }, + FunctionDeclaration(node) { + functionDepth++; + functionStack.push(node); + }, + 'FunctionDeclaration:exit'() { + functionDepth--; + functionStack.pop(); + }, + FunctionExpression(node) { + functionDepth++; + functionStack.push(node); + }, + 'FunctionExpression:exit'() { + functionDepth--; + functionStack.pop(); + }, + ArrowFunctionExpression(node) { + functionDepth++; + functionStack.push(node); + }, + 'ArrowFunctionExpression:exit'() { + functionDepth--; + functionStack.pop(); + }, + Program(node) { + adjustTypeScriptEnumsInStatements(node.body); + adjustStaticMembersInStatements(node.body); + }, + BlockStatement(node) { + adjustTypeScriptEnumsInStatements(node.body); + adjustStaticMembersInStatements(node.body); + }, + CallExpression(node) { + if (isAlreadyEdited(node.start, node.end)) { + return; + } + + // 1. Elide Angular Metadata check + let calleeName: string | undefined; + if (node.callee.type === 'Identifier') { + calleeName = node.callee.name; + } else if ( + node.callee.type === 'MemberExpression' && + node.callee.property.type === 'Identifier' + ) { + calleeName = node.callee.property.name; + } + + if (calleeName && angularMetadataFunctions.has(calleeName)) { + const parentFunc = functionStack[functionStack.length - 1]; + if ( + parentFunc && + (parentFunc.type === 'FunctionExpression' || + parentFunc.type === 'ArrowFunctionExpression') + ) { + s.overwrite(node.start, node.end, 'void 0'); + markEdited(node.start, node.end); + + return; + } + } + + // 2. Mark Top-Level Pure Functions check + if (!pureAnnotate || functionDepth > 0 || classDepth > 0 || topLevelSafeMode) { + return; + } + + const callee = unwrapParentheses(node.callee); + if ( + (callee.type === 'FunctionExpression' || callee.type === 'ArrowFunctionExpression') && + node.arguments.length !== 0 + ) { + return; + } + + if ( + callee.type === 'Identifier' && + (isTslibHelperName(callee.name) || isBabelHelperName(callee.name)) + ) { + return; + } + + if (!hasPureComment(node.start)) { + s.appendLeft(node.start, '/*#__PURE__*/ '); + } + }, + NewExpression(node) { + if ( + !pureAnnotate || + functionDepth > 0 || + classDepth > 0 || + isAlreadyEdited(node.start, node.end) + ) { + return; + } + + if (!topLevelSafeMode) { + if (!hasPureComment(node.start)) { + s.appendLeft(node.start, '/*#__PURE__*/ '); + } + + return; + } + + const callee = node.callee; + if (callee.type === 'Identifier' && sideEffectFreeConstructors.has(callee.name)) { + if (!hasPureComment(node.start)) { + s.appendLeft(node.start, '/*#__PURE__*/ '); + } + } + }, + }); + + visitor.visit(program); + + return { + code: s.toString(), + map: options.sourcemap + ? s.generateMap({ hires: true, source: filename }).toString() + : undefined, + }; +} diff --git a/packages/angular/build/src/tools/babel/plugins/pure-toplevel-functions_oxc_spec.ts b/packages/angular/build/src/tools/babel/plugins/pure-toplevel-functions_oxc_spec.ts new file mode 100644 index 000000000000..0b91cc98aa45 --- /dev/null +++ b/packages/angular/build/src/tools/babel/plugins/pure-toplevel-functions_oxc_spec.ts @@ -0,0 +1,202 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { transform } from './oxc-transform'; + +function cleanCode(code: string): string { + return code + .replace(/\s+/g, '') + .replace(/"/g, "'") + .replace(/;}/g, '}') + .replace(/,([}\])])/g, '$1'); +} + +function testCase({ + input, + expected, + options, +}: { + input: string; + expected: string; + options?: { topLevelSafeMode: boolean }; +}): jasmine.ImplementationCallback { + return async () => { + const result = transform('test.js', input, { + sourcemap: false, + topLevelSafeMode: options?.topLevelSafeMode, + }); + if (!result?.code) { + fail('Expected oxc-transform to return a transform result.'); + } else { + const actualClean = cleanCode(result.code); + const expectedClean = cleanCode(expected); + expect(actualClean).toEqual(expectedClean); + } + }; +} + +function testCaseNoChange(input: string): jasmine.ImplementationCallback { + return testCase({ input, expected: input }); +} + +describe('pure-toplevel-functions oxc-transform implementation', () => { + it( + 'annotates top-level new expressions', + testCase({ + input: 'var result = new SomeClass();', + expected: 'var result = /*#__PURE__*/ new SomeClass();', + }), + ); + + it( + 'annotates top-level function calls', + testCase({ + input: 'var result = someCall();', + expected: 'var result = /*#__PURE__*/ someCall();', + }), + ); + + it( + 'annotates top-level IIFE assignments with no arguments', + testCase({ + input: 'var SomeClass = (function () { function SomeClass() { } return SomeClass; })();', + expected: + 'var SomeClass = /*#__PURE__*/(function () { function SomeClass() { } return SomeClass; })();', + }), + ); + + it( + 'annotates top-level arrow-function-based IIFE assignments with no arguments', + testCase({ + input: 'var SomeClass = (() => { function SomeClass() { } return SomeClass; })();', + expected: + 'var SomeClass = /*#__PURE__*/(() => { function SomeClass() { } return SomeClass; })();', + }), + ); + + it( + 'does not annotate top-level IIFE assignments with arguments', + testCaseNoChange( + 'var SomeClass = (function () { function SomeClass() { } return SomeClass; })(abc);', + ), + ); + + it( + 'does not annotate top-level arrow-function-based IIFE assignments with arguments', + testCaseNoChange( + 'var SomeClass = (() => { function SomeClass() { } return SomeClass; })(abc);', + ), + ); + + it( + 'does not annotate call expressions inside function declarations', + testCaseNoChange('function funcDecl() { const result = someFunction(); }'), + ); + + it( + 'does not annotate call expressions inside function expressions', + testCaseNoChange('const foo = function funcDecl() { const result = someFunction(); }'), + ); + + it( + 'does not annotate call expressions inside arrow functions', + testCaseNoChange('const foo = () => { const result = someFunction(); }'), + ); + + it( + 'does not annotate new expressions inside function declarations', + testCaseNoChange('function funcDecl() { const result = new SomeClass(); }'), + ); + + it( + 'does not annotate new expressions inside function expressions', + testCaseNoChange('const foo = function funcDecl() { const result = new SomeClass(); }'), + ); + + it( + 'does not annotate new expressions inside arrow functions', + testCaseNoChange('const foo = () => { const result = new SomeClass(); }'), + ); + + it( + 'does not annotate TypeScript helper functions (tslib)', + testCaseNoChange(` + class LanguageState {} + __decorate([ + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", void 0) + ], LanguageState.prototype, "checkLanguage", null); + `), + ); + + it( + 'does not annotate _defineProperty function', + testCaseNoChange(` + class LanguageState {} + _defineProperty( + LanguageState, + 'property', + 'value' + ); + `), + ); + + it( + 'does not annotate object literal methods', + testCaseNoChange(` + const literal = { + method() { + var newClazz = new Clazz(); + } + }; + `), + ); + + it( + 'annotates helper functions with non-numeric suffixes', + testCase({ + input: 'var result = __decorate$foo();', + expected: 'var result = /*#__PURE__*/ __decorate$foo();', + }), + ); + + it( + 'does not annotate helper functions with numeric suffixes', + testCaseNoChange('var result = __decorate$1();'), + ); + + describe('topLevelSafeMode: true', () => { + it( + 'annotates top-level `new InjectionToken` expressions', + testCase({ + input: `const result = new InjectionToken('abc');`, + expected: `const result = /*#__PURE__*/ new InjectionToken('abc');`, + options: { topLevelSafeMode: true }, + }), + ); + + it( + 'does not annotate other top-level `new` expressions', + testCase({ + input: 'const result = new SomeClass();', + expected: 'const result = new SomeClass();', + options: { topLevelSafeMode: true }, + }), + ); + + it( + 'does not annotate top-level function calls', + testCase({ + input: 'const result = someCall();', + expected: 'const result = someCall();', + options: { topLevelSafeMode: true }, + }), + ); + }); +}); diff --git a/packages/angular/build/src/tools/esbuild/javascript-transformer-worker.ts b/packages/angular/build/src/tools/esbuild/javascript-transformer-worker.ts index f2e5c0e64886..734a8a994882 100644 --- a/packages/angular/build/src/tools/esbuild/javascript-transformer-worker.ts +++ b/packages/angular/build/src/tools/esbuild/javascript-transformer-worker.ts @@ -42,7 +42,7 @@ export default async function transformJavaScript( const { filename, data, ...options } = request; const textData = typeof data === 'string' ? data : textDecoder.decode(data); - const transformedData = await transformWithBabel(filename, textData, options); + const transformedData = await transformJavaScriptImpl(filename, textData, options); // Transfer the data via `move` instead of cloning return Piscina.move(textEncoder.encode(transformedData)); @@ -54,7 +54,7 @@ export default async function transformJavaScript( let linkerPluginCreator: typeof import('@angular/compiler-cli/linker/babel').createEs2015LinkerPlugin | undefined; -async function transformWithBabel( +async function transformJavaScriptImpl( filename: string, data: string, options: Omit, @@ -64,7 +64,7 @@ async function transformWithBabel( options.sourcemap && (!!options.thirdPartySourcemaps || !/[\\/]node_modules[\\/]/.test(filename)); - const plugins: PluginItem[] = []; + const babelPlugins: PluginItem[] = []; if (options.instrumentForCoverage) { try { @@ -85,7 +85,7 @@ async function transformWithBabel( const { default: coveragePluginFactory } = await import('../babel/plugins/add-code-coverage.js'); - plugins.push(coveragePluginFactory(programVisitor) as unknown as PluginItem); + babelPlugins.push(coveragePluginFactory(programVisitor) as unknown as PluginItem); } catch (error) { throw new Error( `The 'istanbul-lib-instrument' package is required for code coverage but was not found. Please install the package.`, @@ -97,47 +97,52 @@ async function transformWithBabel( if (shouldLink) { // Lazy load the linker plugin only when linking is required const linkerPlugin = await createLinkerPlugin(options); - plugins.push(linkerPlugin as unknown as PluginItem); + babelPlugins.push(linkerPlugin as unknown as PluginItem); } - if (options.advancedOptimizations) { - const { adjustStaticMembers, adjustTypeScriptEnums, elideAngularMetadata, markTopLevelPure } = - await import('../babel/plugins'); + let code = data; + + // If Babel is needed, run it first + if (babelPlugins.length > 0) { + const result = await transformAsync(code, { + filename, + inputSourceMap: (useInputSourcemap ? undefined : false) as undefined, + sourceMaps: useInputSourcemap ? 'inline' : false, + compact: false, + configFile: false, + babelrc: false, + browserslistConfigFile: false, + plugins: babelPlugins, + }); + code = result?.code ?? code; + } + // Run advanced optimizations using our fast oxc-transform + if (options.advancedOptimizations) { + const { transform } = await import('../babel/plugins/oxc-transform.js'); const sideEffectFree = options.sideEffects === false; const safeAngularPackage = sideEffectFree && /[\\/]node_modules[\\/]@angular[\\/]/.test(filename); - - plugins.push( - [markTopLevelPure, { topLevelSafeMode: !safeAngularPackage }], - elideAngularMetadata, - adjustTypeScriptEnums, - [adjustStaticMembers, { wrapDecorators: sideEffectFree }], - ); - } - - // If no additional transformations are needed, return the data directly - if (plugins.length === 0) { - // Strip sourcemaps if they should not be used - return useInputSourcemap ? data : removeSourceMappingURL(data); + const topLevelSafeMode = !safeAngularPackage; + + const result = transform(filename, code, { + sourcemap: useInputSourcemap, + sideEffects: options.sideEffects, + jit: options.jit, + topLevelSafeMode, + }); + code = result.code; + + if (useInputSourcemap && result.map) { + // Strip old source map comment if Babel added one + code = removeSourceMappingURL(code); + const base64Map = Buffer.from(result.map).toString('base64'); + code += `\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,${base64Map}`; + } } - const result = await transformAsync(data, { - filename, - inputSourceMap: (useInputSourcemap ? undefined : false) as undefined, - sourceMaps: useInputSourcemap ? 'inline' : false, - compact: false, - configFile: false, - babelrc: false, - browserslistConfigFile: false, - plugins, - }); - - const outputCode = result?.code ?? data; - - // Strip sourcemaps if they should not be used. - // Babel will keep the original comments even if sourcemaps are disabled. - return useInputSourcemap ? outputCode : removeSourceMappingURL(outputCode); + // Strip sourcemaps if they should not be used + return useInputSourcemap ? code : removeSourceMappingURL(code); } async function requiresLinking(path: string, source: string): Promise { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e0026b7b1ad4..29b8cc517ccc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -78,13 +78,13 @@ importers: version: 0.28.0 '@eslint/compat': specifier: 2.1.0 - version: 2.1.0(eslint@10.6.0(jiti@2.7.0)) + version: 2.1.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2)) '@eslint/eslintrc': specifier: 3.3.5 - version: 3.3.5 + version: 3.3.5(supports-color@10.2.2) '@eslint/js': specifier: 10.0.1 - version: 10.0.1(eslint@10.6.0(jiti@2.7.0)) + version: 10.0.1(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2)) '@rollup/plugin-alias': specifier: ^6.0.0 version: 6.0.0(rollup@4.62.2) @@ -102,10 +102,10 @@ importers: version: 4.62.2 '@stylistic/eslint-plugin': specifier: ^5.0.0 - version: 5.10.0(eslint@10.6.0(jiti@2.7.0)) + version: 5.10.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2)) '@tony.ganchev/eslint-plugin-header': specifier: ~3.4.0 - version: 3.4.4(eslint@10.6.0(jiti@2.7.0)) + version: 3.4.4(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2)) '@types/babel__core': specifier: 7.20.5 version: 7.20.5 @@ -165,10 +165,10 @@ importers: version: 21.0.3 '@typescript-eslint/eslint-plugin': specifier: 8.63.0 - version: 8.63.0(@typescript-eslint/parser@8.63.0(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3) + version: 8.63.0(@typescript-eslint/parser@8.63.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) '@typescript-eslint/parser': specifier: 8.63.0 - version: 8.63.0(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3) + version: 8.63.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) ajv: specifier: 8.20.0 version: 8.20.0 @@ -183,16 +183,16 @@ importers: version: 0.28.1 eslint: specifier: 10.6.0 - version: 10.6.0(jiti@2.7.0) + version: 10.6.0(jiti@2.7.0)(supports-color@10.2.2) eslint-config-prettier: specifier: 10.1.8 - version: 10.1.8(eslint@10.6.0(jiti@2.7.0)) + version: 10.1.8(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2)) eslint-plugin-import: specifier: 2.32.0 - version: 2.32.0(@typescript-eslint/parser@8.63.0(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.6.0(jiti@2.7.0)) + version: 2.32.0(@typescript-eslint/parser@8.63.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2)) express: specifier: 5.2.1 - version: 5.2.1 + version: 5.2.1(supports-color@10.2.2) fast-glob: specifier: 3.3.3 version: 3.3.3 @@ -204,7 +204,7 @@ importers: version: 1.18.1 http-proxy-middleware: specifier: 4.2.0 - version: 4.2.0 + version: 4.2.0(supports-color@10.2.2) husky: specifier: 9.1.7 version: 9.1.7 @@ -222,19 +222,19 @@ importers: version: 7.0.0 karma: specifier: ~6.4.0 - version: 6.4.4(bufferutil@4.1.0)(utf-8-validate@6.0.6) + version: 6.4.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) karma-chrome-launcher: specifier: ~3.2.0 version: 3.2.0 karma-coverage: specifier: ~2.2.0 - version: 2.2.1 + version: 2.2.1(supports-color@10.2.2) karma-jasmine: specifier: ~5.1.0 - version: 5.1.0(karma@6.4.4(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + version: 5.1.0(karma@6.4.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6)) karma-jasmine-html-reporter: specifier: ~2.2.0 - version: 2.2.0(jasmine-core@6.3.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(karma@6.4.4(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + version: 2.2.0(jasmine-core@6.3.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6)))(karma@6.4.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6)) karma-source-map-support: specifier: 1.4.0 version: 1.4.0 @@ -282,10 +282,10 @@ importers: version: 1.10.0 verdaccio: specifier: 6.7.4 - version: 6.7.4(encoding@0.1.13) + version: 6.7.4(encoding@0.1.13)(supports-color@10.2.2) verdaccio-auth-memory: specifier: ^13.0.0 - version: 13.0.3 + version: 13.0.3(supports-color@10.2.2) zone.js: specifier: ^0.16.0 version: 0.16.2 @@ -309,7 +309,7 @@ importers: version: 4.1.10(vitest@4.1.10) browser-sync: specifier: 3.0.4 - version: 3.0.4(bufferutil@4.1.0)(utf-8-validate@6.0.6) + version: 3.0.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) istanbul-lib-instrument: specifier: 6.0.3 version: 6.0.3 @@ -360,7 +360,7 @@ importers: version: 0.28.1 https-proxy-agent: specifier: 9.1.0 - version: 9.1.0 + version: 9.1.0(supports-color@10.2.2) jsonc-parser: specifier: 3.3.1 version: 3.3.1 @@ -373,6 +373,9 @@ importers: mrmime: specifier: 2.0.1 version: 2.0.1 + oxc-parser: + specifier: 0.140.0 + version: 0.140.0 parse5-html-rewriting-stream: specifier: 8.0.1 version: 8.0.1 @@ -410,6 +413,9 @@ importers: '@angular/ssr': specifier: workspace:* version: link:../ssr + '@oxc-project/types': + specifier: 0.140.0 + version: 0.140.0 istanbul-lib-instrument: specifier: 6.0.3 version: 6.0.3 @@ -615,7 +621,7 @@ importers: version: 0.28.1 http-proxy-middleware: specifier: 4.2.0 - version: 4.2.0 + version: 4.2.0(supports-color@10.2.2) istanbul-lib-instrument: specifier: 6.0.3 version: 6.0.3 @@ -696,7 +702,7 @@ importers: version: 8.0.3(tslib@2.8.1)(webpack@5.108.4(esbuild@0.28.1)(postcss@8.5.16)) webpack-dev-server: specifier: 5.2.6 - version: 5.2.6(bufferutil@4.1.0)(tslib@2.8.1)(utf-8-validate@6.0.6)(webpack@5.108.4(esbuild@0.28.1)(postcss@8.5.16)) + version: 5.2.6(bufferutil@4.1.0)(supports-color@10.2.2)(tslib@2.8.1)(utf-8-validate@6.0.6)(webpack@5.108.4(esbuild@0.28.1)(postcss@8.5.16)) webpack-merge: specifier: 6.0.1 version: 6.0.1 @@ -709,7 +715,7 @@ importers: version: link:../../angular/ssr browser-sync: specifier: 3.0.4 - version: 3.0.4(bufferutil@4.1.0)(utf-8-validate@6.0.6) + version: 3.0.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) ng-packagr: specifier: 22.1.0-next.3 version: 22.1.0-next.3(@angular/compiler-cli@22.1.0-next.5(@angular/compiler@22.1.0-next.5)(typescript@6.0.3))(tslib@2.8.1)(typescript@6.0.3) @@ -1691,9 +1697,15 @@ packages: '@emnapi/core@1.11.1': resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + '@emnapi/core@1.11.2': + resolution: {integrity: sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==} + '@emnapi/runtime@1.11.1': resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + '@emnapi/runtime@1.11.2': + resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==} + '@emnapi/wasi-threads@1.2.2': resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} @@ -2830,9 +2842,139 @@ packages: resolution: {integrity: sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==} engines: {node: '>=14'} + '@oxc-parser/binding-android-arm-eabi@0.140.0': + resolution: {integrity: sha512-ZfjDZ422mo7eo3b3VltqNsV9kmv1qt/sPEAMSl64iOSwhVfd0eIZ9LB79Mbs1xYXJnk7WSROwzBCKDIiVxPTvQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxc-parser/binding-android-arm64@0.140.0': + resolution: {integrity: sha512-Ia8jSvikUX6Sf+Ht+KOCUF/k1HpR0VlmqIYymubmWDebOEGtsyliHDR6JxsZ4IX3/c/GbrB1uh09aVGQv/LQmQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxc-parser/binding-darwin-arm64@0.140.0': + resolution: {integrity: sha512-G6VK0nK61pH0d0mBjUqSZbVxGqqO5uzeginLDQj+gOO6ObfJjXRwgkD/ol0w1INcnFeAb6YGGO7qc3ueGHaycQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxc-parser/binding-darwin-x64@0.140.0': + resolution: {integrity: sha512-HazBOuZzd2pO1C2uMmp8Gv7mhzMHqKSKDS1OZfcLEvpIcgA+48J92HEtNanVHDIzRD9PRPCV6aS6fkZIWOVl8Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxc-parser/binding-freebsd-x64@0.140.0': + resolution: {integrity: sha512-9hSUU+HmTUyOe4JzMHxNGgLWNY7rrO+6ShicZwImNJacEAACDMIkuEQQkvXSL+WJN50jaNtLYJv8s4OcBdpyUQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxc-parser/binding-linux-arm-gnueabihf@0.140.0': + resolution: {integrity: sha512-RAEuQsYtS0KcDFqN0ABTjyyNlokS91JeuDuoW9tEbG0JTbRNXnpQUdbYc/16JoA6Z/2ALbNrE3KmxtqDiuIjCQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm-musleabihf@0.140.0': + resolution: {integrity: sha512-c4CkHvPvqfojouredJ0w3e6+jiBq0SbFyhH61kr/zPb/7XsaYTNKQ54vmlSsopfdQbNDX40ZeK9Abs2Qet6wcw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm64-gnu@0.140.0': + resolution: {integrity: sha512-yrjmLj8ixPB25yqvPGr28meGjb+keed7m1GqqY/0uqkhZIoT4t9zmfwUgFEtC33C7dtE+UQ7TU0IaVxf97SWJg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-arm64-musl@0.140.0': + resolution: {integrity: sha512-ggGMQTN8Agwxp2WiLMpdY671dt0qTDJWiWlJeig3HnUwTnerRl0J2JdGVghWBeDcss2D9S2V2Js6dZHEiVabVA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-ppc64-gnu@0.140.0': + resolution: {integrity: sha512-IgTs8xYAFgAUGNmR65tIqjlJ8vKgrfXzC515e9goSdfMyKQV4aJpd2pUUudU4u51G64H0/DSEJEXKOraxm9ZCA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-gnu@0.140.0': + resolution: {integrity: sha512-A1x+PMWZmSGaFVOx2YeNTFau8uD+QO14/vLP4GrcuvUPs3+nBkUOjy9Lus86ftHsDojjYMbvBelmKc3F7Rv08g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-musl@0.140.0': + resolution: {integrity: sha512-zBqpfRo2myWPrPo5xUjeZqlnPXPXsX8BcWtWff66/eGRQdbPjhzPgXa/F+AtxT2afUViPxbuDlwscMKzQ5tg+g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-s390x-gnu@0.140.0': + resolution: {integrity: sha512-2M1DPm/8w9I//YzFlFC9qXw+r2tJFh5CYwRlYTq2vUJQS7qoQftEDeCZ8EnN7KHtvSiXvYj8mZI5pR7DpXmcEw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-gnu@0.140.0': + resolution: {integrity: sha512-8aRDbZ/U/jO8N7go1MO72jtbpb4uswV8d7vOkMvt/BPgZiyEYvl1VIWK4ESxZZhnJ4tqwVldgX7dNiP/eB1Jdg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-musl@0.140.0': + resolution: {integrity: sha512-xRqpeI8U2sQQS1W5BMWRyMTxtagkuLG2dEWruet5lFsWHTvBth11/TpSaJatHdqVVwHN0q3uuoS9zRsGinq8hg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-openharmony-arm64@0.140.0': + resolution: {integrity: sha512-GbGRe26MqAKciFRvXeHNQJ6VAHYs9R4miP89sEAncysM3n+f4lnyLWgsa9kklJNpfnxdq2yRoNYHFqwBckVimw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxc-parser/binding-wasm32-wasi@0.140.0': + resolution: {integrity: sha512-vFiC1hqys+hkX1GnQkIoiTQJNiUm43Z0lO35ETKXTw0YtpW7+cN58YRRXFAQQ+TgpkIi3lrhcxdlnqz+Oi3ptQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@oxc-parser/binding-win32-arm64-msvc@0.140.0': + resolution: {integrity: sha512-fGSQldwEYKhM+H8uLt76Op8hh5+FYaR6lvvQ1Txw3Mhn86DyQXLcI0fi1EkFlTK7F+46OCk/j0AJMzZQm6g5Xg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxc-parser/binding-win32-ia32-msvc@0.140.0': + resolution: {integrity: sha512-sDS2Bai+g3ZWYwfZqmosiSuFDBcVnZ3Ta6pszzsiJoLMqsJEWKcxXXbGa7b7yXr++W2lQNPb3ZRJ8czseqL7RA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxc-parser/binding-win32-x64-msvc@0.140.0': + resolution: {integrity: sha512-kHbE1zWyb5OQgJA6/5P4WjiuB01sYdQwtZnSSyE58FQEXDAMnyeeq4vj7KgN75i5SlBzOs8A5MrtlD3gOlDKqQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@oxc-project/types@0.139.0': resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + '@oxc-project/types@0.140.0': + resolution: {integrity: sha512-h5LUOzGArYemnW1NMz/DuuQhBi96J6JL2Bk8zE4kvqxB5Sg3jxmCiH4uyOWHDkiKSt5vWlG4FIwCR/DbstcNRQ==} + '@parcel/watcher-android-arm64@2.5.6': resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==} engines: {node: '>= 10.0.0'} @@ -6612,6 +6754,10 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} + oxc-parser@0.140.0: + resolution: {integrity: sha512-h6QFWd6lBMfjESqgQ27GjzrSDb0qbznp7VDQqp2zvgsrWut4vcchyMIzOVXvGQ2GMZgKw9RWrFNWv9WqGL0p7Q==} + engines: {node: ^20.19.0 || >=22.12.0} + p-cancelable@2.1.1: resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} engines: {node: '>=8'} @@ -9276,11 +9422,22 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/core@1.11.2': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.11.1': dependencies: tslib: 2.8.1 optional: true + '@emnapi/runtime@1.11.2': + dependencies: + tslib: 2.8.1 + optional: true + '@emnapi/wasi-threads@1.2.2': dependencies: tslib: 2.8.1 @@ -9364,20 +9521,20 @@ snapshots: '@esbuild/win32-x64@0.28.1': optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@10.6.0(jiti@2.7.0))': + '@eslint-community/eslint-utils@4.9.1(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))': dependencies: - eslint: 10.6.0(jiti@2.7.0) + eslint: 10.6.0(jiti@2.7.0)(supports-color@10.2.2) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} - '@eslint/compat@2.1.0(eslint@10.6.0(jiti@2.7.0))': + '@eslint/compat@2.1.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))': dependencies: '@eslint/core': 1.2.1 optionalDependencies: - eslint: 10.6.0(jiti@2.7.0) + eslint: 10.6.0(jiti@2.7.0)(supports-color@10.2.2) - '@eslint/config-array@0.23.5': + '@eslint/config-array@0.23.5(supports-color@10.2.2)': dependencies: '@eslint/object-schema': 3.0.5 debug: 4.4.3(supports-color@10.2.2) @@ -9393,7 +9550,7 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.3.5': + '@eslint/eslintrc@3.3.5(supports-color@10.2.2)': dependencies: ajv: 6.15.0 debug: 4.4.3(supports-color@10.2.2) @@ -9407,9 +9564,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@10.0.1(eslint@10.6.0(jiti@2.7.0))': + '@eslint/js@10.0.1(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))': optionalDependencies: - eslint: 10.6.0(jiti@2.7.0) + eslint: 10.6.0(jiti@2.7.0)(supports-color@10.2.2) '@eslint/object-schema@3.0.5': {} @@ -10189,8 +10346,8 @@ snapshots: cross-spawn: 7.0.6 eventsource: 3.0.7 eventsource-parser: 3.1.0 - express: 5.2.1 - express-rate-limit: 8.5.2(express@5.2.1) + express: 5.2.1(supports-color@10.2.2) + express-rate-limit: 8.5.2(express@5.2.1(supports-color@10.2.2)) hono: 4.12.30 jose: 6.2.3 json-schema-typed: 8.0.2 @@ -10307,6 +10464,13 @@ snapshots: '@tybys/wasm-util': 0.10.3 optional: true + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@tybys/wasm-util': 0.10.3 + optional: true + '@noble/hashes@1.4.0': {} '@nodelib/fs.scandir@2.1.5': @@ -10454,8 +10618,74 @@ snapshots: '@opentelemetry/semantic-conventions@1.43.0': {} + '@oxc-parser/binding-android-arm-eabi@0.140.0': + optional: true + + '@oxc-parser/binding-android-arm64@0.140.0': + optional: true + + '@oxc-parser/binding-darwin-arm64@0.140.0': + optional: true + + '@oxc-parser/binding-darwin-x64@0.140.0': + optional: true + + '@oxc-parser/binding-freebsd-x64@0.140.0': + optional: true + + '@oxc-parser/binding-linux-arm-gnueabihf@0.140.0': + optional: true + + '@oxc-parser/binding-linux-arm-musleabihf@0.140.0': + optional: true + + '@oxc-parser/binding-linux-arm64-gnu@0.140.0': + optional: true + + '@oxc-parser/binding-linux-arm64-musl@0.140.0': + optional: true + + '@oxc-parser/binding-linux-ppc64-gnu@0.140.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-gnu@0.140.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-musl@0.140.0': + optional: true + + '@oxc-parser/binding-linux-s390x-gnu@0.140.0': + optional: true + + '@oxc-parser/binding-linux-x64-gnu@0.140.0': + optional: true + + '@oxc-parser/binding-linux-x64-musl@0.140.0': + optional: true + + '@oxc-parser/binding-openharmony-arm64@0.140.0': + optional: true + + '@oxc-parser/binding-wasm32-wasi@0.140.0': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + optional: true + + '@oxc-parser/binding-win32-arm64-msvc@0.140.0': + optional: true + + '@oxc-parser/binding-win32-ia32-msvc@0.140.0': + optional: true + + '@oxc-parser/binding-win32-x64-msvc@0.140.0': + optional: true + '@oxc-project/types@0.139.0': {} + '@oxc-project/types@0.140.0': {} + '@parcel/watcher-android-arm64@2.5.6': optional: true @@ -10847,11 +11077,11 @@ snapshots: '@standard-schema/spec@1.1.0': {} - '@stylistic/eslint-plugin@5.10.0(eslint@10.6.0(jiti@2.7.0))': + '@stylistic/eslint-plugin@5.10.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.6.0(jiti@2.7.0)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2)) '@typescript-eslint/types': 8.64.0 - eslint: 10.6.0(jiti@2.7.0) + eslint: 10.6.0(jiti@2.7.0)(supports-color@10.2.2) eslint-visitor-keys: 4.2.1 espree: 10.4.0 estraverse: 5.3.0 @@ -10861,9 +11091,9 @@ snapshots: dependencies: defer-to-connect: 2.0.1 - '@tony.ganchev/eslint-plugin-header@3.4.4(eslint@10.6.0(jiti@2.7.0))': + '@tony.ganchev/eslint-plugin-header@3.4.4(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))': dependencies: - eslint: 10.6.0(jiti@2.7.0) + eslint: 10.6.0(jiti@2.7.0)(supports-color@10.2.2) '@tybys/wasm-util@0.10.3': dependencies: @@ -11133,15 +11363,15 @@ snapshots: '@types/yarnpkg__lockfile@1.1.9': {} - '@typescript-eslint/eslint-plugin@8.63.0(@typescript-eslint/parser@8.63.0(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3)': + '@typescript-eslint/eslint-plugin@8.63.0(@typescript-eslint/parser@8.63.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.63.0(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/parser': 8.63.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) '@typescript-eslint/scope-manager': 8.63.0 - '@typescript-eslint/type-utils': 8.63.0(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/utils': 8.63.0(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/type-utils': 8.63.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/utils': 8.63.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(typescript@6.0.3) '@typescript-eslint/visitor-keys': 8.63.0 - eslint: 10.6.0(jiti@2.7.0) + eslint: 10.6.0(jiti@2.7.0)(supports-color@10.2.2) ignore: 7.0.6 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@6.0.3) @@ -11149,19 +11379,19 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.63.0(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3)': + '@typescript-eslint/parser@8.63.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': dependencies: '@typescript-eslint/scope-manager': 8.63.0 '@typescript-eslint/types': 8.63.0 - '@typescript-eslint/typescript-estree': 8.63.0(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.63.0(supports-color@10.2.2)(typescript@6.0.3) '@typescript-eslint/visitor-keys': 8.63.0 debug: 4.4.3(supports-color@10.2.2) - eslint: 10.6.0(jiti@2.7.0) + eslint: 10.6.0(jiti@2.7.0)(supports-color@10.2.2) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.63.0(typescript@6.0.3)': + '@typescript-eslint/project-service@8.63.0(supports-color@10.2.2)(typescript@6.0.3)': dependencies: '@typescript-eslint/tsconfig-utils': 8.63.0(typescript@6.0.3) '@typescript-eslint/types': 8.63.0 @@ -11179,13 +11409,13 @@ snapshots: dependencies: typescript: 6.0.3 - '@typescript-eslint/type-utils@8.63.0(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3)': + '@typescript-eslint/type-utils@8.63.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': dependencies: '@typescript-eslint/types': 8.63.0 - '@typescript-eslint/typescript-estree': 8.63.0(typescript@6.0.3) - '@typescript-eslint/utils': 8.63.0(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.63.0(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/utils': 8.63.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(typescript@6.0.3) debug: 4.4.3(supports-color@10.2.2) - eslint: 10.6.0(jiti@2.7.0) + eslint: 10.6.0(jiti@2.7.0)(supports-color@10.2.2) ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: @@ -11195,9 +11425,9 @@ snapshots: '@typescript-eslint/types@8.64.0': {} - '@typescript-eslint/typescript-estree@8.63.0(typescript@6.0.3)': + '@typescript-eslint/typescript-estree@8.63.0(supports-color@10.2.2)(typescript@6.0.3)': dependencies: - '@typescript-eslint/project-service': 8.63.0(typescript@6.0.3) + '@typescript-eslint/project-service': 8.63.0(supports-color@10.2.2)(typescript@6.0.3) '@typescript-eslint/tsconfig-utils': 8.63.0(typescript@6.0.3) '@typescript-eslint/types': 8.63.0 '@typescript-eslint/visitor-keys': 8.63.0 @@ -11210,13 +11440,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.63.0(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3)': + '@typescript-eslint/utils@8.63.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(typescript@6.0.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.6.0(jiti@2.7.0)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2)) '@typescript-eslint/scope-manager': 8.63.0 '@typescript-eslint/types': 8.63.0 - '@typescript-eslint/typescript-estree': 8.63.0(typescript@6.0.3) - eslint: 10.6.0(jiti@2.7.0) + '@typescript-eslint/typescript-estree': 8.63.0(supports-color@10.2.2)(typescript@6.0.3) + eslint: 10.6.0(jiti@2.7.0)(supports-color@10.2.2) typescript: 6.0.3 transitivePeerDependencies: - supports-color @@ -11226,7 +11456,7 @@ snapshots: '@typescript-eslint/types': 8.63.0 eslint-visitor-keys: 5.0.1 - '@verdaccio/auth@8.0.4': + '@verdaccio/auth@8.0.4(supports-color@10.2.2)': dependencies: '@verdaccio/config': 8.1.2 '@verdaccio/core': 8.1.2 @@ -11260,7 +11490,7 @@ snapshots: dependencies: lockfile: 1.0.4 - '@verdaccio/hooks@8.0.3': + '@verdaccio/hooks@8.0.3(supports-color@10.2.2)': dependencies: '@verdaccio/core': 8.1.2 '@verdaccio/logger': 8.0.3 @@ -11278,7 +11508,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@verdaccio/local-storage-legacy@11.3.4': + '@verdaccio/local-storage-legacy@11.3.4(supports-color@10.2.2)': dependencies: '@verdaccio/core': 8.1.2 '@verdaccio/file-locking': 13.0.1 @@ -11317,11 +11547,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@verdaccio/middleware@8.0.5': + '@verdaccio/middleware@8.0.5(supports-color@10.2.2)': dependencies: '@verdaccio/config': 8.1.2 '@verdaccio/core': 8.1.2 - '@verdaccio/url': 13.0.3 + '@verdaccio/url': 13.0.3(supports-color@10.2.2) debug: 4.4.3(supports-color@10.2.2) express: 4.22.1 express-rate-limit: 5.5.1 @@ -11330,7 +11560,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@verdaccio/package-filter@13.0.3': + '@verdaccio/package-filter@13.0.3(supports-color@10.2.2)': dependencies: '@verdaccio/core': 8.1.2 debug: 4.4.3(supports-color@10.2.2) @@ -11338,7 +11568,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@verdaccio/search-indexer@8.0.2': + '@verdaccio/search-indexer@8.0.2(supports-color@10.2.2)': dependencies: debug: 4.4.3(supports-color@10.2.2) fuse.js: 7.3.0 @@ -11356,10 +11586,10 @@ snapshots: '@verdaccio/streams@10.2.5': {} - '@verdaccio/tarball@13.0.3': + '@verdaccio/tarball@13.0.3(supports-color@10.2.2)': dependencies: '@verdaccio/core': 8.1.2 - '@verdaccio/url': 13.0.3 + '@verdaccio/url': 13.0.3(supports-color@10.2.2) debug: 4.4.3(supports-color@10.2.2) gunzip-maybe: 1.4.2 tar-stream: 3.1.7 @@ -11368,13 +11598,13 @@ snapshots: - react-native-b4a - supports-color - '@verdaccio/ui-theme@9.0.0-next-9.20': + '@verdaccio/ui-theme@9.0.0-next-9.20(supports-color@10.2.2)': dependencies: debug: 4.4.3(supports-color@10.2.2) transitivePeerDependencies: - supports-color - '@verdaccio/url@13.0.3': + '@verdaccio/url@13.0.3(supports-color@10.2.2)': dependencies: '@verdaccio/core': 8.1.2 debug: 4.4.3(supports-color@10.2.2) @@ -11565,7 +11795,7 @@ snapshots: loader-utils: 2.0.4 regex-parser: 2.3.1 - agent-base@6.0.2: + agent-base@6.0.2(supports-color@10.2.2): dependencies: debug: 4.4.3(supports-color@10.2.2) transitivePeerDependencies: @@ -11869,7 +12099,7 @@ snapshots: transitivePeerDependencies: - supports-color - body-parser@2.3.0: + body-parser@2.3.0(supports-color@10.2.2): dependencies: bytes: 3.1.2 content-type: 2.0.0 @@ -11915,24 +12145,24 @@ snapshots: fresh: 0.5.2 mitt: 1.2.0 - browser-sync-ui@3.0.4(bufferutil@4.1.0)(utf-8-validate@6.0.6): + browser-sync-ui@3.0.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6): dependencies: async-each-series: 0.1.1 chalk: 4.1.2 connect-history-api-fallback: 1.6.0 immutable: 3.8.3 server-destroy: 1.0.1 - socket.io-client: 4.8.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) + socket.io-client: 4.8.3(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) stream-throttle: 0.1.3 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - browser-sync@3.0.4(bufferutil@4.1.0)(utf-8-validate@6.0.6): + browser-sync@3.0.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6): dependencies: browser-sync-client: 3.0.4 - browser-sync-ui: 3.0.4(bufferutil@4.1.0)(utf-8-validate@6.0.6) + browser-sync-ui: 3.0.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) bs-recipes: 1.3.4 chalk: 4.1.2 chokidar: 3.6.0 @@ -11956,7 +12186,7 @@ snapshots: serve-index: 1.9.2 serve-static: 1.16.3 server-destroy: 1.0.1 - socket.io: 4.8.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) + socket.io: 4.8.3(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) ua-parser-js: 1.0.41 yargs: 17.7.3 transitivePeerDependencies: @@ -12507,7 +12737,7 @@ snapshots: dependencies: once: 1.4.0 - engine.io-client@6.6.6(bufferutil@4.1.0)(utf-8-validate@6.0.6): + engine.io-client@6.6.6(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6): dependencies: '@socket.io/component-emitter': 3.1.2 debug: 4.4.3(supports-color@10.2.2) @@ -12521,7 +12751,7 @@ snapshots: engine.io-parser@5.2.3: {} - engine.io@6.6.9(bufferutil@4.1.0)(utf-8-validate@6.0.6): + engine.io@6.6.9(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6): dependencies: '@types/cors': 2.8.19 '@types/node': 22.20.1 @@ -12702,9 +12932,9 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.8(eslint@10.6.0(jiti@2.7.0)): + eslint-config-prettier@10.1.8(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2)): dependencies: - eslint: 10.6.0(jiti@2.7.0) + eslint: 10.6.0(jiti@2.7.0)(supports-color@10.2.2) eslint-import-resolver-node@0.3.10: dependencies: @@ -12714,17 +12944,17 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.14.0(@typescript-eslint/parser@8.63.0(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint@10.6.0(jiti@2.7.0)): + eslint-module-utils@2.14.0(@typescript-eslint/parser@8.63.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.63.0(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3) - eslint: 10.6.0(jiti@2.7.0) + '@typescript-eslint/parser': 8.63.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + eslint: 10.6.0(jiti@2.7.0)(supports-color@10.2.2) eslint-import-resolver-node: 0.3.10 transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.63.0(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.6.0(jiti@2.7.0)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.63.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -12733,9 +12963,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 10.6.0(jiti@2.7.0) + eslint: 10.6.0(jiti@2.7.0)(supports-color@10.2.2) eslint-import-resolver-node: 0.3.10 - eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.63.0(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint@10.6.0(jiti@2.7.0)) + eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.63.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2)) hasown: 2.0.4 is-core-module: 2.16.2 is-glob: 4.0.3 @@ -12747,7 +12977,7 @@ snapshots: string.prototype.trimend: 1.0.10 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.63.0(eslint@10.6.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/parser': 8.63.0(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -12771,11 +13001,11 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.6.0(jiti@2.7.0): + eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.6.0(jiti@2.7.0)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.6.0(jiti@2.7.0)(supports-color@10.2.2)) '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.23.5 + '@eslint/config-array': 0.23.5(supports-color@10.2.2) '@eslint/config-helpers': 0.6.0 '@eslint/core': 1.2.1 '@eslint/plugin-kit': 0.7.2 @@ -12868,9 +13098,9 @@ snapshots: express-rate-limit@5.5.1: {} - express-rate-limit@8.5.2(express@5.2.1): + express-rate-limit@8.5.2(express@5.2.1(supports-color@10.2.2)): dependencies: - express: 5.2.1 + express: 5.2.1(supports-color@10.2.2) ip-address: 10.2.0 express@4.22.1: @@ -12945,10 +13175,10 @@ snapshots: transitivePeerDependencies: - supports-color - express@5.2.1: + express@5.2.1(supports-color@10.2.2): dependencies: accepts: 2.0.0 - body-parser: 2.3.0 + body-parser: 2.3.0(supports-color@10.2.2) content-disposition: 1.1.0 content-type: 1.0.5 cookie: 0.7.2 @@ -12958,7 +13188,7 @@ snapshots: encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 - finalhandler: 2.1.1 + finalhandler: 2.1.1(supports-color@10.2.2) fresh: 2.0.0 http-errors: 2.0.1 merge-descriptors: 2.0.0 @@ -12969,8 +13199,8 @@ snapshots: proxy-addr: 2.0.7 qs: 6.15.3 range-parser: 1.3.0 - router: 2.2.0 - send: 1.2.1 + router: 2.2.0(supports-color@10.2.2) + send: 1.2.1(supports-color@10.2.2) serve-static: 2.2.1 statuses: 2.0.2 type-is: 2.1.0 @@ -13071,7 +13301,7 @@ snapshots: transitivePeerDependencies: - supports-color - finalhandler@2.1.1: + finalhandler@2.1.1(supports-color@10.2.2): dependencies: debug: 4.4.3(supports-color@10.2.2) encodeurl: 2.0.0 @@ -13536,7 +13766,7 @@ snapshots: transitivePeerDependencies: - debug - http-proxy-middleware@4.2.0: + http-proxy-middleware@4.2.0(supports-color@10.2.2): dependencies: debug: 4.4.3(supports-color@10.2.2) httpxy: 0.5.5 @@ -13567,9 +13797,9 @@ snapshots: quick-lru: 5.1.1 resolve-alpn: 1.2.1 - https-proxy-agent@5.0.1: + https-proxy-agent@5.0.1(supports-color@10.2.2): dependencies: - agent-base: 6.0.2 + agent-base: 6.0.2(supports-color@10.2.2) debug: 4.4.3(supports-color@10.2.2) transitivePeerDependencies: - supports-color @@ -13581,7 +13811,7 @@ snapshots: transitivePeerDependencies: - supports-color - https-proxy-agent@9.1.0: + https-proxy-agent@9.1.0(supports-color@10.2.2): dependencies: agent-base: 9.0.0 debug: 4.4.3(supports-color@10.2.2) @@ -13885,7 +14115,7 @@ snapshots: make-dir: 4.0.0 supports-color: 7.2.0 - istanbul-lib-source-maps@4.0.1: + istanbul-lib-source-maps@4.0.1(supports-color@10.2.2): dependencies: debug: 4.4.3(supports-color@10.2.2) istanbul-lib-coverage: 3.2.2 @@ -14052,33 +14282,33 @@ snapshots: dependencies: which: 1.3.1 - karma-coverage@2.2.1: + karma-coverage@2.2.1(supports-color@10.2.2): dependencies: istanbul-lib-coverage: 3.2.2 istanbul-lib-instrument: 5.2.1 istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1 + istanbul-lib-source-maps: 4.0.1(supports-color@10.2.2) istanbul-reports: 3.2.0 minimatch: 3.1.5 transitivePeerDependencies: - supports-color - karma-jasmine-html-reporter@2.2.0(jasmine-core@6.3.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(karma@6.4.4(bufferutil@4.1.0)(utf-8-validate@6.0.6)): + karma-jasmine-html-reporter@2.2.0(jasmine-core@6.3.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6)))(karma@6.4.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6)): dependencies: jasmine-core: 6.3.0 - karma: 6.4.4(bufferutil@4.1.0)(utf-8-validate@6.0.6) - karma-jasmine: 5.1.0(karma@6.4.4(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + karma: 6.4.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) + karma-jasmine: 5.1.0(karma@6.4.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6)) - karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(utf-8-validate@6.0.6)): + karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6)): dependencies: jasmine-core: 4.6.1 - karma: 6.4.4(bufferutil@4.1.0)(utf-8-validate@6.0.6) + karma: 6.4.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) karma-source-map-support@1.4.0: dependencies: source-map-support: 0.5.21 - karma@6.4.4(bufferutil@4.1.0)(utf-8-validate@6.0.6): + karma@6.4.4(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6): dependencies: '@colors/colors': 1.5.0 body-parser: 1.20.6 @@ -14099,7 +14329,7 @@ snapshots: qjobs: 1.2.0 range-parser: 1.3.0 rimraf: 3.0.2 - socket.io: 4.8.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) + socket.io: 4.8.3(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) source-map: 0.6.1 tmp: 0.2.7 ua-parser-js: 0.7.41 @@ -14724,6 +14954,31 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 + oxc-parser@0.140.0: + dependencies: + '@oxc-project/types': 0.140.0 + optionalDependencies: + '@oxc-parser/binding-android-arm-eabi': 0.140.0 + '@oxc-parser/binding-android-arm64': 0.140.0 + '@oxc-parser/binding-darwin-arm64': 0.140.0 + '@oxc-parser/binding-darwin-x64': 0.140.0 + '@oxc-parser/binding-freebsd-x64': 0.140.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.140.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.140.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.140.0 + '@oxc-parser/binding-linux-arm64-musl': 0.140.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.140.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.140.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.140.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.140.0 + '@oxc-parser/binding-linux-x64-gnu': 0.140.0 + '@oxc-parser/binding-linux-x64-musl': 0.140.0 + '@oxc-parser/binding-openharmony-arm64': 0.140.0 + '@oxc-parser/binding-wasm32-wasi': 0.140.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.140.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.140.0 + '@oxc-parser/binding-win32-x64-msvc': 0.140.0 + p-cancelable@2.1.1: {} p-finally@1.0.0: {} @@ -15327,7 +15582,7 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.62.2 fsevents: 2.3.3 - router@2.2.0: + router@2.2.0(supports-color@10.2.2): dependencies: debug: 4.4.3(supports-color@10.2.2) depd: 2.0.0 @@ -15440,7 +15695,7 @@ snapshots: transitivePeerDependencies: - supports-color - send@1.2.1: + send@1.2.1(supports-color@10.2.2): dependencies: debug: 4.4.3(supports-color@10.2.2) encodeurl: 2.0.0 @@ -15484,7 +15739,7 @@ snapshots: encodeurl: 2.0.0 escape-html: 1.0.3 parseurl: 1.3.3 - send: 1.2.1 + send: 1.2.1(supports-color@10.2.2) transitivePeerDependencies: - supports-color @@ -15572,7 +15827,7 @@ snapshots: ansi-styles: 6.2.3 is-fullwidth-code-point: 5.1.0 - socket.io-adapter@2.5.8(bufferutil@4.1.0)(utf-8-validate@6.0.6): + socket.io-adapter@2.5.8(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6): dependencies: debug: 4.4.3(supports-color@10.2.2) ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) @@ -15581,33 +15836,33 @@ snapshots: - supports-color - utf-8-validate - socket.io-client@4.8.3(bufferutil@4.1.0)(utf-8-validate@6.0.6): + socket.io-client@4.8.3(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6): dependencies: '@socket.io/component-emitter': 3.1.2 debug: 4.4.3(supports-color@10.2.2) - engine.io-client: 6.6.6(bufferutil@4.1.0)(utf-8-validate@6.0.6) - socket.io-parser: 4.2.6 + engine.io-client: 6.6.6(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) + socket.io-parser: 4.2.6(supports-color@10.2.2) transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - socket.io-parser@4.2.6: + socket.io-parser@4.2.6(supports-color@10.2.2): dependencies: '@socket.io/component-emitter': 3.1.2 debug: 4.4.3(supports-color@10.2.2) transitivePeerDependencies: - supports-color - socket.io@4.8.3(bufferutil@4.1.0)(utf-8-validate@6.0.6): + socket.io@4.8.3(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6): dependencies: accepts: 1.3.8 base64id: 2.0.0 cors: 2.8.6 debug: 4.4.3(supports-color@10.2.2) - engine.io: 6.6.9(bufferutil@4.1.0)(utf-8-validate@6.0.6) - socket.io-adapter: 2.5.8(bufferutil@4.1.0)(utf-8-validate@6.0.6) - socket.io-parser: 4.2.6 + engine.io: 6.6.9(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) + socket.io-adapter: 2.5.8(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) + socket.io-parser: 4.2.6(supports-color@10.2.2) transitivePeerDependencies: - bufferutil - supports-color @@ -15657,7 +15912,7 @@ snapshots: spdx-license-ids@3.0.23: {} - spdy-transport@3.0.0: + spdy-transport@3.0.0(supports-color@10.2.2): dependencies: debug: 4.4.3(supports-color@10.2.2) detect-node: 2.1.0 @@ -15668,13 +15923,13 @@ snapshots: transitivePeerDependencies: - supports-color - spdy@4.0.2: + spdy@4.0.2(supports-color@10.2.2): dependencies: debug: 4.4.3(supports-color@10.2.2) handle-thing: 2.0.1 http-deceiver: 1.2.7 select-hose: 2.0.0 - spdy-transport: 3.0.0 + spdy-transport: 3.0.0(supports-color@10.2.2) transitivePeerDependencies: - supports-color @@ -16154,18 +16409,18 @@ snapshots: vary@1.1.2: {} - verdaccio-audit@13.0.3(encoding@0.1.13): + verdaccio-audit@13.0.3(encoding@0.1.13)(supports-color@10.2.2): dependencies: '@verdaccio/config': 8.1.2 '@verdaccio/core': 8.1.2 express: 4.22.1 - https-proxy-agent: 5.0.1 + https-proxy-agent: 5.0.1(supports-color@10.2.2) node-fetch: 2.6.7(encoding@0.1.13) transitivePeerDependencies: - encoding - supports-color - verdaccio-auth-memory@13.0.3: + verdaccio-auth-memory@13.0.3(supports-color@10.2.2): dependencies: '@verdaccio/core': 8.1.2 debug: 4.4.3(supports-color@10.2.2) @@ -16184,24 +16439,24 @@ snapshots: transitivePeerDependencies: - supports-color - verdaccio@6.7.4(encoding@0.1.13): + verdaccio@6.7.4(encoding@0.1.13)(supports-color@10.2.2): dependencies: '@cypress/request': 3.0.10 - '@verdaccio/auth': 8.0.4 + '@verdaccio/auth': 8.0.4(supports-color@10.2.2) '@verdaccio/config': 8.1.2 '@verdaccio/core': 8.1.2 - '@verdaccio/hooks': 8.0.3 + '@verdaccio/hooks': 8.0.3(supports-color@10.2.2) '@verdaccio/loaders': 8.0.3 - '@verdaccio/local-storage-legacy': 11.3.4 + '@verdaccio/local-storage-legacy': 11.3.4(supports-color@10.2.2) '@verdaccio/logger': 8.0.3 - '@verdaccio/middleware': 8.0.5 - '@verdaccio/package-filter': 13.0.3 - '@verdaccio/search-indexer': 8.0.2 + '@verdaccio/middleware': 8.0.5(supports-color@10.2.2) + '@verdaccio/package-filter': 13.0.3(supports-color@10.2.2) + '@verdaccio/search-indexer': 8.0.2(supports-color@10.2.2) '@verdaccio/signature': 8.0.3 '@verdaccio/streams': 10.2.5 - '@verdaccio/tarball': 13.0.3 - '@verdaccio/ui-theme': 9.0.0-next-9.20 - '@verdaccio/url': 13.0.3 + '@verdaccio/tarball': 13.0.3(supports-color@10.2.2) + '@verdaccio/ui-theme': 9.0.0-next-9.20(supports-color@10.2.2) + '@verdaccio/url': 13.0.3(supports-color@10.2.2) '@verdaccio/utils': 8.1.3 JSONStream: 1.3.5 async: 3.2.6 @@ -16215,7 +16470,7 @@ snapshots: lru-cache: 7.18.3 mime: 3.0.0 semver: 7.8.2 - verdaccio-audit: 13.0.3(encoding@0.1.13) + verdaccio-audit: 13.0.3(encoding@0.1.13)(supports-color@10.2.2) verdaccio-htpasswd: 13.0.3 transitivePeerDependencies: - bare-abort-controller @@ -16353,7 +16608,7 @@ snapshots: transitivePeerDependencies: - tslib - webpack-dev-server@5.2.6(bufferutil@4.1.0)(tslib@2.8.1)(utf-8-validate@6.0.6)(webpack@5.108.4(esbuild@0.28.1)(postcss@8.5.16)): + webpack-dev-server@5.2.6(bufferutil@4.1.0)(supports-color@10.2.2)(tslib@2.8.1)(utf-8-validate@6.0.6)(webpack@5.108.4(esbuild@0.28.1)(postcss@8.5.16)): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 @@ -16380,7 +16635,7 @@ snapshots: selfsigned: 5.5.0 serve-index: 1.9.2 sockjs: 0.3.24 - spdy: 4.0.2 + spdy: 4.0.2(supports-color@10.2.2) webpack-dev-middleware: 7.4.5(tslib@2.8.1)(webpack@5.108.4(esbuild@0.28.1)(postcss@8.5.16)) ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) optionalDependencies: @@ -16419,7 +16674,7 @@ snapshots: selfsigned: 5.5.0 serve-index: 1.9.2 sockjs: 0.3.24 - spdy: 4.0.2 + spdy: 4.0.2(supports-color@10.2.2) webpack-dev-middleware: 7.4.5(tslib@2.8.1)(webpack@5.108.4(esbuild@0.28.1)) ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) optionalDependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index a8b25e500967..96e88d3f5f0e 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -24,6 +24,28 @@ minimumReleaseAgeExclude: - '@ngtools/webpack' - '@schematics/*' - 'ng-packagr' + - '@oxc-parser/binding-android-arm-eabi@0.140.0' + - '@oxc-parser/binding-android-arm64@0.140.0' + - '@oxc-parser/binding-darwin-arm64@0.140.0' + - '@oxc-parser/binding-darwin-x64@0.140.0' + - '@oxc-parser/binding-freebsd-x64@0.140.0' + - '@oxc-parser/binding-linux-arm-gnueabihf@0.140.0' + - '@oxc-parser/binding-linux-arm-musleabihf@0.140.0' + - '@oxc-parser/binding-linux-arm64-gnu@0.140.0' + - '@oxc-parser/binding-linux-arm64-musl@0.140.0' + - '@oxc-parser/binding-linux-ppc64-gnu@0.140.0' + - '@oxc-parser/binding-linux-riscv64-gnu@0.140.0' + - '@oxc-parser/binding-linux-riscv64-musl@0.140.0' + - '@oxc-parser/binding-linux-s390x-gnu@0.140.0' + - '@oxc-parser/binding-linux-x64-gnu@0.140.0' + - '@oxc-parser/binding-linux-x64-musl@0.140.0' + - '@oxc-parser/binding-openharmony-arm64@0.140.0' + - '@oxc-parser/binding-wasm32-wasi@0.140.0' + - '@oxc-parser/binding-win32-arm64-msvc@0.140.0' + - '@oxc-parser/binding-win32-ia32-msvc@0.140.0' + - '@oxc-parser/binding-win32-x64-msvc@0.140.0' + - '@oxc-project/types@0.140.0' + - oxc-parser@0.140.0 overrides: '@angular/build': workspace:* packageExtensions: