Prior to this commit, calling change detection for destroyed views resulted in errors being thrown in some cases. This commit adds a check to make sure change detection is invoked for non-destroyed views only.
PR Close#34241
If the `ngI18nClosureMode` global check actually makes it
through to the runtime, then checks for its existence should
be guarded to prevent `Reference undefined` errors in strict
mode.
(Normally, it is stripped out by dead code elimination during
build optimization.)
PR Close#34211
Prior to this commit, i18n runtime code failed with the exception saying that no provider was found for ChangeDetectorRef for a pipe used in ICU. The problem happened because the underlying `createViewRef` function was not taking into account IcuContainer as a valid TNodeType. This commit updates the `createViewRef` function to return corresponding ViewRef for TNodeType.IcuContainer.
PR Close#34198
Includes a few minor performance improvements:
* In the `nextContext` instruction we assign a new LView to the `LFrame.contextLView` and then we immediately look it up to get its context. We don't need to do that since we know the view that was assigned already.
* Removes the default value for the `level` parameter of `nextContextImpl` because it generates more code in es5 and is internal-only.
* Removes the default parameter from `setActiveHostElement` since it generates extra code and it's an internal function.
* Makes a check in `setElementExitFn` more strict since we're guaranteed for the value to match the type.
PR Close#34183
Prior to this commit, the unknown element can happen twice for AOT-compiled components: once during compilation and once again at runtime. Due to the fact that `schemas` information is not present on Component and NgModule defs after AOT compilation, the second check (at runtime) may fail, even though the same check was successful at compile time. This commit updates the code to avoid the second check for AOT-compiled components by checking whether `schemas` information is present in a logic that executes the unknown element check.
PR Close#34024
Since config=ivy now sets the define=compile flag and the define=angular_ivy_enabled
flag to cause usage of Ivy, we can update all of the documentation and scripts that
reference compile=aot to use config=ivy.
PR Close#33983
Prior to this commit, there was a runtime check in i18n logic to make sure "other" case is always present in an ICU. That was not a requirement in View Engine, so ICUs that previously worked may produce errors. This commit removes that restriction and adds support for ICUs without "other" cases.
PR Close#34042
Move a view only if it would end up at a different place.
Otherwise we would do unnecessary processing like DOM manipulation, query notifications etc.
Thanks to @pkozlowski-opensource for the change.
PR Close#34052
When inserting a `viewRef` it is possible to not provide
an `index`, which is regarded as appending to the end of
the container.
If the `viewRef` already exists in the container, then
this results in a move. But there was a fault in the logic
that computed where to insert the `viewRef` that did not
account for the fact that the `viewRef` was already in
the container, so the insertion `index` was outside the
bounds of the array.
Fixes#33924
PR Close#34052
Previously if a type was returning itself it would cause an infinite loop in tsickle. We worked around it with a type that alises to `any`. Now that the issue has been resolved in tsickle, we can clean up the workaround.
PR Close#34019
This commit fixes a compatibility bug where pre-order lifecycle
hooks (onInit, doCheck, OnChanges) for directives on the same
host node were executed based on the order the directives were
matched, rather than the order the directives were instantiated
(i.e. injection order).
This discrepancy can cause issues with forms, where it is common
to inject NgControl and try to extract its control property in
ngOnInit. As the NgControl directive is injected, it should be
instantiated before the control value accessor directive (and
thus its hooks should run first). This ensures that the NgControl
ngOnInit can set up the form control before the ngOnInit
for the control value accessor tries to access it.
Closes#32522
PR Close#34026
These apis have been deprecated in v8, so they should stick around till v10,
but since they are defunct we are removing them early so that they don't take up payload size.
PR Close#33949
The root view case is already covered by the existing code in the
getRenderParent function so no need to have an explicit checks
(and associated memory reads) again.
PR Close#33988
The assertion that we have in the `directiveInject` instruction is too restrictive and we came across some pattern where it throws unnecessarily. This commit removes that assertion for now and more detailed investigation is needed to decide is we need to restrict the set of TNodeType again.
This commit also adds a test which triggered the TNodeType.View to come up in the `directiveInject` instruction, so it might be useful to avoid regressions during further refactoring.
PR Close#33948
NgModule compilation in JIT mode (that is also used in TestBed) caches module scopes on NgModule defs (using `transitiveCompileScopes` field). Module overrides (defined via TestBed.overrideModule) may invalidate this data by adding/removing items in `declarations` list. This commit forces TestBed to recalculate transitive scopes in case module overrides are present, so TestBed always gets the most up-to-date information.
PR Close#33787
This change enables "var(--my-var)" to pass through the style sanitizer.
After consulation with our security team, allowing these doesn't create
new attack vectors, so the sanitizer doesn't need to strip them.
Fixes parts of #23485 related to the sanitizer, other use cases discussed
there related to binding have been addressed via other changes to the
class and style handling in the runtime.
Closes#23485
PR Close#33841
NgModules in Ivy have a definition which contains various different bits
of metadata about the module. In particular, this metadata falls into two
categories:
* metadata required to use the module at runtime (for bootstrapping, etc)
in AOT-only applications.
* metadata required to depend on the module from a JIT-compiled app.
The latter metadata consists of the module's declarations, imports, and
exports. To support JIT usage, this metadata must be included in the
generated code, especially if that code is shipped to NPM. However, because
this metadata preserves the entire NgModule graph (references to all
directives and components in the app), it needs to be removed during
optimization for AOT-only builds.
Previously, this was done with a clever design:
1. The extra metadata was added by a function called `setNgModuleScope`.
A call to this function was generated after each NgModule.
2. This function call was marked as "pure" with a comment and used
`noSideEffects` internally, which causes optimizers to remove it.
The effect was that in dev mode or test mode (which use JIT), no optimizer
runs and the full NgModule metadata was available at runtime. But in
production (presumably AOT) builds, the optimizer runs and removes the JIT-
specific metadata.
However, there are cases where apps that want to use JIT in production, and
still make an optimized build. In this case, the JIT-specific metadata would
be erroneously removed. This commit solves that problem by adding an
`ngJitMode` global variable which guards all `setNgModuleScope` calls. An
optimizer can be configured to statically define this global to be `false`
for AOT-only builds, causing the extra metadata to be stripped.
A configuration for Terser used by the CLI is provided in `tooling.ts` which
sets `ngJitMode` to `false` when building AOT apps.
PR Close#33671
Originally, QueryList implemented Iterable and provided a Symbol.iterator
on its prototype. This caused issues with tree-shaking, so QueryList was
refactored and the Symbol.iterator added in its constructor instead. As
part of this change, QueryList no longer implemented Iterable directly.
Unfortunately, this meant that QueryList was no longer assignable to
Iterable or, consequently, NgIterable. NgIterable is used for NgFor's input,
so this meant that QueryList was not usable (in a type sense) for NgFor
iteration. View Engine's template type checking would not catch this, but
Ivy's did.
As a fix, this commit adds the declaration (but not the implementation) of
the Symbol.iterator function back to QueryList. This has no runtime effect,
so it doesn't affect tree-shaking of QueryList, but it ensures that
QueryList is assignable to NgIterable and thus usable with NgFor.
Fixes#29842
PR Close#33536
TNode.inputs are initialised during directives resolution now so we know early
if a node has directives with inputs or no. We don't need to use undefined value
as an indicator that inputs were not resolved yet.
PR Close#33798
Before this change a public name of a directive's input
was stored in 2 places:
- as a key of an object on TNode.index;
- as a value of PropertyAliasValue at the index 1
This PR changes the data structure so the public name is stored
only once as a key on TNode.index. This saves one array entry
for each and every directive input.
PR Close#33798
Adds support for chaining of `styleProp`, `classProp` and `stylePropInterpolateX` instructions whenever possible which should help generate less code. Note that one complication here is for `stylePropInterpolateX` instructions where we have to break into multiple chains if there are other styling instructions inbetween the interpolations which helps maintain the execution order.
PR Close#33837
This refactorings clearly separates the first and subsequent creation execution
of the `template` instruction. This approach has the following benefits:
- it is clear what happens during the first vs. subsequent executions;
- we can avoid several memory reads and checks after the first creation pass
(there is measurable performance improvement on various benchmarks);
- the template instructions becomes smaller and should become a candidate
for optimisations / inlining faster;
PR Close#33856
When asking for a ViewContainerRef on <ng-container> we do reuse <ng-container> comment
node as a LContainer's anachor. Before this fix the act of re-using a <ng-container>'s
comment node would result in this comment node being re-appended to the DOM in the wrong
place. With the fix in this PR we make sure that re-using <ng-container>'s comment node
doesn't result in unwanted DOM manipulation (ng-gontainer's comment node is already part
of the DOM and doesn't have to be re-created / re-appended).
PR Close#33816
If the application is not running directly in the browser, e.g.
universal or app-shell, then the `$localize` import must be
adding to a different file than for normal browser applications.
This commit adds more information about this to avoid any
confusion.
// FW-1557
PR Close#33826
Prior to this commit the assert that we have in `directiveInject` (assert introduced recently) didn't include IcuContainer TNode type and as a result, the error is thrown in case pipes with dependencies are used inside ICUs. This commit extends the assert to allow for IcuContainer TNode types.
PR Close#33832
This commit moves the `setLContainerActiveIndex` and `getLContainerActiveIndex` functions used in a few files to a common `util/view_util.ts` lib to avoid cyclical dependency while importing `instructions/container.ts` where these functions located originally.
PR Close#33831
Currently if a consumer does something like the following, the object literal will be shared across the two elements and any instances of the component template. The same applies to array literals:
```
<div [someDirective]="{}"></div>
<div [someDirective]="{}"></div>
```
These changes make it so that we generate a pure function even if an object is constant so that each instance gets its own object.
Note that the original design for this fix included moving the pure function factories into the `consts` array. In the process of doing so I realized that pure function are also used inside of directive host bindings which means that we don't have access to the `consts`.
These changes also:
* Fix an issue that meant that the `pureFunction0` instruction could only be run during creation mode.
* Make the `getConstant` utility slightly more convenient to use. This isn't strictly required for these changes to work, but I had made it as a part of a larger refactor that I ended up reverting.
PR Close#33705
Prior to this change, setting style prop value to undefined or empty string would not result in resetting prop value in case the style prop is defined using [style.prop.px] syntax. The problem is that the check for empty value (and thus reseting the value) considered successful only in case of `null` value. This commit updates the check to use `isStylingValueDefined` function that also checks for undefined and empty string.
PR Close#33780
Prior to this change, ComponentFactory.create function invocation in Ivy retained the content of the host element (in case host element reference or CSS seelctor is provided as an argument). This behavior is different in View Engine, where the content of the host element was cleared, except for the case when ShadowDom encapsulation is used (to make sure native slot projection works). This commit aligns Ivy and View Engine and makes sure the host element is cleared before component content insertion.
PR Close#33487
The `ngInjectableDef` property was renamed to `ɵprov`, but core must
still support both because there are published libraries that use the
older term.
We are only interested in such properties that are defined directly on
the type being injected, not on base classes. So there is a check that
the defintion is specifically for the given type.
Previously if you tried to inject a class that had `ngInjectableDef` but
also inherited `ɵprov` then the check would fail on the `ɵprov` property
and never even try the `ngInjectableDef` property resulting in a failed
injection.
This commit fixes this by attempting to find each of the properties
independently.
Fixes https://github.com/angular/ngcc-validation/pull/526
PR Close#33732
Chains multiple listener instructions on a particular element into a single call which results in less generated code. Also handles listeners on templates, host listeners and synthetic host listeners.
PR Close#33720
Most of the use of `document` in the framework is within
the DI so they just inject the `DOCUMENT` token and are done.
Ivy is special because it does not rely upon the DI and must
get hold of the document some other way. There are a limited
number of places relevant to ivy that currently consume a global
document object.
The solution is modelled on the `LOCALE_ID` approach, which has
`getLocaleId()` and `setLocaleId()` top-level functions for ivy (see
`core/src/render3/i18n.ts`). In the rest of Angular (i.e. using DI) the
`LOCALE_ID` token has a provider that also calls setLocaleId() to
ensure that ivy has the same value.
This commit defines `getDocument()` and `setDocument() `top-level
functions for ivy. Wherever ivy needs the global `document`, it calls
`getDocument()` instead. Each of the platforms (e.g. Browser, Server,
WebWorker) have providers for `DOCUMENT`. In each of those providers
they also call `setDocument()` accordingly.
Fixes#33651
PR Close#33712
When debugging `LView`s it is easy to get lost since all of them have
the same name. This change does three things:
1. It makes `TView` have an explicit type:
- `Host`: for the top level `TView` for bootstrap
- `Component`: for the `TView` which represents components template
- `Embedded`: for the `TView` which represents an embedded template
2. It changes the name of `LView` to `LHostView`, `LComponentView`, and
`LEmbeddedView` depending on the `TView` type.
3. For `LComponentView` and `LEmbeddedView` we also append the name of
of the `context` constructor. The result is that we have `LView`s which
are name as: `LComponentView_MyComponent` and `LEmbeddedView_NgIfContext`.
The above changes will make it easier to understand the structure of the
application when debugging.
NOTE: All of these are behind `ngDevMode` and will get removed in
production application.
PR Close#33449
Prior to this commit, i18n runtime logic used `elementAttributeInternal` function (that uses `setAttribute` function under the hood) for all elements where i18n attributes are present. However the `<ng-container>` elements in a template may also have i18n attributes and calling `setAttribute` fails, since they are represented as comment nodes in DOM. This commit ensures that we call `setAttribute` on nodes with TNodeType.Element type (that support that operation) only.
PR Close#33599
This patch gets rid of the configuration settings present in the
`TStylingContext` array that is used within the styling algorithm
for `[style]`, `[style.prop]`, `[class]` and `[class.name]` bindings.
These configurations now all live inside of the `TNodeFlags`.
PR Close#33540
This patch removes the need to lock the style and class context
instances to track when bindings can be added. What happens now is
that the `tNode.firstUpdatePass` is used to track when bindings are
registered on the context instances.
PR Close#33521
To support compile time localization, we need to be
able to provide the locales via a well known global property.
This commit changes `getLocaleData()` so that it will attempt
to read the local from the global `ng.common.locales` if the
locale has not already been registered via `registerLocaleData()`.
PR Close#33523
To limit the exposure of the private `LOCALE_DATA` from outside
`@angular/core` this commit exposes private functions in the core
to hide the internal structures better.
* The `registerLocaleData()` implementation has moved from
`@angular/common` to `@angular/core`. A stub that delegates to
core has been left in common for backward compatibility.
* A new `ɵunregisterLocaleData()` function has been provided,
which is particularly useful in tests to clear out registered locales
to prevent subsequent tests from being affected.
* A private export of `ɵregisterLocaleData()` has been removed
from `@angular/common`. This was not being used and is accessible
via `@angular/core` anyway.
PR Close#33523
This patch introduces a `firstUpdatePass` flag which can be used inside
of instruction code to determine if this is the first time each
instruction is running inside of the update block of a template or
a hostBindings function.
PR Close#31270
We already store a reference to a native host of a component
view so we can drop the getHostNative utility function (that
was getting the same reference from another data structure).
PR Close#33554
In ViewEngine we used to throw an error if we encountered an unknown element while rendering. We have this already for Ivy in AoT, but we didn't in JiT. These changes implement the error for JiT mode.
PR Close#33419
Before this change instantiating multiple directives on the same
host node would result in repeated RNode retrieval and patching.
This commint re-organises code around directive instance creation
so the host node processing (common to all directives) happens
once and only once.
As the additional benefit the directive instantiation logic gets
centralised in one function (at the expense of patching logic
duplication for root node).
PR Close#33322
Now that we've replaced `ngBaseDef` with an abstract directive definition, there are a lot more cases where we generate a directive definition without a selector. These changes make it so that we don't generate the `selectors` array if it's going to be empty.
PR Close#33431
Prior to this commit, i18n logic which ensures that elements removed in a translation are also removed in DOM, didn't take into account the fact that elements may have local refs. As a result, remove operation failed, since there is no corresponding tNode found. This commit updates the logic to skip all local refs while going though the list of nodes to ensure that DOM matches elements present in translation.
PR Close#33415
`bindingIndex` stores the current location of the bindings in the
template function. Because it used to be stored in `LView` that `LView`
was not reentrant. This could happen if a binding was a getter and had
a side-effect of calling `detectChanges()`.
By moving the `bindingIndex` to `LFrame` where all of the global state
is kept in reentrant way we correct the issue.
PR Close#33235
Removes `ngBaseDef` from the compiler and any runtime code that was still referring to it. In the cases where we'd previously generate a base def we now generate a definition for an abstract directive.
PR Close#33264
For abstract directives, i.e. directives without a selector, it may
happen that their constructor is called explicitly from a subclass,
hence its parameters are not required to be valid for Angular's DI
purposes. Prior to this commit however, having an abstract directive
with a constructor that has parameters that are not eligible for
Angular's DI would produce a compilation error.
A similar scenario may occur for `@Injectable`s, where an explicit
`use*` definition allows for the constructor to be irrelevant. For
example, the situation where `useFactory` is specified allows for the
constructor to be called explicitly with any value, so its constructor
parameters are not required to be valid. For `@Injectable`s this is
handled by generating a DI factory function that throws.
This commit implements the same solution for abstract directives, such
that a compilation error is avoided while still producing an error at
runtime if the type is instantiated implicitly by Angular's DI
mechanism.
Fixes#32981
PR Close#32987
This commit adds CopyDefinitionFeature, which supports the case where an
entire decorator (@Component or @Directive) is inherited from parent to
child.
The existing inheritance feature, InheritDefinitionFeature, supports merging
of parent and child definitions when both were originally present. This
merges things like inputs, outputs, host bindings, etc.
CopyDefinitionFeature, on the other hand, compensates for a definition that
was missing entirely on the child class, by copying fields that aren't
ordinarily inherited (like the template function itself).
This feature is intended to only be used as part of ngcc code generation.
PR Close#33362
This patch ensures that the `[style]` and `[class]` based bindings
are directly applied to an element's style and className attributes.
This patch optimizes the algorithm so that it...
- Doesn't construct an update an instance of `StylingMapArray` for
`[style]` and `[class]` bindings
- Doesn't apply `[style]` and `[class]` based entries using
`classList` and `style` (direct attributes are used instead)
- Doesn't split or iterate over all string-based tokens in a
string value obtained from a `[class]` binding.
This patch speeds up the following cases:
- `<div [class]>` and `<div class="..." [class]>`
- `<div [style]>` and `<div style="..." [style]>`
The overall speec increase is by over 5x.
PR Close#33336
`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
Recently it was made possible to have a directive without selector,
which are referred to as abstract directives. Such directives should not
be registered in an NgModule, but can still contain decorators for
inputs, outputs, queries, etc. The information from these decorators and
the `@Directive()` decorator itself needs to be registered with the
central `MetadataRegistry` so that other areas of the compiler can
request information about a given directive, an example of which is the
template type checker that needs to know about the inputs and outputs of
directives.
Prior to this change, however, abstract directives would only register
themselves with the `MetadataRegistry` as being an abstract directive,
without all of its other metadata like inputs and outputs. This meant
that the template type checker was unable to resolve the inputs and
outputs of these abstract directives, therefore failing to check them
correctly. The typical error would be that some property does not exist
on a DOM element, whereas said property should have been bound to the
abstract directive's input.
This commit fixes the problem by always registering the metadata of a
directive or component with the `MetadataRegistry`. Tests have been
added to ensure abstract directives are handled correctly in the
template type checker, together with tests to verify the form of
abstract directives in declaration files.
Fixes#30080
PR Close#33131
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
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
With Ivy the `entryComponents` array isn't necessary anymore. These changes mark it as deprecated so that it can be removed in a future version.
PR Close#33205
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
LocaleID 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
ngLocaleIdDef to loc. 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#33212
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
This change assures that data structures related to initial inputs
(ones set from static attributes) are created only once (during the
first template pass) and no additional runtime checks are done for
subsequent passes.
Additionally this commit changes the data structure used by initial inputs
on TNode - previously initial inputs for a directive were stored at the
directive index in LView. This meant that an array holding initial inputs
was relativelly big and had many null elements (as placeholders for elements,
directives, injector etc.). After the change we only create an array of a size
equal to a number of directives matched on a given TNode.
For the `directive_instantiate` benchmark it boils to allocating a 1-element
array vs. 100-element array previously.
PR Close#33195
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
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
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
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
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
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
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