We currently have a handwritten version of the Ivy directive def for NgClass so
we can switch between Ivy and View Engine behavior. This generated code needs to
be kept up-to-date with what the Ivy compiler generates.
PR 30742 recently changed `classMap` such that it now requires allocation of
host binding slots. This means that the `allocHostVars()` function must be
called in the NgClass directive def to match compiler output, but the
handwritten directive def was not updated. This caused a bug where NgClass
was inappropriately overwriting data for other directives because space was
not allocated for its values.
PR Close#31788
This commit is the final patch of the ivy styling algorithm refactor.
This patch swaps functionality from the old styling mechanism to the
new refactored code by changing the instruction code the compiler
generates and by pointing the runtime instruction code to the new
styling algorithm.
PR Close#30742
Fixes all TypeScript failures caused by enabling the `--strict`
flag for test source files. We also want to enable the strict
options for tests as the strictness enforcement improves the
overall codehealth, unveiled common issues and additionally it
allows us to enable `strict` in the `tsconfig.json` that is picked
up by IDE's.
PR Close#30993
In View Engine, developers can pass bootstrap and entry components
as nested arrays. e.g.
```ts
export const MyOtherEntryComponents = [A, B, C]
@NgModule({
entryComponents: [MyComp, MyOtherEntryComponents]
})
```
Currently using nested arrays for these properties causes
unexpected errors to be reported in Ivy since the semantic
NgModule checks aren't properly recursing into the nested
entry/bootstrap components. This issue has been unveiled by
enabling the strict function parameter checks.
PR Close#30993
As part of FW-1265, the `@angular/core` package is made compatible
with the TypeScript `--strict` flag. This already unveiled a few bugs,
so the strictness flag seems to help with increasing the overall code health.
Read more about the strict flag [here](https://www.typescriptlang.org/docs/handbook/compiler-options.html)
PR Close#30993
Fixes Ivy matching directives against attribute bindings (e.g. `[attr.some-directive]="foo"`). Works by excluding attribute bindings from the attributes array during compilation. This has the added benefit of generating less code.
**Note:** My initial approach to implementing this was to have a different marker for attribute bindings so that they can be ignored when matching directives, however as I was implementing it I realized that the attributes in that array were only used for directive matching (as far as I could tell). I decided to drop the attribute bindings completely, because it results in less generated code.
PR Close#31541
Currently we reuse the same instruction both for regular property bindings and property bindings on the `host`. The only difference between the two is that when it's on the host we shouldn't support inputs. We have an optional parameter called `nativeOnly` which is used to differentiate the two, however since `nativeOnly` is preceeded by another optional parameter (`sanitizer`), we have to generate two extra parameters for each host property bindings every time (e.g. `property('someProp', 'someValue', null, true)`).
These changes add a new instruction called `hostProperty` which avoids the need for the two parameters by removing `nativeOnly` which is always set and it allows us to omit `sanitizer` when it isn't being used.
These changes also remove the `nativeOnly` parameter from the `updateSyntheticHostBinding` instruction, because it's only generated for host elements which means that we can assume that its value will always be `true`.
PR Close#31550
Prior to this fix, the logic to set the right placeholder format for ICUs was a bit incorrect: if there was a nested ICU in one of the root ICU cases, that led to a problem where placeholders in subsequent branches used the wrong ({$placeholder}) format instead of {PLACEHOLDER} one. This commit updates the logic to make sure we properly transform all placeholders even if nested ICUs are present.
PR Close#31516
Prior to this commit, it was impossible to override providers defined via ModuleWithProviders using TestBed.overrideProvider API. The problem was caused by the fact that we were not taking into account these providers while calculating accumulated set of provider overrides. This commit updates the logic to extract providers from ModuleWithProviders and calculate the final set of overrides taking them into account.
PR Close#31415
Removes direct calls from one instruction into another, moves the shared logic into a separate function and removes the state getters from the shared function.
This PR resolves FW-1340.
PR Close#31456
Since `goog.getMsg` does not process ICUs (post-processing is required via goog.i18n.MessageFormat, https://google.github.io/closure-library/api/goog.i18n.MessageFormat.html) and placeholder format used for ICUs and regular messages inside `goog.getMsg` are different, the current implementation (that assumed the same placeholder format) needs to be updated. This commit updates placeholder format used inside ICUs from `{$placeholder}` to `{PLACEHOLDER}` to better align with Closure. ICU placeholders (that were left as is prior to this commit) are now replaced with actual values in post-processing step (inside `i18nPostprocess`).
PR Close#31459
Prior to this commit, the `` unicode symbol that represents `&ngsp` in translations was not handled correctly, i.e. was not replaced with a whitespace, thus appearing on a screen. This commit adds post-processing and replaces the mentioned symbol with a whitespace.
PR Close#31479
`i18nStart` was calling `allocExpando` even if there was 0 new variable created.
This created a new expando instruction with the value 0 which was later interpreted as the start of a new expando block instead of just skipping 0 instructions.
FW-1417 #resolve
PR Close#31451
Fixes Ivy's return value for `DebugNode.context` not being consistent for the case where there is both a structural directive and a component on a node. In `ViewEngine` the instance of the component would be returned, whereas in Ivy the context of the directive is returned.
Also adds a couple of extra test cases for how `DebugNode.context` deals with directives.
This PR resolves FW-1343.
PR Close#31442
Adds a new `elementContainer` instruction that can be used to avoid two instruction (`elementContainerStart` and `elementContainerEnd`) for `ng-container` that has text-only content. This is particularly useful when we have `ng-container` inside i18n sections.
This PR resolves FW-1105.
PR Close#31444
Adds the new `classMapInterpolate1` through `classMapInterpolate8` instructions which handle interpolations inside the `class` attribute and moves the interpolation logic internally. This allows us to remove the `interpolationX` instructions in a follow-up PR.
These changes also add an error if an interpolation is encountered inside a `style` tag (e.g. `style="width: {{value}}"`). Up until now this would actually generate valid instructions, because `styleMap` goes through the same code path as `classMap` which does support interpolation. At runtime, however, `styleMap` would set invalid styles that look like `<div style="0:w;1:i;2:d;3:t;4:h;5::;7:1;">`. In `ViewEngine` interpolations inside `style` weren't supported either, however there we'd output invalid styles like `<div style="unsafe">`, even if the content was trusted.
PR Close#31211
Brings in ts_library fixes required to get angular/angular building after 0.32.0:
typescript: exclude typescript lib declarations in node_module_library transitive_declarations
typescript: remove override of @bazel/tsetse (+1 squashed commit)
@npm//node_modules/foobar:foobar.js labels changed to @npm//:node_modules/foobar/foobar.js with fix for bazelbuild/rules_nodejs#802
also updates to rules_rass commit compatible with rules_nodejs 0.32.0
PR Close#31325
Prior to this commit, host element of a view created via TestBed.createComponent was not attached to the component's host, making it problematic to use TestBed.createComponent API in component factories, which might be used for testing purposes only. This behavior is observed in google3 app tests and was supported by VE, so this commit aligns Ivy and VE.
PR Close#31318
When `walkTNodeTree` was refactored, the case of ICU expressions was forgotten (because it was handled in the `else` previously).
This PR fixes that to handle it like `ElementContainer`.
FW-1411 #resolve
PR Close#31313
Currently in Ivy whenever we encounter a new namespace, we set it in the global state so that all subsequent nodes are created under the same namespace. Next time a template is run the namespace will be reset back to HTML.
This breaks down if the last node that was rendered was under the SVG or MathML namespace and we create a component through `ViewContainerRef.create`, because the next template function hasn't run yet and it hasn't had the chance to update the namespace. The result is that the root node of the new component will retain the wrong namespace and may not end up rendering at all (e.g. if we're trying to show a `div` inside the SVG namespace). This issue has the potential to affect a lot of apps, because all components inserted through the router also go through `ViewContainerRef.create`.
PR Close#31232
The Angular runtime frequently calls into user code (for example, when
writing to a property binding). Since user code can throw errors, calls to
it are frequently wrapped in a try-finally block. In Ivy, the following
pattern is common:
```typescript
enterView();
try {
callUserCode();
} finally {
leaveView();
}
```
This has a significant problem, however: `leaveView` has a side effect: it
calls any pending lifecycle hooks that might've been scheduled during the
current round of change detection. Generally it's a bad idea to run
lifecycle hooks after the application has crashed. The application is in an
inconsistent state - directives may not be instantiated fully, queries may
not be resolved, bindings may not have been applied, etc. Invariants that
the app code relies upon may not hold. Further crashes or broken behavior
are likely.
Frequently, lifecycle hooks are used to make assertions about these
invariants. When these assertions fail, they will throw and "swallow" the
original error, making debugging of the problem much more difficult.
This commit modifies `leaveView` to understand whether the application is
currently crashing, via a parameter `safeToRunHooks`. This parameter is set
by modifying the above pattern:
```typescript
enterView();
let safeToRunHooks = false;
try {
callUserCode();
safeToRunHooks = true;
} finally {
leaveView(..., safeToRunHooks);
}
```
If `callUserCode` crashes, then `safeToRunHooks` will never be set to `true`
and `leaveView` won't call any further user code. The original error will
then propagate back up the stack and be reported correctly. A test is added
to verify this behavior.
PR Close#31244
Brings in ts_library fixes required to get angular/angular building after 0.32.0:
typescript: exclude typescript lib declarations in node_module_library transitive_declarations
typescript: remove override of @bazel/tsetse (+1 squashed commit)
@npm//node_modules/foobar:foobar.js labels changed to @npm//:node_modules/foobar/foobar.js with fix for bazelbuild/rules_nodejs#802
also updates to rules_rass commit compatible with rules_nodejs 0.32.0
PR Close#31019
In ViewEngine injecting a Renderer2 returns a renderer that is specific to the particular component, however in Ivy we inject the renderer for the parent view instead. This causes it to set incorrect `ngcontent` attributes when creating elements through the renderer.
The issue comes from the fact that the `Renderer2` is created according to the current `LView`, but because DI happens before we've entered the `LView` of the component that's injecting the renderer, we end up with one that's one level up. We work around the issue by finding the `LView` that corresponds to the `previousOrParentTNode` inside of the parent view and associating the `Renderer2` with it.
This PR resolves FW-1382.
PR Close#31063
Previously, multiple ViewContainerRef instances (obtained by injecting
ViewContainerRef multiple times) each had private state that could be out of
sync with actual LContainer, if views were inserted/removed/queried across
the different instances. In particular each instance had its own array which
tracked ViewRefs inserted via that instance.
This commit moves the ViewRefs array onto the LContainer itself, so that it
can be shared across multiple ViewContainerRef instances. A test is added
that verifies ViewContainerRefs now provide a consistent view of the
container.
FW-1377 #resolve
PR Close#30985
The function `bind` has been internalized wherever it was needed, this PR makes sure that it is no longer publicly exported.
FW-1385 #resolve
PR Close#31131
When using `createEmbeddedView` after the creation of an ICU expression, the nodes for the current selected case were not reprojected (only the anchor comment node was moved to the new location).
Now we reproject correctly all the child nodes of an ICU expression when an anchor comment node is projected.
FW-1372 #resolve
PR Close#30979
- Splits core functionality off into a shared internal function
- ɵɵtextBinding will no longer require an index
- Alters the compiler to stop generating an index argument for the instruction
- Updates tests
- Updates some usage of ɵɵtextBinding in i18n to use the helper function instead
PR Close#30792
Currently in Ivy we throw when attempting to destroy a `ComponentRef` that has been destroyed, however in ViewEngine we didn't which can cause some tests to break. These changes remove the error to match ViewEngine.
These changes resolve FW-1379.
PR Close#31022
To provide some context: The implicit receiver is part of the
parsed Angular template AST. Any property reads in bindings,
interpolations etc. read from a given object (usually the component
instance). In that case there is an _implicit_ receiver which can also
be specified explicitly by just using `this`.
e.g.
```html
<ng-template>{{this.myProperty}}</ng-template>
```
This works as expected in Ivy and View Engine, but breaks in case the
implicit receiver is not used for property reads. For example:
```html
<my-dir [myFn]="greetFn.bind(this)"></my-dir>
```
In that case the `this` will not be properly translated into the generated
template function code because the Ivy compiler currently always treats
the `ctx` variable as the implicit receiver. This is **not correct** and breaks
compatibility with View Engine. Rather we need to ensure that we retrieve
the root context for the standalone implicit receiver similar to how it works
for property reads (as seen in the example above with `this.myProperty`)
Note that this requires some small changes to the `expression_converter`
because we only want to generate the `eenextContent()` instruction if the
implicit receiver is _actually_ used/needed. View Engine determines if that is the case by recursively walking through the converted output AST and
checking for usages of the `o.variable('_co')` variable ([see here][ve_check]). This would work too for Ivy, but involves most likely more code duplication
since templates are isolated in different functions and it another pass
through the output AST for every template expression.
[ve_check]: 0d6c9d36a1/packages/compiler/src/view_compiler/view_compiler.ts (L206-L208)
Resolves FW-1366.
PR Close#30897
In a derived service class with no decorator (and therefore no factory) of
its own, the factory function of the base class will be used instead.
Previously this logic had a bug where the factory function would be called
with no arguments, which would incorrectly create an instance of the base
class.
This commit adds logic to call the base class' factory and pass the type of
the derived class, which will correctly construct an instance of the
derived class using the base class' factory. A test is also added to verify
correctness of this behavior.
PR Close#30855
Factory functions written by the compiler optionally allow an explicit type
to be passed. If called with this type, an instance of the given type will
be created instead of the type for which the factory was generated. This is
used to power inheritance of Angular types, as if the constructor of a class
is inherited from its superclass, then the factory function of the
superclass must be used (it has all the DI info) to construct an instance of
the derived class.
This commit adjusts typings in a few places to allow factory functions to be
called with this extra type parameter.
PR Close#30855
The compiler generates a 'token' field when it emits an ngInjectableDef,
but this field was not required by defineInjectable or the InjectableDef
interface, nor was it added by InjectionToken.
This commit makes 'token' required and adds it where missing.
PR Close#30855
17d87d4e10 has been created before the changes
to the `@ViewChild` and `@ContentChild` decorators. Meaning that it still uses the queries
without the `static` flag. This results in failures in `master` because #30625 has been merged.
PR Close#30967
`TView.firstChild` was defined as the first node with index 0, but when we use runtime i18n then the instruction `i18nStart` can be the one with index 0 and the first node will be index 1 or more.
With this fix we set `TView.firstChild` when we see the first node with index 0 or later if `TView.firstChild` is still null.
FW-1367 #resolve
PR Close#30920