Currently if a user accidentally calls ViewContainerRef.insert() with
a view that has already been attached, we do not clean up the references
properly, so we create a view tree with a cycle. This causes an infinite
loop when the view is destroyed.
This PR ensures that we fall back to ViewContainerRef.move() behavior
if we try to insert a view that is already attached. This fixes the
cycle and honors the user intention.
PR Close#29047
This change helps highlight certain misoptimizations with Closure
compiler. It is also stylistically preferable to consistently use index
access on index sig types.
Roughly, when one sees '.foo' they know it is always checked for typos
in the prop name by the type system (unless 'any'), while "['foo']" is
always not.
Once all angular repos are conforming this will become a tsetse.info
check, enforced by bazel.
PR Close#28937
Previously the start of a character indicated by an escape sequence
was being incorrectly computed by the lexer, which caused tokens
to include the start of the escaped character sequence in the
preceding token. In particular this affected the name extracted
from opening tags if the name was terminated by an escape sequence.
For example, `<t\n>` would have the name `t\` rather than `t`.
This fix refactors the lexer to use a "cursor" object to iterate over
the characters in the template source. There are two cursor implementations,
one expects a simple string, the other expects a string that contains
JavaScript escape sequences that need to be unescaped.
PR Close#28978
The parts of a token are supposed to be an array of not-null strings,
but we were using `null` for tags that had no prefix. This has been
fixed to use the empty string in such cases, which allows the `null !`
hack to be removed.
PR Close#28978
Prior to this change, TypeScript stripped out some imports in case we reference a type that can be represented as a value (for ex. classes). This fix ensures that we use correct symbol identifier, which makes TypeScript retain the necessary import statements.
PR Close#28941
This commit removes code duplication around projectables nodes insertion.
It also simplfy the overall logic by using recursive function calls instead
of hand-unrolled stack (we can always optimise this part if needed).
PR Close#29008
When web-animations and/or CSS keyframes are used for animations certain
CSS style values (such as `display` and `position`) may be ignored by a
keyframe-based animation. Angular should special-case these styles to
ensure that they get applied as inline styles throughout the duration of
the animation.
Closes#24923Closes#25635
Jira Issue: FW-1091
Jira Issue: FW-1092
PR Close#28911
Angular supports using <style> and <link> tags inline in component
templates, but previously such tags were not implemented within the ngtsc
compiler. This commit introduces that support.
FW-1069 #resolve
PR Close#28997
Prior to this change i18n block bindings were converted to Expressions right away (once we first access them), when in non-i18n cases we processed them differently: the actual conversion happens at instructions generation. Because of this discrepancy, the output for bindings in i18n blocks was generated incorrectly (with invalid indicies in pipeBindN fns and invalid references to non-existent local variables). Now the bindings processing is unified and i18nExp instructions should contain right bind expressions.
PR Close#28969
This commit introduces support for the windows paths in the new concrete types mechanism that was introduced in this PR https://github.com/angular/angular/pull/28523
Normalized posix paths that start with either a `/` or `C:/` are considered to be an absolute path.
Note: `C:/` is used as a reference, as other drive letters are also supported.
Fixes#28754
PR Close#28752
Prior to this change, the logic that outputs i18n consts (like `const MSG_XXX = goog.getMsg(...)`) didn't have a check whether a given const that represent a certain i18n message was already included into the generated output. This commit adds the logic to mark corresponding i18n contexts after translation was generated, to avoid duplicate consts in the output.
PR Close#28967
Karma is not configured to retrieve the imported scripts using those
absolute deep paths. Using relative paths instead.
See [here][1] for an example failing job.
[1]: https://circleci.com/gh/angular/angular/220751
PR Close#29009
The partial evaluator in ngtsc can handle a shorthand property declaration
in the middle evaluation, but fails if evaluation starts at the shorthand
property itself. This is because evaluation starts at the ts.Identifier
of the property (the ts.Expression representing it), not the ts.Declaration
for the property.
The fix for this is to detect in TypeScriptReflectionHost when a ts.Symbol
refers to a shorthand property, and to use the ts.TypeChecker method
getShorthandAssignmentValueSymbol() to resolve the value of the assignment
instead.
FW-1089 #resolve
PR Close#28936
This will make the debugging output go away
DEBUG: Rule 'io_bazel_rules_sass' modified arguments {"sha256": "6caffb8277b3033d6b5117b77437faaa6cd3c6679d6d6c81284511225aa54711"}
PR Close#28994
In the past, the sanitizer would remove unsafe elements, but still
traverse and sanitize (and potentially preserve) their content. This was
problematic in the case of `<style></style>` tags, whose content would
be converted to HTML text nodes.
In order to fix this, the sanitizer's behavior was changed in #25879 to
ignore the content of _all_ unsafe elements. While this fixed the
problem with `<style></style>` tags, it unnecessarily removed the
contents for _any_ unsafe element. This was an unneeded breaking change.
This commit partially restores the old sanitizer behavior (namely
traversing content of unsafe elements), but introduces a list of
elements whose content should not be traversed if the elements
themselves are considered unsafe. Currently, this list contains `style`,
`script` and `template`.
Related to #25879 and #26007.
Fixes#28427
PR Close#28804
Currently if an embedded view contains projected nodes, its `rootNodes` array will include `null` instead of the root nodes inside the projection slot. This manifested itself in one of the Material unit tests where we stamp out a template and then move its `rootNodes` into the overlay container.
This PR is related to FW-1087.
PR Close#28951
For efficiency reasons we often put several different data types (`RNode`, `LView`, `LContainer`,
`StylingContext`) in same location in `LView`. This is because we don't want to pre-allocate
space
for it because the storage is sparse. This file contains utilities for dealing with such data
types.
How do we know what is stored at a given location in `LView`.
- `Array.isArray(value) === false` => `RNode` (The normal storage value)
- `Array.isArray(value) === true` => than the `value[0]` represents the wrapped value.
- `typeof value[TYPE] === 'object'` => `LView`
- This happens when we have a component at a given location
- `typeof value[TYPE] === 'number'` => `StylingContext`
- This happens when we have style/class binding at a given location.
- `typeof value[TYPE] === true` => `LContainer`
- This happens when we have `LContainer` binding at a given location.
NOTE: it is assumed that `Array.isArray` and `typeof` operations are very efficient.
PR Close#28947
`LView`, `LContainer`, `StylingContext` are all arrays which wrap either
an `HTMLElement`, `LView`, `LContainer`, `StylingContext`. It is often
necessary to retrieve the correct type of element from the location
which means that we often have to wrap the arrays. Logically it makes
more sense if the thing which we are wrapping is at `0` location. Also
it may be more performant since data is more local which may result in
more L2 cache hits in CPU.
PR Close#28947
This change contains conditionally attached classes which provide human readable (debug) level
information for `LView`, `LContainer` and other internal data structures. These data structures
are stored internally as array which makes it very difficult during debugging to reason about the
current state of the system.
Patching the array with extra property does change the array's hidden class' but it does not
change the cost of access, therefore this patching should not have significant if any impact in
`ngDevMode` mode. (see: https://jsperf.com/array-vs-monkey-patch-array)
So instead of seeing:
```
Array(30) [Object, 659, null, …]
```
```
LViewDebug {
views: [...],
flags: {attached: true, ...}
nodes: [
{html: '<div id="123">', ..., nodes: [
{html: '<span>', ..., nodes: null}
]}
]
}
```
PR Close#28945
If an interface is not exported publicly from its package, then the doc-gen
does not see it, and so cannot include it in the generated documentation.
This was the case for a number of `...Decorator` interfaces, such as
`PipeDecorator` and `InputDecorator.
This commit adds these interfaces to the public export to fix this problem.
PR Close#28836
Google3 detected circular references here, so splitting up this rather hodge-podge list of functions into slightly better organizational units.
PR Close#28382
- TView no longer stores childIndex
- LView now as CHILD_HEAD and CHILD_TAIL
TView used to store the head of the list, therefor all LViews had to have the same head, which is incorrect.
PR Close#28382
- Removes CONTAINER_INDEX
- LView[PARENT] now contains LContainer when necessary
- Removes now unused arguments to methods after refactor
PR Close#28382
In certain configurations (such as the g3 repository) which have lots of
small compilation units as well as strict dependency checking on generated
code, ngtsc's default strategy of directly importing directives/pipes into
components will not work. To handle these cases, an additional mode is
introduced, and is enabled when using the FileToModuleHost provided by such
compilation environments.
In this mode, when ngtsc encounters an NgModule which re-exports another
from a different file, it will re-export all the directives it contains at
the ES2015 level. The exports will have a predictable name based on the
FileToModuleHost. For example, if the host says that a directive Foo is
from the 'root/external/foo' module, ngtsc will add:
```
export {Foo as ɵng$root$external$foo$$Foo} from 'root/external/foo';
```
Consumers of the re-exported directive will then import it via this path
instead of directly from root/external/foo, preserving strict dependency
semantics.
PR Close#28852
This commit splits apart selector_scope.ts in ngtsc and extracts the logic
into two separate classes, the LocalModuleScopeRegistry and the
DtsModuleScopeResolver. The logic is cleaned up significantly and new tests
are added to verify behavior.
LocalModuleScopeRegistry implements the NgModule semantics for compilation
scopes, and handles NgModules declared in the current compilation unit.
DtsModuleScopeResolver implements simpler logic for export scopes and
handles NgModules declared in .d.ts files.
This is done in preparation for the addition of re-export logic to solve
StrictDeps issues.
PR Close#28852
This PR fixes a bug in autocompletion for @Input/@Output decorator with
an alias. The current implementation ignores the alias.
Credit for this work is attributed to @edgardmessias
The original work fixed the bug, but was lacking test.
PR Close#27959
PR Close#28904
At the moment, the API extractor doesn't support local namespaced imports, this will break the generation of flat dts files. When we turn on dts bundling for this package it will break. Hence this is the ground work needed for making this package compatable with the API extractor.
See: https://github.com/Microsoft/web-build-tools/issues/1029
Relates to #28588
PR Close#28642
During build time we remap particular property bindings, because their names don't match their attribute equivalents (e.g. the property for the `for` attribute is called `htmlFor`). This breaks down if the particular element has an input that has the same name, because the property gets mapped to something invalid.
The following changes address the issue by mapping the name during runtime, because that's when directives are resolved and we know all of the inputs that are associated with a particular element.
PR Close#28765
Fixes the `ngOnDestroy` hook on a component or directive being called twice, if the type is also registered as a provider.
This PR resolves FW-1010.
PR Close#28470
Prior to this change presence of HTML comments inside <ng-content> caused compiler to throw an error that <ng-content> is not empty. Now HTML comments are not considered as a meaningful content, thus no error is thrown. This behavior is now aligned in Ivy/VE.
PR Close#28849
Prior to this change absolute file paths (like `/a/b/c/style.css`) were calculated taking current component file location into account. As a result, absolute file paths were calculated using current file as a root. This change updates this logic to ignore current file path in case of absolute paths.
PR Close#28789
Prior to this change, Ivy and VE CSS resource resolution was different: in addition to specified styleUrl (with .scss, .less and .styl extensions), VE also makes an attempt to resolve resource with .css extension. This change introduces similar logic for Ivy to make sure Ivy behavior is backwards compatible.
PR Close#28770
Prior to this change, the @fileoverview annotations added by users in source files or by tsickle during compilation might have change a location due to the fact that Ngtsc may prepend extra imports or constants. As a result, the output file is considered invalid by Closure (misplaced @fileoverview annotation). In order to resolve the problem we relocate @fileoverview annotation if we detect that its host node shifted.
PR Close#28723
This change is kind of similar to #27466, but instead of ensuring that
these shims can be generated, we also need to make sure that developers
are able to also use the factory shims like with `ngc`.
This issue is now surfacing because we have various old examples which
are now also built with `ngtsc` (due to the bazel migration). On case insensitive
platforms (e.g. windows) these examples cannot be built because ngtsc fails
the app imports a generated shim file (such as the factory shim files).
This is because the `GeneratedShimsHostWrapper` TypeScript host uses
the `getCanonicalFileName` method in order to check whether a given
file/module exists in the generator file maps. e.g.
```
// Generator Map:
'C:/users/paul/_bazel_paul/lm3s4mgv/execroot/angular/packages/core/index.ngfactory.ts' =>
'C:/users/paul/_bazel_paul/lm3s4mgv/execroot/angular/packages/core/index.ts',
// Path passed into `fileExists`
C:/users/paul/_bazel_paul/lm3s4mgv/execroot/angular/packages/core/index.ngfactory.ts
// After getCanonicalFileName (notice the **lower-case drive name**)
c:/users/paul/_bazel_paul/lm3s4mgv/execroot/angular/packages/core/index.ngfactory.ts
```
As seen above, the generator map does not use the canonical file names, as well as
TypeScript internally does not pass around canonical file names. We can fix this by removing
the manual call to `getCanonicalFileName` and just following TypeScript internal-semantics.
PR Close#28831
Fixes a minor typo in the `listLazyRoutes` method for `ngtsc`. Also in
addition fixes that a newly introduced test for `listLazyRoutes` broke the
tests in Windows. It's clear that we still don't run tests against
Windows, but we also made all other tests pass (without CI verification),
and it's not a big deal fixing this while being at it.
PR Close#28831
With #28402 we updated the `examples` package to be
built and tested with Bazel. This PR was only intended
for the e2e integration tests, and there still seem to be
a few unit tests that need to be migrated to Bazel until
we can remove the legacy local unit tests job.
PR Close#28703
Prior to this fix, both the `NgStyle` and `NgClass` directives made use
of `Renderer2` and this dependency raised issues for future versions of
Angular that cannot inject it. This patch ensures that there are two
versions of both directives: one for the VE and another for Ivy.
Jira Issue: FW-882
PR Close#28711
Prior to this fix, using the compiler's ivy_switch mechanism was
only available to core packages. This patch allows for this variable
switching mechanism to work across all other angular packages.
PR Close#28711
This commit adds a postinstall step to the package.json generated by the
schematics to generate ng summary files needed for AOT. Summary files
are not published in npm packages.
PR Close#28850
Since rxjs is no longer built from source in Bazel schematics, the
minimum version ought to be at least 6.4.0.
This commit adds function to bump the version in package.json.
PR Close#28841
This change enables dts bundling for the following packages and their secondary entry points:
- @angular/animations
- @angular/elements
- @angular/http
- @angular/platform-browser
- @angular/platform-browser-dynamic
- @angular/platform-server
- @angular/platform-webworker
- @angular/platform-webworker-dynamic
- @angular/servce-worker
Dts bundling happens in `ng_module` bazel definition, hence packages such as `@angular/compiler`, `@angular/compiler-cli` and `@angular/langauge service` cannot be flattened as they use `ts_library`.
`@angular/core`, `@angular/common`, `@angular/upgrade` and `@angular/forms` will be done seperatly as it requires some changes either to their source or specs.
PR Close#28726
We previously disabled this test because we did not yet have
static query support in Ivy and the planned API would be
slightly different. Now that a static query flag is available
that works in both View Engine and Ivy, the test has been
updated to use that flag and has been turned on to run in CI.
Since the test was always unrelated to queries and was intended
to test *ngIf behavior, updating the test in this instance
seems reasonable.
PR Close#28845
The `setUpLocationSync` function in @angular/router/upgrade didn't previously let you sync hash-based navigations. With this change, you can now pass an option to `setUpLocationSync` that will make sure location changes run in Angular in hash-based apps.
Fixes#24429#21995
PR Close#28609
I18n can change the order of the nodes, or insert new dynamic nodes. When that happens it can break the existing links (`TNode.next`) or even create loops:
```
div1 → div2 → div3 → div4 → div5
```
Can become:
```
div1 → div4 → div2 → div3 div5
🡑 │
└─────────────┘
```
This PR fixes this issue by recreating the broken links between those nodes.
PR Close#28827
This commit adds support for the `static: true` flag in `ContentChild`
queries. Prior to this commit, all `ContentChild` queries were resolved
after change detection ran. This is a problem for backwards
compatibility because View Engine also supported "static" queries which
would resolve before change detection.
Now if users add a `static: true` option, the query will be resolved in
creation mode (before change detection runs). For example:
```ts
@ContentChild(TemplateRef, {static: true}) template !: TemplateRef;
```
This feature will come in handy for components that need
to create components dynamically.
PR Close#28811
This commit adds support for the `static: true` flag in
`ViewChild` queries. Prior to this commit, all `ViewChild`
queries were resolved after change detection ran. This is
a problem for backwards compatibility because View Engine
also supported "static" queries which would resolve before
change detection.
Now if users add a `static: true` option, the query will be
resolved in creation mode (before change detection runs).
For example:
```ts
@ViewChild(TemplateRef, {static: true}) template !: TemplateRef;
```
This feature will come in handy for components that need
to create components dynamically.
PR Close#28811
Prior to this commit, the timing of `ViewChild`/`ContentChild` query
resolution depended on the results of each query. If any results
for a particular query were nested inside embedded views (e.g.
*ngIfs), that query would be resolved after change detection ran.
Otherwise, the query would be resolved as soon as nodes were created.
This inconsistency in resolution timing had the potential to cause
confusion because query results would sometimes be available in
ngOnInit, but sometimes wouldn't be available until ngAfterContentInit
or ngAfterViewInit. Code depending on a query result could suddenly
stop working as soon as an *ngIf or an *ngFor was added to the template.
With this commit, users can dictate when they want a particular
`ViewChild` or `ContentChild` query to be resolved with the `static`
flag. For example, one can mark a particular query as `static: false`
to ensure change detection always runs before its results are set:
```ts
@ContentChild('foo', {static: false}) foo !: ElementRef;
```
This means that even if there isn't a query result wrapped in an
*ngIf or an *ngFor now, adding one to the template later won't change
the timing of the query resolution and potentially break your component.
Similarly, if you know that your query needs to be resolved earlier
(e.g. you need results in an ngOnInit hook), you can mark it as
`static: true`.
```ts
@ViewChild(TemplateRef, {static: true}) foo !: TemplateRef;
```
Note: this means that your component will not support *ngIf results.
If you do not supply a `static` option when creating your `ViewChild` or
`ContentChild` query, the default query resolution timing will kick in.
Note: This new option only applies to `ViewChild` and `ContentChild`
queries, not `ViewChildren` or `ContentChildren` queries, as those types
already resolve after CD runs.
PR Close#28810
Currently if developers use call expressions in their static
class members ([like we do in Angular](https://github.com/angular/angular/blob/master/packages/core/src/change_detection/differs/keyvalue_differs.ts#L121)),
the metadata that is generated for flat modules is invalid. This
is because the metadata bundler logic currently does not handle
call expressions in static class members and the symbol references
are not rewritten to avoid relative paths in the bundle.
Static class members using a call expression are not relevant for
the ViewEngine AOT compilation, but it is problematic that the
bundled metadata references modules using their original relative
path. This means that the bundled metadata is no longer encapsulated
and depends on other emitted files to be emitted in the proper place.
These incorrect relative paths can now cause issues where NGC
looks for the referenced symbols in the incorrect path. e.g.
```
src/
| lib/
| index.ts -> References the call expression using `../../di`
```
Now the metadata looks like that:
```
node_modules/
| @angular/
-- | core/
-- -- | core.metadata.json -> Says that the call expr. is in `../../di`.
| di/
```
Now if NGC tries to use the metadata files and create the summary files,
NGC resolves the call expression to the `node_modules/di` module. Since
the "unexpected" module does not contain the desired symbol, NGC will
error out.
We should fix this by ensuring that we don't ship corrupted metadata
to NPM which contains relative references that can cause such
failures (other imports can be affected as well; it depends on what
modules the developer has installed and how we import our call
expressions).
Fixes#28741.
PR Close#28762
Currently setting `enableIvy` to true runs a hybrid mode of `ngc` and `ngtsc`. This is counterintuitive given the name of the flag itself.
This PR makes the `true` value equivalent to the previous `ngtsc`, and `ngtsc` becomes an alias for `true`. Effectively this removes the hybrid mode as well since there's no other way to enable it.
PR Close#28616
Previously, `ngtsc` detected class inheritance in a way that only worked
in TS or ES2015 code. As a result, inheritance would not be detected for
code in ES5 format, such as when running `ngtsc` through `ngcc` to
transform old-style Angular code to ivy format.
This commit fixes it by delegating class inheritance detection to the
current `ReflectionHost`, which is able to correctly interpret the used
code format.
PR Close#28773
This commit turns off an unknown binding test that is specific
to the View Engine implementation. In Ivy, we do property validation
at runtime for jit, so this test does not apply.
PR Close#28740
Accounts for schemas in when validating properties in Ivy.
This PR resolves FW-819.
A couple of notes:
* I had to rework the test slightly, in order to have it fail when we expect it to. The one in master is passing since Ivy's validation runs during the update phase, rather than creation.
* I had to deviate from the design in FW-819 and not add an `enableSchema` instruction, because the schema is part of the `NgModule` scope, however the scope is only assigned to a component once all of the module's declarations have been resolved and some of them can be async. Instead, I opted to have the `schemas` on the component definition.
PR Close#28637
Since we build and publish the individual packages
using Bazel and `build.sh` has been removed, we can
safely remove the `rollup.config.js` files which are no
longer needed because the `ng_package` bazel rule
automatically handles the rollup settings and globals.
PR Close#28646
Currently errors thrown inside event handler in Ivy are caught and forwarded to the `ErrorHandler`, however this means that if they happen during a unit test, the test won't fail. These changes add a test-specific `ErrorHandler` that throws the error rather than logging it out.
PR Close#28707
Previously `DebugNode.classes` and `DebugNode.styles` mistakenly used an
object that is only *sometimes* a `StylingContext`. Also fixes a mistake
in `debug_node_spec.ts` where a test component was not declared in the
testing module.
There is still a bug here where `DebugNode` is not exposing *static*
values. This will need to be fixed in a follow up.
PR Close#28709
Prior to this fix if a root component was instantiated it create host
bindings, but never render them once update mode ran unless one or more
slot-allocated bindings were issued. Since styling in Ivy does not make
use of LView slots, the host bindings function never ran on the root
component.
This fix ensures that the `hostBindings` function does run for a root
component and also renders the schedlued styling instructions when
executed.
Jira Issue: FW-1062
PR Close#28664
Under Bazel, some compilerOptions in tsconfig.json are controlled by
downstream rules. The default tsconfig.json causes Bazel to print out
warnings about overriden settings.
This commit makes a backup of the original tsconfig.json and removes
tsconfig settings that are controlled by Bazel.
As part of this fix, JsonAst utils are refactored into separate package
and unit tests are added.
PR closes https://github.com/angular/angular/issues/28034
PR Close#28674
BREAKING CHANGE
Previous to this change, when a control was reset, value and status change
events would be emitted before the control was reset to pristine. As a
result, if one were to check a control's pristine state in a valueChange
listener, it would appear that the control was still dirty after reset.
This change delays emission of value and status change events until after
controls have been marked pristine. This means the pristine state will be
reset as expected if one checks in a listener.
Theoretically, there could be applications depending on checking whether a
control *used to be dirty*, so this is marked as breaking. In these cases,
apps should cache the state on the app side before calling reset.
Fixes#28130
PR Close#28395
This enabled dts flattening in the final distrubutable package.
Notes:
- For the time being this is an opt-in feature via the `ng_module` attribute `bundle_dts`, however in the near future this will be turned on by default.
- This only supports the legacy compiler `ngc`, as `ngtsc` emits namespaced imports `import * as __` from local modules which is not supported for the time being by API Extractor. See: https://github.com/Microsoft/web-build-tools/issues/1029
Ref: TOOL-611
PR Close#28588
The ultimate goal of this commit is to make use of fileNameToModuleName to
get the module specifier to use when generating an import, when that API is
available in the CompilerHost that ngtsc is created with.
As part of getting there, the way in which ngtsc tracks references and
generates import module specifiers is refactored considerably. References
are tracked with the Reference class, and previously ngtsc had several
different kinds of Reference. An AbsoluteReference represented a declaration
which needed to be imported via an absolute module specifier tracked in the
AbsoluteReference, and a RelativeReference represented a declaration from
the local program, imported via relative path or referred to directly by
identifier if possible. Thus, how to refer to a particular declaration was
encoded into the Reference type _at the time of creation of the Reference_.
This commit refactors that logic and reduces Reference to a single class
with no subclasses. A Reference represents a node being referenced, plus
context about how the node was located. This context includes a
"bestGuessOwningModule", the compiler's best guess at which absolute
module specifier has defined this reference. For example, if the compiler
arrives at the declaration of CommonModule via an import to @angular/common,
then any references obtained from CommonModule (e.g. NgIf) will also be
considered to be owned by @angular/common.
A ReferenceEmitter class and accompanying ReferenceEmitStrategy interface
are introduced. To produce an Expression referring to a given Reference'd
node, the ReferenceEmitter consults a sequence of ReferenceEmitStrategy
implementations.
Several different strategies are defined:
- LocalIdentifierStrategy: use local ts.Identifiers if available.
- AbsoluteModuleStrategy: if the Reference has a bestGuessOwningModule,
import the node via an absolute import from that module specifier.
- LogicalProjectStrategy: if the Reference is in the logical project
(is under the project rootDirs), import the node via a relative import.
- FileToModuleStrategy: use a FileToModuleHost to generate the module
specifier by which to import the node.
Depending on the availability of fileNameToModuleName in the CompilerHost,
then, a different collection of these strategies is used for compilation.
PR Close#28523
This commit introduces a new ngtsc sub-library, 'path', which contains
branded string types for the different kind of paths that ngtsc manipulates.
Having static types for these paths will reduce the number of path-related
bugs (especially on Windows) and will eliminate unnecessary defensive
normalizing.
See the README.md file for more detail.
PR Close#28523
Previously, ngtsc would throw an error if two decorators were matched on
the same class simultaneously. However, @Injectable is a special case, and
it appears frequently on component, directive, and pipe classes. For pipes
in particular, it's a common pattern to treat the pipe class also as an
injectable service.
ngtsc actually lacked the capability to compile multiple matching
decorators on a class, so this commit adds support for that. Decorator
handlers (and thus the decorators they match) are classified into three
categories: PRIMARY, SHARED, and WEAK.
PRIMARY handlers compile decorators that cannot coexist with other primary
decorators. The handlers for Component, Directive, Pipe, and NgModule are
marked as PRIMARY. A class may only have one decorator from this group.
SHARED handlers compile decorators that can coexist with others. Injectable
is the only decorator in this category, meaning it's valid to put an
@Injectable decorator on a previously decorated class.
WEAK handlers behave like SHARED, but are dropped if any non-WEAK handler
matches a class. The handler which compiles ngBaseDef is WEAK, since
ngBaseDef is only needed if a class doesn't otherwise have a decorator.
Tests are added to validate that @Injectable can coexist with the other
decorators and that an error is generated when mixing the primaries.
PR Close#28523
In the past, @Injectable had no side effects and existing Angular code is
therefore littered with @Injectable usage on classes which are not intended
to be injected.
A common example is:
@Injectable()
class Foo {
constructor(private notInjectable: string) {}
}
and somewhere else:
providers: [{provide: Foo, useFactory: ...})
Here, there is no need for Foo to be injectable - indeed, it's impossible
for the DI system to create an instance of it, as it has a non-injectable
constructor. The provider configures a factory for the DI system to be
able to create instances of Foo.
Adding @Injectable in Ivy signifies that the class's own constructor, and
not a provider, determines how the class will be created.
This commit adds logic to compile classes which are marked with @Injectable
but are otherwise not injectable, and create an ngInjectableDef field with
a factory function that throws an error. This way, existing code in the wild
continues to compile, but if someone attempts to use the injectable it will
fail with a useful error message.
In the case where strictInjectionParameters is set to true, a compile-time
error is thrown instead of the runtime error, as ngtsc has enough
information to determine when injection couldn't possibly be valid.
PR Close#28523
Translation of WriteKeyExpr expressions was not implemented in the ngtsc
expression translator. This resulted in binding expressions like
"target[key] = $event" not compiling.
This commit fixes the bug by implementing WriteKeyExpr translation.
PR Close#28523
Some applications use enum values in their host bindings:
@Component({
host: {
'[prop]': EnumType.Key,
}, ...
})
This commit changes the resolution of host properties to follow the enum
declaration and extract the correct value for the binding.
PR Close#28523
Testing of Ivy revealed two bugs in the AstMemoryEfficientTransformer
class, a part of existing View Engine compiler infrastructure that's
reused in Ivy. These bugs cause AST expressions not to be transformed
under certain circumstances.
The fix is simple, and tests are added to ensure the specific expression
forms that trigger the issue compile properly under Ivy.
PR Close#28523
While marking a given views tree as dirty we should go all the way to the
root of the views tree and cross boundaries of dynamically inserted views.
In other words the markForCheck functionality should consider parents of
dynamically inserted views.
PR Close#28687
Prior to this change we used current injector implementation for module injector, which was causing problems and produces circular dependencies in case the same token is referenced (with @SkipSelf flag) in the `deps` array. The origin of the problem was that once `directiveInject` implementation becomes active, it was used for module injector as well, thus searching deps in Component/Directive DI scope. This fix sets `injectInjectorOnly` implementation for module injector to resolve the problem.
PR Close#28667
Prior to this update we had separate contentQueries and contentQueriesRefresh functions to handle creation and update phases. This approach was inconsistent with View Queries, Host Bindings and Template functions that we generate for Component/Directive defs. Now the mentioned 2 functions are combines into one (contentQueries), creation and update logic is separated with RenderFlags (similar to what we have in other generated functions).
PR Close#28503
This commit fixes a bug whereby recompilation occurs every time `yarn ng build`
or `yarn bazel build ...` is invoked.
This is a temporary solution until # https://github.com/bazelbuild/bazel/issues/7026
is fixed.
PR Close#28675
`multi_sass_binary` rules is reinstated in rules_sass v1.17.0
and it is a better solution than list comprehension currently used
because it handles imports correctly.
PR Close#28669
For TypeScript compilation units that have the "strictFunctionTypes"
option enabled, an error would be produced for Ivy's definition fields
in declaration files in the case of inheritance across directives or
pipes.
This change loosens the definition types to allow for subtypes of the
defined type where necessary.
A test package that has the "strict" option enabled verifies that we
won't regress in environments where strict type checking is enabled.
Fixes#28079
PR Close#28634
With #28594 we refactored the `@angular/compiler` slightly to
allow opting out from external symbol re-exports which are
enabled by default.
Since symbol re-exports only benefit projects which have a
very strict dependency enforcement, external symbols should
not be re-exported by default as this could grow the size of
factory files and cause unexpected behavior with Angular's
AOT symbol resolving (e.g. see: #25644).
Note that the common strict dependency enforcement for source
files does still work with external symbol re-exports disabled,
but there are also strict dependency checks that enforce strict
module dependencies also for _generated files_ (such as the
ngfactory files). This is how Google3 manages it's dependencies
and therefore external symbol re-exports need to be enabled within
Google3.
Also "ngtsc" also does not provide any way of using external symbol
re-exports, so this means that with this change, NGC can partially
match the behavior of "ngtsc" then (unless explicitly opted-out).
As mentioned before, internally at Google symbol re-exports need to
be still enabled, so the `ng_module` Bazel rule will enable the symbol
re-exports by default when running within Blaze.
Fixes#25644.
PR Close#28633
Previously, using a pipe in an input binding on an ng-template would
evaluate the pipe in the context of node that was processed before the
template. This caused the retrieval of e.g. ChangeDetectorRef to be
incorrect, resulting in one of the following bugs depending on the
template's structure:
1. If the template was at the root of a view, the previously processed
node would be the component's host node outside of the current view.
Accessing that node in the context of the current view results in a crash.
2. For templates not at the root, the ChangeDetectorRef injected into the
pipe would correspond with the previously processed node. If that node
hosts a component, the ChangeDetectorRef would not correspond with the
view that the ng-template is part of.
The solution to the above problem is two-fold:
1. Template compilation is adjusted such that the template instruction
is emitted before any instructions produced by input bindings, such as
pipes. This ensures that pipes are evaluated in the context of the
template's container node.
2. A ChangeDetectorRef can be requested for container nodes.
Fixes#28587
PR Close#27565
During analysis, the `ComponentDecoratorHandler` passes the component
template to the `parseTemplate()` function. Previously, there was little or
no information about the original source file, where the template is found,
passed when calling this function.
Now, we correctly compute the URL of the source of the template, both
for external `templateUrl` and in-line `template` cases. Further in the
in-line template case we compute the character range of the template
in its containing source file; *but only in the case that the template is
a simple string literal*. If the template is actually a dynamic value like
an interpolated string or a function call, then we do not try to add the
originating source file information.
The translator that converts Ivy AST nodes to TypeScript now adds these
template specific source mappings, which account for the file where
the template was found, to the templates to support stepping through the
template creation and update code when debugging an Angular application.
Note that some versions of TypeScript have a bug which means they cannot
support external template source-maps. We check for this via the
`canSourceMapExternalTemplates()` helper function and avoid trying to
add template mappings to external templates if not supported.
PR Close#28055
When template bindings are being parsed the event handlers
were receiving a source span that included the whole attribute.
Now they get a span that is focussed on the handler itself.
PR Close#28055
The `convertActionBinding()` now accepts an optional `baseSourceSpan`,
which is the start point of the action expression being converted in the
original source code. This is used to compute the original position of
the output AST nodes.
PR Close#28055
When tokenizing markup (e.g. HTML) element attributes
can have quoted or unquoted values (e.g. `a=b` or `a="b"`).
The `ATTR_VALUE` tokens were capturing the quotes, which
was inconsistent and also affected source-mapping.
Now the tokenizer captures additional `ATTR_QUOTE` tokens,
which the HTML related parsers understand and factor into their
token parsing.
PR Close#28055
There are some differences in how ivy maps template source
compared to View Engine. In this commit we recreate the View Engine
tests for ivy.
PR Close#28055
Previously the call to `extractSourceMap()` would only work if the
`//#sourceMappingURL ...` was the last line of the file. This doesn't
work if the code is JIT evaluated as the comment is actually the last
line in the body of a function, wrapped by curly-braces.
PR Close#28055
When testing JIT code, it is useful to be able to access the
generated JIT source. Previously this is done by spying on the
global `Function` object, to capture the code when it is being
evaluated. This is problematic because you can only capture
the body of the function, and not the arguments, which messes
up line and column positions for source mapping for instance.
Now the code that generates and then evaluates JIT code is
wrapped in a `JitEvaluator` class, making it possible to provide
a mock implementation that can capture the generated source of
the function passed to `executeFunction(fn: Function, args: any[])`.
PR Close#28055
When we resolve a component `templateUrl` we copy the contents of the
resolved template file into the `template` property.
Previously we would then remove the `templateUrl` to indicate that
the component has been resolved. But this meant that we no longer had
access to the URL of the original template file. This is essential for
diagnostics messages about the template compilation.
Now the existence of the `template` property overrides the existence of
`templateUrl`, which allows us to keep the `templateUrl` property.
PR Close#28055
In order to support source mapping of templates, we need
to be able to tokenize the template in its original context.
When the template is defined inline as a JavaScript string
in a TS/JS source file, the tokenizer must be able to handle
string escape sequences, such as `\n` and `\"` as they
appear in the original source file.
This commit teaches the lexer how to unescape these
sequences, but only when the `escapedString` option is
set to true. Otherwise there is no change to the tokenizing
behaviour.
PR Close#28055
The lexer that does the tokenizing can now process only a part the source
string, by passing a `range` property in the `options` argument. The
locations of the nodes that are tokenized will now take into account the
position of the span in the context of the original source string.
This `range` option is, in turn, exposed from the template parser as well.
Being able to process parts of files helps to enable SourceMap support
when compiling inline component templates.
PR Close#28055
When we added the strict null checks, the lexer had some `!`
operators added to prevent the compilation from failing.
This commit resolves this problem correctly and removes the
hacks.
Also the comment
```
// Note: this is always lowercase!
```
has been removed as it is no longer true.
See #24571
PR Close#28055
This commit consolidates the options that can modify the
parsing of text (e.g. HTML, Angular templates, CSS, i18n)
into an AST for further processing into a single `options`
hash.
This makes the code cleaner and more readable, but also
enables us to support further options to parsing without
triggering wide ranging changes to code that should not
be affected by these new options. Specifically, it will let
us pass information about the placement of a template
that is being parsed in its containing file, which is essential
for accurate SourceMap processing.
PR Close#28055
Due to the fact that host nodes no longer match in ContentChild queries in Ivy, we disable test that was enabled previously in other commit.
PR Close#28660
I don't know of any use of this API with a project-root-relative path
(i.e. the cli will always call it with an absolute path), but keeping
the API backwards compatible just in case.
PR Close#28542