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
Based on the results of the `directive_instantiate` executing host
bindings logic (in creation mode) account for ~23% of time spent in
the directive instantiation, even if a directive doesn't have host
bindings! This is clearly wastful hence a new flag.
PR Close#33102
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
We used to have a custom version of the NodeInjectorFactory check that was
supposed to be faster to the direct usage of the `instanceof` operator. This
might have been the case in the past but the recent benchmark shows that using
`instanceof` speeds up the `directive_instantiate` by ~10%
(from time getting from ~340ms down to ~305ms).
PR Close#33082
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
Currently the `ngForOf` input accepts `null` or `undefined` as valid
values. Although when using strict template input type checking
(which will be supported by `ngtsc`), passing `null` or `undefined`
with strict null checks enabled causes a type check failure because
the type for the `ngForOf` input becomes too strict if strict null checks
are enabled. The type of the input needs to be expanded to also accept
`null` or `undefined` to behave consistently regardless of the
`strictNullChecks` flag.
This is necessary because whenever strict input type checking is enabled
by default, most of the Angular projects that use `*ngFor` with the async pipe
will either need to disable template type checking or strict null checks
because the `async` pipe returns `null` if the observable hasn't been
emitted yet.
See for example how this affects the `angular/components` repository and
how much bloat the workaround involves: https://github.com/angular/components/pull/16373/files#r296942696.
PR Close#31371
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
Prior to this commit, the `ng` was exposed in global namespace, which turned out to be problematic when minifying code with Closure, since it sometimes clobber our `ng` global. This commit aligns Ivy debugging tools behavior with existing logic in "platform-browser" package (packages/platform-browser/src/dom/util.ts#L31) by avoiding `ng` in global namespace when Closure Compiler is used.
PR Close#33010
Re-enables the dynamic queries migration, now that we have all of the necessary framework changes in place.
Also moves the logic that identifies static queries out of the compiler and into the static queries migration, because that's the only place left that's using it.
PR Close#32992
Followup to #32720 that removed the logic that statically determines whether a query is dynamic.
This updates the docs to reflect that, and mentions that the flag now defaults to false.
PR Close#32993
Current we need to create and override certain compiler host methods in every schematic because schematics use a virtual fs. We this change we extract this logic to a common util.
PR Close#32827
The creation of StaticReflector in createMetadataResolver() is a very expensive operation because it involves numerous module resolutions.
To make matter worse, since the API of the Reflector does not provide the ability to invalidate its internal caches, it has to be destroyed and recreated on *every* program change.
This has a HUGE impact on performance.
This PR fixes this problem by carefully invalidating all StaticSymbols in a file that has changed, thereby reducing the overhead of recomputation on program change.
PR Close#32543
This is a re-submit of #32686.
Switches back to having the static flag be optional on ViewChild and ContentChild queries, in preparation for changing its default value.
PR Close#32986
This PR updates Angular to compile with TypeScript 3.6 while retaining
compatibility with TS3.5. We achieve this by inserting several `as any`
casts for compatiblity around `ts.CompilerHost` APIs.
PR Close#32908
Currently the undecorated-classes-with-di migration leverages NGC in order
to work with metadata resolution. Since NGC by default tries to resolve referenced
resources on initialization of the underlying TS program, it can result in unexpected
migration failures due to missing resource files.
This is especially an issue since the CLI wraps the `AngularCompilerProgram` with
special logic (i.e. to support SCSS preprocessing etc.). We don't have all of this since
we instantiate a vanilla NGC program.
The solution to the problem is to simply treat resource requests as valid, and returning
a fake content. The migration is not dependent on templates or stylesheets.. so it's the
simplest and most robust solution.
Fixes#32826
PR Close#32953
ec4381d explicitly set `enableIvy: false` for all migrations inside
the core package. This actually hides migration issues because the
migration itself should ensure that it instantiates the right
compiler program if it relies on `@angular/compiler-cli`.
We should remove these options from all migration tests to
ensure that we catch issues with migrations running in version
9 where Ivy is enabled by default.
e.g. e5636a322c
was accidentally hidden due to the `enableIvy: false` option.
PR Close#32954
ec4381d enabled Ivy by default. This is problematic as migrations
like `static-queries` depend on the `AngularCompilerProgram` (NGC)
in order to perform the migration from version 7 to version 8.
In order to ensure that the migration always runs with NGC
(and doesn't get the `NgtscProgram`), we need to explicitly disable
ivy when creating the `@angular/compiler-cli` program for the migration.
This code is still relevant even though the update from version 7
to version 8 landed. Developers can run `ng update` from version 7
and immediately get to version 9 where Ivy is enabled by default (and in
that case we need to ensure that ngtsc is not accidentally used).
Similar to
e5636a322c.
PR Close#32954
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
Switches back to having the `static` flag be optional on `ViewChild` and `ContentChild` queries, in preparation for changing its default value.
PR Close#32686
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
Before this refactoring native node `classList` / `style` properties were
read even if not used. The reason for this was desire to avoid code duplication
between procedural and non-procedural renderers. Unfortunatelly for the case
which will be used by most users (a procedura renderer) the `classList` / `style`
properties were read twice, making the `setStyle` \ `setClass` functions the
most expensive ones (self time) in several benchmarks (large table, expanding
rows).
This refactoring adds a bit of code duplication in order to get better
runtime performance. The code duplication will be removed when we drop
checks for a procedural renderer.
PR Close#32716
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
Currently all property instructions eventually call into `elementPropertyInternal` which in turn calls to `getLView`, however all of the instructions already have access to the LView. These changes switch to passing in the LView as a parameter.
PR Close#32681
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
All of the `pipeBind` instructions call into `isPure` and `unwrapValue` which in turn call `getLView` internally. These internal calls are redundant, because we already have the `LView` from the `load` calls just before it.
PR Close#32633
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