The `ɵɵngDeclareComponent` calls are designed to be translated to fully
AOT compiled code during a build transform, but in cases this is not
done it is still possible to compile the declaration object in the
browser using the JIT compiler. This commit adds a runtime
implementation of `ɵɵngDeclareComponent` which invokes the JIT compiler
using the declaration object, such that a compiled component definition
is made available to the Ivy runtime.
PR Close#40127
The `render3` test targets are currently also executed for ViewEngine
builds, even though the `render3` infrastructure only concerns Ivy
infrastructure. This commit tags the test targets as ivy-only to disable
those tests for View Engine.
PR Close#40127
Currently we check whether a property binding contains an interpolation using a regex so
that we can throw an error. The problem is that the regex doesn't account for quotes
which means that something like `[prop]="'{{ foo }}'"` will be considered an error, even
though it's not actually an interpolation.
These changes build on top of the logic from #39826 to account for interpolation
characters inside quotes.
Fixes#39601.
PR Close#40267
The trustConstantHtml and trustConstantResourceUrl functions are only
meant to be passed constant strings extracted from Angular application
templates, as passing other strings or variables could introduce XSS
vulnerabilities.
To better protect these APIs, turn them into template tags. This makes
it possible to assert that the associated template literals do not
contain any interpolation, and thus must be constant.
Also add tests for the change to prevent regression.
PR Close#40082
There are two parts to this commit:
1. Revert the changes from #38379. This change had an incomplete view of
how things worked and also diverged the implementations of
`applyRedirects` and `recognize` even more.
2. Apply the fixes from the `recognize` algorithm to ensure that named
outlets with empty path parents can be matched. This change also passes
all the tests that were added in #38379 with the added benefit of being
a more complete fix that stays in-line with the `recognize` algorithm.
This was made possible by using the same approach for `split` by
always creating segments for empty path matches (previously, this was
only done in `applyRedirects` if there was a `redirectTo` value). At the
end of the expansions, we need to squash all empty segments so that
serializing the final `UrlTree` returns the same result as before.
Fixes#39952Fixes#10726Closes#30410
PR Close#40029
Prior to this commit, removing `FormControlDirective` and `FormGroupName` directive instances didn't clear
the callbacks previously registered on FromControl/FormGroup class instances. As a result, these callbacks
were executed even after `FormControlDirective` and `FormGroupName` directive instances were destroyed. That was
also causing memory leaks since these callbacks also retained references to DOM elements.
This commit updates the cleanup logic to take care of properly detaching FormControl/FormGroup/FormArray instances
from the view by removing view-specific callback at destroy time.
Closes#20007, #37431, #39590.
PR Close#39235
DI providers can be defined via `useFactory` function, which may have arguments configured via `deps` array.
The `deps` array may contain DI flags represented by DI decorators (such as `@Self`, `@SkipSelf`, etc). Prior to this
commit, having the `@Host` decorator in `deps` array resulted in runtime error in Ivy. The problem was that the `@Host`
decorator was not taken into account while `useFactory` argument list was constructed, the `@Host` decorator was
treated as a token that should be looked up.
This commit updates the logic which prepares `useFactory` arguments to recognize the `@Host` decorator.
PR Close#40122
`Route` configs with `redirectTo` as well as `canActivate` are not valid
because the `canActivate` guards will never execute. Redirects are
applied before activation. There is no error currently for these
configs, but another commit will change this so that an error does
appear in dev mode. This migration fixes the configs by removing the
`canActivate` property.
PR Close#40067
The `ɵɵngDeclareDirective` calls are designed to be translated to fully
AOT compiled code during a build transform, but in cases this is not
done it is still possible to compile the declaration object in the
browser using the JIT compiler. This commit adds a runtime
implementation of `ɵɵngDeclareDirective` which invokes the JIT compiler
using the declaration object, such that a compiled directive definition
is made available to the Ivy runtime.
PR Close#40101
Internally we store lifecycle hooks in the format `[index, hook, index, hook]` and when
iterating over them, we check one place ahead to figure out whether we've hit found
a hook or an index. The problem is that the loop is set up to iterate up to `hooks.length`
which means that we may go out of bounds on the last iteration, depending on where
we started. This appears to happen under a specific set of circumstances where a
directive calls `detectChanges` from an input setter while it has `ngOnChanges` and
`ngAfterViewInit` hooks.
These changes resolve the issue by only iterating up to `length - 1` which guarantees that
we can always look one place ahead.
This appears to have regressed some time in version 10.
Fixes#38611.
PR Close#40206
The types of directives and pipes that are used in a component's
template may be emitted into the partial declaration wrapped inside a
closure, which is needed when the type is declared later in the module.
This poses a problem for JIT compilation of partial declarations, as
this closure is indistinguishable from a class reference itself. To mark
the forward reference function as such, this commit changes the partial
declaration codegen to emit a `forwardRef` invocation wrapped around
the closure, which ensures that the closure is properly tagged as a
forward reference. This allows the forward reference to be treated as
such during JIT compilation.
PR Close#40117
PR #39876 introduced an error where the `onDestroy` of `ComponentRef`
would only get called if `ngDevMode` was set to true. This was because
in dev mode we would freeze `TCleanup` to verify that no more
static cleanup would get added to `TCleanup` array. This ensured
that `TCleanup` was always present in dev mode. In production the
`TCleanup` would get created only when needed. The resulting cleanup
code was incorrectly indented and would only run if `TCleanup` was
present causing this issue.
Fix#40105
PR Close#40120
Escape the content of the strings so that it can be safely inserted into a comment node.
The issue is that HTML does not specify any way to escape comment end text inside the comment.
`<!-- The way you close a comment is with "-->". -->`. Above the `"-->"` is meant to be text
not an end to the comment. This can be created programmatically through DOM APIs.
```
div.innerHTML = div.innerHTML
```
One would expect that the above code would be safe to do, but it turns out that because comment
text is not escaped, the comment may contain text which will prematurely close the comment
opening up the application for XSS attack. (In SSR we programmatically create comment nodes which
may contain such text and expect them to be safe.)
This function escapes the comment text by looking for the closing char sequence `-->` and replace
it with `-_-_>` where the `_` is a zero width space `\u200B`. The result is that if a comment
contains `-->` text it will render normally but it will not cause the HTML parser to close the
comment.
PR Close#40136
Currently when `ɵɵtemplate` and `ɵɵelement` instructions are generated by compiler, all static attributes are
duplicated for both instructions. As a part of this duplication, i18n translation blocks for static i18n attributes
are generated twice as well, causing duplicate entries in extracted translation files (when Ivy extraction mechanisms
are used). This commit fixes this issue by introducing a cache for i18n translation blocks (for static attributes
only).
Also this commit further aligns `ɵɵtemplate` and `ɵɵelement` instruction attributes, which should help implement
more effective attributes deduplication logic.
Closes#39942.
PR Close#40077
Prior to this change, the `setClassMetadata` call would be invoked
inside of an IIFE that was marked as pure. This allows the call to be
tree-shaken away in production builds, as the `setClassMetadata` call
is only present to make the original class metadata available to the
testing infrastructure. The pure marker is problematic, though, as the
`setClassMetadata` call does in fact have the side-effect of assigning
the metadata into class properties. This has worked under the assumption
that only build optimization tools perform tree-shaking, however modern
bundlers are also able to elide calls that have been marked pure so this
assumption does no longer hold. Instead, an `ngDevMode` guard is used
which still allows the call to be elided but only by tooling that is
configured to consider `ngDevMode` as constant `false` value.
PR Close#39987
Currently the compiler treats something like `{{ '{{a}}' }}` as a nested
binding and throws an error, because it doesn't account for quotes
when it looks for binding characters. These changes add a bit of
logic to skip over text inside quotes when parsing.
Fixes#39601.
PR Close#39826
Differs tries to inject parent differ in order to support extending.
This does not work in the 'root' injector as the provider overrides the
default injector. The fix is to just assume standard set of providers
and extend those instead.
PR close#25015
Issue close#11309 `Can't extend IterableDiffers`
Issue close#18554 `IterableDiffers.extend is not AOT compatible`
(This is fixed because we no longer have an arrow function in the
factory but a proper function which can be imported.)
PR Close#39981
This commit adds `ngDevMode` guard to run `checkNoChanges` only
in dev mode (similar to how things work in other parts of Ivy runtime code).
The `ngDevMode` flag helps to tree-shake this code from production builds
(in dev mode everything will work as it works right now) to decrease production bundle size.
PR Close#39964
This commit adds `ngDevMode` guard to show sanitization warnings only
in dev mode (similar to how things work in other parts of Ivy runtime code).
The `ngDevMode` flag helps to tree-shake these warnings from production builds
(in dev mode everything will work as it works right now) to decrease production bundle size.
PR Close#39959
At the moment, when creating a root module, a subscription to the
`onError` subject is also created. It captures the scope where `NgModuleRef`
is created and prevents it from being garbage collected. Also note that this
`NgModuleRef` has a reference to the root module instance (e.g. `AppModule`),
which also prevents it from being GC'd.
PR Close#39940
This commit adds a few tests to verify that the `onDestroy` callbacks are invoked when `ComponentRef` instance
is destroyed and the logic is consistent between ViewEngine and Ivy.
PR Close#39876
In the new behavior Angular removes applications from the testability registry when the
root view gets destroyed. This eliminates a memory leak, because before that the
TestabilityRegistry holds references to HTML elements, thus they cannot be GCed.
PR Close#22106
PR Close#39876
Currently we convert objects to strings using `'' + value` which is quickest,
but it stringifies the value using its `valueOf`, rather than `toString`. These
changes switch to using `String(value)` which has identical performance
and calls the `toString` method as expected. Note that another option
was calling `toString` directly, but benchmarking showed it to be slower.
I've included the benchmark I used to verify the performance so we have it
for future reference and we can reuse it when making changes to `renderStringify`
in the future.
Also for reference, here are the results of the benchmark:
```
Benchmark: renderStringify
concat: 2.006 ns(0%)
concat with toString: 2.201 ns(-10%)
toString: 237.494 ns(-11741%)
toString with toString: 121.072 ns(-5937%)
constructor: 2.201 ns(-10%)
constructor with toString: 2.201 ns(-10%)
toString mono: 14.536 ns(-625%)
toString with toString mono: 9.757 ns(-386%)
```
Fixes#38839.
PR Close#39843
We currently only wrap the event listener in the function which ensures
ancestors are marked for check when the listener is placed on an element
that has a native method for listening to an event. We actually need to do
this wrapping in all cases so that events that are attached to non-rendered
template items (`ng-template` and `ng-container`) also mark ancestors for check
when they receive the event.
fixes#39832
PR Close#39833
`@angular/core` support zone.js `^0.10.2 and ^0.11.3`, so this PR updates the
peerDependencies to `^0.10.2 || ^ 0.11.3`, so the app will not show warning about
peer denepdency not consistent when using zone.js 0.10.x version.
PR Close#39809
This commit implements partial compilation of components, together with
linking the partial declaration into its full AOT output.
This commit does not yet enable accurate source maps into external
templates. This requires additional work to account for escape sequences
which is non-trivial. Inline templates that were represented using a
string or template literal are transplated into the partial declaration
output, so their source maps should be accurate. Note, however, that
the accuracy of source maps is not currently verified in tests; this is
also left as future work.
The golden files of partial compilation output have been updated to
reflect the generated code for components. Please note that the current
output should not yet be considered stable.
PR Close#39707
Script tags, inline event handlers and other script contexts are
forbidden or stripped from Angular templates by the compiler. In the
context of Trusted Types, this leaves no sinks that require use of a
TrustedScript. This means that trustConstantScript is never used, and
can be removed.
PR Close#39554
To minimize security risk (XSS in particular) in the i18n pipeline,
disallow i18n translation of attributes that are Trusted Types sinks.
Add integration tests to ensure that such sinks cannot be translated.
PR Close#39554
As only methods from the Subscribable interface are currently used in the
implementation of the async pipe, it makes sense to make it explicit so
that it works successfully with any other implementation instead of
only Observable.
PR Close#39627
Currently all of our migrations are set up to find the tsconfig paths within a project,
create a `Program` out of each and migrate the files inside of the `Program`. The
problem is that the `Program` can include files outside of the project and the CLI
APIs that we use to interact with the file system assume that all files are within
the project.
These changes consolidate the logic, that determines whether a file can be migrated,
in a single place and add an extra check to exclude files outside of the root.
Fixes#39778.
PR Close#39790
`zone.js` 0.8.25 introduces `zone-testing` bundle and move all `fakeAsync/async` logic
from `@angular/core/testing` to `zone.js` package. But in case some user still using the old
version of `zone.js`, an old version of `fakeAsync/async` logic were still kept inside `@angular/core/testing`
package as `fallback` logic. Since now `Angular8+` already use `zone.js 0.9+`, so
those fallback logic is removed.
PR Close#37879
The codebase currently contains two `getOutlet` functions,
and they can end up in the bundle of an application.
A recent commit 6fbe21941d tipped us off
as it introduced several `noop` occurrences in the golden symbol files.
After investigating with @petebacondarwin,
we decided to remove the duplicated functions.
This probably shaves only a few bytes,
but this commit removes the duplicated functions,
by always using the one in `router/src/utils/config`.
PR Close#39764
This commit fixes a bug when `Attribute` DI decorator is used in the
`deps` section of a token that uses a factory function. The problem
appeared because the `Attribute` DI decorator was not handled correctly
while injecting factory function attributes.
Closes#36479
PR Close#37085
The codebase currently contains several `noop` functions,
and they can end up in the bundle of an application.
A recent commit 6fbe21941d tipped us off
as it introduced several `noop` occurrences in the golden symbol files.
After investigating with @petebacondarwin,
we decided to remove the duplicated functions.
This probably shaves only a few bytes,
but this commit removes the duplicated functions,
by always using the one in `core/src/utils/noop`.
PR Close#39761
In #38762 we added a migration to replace the deprecated `preserveQueryParams`
option with `queryParamsHandling`, however due to a typo, we ended up replacing it
with `queryParamsHandler` which is invalid.
Fixes#39755.
PR Close#39763
This commit removes the TODO comment that proposed
that we use the built-in RxJS `isObservable()` function.
This is not a viable approach since the built-in function
requires that the `obj` contains additional methods that
our "observable" types (such as `EventEmitter`) do not
necessarily have.
See #39643 for more information.
PR Close#39669
`ViewRef` and `ApplicationRef` had a circular reference. This change
introduces `ViewRefTracker` which is a subset of `ApplicationRef` for
this purpose.
PR Close#39621
JIT needs to identify which type is `ChangeDetectorRef`. It was doing so
by importing `ChangeDetectorRef` and than comparing the types. This creates
circular dependency as well as prevents tree shaking. The new solution is
to brand the class with `__ChangeDetectorRef__` so that it can be identified
without creating circular dependency.
PR Close#39621
`LContainer` stores `ViewRef`s this is not quite right as it creates
circular dependency between the two types. Also `LContainer` should not
be aware of `ViewRef` which iv ViewEngine specific construct.
PR Close#39621
Due to historical reasons `Injector.__NG_ELEMENT_ID__` was set to `-1`.
This changes it to be consistent with other `*Ref.__NG_ELEMENT_ID__`
constructs.
PR Close#39621
`Renderer2` is declared in ViewEngine but it sub-classed in Ivy. This creates a circular
dependency between ViewEngine `Renderer2` which needs to declare `__NG_ELEMENT_ID__` and
ivy factory which needs to create it. The workaround used to be to pass the `Renderer2`
through stack but that created a very convoluted code. This refactoring simply bundles the
two files together and removes the stack workaround making the code simpler to follow.
PR Close#39621
`ChangeDetectorRef` is declared in ViewEngine but it sub-classed in Ivy. This creates a circular
dependency between ViewEngine `ChangeDetectorRef` which needs to declare `__NG_ELEMENT_ID__` and
ivy factory which needs to create it. The workaround used to be to pass the `ChangeDetectorRef`
through stack but that created a very convoluted code. This refactoring simply bundles the
two files together and removes the stack workaround making the code simpler to follow.
PR Close#39621
`ViewContainerRef` is declared in ViewEngine but it sub-classed in Ivy. This creates a circular
dependency between ViewEngine `ViewContainerRef` which needs to declare `__NG_ELEMENT_ID__` and
ivy factory which needs to create it. The workaround used to be to pass the `ViewContainerRef`
through stack but that created a very convoluted code. This refactoring simply bundles the
two files together and removes the stack workaround making the code simpler to follow.
PR Close#39621
`TemplateRef` is declared in ViewEngine but it sub-classed in Ivy. This creates a circular
dependency between ViewEngine `TemplateRef` which needs to declare `__NG_ELEMENT_ID__` and
ivy factory which needs to create it. The workaround used to be to pass the `TemplateRef`
through stack but that created a very convoluted code. This refactoring simply bundles the
two files together and removes the stack workaround making the code simpler to follow.
PR Close#39621
`ElementRef` is declared in ViewEngine but it sub-classed in Ivy. This creates a circular
dependency between ViewEngine `ElementRef` which needs to declare `__NG_ELEMENT_ID__` and
ivy factory which needs to create it. The workaround used to be to pass the `ElementRef`
through stack but that created a very convoluted code. This refactoring simply bundles the
two files together and removes the stack workaround making the code simpler to follow.
PR Close#39621
Close#39348
Now `NgZone` has an option `shouldCoalesceEventChangeDetection` to coalesce
multiple event handler's change detections to one async change detection.
And there are some cases other than `event handler` have the same issues.
In #39348, the case like this.
```
// This code results in one change detection occurring per
// ngZone.run() call. This is entirely feasible, and can be a serious
// performance issue.
for (let i = 0; i < 100; i++) {
this.ngZone.run(() => {
// do something
});
}
```
So such kind of case will trigger multiple change detections.
And now with Ivy, we have a new `markDirty()` API will schedule
a requestAnimationFrame to trigger change detection and also coalesce
the change detections in the same event loop, `markDirty()` API doesn't
only take care `event handler` but also all other cases `sync/macroTask/..`
So this PR add a new option to coalesce change detections for all cases.
test(core): add test case for shouldCoalesceEventChangeDetection option
Add new test cases for current `shouldCoalesceEventChangeDetection` in `ng_zone.spec`, since
currently we only have integration test for this one.
PR Close#39422
`setComponentScope` was previously undocumented. This commit adds a short
explanation of what the function does, and adds a link to a doc which
explains issues with cycles in more detail.
PR Close#39662
When a `ViewContainerRef` is injected, we dynamically create a comment node next to the host
so that it can be used as an anchor point for inserting views. The comment node is inserted
through the `appendChild` helper from `node_manipulation.ts` in most cases.
The problem with using `appendChild` here is that it has some extra logic which doesn't return
a parent `RNode` if an element is at the root of a component. I __think__ that this is a performance
optimization which is used to avoid inserting an element in one place in the DOM and then
moving it a bit later when it is projected. This can break down in some cases when creating
a `ViewContainerRef` for a non-component node at the root of another component like the following:
```
<root>
<div #viewContainerRef></div>
</root>
```
In this case the `#viewContainerRef` node is at the root of a component so we intentionally don't
insert it, but since its anchor element was created manually, it'll never be projected. This will
prevent any views added through the `ViewContainerRef` from being inserted into the DOM.
These changes resolve the issue by not going through `appendChild` at all when creating a comment
node for `ViewContainerRef`. This should work identically since `appendChild` doesn't really do
anything with the T structures anyway, it only uses them to reach the relevant DOM nodes.
Fixes#39556.
PR Close#39599
Currently when an instance of the `FormControlName` directive is destroyed, the Forms package invokes
the `cleanUpControl` to clear all directive-specific logic (such as validators, onChange handlers,
etc) from a bound control. The logic of the `cleanUpControl` function should revert all setup
performed by the `setUpControl` function. However the `cleanUpControl` is too aggressive and removes
all callbacks related to the onChange and disabled state handling. This is causing problems when
a form control is bound to multiple FormControlName` directives, causing other instances of that
directive to stop working correctly when the first one is destroyed.
This commit updates the cleanup logic to only remove callbacks added while setting up a control
for a given directive instance.
The fix is needed to allow adding `cleanUpControl` function to other places where cleanup is needed
(missing this function calls in some other places causes memory leak issues).
PR Close#39623
* Fixes that the Ivy styling logic wasn't accounting for `!important` in the property value.
* Fixes that the default DOM renderer only sets `!important` on a property with a dash in its name.
* Accounts for the `flags` parameter of `setStyle` in the server renderer.
Fixes#35323.
PR Close#39603
In ViewEngine, SelfSkip would navigate up the tree to get tokens from
the parent node, skipping the child. This restores that functionality in
Ivy. In ViewEngine, if a special token (e.g. ElementRef) was not found
in the NodeInjector tree, the ModuleInjector was also used to lookup
that token. While special tokens like ElementRef make sense only in a
context of a NodeInjector, we preserved ViewEngine logic for now to
avoid breaking changes.
We identified 4 scenarios related to @SkipSelf and special tokens where
ViewEngine behavior was incorrect and is likely due to bugs. In Ivy this
is implemented to provide a more intuitive API. The list of scenarios
can be found below.
1. When Injector is used in combination with @Host and @SkipSelf on the
first Component within a module and the injector is defined in the
module, ViewEngine will get the injector from the module. In Ivy, it
does not do this and throws instead.
2. When retrieving a @ViewContainerRef while @SkipSelf and @Host are
present, in ViewEngine, it throws an exception. In Ivy it returns the
host ViewContainerRef.
3. When retrieving a @ViewContainerRef on an embedded view and @SkipSelf
is present, in ViewEngine, the ref is null. In Ivy it returns the parent
ViewContainerRef.
4. When utilizing viewProviders and providers, a child component that is
nested within a parent component that has @SkipSelf on a viewProvider
value, if that provider is provided by the parent component's
viewProviders and providers, ViewEngine will return that parent's
viewProviders value, which violates how viewProviders' visibility should
work. In Ivy, it retrieves the value from providers, as it should.
These discrepancies all behave as they should in Ivy and are likely bugs
in ViewEngine.
PR Close#39464
The lexer is able to skip leading trivia in the `start` location of tokens.
This makes the source-span more friendly since things like elements
appear to begin at the start of the opening tag, rather than at the
start of any leading whitespace, which could include newlines.
But some tooling requires the full source-span to be available, such
as when tokenizing a text span into an Angular expression.
This commit simply adds the `fullStart` location to the `ParseSourceSpan`
class, and ensures that places where such spans are cloned, this
property flows through too.
PR Close#39486
Prior to this commit, the `cleanUpControl` function (responsible for cleaning up control instance)
was not taking validators into account. As a result, these validators remain registered on a detached
form control instance, thus causing memory leaks. This commit updates the `cleanUpControl` function
logic to also run validators cleanup.
As a part of this change, the logic to setup and cleanup validators was refactored and moved to
separate functions (with completely opposite behavior), so that they can be reused in the future.
This commit doesn't add the `cleanUpControl` calls to all possible places, it just fixes the cases
where this function is being called, but doesn't fully perform a cleanup. The `cleanUpControl`
function calls will be added to other parts of code (to avoid more memory leaks) in a followup PR.
PR Close#39234
For consistency with other generated code, the partial declaration
functions are renamed to use the `ɵɵ` prefix which indicates that it is
generated API.
This commit also removes the declaration from the public API golden
file, as it's not yet considered stable at this point. Once the linker
is finalized will these declaration function be included into the golden
file.
PR Close#39518
This commit implements partial code generation for directives, which
will be transformed by the linker plugin to fully AOT compiled code in
follow-up work.
PR Close#39518
When registering an NgModule based on its id, all transitively imported
NgModules are also registered. This commit introduces a visited set to
avoid traversing into NgModules that are reachable from multiple import
paths multiple times.
Fixes#39487
PR Close#39514
This commit has a small refactor of some methods in create_url_tree.ts
and adds some test cases, including two that will fail at the moment but
should pass. A follow-up commit will make use of the refactorings to fix
the test with minimal changes.
PR Close#39456
Currently expressions `$event.foo()` and `this.$event.foo()`, as well as `$any(foo)` and
`this.$any(foo)`, are treated as the same expression by the compiler, because `this` is considered
the same implicit receiver as when the receiver is omitted. This introduces the following issues:
1. Any time something called `$any` is used, it'll be stripped away, leaving only the first parameter.
2. If something called `$event` is used anywhere in a template, it'll be preserved as `$event`,
rather than being rewritten to `ctx.$event`, causing the value to undefined at runtime. This
applies to listener, property and text bindings.
These changes resolve the first issue and part of the second one by preserving anything that
is accessed through `this`, even if it's one of the "special" ones like `$any` or `$event`.
Furthermore, these changes only expose the `$event` global variable inside event listeners,
whereas previously it was available everywhere.
Fixes#30278.
PR Close#39323
This commit updates the docs for the `tView.preOrderHooks` and `tView.preOrderCheckHooks` TView
fields. Current docs are not up-to-date as it was pointed out in #39439.
Closes#39439.
PR Close#39497
Close#39296
Fix an issue that `markDirty()` will not trigger change detection.
The case is for example we have the following component.
```
export class AppComponent implements OnInit {
constructor(private router: Router) {}
ngOnInit() {
this.router.events
.pipe(filter((e) => e instanceof NavigationEnd))
.subscribe(() => ɵmarkDirty(this));
}
}
export class CounterComponent implements OnInit, OnDestroy {
ngOnInit() {
this.countSubject.pipe(takeUntil(this.destroy)).subscribe((count) => {
this.count = count;
ɵmarkDirty(this);
});
}
```
Then the app navigate from `AppComponent` to `CounterComponent`,
so there are 2 `markDirty()` call at in a row.
The `1st` call is from `AppComponent` when router changed, the
`2nd` call is from `CounterComponent.ngOnInit()`.
And the `markDirty()->scheduleTick()` code look like this
```
function scheduleTick(rootContext, flags) {
const nothingScheduled = rootContext.flags === 0 /* Empty */;
rootContext.flags |= flags;
if (nothingScheduled && rootContext.clean == _CLEAN_PROMISE) {
rootContext.schedule(() => {
...
if (rootContext.flags & RootContextFlags.DetectChanges)
rootContext.flags &= ~RootContextFlags.DetectChanges;
tickContext();
rootContext.clean = _CLEAN_PROMISE;
...
});
```
So in this case, the `1st` markDirty() will
1. set rootContext.flags = 1
2. before `tickContext()`, reset rootContext.flags = 0
3. inside `tickContext()`, it will call `CounterComponent.ngOnint()`,
so the `2nd` markDirty() is called.
4. and the `2nd` scheduleTick is called, `nothingScheduled` is true,
but rootContext.clean is not `_CLEAN_PROMISE` yet, since the `1st` markDirty tick
is still running.
5. So nowhere will reset the `rootContext.flags`.
6. then in the future, any other `markDirty()` call will not trigger the tick, since
`nothingScheduled` is always false.
So `nothingScheduled` means no tick is scheduled, `rootContext.clean === _CLEAN_PROMISE`
means no tick is running.
So we should set the flags to `rootContext` only when `no tick is scheudled or running`.
PR Close#39316
Angular-internal type definitions for Trusted Types were added in #39211.
When compiled using the Closure compiler with certain optimization
flags, identifiers from these type definitions (such as createPolicy)
are currently uglified and renamed to shorter strings. This causes
Angular applications compiled in this way to fail to create a Trusted
Types policy, and fall bock to using strings.
To fix this, mark the internal Trusted Types definitions as declarations
using the "declare" keyword. Also convert types to interfaces, for
the reasons explained in https://ncjamieson.com/prefer-interfaces/
PR Close#39471
adds RuntimeError and code enum to improve debugging experience
refactor ExpressionChangedAfterItHasBeenCheckedError to code NG0100
refactor CyclicDependency to code NG0200
refactor No Provider to code NG0201
refactor MultipleComponentsMatch to code NG0300
refactor ExportNotFound to code NG0301
refactor PipeNotFound to code NG0302
refactor BindingNotKnown to code NG0303
refactor NotKnownElement to code NG0304
PR Close#39188
Currently `i18n` attributes are treated the same no matter if they have data bindings or not. This
both generates more code since they have to go through the `ɵɵi18nAttributes` instruction and
prevents the translated attributes from being injected using the `@Attribute` decorator.
These changes makes it so that static translated attributes are treated in the same way as regular
static attributes and all other `i18n` attributes go through the old code path.
Fixes#38231.
PR Close#39408
This commit removes a workaround to calculate the `expandoStartIndex` value. That workaround was needed
because the `expandoStartIndex` was updated previously, so it pointed at the wrong location. The problem
was fixed in PR #39301 and the workaround is no longer needed.
PR Close#39416
In production mode, the `ngDevMode` global may not have been declared.
This is typically not a problem, as optimizers should have removed all
usages of the `ngDevMode` variables. This does however require the
bundler/optimizer to have been configured in a certain way, as to allow
for `ngDevMode` guarded code to be removed.
As an example, Terser can be configured to remove the `ngDevMode`
guarded code using the following configuration:
```js
const terserOptions = {
// ...
compress: {
// ...
global_defs: require('@angular/compiler-cli').GLOBAL_DEFS_FOR_TERSER,
}
}
```
(Taken from https://github.com/angular/angular/issues/31595#issuecomment-519129090)
If this is not done, however, the bundle should still work (albeit with
larger code size due to missed tree-shaking opportunities). This commit
adds a check for whether `ngDevMode` has been declared, as it is a
top-level statement that executes before `ngDevMode` has been initialized.
Fixes#31595
PR Close#39415
Runtime i18n logic doesn't distinguish `<ng-content>` tag placeholders and regular element tag
placeholders in i18n messages, so there is no need to have a special marker for projection-based
placeholders and element markers can be used instead.
PR Close#39172
group together similar error messages as part of error code efforts
ProviderNotFound & NodeInjector grouped into throwProviderNotFoundError
Cyclic dependency errors grouped into throwCyclicDependencyError
PR Close#39251
`TNode.insertBeforeIndex` is only populated when i18n is present. This
change puts all code which reads `insertBeforeIndex` behind a
dynamically loaded functions which are set only when i18n code executes.
PR Close#39301
The `ExpandoInstructions` was unnecessarily convoluted way to solve the
problem of calling the `HostBindingFunction`s on components and
directives. The code was complicated and hard to fallow.
The replacement is a simplified way to achieve the same thing, which
is also more efficient in space and speed.
PR Close#39301
`expandoInstructions` uses negative numbers by `-x`. This has lead to
issues in the paste as `-0` is processed as float rather than integer
leading to de-optimization.
PR Close#39233
IMPORTANT: `HEADER_OFFSET` should only be refereed to the in the `ɵɵ*` instructions to translate
instruction index into `LView` index. All other indexes should be in the `LView` index space and
there should be no need to refer to `HEADER_OFFSET` anywhere else.
PR Close#39233
- Made `*OpCodes` array branded for safer type checking.
- Simplify `I18NRemoveOpCodes` encoding.
- Broke out `IcuCreateOpCodes` from `I18nMutableOpCodes`.
PR Close#39233
`COMMENT_MARKER` is a generic name which does not make it obvious that
it is used for ICU use case. `ICU_MARKER` is more explicit as it is used
exclusively with ICUs.
PR Close#39233
When looking at `TView` debug template only Element nodes were displayed
as `TNode.Element` was used for both `RElement` and `RText`.
Additionally no text was stored in `TNode.value`. The result was that
the whole template could not be reconstructed. This refactoring creates
`TNodeType.Text` and store the text value in `TNode.value`.
The refactoring also changes `TNodeType` into flag-like structure make
it more efficient to check many different types at once.
PR Close#39233
Remove casting where we stored `TIcu` in `TNode.tagName` which was of
type `string` rather than `TIcu'. (renamed to `TNode.value` in previous
commit.)
PR Close#39233
Before this refactoring/fix the ICU would store the current selected
index in `TView`. This is incorrect, since if ICU is in `ngFor` it will
cause issues in some circumstances. This refactoring properly moves the
state to `LView`.
closes#37021closes#38144closes#38073
PR Close#39233
`TemplateFixture` used to have positional parameters and many tests got
hard to read as number of parameters reach 10+ with many of them `null`.
This refactoring changes `TemplateFixture` to take named parameters
which improves usability and readability in tests.
PR Close#39233
Use the bypass-specific Trusted Types policy for automatically upgrade
any values from custom sanitizers or the bypassSecurityTrust functions
to a Trusted Type. Update tests to reflect the new behavior.
PR Close#39218
When an application uses a custom sanitizer or one of the
bypassSecurityTrust functions, Angular has no way of knowing whether
they are implemented in a secure way. (It doesn't even know if they're
introduced by the application or by a shady third-party dependency.)
Thus using Angular's main Trusted Types policy to bless values coming
from these two sources would undermine the security that Trusted Types
brings.
Instead, introduce a Trusted Types policy called angular#unsafe-bypass
specifically for blessing values from these sources. This allows an
application to enforce Trusted Types even if their application uses a
custom sanitizer or the bypassSecurityTrust functions, knowing that
compromises to either of these two sources may lead to arbitrary script
execution. In the future Angular will provide a way to implement
custom sanitizers in a manner that makes better use of Trusted Types.
PR Close#39218
Make Angular's HTML sanitizer return a TrustedHTML, as its output is
trusted not to cause XSS vulnerabilities when used in a context where a
browser may parse and evaluate HTML. Also update tests to reflect the
new behaviour.
PR Close#39218
Sanitizers in Angular currently return strings, which will then
eventually make their way down to the DOM, e.g. as the value of an
attribute or property. This may cause a Trusted Types violation. As a
step towards fixing that, make it possible to return Trusted Types from
the SanitizerFn interface, which represents the internal sanitization
pipeline. DOM renderer interfaces are also updated to reflect the fact
that setAttribute and setAttributeNS must be able to accept Trusted
Types.
PR Close#39218
When reading globals such as `ngDevMode` the read should be guarded by `typeof ngDevMode` otherwise it will throw if not
defined in `"use strict"` mode.
PR Close#36055
getCheckNoChangesMode was discovered to be unclear as to the purpose of
it. This refactor is a simple renaming to make it much clearer what that
method and property does.
PR Close#39277
Angular treats constant values of attributes and properties in templates
as secure. This means that these values are not sanitized, and are
instead passed directly to the corresponding setAttribute or setProperty
function. In cases where the given attribute or property is
security-sensitive, this causes a Trusted Types violation.
To address this, functions for promoting constant strings to each of the
three Trusted Types are introduced to Angular's private codegen API. The
compiler is updated to wrap constant strings with calls to these
functions as appropriate when constructing the `consts` array. This is
only done for security-sensitive attributes and properties, as
classified by Angular's dom_security_schema.
PR Close#39211
The @types/trusted-types type definitions are currently imported in
types.d.ts, which causes them to eventually be imported in core.d.ts.
This forces anyone compiling against @angular/core to provide the
@types/trusted-types package in their compilation unit, which we don't
want.
To address this, get rid of the @types/trusted-types and instead import
a minimal version of the Trusted Types type definitions directly into
Angular's codebase.
Update the existing references to Trusted Types to point to the new
definitions.
PR Close#39211
This commit updates micro benchmarks to use relative path to Ivy runtime code. Keeping absolute
locations caused issues with build optimizer that retained certain symbols and they appeared in the
output twice.
PR Close#39142
This commit adds micro benchmarks to run micro benchmarks for i18n-related logic in the
following scenarios:
- i18n static attributes
- i18n attributes with interpolations
- i18n blocks of static text
- i18n blocks of text + interpolations
- simple ICUs
- nested ICUs
First 4 scenarios also have baseline scenarios (non-i18n) so that we can compare i18n perf with
non-i18n logic.
PR Close#39142
Add a schematic to update users to the new v11 `initialNavigation`
options for `RouterModule`. This replaces the deprecated/removed
`true`, `false`, `legacy_disabled`, and `legacy_enabled` options
with the newer `enabledBlocking` and `enabledNonBlocking` options.
PR Close#36926
Address a Trusted Types violation that occurs in createNamedArrayType
during development mode. Instead of passing strings directly to "new
Function", use the Trusted Types compatible function constructor exposed
by the Trusted Types policy.
PR Close#39209
Chrome currently does not support passing TrustedScript to the Function
constructor, and instead fails with a Trusted Types violation when
called. As the Function constructor is used in a handful of places
within Angular, such as in the JIT compiler and named_array_type, the
workaround proposed on the following page is implemented:
https://github.com/w3c/webappsec-trusted-types/wiki/Trusted-Types-for-function-constructor
To be precise, it constructs a string representing an anonymous function
in a way that is equivalent to what the Function constructor does,
promotes it to a TrustedScript and then calls eval.
To facilitate backwards compatibility, new Function is used directly in
environments that do not support Trusted Types.
PR Close#39209
This commit removes a workaround previously used for IE 9 and 10 to identify whether InjectableDef
was defined on a given class instance. Since support for IE 9 and 10 is removed, this fallback is
no longer needed.
PR Close#39090
This commit updates core tests and removes the code needed to support IE 9 and IE 10 only.
The code is no longer needed since IE 9 and IE 10 support is removed in v11.
PR Close#39090
When Angular is used in an environment that enforces Trusted Types, the
inert DOM builder raises a Trusted Types violation due to its use of
DOMParser and element.innerHTML with plain strings. Since it is only
used internally (in the HTML sanitizer and for i18n ICU parsing), we
update it to use Angular's Trusted Types policy to promote the provided
HTML to TrustedHTML.
PR Close#39208
Add a module that provides a Trusted Types policy for use internally by
Angular. The policy is created lazily and stored in a module-local
variable. For now the module does not allow configuring custom policies
or policy names, and instead creates its own policy with 'angular' as a
fixed policy name. This is to more easily support tree-shakability.
Helper functions for unsafely converting strings to each of the three
Trusted Types are also introduced, with documentation that make it clear
that their use requires a security review. When Trusted Types are not
available, these helper functions fall back to returning strings.
PR Close#39207
Adds a migration that finds all imports and calls to the deprecated `async` function from
`@angular/core/testing` and replaces them with `waitForAsync`.
These changes also move a bit of code out of the `Renderer2` migration so that it can be reused.
PR Close#39212
Removes `ViewEncapsulation.Native` which has been deprecated for several major versions.
BREAKING CHANGES:
* `ViewEncapsulation.Native` has been removed. Use `ViewEncapsulation.ShadowDom` instead. Existing
usages will be updated automatically by `ng update`.
PR Close#38882
Updates to rules_nodejs 2.2.0. This is the first major release in 7 months and includes a number of features as well
as breaking changes.
Release notes: https://github.com/bazelbuild/rules_nodejs/releases/tag/2.0.0
Features of note for angular/angular:
* stdout/stderr/exit code capture; this could be potentially be useful
* TypeScript (ts_project); a simpler tsc rule that ts_library that can be used in the repo where ts_library is too
heavy weight
Breaking changes of note for angular/angular:
* loading custom rules from npm packages: `ts_library` is no longer loaded from `@npm_bazel_typescript//:index.bzl`
(which no longer exists) but is now loaded from `@npm//@bazel/typescript:index.bzl`
* with the loading changes above, `load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")` is
no longer needed in the WORKSPACE which also means that yarn_install does not need to run unless building/testing
a target that depends on @npm. In angular/angular this is a minor improvement as almost everything depends on @npm.
* @angular/bazel package is also updated in this PR to support the new load location; Angular + Bazel users that
require it for ng_package (ng_module is no longer needed in OSS with Angular 10) will need to load from
`@npm//@angular/bazel:index.bzl`. I investigated if it was possible to maintain backward compatability for the old
load location `@npm_angular_bazel` but it is not since the package itself needs to be updated to load from
`@npm//@bazel/typescript:index.bzl` instead of `@npm_bazel_typescript//:index.bzl` as it depends on ts_library
internals for ng_module.
* runfiles.resolve will now throw instead of returning undefined to match behavior of node require
Other changes in angular/angular:
* integration/bazel has been updated to use both ng_module and ts_libary with use_angular_plugin=true.
The latter is the recommended way for rules_nodejs users to compile Angular 10 with Ivy. Bazel + Angular ViewEngine is
supported with @angular/bazel <= 9.0.5 and Angular <= 8. There is still Angular ViewEngine example on rules_nodejs
https://github.com/bazelbuild/rules_nodejs/tree/stable/examples/angular_view_engine on these older versions but users
that want to update to Angular 10 and are on Bazel must switch to Ivy and at that point ts_library with
use_angular_plugin=true is more performant that ng_module. Angular example in rules_nodejs is configured this way
as well: https://github.com/bazelbuild/rules_nodejs/tree/stable/examples/angular. As an aside, we also have an
example of building Angular 10 with architect() rule directly instead of using ts_library with angular plugin:
https://github.com/bazelbuild/rules_nodejs/tree/stable/examples/angular_bazel_architect.
NB: ng_module is still required for angular/angular repository as it still builds ViewEngine & @angular/bazel
also provides the ng_package rule. ng_module can be removed in the future if ViewEngine is no longer needed in
angular repo.
* JSModuleInfo provider added to ng_module. this is for forward compat for future rules_nodejs versions.
PR Close#39182
This is a roll forward of #39082, using `ts.createIdentifier(`'legacy'`)` as a cross-version compatible way of making
a single quoted string literal.
Migrated code now uses single quotes, which is in line with the default linting options, so there is no lint error after
migration.
PR Close#39102
As of #32671, the type of `AbstractControl.parent` can be null which can cause
compilation errors in existing apps. These changes add a migration that will append
non-null assertions to existing unsafe accesses.
````
// Before
console.log(control.parent.value);
// After
console.log(control.parent!.value);
```
The migration also tries its best to avoid cases where the non-null assertions aren't
necessary (e.g. if the `parent` was null checked already).
PR Close#39009
Updates to rules_nodejs 2.2.0. This is the first major release in 7 months and includes a number of features as well
as breaking changes.
Release notes: https://github.com/bazelbuild/rules_nodejs/releases/tag/2.0.0
Features of note for angular/angular:
* stdout/stderr/exit code capture; this could be potentially be useful
* TypeScript (ts_project); a simpler tsc rule that ts_library that can be used in the repo where ts_library is too
heavy weight
Breaking changes of note for angular/angular:
* loading custom rules from npm packages: `ts_library` is no longer loaded from `@npm_bazel_typescript//:index.bzl`
(which no longer exists) but is now loaded from `@npm//@bazel/typescript:index.bzl`
* with the loading changes above, `load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")` is
no longer needed in the WORKSPACE which also means that yarn_install does not need to run unless building/testing
a target that depends on @npm. In angular/angular this is a minor improvement as almost everything depends on @npm.
* @angular/bazel package is also updated in this PR to support the new load location; Angular + Bazel users that
require it for ng_package (ng_module is no longer needed in OSS with Angular 10) will need to load from
`@npm//@angular/bazel:index.bzl`. I investigated if it was possible to maintain backward compatability for the old
load location `@npm_angular_bazel` but it is not since the package itself needs to be updated to load from
`@npm//@bazel/typescript:index.bzl` instead of `@npm_bazel_typescript//:index.bzl` as it depends on ts_library
internals for ng_module.
* runfiles.resolve will now throw instead of returning undefined to match behavior of node require
Other changes in angular/angular:
* integration/bazel has been updated to use both ng_module and ts_libary with use_angular_plugin=true.
The latter is the recommended way for rules_nodejs users to compile Angular 10 with Ivy. Bazel + Angular ViewEngine is
supported with @angular/bazel <= 9.0.5 and Angular <= 8. There is still Angular ViewEngine example on rules_nodejs
https://github.com/bazelbuild/rules_nodejs/tree/stable/examples/angular_view_engine on these older versions but users
that want to update to Angular 10 and are on Bazel must switch to Ivy and at that point ts_library with
use_angular_plugin=true is more performant that ng_module. Angular example in rules_nodejs is configured this way
as well: https://github.com/bazelbuild/rules_nodejs/tree/stable/examples/angular. As an aside, we also have an
example of building Angular 10 with architect() rule directly instead of using ts_library with angular plugin:
https://github.com/bazelbuild/rules_nodejs/tree/stable/examples/angular_bazel_architect.
NB: ng_module is still required for angular/angular repository as it still builds ViewEngine & @angular/bazel
also provides the ng_package rule. ng_module can be removed in the future if ViewEngine is no longer needed in
angular repo.
* JSModuleInfo provider added to ng_module. this is for forward compat for future rules_nodejs versions.
@josephperrott, this touches `packages/bazel/src/external.bzl` which will make the sync to g3 non-trivial.
PR Close#37727
This updates the migration to align with the style guide and work with default lint rules. It avoids a lint error on
newly migrated projects and fixes a test in the CLI repo.
PR Close#39070
`NodeInjector` is store in expando as a list of values in an array. The
offset constant into the array have been brought together into a single
`NodeInjectorOffset` enum with better documentation explaining their usage.
PR Close#38707
This change makes `getPreviousOrParentTNode` return `TNode|null` (rather
than just `TNode`) which is more reflective of the reality. The
`getPreviousOrParentTNode` can be `null` upon entering the `LView`.
PR Close#38707
`TNodeType.View` was created to support inline views. That feature did
not materialize and we have since removed the instructions for it, leave
an unneeded `TNodeType.View` which was still used in a very
inconsistent way. This change no longer created `TNodeType.View` (and
there will be a follow up chang to completely remove it.)
Also simplified the mental model so that `LView[HOST]`/`LView[T_HOST]`
always point to the insertion location of the `LView`.
PR Close#38707
Host `TNode` was passed into `getOrCreateTNode` just so that we can
compute weather or not we are a root node. This was needed because
`previousOrParentTNode` could have `TNode` from `TView` other then
current `TView`. This is confusing mental model. Previous change
ensured that `previousOrParentTNode` must always be part of `TView`,
which enabled this change to remove the unneeded argument.
PR Close#38707
`previousOrParentTNode` stores current `TNode`. Due to inconsistent
implementation the value stored would sometimes belong to the current
`TView` and sometimes to the parent. We have extra logic which accounts
for it. A better solution is to just ensure that `previousOrParentTNode`
always belongs to current `TNode`. This simplifies the mental model
and cleans up some code.
PR Close#38707
The default value for `relativeLinkResolution` is changing from 'legacy' to 'corrected'.
This migration updates `RouterModule` configurations that use the default value to
now specifically use 'legacy' to prevent breakages when updating.
PR Close#38698
There is an inconsistency in overrideProvider behaviour. Testing documentation says
(https://angular.io/guide/testing-components-basics#createcomponent) that all override...
methods throw error if TestBed is already instantiated. However overrideProvider doesn't throw any error, but (same as
other override... methods) doesn't replace providers if TestBed is instantiated. Add TestBed instantiation check to
overrideProvider method to make it consistent.
BREAKING CHANGE:
If you call `TestBed.overrideProvider` after TestBed initialization, provider overrides are not applied. This
behavior is consistent with other override methods (such as `TestBed.overrideDirective`, etc) but they
throw an error to indicate that, when the check was missing in the `TestBed.overrideProvider` function.
Now calling `TestBed.overrideProvider` after TestBed initialization also triggers an
error, thus there is a chance that some tests (where `TestBed.overrideProvider` is
called after TestBed initialization) will start to fail and require updates to move `TestBed.overrideProvider` calls
before TestBed initialization is completed.
Issue mentioned here: https://github.com/angular/angular/issues/13460#issuecomment-636005966
Documentation: https://angular.io/guide/testing-components-basics#createcomponent
PR Close#38717
This commit updates several import statements in the core package to decrease the number of
cycles detected by the dependency checker tool.
PR Close#38805
In #38227 the signatures of `navigateByUrl` and `createUrlTree` were updated to exclude unsupported
properties from their `extras` parameter. This migration looks for the relevant method calls that
pass in an `extras` parameter and drops the unsupported properties.
**Before:**
```
this._router.navigateByUrl('/', {skipLocationChange: false, fragment: 'foo'});
```
**After:**
```
this._router.navigateByUrl('/', {
/* Removed unsupported properties by Angular migration: fragment. */
skipLocationChange: false
});
```
These changes also move the method call detection logic out of the `Renderer2` migration and into
a common place so that it can be reused in other migrations.
PR Close#38825
This commit creates a sample router test application to introduce the
symbol tests. It serves as a guard to ensure that any future work on the
router package does not unintentionally increase the payload size.
PR Close#38714