- Adds `property` instruction
- Does _NOT_ add compiler changes to accommodate `property` instruction, that will be a follow up PR.
- Updates `select` instruction to set the selected index in state.
- Adds dev mode assertions around the selected index state.
Related #29527
PR Close#29513
- Adds `property` instruction
- Does _NOT_ add compiler changes to accommodate `property` instruction, that will be a follow up PR.
- Updates `select` instruction to set the selected index in state.
- Adds dev mode assertions around the selected index state.
Related #29527
PR Close#29513
forEach is slower as compared to a regular loop but more importantly
this change removes an anonymous function and thus makes stack traces
shorter and easier to read (important for perf analysis).
PR Close#29543
This commit removes code duplication where we had 2 versions of a
`flatten` utility. Moreover this change results in queries using
a non-recursive version of `flatten` which should result in a better
performance of query refresh operations.
PR Close#29547
The API changes are due to enabling strict checks in TypeScript (via `strict: true`).
The payload size changes in `polyfills.js` are due to more browser APIs being patched in recent versions (e.g. `fetch`, `customElement v1`).
PR Close#28219
In View Engine, we used to generate empty QueryLists for content queries on root
components (though we did not actually support populating these lists). We need
to keep this behavior in Ivy for backwards compatibility. Otherwise, components
that are sometimes used as root will fail if they are relying on content query
results to always be defined.
PR Close#29514
ivy's bindingUpdated instruction is using the assertNotEqual check to make
sure that NO_CHANGE value (of type Object) is not passed as a value to be
dirty-checked. In practice it means that any value passed as a binding
value would be compared to the NO_CHANGE object.
It turns out that the assertNotEqual is using == and given
that binding values are of different type and we always compare it to the
NO_CHANGE object we were doing lots of type coercion. It resulted in calls
to expensive types conversions and calls to Object.toString().
A profiler reported ~15% of the self time spent in the assertNotEqual
but it turns out that removing type coercion speeds up Material Chips with
input scenario much more (~40ms down to ~20ms).
This PR introduces new assert method `assertNotSame` that uses strict equality
check. The new assertion is used in binding instructions to compare to
NO_CHANGE object reference.
PR Close#29470
In ReflectionCapabilities, when checking for own parameters of a type, inherit the types properly for classes that do have a constructor, but the constructor takes no declared parameters and just delegates to super(...arguments). This removes the need to declare trivial constructors in such classes to make them work properly in JIT mode. Without this, DI fails and injectables are undefined.
PR Close#29232
This fix corrects a bug where we were passing a binding _value_
in place of an expected binding index. This reulted in the binding
value being compared to an array length and buggy type coercion.
Fixing this bug speeds up test scenario by ~10-15%.
PR Close#29476
Previously, only directives and services with generic type parameters
would emit `any` as generic type when emitting Ivy metadata into .d.ts
files. Pipes can also have generic type parameters but did not emit
`any` for all type parameters, resulting in the omission of those
parameters which causes compilation errors.
This commit adds support for pipes with generic type arguments and emits
`any` as generic type in the Ivy metadata.
Fixes#29400
PR Close#29403
This patch is the first of a few patches which separates the
styling logic between template bindings (e.g. <div [style])
from host bindings (e.g. @HostBinding('style')). This patch
in particular introduces a series of host-specific styling
instructions and changes the existing set of template styling
instructions not to accept directives. The underyling code (which
communicates with the styling algorithm) still works as it did
before.
This PR also separates the styling instruction code into a separate
file and moves over all other instructions into an dedicated
instructions directory.
PR Close#29292
Prior to this change, we always recompile all Components/Directives/Pipes even if they were AOT-compiled and had no overrides. This is causing problems in case we try to recompile a Component with "templateUrl" or "styleUrls" (which were already resolved in case of AOT) and generally this unnecessary work that TestBed was doing is not required. This commit adds extra logic to check whether a Component/Directive/Pipe already have compiled NG def (like ngComponentDef) and whether there are no overrides present - in this case recompilation is skipped. Recompilation is also skipped in case a Component/Directive has only Provider overrides - in this situation providers resolver function is patched to reflect overrides. Provider overrides are very common in g3, thus this code path ensures no full recompilation.
PR Close#29294
Just updating comments in query-related things to make it easier for the next person that has to grok this for the first time.
Also adds a demo from @mhevery to one of the query specs
Related #29031
PR Close#29342
Just updating comments in query-related things to make it easier for the next person that has to grok this for the first time.
Also adds a demo from @mhevery to one of the query specs
Related #29031
PR Close#29342
Fixes host listeners being inherited twice, if the sub class has its own `propMetadata`. This is related to #29170 which fixed something similar, however all of the test cases there had a super class with some metadata and a sub class that didn't have any. The issue manifested itself in the `MatTreeToggle` which inherits a listener from the `CdkTreeToggle` and adds an extra `Input` of its own, causing the listener to be added twice.
PR Close#29353
- Remove an extra type `ViewOrElement`, which even had the same numeric value as `View`.
- Updates comment to remove part about alleged bit-masking that we could be doing here.
We aren't using this with bitmasks, and if we were, everything would be a `NodeType.Container`,
because it's value was `0`.
- Updates the number values to be simple, human-readable integers, since we're not using these
with any kind of bit-manipulation.
- Add comments about each type.
PR Close#29343
Angular Ivy interprets inline static style/class attribute values as instructions that
are processed whilst an element gets created. Because these inline style values are
referenced by style/class bindings, their inline style values are applied at a later
stage. Despite them being eventually applied, their values should be applied earlier
before any directives are instantiated so that directive code can rely on any inline
style/class changes.
This patch ensures that all static style/class attribute values are applied (rendered)
on the element before directives are instantiated.
Jira Issue: FW-1133
PR Close#29269
Following my previous change for placeholders removal, some special code that was used to find the last created node was no longer needed and had wrong interactions with the *ngFor directive.
Removing it fixed the issue.
PR Close#29308
When injecting with `@Attribute`, namespaced attributes should not match (in order to have feature parity with View Engine).
This PR resolves FW-1137
PR Close#29257
Previously, ngtsc would resolve forward references while evaluating the
bootstrap, declaration, imports, and exports fields of NgModule types.
However, when generating the resulting ngModuleDef, the forward nature of
these references was not taken into consideration, and so the generated JS
code would incorrectly reference types not yet declared.
This commit fixes this issue by introducing function closures in the
NgModuleDef type, similarly to how NgComponentDef uses them for forward
declarations of its directives and pipes arrays. ngtsc will then generate
closures when required, and the runtime will unwrap them if present.
PR Close#29198
Currently with ViewEngine, if someone runs the platform's
`bootstrapModule` method in order to boostrap a module in
JIT mode, external component resources are properly resolved
*automatically*.
Currently with Ivy, the developer would need to manually call
`resolveComponentResources` in order to asynchronously fetch
the determined external component resources. In order to make
this backwards compatible with ViewEngine, and also since
platforms can already specify a `ResourceLoader` compiler
provider, we need to automatically resolve all external
component resources on module bootstrap.
--
Since the `ResourceLoader` is part of the `@angular/compiler`,
because ViewEngine performed the factory creation in the compiler,
we can't access the `ResourceLoader` token from within core.
In order to workaround this without introducing a breaking change,
we just proxy the `ResourceLoader` token to `core` through the
compiler facade. In the future, we should be able to move the
`ResourceLoader` to core when ViewEngine code no longer exists in
the `@angular/compiler`.
PR Close#29083
Dynamic nodes are created at the end of the view stack, but we were removing all the placeholders between `i18nStart` and the last created node index, instead of removing everything between `i18nStart` and `i18nEnd`. This caused errors when dynamic nodes where created in multiple i18n blocks because we would remove all of the dynamic nodes created in the previous i18n blocks.
PR Close#29252
`ng_module` will now include an `src/r3_symbol.d.ts` when compiling the core package under `ngc` togather with `dts bundling`, This is due that `ngcc` relies on this file to be present, but the `r3_symbols` file which is not part of our public api.
With this change, we can now ship an addition dts file which is flattened.
PR Close#28884
The content projection mechanism is static, in that it only looks at the static
template nodes before directives are matched and change detection is run.
When you have a selector-based content projection the selection is based
on nodes that are available in the template.
For example:
```
<ng-content selector="[some-attr]"></ng-content>
```
would match
```
<div some-attr="..."></div>
```
If you have an inline-template in your projected nodes. For example:
```
<div *ngIf="..." some-attr="..."></div>
```
This gets pre-parsed and converted to a canonical form.
For example:
```
<ng-template [ngIf]="...">
<div some-attr=".."></div>
</ng-template>
```
Note that only structural attributes (e.g. `*ngIf`) stay with the `<ng-template>`
node. The other attributes move to the contained element inside the template.
When this happens in ivy, the ng-template content is removed
from the component template function and is compiled into its own
template function. But this means that the information about the
attributes that were on the content are lost and the projection
selection mechanism is unable to match the original
`<div *ngIf="..." some-attr>`.
This commit adds support for this in ivy. Attributes are separated into three
groups (Bindings, Templates and "other"). For inline-templates the Bindings
and "other" types are hoisted back from the contained node to the `template()`
instruction, so that they can be used in content projection matching.
PR Close#29041
This commit adds a new `AttributeMarker` type that will be used, in a
future commit, to mark attributes as coming from an inline-template
expansion, rather than the element that is being contained in the template.
PR Close#29041
Angular supports having a component extend off of a parent component.
When this happens, all annotation-level data is inherited including styles
and classes. Up until now, Ivy only paid attention to static styling
values on the parent component and not the child component. This patch
ensures that both the parent's component and child component's styling
data is merged and rendered accordingly.
Jira Issue: FW-1081
PR Close#29015
Currently we only reset the `Attached` flag of a view if it is detached through its parent, however this means that if a root view is destroyed, its flag will never be reset. This manifested itself in one of the Material tests where we were destroying the root view.
This PR resolves FW-1130.
PR Close#29064
Currently if a user accidentally calls ViewContainerRef.insert() with
a view that has already been attached, we do not clean up the references
properly, so we create a view tree with a cycle. This causes an infinite
loop when the view is destroyed.
This PR ensures that we fall back to ViewContainerRef.move() behavior
if we try to insert a view that is already attached. This fixes the
cycle and honors the user intention.
PR Close#29047
This change helps highlight certain misoptimizations with Closure
compiler. It is also stylistically preferable to consistently use index
access on index sig types.
Roughly, when one sees '.foo' they know it is always checked for typos
in the prop name by the type system (unless 'any'), while "['foo']" is
always not.
Once all angular repos are conforming this will become a tsetse.info
check, enforced by bazel.
PR Close#28937
This commit removes code duplication around projectables nodes insertion.
It also simplfy the overall logic by using recursive function calls instead
of hand-unrolled stack (we can always optimise this part if needed).
PR Close#29008
In the past, the sanitizer would remove unsafe elements, but still
traverse and sanitize (and potentially preserve) their content. This was
problematic in the case of `<style></style>` tags, whose content would
be converted to HTML text nodes.
In order to fix this, the sanitizer's behavior was changed in #25879 to
ignore the content of _all_ unsafe elements. While this fixed the
problem with `<style></style>` tags, it unnecessarily removed the
contents for _any_ unsafe element. This was an unneeded breaking change.
This commit partially restores the old sanitizer behavior (namely
traversing content of unsafe elements), but introduces a list of
elements whose content should not be traversed if the elements
themselves are considered unsafe. Currently, this list contains `style`,
`script` and `template`.
Related to #25879 and #26007.
Fixes#28427
PR Close#28804
Currently if an embedded view contains projected nodes, its `rootNodes` array will include `null` instead of the root nodes inside the projection slot. This manifested itself in one of the Material unit tests where we stamp out a template and then move its `rootNodes` into the overlay container.
This PR is related to FW-1087.
PR Close#28951
For efficiency reasons we often put several different data types (`RNode`, `LView`, `LContainer`,
`StylingContext`) in same location in `LView`. This is because we don't want to pre-allocate
space
for it because the storage is sparse. This file contains utilities for dealing with such data
types.
How do we know what is stored at a given location in `LView`.
- `Array.isArray(value) === false` => `RNode` (The normal storage value)
- `Array.isArray(value) === true` => than the `value[0]` represents the wrapped value.
- `typeof value[TYPE] === 'object'` => `LView`
- This happens when we have a component at a given location
- `typeof value[TYPE] === 'number'` => `StylingContext`
- This happens when we have style/class binding at a given location.
- `typeof value[TYPE] === true` => `LContainer`
- This happens when we have `LContainer` binding at a given location.
NOTE: it is assumed that `Array.isArray` and `typeof` operations are very efficient.
PR Close#28947
`LView`, `LContainer`, `StylingContext` are all arrays which wrap either
an `HTMLElement`, `LView`, `LContainer`, `StylingContext`. It is often
necessary to retrieve the correct type of element from the location
which means that we often have to wrap the arrays. Logically it makes
more sense if the thing which we are wrapping is at `0` location. Also
it may be more performant since data is more local which may result in
more L2 cache hits in CPU.
PR Close#28947
This change contains conditionally attached classes which provide human readable (debug) level
information for `LView`, `LContainer` and other internal data structures. These data structures
are stored internally as array which makes it very difficult during debugging to reason about the
current state of the system.
Patching the array with extra property does change the array's hidden class' but it does not
change the cost of access, therefore this patching should not have significant if any impact in
`ngDevMode` mode. (see: https://jsperf.com/array-vs-monkey-patch-array)
So instead of seeing:
```
Array(30) [Object, 659, null, …]
```
```
LViewDebug {
views: [...],
flags: {attached: true, ...}
nodes: [
{html: '<div id="123">', ..., nodes: [
{html: '<span>', ..., nodes: null}
]}
]
}
```
PR Close#28945
If an interface is not exported publicly from its package, then the doc-gen
does not see it, and so cannot include it in the generated documentation.
This was the case for a number of `...Decorator` interfaces, such as
`PipeDecorator` and `InputDecorator.
This commit adds these interfaces to the public export to fix this problem.
PR Close#28836
Google3 detected circular references here, so splitting up this rather hodge-podge list of functions into slightly better organizational units.
PR Close#28382
- TView no longer stores childIndex
- LView now as CHILD_HEAD and CHILD_TAIL
TView used to store the head of the list, therefor all LViews had to have the same head, which is incorrect.
PR Close#28382
- Removes CONTAINER_INDEX
- LView[PARENT] now contains LContainer when necessary
- Removes now unused arguments to methods after refactor
PR Close#28382
During build time we remap particular property bindings, because their names don't match their attribute equivalents (e.g. the property for the `for` attribute is called `htmlFor`). This breaks down if the particular element has an input that has the same name, because the property gets mapped to something invalid.
The following changes address the issue by mapping the name during runtime, because that's when directives are resolved and we know all of the inputs that are associated with a particular element.
PR Close#28765
Fixes the `ngOnDestroy` hook on a component or directive being called twice, if the type is also registered as a provider.
This PR resolves FW-1010.
PR Close#28470
Prior to this fix, both the `NgStyle` and `NgClass` directives made use
of `Renderer2` and this dependency raised issues for future versions of
Angular that cannot inject it. This patch ensures that there are two
versions of both directives: one for the VE and another for Ivy.
Jira Issue: FW-882
PR Close#28711
I18n can change the order of the nodes, or insert new dynamic nodes. When that happens it can break the existing links (`TNode.next`) or even create loops:
```
div1 → div2 → div3 → div4 → div5
```
Can become:
```
div1 → div4 → div2 → div3 div5
🡑 │
└─────────────┘
```
This PR fixes this issue by recreating the broken links between those nodes.
PR Close#28827
This commit adds support for the `static: true` flag in `ContentChild`
queries. Prior to this commit, all `ContentChild` queries were resolved
after change detection ran. This is a problem for backwards
compatibility because View Engine also supported "static" queries which
would resolve before change detection.
Now if users add a `static: true` option, the query will be resolved in
creation mode (before change detection runs). For example:
```ts
@ContentChild(TemplateRef, {static: true}) template !: TemplateRef;
```
This feature will come in handy for components that need
to create components dynamically.
PR Close#28811
This commit adds support for the `static: true` flag in
`ViewChild` queries. Prior to this commit, all `ViewChild`
queries were resolved after change detection ran. This is
a problem for backwards compatibility because View Engine
also supported "static" queries which would resolve before
change detection.
Now if users add a `static: true` option, the query will be
resolved in creation mode (before change detection runs).
For example:
```ts
@ViewChild(TemplateRef, {static: true}) template !: TemplateRef;
```
This feature will come in handy for components that need
to create components dynamically.
PR Close#28811
Prior to this commit, the timing of `ViewChild`/`ContentChild` query
resolution depended on the results of each query. If any results
for a particular query were nested inside embedded views (e.g.
*ngIfs), that query would be resolved after change detection ran.
Otherwise, the query would be resolved as soon as nodes were created.
This inconsistency in resolution timing had the potential to cause
confusion because query results would sometimes be available in
ngOnInit, but sometimes wouldn't be available until ngAfterContentInit
or ngAfterViewInit. Code depending on a query result could suddenly
stop working as soon as an *ngIf or an *ngFor was added to the template.
With this commit, users can dictate when they want a particular
`ViewChild` or `ContentChild` query to be resolved with the `static`
flag. For example, one can mark a particular query as `static: false`
to ensure change detection always runs before its results are set:
```ts
@ContentChild('foo', {static: false}) foo !: ElementRef;
```
This means that even if there isn't a query result wrapped in an
*ngIf or an *ngFor now, adding one to the template later won't change
the timing of the query resolution and potentially break your component.
Similarly, if you know that your query needs to be resolved earlier
(e.g. you need results in an ngOnInit hook), you can mark it as
`static: true`.
```ts
@ViewChild(TemplateRef, {static: true}) foo !: TemplateRef;
```
Note: this means that your component will not support *ngIf results.
If you do not supply a `static` option when creating your `ViewChild` or
`ContentChild` query, the default query resolution timing will kick in.
Note: This new option only applies to `ViewChild` and `ContentChild`
queries, not `ViewChildren` or `ContentChildren` queries, as those types
already resolve after CD runs.
PR Close#28810
Accounts for schemas in when validating properties in Ivy.
This PR resolves FW-819.
A couple of notes:
* I had to rework the test slightly, in order to have it fail when we expect it to. The one in master is passing since Ivy's validation runs during the update phase, rather than creation.
* I had to deviate from the design in FW-819 and not add an `enableSchema` instruction, because the schema is part of the `NgModule` scope, however the scope is only assigned to a component once all of the module's declarations have been resolved and some of them can be async. Instead, I opted to have the `schemas` on the component definition.
PR Close#28637
Previously `DebugNode.classes` and `DebugNode.styles` mistakenly used an
object that is only *sometimes* a `StylingContext`. Also fixes a mistake
in `debug_node_spec.ts` where a test component was not declared in the
testing module.
There is still a bug here where `DebugNode` is not exposing *static*
values. This will need to be fixed in a follow up.
PR Close#28709
Prior to this fix if a root component was instantiated it create host
bindings, but never render them once update mode ran unless one or more
slot-allocated bindings were issued. Since styling in Ivy does not make
use of LView slots, the host bindings function never ran on the root
component.
This fix ensures that the `hostBindings` function does run for a root
component and also renders the schedlued styling instructions when
executed.
Jira Issue: FW-1062
PR Close#28664
In the past, @Injectable had no side effects and existing Angular code is
therefore littered with @Injectable usage on classes which are not intended
to be injected.
A common example is:
@Injectable()
class Foo {
constructor(private notInjectable: string) {}
}
and somewhere else:
providers: [{provide: Foo, useFactory: ...})
Here, there is no need for Foo to be injectable - indeed, it's impossible
for the DI system to create an instance of it, as it has a non-injectable
constructor. The provider configures a factory for the DI system to be
able to create instances of Foo.
Adding @Injectable in Ivy signifies that the class's own constructor, and
not a provider, determines how the class will be created.
This commit adds logic to compile classes which are marked with @Injectable
but are otherwise not injectable, and create an ngInjectableDef field with
a factory function that throws an error. This way, existing code in the wild
continues to compile, but if someone attempts to use the injectable it will
fail with a useful error message.
In the case where strictInjectionParameters is set to true, a compile-time
error is thrown instead of the runtime error, as ngtsc has enough
information to determine when injection couldn't possibly be valid.
PR Close#28523
While marking a given views tree as dirty we should go all the way to the
root of the views tree and cross boundaries of dynamically inserted views.
In other words the markForCheck functionality should consider parents of
dynamically inserted views.
PR Close#28687
Prior to this change we used current injector implementation for module injector, which was causing problems and produces circular dependencies in case the same token is referenced (with @SkipSelf flag) in the `deps` array. The origin of the problem was that once `directiveInject` implementation becomes active, it was used for module injector as well, thus searching deps in Component/Directive DI scope. This fix sets `injectInjectorOnly` implementation for module injector to resolve the problem.
PR Close#28667
Prior to this update we had separate contentQueries and contentQueriesRefresh functions to handle creation and update phases. This approach was inconsistent with View Queries, Host Bindings and Template functions that we generate for Component/Directive defs. Now the mentioned 2 functions are combines into one (contentQueries), creation and update logic is separated with RenderFlags (similar to what we have in other generated functions).
PR Close#28503
For TypeScript compilation units that have the "strictFunctionTypes"
option enabled, an error would be produced for Ivy's definition fields
in declaration files in the case of inheritance across directives or
pipes.
This change loosens the definition types to allow for subtypes of the
defined type where necessary.
A test package that has the "strict" option enabled verifies that we
won't regress in environments where strict type checking is enabled.
Fixes#28079
PR Close#28634