TypeScript reuses SourceFile objects between old and new programs, so untagging the old program also untags shared files in the new program. Re-apply shim tags on the new program to prevent getSemanticDiagnostics() crashes with TS 5.5+.
Transform assumed `.required` functions always take options as the first argument.
This is true for `input` and `model`, but not for `viewChild` and `contentChild`,
which take the same arguments as non-required versions.
Change the code to put options for signal queries in the right position,
causing debugName to be correctly generated for signal queries.
Replaces the `node.keySpan.toString().startsWith('attr.')` string allocation in the `suffixNotSupported` extended template check with an O(1) `node.type === BindingType.Attribute` enum comparison.
The diagnostic message string is also extracted to a module-level constant so it is created once at module load time instead of on every diagnostic emit.
Additionally, this change adds missing test coverage for the `.%` and `.em` suffixes, as well as for a plain `attr.` binding without a style suffix.
Measured with a 100-iteration microbenchmark before and after the change (MacBook Pro 2018, Intel CPU):
```ts
const start = performance.now();
for (let i = 0; i < 100; i++) {
new ExtendedTemplateCheckerImpl(templateTypeChecker, program.getTypeChecker(),
[suffixNotSupportedFactory], {}).getDiagnosticsForComponent(component);
}
console.log((performance.now() - start) / 100, 'ms/iter');
```
Before: `~0.24 ms/iter`
After: `~0.14 ms/iter` (~40% faster)
Extend the interpolated signal extended diagnostic to inspect ternary-bound expressions and report uninvoked signal reads in bound bindings.
```
<div [style.width]="width() ? 1 : width"></div>
```
where the false branch should invoke the signal as `width()`.
Previously, extracting foreign component imports relied on the partial
evaluator and semantic import resolution to locate declaration
references across files. This resolver-based approach is incompatible
with isolated declarations and local compilation, where cross-file type
information and full semantic resolution are unavailable.
Replace the resolver-based foreign import evaluation with a lightweight,
AST-based extraction mechanism (`extractForeignImportsFromAst`). This
allows the compiler to extract foreign component names and raw AST
expressions directly from syntax trees during the analysis phase without
requiring full type checking.
Additionally, simplify the `ForeignComponentMeta` interface by removing
the obsolete reference property and implement granular AST diagnostics
that provide actionable error messages and usage examples when invalid
expressions are passed to `foreignImports`.
the toSignal function received a debugName option in 0812ac3bec,
but was not covered by the signalMetadataTransform which sets the debugName in dev mode
automatically.
Transition parameterless `@content` projection in foreign components
from eager DOM creation to lazy evaluation. Previously, projecting
content into a foreign component eagerly instantiated the embedded view
and created DOM nodes, causing unnecessary resource consumption if the
content was hidden or unmounted.
With this change, runtime content instructions (`ɵɵforeignContent` and
`ɵɵforeignContentFn`) pass lazy producer callbacks directly through the
foreign component's configured `contentAdapter`. View creation and
teardown registration occur lazily when the external framework evaluates
the adapted producer.
`foreignImport` now requires a third argument, `contentAdapter`,
specifying how Angular content producer callbacks are adapted for the
target external framework.
`parseHostBindings` throws plain `Error`s for malformed host bindings
(e.g. a property binding with a non-static value, as can happen while
editing in the language service). These were uncaught during directive
analysis, crashing the compiler and the Angular Language Service.
Wrap the call and surface the error as a `FatalDiagnosticError` so it
becomes a diagnostic and analysis can complete normally.
Fixes#69106
Adds support for `@Input` transform functions in isolated declarations mode (`emitDeclarationOnly: true`), allowing components and directives to specify `transform` functions without triggering fatal compiler errors.
Synthesizes the `ngAcceptInputType_` write type syntactically:
- For referenced functions (`transform: booleanAttribute`), emits `Parameters<typeof booleanAttribute>[0]`, relying on downstream template type checking to resolve the type.
- For inline functions (`transform: (v: string) => boolean`), extracts `parameters[0].type` directly from the local TypeScript AST.
Removes restrictions around using external references and local directives in `hostDirectives` under isolated declarations mode (`emitDeclarationOnly: true`).
By wrapping the host directive reference in a `WrappedNodeExpr`, TypeScript's declaration emitter seamlessly emits `typeof hostReference.node`, preserving existing imports or local identifiers exactly as authored. Also adds support for translating `PropertyAccessExpression` inside `WrappedNodeExpr` into `QualifiedName` for `.d.ts` emission, ensuring namespace imports (`import * as n from './dir'`) are preserved correctly.
Ensures `@content` blocks on foreign components have unique names and do not
conflict with static attributes or input property bindings.
Specifically, this commit introduces two new template diagnostics:
1. `CONFLICTING_CONTENT_DECLARATION` (8028): Raised when multiple `@content`
blocks with the same name are defined under the same foreign component.
2. `CONFLICTING_CONTENT_AND_PROPERTY` (8029): Raised when a `@content` block's
name matches an attribute or input property binding on the parent foreign
component.
Both diagnostics include related information pointing to the location of the
conflicting declaration or property.
Defining a `@content (children)` block explicitly is unnecessary because
children should always be passed implicitly as direct nested content of the
foreign component. Using an explicit block could also lead to conflicts and
silent template rendering issues where implicit content (like whitespace)
accidentally overwrote the explicit block in the compiler's template
representation.
This change introduces a compilation error
(`FOREIGN_COMPONENT_CONTENT_UNNECESSARY_FOR_CHILDREN`) when an explicit
`@content (children)` block is detected, guiding developers to pass children
implicitly instead.
Adds validation to verify that `@content` blocks are only used as direct
children of foreign components.
Specifically:
- Defines a new compile diagnostic code `INVALID_CONTENT_PLACEMENT = 8026`.
- Updates `ForeignComponentFeatureAnalyzer` to traverse content blocks and
report `INVALID_CONTENT_PLACEMENT` diagnostics if they are placed
incorrectly.
- Removes the raw error thrown during ingestion in
`packages/compiler/src/template/pipeline/src/ingest.ts`.
- Adds integration tests in `template_typecheck_spec.ts`.
Refactors the unsupported bindings validation for foreign components from the
template semantics checker phase (during type-checking) to the component
analysis phase. Surfacing this check during component analysis means it will be
correctly reported during local compilation (which skips full template
type-checking).
Specifically:
- Creates a new helper `analyzeForeignComponentFeatures` in
`foreign_component.ts` that traverses template elements and checks for
unsupported outputs, references, and non-property inputs on foreign components.
- Removes the legacy validation from `template_semantics_checker.ts`.
- Invokes the validation during component analysis in
`ComponentDecoratorHandler.analyze()`.
Avoid triggering the `interpolated_signal_not_invoked` diagnostic when
a signal is passed directly as a property binding to a foreign
component. Foreign components may accept signals directly, so they
should not be flagged as uninvoked in this context.
To support testing this, the typecheck testing infrastructure was
updated to allow defining mock foreign components in the test setup.
When a template element matches an imported foreign component, the compiler
omits standard element instructions (`ɵɵelementStart`/`ɵɵelement`) and instead
generates a single `ɵɵforeignComponent` call. The call passes the exact foreign
import wrapper expression defined in `@Component.foreignImports` along with an
aggregated object literal containing all static attributes and property
bindings.
Replace specific file patches applied during google3 sync with generic comment-based mechanisms.
By adding `// g3-only` prefix comments to g3-specific exports and declarations, and appending `// 3p-only` context to `@internal` tags, we enable generic tooling to handle these modifications during the sync process.
Additionally, wrap 3rd-party-only imports and exports (which should be stripped in google3) with `// 3p-only-start` and `// 3p-only-end` comment markers.
This reduces the need for maintaining custom file-specific patches in google3.
Also, add a comprehensive guide to these sync comment markers in `contributing-docs/google-markers.md` to assist external contributors.
Specifically:
- Add `// 3p-only` context to `@internal` in `directives.ts` for `foreignImports` and `deferredImports`.
- Add `// g3-only` commented exports in `core.ts`.
- Add `// g3-only-start`/`// g3-only-end` commented global declaration block in `zone.ts`.
- Wrap 3p-only imports in `fake_navigation.ts` with `// 3p-only-start` and `// 3p-only-end`.
- Wrap 3p-only exports in `compiler-cli/index.ts` with `// 3p-only-start` and `// 3p-only-end`.
- Add `// g3-only` and `// 3p-only` markers to `shared.ts` for `setDisabledStateDefault` configuration.
- Add `// g3-only` and `// 3p-only` markers to `feature_detection.ts` for semver dependency.
- Add `// g3-only` and `// 3p-only` markers to `domino_adapter.ts` for domino import path.
- Add `// 3p-only` marker to `ng_dev_mode` import in `event_dispatcher.ts`.
- Add `// g3-only` and `// 3p-only` markers to `MOUSE_SPECIAL_SUPPORT` in `event_contract_defines.ts`.
- Add `// g3-only` and `// 3p-only` markers to `BrowserModule` imports in `module.ts` (animations) and `browser.ts` (testing).
- Add `// 3p-only` marker to `goog.d.ts` reference tags in `util.ts` (platform-browser), `types.d.ts`, `ng_i18n_closure_mode.ts`, `tokens.ts`, and `global_utils.ts`.
- Wrap `Default` enum value of `ChangeDetectionStrategy` in `constants.ts` with `// 3p-only-start` and `// 3p-only-end`.
- Add `// g3-only` and `// 3p-only` markers to `LEGACY_OPTIONAL_CHAINING_DEFAULT` in `legacy_optional_chaining_default.ts` and `legacyOptionalChaining` in `directive.ts`.
- Add `// g3-only` and `// 3p-only` markers to `DEFAULT_PARAMS_INHERITANCE_STRATEGY` in `router_state.ts`.
- Add `// g3-only` and `// 3p-only` (and block variants) markers to `@mcp-b/webmcp-types` imports in `declare_tool.ts`, `provide_tools.ts`, and `types.ts`.
- Add `contributing-docs/google-markers.md` guide.
TAG=agy
CONV=cd09a4f3-869a-4f41-949b-c91f1b8f1c51
We extract the identifier name from the `foreignImports` expression in
`ComponentDecoratorHandler` and use a `SelectorlessMatcher` to match element
tags against these names. If an element matches both a regular Angular
directive and a foreign component, a conflict error is thrown.
In addition, we implement strict template semantic validation for these matched
foreign components within `TemplateSemanticsChecker`. Elements matched as
foreign components only support static attributes and property bindings. Any
event bindings, template references, or non-property input bindings (e.g.
class, style, or attribute bindings) trigger a semantic error diagnostic.
Finally, we skip standard DOM schema checks for foreign components to prevent spurious
validation errors since foreign components are not defined in standard HTML schemas.
PR Close#68674
- Added the ForeignComponent interface in @angular/core.
- Added Component.foreignImports for importing ForeignComponents (supporting direct references and adapter function wrappers).
- Updated the compiler to handle ForeignComponent in template dependencies.
- Updated ngtsc to extract foreignImports from standalone components.
Currently if a `@for` loop doesn't have a `track` expression we don't produce an AST for it at all which means no type checking and language service support for it.
These changes make it so we produce the AST anyways since it gives the user more tools to resolve the issue (e.g. autocompletion when writing the `track` expression).
The `readFileBuffer` method in `node_js_file_system.ts` was wrapped in
`@ts-ignore` to suppress a TS2322 Buffer/Uint8Array typing error that
was fixed in the TypeScript 5.9.2 upgrade. The minimum supported
TypeScript is now 6.0, so the suppression is dead.
Convert four `.forEach()` calls in `private_export_checker.ts` and
`reference_graph.ts` to `for...of`, matching the iteration style used
elsewhere in the compiler. The TODOs that forced these workarounds are
obsolete.
The getters and setters for jsDocParsingMode in `host.ts` and
`ts_create_program_driver.ts` were suppressed with @ts-ignore to
support TypeScript 5.2, which lacked the property on `ts.CompilerHost`.
The minimum supported TypeScript is now 6.0, and `jsDocParsingMode`
is part of the public TypeScript API, so the suppressions can go.
This allows us to show the API docs when the jsdoc block is at the top of a overloaded function (and not on the implementation signature).
eg: `injectAsync`
Ensure paths are normalized before comparison and key generation in tcb_adapter.ts to avoid failures on Windows.
Ensure a newline before appending imports in TypeCheckFile.render to prevent trailing comments from neutralizing them.
PR Close#68454
This change updates the language service to generate TCBs for templates that would previously
have required inlining. The new strategy is to copy the original source and then do inlining
in the external TCB. This allows language features and type-checking in templates of non-exported
classes (such as test components) or classes with local, non exported dependencies.
PR Close#68454
Langauge service previously never compiled non-exported classes. This avoided issues
where test modules would cause diagnostic noise due to components appearing in
declarations of two modules, for example. This change updates the logic to ensure
non-exported, but standalone classes _are_ still compiled.
fixes#65515
PR Close#68454
Moves the event attribute validation check outside of `ngDevMode` in the `elementAttributeInternal` instruction to ensure that bindings to event attributes like `on*` are always blocked at runtime.
Rather than requiring TS AST in the indexer API, this update makes it generic with adapters to provide necessary information. This allows other analysis pipelines that don't use TS AST to work with the indexer.
This change adds a new that allows environments that cannot support inline TCBs (such as the language service or source-to-source transforms where TS compilation and emit are downstream) to still perform template type checking.
Instead of inlining the TCB into the original source file when non-exported symbols are referenced, we now copy the file content to the .ngtypecheck.ts shim file and generate the external TCB there, if requested by the inlining mode. This preserves the local scope of the original file while keeping the original file unmodified.
all necessary info is already available in the tcb meta objects. environments without full ts program no longer need a reflectionhost for tcb generation