`LFrame` stores information specifice to the current `LView` As the code
enters and leaves `LView`s we use `enterView()` and `leaveView()`
respectively to build a a stack of `LFrame`s. This allows us to easily
restore the previous `LView` instruction state.
PR Close#33178
In the post-$localize world the current locale value is defined by setting
`$localize.locale` which is then read at runtime by Angular in the provider
for the `LOCALE_ID` token and also passed to the ivy machinery via`setLocaleId()`.
The $localize compile-time inlining tooling can replace occurrences of
`$localize.locale` with a string literal, similar to how translations
are inlined.
// FW-1639
See https://github.com/angular/angular-cli/issues/15896
PR Close#33314
Decrease `MIN_SAMPLE_DURATION` to make it more likely that we cane fit into single time slice.
Increase `MIN_SAMPLE_COUNT_NO_IMPROVEMENT` to make it more likely to find the best
PR Close#33341
change the existing implementation from using
```
string.split(/\s+/);
```
to a char scan which performers the same thing.
The reason why `split(/\s+/)` is slow is that:
- `/\s+/` allocates new `RegExp` every time this code executes.
- `RegExp` scans are a lot more expensive because they are more powerful.
PR Close#33326
Until now, the template type checker has not checked any of the event
bindings that could be present on an element, for example
```
<my-cmp
(changed)="handleChange($event)"
(click)="handleClick($event)"></my-cmp>
```
has two event bindings: the `change` event corresponding with an
`@Output()` on the `my-cmp` component and the `click` DOM event.
This commit adds functionality to the template type checker in order to
type check both kind of event bindings. This means that the correctness
of the bindings expressions, as well as the type of the `$event`
variable will now be taken into account during template type checking.
Resolves FW-1598
PR Close#33125
Prior to this fix if a map-based class or style binding wrote
its values onto an elemenent, the internal styling context would
not register the binding if the initial value as a `NO_CHANGE`
value. This situation occurs if a directive takes control of the
`class` or `style` input values and then returns a `NO_CHANGE` value
if the initial value is empty.
This patch ensures that all bindings are always registered with the
`TStylingContext` data-structure even if their initial value is
an instance of `NO_CHANGE`.
PR Close#33236
Prior to this fix, all style/class bindings (e.g. `[style]` and
`[class.foo]`) would quietly update a binding value if and when the
current binding value changes during checkNoChanges.
With this patch, all styling instructions will properly check to see
if the value has changed during the second pass of detectChanges()
if checkNoChanges is active.
PR Close#33103
Prior to this commit, metadata defined on ICU container element was not inherited by the ICU if the whole message is a single ICU (for example: `<ng-container i18n="meaning|description@@id">{count, select, ...}</ng-container>). This commit updates the logic to use parent container i18n meta information for the cases when a message consists of a single ICU.
Fixes#33171
PR Close#33191
Turns out that writing to global state is more expensive than writing to
a property on an object.
Slower:
````
let count = 0;
function increment() {
count++;
}
```
Faster:
````
const state = {
count: 0
};
function increment() {
state.count++;
}
```
This change moves all of the instruction state into a single state object.
`noop_change_detection` benchmark
Pre refactoring: 16.7 us
Post refactoring: 14.523 us (-13.3%)
PR Close#33093
Prior to this commit, all `className` inputs were not set because the runtime code assumed that the `classMap` instruction is only generated for `[class]` bindings. However the `[className]` binding also produces the same `classMap`, thus the code needs to distinguish between `class` and `className`. This commit adds extra logic to select the right input name and also throws an error in case `[class]` and `[className]` bindings are used on the same element simultaneously.
PR Close#33188
This patch introduces the `printTable()` and `printSources()`
methods to `DebugStylingContext` which can be used via the
`window.ng.getDebugNode` helpers when debugging an application.
PR Close#33179
Injectable defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.
This commit adds the prefix and shortens the name from
ngInjectableDef to "prov" (for "provider", since injector defs
are known as "inj"). This is because property names cannot
be minified by Uglify without turning on property mangling
(which most apps have turned off) and are thus size-sensitive.
PR Close#33151
Injector defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.
This commit adds the prefix and shortens the name from
ngInjectorDef to inj. This is because property names
cannot be minified by Uglify without turning on property
mangling (which most apps have turned off) and are thus
size-sensitive.
PR Close#33151
Prior to this commit, Ivy runtime asserted that a given element is an instance of a DOM node. These asserts may not be correct in case custom renderer is used, which operates objects with a shape different than DOM nodes. This commit updates the code to avoid the mentioned checks in case procedural renderer is used.
PR Close#33156
Prior to this patch, if a map-class binding is applied directly then
that value will be incorrectly provided a sanitizer even if there is no
sanitization present for an element.
PR Close#33154
Module defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.
This commit adds the prefix and shortens the name from
ngModuleDef to mod. This is because property names
cannot be minified by Uglify without turning on property
mangling (which most apps have turned off) and are thus
size-sensitive.
PR Close#33142
Pipe defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.
This commit adds the prefix and shortens the name from
ngPipeDef to pipe. This is because property names
cannot be minified by Uglify without turning on property
mangling (which most apps have turned off) and are thus
size-sensitive.
PR Close#33142
Factory defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.
This commit adds the prefix and shortens the name from
ngFactoryDef to fac. This is because property names
cannot be minified by Uglify without turning on property
mangling (which most apps have turned off) and are thus
size-sensitive.
Note that the other "defs" (ngPipeDef, etc) will be
prefixed and shortened in follow-up PRs, in an attempt to
limit how large and conflict-y this change is.
PR Close#33116
Directive defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.
This commit adds the prefix and shortens the name from
ngDirectiveDef to dir. This is because property names
cannot be minified by Uglify without turning on property
mangling (which most apps have turned off) and are thus
size-sensitive.
Note that the other "defs" (ngFactoryDef, etc) will be
prefixed and shortened in follow-up PRs, in an attempt to
limit how large and conflict-y this change is.
PR Close#33110
Component defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.
This commit adds the prefix and shortens the name from
`ngComponentDef` to `cmp`. This is because property names
cannot be minified by Uglify without turning on property
mangling (which most apps have turned off) and are thus
size-sensitive.
Note that the other "defs" (ngDirectiveDef, etc) will be
prefixed and shortened in follow-up PRs, in an attempt to
limit how large and conflict-y this change is.
PR Close#33088
This patch enables a styling debug instance (which is apart of the
`debugNode.styles` or `debugNode.classes` data structures) to expose
its context value so that it can be easily debugged.
PR Close#32856
Prior to this fix, whenever a style or class binding is present, the
binding application process would require an instance of `TStylingContext`
to be built regardless of whether or not any binding resolution is needed
(just so that it knows whether or not there are any collisions).
This check is, however, unnecessary because if (and only if) there
are directives present on the element then are collisions possible.
This patch removes the need for style/class bindings to register
themselves on to a `TStylingContext` if there are no directives and
present on an element. This means that all map and prop-based
style/class bindings are applied as soon as bindings are updated on
an element.
PR Close#32919
A PR that updates one of the benchmarks and another one that changes the signature for `elementStart` got in around the same time which is causing a compilation error. These changes fix the error.
PR Close#33067
Currently Ivy stores the element attributes into an array above the component def and passes it into the relevant instructions, however the problem is that upon minification the array will get a unique name which won't compress very well. These changes move the attributes array into the component def and pass in the index into the instructions instead.
Before:
```
const _c0 = ['foo', 'bar'];
SomeComp.ngComponentDef = defineComponent({
template: function() {
element(0, 'div', _c0);
}
});
```
After:
```
SomeComp.ngComponentDef = defineComponent({
consts: [['foo', 'bar']],
template: function() {
element(0, 'div', 0);
}
});
```
A couple of cases that this PR doesn't handle:
* Template references are still in a separate array.
* i18n attributes are still in a separate array.
PR Close#32798
Accessing a string's character at index allocates a new, single character string.
A better (faster) check is to use `charCodeAt` that doesn't trigger allocation.
This simple change speeds up the element_text_create benchmark by ~7%.
PR Close#32997
Removes the `Renderer` and related symbols which have been deprecated since version 4.
BREAKING CHANGES:
* `Renderer` has been removed. Use `Renderer2` instead.
* `RenderComponentType` has been removed. Use `RendererType2` instead.
* `RootRenderer` has been removed. Use `RendererFactory2` instead.
PR Close#33019
In View Engine, animation metadata could occur in nested arrays which
would be flattened in the compiler. When compiling a component for Ivy
however, the compiler no longer statically evaluates a component's
animation metadata and is therefore unable to flatten it statically.
This resulted in an issue to find animations at runtime, as the metadata
was incorrectly registered with the animation engine.
Although it would be possible to statically evaluate the animation
metadata in ngtsc, doing so would prevent reusable animations exported
from libraries from being usable as ngtsc's partial evaluator is unable
to read values inside libraries. This is unlike ngc's usage of static
symbols represented in a library's `.metadata.json`, which explains how
the View Engine compiler is able to flatten the animation metadata
statically.
As an alternative solution, the metadata flattening is now done in the
runtime during the registration of the animation metadata with the
animation engine.
Fixes#32794
PR Close#32818
Prior to this change, ng-reflect properties were not created in case an attribute was marked as translatable (for ex. `i18n-title`). This commit adds the logic to generate ng-reflect for such cases.
PR Close#32989
In an attempt to be compatible with previous translation files
the Angular compiler was generating instructions that always
included the message id. This was because it was not possible
to accurately re-generate the id from the calls to `$localize()` alone.
In line with https://hackmd.io/EQF4_-atSXK4XWg8eAha2g this
commit changes the compiler so that it only renders ids if they are
"custom" ones provided by the template author.
NOTE:
When translating messages generated by the Angular compiler
from i18n tags in templates, the `$localize.translate()` function
will compute message ids, if no custom id is provided, using a
common digest function that only relies upon the information
available in the `$localize()` calls.
This computed message id will not be the same as the message
ids stored in legacy translation files. Such files will need to be
migrated to use the new common digest function.
This only affects developers who have been trialling `$localize`, have
been calling `loadTranslations()`, and are not exclusively using custom
ids in their templates.
PR Close#32867
With #31953 we moved the factories for components, directives and pipes into a new field called `ngFactoryDef`, however I decided not to do it for injectables, because they needed some extra logic. These changes set up the `ngFactoryDef` for injectables as well.
For reference, the extra logic mentioned above is that for injectables we have two code paths:
1. For injectables that don't configure how they should be instantiated, we create a `factory` that proxies to `ngFactoryDef`:
```
// Source
@Injectable()
class Service {}
// Output
class Service {
static ngInjectableDef = defineInjectable({
factory: () => Service.ngFactoryFn(),
});
static ngFactoryFn: (t) => new (t || Service)();
}
```
2. For injectables that do configure how they're created, we keep the `ngFactoryDef` and generate the factory based on the metadata:
```
// Source
@Injectable({
useValue: DEFAULT_IMPL,
})
class Service {}
// Output
export class Service {
static ngInjectableDef = defineInjectable({
factory: () => DEFAULT_IMPL,
});
static ngFactoryFn: (t) => new (t || Service)();
}
```
PR Close#32433
There are a couple scenarios that are problematic and need special
handling:
1. A user has a custom implementation of lazy-loaded modules, sets some
provider overrides, then compiles the module so it can be loaded. In a
follow-up test, the user sets different overrides for the module and
then compiles. This is problematic because we need to be sure the module
registered in the first test is not used, so we need to clear it out of
the modules list in `ng_module_factory_registration`.
2. A user has a similar lazy-loaded module factory implementation but
relies on the module being registered automatically. This can happen,
for example, as a side effect of importing the ngfactory file.
PR Close#32944
Child component refresh must happen before executing the ViewQueryFn because
child components could insert a template from the host that contains the result
of the ViewQuery function (see related test added in this PR).
PR Close#32922
This patch changes the Ivy `DebugElement` code to always read style and
class values directly from the native element instead of reading them
through the styling contexts. The reason for this change is because Ivy
does not make use of a debug renderer and will therefore not have access
to any classes/styles applied directly through the renderer (unless it
reads the values directly from the element).
PR Close#32842
Prior to this commit, the `ngProjectAs` attribute was only included with a special flag and in a parsed format. As a result, projected node was missing `ngProjectAs` attribute as well as other attributes added after `ngProjectAs` one. This is problematic since app code might rely on the presence of `ngProjectAs` attribute (for example in CSS). This commit fixes the problem by including `ngProjectAs` into attributes array as a regular attribute and also makes sure that the parsed version of the `ngProjectAs` attribute with a special marker is added after regular attributes (thus we set them correctly at runtime). This change also aligns View Engine and Ivy behavior.
PR Close#32784
This release includes a ts_config runfiles fix so also cleaning up the one line work-around from #31943.
This also updates to upstream rules_webtesting browser repositories load("@io_bazel_rules_webtesting//web/versioned:browsers-0.3.2.bzl", "browser_repositories") to fix a breaking change in the chromedriver distro. This bumps up the version of chromium to the version here: https://github.com/bazelbuild/rules_webtesting/blob/master/web/versioned/browsers-0.3.2.bzl
PR Close#32151
This patch fixes a bug where the map-based cursor moves too far and
skips intermediate values when the correct combination of single-prop
bindings and map-based bindings are used together.
PR Close#32774
This patch introduces the `printTable()` and `printSources()`
methods to `DebugStylingContext` which can be used via the
`window.ng.getDebugNode` helpers when debugging an application.
PR Close#32753
This patch enables a styling debug instance (which is apart of the
`debugNode.styles` or `debugNode.classes` data structures) to expose
its context value so that it can be easily debugged.
PR Close#32753
Prior to this patch the `window.ng.getDebugNode` method would fail to
return the debug information for an element that is a host element to
a component.
PR Close#32780
Prior to this patch if any backwards-compatible Angular code was using
Ivy then the built-in `window.ng` debug utilies would not be exposed.
PR Close#32725
Now that the `$localize` translations are `MessageId` based the
compiler must render `MessageId`s in its generated `$localize` code.
This is because the `MessageId` used by the compiler is computed
from information that does not get passed through to the `$localize`
tagged string.
For example, the generated code for the following template
```html
<div id="static" i18n-title="m|d" title="introduction"></div>
```
will contain these localization statements
```ts
if (ngI18nClosureMode) {
/**
* @desc d
* @meaning m
*/
const MSG_EXTERNAL_8809028065680254561$$APP_SPEC_TS_1 = goog.getMsg("introduction");
I18N_1 = MSG_EXTERNAL_8809028065680254561$$APP_SPEC_TS_1;
}
else {
I18N_1 = $localize \`:m|d@@8809028065680254561:introduction\`;
}
```
Since `$localize` is not able to accurately regenerate the source-message
(and so the `MessageId`) from the generated code, it must rely upon the
`MessageId` being provided explicitly in the generated code.
The compiler now prepends all localized messages with a "metadata block"
containing the id (and the meaning and description if defined).
Note that this metadata block will also allow translation file extraction
from the compiled code - rather than relying on the legacy ViewEngine
extraction code. (This will be implemented post-v9).
Although these metadata blocks add to the initial code size, compile-time
inlining will completely remove these strings and so will not impact on
production bundle size.
PR Close#32594
Prior to this patch, each time `advance()` would run (or when a
templateFn or hostBindings code exits) then the core change detection
code would check to see whether the styling data needs to be reset. This
patch removes that functionality and places everything inside of the
scheduled styling exit function. This means that each time one or more
styling bindings run (even if the value hasn't changed) then an exit
function will be scheduled and that will do all the cleanup.
PR Close#32591
This patch is a final major refactor in styling Angular.
This PR includes three main fixes:
All temporary state taht is persisted between template style/class application
and style/class application in host bindings is now removed.
Removes the styling() and stylingApply() instructions.
Introduces a "direct apply" mode that is used apply prop-based
style/class in the event that there are no map-based bindings as
well as property collisions.
PR Close#32259
PR Close#32591
If an <ng-template> contains a structural directive (for example *ngIf), Ngtsc generates extra template function with 1 template instruction call. When <ng-template> tag also contains i18n attribute on it, we generate i18nStart and i18nEnd instructions around it, which is unnecessary and breaking runtime. This commit adds a logic to make sure we do not generate i18n instructions in case only `template` is present.
PR Close#32623
This is a refactoring that moves the source code around to provide a better
platform for adding the compile-time inlining.
1. Move the global side-effect import from the primary entry-point to a
secondary entry-point @angular/localize/init.
This has two benefits: first it allows the top level entry-point to
contain tree-shakable shareable code; second it gives the side-effect
import more of an "action" oriented name, which indicates that importing
it does something tangible
2. Move all the source code into the top src folder, and import the localize
related functions into the localize/init/index.ts entry-point.
This allows the different parts of the package to share code without
a proliferation of secondary entry-points (i.e. localize/utils).
3. Avoid publicly exporting any utilities at this time - the only public
API at this point are the global `$localize` function and the two runtime
helpers `loadTranslations()` and `clearTranslations()`.
This does not mean that we will not expose additional helpers for 3rd
party tooling in the future, but it avoid us preemptively exposing
something that we might want to change in the near future.
Notes:
It is not possible to have the `$localize` code in the same Bazel package
as the rest of the code. If we did this, then the bundled `@angular/localize/init`
entry-point code contains all of the helper code, even though most of it is not used.
Equally it is not possible to have the `$localize` types (i.e. `LocalizeFn`
and `TranslateFn`) defined in the `@angular/localize/init` entry-point because
these types are needed for the runtime code, which is inside the primary
entry-point. Importing them from `@angular/localize/init` would run the
side-effect.
The solution is to have a Bazel sub-package at `//packages/localize/src/localize`
which contains these types and the `$localize` function implementation.
The primary `//packages/localize` entry-point imports the types without
any side-effect.
The secondary `//packages/localize/init` entry-point imports the `$localize`
function and attaches it to the global scope as a side-effect, without
bringing with it all the other utility functions.
BREAKING CHANGES:
The entry-points have changed:
* To attach the `$localize` function to the global scope import from
`@angular/localize/init`. Previously it was `@angular/localize`.
* To access the `loadTranslations()` and `clearTranslations()` functions,
import from `@angular/localize`. Previously it was `@angular/localize/run_time`.
PR Close#32488
This perf-focused refactoring moves the TNode's input / output initialization
logic to the first template pass - close to the place where directives are
matched and resolved.
This code change makes it possible to update-mode checks for both property
bindings and listeners registration.
PR Close#32608
Before this refactoring we had 2 utility functions to check if a given
TNode has matching directives. This PR leaves just one such function
(one that does less memory read).
PR Close#32495
While determining a property name to bind to we were checking a mapping object
resulting in the megamorphic read. Replacing such read with a series of if checks
speeds up rproprty update benchmark ~30% (~1400ms down to ~1000ms).
PR Close#32574
Ensures that the "core_all:size_test" target runs with "--define=compile=aot".
This is necessary because we don't run this test on CI currently, but if we run
it manually, we need to ensure that it runs with Ivy for proper size comparisons.
PR Close#32613
This patch is a final major refactor in styling Angular.
This PR includes three main fixes:
All temporary state taht is persisted between template style/class application
and style/class application in host bindings is now removed.
Removes the styling() and stylingApply() instructions.
Introduces a "direct apply" mode that is used apply prop-based
style/class in the event that there are no map-based bindings as
well as property collisions.
PR Close#32259
PR Close#32596
This patch is a final major refactor in styling Angular.
This PR includes three main fixes:
All temporary state taht is persisted between template style/class application
and style/class application in host bindings is now removed.
Removes the styling() and stylingApply() instructions.
Introduces a "direct apply" mode that is used apply prop-based
style/class in the event that there are no map-based bindings as
well as property collisions.
PR Close#32259
Prior to this commit, a directive with a selector `selector=".Titledir"` would not match an element like `div class="titleDir"` in Ivy whereas it would in VE. The same issue was present for `selector="[title=Titledir]` and `title="titleDir"`. This fixes the Ivy behavior by changing the matching algorithm to use lowercased values.
Note that some `render3` tests needed to be changed to reflect that the compiler generates lowercase selectors. These tests are in the process to be migrated to `acceptance` to use `TestBed` in another PR anyway.
PR Close#32548
Adds two acceptance tests to show a current difference in behavior between Ivy and VE.
A directive with a selector `.Titledir` matches an element with `class="titleDir"` in VE but not in Ivy.
Same thing for an attribute value.
PR Close#32548
Prior to this commit, the `previousOrParentTNode` was set to null after performing all operations within `refreshView` function. It's causing problems in more complex scenarios, for example when change detection is triggered during DI (see test added as a part of this commit). As a result, global state might be corrupted. This commit captures current value of `previousOrParentTNode` and restores it after `refreshView` call.
PR Close#32521
Replaces the `select` instruction with a new one called `advance`. Instead of the jumping to a specific index, the new instruction goes forward X amount of elements. The advantage of doing this is that it should generate code the compresses better.
PR Close#32516
The `goog.getMsg()` function requires placeholder names to be camelCased.
This is not the case for `$localize`. Here placeholder names need
match what is serialized to translation files.
Specifically such placeholder names keep their casing but have all characters
that are not in `a-z`, `A-Z`, `0-9` and `_` converted to `_`.
PR Close#32509
Logs a warning instead of throwing when running into a binding to an unknown property in JIT mode. Since we aren't using a schema for the runtime validation anymore, this allows us to support browsers where properties are unsupported.
PR Close#32463
Prior to this commit, listeners order was not preserved in case we coalesce them to avoid triggering unnecessary change detection cycles. For performance reasons we were attaching listeners to existing events at head (always using first listener as an anchor), to avoid going through the list, thus breaking the order in which listeners are registered. In some scenarios this order might be important (for example with `ngModelChange` and `input` listeners), so this commit updates the logic to put new listeners at the end of the list. In order to avoid performance implications, we keep a pointer to the last listener in the list, so adding a new listener takes constant amount of time.
PR Close#32484
Fixes an issue where Ivy incorrectly inserts items in the beginning of an `ngFor`, if the `ngFor` is set on an `ng-container`. The issue comes from the fact that we choose the `ng-container` comment node as the anchor point before which to insert the content, however the node might be after any of the nodes inside the container. These changes switch to picking out the first node inside of the container instead.
PR Close#32324
Prior to this commit, complex expressions (that require additional statements to be generated) were handled incorrectly in case they were used in attributes annotated with i18n flags. The problem was caused by the fact that extra statements were not appended to the temporary vars block, so they were missing in generated code. This commit updated the logic to use the `convertPropertyBinding`, which contains the necessary code to append extra statements. The `convertExpressionBinding` function was removed as it duplicates the `convertPropertyBinding` one (for the most part) and is no longer used.
PR Close#32309
Prior to this fix if a `NO_CHANGE` value was assigned to a binding, or
an interpolation value rendererd a `NO_CHANGE` value, then the presence
of that value would cause the internal counter index values to not
increment properly. This patch ensures that this doesn't happen and
that the counter/bitmask values update accordingly.
PR Close#32143
PR #32154 introduced `platform` and `any` for `providedIn` and the doc has a minor typo.
Also a test name was not changed accordingly to the refactoring done.
PR Close#32410
Since property binding metadata storage is guarded with the ngDevMode now
and several instructions were merged together, we can simplify the way we
store and read property binding metadata.
PR Close#32457
This commit changes the Angular compiler (ivy-only) to generate `$localize`
tagged strings for component templates that use `i18n` attributes.
BREAKING CHANGE
Since `$localize` is a global function, it must be included in any applications
that use i18n. This is achieved by importing the `@angular/localize` package
into an appropriate bundle, where it will be executed before the renderer
needs to call `$localize`. For CLI based projects, this is best done in
the `polyfills.ts` file.
```ts
import '@angular/localize';
```
For non-CLI applications this could be added as a script to the index.html
file or another suitable script file.
PR Close#31609
DebugElement.query also searches elements that may have been created
outside of Angular (ex: with `document.appendChild`). The current
behavior attempts to get the LContext of these nodes but throws an error
because the LContext does not exist.
PR Close#32361
This patch introduces a new micro benchmark that performance tests
against map-based style and class bindings in Ivy running together
on the same element.
PR Close#32401
This patch introduces a new micro benchmark that performance tests
against style and class bindings in Ivy running together on the same
element.
PR Close#32401
Extend the vocabulary of the `providedIn` to also include `'platform'` and `'any'`` scope.
```
@Injectable({
providedId: 'platform', // tree shakable injector for platform injector
})
class MyService {...}
```
PR Close#32154
TestBed.get is not type safe, fixing it would be a massive breaking
change. The Angular team has proposed replacing it with TestBed.inject
and deprecate TestBed.get.
Deprecation from TestBed.get will come as a separate commit.
Issue #26491Fixes#29905
BREAKING CHANGE: Injector.get now accepts abstract classes to return
type-safe values. Previous implementation returned `any` through the
deprecated implementation.
PR Close#32200
Reworks the compiler to output the factories for directives, components and pipes under a new static field called `ngFactoryFn`, instead of the usual `factory` property in their respective defs. This should eventually allow us to inject any kind of decorated class (e.g. a pipe).
**Note:** these changes are the first part of the refactor and they don't include injectables. I decided to leave injectables for a follow-up PR, because there's some more cases we need to handle when it comes to their factories. Furthermore, directives, components and pipes make up most of the compiler output tests that need to be refactored and it'll make follow-up PRs easier to review if the tests are cleaned up now.
This is part of the larger refactor for FW-1468.
PR Close#31953
Binding metadata are only needed:
- for property bindings;
- when TestBed tests are being run.
This commit guards binding metadata storage with the ngDevMode flag
which saves ~6% of a proerty binding processing time in the production
mode (and reduces bundle size).
PR Close#32317
After a series of recent refactorings `enterView` and `leaveView` became
identical. This PR merges both into one concept of view selectio (similar
to a node selection). This reduces number of concepts and code size.
PR Close#32263
Prior to this change, the `BINDING_INDEX` of a given lView was reset after processing a template. However change detection can be triggered as a result of View queries processing, thus leading to subsequent `refreshView` call (and executing a template), which in turn operates with the binding index that is not reset after the previous `refreshView` call. This commit updates the logic to reset binding index before we execute a template, so binding index is correct for instructions inside template function.
PR Close#32201
This commit drops our custom, change-detection specific, equality comparison util
in favour of the standard Object.is which has desired semantics.
There are multiple advantages of this approach:
- less code to maintain on our end;
- avoid NaN checks if both values are equal;
- re-write NaN checks so we don't trigger V8 deoptimizations.
PR Close#32212
Angular hooks come after 2 flavours:
- init hooks (OnInit, AfterContentInit, AfterViewInit);
- check hooks (OnChanges, DoChanges, AfterContentChecked, AfterViewChecked).
We need to do more processing for init hooks to ensure that those hooks
are run once and only once for a given directive (even in case of errors).
As soon as all init hooks execute to completion we are only left with the
checks to execute.
It turns out that keeping track of the remaining init hooks to execute is
rather expensive (multiple LView flags reads, writes and checks). But we can
observe that non of this tracking is needed as soon as all init hooks are
completed.
This PR takes advantage of the above observations and splits hooks processing
functions into:
- init-specific (slower but less common);
- check-specific (faster and more common).
NOTE: there is code duplication in this PR and it is left like this intentinally:
hand-inlining this perf-critical code makes the view refresh process substentially
faster.
PR Close#32131
In VE the `Sanitizer` is always available in `BrowserModule` because the VE retrieves it using injection.
In Ivy the injection is optional and we have instructions instead of component definition arrays. The implication of this is that in Ivy the instructions can pull in the sanitizer only when they are working with a property which is known to be unsafe. Because the Injection is optional this works even if no Sanitizer is present. So in Ivy we first use the sanitizer which is pulled in by the instruction, unless one is available through the `Injector` then we use that one instead.
This PR does few things:
1) It makes `Sanitizer` optional in Ivy.
2) It makes `DomSanitizer` tree shakable.
3) It aligns the semantics of Ivy `Sanitizer` with that of the Ivy sanitization rules.
4) It refactors `DomSanitizer` to use same functions as Ivy sanitization for consistency.
PR Close#31934
For some reason (on OS/X) this transitive dependency is not being passed
through to the final TS builds that rely on this rule, so the build fails
with a missing file error:
```
The specified path does not exist:
'/.../sandbox/darwin-sandbox/451/execroot/angular/packages/tsconfig-build.json'.
```
PR Close#31943
Similar to interpolation, we do not want to completely remove whitespace
nodes that are siblings of an expansion.
For example, the following template
```html
<div>
<strong>items left<strong> {count, plural, =1 {item} other {items}}
</div>
```
was being collapsed to
```html
<div><strong>items left<strong>{count, plural, =1 {item} other {items}}</div>
```
which results in the text looking like
```
items left4
```
instead it should be collapsed to
```html
<div><strong>items left<strong> {count, plural, =1 {item} other {items}}</div>
```
which results in the text looking like
```
items left 4
```
---
**Analysis of the code and manual testing has shown that this does not cause
the generated ids to change, so there is no breaking change here.**
PR Close#31962
Fixes Ivy's directive matching not capturing attribute selectors when there is one class binding, one style binding and a regular binding that precede the attribute that would match the directive. The issue appears to come from the fact that we weren't skipping over style bindings correctly which was throwing the loop off not to go into `bindingsMode` and to skip some of the bindings when matching.
PR Close#31942
Fixes Ivy's `DebugElement.triggerEventHandler` to picking up events that have been registered through a `Renderer2`, unlike ViewEngine.
This PR resolves FW-1480.
PR Close#31845
Prior to this commit, the `schemas` configuration was applied to top-level view only. That leads to problems when using unknown props with elements inside nested views (for example generated as a result of *ngIf). This commit passes `schemas` information down to nested views to make sure that all the checks are consistent.
PR Close#31913
Currently the `DebugElement.listeners` array are retained after the node is destroyed. This means that they'll continue to fire through `triggerEventHandler` and can cause memory leaks. This has already been fixed in Ivy, but these changes fix it in ViewEngine for consistency.
PR Close#31820
nodejs rules 0.34.0 now includes protractor_web_test_suite rule (via new @bazel/protractor rule) so we switch to that location for that rule in this PR so that /packages/bazel/src/protractor can be removed in a future PR
this PR also brings in node toolchain support which was released in nodejs rules 0.33.0. this is a prerequisite for RBE for mac & windows users
bazel schematics also updated with the same. @bazel/bazel 0.28.1 npm package includes transitive dep on hide-bazel-files so we're able to remove an explicit dep on that as well.
PR Close#31824
In `BrowserModule` the value of `LOCALE_ID` is defined in the `APPLICATION_MODULE_PROVIDERS` after `APP_INITIALIZER` has run.
This PR ensures that `LOCALE_ID` is also set for ivy at the same moment which allows the application to fetch the locale from a backend (for example).
Fixes#31465
FW-1436 #resolve
PR Close#31566
Fixes Ivy throwing an error when something is passed in as a `forwardRef` into `@Injectable`'s `useClass` option. The error was being thrown, because we were trying to get the provider factory off of the wrapper function, rather than the value itself.
This PR resolves FW-1335.
PR Close#30532
Currently we always generate the `read` parameter for the view and content query instructions, however since most of the time the `read` parameter won't be set, we'll end up generating `null` which adds 5 bytes for each query when minified. These changes make it so that the `read` parameter only gets generated if it has a value.
PR Close#31667
This commit fixes a bug where we assumed all dynamically created
components would have tag-name selectors, so we passed through the
"tag name" to the renderer as the first index of the selector. For
components with attribute selectors, the tag name would be "", so
the renderer would try to create an element with tag name "" and
throw. Now we default to a "div" element the same way that View
Engine did.
Closes#31785
PR Close#31812
The way the `ComponentFactory.create` is set up at the moment is that if a `rootSelectorOrNode` is passed in, the root context will be injected instead of creating dedicated one for the component. As far as I can tell, there doesn't seem to be a reason to do this and nothing seems to break because of it. These changes switch to always create the root context.
PR Close#31661
In ViewEngine nodes that were inserted through `Renderer2` would also be picked up by `DebugNode.query` and `DebugNode.queryAll`. This worked because everything in ViewEngine went through `Renderer2` and `DebugRenderer2` in dev mode which was able to keep track of the child nodes as they're being inserted. This no longer works in Ivy, because we don't use `DebugRenderer2` and debug nodes work a little differently. These changes work around the issue by walking the DOM as the logical tree is being walked and looking for matches. Note that this is __not__ optimal, because we're walking similar trees multiple times. ViewEngine could do it more efficiently, because all the insertions go through Renderer2, however that's not the case in Ivy. This approach is being used because:
1. Matching the ViewEngine behavior would mean potentially introducing a depedency from `Renderer2` to Ivy which could bring Ivy code into ViewEngine.
2. We would have to make `Renderer3` "know" about debug nodes.
3. It allows us to capture nodes that were inserted directly via the DOM.
PR Close#31716
When injecting a `ChangeDetectorRef` into a pipe, the expected result is that the ref will be tied to the component in which the pipe is being used. This works for most cases, however when a pipe is used inside a property binding of a component (see test case as an example), the current `TNode` is pointing to component's host so we end up injecting the inner component's view. These changes fix the issue by only looking up the component view of the `TNode` if the `TNode` is a parent.
This PR resolves FW-1419.
PR Close#31438
In the previous patch () all the existing styling code was turned
off in favor of using the new refactored ivy styling code. This
patch is a follow up patch to that and removes all old, unused
styling code from the render3 directory.
PR Close#31193
This commit fixes a bug where ICU expressions inserted into ngTemplateOutlets
that are inside ngFor blocks would throw an error. We were assuming in view
insertion code that text nodes would always exist by the time a view\`s
creation block had executed. This is not true for text nodes created dynamically
by ICUs because this happens in the update block (in `i18nApply`).
This change ensures such dynamically created nodes are skipped when encountered
too early (as they will be attached later by i18n code anyway).
PR Close#31789
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