When translated content was projected, all of the content was reappended, even the placeholders that had been removed in the translation.
To avoid that we added a new flag on `TNode` that specifies that a node is detached, in which case it should be ignored by the projection.
FW-1319 #resolve
PR Close#30783
- Removes ɵɵelementProperty instruction
- Updates tests that were using it
- NOTE: There is one test under `render3/integration_spec.ts` that is commented out, and needs to be reviewed. Basically, I could not find a good why to test what it was doing, because it was doing things that I am not sure we could generate in an acceptance test.
PR Close#30645
Added a new syntax for projections (`¤` will represent `ng-content` nodes) so that we can treat them specifically.
When we enter an i18n block with the instruction `i18nStart`, a new `delayProjection` variable is set to true to prevent the instruction `projection` from projecting the nodes. Once we reach the `i18nEnd` instruction and encounter a projection in the translation we will project its nodes.
If a projection was removed from a translation, then its nodes won't be projected at all.
The variable `delayProjection` is restored to `false` at the end of `i18nEnd` so that it doesn't stop projections outside of i18n blocks.
FW-1261 #resolve
PR Close#30782
We used to ignore empty strings for optimization purposes, but it turns out that empty strings are also valid values for ICU cases and we shouldn't ignore those.
FW-1290 #resolve
PR Close#30846
Some HTML attributes don't correspond to their DOM property name, in which
case the runtime will apply the appropriate transformation when assigning
a property using its attribute name. One example of this is the `for`
attribute, for which the DOM property is named `htmlFor`.
The type-checking machinery in ngtsc must also take this mapping into
account, as it generates type-check code in which unclaimed property bindings
are assigned to properties of (subtypes of) `HTMLElement`.
Fixes#30607
Fixes FW-1327
PR Close#30675
Before this change we would systematically call LQueries.clone() when executting
elementStart / elementContainerStart instructions. This was often unnecessary as
LQueries can be mutated under 2 conditions only:
- we are crossing an element that has directives with content queries
(new queries must be added);
- we are descending into element hierarchy (creating a child element of an existing element)
and the current LQueries object is tracking shallow queries (shallow queries are removed).
With this PR LQueires.clone() is only done when needed and this gratelly reduces number
of LQueries object created: in the "expanding rows" benchmark number of allocated
(and often GCed just after!) LQueries is reduced from ~100k -> ~35k. This represents
over 1MB of memory that is not allocated.
PR Close#30664
Projecting bare ICU expressions failed because we would assume that component's content nodes would be projected later and doing so at that point would be wasteful. But ICU nodes are handled independently and should be inserted immediately because they will be ignored by projections.
FW-1348 #resolve
PR Close#30696
Inside of `DebugNode.queryAll` we walk through all of the descendants of the node that we're querying against, however the logic that walks sideways through a node siblings also applies to the root node. This means that eventually we'll match against its nodes as well which will give us invalid results. These changes add an extra check to ensure that we aren't matching against the siblings of the root node.
This PR resolves FW-1353.
PR Close#30788
With View engine it was possible to declare multiple projection
definitions and to programmatically project nodes into the slots.
e.g.
```html
<ng-content></ng-content>
<ng-content></ng-content>
```
Using `ViewContainerRef#createComponent` allowed projecting
nodes into one of the projection defs (through index)
This no longer works with Ivy as the `projectionDef` instruction only
retrieves a list of selectors instead of also retrieving entries for
reserved projection slots which appear when using the default
selector multiple times (as seen above).
In order to fix this issue, the Ivy compiler now passes all
projection slots to the `projectionDef` instruction. Meaning that
there can be multiple projection slots with the same wildcard
selector. This allows multi-slot projection as seen in the
example above, and it also allows us to match the multi-slot node
projection order from View Engine (to avoid breaking changes).
It basically ensures that Ivy fully matches the View Engine behavior
except of a very small edge case that has already been discussed
in FW-886 (with the conclusion of working as intended).
Read more here: https://hackmd.io/s/Sy2kQlgTE
PR Close#30561
Currently with Ivy, `ModuleWithProvider` providers are processed in order
of declaration in the `NgModule` imports. This technically makes makes
sense but is a potential breaking change as `ModuleWithProvider` providers
are processed after all imported modules in View Engine.
In order to keep the behavior of View Engine, the `r3_injector` is updated
to no longer process `ModuleWithProvider` providers egarly.
Resolves FW-1349
PR Close#30688
The "async" around a couple tests was removed because of the merge conflict in one of the previous commits (80394ce08b). This change restores missing "async"s.
PR Close#30762
fix(@schematics/angular): TypeScript related migrations should cater for BOM
In the CLI `UpdateRecorder` methods such as `insertLeft`, `remove` etc.. accepts positions which are not offset by a BOM. This is because when a file has a BOM a different recorder will be used https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/src/tree/recorder.ts#L72 which caters for an addition offset/delta.
The main reason for this is that when a developer is writing a schematic they shouldn't need to compute the offset based if a file has a BOM or not and is handled out of the box.
Example
```ts
recorder.insertLeft(5, 'true');
```
However this is unfortunate in the case if a ts SourceFile is used and one uses `getWidth` and `getStart` method they will already be offset by 1, which at the end it results in a double offset and hence the problem.
Fixes#30713
PR Close#30719
Two issues with DebugNode/DebugElement in Ivy were causing problems in user
tests.
1. The DebugNodes returned by Ivy were not actually instances of DebugNode.
This was due to an issue with the Ivy switch logic in debug_node.ts.
The declaration of the exported DebugNode reference was set to
`DebugNode__PRE_R3__ as any`. The cast prevented the Ivy switch transform
from detecting this as a switchable declaration. The transform cannot handle
arbitrary syntax, and exports *must* be of the form "const x = y__PRE_R3__;"
or they will not work. The cast to any in this case was not needed, so this
commit removes it.
2. DebugNodes returned by Ivy multiple times for the same element were not
reference-identical. This was previously considered a minor breaking change
in Ivy, but testing has shown that users depend on referential equality of
DebugNodes. This commit caches a DebugNode on a DOM node when first creating
it, to allow returning the same instance in subsequent operations.
PR Close#30756
Due to sanitization being stored as a temp/global value between
instructions, unit tests randomly failed because one test failed
to clean up its temporary value. This patch fixes this issue.
`i18nAttributes` instructions always occur after the element instruction. This means that we need to treat `i18n-` attributes differently.
By defining a specific `AttributeMarker` we can ensure that we won't trigger directive inputs with untranslated attribute values.
FW-1332 #resolve
PR Close#30402
Changed runtime i18n to define attributes with bindings, or matching directive inputs/outputs as element properties as we are supposed to do in Angular.
This PR fixes the issue where directive inputs wouldn't be trigged.
FW-1315 #resolve
PR Close#30402
Commit 0df719a46 introduced registration of NgModules with ids when compiled
with AOT, and f74373f2d corrected the timing to avoid issues with tree
shaking. Neither of these approaches were correct.
This commit fixes the timing to match View Engine and avoid tree shaking
issues, as well as fixes a bug with the registration of imported module ids.
A new Ivy-only test is added which verifies that modules get registered
correctly under real-world conditions.
PR Close#30706
Plural ICU expressions depend on the locale (different languages have different plural forms). Until now the locale was hard coded as `en-US`.
For compatibility reasons, if you use ivy with AOT and bootstrap your app with `bootstrapModule` then the `LOCALE_ID` token will be set automatically for ivy, which is then used to get the correct plural form.
If you use JIT, you need to define the `LOCALE_ID` provider on the module that you bootstrap.
For `TestBed` you can use either `configureTestingModule` or `overrideProvider` to define that provider.
If you don't use the compat mode and start your app with `renderComponent` you need to call `ɵsetLocaleId` manually to define the `LOCALE_ID` before bootstrap. We expect this to change once we start adding the new i18n APIs, so don't rely on this function (there's a reason why it's a private export).
PR Close#29249
This patch is one of the final patches to refactor the styling algorithm
to be more efficient, performant and less complex.
This patch enables sanitization support for map-based and prop-based
style bindings.
PR Close#30667
Instead of linking to a markdown file explaining what the migration warnings
are about, we should link to the deprecation guide which now also contains
an entry for that schematic. This makes the deprecation explanations
consistent and more centralized.
PR Close#30702
This fixes a collision between #30639 and #30543 where the latter added
usages of @ViewChild without the static flag present, but the former
made the flag required.
PR Close#30666
This commit makes the static flag on @ViewChild and @ContentChild required.
BREAKING CHANGE:
In Angular version 8, it's required that all @ViewChild and @ContentChild
queries have a 'static' flag specifying whether the query is 'static' or
'dynamic'. The compiler previously sorted queries automatically, but in
8.0 developers are required to explicitly specify which behavior is wanted.
This is a temporary requirement as part of a migration; see
https://angular.io/guide/static-query-migration for more details.
@ViewChildren and @ContentChildren queries are always dynamic, and so are
unaffected.
PR Close#30639
This patch in the second runtime change which refactors how styling
bindings work in Angular. This patch refactors how map-based
`[style]` and `[class]` bindings work using a new algorithm which
is faster and less complex than the former one.
This patch is a follow-up to an earlier refactor which enabled
support for prop-based `[style.name]` and `[class.name]`
bindings (see f03475cac8).
PR Close#30543
This is a new feature of the Ivy TestBed.
A common user pattern is to test one component with another. This is
commonly done by creating a `TestFixture` component which exercises the
main component under test.
This pattern is more difficult if the component under test is declared in an
NgModule but not exported. In this case, overriding the module is necessary.
In g3 (and View Engine), it's possible to use an NgSummary to override the
recompilation of a component, and depend on its AOT compiled factory. The
way this is implemented, however, specifying a summary for a module
effectively overrides much of the TestBed's other behavior. For example, the
following is legal:
```typescript
TestBed.configureTestingModule({
declarations: [FooCmp, TestFixture],
imports: [FooModule],
aotSummaries: [FooModuleNgSummary],
});
```
Here, `FooCmp` is declared in both the testing module and in the imported
`FooModule`. However, because the summary is provided, `FooCmp` is not
compiled within the context of the testing module, but _is_ made available
for `TestFixture` to use, even if it wasn't originally exported from
`FooModule`.
This pattern breaks in Ivy - because summaries are a no-op, this amounts
to a true double declaration of `FooCmp` which raises an error.
Fixing this in user code is possible, but is difficult to do in an
automated or backwards compatible way. An alternative solution is
implemented in this PR.
This PR attempts to capture the user intent of the following previously
unsupported configuration:
```typescript
TestBed.configureTestingModule({
declarations: [FooCmp, TestFixture],
imports: [FooModule],
});
```
Note that this is the same as the configuration above in Ivy, as the
`aotSummaries` value provided has no effect.
The user intent here is interpreted as follows:
1) `FooCmp` is a pre-existing component that's being used in the test
(via import of `FooModule`). It may or may not be exported by this
module.
2) `FooCmp` should be part of the testing module's scope. That is, it
should be visible to `TestFixture`. This is because it's listed in
`declarations`.
This feature effectively makes the `TestBed` testing module special. It's
able to declare components without compiling them, if they're already
compiled (or configured to be compiled) in the imports. And crucially, the
behavior matches the first example with the summary, making Ivy backwards
compatible with View Engine for tests that use summaries.
PR Close#30578
Depending on which placeholders the translation uses, there are some legitimate cases where we might not use all placeholder replacements in `i18nPostprocess`. For example if some of the placeholders of the original messages have been removed in the translation.
FW-1312 #resolve
PR Close#30632
8479cb4233 updated the static-query migration
to refer to the new guide on AIO. Unfortunately these URLs are currently not
valid as the guide is only available on `next.angular.io` right now. In order to
make the link work permanently (e.g. if we eventually remove the guide in future
major versions), we use the permalink from the `v8` subdomain.
PR Close#30649
DEPRECATION:
Angular previously has supported an integration with the Web Tracing
Framework (WTF) for performance testing of Angular applications. This
integration has not been maintained and likely does not work for the
majority of Angular applications today. As a result, we are deprecating
the integration in Angular version 8.
This deprecation covers the following public APIs:
* `WtfScopeFn`
* `wtfCreateScope`
* `wtfStartTimeRange`
* `wtfEndTimeRange`
* `wtfLeave`
FW-1338 #resolve
PR Close#30642
Currently if a project has source-files with syntax failures and the migration
has been started on a broken project, we silently migrate *as much as possible*,
but never notify the developer that the project was in a broken state and that
he can re-run the migration after the failures are fixed.
Additionally the template strategy does not need to exit gracefully if it detects
Angular semantic diagnostics on generated files (template type checking). These
diagnostics are not relevant for the query timing analysis.
PR Close#30628
We are removing the prompt for the `static-query` migration and make the
template strategy the migration strategy for the migration. The usage
strategy is good for best-practices, but for now we want to ensure that
the migration is a seamless as possible and that is only achievable my
re-using the same logic that View Engine uses for determining the
timing of a query.
PR Close#30628
Prior to this change a component was considered unresolved (i.e. having dynamic resources that should be loaded, like external template or stylesheets) even if template override was provided as an empty string (for example, via TestBed.overrideTemplateUsingTestingModule call). This commit fixes the condition that previously treated empty string as an absent template value.
PR Close#30602
With Ivy, injecting a `ViewContainerRef` for a `<ng-container>` element
results in two comments generated in the DOM. One comment as host
element for the `ElementContainer` and one for the generated `LContainer`
which is needed for the created `ViewContainerRef`.
This is problematic as developers expect the same anchor element for
the `LContainer` and the `ElementContainer` in order to be able to move
the host element of `<ng-container>` without leaving the actual
`LContainer` anchor element at the original location.
This worked differently in View Engine and various applications might
depend on the behavior where the `ViewContainerRef` shares the anchor
comment node with the host comment node of the `<ng-container>`. For
example `CdkTable` from `@angular/cdk` moves around the host element of
a `<ng-container>` and also expects embedded views to be inserted next
to the moved `<ng-container>` host element.
See: f8be5329f8/src/cdk/table/table.ts (L999-L1016)
Resolves FW-1341
PR Close#30611
Prior to this change we processed binding expression (including bindings with pipes) in i18n attributes before we generate update instruction. As a result, slot offsets for pipeBind instructions were calculated incorrectly. Now we perform binding expression processing when we generate "update block" instructions, so offsets are calculated correctly.
PR Close#30573
Currently we try to parse CLI workspace configurations gracefully by
using the native `JSON.parse()` method. This means that the CLI workspace
configuration needs to follow the strict JSON specification because otherwise
the migrations would not be able to find TypeScript configurations in the CLI
project where JSON5 workspace configurations are supported.
In order to handle such workspace configurations, we leverage the JSON
parsing logicfrom the `@angular-devkit/core` which is also used by the CLI.
PR Close#30582
PR #29290 introduced a new `TestBed.get` signature and deprecated the existing one.
This raises a lot of TSLint deprecation warnings in projects using a strict TS config (see #29905 for context), so we are temporarily removing the `@deprecated` annotation in favor of a plain text warning until we properly fix it.
Refs #29905
Fixes FW-1336
PR Close#30514
The `flatten` function used `concat` and `slice` which created a lot of intermediary
object allocations. Because `flatten` is used from query any benchmark which
used query would exhibit high minor GC counts.
PR Close#30468
BREAKING CHANGE
In PR #19558, we fixed a bug in `TestBed.overrideProvider` where
eager providers were not being instantiated correctly. However,
it turned out that since this bug had been around for quite a bit,
many apps were relying on the broken behavior where the providers
would not be instantiated. To assist in the transition, the
`TestBed.deprecatedOverrideProvider` method was temporarily
introduced to mimic the old behavior so that apps would have a
longer time period to migrate their code.
2 years and 3 versions later, it is time to remove the temporary
method. This commit removes `TestBed.deprecatedOverrideProvider`
altogether. Any usages of `TestBed.deprecatedOverrideProvider`
should be replaced with `TestBed.overrideProvider`. This may mean
that providers that were not created before will now be instantiated,
which could mean that your tests need to provide more mocks or stubs
for the dependencies of the newly instantiated providers.
PR Close#30576
There is an encoding issue with using delta `Δ`, where the browser will attempt to detect the file encoding if the character set is not explicitly declared on a `<script/>` tag, and Chrome will find the `Δ` character and decide it is window-1252 encoding, which misinterprets the `Δ` character to be some other character that is not a valid JS identifier character
So back to the frog eyes we go.
```
__
/ɵɵ\
( -- ) - I am ineffable. I am forever.
_/ \_
/ \ / \
== == ==
```
PR Close#30546
Moves all manual render3 view_container_ref tests that use property
bindings to acceptance tests with TestBed.
Two issues surfaced and refer to a difference between Ivy and View
engine:
* Multi-slot projection is not working with Ivy: FW-1331
* ViewContainerRef throws if index is invalid while View Engine clamped index: FW-1330
PR Close#30488
This is the first refactor PR designed to change how styling bindings
(i.e. `[style]` and `[class]`) behave in Ivy. Instead of having a heavy
element-by-element context be generated for each element, this new
refactor aims to use a single context for each `tNode` element that is
examined and iterated over when styling values are to be applied to the
element.
This patch brings this new functionality to prop-based bindings such as
`[style.prop]` and `[class.name]`.
PR Close#30469
Moves most of the tests from `render3/integration_spec` into `acceptance`. Note that there are still a handful of tests left in render3, because we don't have a way of moving all of them to go through `TestBed` since they either have r3-specific assertions or we don't have access to the same APIs as the raw instructions.
PR Close#30461
Ports render3 onDestroy tests over to be acceptance tests. Removes old render3 tests if possible.
Note the onlyInIvy test for one area where Ivy has a different behavior than ViewEngine
PR Close#30445
- Adds inheritance tests for many combinations of directive, component and bare class inheritance
- Adds tests that are failing in ivy, but should work, marks them with `xit` and a TODO.
- Removes render3 unit tests that cover the same things.
PR Close#30442
In View Engine, we would simply ignore host style bindings on template nodes. In Ivy,
we are throwing a "Cannot read length of undefined" error instead. For backwards
compatibility, we should also ignore these bindings rather than blowing up.
PR Close#30498
In View engine it is possible to instantiate a service that that has no
`@Injectable` decorator as long as it satisfies one of:
1) It has no dependencies and so a constructor with no parameters.
This is already supported in Ivy.
2) It has no constructor of its own and sub-classes a service which has
dependencies but has its own `@Injectable` decorator. This second
scenario was broken in Ivy.
In Ivy, previous to this commit, if a class to be instantiated did not have
its own `@Injectable` decorator and did not provide a constructor of
its own, then it would be created using `new` with no arguments -
i.e. falling back to the first scenario.
After this commit Ivy correctly uses the `ngInjectableDef` inherited
from the super-class to provide the `factory` for instantiating the
sub-class.
FW-1314
PR Close#30388
- Moves template ref tests from render3 unit tests to acceptance tests.
- Marks tests testing ivy specific changes as `onlyInIvy`.
- Deletes old render3 unit tests that are no longer necessary
PR Close#30443
Slightly improves the messages for the static-query migration in order
to make the terminal output less verbose but more helpful. Unfortunately
we are limited in what we can print due to the devkit not providing much
utilities for printing good messages from a migration schematic.
PR Close#30458
Currently if something fails in the selected strategy (e.g. AOT failures),
the migration currently accidentally falls back to the test strategy. This
is not helpful as we want to give developers the possibility to re-run
the migration after fixing potential AOT failures.
PR Close#30458
Apparently the devkit logger is not able to properly print
out error objects, so we need to convert them to a string
before in order to make the error visible to the user.
This is not testable without an e2e test that validates the CLI
terminal output.
PR Close#30458
Preserve compatibility with rollup_bundle rule.
Add missing npm dependencies, which are now enforced by the strict_deps plugin in tsc_wrapped
PR Close#30370
Moves most of the r3 change detection tests into `acceptance`. Notes:
* A handful of tests weren't migrated, because they were testing an API that isn't exposed publicly yet.
* The `should throw if bindings in children of current view have changed` and `should NOT throw if bindings in ancestors of current view have changed` tests were removed, because there's not nice way of hitting the same code path with `TestBed` and doing the same assertion as with the raw instructions. I'm open to ideas on how we could do them.
* There were a few tests that assert that the `innerHTML` looks in a particular way. I've switched them to use `textContent`, because Ivy and ViewEngine produce slightly different DOM. The tests were only checking whether the text has changed anyway.
PR Close#30425
Moves all manual render3 property binding tests to
TestBed acceptance tests. Unfortunately three property
binding tests could not be migrated as these rely on
manual Ivy template code that is not supported within
TestBed. These can be revisited as discussed in the
framework team meeting.
PR Close#30426
Moves all manual render3 tests which are located within the
`renderer_factory_spec.ts` file to acceptance tests. A few tests
that use Ivy-specific logic which is not replicable with `TestBed`
remain in the render3 folder (e.g. using `renderTemplate`)
Additionally migrated tests that assert the lifecycles of the
renderer_factory are set to *ivy only* as the lifecycle seems
to be different in Ivy. Tracked with: FW-1320
PR Close#30435
Currently in Ivy `NgModule` registration happens when the class is declared, however this is inconsistent with ViewEngine and requires extra generated code. These changes remove the generated code for `registerModuleFactory`, pass the id through to the `ngModuleDef` and do the module registration inside `NgModuleFactory.create`.
This PR resolves FW-1285.
PR Close#30244
- Moves tests related to the pureFunction instructions from render3 to acceptance tests
- Leaves behind one test for in-template javascript that is not supported syntax yet
PR Close#30406
Moves over the tests from `pipe_spec` into `acceptance`. Note that the two `WrappedValue` tests haven't been moved over, because impure pipes always throw "changed after checked" errors in `TestBed`. This seems to be consistent with ViewEngine.
PR Close#30389
Moves most of the tests in `output_spec` into `acceptance`. Note that one test is left in `render3`, because it's testing mixing in custom logic with instructions which we can't replicate using `TestBed`.
PR Close#30372
Moves all manual `render3` content projection tests that use
the `ɵɵelementProperty` to acceptance tests. Additionally a
few other content projection tests were moved over to
acceptance. Eventually we'll be able to move all remaining
content projection tests to acceptance.
PR Close#30357
This commit moves the delegated constructor detection to a helper
function and also adds more test coverage.
The original code for this came from https://github.com/angular/angular/pull/24156
thanks to @ts2do.
Closes#24156Closes#27267
// FW-1310
PR Close#30368
Currently we always just set the timing to `false` if we aren't
able to analyze a given call expression or new expression. e.g.
```ts
ngOnInit() {
thirdPartyCallSync(() => this.query.doSomething())
}
```
In that case the `thirdPartyCallSync` function comes from the `node_modules`
and is only defined through types while there is no code for the
actual function logic that can be analyzed. This makes it impossible
to tell whether the given call expression actually causes the specified
arrow function to be executed synchronously or not. In order to be able
to make this better, we now peek into the passed arrow function and
check for a synchronous query usage. If so, we set the query timing to
static and mark it as ambiguous. This ensures that the usage strategy is
less "magical" and more correct with third-party code.
Additionally since functions like `setTimeout` are not analyzable but known
to be asynchronous, there is a hard-coded list of known functions which
shouldn't be marked as ambiguous.
Resolves FW-1214. As planned within https://hackmd.io/hPiLWpPlQ4uynC1luIBdfQ
PR Close#30215
Even though we don't run the size-tracking test on CI
right now, we update the golden size map as part of
the size-tracking tool update. The size-map difference
should generally be kept up-to-date to be able to
determine which PRs contribute size to a given file.
PR Close#30257
Based on discussion that happened on the PR that introduced
the size-tracking tool, we want to have another threshold for
the raw byte difference. This allows us to better control for
which changes the size-tracking tool should report a difference.
See: https://github.com/angular/angular/pull/30070#discussion_r278332315
PR Close#30257
- splits existing property acceptance tests into property_binding and property_interpolation
- ports tests from render3 instructions tests to acceptance tests
- removes redundant or unnecessary tests that are covered by existing acceptance tests
:)
PR Close#30321
Currently the static-query migration ignores queries declared on getters
or setters as these are not part of a `PropertyDeclaration`. We need to
handle these queries in order to cover all queries within a given project.
The usage strategy is not able to detect timing for queries on accessors,
so we add a TODO and print a message. The template strategy is able
to detect the proper timing for such queries because it's not dependent
on detecting the usage of the query.
Resolves FW-1215
PR Close#30327
We have an issue where we would like to be able to test perf counter metrics in acceptance tests, but we are unable to do so, because it will break when those same tests are run with ViewEngine. This PR adds a testing utility to `onlyInIvy` that allows for testing of performance counters, and even gives readable errors for what value on `ngDevMode` is incorrect. Has typings for decent autocompletion as well.
PR Close#30339
This is the final patch to migrate the Angular styling code to have a
smaller instruction set in preparation for the runtime refactor. All
styling-related instructions now work both in template and hostBindings
functions and do not use `element` as a prefix for their names:
BEFORE:
elementStyling()
elementStyleProp()
elementClassProp()
elementStyleMap()
elementClassMap()
elementStylingApply()
AFTER:
styling()
styleProp()
classProp()
styleMap()
classMap()
stylingApply()
PR Close#30318
This patch removes all host-specific styling instructions in favor of
using element-level instructions instead. Because of the previous
patches that made sure `select(n)` worked between styling calls, all
host level instructions are not needed anymore. This patch changes each
of those instruction calls to use any of the `elementStyling*`,
`elementStyle*` and `elementClass*` styling instructions instead.
PR Close#30336
The static-query template strategy leverages the AOT compiler
in order to determine the query timing. Unfortunately the AOT
compiler has open bugs that can cause unexpected failures which
make the template strategy unusable in rare cases. These rare
exceptions need to be handled gracefully in order to avoid confusion
and to provide a more smooth migration.
Additionally migration strategy setup failures are now reported with
stack traces as the `ng update` command does not print stack traces.
This makes it easier to reproduce and report migration issues.
PR Close#30269
In an Angular CLI project scenario where projects only reference
top-level source-files through the `tsconfig` `files` option, we currently
do not migrate referenced source-files. This can be fixed checking all
referenced source-files which aren't coming from an external library.
This is similar to how `tslint` determines project source-files.
PR Close#30269
Currently when someone has a call expression within the `ngOnInit` call
and we try to peek into that function with respect to the current function
context, the schematic errors because a call expression argument is
undefined. This is valid because the target function declaration defines
that parameter with a default value. In order to fix this, we need to
respect parameter default values.
PR Close#30269
Fixes not being able to bind a `SafeStyle` as a camel cased style property (e.g. `[style.backgroundImage]="someSafeStyle"`). The issue was due to the fact that we only check the dash case property names to determine whether to sanitize a value.
This PR resolves FW-1279.
PR Close#30328
572b54967c changed how the schematic
tests are executed. Tests no longer use the schematic collection
that is also used by the CLI `ng update` command and therefore
the migration collection could technically be invalid.
In order to ensure that the public migration collection is guaranteed
to work and to avoid duplication within two schematic collections, the
changes are partially reverted and only the disabled `injectable-pipe`
schematic has its own collection.
PR Close#30198
Currently we always prompt when the static-query migration runs. This is not
always needed because some applications do not even use `ViewChild` or
`ContentChild` queries and it just causes confusion if developers need to
decide on a migration strategy while there is nothing to migrate.
In order to avoid this confusion, we no longer prompt for a strategy
if there are no queries declared within the project.
PR Close#30254
This patch is one commit of many patches that will unify all styling instructions
across both template-level bindings and host-level bindings. This patch in particular
removes the `elementIndex` param because it is already set prior to each styling
instruction via the `select(n)` instruction.
PR Close#30313
Currently, in jit mode, `ngInjectableDef`, `ngDirectiveDef`, `ngPipeDef` and `ngModuleDef` use `ng://`,
which display them in the top domain in Chrome Dev Tools, whereas `ngComponentDef` uses `ng:///` which display components in a separate domain.
You can currently see:
```
AppModule
UserService
ng://
|_ AppComponent
|_ template.html
|_ AppComponent.js
...
```
This commits replaces all `ng://` with `ng:///` to display every Angular entity in the `ng://` domain.
```
ng://
|_ AppModule
|_ UserService
|_ AppComponent
...
```
PR Close#29826
This patch breaks up the existing `elementStylingMap` into
`elementClassMap` and `elementStyleMap` instructions. It also breaks
apart `hostStlyingMap` into `hostClassMap` and `hostStyleMap`
instructions. This change allows for better tree-shaking and reduces
the complexity of the styling algorithm code for `[style]` and `[class]`
bindings.
PR Close#30293
In the existing implementation the `elementPropertyInternal` function (meant to
set element properties) was executed even if a bound value didn't change. The
`elementPropertyInternal` was inspecting the incoming value and after comparing it
to `NO_CHANGE` - exiting early. All in all it meant that we were unnecessarily
invoking the `elementPropertyInternal` function for cases where bound value didn't
change.
Based on my bencharks (running change detection without any model update in a tight
loop) this unnecessary function call was causing ~5% slowdown in the change detection
process.
PR Close#30255
This commit fixes a regression introduced in PR 29692 where
the interpolate symbol in View Engine was improperly prefixed
with the ɵɵ that signifies private instructions for Ivy. It
resulted in interpolations of 10+ values not working correctly
in AOT mode. This commit removes the prefix.
PR Close#30243
Previously, `R3TestBedCompiler` was dynamically defining an
`@NgModule`-decorated `CompilerModule` class inside a method call.
Since ngcc only processes top-level classes, this class was not
transformed causing failures in unit tests (see #30121 for details).
This commit fixes it by using `compileNgModuleDefs()` directly (similar
to the fix in #30037).
Fixes#30121
PR Close#28530
Ivy uses R3Injector, but we are currently pulling in both the StaticInjector
(View Engine injector) and the R3Injector when running with Ivy. This commit
adds an ivy switch so calling Injector.create() pulls in the correct
implementation of the injector depending on whether you are using VE or Ivy.
This saves us about 3KB in the bundle.
PR Close#30219
Previously, we were supporting injection flags for provider deps, but only
if they fit the format `new Optional()`. This commit fixes resolution of
provider deps to also support `Optional` (without the new). This keeps us
backwards compatible with what View Engine supported.
PR Close#30216
Stores the views that are part of a container directly on the `LContainer`, rather than maintaining a dedicated sub-array.
This PR resolves FW-1288.
PR Close#30179
Currently, we are not properly resolving forward refs when they appear
in deps for providers created with the useFactory strategy. This commit
wraps provider deps in the resolveForwardRef call so the tokens are
passed into the inject function as expected.
PR Close#30201
Fixes `HostBinding` and `HostListener` declarations not being inherited from base classes that don't have an Angular decorator.
This PR resolves FW-1275.
PR Close#30158
Currently the `static-query` migrations fails at the final step of
updating a query when the query already specifies options which
cannot be transformed easily. e.g. the options are computed through
a function call: `@ViewChild(..., getQueryOpts());` or `@ViewChild(..., myOptionsVar)`.
In these cases we technically could add additionally logic to update
the query options, but given that this is an edge-case and it's
potentially over-engineering the migration schematic, we just
always add a TODO for the timing and print out the determined
query timing in the console. The developer in that case just needs
to manually update the logic for the query options to contain the
printed query timing.
Potentially related to: https://github.com/angular/angular-cli/issues/14298
PR Close#30178
Introduces a new Bazel test that allows us to inspect
what source-files contribute to a given bundled file
and how much bytes they contribute to the bundle size.
Additionally the size-tracking rule groups the size
data by directories. This allows us to compare size
changes in the scope of directories. e.g. a lot of
files in a directory could increase slightly in size, but
in the directory scope the size change could be significant
and needs to be reported by the test target.
Resolves FW-1278
PR Close#30070
Disables the injectable pipe migration until we can decide whether this is the right solution for Ivy. Rolling it out properly will involve a more detailed plan and more changes like updating the styleguide, scaffolding schematics etc.
Context for the new `test-migrations.json`: since we use the `migrations.json` both for the real migrations and for tests, it doesn't allow us to disable a schematic, but continue running its tests. This change adds the test-specific file so that we can continue running the `injectable-pipe` tests, even though the schematic itself is disabled.
PR Close#30180
Currently the injectable pipe schematic generates invalid imports like `import import { Pipe, PipeTransform, Injectable } from '@angular/core'; from '@angular/core';`. The issue wasn't caught by the unit tests, because the invalid import still contains the valid one.
Fixes#30159.
PR Close#30170
Fixes Ivy reflecting properties with `undefined` values, rather than omitting them. Also fixes that Ivy doesn't clear the reflected values when property value changes from something that is defined to undefined.
This PR resolves FW-1277.
PR Close#30103
Move tests for special tokens like `Injector`, `ElementRef`, `TemplateRef`, `ViewContainerRef`, `ChangeDectetorRef` and custom string tokens.
PR Close#29299
- Extracts and documents code that will be common to interpolation instructions
- Ensures that binding indices are updated at the proper time during compilation
- Adds additional tests
Related #30011
PR Close#30129
The proposed ES dynamic import() is now supported by the Angular CLI and the
larger toolchain. This renders the `loadChildren: string` API largely
redundant, as import() is far more natural, is less error-prone, and is
standards compliant. This commit deprecates the `string` form of
`loadChildren` in favor of dynamic import().
DEPRECATION:
When defining lazy-loaded route, Angular previously offered two options for
configuring the module to be loaded, both via the `loadChildren` parameter
of the route. Most Angular developers are familiar withthe `string` form of
this API. For example, the following route definition configures Angular to
load a `LazyModule` NgModule from `lazy-route/lazy.module.ts`:
```
[{
path: 'lazy',
loadChildren: 'lazy-route/lazy.module#LazyModule',
}]
```
This "magic string" configuration was previously necessary as there was
no dynamic module loading standard on the web. This has changed with the
pending standardization of dynamic `import()` expressions, which are now
supported in the Angular CLI and in web tooling in general. `import()`
offers a more natural and robust solution to dynamic module loading. The
above example can be rewritten to use dynamic `import()`:
```
[{
path: 'lazy',
loadChildren: () => import('./lazy-route/lazy.module').then(mod => mod.LazyModule),
}]
```
This form of lazy loading offers significant advantages in terms of:
* type checking via TypeScript
* simplicity of generated code
* future potential to run natively in supporting browsers
(see: [caniuse: dynamic import()](https://caniuse.com/#feat=es6-module-dynamic-import))
As a result, Angular is deprecating the `loadChildren: string` syntax in
favor of ES dynamic `import()`. An automatic migration will run during
`ng upgrade` to convert your existing Angular code to the new syntax.
PR Close#30073
The `renderStringify` function is used in a lot of performance-sensitive places, however it contains a megamorphic read which is used primarily for error messages. These changes introduce a new function that can be used to stringify output for errors and removes the megamorphic read from `renderStringify`.
This PR resolves FW-1286.
PR Close#30082
Fixes view and content queries not being inherited in Ivy, if the base class hasn't been annotated with an Angular decorator (e.g. `Component` or `Directive`).
Also reworks the way the `ngBaseDef` is created so that it is added at the same point as the queries, rather than inside of the `Input` and `Output` decorators.
This PR partially resolves FW-1275. Support for host bindings will be added in a follow-up, because this PR is somewhat large as it is.
PR Close#30015
Currently when someone runs `ng update` with the static-query migration,
the migration can fail with an error saying that the `AOT` compiler could not
be created. This can happen if the CLI project contains a test `tsconfig.json`
that is picked up by the schematic.
Due to the fact that spec tsconfig files cannot be ran with NGC (e.g. test
components are not part of a module; not all source files are guaranteed to
be included), test `tsconfig` projects will now use a new `test` migration
strategy where all queries within tests are left untouched and a TODO is added.
PR Close#30034
This commit unifies the way auxillary RootScopeModule and DynamicTestModule are compiled in R3TestBed by calling `compileNgModuleDefs` explicitly for RootScopeModule. This change also resolves the problem where TestBed's code was used from the @angular/core NPM package: due to the "jit" flag, the @NgModule decorator on the RootScopeModule was transformed to RootScopeModule.decorators = [...], but actual ngModuleDef was never defined.
PR Close#30037
Fixes Ivy throwing an error because it tries to generate styling instructions for empty `style` and `class` bindings.
This PR resolves FW-1274.
PR Close#30024
Currently the `template-var-assignment` migration incorrectly warns if
the template writes to a property in the component that has the same
`ast.PropertyWrite´ name as a template input variable but different
receiver. e.g.
```html
<!-- "someProp.element" will be incorrectly reported as template variable assignment -->
<button *ngFor="let element of list" (click)="someProp.element = null">Reset</button>
```
Similarly if an output writes to a component property with the same name as a
template input variable, but the expression is within a different template scope,
the schematic currently incorrectly warns. e.g.
```html
<button *ngFor="let element of list">{{element}}</button>
<!-- The "element = null" expression does not refer to the "element" template input variable -->
<button (click)="element = null"></button>
```
PR Close#30026
Previously, we had a bug where directive matching could fail if the directive
attribute was bound and followed a certain number of classes. This is because
in the matching logic, we were treating classes like normal attributes. We
should instead be skipping classes in the attribute matching logic. Otherwise
classes will match for directives with attribute selectors, and as we are
iterating through them in twos (when they are stored as name-only, not in
name-value pairs), it may throw off directive matching for any bound attributes
that come after. This commit changes the directive matching logic to skip
classes altogether.
PR Close#30002
We only set ng-reflect properties on directive input bindings.
This PR ensures that we also add ng-reflect properties on unbound inputs for backwards compatibility.
FW-1266 #resolve
PR Close#29973
This commit adds registration of AOT compiled NgModules that have 'id'
properties set in their metadata. Such modules have a call to
registerNgModuleType() emitted as part of compilation.
The JIT behavior of this code is already in place.
This is required for module loading systems (such as g3) which rely on
getModuleFactory().
PR Close#29980
Previous to this change, we assumed embedded views could only be created after
their parent template node had completed processing. As a result, we only set
up query logic for containers after directives on the node were created.
However, this assumption didn't take into account the case where a directive
on a template node could create views in its constructor.
This commit fixes query logic to work with views created in constructors.
In that case, we need to create a query container before the new view is
rendered so query results in the view aren't lost. But since the query container
is created before directives have completed processing, we also have to ensure
that query results gathered later on the template node are inserted before that
query container. Otherwise, query results in embedded views will clobber query
results on template nodes.
This splice mode may be slightly slower than the normal matching for queries on
containers, but we should only fall back to this strategy in the edge case where
views are created in constructors. (We should encourage developers to create
views in ngOnInit instead).
PR Close#29983
Prior to this change, components created via TestBed.createComponent in the same test were placed into the same root context, which caused problems in conjunction with fixture.autoDetectChanges usage in the same test. Specifically, change detection was triggered immediately for created component (starting from the 2nd one) even if it was not required/desired. This commit makes Ivy and VE behavior consistent: now every component created via TestBed.createComponent is isolated from each other. Current solution uses host element id naming convention, which is not ideal, but helps avoid public API surface changes at this point (we might revisit this approach later).
Note: this commit also adds extra tests to verify bootstrap and change detection behavior in case of multiple components in `bootstrap` array in @NgModule, to make sure this behavior is aligned between Ivy and VE.
PR Close#29981
Currently the `template-strategy` for the static query migration uses the
Angular compiler in order to determine the query timing. This is problematic
as the AngularCompilerProgram also collects metadata for referenced
component stylesheets which aren't necessarily present. e.g. in a CLI
project the component can reference a Sass file. It's not guaranteed
that the standalone Angular compiler plugin supports Sass without
custom logic that is brought in by the Angular CLI webpack plugin.
In order to avoid any failures for invalid stylesheets, we just disable
normalizing of all referenced stylesheets.
PR Close#29876
Currently there are two available migration strategies for the `static-query`
schematic. Both have benefits and negatives which depend on what the
developer prefers. Since we can't decide which migration strategy is the
best for a given project, the developer should be able to select a specific
strategy through a simple choice prompt.
In order to be able to use prompts in a migration schematic, we need to
take advantage of the "inquirer" package which is also used by the CLI
schematic prompts (schematic prompts are usually only statically defined
in the schema). Additionally the schematic needs to be made "async"
because with prompts the schematic can no longer execute synchronously
without implementing some logic that blocks the execution.
PR Close#29876
With dts bundles, `core.d.ts` will include an `EventListener` class as it's used in 303eae918d/packages/core/src/debug/debug_node.ts (L32)
This will conflict with the DOM EventListener, as anything in `core.d.ts` which is using the DOM EventListener will fallback in using the one defined in the same module and hence build will fail because their implementation is different.
With this change, we rename the local `EventListener` to `DebugEventListener`, the later one is non exported.
Fixes#29806
PR Close#29809
When compiling Angular classes, the compiler may decide to append statements with specific metadata that's only required for JIT. This includes things like decorator metadata as well as NgModule scope data.
When the compiler generates such calls, the call sites are marked with Uglify's PURE annotation, so the optimizer will remove them in production builds. However, Closure does not have the PURE (or similar) annotation. We have a utility function `noSideEffects` in the runtime for this purpose. This commit wraps `setClassMetadata` and `setNgModuleScope` function bodies in `noSideEffect` closures to allow Closure remove them.
PR Close#29947
The `TNode.cleanup` data structure can contain sequences of 4-element
sequence of entries (event handlers, directive outputs) mixed with
2-element sequence of entries (QueryList cleanup). Before this fix
we would always skip 4 elements in the `TNode.cleanup` while looking
up event handler cleanups. 4-element skips are not correct in case
of query cleanup presence and this commit corrects the algorithm to
jump 4 or 2 elements depending on a type of cleanup encountered.
PR Close#29957
If a component has its definition set by defineComponent (as opposed to
JIT getter), then it will generate a factory that uses directiveInject()
to retrieve its dependencies. This can be problematic in test code because
tests could use the injection utility before bootstrapping the component,
and directiveInject() relies on the view having been created.
This commit tweaks directiveInject() to fall back to inject() if the view
has not been created. This will allow injection to work in tests even if
it is called before the component is bootstrapped.
PR Close#29948
Previous to this commit, providing a component or directive in a test
module without @Injectable() would throw because the injectable factory
would not be found. Providing components in tests in addition to declaring
or importing them is not necessary, but it should not throw an error.
This commit ensures factory data is saved when component defs and directive
defs are created, which allows them to be processed by the module injector.
Note that bootstrapping is still required for this setup to work because
directiveInject() does not support cases where the view has not been
created. This case will be handled in a future commit.
PR Close#29945
We had a bug where event.preventDefault() was not always called if listeners
were coalesced. This is because we were overwriting the previous listener's
result every time we called the next listener, so listeners early in the chain
that returned false would be ignored and preventDefault would not be called.
This commit fixes that issue, so now preventDefault() is called if any listener
in a coalesced chain returns false. This brings us in line with View Engine
behavior.
PR Close#29934
Overriding multi provider values (providers with `multi: true` flag) via TestBed require additional handling: all existing multi-provider values for the same token should be removed from the override list, so that they are not included into the final value of a given provider. This commit adds this logic to make sure we handle multi providers correctly.
PR Close#29919
Because the styling context may be stored in a different location
and be apart of a sub array, reading the styling context each time
a host binding is evaluated is costly. This patch ensures that the
active styling context is cached so that multiple interactions with
styling bindings can easily retrieve the styling context efficiently.
PR Close#29818
Currently if there are multiple source files within a given
TypeScript source file, only the last template in the source
file is checked as we store templates in a `Map` with the
source file paths as keys.
This is problematic as multiple templates can live within the
same source file and we therefore accidentally overwrite
existing entries in the resolved templates map.
PR Close#29841
Introduces a new strategy for the `static-query` schematic that
is enabled by default. In order to provide a migration that works
for the most Angular applications and makes the upgrade as easy
as possible, the template strategy leverages the view engine
Angular compiler logic in order to determine the query timing
that is currently used within applications using view engine.
PR Close#29815
In order to support multiple strategies for detecting the query timing, the
query usage logic has been moved into a query usage strategy.
PR Close#29815