Commit Graph

898 Commits

Author SHA1 Message Date
Suraj Yadav 2c141c04cb refactor(compiler-cli): simplify Angular decorator stripping
Removes redundant decorator-stripping branches and consolidates
the transformation flow to reduce complexity and improve readability.
2026-04-22 11:07:35 -07:00
Kristiyan Kostadinov 8f3d0b9d97 feat(core): introduce @Service decorator
These changes introduce the new `@Service` decorator which is a more ergonomic alternative to `@Injectable`. The reason we're adding a new decorator is that `@Injectable` has been around since the beginning of Angular and it has a lot of baggage that adds unnecessary overhead for users that generally want to define a singleton service, available in their entire app. The key differences between `@Service` and `@Injectable` are:
1. `@Service` is `providedIn: 'root'` by default. You can opt into providing the service yourself by setting `autoProvided: false` on it.
2. `@Service` doesn't allow constructor-based injection, only the `inject` function.
3. `@Service` doesn't support the complex type signature of `@Injectable` (`useClass`, `useValue` etc.). Instead it supports a single `factory` function.

Example:

```ts
import {Service} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {AuthService} from './auth';

@Service()
export class PostService {
  private readonly httpClient = inject(HttpClient);
  private readonly authService = inject(AuthService);

  getUserPosts() {
    return this.httpClient.get('/api/posts/' + this.authService.userId);
  }
}
```
2026-04-22 11:01:01 -07:00
Kristiyan Kostadinov e5f96c2d88 fix(compiler-cli): animation events not type checked properly when bound through HostListener decorator
Fixes that we weren't inferring the type of `animate.` event correctly, if they're bound through a `@HostListener` decorator.
2026-04-13 11:05:16 +03:00
Matthieu Riegler 47fcbc4704 feat(compiler): allow safe navigation to correctly narrow down nullables
The commit updates the TCB for safe navigation expressions to allow for correct narrowing of nullables.

This will trigger the `nullishCoalescingNotNullable` and `optionalChainNotNullable` diagnostics on exisiting projects.
You might want to disable those 2 diagnotiscs in your `tsconfig` temporarily if you want to update your project without having to fix all the issues at once.

Narrowing can be disabled altogether with `strictSafeNavigationTyes: false`.

fixes #37619

BREAKING CHANGE: This change will trigger the `nullishCoalescingNotNullable` and `optionalChainNotNullable` diagnostics on exisiting projects.
You might want to disable those 2 diagnotiscs in your `tsconfig` temporarily.
2026-04-09 18:26:08 +03:00
Kristiyan Kostadinov ab061a7610 fix(compiler-cli): error for type parameter declarations
Fixes an error that was heppning when a generic param has type parameters of its own. There were a few different issues going on:
1. In #67707 I had changed a bit how we pass the `genericContextBehavior` which ended up ignoring the `useContextGenericType` option from the environment.
2. All directives depend on themselves, but we were overridding the `genericContextBehavior` for the directive being processed.
3. The type translator wasn't handling type parameter declarations. Technically we shouldn't be able to hit a code path that has a type parameter, however it's also easy enough to handle so we might as well.

Relates to #67704.
2026-04-07 09:29:29 -07:00
Kristiyan Kostadinov fd95735594 refactor(compiler-cli): fix failing tests
Fixes some tests that started failing after recent changes.
2026-04-06 12:33:05 -07:00
Matthieu Riegler f3c471e0d5 refactor(compiler): remove fullTemplateTypeCheck compiler option.
The option was deprecated back in v13. Users should use `strictTemplates: true`.
2026-04-06 11:55:09 -07:00
Kristiyan Kostadinov 57432f1b6a refactor(compiler-cli): merge duplicate directive matches and report conflicts
Implements the logic at the compiler level that will de-duplicate host directives and merge them together. It will also report if a conflict is detected during merging.
2026-04-03 09:44:39 -07:00
Andrei Chmelev fcd0bb0db8 fix(compiler-cli): prevent recursive scope checks for invalid NgModule imports
Avoid recursive local scope lookups when invalid NgModule imports create import cycles.
2026-03-27 16:10:01 +01:00
Matthieu Riegler eae8f7e30b feat(core): Set default Component changeDetection strategy to OnPush
The default change detection strategy is now OnPush.

BREAKING CHANGE: Component with undefined `changeDetection` property are now `OnPush` by default. Specify `changeDetection: ChangeDetectionStrategy.Eager` to keep the previous behavior.
2026-03-24 16:25:02 -07:00
Matthieu Riegler f46e8bd440 refactor(compiler): remove fullTemplateTypeCheck compiler option.
The option was deprecated back in v13. Users should use `strictTemplates: true`.
2026-03-23 11:33:15 -07:00
Kristiyan Kostadinov 63ac1bd2fd refactor(compiler-cli): decouple host element creation logic from TypeScript
Reworks the logic for constructing a `HostElement` node so that we can reuse it without depending on TypeScript APIs.
2026-03-23 11:16:39 -07:00
SkyZeroZx ca67828ee2 refactor(compiler-cli): introduce NG8023 compile-time diagnostic for duplicate selectors
Add NG8023 extended diagnostic to report duplicate component selectors
during compilation.

This replaces the former NG0300 runtime error, ensuring the failure
occurs at build time instead of runtime.

Closes  angular#48377

BREAKING CHANGE: Elements with multiple matching selectors will now throw at compile time.
2026-03-19 16:12:02 -07:00
Alex Rickabaugh 41b1410cb8 feat(forms): support binding number|null to <input type="text">
`<input type="number">` often does not provide the desired user experience when editing numbers in
a form. MDN even [describes](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/number#using_number_inputs)
how text inputs should be used in many cases instead, via `<input type="text" inputmode="numeric">`
or similar configurations. Previously, this did not work with Signal Forms without a custom input
component/directive.

This PR builds support for binding `number|null` models directly to `<input type="text">` native
controls via `[formField]`. When a model has a number or `null` value, signal forms will preserve
that status when the user makes edits/changes. Empty string values are converted to `null`, other
values are parsed as numbers, and a parse error is raised when a non-numeric value is entered.

Note that it's up to the UI developer to configure additional UI affordances such as setting an
appropriate `inputmode`, rejecting non-numeric keypresses, etc.

Fixes #66903
Fixes #66157
2026-03-19 15:26:34 -07:00
Kristiyan Kostadinov c457b9b5b4 refactor(compiler): add ts-ignore comment on factory functions
Adds a `ts-ignore` comment to thew instantiation expressions in factories, because in some compilation modes we can't guarantee that they'll compile.
2026-03-18 14:05:18 -06:00
Kristiyan Kostadinov 9769560da7 fix(compiler-cli): generic types not filled out correctly in type check block
Fixes a regression caused by the recent TCB changes where we moved the type parameter processing earlier in the pipeline and stopped properly accounting for the `TcbGenericContextBehavior`.

Fixes #67704.
2026-03-17 13:21:27 -06:00
Kristiyan Kostadinov 2bd708fb6b fix(compiler-cli): escape template literal in TCB
Fixes a regression introduced by #67381 where we weren't escaping backticks in template literals.

Fixes #67675.
2026-03-16 10:47:25 -06:00
Kristiyan Kostadinov cd656701b0 refactor(compiler): update tests after codegen changes
Updates the compliance tests to account for the recent changes.
2026-03-16 09:58:18 -06:00
Kristiyan Kostadinov 4636218395 refactor(compiler-cli): avoid typescript errors from debugName transform
In some cases the `debugName` transform generates a spread into the signal function parameters. This can cause compiler errors, because the functions don't have rest parameters.

These changes work around it by adding a `@ts-ignore` above it.
2026-03-16 09:58:18 -06:00
Doug Parker dc4cf649b6 fix(compiler-cli): ignore generated ngDevMode signal branch for code coverage
The Angular compiler unconditionally adds a debug name transform for signals
which generates a conditional on `ngDevMode` (e.g., `ngDevMode ? { debugName: "xyz" } : []`).
During testing, `ngDevMode` is true, so the true branch executes but the
false branch is never executed. Consequently, coverage tools report the
false branch as an untested line/branch, preventing 100% test coverage.

This commit adds a synthetic `/* istanbul ignore next */` comment to the
generated false branch so that Istanbul ignores it. We only include the
istanbul comment (instead of additionally including c8) to focus on the
established standard for Angular CLI/Karma coverage while maintaining
compatibility with modern Vitest setups, since @vitest/coverage-v8 now
natively respects the fallback istanbul comment.

Fixes #64583
2026-03-04 14:42:53 -08:00
Matthieu Riegler 03db2aefaa fix(compiler): throw on duplicate input/outputs
inputs & outputs cannot be binded to 2 different directives/components properties

Eg
```
data = model();
dataChange = output(); // throws because model already emits on the `dataChange` output

userSomething = input({alias 'user'});
user = input(); // throws because userSomething already binds to the `user` input
````

fixes #65844

BREAKING CHANGE: The compiler will throw when there a when inputs, outputs or model are binding to the same input/outputs.
2026-02-26 13:47:37 -08:00
SkyZeroZx f90e5565e0 fix(compiler-cli): detect uninvoked functions in defer trigger expressions
Wrap `@defer` trigger expressions (`when`, `prefetch when`, `hydrate when`)
in a conditional context within the TCB to enable TypeScript's TS2774
diagnostic for detecting functions used without invocation.

Previously, signals and functions passed to `when` triggers without
parentheses would silently evaluate to truthy, causing unexpected behavior.
Now the compiler reports an error when a function is used as a condition
without being called.
2026-02-20 08:57:03 -08:00
Kristiyan Kostadinov 81cabc1477 feat(core): add support for TypeScript 6
Updates the project to support TypeScript 6 and accounts for some of the breakages.
2026-02-17 08:40:38 -08:00
Leon Senft 3606902b33 refactor(forms): relax [formField] input type from FieldTree to Field
`FieldTree` was an unnecessarily specific type for the `[formField]`
input. It forced the directive to care about what _kind_ of `FieldTree`
was bound–specifically whether it was Reactive Forms compatible or not.
This made it difficult to author forms system-agnostic components with
passthrough `[formField]` inputs.
2026-02-11 11:45:20 -08:00
Angular Robot 11767cabe4 build: update Jasmine to 6.0.0
Jasmine enables `forbidDuplicateNames: true` by default. So we also need to desambiguate duplicate spec names.
2026-02-09 12:15:57 -08:00
Matthieu Riegler 43d61ecbb2 docs(docs-infra): extract call signature return type.
fixes #66799
2026-02-03 12:31:36 -08:00
Matthieu Riegler 72dfb4d92a docs(docs-infra): wrap getTextOfJSDocComment
This commits adds a wrapper around `ts.getTextOfJSDocComment` because of bugs that won't be fixed by the TS team (see microsoft/TypeScript#63027)
2026-01-29 13:16:00 -08:00
Kristiyan Kostadinov d9c980a958 build: initial test of TypeScript 6
Resolves some initial test failures after updating to TypeScript 6.
2026-01-15 13:41:01 -08:00
Matthieu Riegler 72534e2a34 feat(compiler): Add support for the instanceof binary operator
Because why not ?

fixes #59975
2026-01-13 08:33:12 -08:00
Shuaib Hasan Akib 1b4dcc01ff docs: replace old https://angular.io/license with https://angular.dev/license 2026-01-12 13:41:30 -08:00
Miles Malerba 5671f2cc07 fix(forms): Rename signal form [field] to [formField]
This completes the rename started in #66136. `[field]` is too generic of
a selector for the forms system to own, and likely to cause naming
collisions with existing components. Therefore it is being renamed to
`[formField]`
2026-01-09 14:33:09 -08:00
Kristiyan Kostadinov 87a422358b refactor(compiler-cli): template type checking support for arrow functions
Updates the template type checker to support arrow functions. The main challenge was getting the current infrastructure not to rewrite references to arrow function parameters.
2026-01-09 10:35:37 -08:00
Kristiyan Kostadinov a0dfa5fa86 feat(core): support rest arguments in function calls
Updates the template syntax to support rest arguments in function calls. This can be handy for functions with a variable number of arguments.
2026-01-07 12:37:52 -05:00
Kristiyan Kostadinov 6e18fa8bc9 feat(core): support spread elements in array literals
Expands the template syntax to support spread elements inside arrays. This can be handy for some bindings.
2026-01-07 12:37:52 -05:00
Kristiyan Kostadinov e407280ab5 feat(core): support spread expressions in object literals
Adds support for spread expressions inside of object literals. This can be handy when constructing maps for `class` bindings.
2026-01-07 12:37:52 -05:00
Matthieu Riegler 640693da8e feat(compiler): Add support for multiple swich cases matching
consecutive `@case` blocks are now supported:

```ts
@switch (case) {
  @case (0)
  @case (1) {
    case 0 or 1
  }
  @case (2) {
    case 2
  }
  @default {
    default
  }
}
```

fixes #14659
2026-01-07 09:23:50 -05:00
Alan Agius 91dc91bae4 fix(core): sanitize sensitive attributes on SVG script elements
This commit updates the DOM security schema and sanitization logic to properly recognize and sanitize `href` and `xlink:href` attributes on SVG `<script>` elements.
2026-01-06 15:49:52 -05:00
SkyZeroZx ed7bfb3c88 feat(docs-infra): Extracts aliases from doc entries
Implements a mechanism to extract alias names from a directive's selector.
2026-01-05 12:33:14 -05:00
Kristiyan Kostadinov 3a26244d61 fix(compiler-cli): fix up spelling of diagnostic
Fixes the spelling for the `component is missing a template` diagnostic and expands it a bit.
2026-01-02 08:27:27 +01:00
JoostK 106ba63650 fix(compiler-cli): ensure component import diagnostics are reported within the imports expression
PR #60455 improved error reporting for `@Component.imports` by scoping the diagnostic to an individual
element within the `imports` array, but this may introduce hard to track diagnostics when it ends
up being reported (far) away from the component itself.

This can be even more problematic when the diagnostic would end up being reported in a declaration file,
as happened in issue #65686; the declaration files of an imported library contained syntax that the
static interpreter did not support, hence the `@Component.imports` was rejected with a diagnostic reported
in the library's declaration file. This diagnostic isn't guaranteed to be reported (e.g. the CLI only
gathers Angular-specific diagnostics for Angular-compiled files, which excludes declaration files).

This commit changes the diagnostic location to ensure it is being reported within the `@Component.imports`
expression, in most cases retaining the desirable effect of #60455 while avoiding out-of-band diagnostics.
2026-01-02 08:21:08 +01:00
Alan Agius d4111eebc6 refactor(compiler): remove unnecessary sanitization for safe attributes
Remove sanitization for attributes that cannot execute code (e.g. `javascript: URIs`).
2025-12-15 14:13:38 -08:00
Andrew Kushnir 8243bb3064 Revert "refactor(compiler): remove unnecessary sanitization for safe attributes"
This reverts commit 128aef0ede.
2025-12-12 12:59:47 -08:00
Alan Agius 128aef0ede refactor(compiler): remove unnecessary sanitization for safe attributes
Remove sanitization for attributes that cannot execute code (e.g. `javascript: URIs`).
2025-12-12 08:05:58 -08:00
Kristiyan Kostadinov 8a3f3a91cf fix(compiler-cli): expand type for native controls with a dynamic type
We recently allowed users to have a dynamic input `type` with signal forms, but the logic that infers the value type falls back to `string` even though in theory it can be any of the other types.

These changes expand the inferred type to `string | number | boolean | Date | null` if we detect a dynamic `type` binding.
2025-12-09 13:01:30 -08:00
Matthieu Riegler 8199945637 refactor(core): add dedicated deprecated signatures for providedIn: any / NgModule.
Those were deprecated by #47616 back in v15.

fixes #65923
2025-12-09 10:38:09 -08:00
Kristiyan Kostadinov ae1c0dc490 perf(compiler): chain query creation instructions
We always emit the query creation instructions in a group which makes them good candidates for chaining.
2025-12-09 09:24:36 -08:00
Kristiyan Kostadinov 6773d3b97d fix(compiler-cli): check that field radio button values are strings
Adds some type checking code which verifies that the bound `value` on a `Field` radio button is a string.

Fixes #65726.
2025-12-03 12:18:57 +01:00
Kristiyan Kostadinov e30e61b789 fix(compiler-cli): avoid allocating an object for signals in production mode
Currently when the signal debug name transform sees something like `const foo = signal(0);`, it transforms the signal into `signal(0, {...(ngDevMode ? { debugName: 'foo' } : {})})`. After minification this becomes `signal(0, {})` which will allocate memory for the empty object literal.

These changes rework the logic to produce `signal(0, ...(ngDevMode ? [{ debugName: 'foo' }] : []))` which will be fully tree shaken away to `signal(0)`.
2025-12-02 15:06:51 +01:00
Alan Agius 1c6b0704fb fix(compiler): prevent XSS via SVG animation attributeName and MathML/SVG URLs
This commit implements a security fix to prevent XSS vulnerabilities where SVG animation elements (`<animate>`, `<set>`, etc.) could be used to modify the `href` or `xlink:href` attributes of other elements to `javascript:` URLs.
2025-12-01 10:26:56 +01:00
AntonChesnokov 5bfa027d41 fix(compiler-cli): escape angular control flow in jsdoc
Escape @-prefixed template control flow constructs during doc extraction so JSDoc parsing keeps description text intact. Add regression coverage for @for snippets.
2025-11-25 11:33:25 -05:00