Commit Graph

359 Commits

Author SHA1 Message Date
Alex Rickabaugh bb290cefae fix(core): make QueryList implement Iterable in the type system (#33536)
Originally, QueryList implemented Iterable and provided a Symbol.iterator
on its prototype. This caused issues with tree-shaking, so QueryList was
refactored and the Symbol.iterator added in its constructor instead. As
part of this change, QueryList no longer implemented Iterable directly.

Unfortunately, this meant that QueryList was no longer assignable to
Iterable or, consequently, NgIterable. NgIterable is used for NgFor's input,
so this meant that QueryList was not usable (in a type sense) for NgFor
iteration. View Engine's template type checking would not catch this, but
Ivy's did.

As a fix, this commit adds the declaration (but not the implementation) of
the Symbol.iterator function back to QueryList. This has no runtime effect,
so it doesn't affect tree-shaking of QueryList, but it ensures that
QueryList is assignable to NgIterable and thus usable with NgFor.

Fixes #29842

PR Close #33536
2019-11-19 13:43:53 -08:00
Alex Rickabaugh 850aee2448 fix(ivy): emit fs-relative paths when rootDir(s) aren't in effect (#33828)
Previously, the compiler assumed that all TS files logically within a
project existed under one or more "root directories". If the TS compiler
option `rootDir` or `rootDirs` was set, they would dictate the root
directories in use, otherwise the current directory was used.

Unfortunately this assumption was unfounded - it's common for projects
without explicit `rootDirs` to import from files outside the current
working directory. In such cases the `LogicalProjectStrategy` would attempt
to generate imports into those files, and fail. This would lead to no
`ReferenceEmitStrategy` being able to generate an import, and end in a
compiler assertion failure.

This commit introduces a new strategy to use when there are no `rootDirs`
explicitly present, the `RelativePathStrategy`. It uses simpler, filesystem-
relative paths to generate imports, even to files above the current working
directory.

Fixes #33659
Fixes #33562

PR Close #33828
2019-11-19 12:41:24 -08:00
Alex Rickabaugh 51720745dd test(ivy): support chdir() on the compiler's filesystem abstraction (#33828)
This commit adds the ability to change directories using the compiler's
internal filesystem abstraction. This is a prerequisite for writing tests
which are sensitive to the current working directory.

In addition to supporting the `chdir()` operation, this commit also fixes
`getDefaultLibLocation()` for mock filesystems to not assume `node_modules`
is in the current directory, but to resolve it similarly to how Node does
by progressively looking higher in the directory tree.

PR Close #33828
2019-11-19 12:41:24 -08:00
George Kalpakas c79d50f38f refactor(compiler-cli): avoid superfluous parenthesis around statements (#33514)
Previously, due to a bug a `Context` with `isStatement: false` could be
returned in places where a `Context` with `isStatement: true` was
requested. As a result, some statements would be unnecessarily wrapped
in parenthesis.

This commit fixes the bug in `Context#withStatementMode` to always
return a `Context` with the correct `isStatement` value. Note that this
does not have any impact on the generated code other than avoiding some
superfluous parenthesis on certain statements.

PR Close #33514
2019-11-13 13:49:30 -08:00
JoostK 15f8638b1c fix(ivy): ensure module scope is rebuild on dependent change (#33522)
During incremental compilations, ngtsc needs to know which metadata
from a previous compilation can be reused, versus which metadata has to
be recomputed as some dependency was updated. Changes to
directives/components should cause the NgModule in which they are
declared to be recompiled, as the NgModule's compilation is dependent
on its directives/components.

When a dependent source file of a directive/component is updated,
however, a more subtle dependency should also cause to NgModule's source
file to be invalidated. During the reconciliation of state from a
previous compilation into the new program, the component's source file
is invalidated because one of its dependency has changed, ergo the
NgModule needs to be invalidated as well. Up until now, this implicit
dependency was not imposed on the NgModule. Additionally, any change to
a dependent file may influence the module scope to change, so all
components within the module must be invalidated as well.

This commit fixes the bug by introducing additional file dependencies,
as to ensure a proper rebuild of the module scope and its components.

Fixes #32416

PR Close #33522
2019-11-12 13:56:30 -08:00
crisbeto e31f62045d perf(ivy): chain listener instructions (#33720)
Chains multiple listener instructions on a particular element into a single call which results in less generated code. Also handles listeners on templates, host listeners and synthetic host listeners.

PR Close #33720
2019-11-12 09:59:13 -08:00
Charles Lyding fc8eecad3f fix(compiler-cli): remove unused CLI private exports (#33242)
These exports are no longer used by the CLI since 7.1.0.  Since major versions of the CLI are now locked to major versions of the framework, a CLI user will not be able to use FW 9.0+ on an outdated version (<7.1.0) of the CLI that uses these old APIs.

PR Close #33242
2019-11-01 17:43:47 +00:00
Alex Rickabaugh 38758d856a fix(ivy): don't crash on unknown pipe (#33454)
Previously the compiler would crash if a pipe was encountered which did not
match any pipe in the scope of a template.

This commit introduces a new diagnostic error for unknown pipes instead.

PR Close #33454
2019-10-31 23:43:32 +00:00
Alex Rickabaugh 9db59d010d fix(ivy): don't crash on an unknown localref target (#33454)
Previously the template binder would crash when encountering an unknown
localref (# reference) such as `<div #ref="foo">` when no directive has
`exportAs: "foo"`.

With this commit, the compiler instead generates a template diagnostic error
informing the user about the invalid reference.

PR Close #33454
2019-10-31 23:43:32 +00:00
Pete Bacon Darwin 1d141a8ab1 fix(compiler-cli): attach the correct `viaModule` to namespace imports (#33495)
Previously declarations that were imported via a namespace import
were given the same `bestGuessOwningModule` as the context
where they were imported to. This causes problems with resolving
`ModuleWithProviders` that have a type that has been imported in
this way, causing errors like:

```
ERROR in Symbol UIRouterModule declared in
.../@uirouter/angular/uiRouterNgModule.d.ts
is not exported from
.../@uirouter/angular/uirouter-angular.d.ts
(import into .../src/app/child.module.ts)
```

This commit modifies the `TypescriptReflectionHost.getDirectImportOfIdentifier()`
method so that it also understands how to attach the correct `viaModule` to
the identifier of the namespace import.

Resolves #32166

PR Close #33495
2019-10-31 22:25:48 +00:00
crisbeto c3e93564d0 perf(ivy): avoid generating selectors array for directives without a selector (#33431)
Now that we've replaced `ngBaseDef` with an abstract directive definition, there are a lot more cases where we generate a directive definition without a selector. These changes make it so that we don't generate the `selectors` array if it's going to be empty.

PR Close #33431
2019-10-29 12:06:15 -07:00
crisbeto 14c4b1b205 refactor(ivy): remove ngBaseDef (#33264)
Removes `ngBaseDef` from the compiler and any runtime code that was still referring to it. In the cases where we'd previously generate a base def we now generate a definition for an abstract directive.

PR Close #33264
2019-10-25 13:11:34 -07:00
JoostK 8d15bfa6ee fix(ivy): allow abstract directives to have an invalid constructor (#32987)
For abstract directives, i.e. directives without a selector, it may
happen that their constructor is called explicitly from a subclass,
hence its parameters are not required to be valid for Angular's DI
purposes. Prior to this commit however, having an abstract directive
with a constructor that has parameters that are not eligible for
Angular's DI would produce a compilation error.

A similar scenario may occur for `@Injectable`s, where an explicit
`use*` definition allows for the constructor to be irrelevant. For
example, the situation where `useFactory` is specified allows for the
constructor to be called explicitly with any value, so its constructor
parameters are not required to be valid. For `@Injectable`s this is
handled by generating a DI factory function that throws.

This commit implements the same solution for abstract directives, such
that a compilation error is avoided while still producing an error at
runtime if the type is instantiated implicitly by Angular's DI
mechanism.

Fixes #32981

PR Close #32987
2019-10-25 12:13:23 -07:00
JoostK 0d9be22023 feat(ivy): strictness flags for template type checking (#33365)
The template type checking abilities of the Ivy compiler are far more
advanced than the level of template type checking that was previously
done for Angular templates. Up until now, a single compiler option
called "fullTemplateTypeCheck" was available to configure the level
of template type checking. However, now that more advanced type checking
is being done, new errors may surface that were previously not reported,
in which case it may not be feasible to fix all new errors at once.

Having only a single option to disable a large number of template type
checking capabilities does not allow for incrementally addressing newly
reported types of errors. As a solution, this commit introduces some new
compiler options to be able to enable/disable certain kinds of template
type checks on a fine-grained basis.

PR Close #33365
2019-10-24 16:16:14 -07:00
JoostK 4aa51b751b feat(ivy): verify whether TypeScript version is supported (#33377)
During the creation of an Angular program in the compiler, a check is
done to verify whether the version of TypeScript is considered
supported, producing an error if it is not. This check was missing in
the Ivy compiler, so users may have ended up running an unsupported
TypeScript version inadvertently.

Resolves FW-1643

PR Close #33377
2019-10-24 15:46:23 -07:00
JoostK a42057d0f8 fix(ivy): support abstract directives in template type checking (#33131)
Recently it was made possible to have a directive without selector,
which are referred to as abstract directives. Such directives should not
be registered in an NgModule, but can still contain decorators for
inputs, outputs, queries, etc. The information from these decorators and
the `@Directive()` decorator itself needs to be registered with the
central `MetadataRegistry` so that other areas of the compiler can
request information about a given directive, an example of which is the
template type checker that needs to know about the inputs and outputs of
directives.

Prior to this change, however, abstract directives would only register
themselves with the `MetadataRegistry` as being an abstract directive,
without all of its other metadata like inputs and outputs. This meant
that the template type checker was unable to resolve the inputs and
outputs of these abstract directives, therefore failing to check them
correctly. The typical error would be that some property does not exist
on a DOM element, whereas said property should have been bound to the
abstract directive's input.

This commit fixes the problem by always registering the metadata of a
directive or component with the `MetadataRegistry`. Tests have been
added to ensure abstract directives are handled correctly in the
template type checker, together with tests to verify the form of
abstract directives in declaration files.

Fixes #30080

PR Close #33131
2019-10-24 12:44:30 -07:00
Alex Rickabaugh f1269d98dc feat(ivy): input type coercion for template type-checking (#33243)
Often the types of an `@Input`'s field don't fully reflect the types of
assignable values. This can happen when an input has a getter/setter pair
where the getter always returns a narrow type, and the setter coerces a
wider value down to the narrow type.

For example, you could imagine an input of the form:

```typescript
@Input() get value(): string {
  return this._value;
}

set value(v: {toString(): string}) {
  this._value = v.toString();
}
```

Here, the getter always returns a `string`, but the setter accepts any value
that can be `toString()`'d, and coerces it to a string.

Unfortunately TypeScript does not actually support this syntax, and so
Angular users are forced to type their setters as narrowly as the getters,
even though at runtime the coercion works just fine.

To support these kinds of patterns (e.g. as used by Material), this commit
adds a compiler feature called "input coercion". When a binding is made to
the 'value' input of a directive like MatInput, the compiler will look for a
static field with the name ngAcceptInputType_value. If such a field is found
the type-checking expression for the input will use the static field's type
instead of the type for the @Input field,allowing for the expression of a
type conversion between the binding expression and the value being written
to the input's field.

To solve the case above, for example, MatInput might write:

```typescript
class MatInput {
  // rest of the directive...

  static ngAcceptInputType_value: {toString(): string};
}
```

FW-1475 #resolve

PR Close #33243
2019-10-24 09:49:38 -07:00
Paul Gschwendtner 355e54a410 fix(compiler): do not throw when using abstract directive from other compilation unit (#33347)
Libraries can expose directive/component base classes that will be
used by consumer applications. Using such a base class from another
compilation unit works fine with "ngtsc", but when using "ngc", the
compiler will thrown an error saying that the base class is not
part of a NgModule. e.g.

```
Cannot determine the module for class X in Y! Add X to the NgModule to fix it.
```

This seems to be because the logic for distinguishing directives from
abstract directives is scoped to the current compilation unit within
ngc. This causes abstract directives from other compilation units to
be considered as actual directives (causing the exception).

PR Close #33347
2019-10-23 11:59:24 -07:00
Pete Bacon Darwin 5d86e4a9b1 fix(compiler): ensure that legacy ids are rendered for ICUs (#33318)
When computing i18n messages for templates there are two passes.
This is because messages must be computed before any whitespace
is removed. Then on a second pass, the messages must be recreated
but reusing the message ids from the first pass.

Previously ICUs were losing their legacy ids that had been computed
via the first pass. This commit fixes that by keeping track of the
message from the first pass (`previousMessage`) for ICU placeholder
nodes.

// FW-1637

PR Close #33318
2019-10-22 13:30:16 -04:00
Alex Rickabaugh c4733c15c0 feat(ivy): enable re-export of the compilation scope of NgModules privately (#33177)
This commit refactors the aliasing system to support multiple different
AliasingHost implementations, which control specific aliasing behavior
in ngtsc (see the README.md).

A new host is introduced, the `PrivateExportAliasingHost`. This solves a
longstanding problem in ngtsc regarding support for "monorepo" style private
libraries. These are libraries which are compiled separately from the main
application, and depended upon through TypeScript path mappings. Such
libraries are frequently not in the Angular Package Format and do not have
entrypoints, but rather make use of deep import style module specifiers.
This can cause issues with ngtsc's ability to import a directive given the
module specifier of its NgModule.

For example, if the application uses a directive `Foo` from such a library
`foo`, the user might write:

```typescript
import {FooModule} from 'foo/module';
```

In this case, foo/module.d.ts is path-mapped into the program. Ordinarily
the compiler would see this as an absolute module specifier, and assume that
the `Foo` directive can be imported from the same specifier. For such non-
APF libraries, this assumption fails. Really `Foo` should be imported from
the file which declares it, but there are two problems with this:

1. The compiler would have to reverse the path mapping in order to determine
   a path-mapped path to the file (maybe foo/dir.d.ts).
2. There is no guarantee that the file containing the directive is path-
   mapped in the program at all.

The compiler would effectively have to "guess" 'foo/dir' as a module
specifier, which may or may not be accurate depending on how the library and
path mapping are set up.

It's strongly desirable that the compiler not break its current invariant
that the module specifier given by the user for the NgModule is always the
module specifier from which directives/pipes are imported. Thus, for any
given NgModule from a particular module specifier, it must always be
possible to import any directives/pipes from the same specifier, no matter
how it's packaged.

To make this possible, when compiling a file containing an NgModule, ngtsc
will automatically add re-exports for any directives/pipes not yet exported
by the user, with a name of the form: ɵngExportɵModuleNameɵDirectiveName

This has several effects:

1. It guarantees anyone depending on the NgModule will be able to import its
   directives/pipes from the same specifier.
2. It maintains a stable name for the exported symbol that is safe to depend
   on from code on NPM. Effectively, this private exported name will be a
   part of the package's .d.ts API, and cannot be changed in a non-breaking
   fashion.

Fixes #29361
FW-1610 #resolve

PR Close #33177
2019-10-22 13:14:31 -04:00
Matias Niemelä c0ebecf54d revert: feat(ivy): input type coercion for template type-checking (#33243) (#33299)
This reverts commit 1b4eaea6d4.

PR Close #33299
2019-10-21 12:00:24 -04:00
Alex Rickabaugh 1b4eaea6d4 feat(ivy): input type coercion for template type-checking (#33243)
Often the types of an `@Input`'s field don't fully reflect the types of
assignable values. This can happen when an input has a getter/setter pair
where the getter always returns a narrow type, and the setter coerces a
wider value down to the narrow type.

For example, you could imagine an input of the form:

```typescript
@Input() get value(): string {
  return this._value;
}

set value(v: {toString(): string}) {
  this._value = v.toString();
}
```

Here, the getter always returns a `string`, but the setter accepts any value
that can be `toString()`'d, and coerces it to a string.

Unfortunately TypeScript does not actually support this syntax, and so
Angular users are forced to type their setters as narrowly as the getters,
even though at runtime the coercion works just fine.

To support these kinds of patterns (e.g. as used by Material), this commit
adds a compiler feature called "input coercion". When a binding is made to
the 'value' input of a directive like MatInput, the compiler will look for a
static function with the name ngCoerceInput_value. If such a function is
found, the type-checking expression for the input will be wrapped in a call
to the function, allowing for the expression of a type conversion between
the binding expression and the value being written to the input's field.

To solve the case above, for example, MatInput might write:

```typescript
class MatInput {
  // rest of the directive...

  static ngCoerceInput_value(value: {toString(): string}): string {
    return null!;
  }
}
```

FW-1475 #resolve

PR Close #33243
2019-10-21 11:25:07 -04:00
Alex Rickabaugh d4db746898 feat(ivy): give shim generation its own compiler options (#33256)
As a hack to get the Ivy compiler ngtsc off the ground, the existing
'allowEmptyCodegenFiles' option was used to control generation of ngfactory
and ngsummary shims during compilation. This option was selected since it's
enabled in google3 but never enabled in external projects.

As ngtsc is now mature and the role shims play in compilation is now better
understood across the ecosystem, this commit introduces two new compiler
options to control shim generation:

* generateNgFactoryShims controls the generation of .ngfactory shims.
* generateNgSummaryShims controls the generation of .ngsummary shims.

The 'allowEmptyCodegenFiles' option is still honored if either of the above
flags are not set explicitly.

PR Close #33256
2019-10-21 11:24:26 -04:00
crisbeto 0e08ad628a fix(ivy): throw better error for missing generic type in ModuleWithProviders (#33187)
Currently if a `ModuleWithProviders` is missng its generic type, we throw a cryptic error like:

```
error TS-991010: Value at position 3 in the NgModule.imports of TodosModule is not a reference: [object Object]
```

These changes add a better error to make it easier to debug.

PR Close #33187
2019-10-18 14:49:54 -04:00
JoostK 6958d11d95 feat(ivy): type checking of event bindings (#33125)
Until now, the template type checker has not checked any of the event
bindings that could be present on an element, for example

```
<my-cmp
  (changed)="handleChange($event)"
  (click)="handleClick($event)"></my-cmp>
```

has two event bindings: the `change` event corresponding with an
`@Output()` on the `my-cmp` component and the `click` DOM event.

This commit adds functionality to the template type checker in order to
type check both kind of event bindings. This means that the correctness
of the bindings expressions, as well as the type of the `$event`
variable will now be taken into account during template type checking.

Resolves FW-1598

PR Close #33125
2019-10-18 14:41:53 -04:00
crisbeto 9d54679e66 test: clean up explicit dynamic query usages (#33015)
Cleans up all the places where we explicitly set `static: false` on queries.

PR Close #33015
2019-10-17 16:10:10 -04:00
Kara Erickson 86104b82b8 refactor(core): rename ngInjectableDef to ɵprov (#33151)
Injectable defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.

This commit adds the prefix and shortens the name from
ngInjectableDef to "prov" (for "provider", since injector defs
are known as "inj"). This is because property names cannot
be minified by Uglify without turning on property mangling
(which most apps have turned off) and are thus size-sensitive.

PR Close #33151
2019-10-16 16:36:19 -04:00
Kara Erickson cda9248b33 refactor(core): rename ngInjectorDef to ɵinj (#33151)
Injector defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.

This commit adds the prefix and shortens the name from
ngInjectorDef to inj. This is because property names
cannot be minified by Uglify without turning on property
mangling (which most apps have turned off) and are thus
size-sensitive.

PR Close #33151
2019-10-16 16:36:19 -04:00
Pete Bacon Darwin ad72c90447 fix(ivy): i18n - add XLIFF aliases for legacy message id support (#33160)
The `legacyMessageIdFormat` is taken from the `i18nInFormat` property but we were only considering
`xmb`, `xlf` and `xlf2` values.

The CLI also supports `xliff` and `xliff2` values for the
`i18nInFormat`.

This commit adds support for those aliases.

PR Close #33160
2019-10-15 21:04:17 +00:00
Kara Erickson fc93dafab1 refactor(core): rename ngModuleDef to ɵmod (#33142)
Module defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.

This commit adds the prefix and shortens the name from
ngModuleDef to mod. This is because property names
cannot be minified by Uglify without turning on property
mangling (which most apps have turned off) and are thus
size-sensitive.

PR Close #33142
2019-10-14 23:08:10 +00:00
Kara Erickson d62eff7316 refactor(core): rename ngPipeDef to ɵpipe (#33142)
Pipe defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.

This commit adds the prefix and shortens the name from
ngPipeDef to pipe. This is because property names
cannot be minified by Uglify without turning on property
mangling (which most apps have turned off) and are thus
size-sensitive.

PR Close #33142
2019-10-14 23:08:10 +00:00
Kara Erickson 0de2a5e408 refactor(core): rename ngFactoryDef to ɵfac (#33116)
Factory defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.

This commit adds the prefix and shortens the name from
ngFactoryDef to fac. This is because property names
cannot be minified by Uglify without turning on property
mangling (which most apps have turned off) and are thus
size-sensitive.

Note that the other "defs" (ngPipeDef, etc) will be
prefixed and shortened in follow-up PRs, in an attempt to
limit how large and conflict-y this change is.

PR Close #33116
2019-10-14 20:27:25 +00:00
JoostK cd7b199219 feat(ivy): check regular attributes that correspond with directive inputs (#33066)
Prior to this change, a static attribute that corresponds with a
directive's input would not be type-checked against the type of the
input. This is unfortunate, as a static value always has type `string`,
whereas the directive's input type might be something different. This
typically occurs when a developer forgets to enclose the attribute name
in brackets to make it a property binding.

This commit lets static attributes be considered as bindings with string
values, so that they will be properly type-checked.

PR Close #33066
2019-10-14 20:25:20 +00:00
JoostK 50bf17aca0 fix(ivy): do not always accept `undefined` for directive inputs (#33066)
Prior to this change, the template type checker would always allow a
value of type `undefined` to be passed into a directive's inputs, even
if the input's type did not allow for it. This was due to how the type
constructor for a directive was generated, where a `Partial` mapped
type was used to allow for inputs to be unset. This essentially
introduces the `undefined` type as acceptable type for all inputs.

This commit removes the `Partial` type from the type constructor, which
means that we can no longer omit any properties that were unset.
Instead, any properties that are not set will still be included in the
type constructor call, having their value assigned to `any`.

Before:

```typescript
class NgForOf<T> {
  static ngTypeCtor<T>(init: Partial<Pick<NgForOf<T>,
    'ngForOf'|'ngForTrackBy'|'ngForTemplate'>>): NgForOf<T>;
}

NgForOf.ngTypeCtor(init: {ngForOf: ['foo', 'bar']});
```

After:

```typescript
class NgForOf<T> {
  static ngTypeCtor<T>(init: Pick<NgForOf<T>,
    'ngForOf'|'ngForTrackBy'|'ngForTemplate'>): NgForOf<T>;
}

NgForOf.ngTypeCtor(init: {
  ngForOf: ['foo', 'bar'],
  ngForTrackBy: null as any,
  ngForTemplate: null as any,
});
```

This change only affects generated type check code, the generated
runtime code is not affected.

Fixes #32690
Resolves FW-1606

PR Close #33066
2019-10-14 20:25:20 +00:00
Kara Erickson 1a67d70bf8 refactor(core): rename ngDirectiveDef to ɵdir (#33110)
Directive defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.

This commit adds the prefix and shortens the name from
ngDirectiveDef to dir. This is because property names
cannot be minified by Uglify without turning on property
mangling (which most apps have turned off) and are thus
size-sensitive.

Note that the other "defs" (ngFactoryDef, etc) will be
prefixed and shortened in follow-up PRs, in an attempt to
limit how large and conflict-y this change is.

PR Close #33110
2019-10-14 16:20:11 +00:00
JoostK d8249d1230 feat(ivy): better error messages for unknown components (#33064)
For elements in a template that look like custom elements, i.e.
containing a dash in their name, the template type checker will now
issue an error with instructions on how the resolve the issue.
Additionally, a property binding to a non-existent property will also
produce a more descriptive error message.

Resolves FW-1597

PR Close #33064
2019-10-14 16:19:13 +00:00
Kara Erickson 64fd0d6db9 refactor(core): rename ngComponentDef to ɵcmp (#33088)
Component defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.

This commit adds the prefix and shortens the name from
`ngComponentDef` to `cmp`. This is because property names
cannot be minified by Uglify without turning on property
mangling (which most apps have turned off) and are thus
size-sensitive.

Note that the other "defs" (ngDirectiveDef, etc) will be
prefixed and shortened in follow-up PRs, in an attempt to
limit how large and conflict-y this change is.

PR Close #33088
2019-10-11 15:45:22 -07:00
Pete Bacon Darwin f640a4a494 fix(ivy): i18n - turn on legacy message-id support by default (#33053)
For v9 we want the migration to the new i18n to be as
simple as possible.

Previously the developer had to positively choose to use
legacy messsage id support in the case that their translation
files had not been migrated to the new format by setting the
`legacyMessageIdFormat` option in tsconfig.json to the format
of their translation files.

Now this setting has been changed to `enableI18nLegacyMessageFormat`
as is a boolean that defaults to `true`. The format is then read from
the `i18nInFormat` option, which was previously used to trigger translations
in the pre-ivy angular compiler.

PR Close #33053
2019-10-10 13:58:30 -07:00
crisbeto d5b87d32b0 perf(ivy): move attributes array into component def (#32798)
Currently Ivy stores the element attributes into an array above the component def and passes it into the relevant instructions, however the problem is that upon minification the array will get a unique name which won't compress very well. These changes move the attributes array into the component def and pass in the index into the instructions instead.

Before:
```
const _c0 = ['foo', 'bar'];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', 'bar']],
  template: function() {
    element(0, 'div', 0);
  }
});
```

A couple of cases that this PR doesn't handle:
* Template references are still in a separate array.
* i18n attributes are still in a separate array.

PR Close #32798
2019-10-09 13:16:55 -07:00
Pete Bacon Darwin bcbf3e4123 feat(ivy): i18n - render legacy message ids in `$localize` if requested (#32937)
The `$localize` library uses a new message digest function for
computing message ids. This means that translations in legacy
translation files will no longer match the message ids in the code
and so will not be translated.

This commit adds the ability to specify the format of your legacy
translation files, so that the appropriate message id can be rendered
in the `$localize` tagged strings. This results in larger code size
and requires that all translations are in the legacy format.

Going forward the developer should migrate their translation files
to use the new message id format.

PR Close #32937
2019-10-03 12:12:55 -07:00
crisbeto 4e35e348af refactor(ivy): generate ngFactoryDef for injectables (#32433)
With #31953 we moved the factories for components, directives and pipes into a new field called `ngFactoryDef`, however I decided not to do it for injectables, because they needed some extra logic. These changes set up the `ngFactoryDef` for injectables as well.

For reference, the extra logic mentioned above is that for injectables we have two code paths:

1. For injectables that don't configure how they should be instantiated, we create a `factory` that proxies to `ngFactoryDef`:

```
// Source
@Injectable()
class Service {}

// Output
class Service {
  static ngInjectableDef = defineInjectable({
    factory: () => Service.ngFactoryFn(),
  });

  static ngFactoryFn: (t) => new (t || Service)();
}
```

2. For injectables that do configure how they're created, we keep the `ngFactoryDef` and generate the factory based on the metadata:

```
// Source
@Injectable({
  useValue: DEFAULT_IMPL,
})
class Service {}

// Output
export class Service {
  static ngInjectableDef = defineInjectable({
    factory: () => DEFAULT_IMPL,
  });

  static ngFactoryFn: (t) => new (t || Service)();
}
```

PR Close #32433
2019-10-02 13:04:26 -07:00
Matias Niemelä 4f41473048 refactor(ivy): remove styling state storage and introduce direct style writing (#32591)
This patch is a final major refactor in styling Angular.

This PR includes three main fixes:

All temporary state taht is persisted between template style/class application
and style/class application in host bindings is now removed.
Removes the styling() and stylingApply() instructions.
Introduces a "direct apply" mode that is used apply prop-based
style/class in the event that there are no map-based bindings as
well as property collisions.

PR Close #32259

PR Close #32591
2019-09-16 14:12:48 -07:00
Matias Niemelä 53dbff66d7 revert: refactor(ivy): remove styling state storage and introduce direct style writing (#32259)
This reverts commit 15aeab1620.
2019-09-11 15:24:10 -07:00
Matias Niemelä 15aeab1620 refactor(ivy): remove styling state storage and introduce direct style writing (#32259) (#32596)
This patch is a final major refactor in styling Angular.

This PR includes three main fixes:

All temporary state taht is persisted between template style/class application
and style/class application in host bindings is now removed.
Removes the styling() and stylingApply() instructions.
Introduces a "direct apply" mode that is used apply prop-based
style/class in the event that there are no map-based bindings as
well as property collisions.

PR Close #32259

PR Close #32596
2019-09-11 16:27:10 -04:00
Matias Niemelä c84c27f7f4 revert: refactor(ivy): remove styling state storage and introduce direct style writing (#32259) 2019-09-10 18:08:05 -04:00
Matias Niemelä 3b37469735 refactor(ivy): remove styling state storage and introduce direct style writing (#32259)
This patch is a final major refactor in styling Angular.

This PR includes three main fixes:

All temporary state taht is persisted between template style/class application
and style/class application in host bindings is now removed.
Removes the styling() and stylingApply() instructions.
Introduces a "direct apply" mode that is used apply prop-based
style/class in the event that there are no map-based bindings as
well as property collisions.

PR Close #32259
2019-09-10 15:54:58 -04:00
JoostK a64eded521 fix(ivy): capture template source mapping details during preanalysis (#32544)
Prior to this change, the template source mapping details were always
built during the analysis phase, under the assumption that pre-analysed
templates would always correspond with external templates. This has
turned out to be a false assumption, as inline templates are also
pre-analyzed to be able to preload any stylesheets included in the
template.

This commit fixes the bug by capturing the template source mapping
details at the moment the template is parsed, which is either during the
preanalysis phase when preloading is available, or during the analysis
phase when preloading is not supported.

Tests have been added to exercise the template error mapping in
asynchronous compilations where preloading is enabled, similar to how
the CLI performs compilations.

Fixes #32538

PR Close #32544
2019-09-09 19:10:34 -04:00
Kristiyan Kostadinov c885178d5f refactor(ivy): move directive, component and pipe factories to ngFactoryFn (#31953)
Reworks the compiler to output the factories for directives, components and pipes under a new static field called `ngFactoryFn`, instead of the usual `factory` property in their respective defs. This should eventually allow us to inject any kind of decorated class (e.g. a pipe).

**Note:** these changes are the first part of the refactor and they don't include injectables. I decided to leave injectables for a follow-up PR, because there's some more cases we need to handle when it comes to their factories. Furthermore, directives, components and pipes make up most of the compiler output tests that need to be refactored and it'll make follow-up PRs easier to review if the tests are cleaned up now.

This is part of the larger refactor for FW-1468.

PR Close #31953
2019-08-27 13:57:00 -07:00
Paul Gschwendtner 4f7c971ee7 fix(ivy): ngtsc throws if "flatModuleOutFile" is set to null (#32235)
In ngc is was valid to set the "flatModuleOutFile" option to "null". This is sometimes
necessary if a tsconfig extends from another one but the "fatModuleOutFile" option
needs to be unset (note that "undefined" does not exist as value in JSON)

Now if ngtsc is used to compile the project, ngtsc will fail with an error because it
tries to do string manipulation on the "flatModuleOutFile". This happens because
ngtsc only skips flat module indices if the option is set to "undefined".

Since this is not compatible with what was supported in ngc and such exceptions
should be avoided, the flat module check is now aligned with ngc.

```
TypeError: Cannot read property 'replace' of null
    at Object.normalizeSeparators (/home/circleci/project/node_modules/@angular/compiler-cli/src/ngtsc/util/src/path.js:35:21)
    at new NgtscProgram (/home/circleci/project/node_modules/@angular/compiler-cli/src/ngtsc/program.js:126:52)
```

Additionally setting the `flatModuleOutFile` option to an empty string
currently results in unexpected behavior. No errors is thrown, but the
flat module index file will be `.ts` (no file name; just extension).

This is now also fixed by treating an empty string similarly to
`null`.

PR Close #32235
2019-08-22 10:14:38 -07:00
Alex Rickabaugh 0677cf0cbe feat(ivy): use the schema registry to check DOM bindings (#32171)
Previously, ngtsc attempted to use the .d.ts schema for HTML elements to
check bindings to DOM properties. However, the TypeScript lib.dom.d.ts
schema does not perfectly align with the Angular DomElementSchemaRegistry,
and these inconsistencies would cause issues in apps. There is also the
concern of supporting both CUSTOM_ELEMENTS_SCHEMA and NO_ERRORS_SCHEMA which
would have been very difficult to do in the existing system.

With this commit, the DomElementSchemaRegistry is employed in ngtsc to check
bindings to the DOM. Previous work on producing template diagnostics is used
to support generation of this different kind of error with the same high
quality of error message.

PR Close #32171
2019-08-22 10:12:45 -07:00
Alex Rickabaugh 0287b234ea feat(ivy): convert all ngtsc diagnostics to ts.Diagnostics (#31952)
Historically, the Angular Compiler has produced both native TypeScript
diagnostics (called ts.Diagnostics) and its own internal Diagnostic format
(called an api.Diagnostic). This was done because TypeScript ts.Diagnostics
cannot be produced for files not in the ts.Program, and template type-
checking diagnostics are naturally produced for external .html template
files.

This design isn't optimal for several reasons:

1) Downstream tooling (such as the CLI) must support multiple formats of
diagnostics, adding to the maintenance burden.

2) ts.Diagnostics have gotten a lot better in recent releases, with support
for suggested changes, highlighting of the code in question, etc. None of
these changes have been of any benefit for api.Diagnostics, which have
continued to be reported in a very primitive fashion.

3) A future plugin model will not support anything but ts.Diagnostics, so
generating api.Diagnostics is a blocker for ngtsc-as-a-plugin.

4) The split complicates both the typings and the testing of ngtsc.

To fix this issue, this commit changes template type-checking to produce
ts.Diagnostics instead. Instead of reporting a special kind of diagnostic
for external template files, errors in a template are always reported in
a ts.Diagnostic that highlights the portion of the template which contains
the error. When this template text is distinct from the source .ts file
(for example, when the template is parsed from an external resource file),
additional contextual information links the error back to the originating
component.

A template error can thus be reported in 3 separate ways, depending on how
the template was configured:

1) For inline template strings which can be directly mapped to offsets in
the TS code, ts.Diagnostics point to real ranges in the source.

This is the case if an inline template is used with a string literal or a
"no-substitution" string. For example:

```typescript
@Component({..., template: `
<p>Bar: {{baz}}</p>
`})
export class TestCmp {
  bar: string;
}
```

The above template contains an error (no 'baz' property of `TestCmp`). The
error produced by TS will look like:

```
<p>Bar: {{baz}}</p>
          ~~~

test.ts:2:11 - error TS2339: Property 'baz' does not exist on type 'TestCmp'. Did you mean 'bar'?
```

2) For template strings which cannot be directly mapped to offsets in the
TS code, a logical offset into the template string will be included in
the error message. For example:

```typescript
const SOME_TEMPLATE = '<p>Bar: {{baz}}</p>';

@Component({..., template: SOME_TEMPLATE})
export class TestCmp {
  bar: string;
}
```

Because the template is a reference to another variable and is not an
inline string constant, the compiler will not be able to use "absolute"
positions when parsing the template. As a result, errors will report logical
offsets into the template string:

```
<p>Bar: {{baz}}</p>
          ~~~

test.ts (TestCmp template):2:15 - error TS2339: Property 'baz' does not exist on type 'TestCmp'.

  test.ts:3:28
    @Component({..., template: TEMPLATE})
                               ~~~~~~~~

    Error occurs in the template of component TestCmp.
```

This error message uses logical offsets into the template string, and also
gives a reference to the `TEMPLATE` expression from which the template was
parsed. This helps in locating the component which contains the error.

3) For external templates (templateUrl), the error message is delivered
within the HTML template file (testcmp.html) instead, and additional
information contextualizes the error on the templateUrl expression from
which the template file was determined:

```
<p>Bar: {{baz}}</p>
          ~~~

testcmp.html:2:15 - error TS2339: Property 'baz' does not exist on type 'TestCmp'.

  test.ts:10:31
    @Component({..., templateUrl: './testcmp.html'})
                                  ~~~~~~~~~~~~~~~~

    Error occurs in the template of component TestCmp.
```

PR Close #31952
2019-08-21 10:51:59 -07:00
atscott cfed0c0cf1 fix(ivy): Support selector-less directive as base classes (#32125)
Following #31379, this adds support for directives without a selector to
Ivy.

PR Close #32125
2019-08-20 09:56:54 -07:00
Pete Bacon Darwin eb5412d76f fix(ivy): reuse compilation scope for incremental template changes. (#31932)
Previously if only a component template changed then we would know to
rebuild its component source file. But the compilation was incorrect if the
component was part of an NgModule, since we were not capturing the
compilation scope information that had a been acquired from the NgModule
and was not being regenerated since we were not needing to recompile
the NgModule.

Now we register compilation scope information for each component, via the
`ComponentScopeRegistry` interface, so that it is available for incremental
compilation.

The `ComponentDecoratorHandler` now reads the compilation scope from a
`ComponentScopeReader` interface which is implemented as a compound
reader composed of the original `LocalModuleScopeRegistry` and the
`IncrementalState`.

Fixes #31654

PR Close #31932
2019-08-09 10:50:40 -07:00
Igor Minar 6ece7db37a build: TypeScript 3.5 upgrade (#31615)
https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#typescript-35

PR Close #31615
2019-07-25 17:05:23 -07:00
JoostK 3a2b195a58 feat(ivy): translate type-check diagnostics to their original source (#30181)
PR Close #30181
2019-07-25 16:36:32 -07:00
Ayaz Hafiz 6b67cd5620 feat(ivy): index template references, variables, bound attributes/events (#31535)
Adds support for indexing template referenecs, variables, and property
and method calls inside bound attributes and bound events. This is
mostly an extension of the existing indexing infrastructure.

PR Close #31535
2019-07-25 13:09:10 -07:00
crisbeto 3d7303efc0 perf(ivy): avoid extra parameter in query instructions (#31667)
Currently we always generate the `read` parameter for the view and content query instructions, however since most of the time the `read` parameter won't be set, we'll end up generating `null` which adds 5 bytes for each query when minified. These changes make it so that the `read` parameter only gets generated if it has a value.

PR Close #31667
2019-07-24 14:37:51 -07:00
Matias Niemelä 9c954ebc62 refactor(ivy): make styling instructions use the new styling algorithm (#30742)
This commit is the final patch of the ivy styling algorithm refactor.
This patch swaps functionality from the old styling mechanism to the
new refactored code by changing the instruction code the compiler
generates and by pointing the runtime instruction code to the new
styling algorithm.

PR Close #30742
2019-07-19 16:40:40 -07:00
Matt Lewis 4aecf9253b fix(ivy): support older CLI versions that do not pass a list of changed files (#31322)
Versions of CLI prior to angular/angular-cli@0e339ee did not expose the host.getModifiedResourceFiles() method.

This meant that null was being passed through to the IncrementalState.reconcile() method
to indicate that there were either no changes or the host didn't support that method.

This commit fixes a bug where we were checking for undefined rather than null when
deciding whether any resource files had changed, causing a null reference error to be thrown.

This bug was not caught by the unit testing because the tests set up the changed files
via a slightly different process, not having access to the CompilerHost, and these test
were making the erroneous assumption that undefined indicated that there were no
changed files.

PR Close #31322
2019-07-18 14:22:07 -07:00
Paul Gschwendtner 647d7bdd88 refactor: fix typescript strict flag failures in all tests (#30993)
Fixes all TypeScript failures caused by enabling the `--strict`
flag for test source files. We also want to enable the strict
options for tests as the strictness enforcement improves the
overall codehealth, unveiled common issues and additionally it
allows us to enable `strict` in the `tsconfig.json` that is picked
up by IDE's.

PR Close #30993
2019-07-18 14:21:26 -07:00
crisbeto 40d785f0a0 perf(ivy): avoid generating extra parameters for host property bindings (#31550)
Currently we reuse the same instruction both for regular property bindings and property bindings on the `host`. The only difference between the two is that when it's on the host we shouldn't support inputs. We have an optional parameter called `nativeOnly` which is used to differentiate the two, however since `nativeOnly` is preceeded by another optional parameter (`sanitizer`), we have to generate two extra parameters for each host property bindings every time (e.g. `property('someProp', 'someValue', null, true)`).

These changes add a new instruction called `hostProperty` which avoids the need for the two parameters by removing `nativeOnly` which is always set and it allows us to omit `sanitizer` when it isn't being used.

These changes also remove the `nativeOnly` parameter from the `updateSyntheticHostBinding` instruction, because it's only generated for host elements which means that we can assume that its value will always be `true`.

PR Close #31550
2019-07-16 13:01:42 -04:00
Jon Wallsten 3166cffd28 fix(compiler-cli): Return original sourceFile instead of redirected sourceFile from getSourceFile (#26036)
Closes #22524

PR Close #26036
2019-07-15 17:33:40 -04:00
Ayaz Hafiz 604d9063c5 feat(ivy): index template elements for selectors, attributes, directives (#31240)
Add support for indexing elements in the indexing module.
Opening and self-closing HTML tags have their selector indexed, as well
as the attributes on the element and the directives applied to an
element.

PR Close #31240
2019-07-12 17:54:08 -04:00
George Kalpakas 4bb283cbb2 build: remove redundant `@types/source-map` dependency (#31468)
In version 0.6.1 that we are using, `source-map` ships with
[its own typings][1], so there is no need to use `@types/source-map`.
The types were even removed from `DefinitelyTyped` in
DefinitelyTyped/DefinitelyTyped@1792bfaa2.

[1]: https://github.com/mozilla/source-map/blob/0.6.1/package.json#L72

PR Close #31468
2019-07-11 17:18:12 -04:00
Alex Rickabaugh 1cba5d42d1 fix(ivy): handle rooted resource paths correctly (#31511)
Previously, resource paths beginning with '/' (aka "rooted" paths, which
are not actually absolute filesystem paths, but are relative to the
TypeScript project root directory) were not handled correctly. The leading
'/' was stripped and the path was resolved as if it was relative, but with
no containing file for context. This led to resources in different rootDirs
not being found.

Instead, such rooted paths are now resolved without TypeScript's help, by
checking each root directory. A test is added to this effect.

PR Close #31511
2019-07-11 11:42:33 -04:00
JoostK eb6281f5b4 fix(ivy): include type parameter for `ngBaseDef` declaration (#31210)
When a class uses Angular decorators such as `@Input`, `@Output` and
friends without an Angular class decorator, they are compiled into a
static `ngBaseDef` field on the class, with the TypeScript declaration
of the class being altered to declare the `ngBaseDef` field to be of type
`ɵɵBaseDef`. This type however requires a generic type parameter that
corresponds with the type of the class, however the compiler did not
provide this type parameter. As a result, compiling a program where such
invalid `ngBaseDef` declarations are present will result in compilation
errors.

This commit fixes the problem by providing the generic type parameter.

Fixes #31160

PR Close #31210
2019-07-02 11:06:46 -07:00
crisbeto 81332150aa perf(ivy): chain host binding instructions (#31296)
Adds chaining to the `property`, `attribute` and `updateSyntheticHostBinding` instructions when they're used in a host binding.

This PR resolves FW-1404.

PR Close #31296
2019-06-28 09:26:20 -07:00
Pete Bacon Darwin 7186f9c016 refactor(ivy): implement a virtual file-system layer in ngtsc + ngcc (#30921)
To improve cross platform support, all file access (and path manipulation)
is now done through a well known interface (`FileSystem`).

For testing a number of `MockFileSystem` implementations are provided.
These provide an in-memory file-system which emulates operating systems
like OS/X, Unix and Windows.

The current file system is always available via the static method,
`FileSystem.getFileSystem()`. This is also used by a number of static
methods on `AbsoluteFsPath` and `PathSegment`, to avoid having to pass
`FileSystem` objects around all the time. The result of this is that one
must be careful to ensure that the file-system has been initialized before
using any of these static methods. To prevent this happening accidentally
the current file system always starts out as an instance of `InvalidFileSystem`,
which will throw an error if any of its methods are called.

You can set the current file-system by calling `FileSystem.setFileSystem()`.
During testing you can call the helper function `initMockFileSystem(os)`
which takes a string name of the OS to emulate, and will also monkey-patch
aspects of the TypeScript library to ensure that TS is also using the
current file-system.

Finally there is the `NgtscCompilerHost` to be used for any TypeScript
compilation, which uses a given file-system.

All tests that interact with the file-system should be tested against each
of the mock file-systems. A series of helpers have been provided to support
such tests:

* `runInEachFileSystem()` - wrap your tests in this helper to run all the
wrapped tests in each of the mock file-systems.
* `addTestFilesToFileSystem()` - use this to add files and their contents
to the mock file system for testing.
* `loadTestFilesFromDisk()` - use this to load a mirror image of files on
disk into the in-memory mock file-system.
* `loadFakeCore()` - use this to load a fake version of `@angular/core`
into the mock file-system.

All ngcc and ngtsc source and tests now use this virtual file-system setup.

PR Close #30921
2019-06-25 16:25:24 -07:00
Andrew Kushnir 2aba485118 refactor(ivy): use FatalDiagnosticError to throw more descriptive errors while extracting queries information (#31123)
Prior to this commit, the logic to extract query information from class fields used an instance of regular Error class to throw an error. As a result, some useful information (like reference to a specific field) was missing. Replacing Error class with FatalDiagnosticError one makes the error more verbose that should simplify debugging.

PR Close #31123
2019-06-25 10:23:24 -07:00
Ayaz Hafiz 74f4f5dfab feat(ivy): integrate indexing pipeline with NgtscProgram (#31151)
Add an IndexingContext class to store indexing information and a
transformer module to generate indexing analysis. Integrate the indexing
module with the rest of NgtscProgram and add integration tests.

Closes #30959

PR Close #31151
2019-06-24 18:47:56 -07:00
Pete Bacon Darwin 48def92cad fix(ivy): ensure that changes to component resources trigger incremental builds (#30954)
Optimizations to skip compiling source files that had not changed
did not account for the case where only a resource file changes,
such as an external template or style file.

Now we track such dependencies and trigger a recompilation
if any of the previously tracked resources have changed.

This will require a change on the CLI side to provide the list of
resource files that changed to trigger the current compilation by
implementing `CompilerHost.getModifiedResourceFiles()`.

Closes #30947

PR Close #30954
2019-06-21 10:13:46 -07:00
JoostK 75ac724842 fix(ivy): quote dots in directive inputs and outputs (#31146)
A temporary check is in place to determine whether a key in an object
literal needs to be quoted during emit. Previously, only the presence of
a dash caused a key to become quoted, this however is not sufficient for
@angular/flex-layout to compile properly as it has dots in its inputs.

This commit extends the check to also use quotes when a dot is present.

Fixes #30114

PR Close #31146
2019-06-19 17:57:13 -07:00
Alex Eagle db08fd2607 build: enable shard_count for some jasmine tests that have many specs (#31009)
This partitions the spects across multiple processes so they run in parallel.

PR Close #31009
2019-06-18 12:11:30 -07:00
Alex Eagle ef0b2cc74d build: convert entry_point to label (#30627)
PR Close #30627
2019-06-11 00:03:11 +00:00
Ben Lesh d1df0a94d4 refactor(ivy): remove ɵɵelementProperty instruction (#30645)
- 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
2019-06-05 09:04:43 -07:00
Paul Gschwendtner aca339e864 fix(ivy): unable to project into multiple slots with default selector (#30561)
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
2019-05-31 09:52:32 -07:00
Alex Rickabaugh b61784948a fix(ivy): template inputs/outputs should not be bound in template scope (#30669)
The R3TargetBinder "binds" an Angular template AST, computing semantic
information regarding the template and making it accessible.

One of the binding passes previously had a bug, where for the following
template:

<div *ngIf="foo as foo"></div>

which desugars to:

<ng-template ngIf [ngIf]="foo" let-foo="ngIf">
  <div></div>
</ng-template>

would have the `[ngIf]` binding processed twice - in both the scope which
contains the `<ng-template>` and the scope inside the template. The bug
arises because during the latter, `foo` is a variable defined by `let-foo`,
and so the R3TargetBinder would incorrectly learn that `foo` inside `[ngIf]`
maps to that variable.

This commit fixes the bug by only processing inputs, outputs, and
templateAttrs from `Template`s in the outer scope.

PR Close #30669
2019-05-30 15:17:07 -04:00
Andrew Kushnir 7a0f8ac36c fix(ivy): generate explicit type annotation for NgModuleFactory calls in ngfactories (#30708)
Prior to this commit there were no explicit types setup for NgModuleFactory calls in ngfactories, so TypeScript inferred the type based on a given call. In some cases (when generic types were used for Components/Directives) that turned out to be problematic, so we add explicit typing for NgModuleFactory calls.

PR Close #30708
2019-05-30 15:09:56 -04:00
Ben Lesh dd0815095f feat(ivy): add ɵɵtextInterpolateX instructions (#30011)
- `ɵɵtextBinding(..., ɵɵinterpolationX())` instructions will now just be `ɵɵtextInterpolate(...)` instructions

PR Close #30011
2019-05-29 12:38:58 -04:00
Kara Erickson 214ae0ea4c test(compiler): update examples and compiler tests (#30626)
PR Close #30626
2019-05-23 10:31:32 -07:00
Ben Lesh 988afad2af refactor(ivy): generate new ɵɵattribute instruction in host bindings (#30503)
PR Close #30503
2019-05-22 16:30:29 -07:00
Ben Lesh d7eaae6f22 refactor(ivy): Move instructions back to ɵɵ (#30546)
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
2019-05-20 16:37:47 -07:00
Pete Bacon Darwin eda09e69ea fix(ivy): ngtsc - do not wrap arguments unnecessarily (#30349)
Previously we defensively wrapped expressions in case they ran afoul of
precedence rules. For example, it would be easy to create the TS AST structure
Call(Ternary(a, b, c)), but might result in printed code of:

```
a ? b : c()
```

Whereas the actual structure we meant to generate is:

```
(a ? b : c)()
```

However the TypeScript renderer appears to be clever enough to provide
parenthesis as necessary.

This commit removes these defensive paraenthesis in the cases of binary
and ternary operations.

FW-1273

PR Close #30349
2019-05-17 09:55:46 -07:00
JoostK e9ead2bc09 feat(ivy): more accurate type narrowing for `ngIf` directive (#30248)
A structural directive can specify a template guard for an input, such that
the type of that input's binding can be narrowed based on the guard's return
type. Previously, such template guards could only be methods, of which an
invocation would be inserted into the type-check block (TCB). For `NgIf`,
the template guard narrowed the type of its expression to be `NonNullable`
using the following declaration:

```typescript
export declare class NgIf {
  static ngTemplateGuard_ngIf<E>(dir: NgIf, expr: E): expr is NonNullable<E>
}
```

This works fine for usages such as `*ngIf="person"` but starts to introduce
false-positives when e.g. an explicit non-null check like
`*ngIf="person !== null"` is used, as the method invocation in the TCB
would not have the desired effect of narrowing `person` to become
non-nullable:

```typescript
if (NgIf.ngTemplateGuard_ngIf(directive, ctx.person !== null)) {
  // Usages of `ctx.person` within this block would
  // not have been narrowed to be non-nullable.
}
```

This commit introduces a new strategy for template guards to allow for the
binding expression itself to be used as template guard in the TCB. Now,
the TCB generated for `*ngIf="person !== null"` would look as follows:

```typescript
if (ctx.person !== null) {
  // This time `ctx.person` will successfully have
  // been narrowed to be non-nullable.
}
```

This strategy can be activated by declaring the template guard as a
property declaration with `'binding'` as literal return type.

See #30235 for an example where this led to a false positive.

PR Close #30248
2019-05-16 09:48:40 -07:00
Ben Lesh cf86ed7b29 refactor(ivy): migrate ɵɵ prefix back to Δ (#30362)
Now that issues are resolved with Closure compiler, we can move back to our desired prefix of `Δ`.

PR Close #30362
2019-05-14 16:52:15 -07:00
Alan c7f9a95a3f test: fix tests in windows ci (#30451)
PR Close #30451
2019-05-14 10:35:55 -07:00
Kristiyan Kostadinov f74373f2dd fix(ivy): align NgModule registration timing with ViewEngine (#30244)
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
2019-05-13 11:13:25 -07:00
Alan Agius 2f35dbfd3b test: fix ngtsc tests in windows (#30146)
This commit fixes the following test target in windows

```
//packages/compiler-cli/test/ngtsc:ngtsc
```

PR Close #30146
2019-05-13 11:06:12 -07:00
Pete Bacon Darwin fbff03b476 feat(ivy): skip analysis of unchanged components (#30238)
Now that the dependent files and compilation scopes are being tracked in
the incremental state, we can skip analysing and emitting source files if
none of their dependent files have changed since the last compile.

The computation of what files (and their dependencies) are unchanged is
computed during reconciliation.

This commit also removes the previous emission skipping logic, since this
approach covers those cases already.

PR Close #30238
2019-05-10 12:10:40 -07:00
Matias Niemelä d8665e639b refactor(ivy): drop `element` prefixes for all styling-related instructions (#30318)
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
2019-05-08 15:33:39 -07:00
Matias Niemelä c016e2c4ec refactor(ivy): migrate all host-specific styling instructions to element-level styling instructions (#30336)
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
2019-05-08 14:54:44 -07:00
Kristiyan Kostadinov 68ff2cc323 fix(ivy): host bindings and listeners not being inherited from undecorated classes (#30158)
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
2019-04-29 13:35:14 -07:00
Alex Rickabaugh 79141f4424 fix(ivy): generate default 'any' types for type ctor generic params (#30094)
ngtsc generates type constructors which infer the type of a directive based
on its inputs. Previously, a bug existed where this inference would fail in
the case of 'any' input values. For example, the inference of NgForOf fails
when an 'any' is provided, as it causes TypeScript to attempt to solve:

T[] = any

In this case, T gets inferred as {}, the empty object type, which is not
desirable.

The fix is to assign generic types in type constructors a default type of
'any', which TypeScript uses instead of {} when inference fails.

PR Close #30094
2019-04-24 17:10:21 -07:00
Alex Rickabaugh 3938563565 fix(ivy): don't reuse a ts.Program more than once in ngtsc (#30090)
ngtsc previously could attempt to reuse the main ts.Program twice. This
occurred when template type-checking was enabled and then an incremental
build was performed. This breaks a TypeScript invariant - ts.Programs can
only be reused once.

The creation of the template type-checking program reuses the main program,
rendering it moot. Then, on the next incremental build the main program
would be subject to reuse again, which would crash inside TypeScript.

This commit fixes the issue by reusing the template type-checking program
from the previous run on the next incremental build. Since under normal
circumstances the files in the type-checking program aren't changed, this
should be just as fast.

Testing strategy: a test is added in the incremental_spec which validates
that program reuse with type-checking turned on does not crash the compiler.

Fixes #30079

PR Close #30090
2019-04-24 11:41:21 -07:00
Andrew Kushnir aaf8145c48 fix(ivy): support module.id as @NgModule's "id" field value (#30040)
Prior to this commit, the check that verifies correct "id" field type was too strict and didn't allow `module.id` as @NgModule's "id" field value. This change adds a special handling for `module.id` and uses it as id of @NgModule if specified.

PR Close #30040
2019-04-23 14:50:58 -07:00
Ben Lesh 0f9230d018 feat(ivy): generate ɵɵproperty in host bindings (#30009)
PR Close #30009
2019-04-22 17:30:17 -07:00
Ben Lesh 0bcb2320ba feat(ivy): generate ɵɵpropertyInterpolateX instructions (#30008)
- Compiler now generates `ɵɵpropertyInterpolateX` instructions.

PR Close #30008
2019-04-22 17:10:36 -07:00
Ben Lesh 10217bb3bc feat(ivy): generate ɵɵproperty instructions (#29946)
PR Close #29946
2019-04-19 16:07:52 -07:00
Alex Rickabaugh d9ce8a4ab5 feat(ivy): introduce a flag to control template type-checking for Ivy (#29698)
Template type-checking is enabled by default in the View Engine compiler.
The feature in Ivy is not quite ready for this yet, so this flag will
temporarily control whether templates are type-checked in ngtsc.

The goal is to remove this flag after rolling out template type-checking in
google3 in Ivy mode, and making sure the feature is as compatible with the
View Engine implementation as possible.

Initially, the default value of the flag will leave checking disabled.

PR Close #29698
2019-04-19 11:15:25 -07:00
Alex Rickabaugh 5268ae61a0 feat(ivy): support for template type-checking pipe bindings (#29698)
This commit adds support for template type-checking a pipe binding which
previously was not handled by the type-checking engine. In compatibility
mode, the arguments to transform() are not checked and the type returned
by a pipe is 'any'. In full type-checking mode, the transform() method's
type signature is used to check the pipe usage and infer the return type
of the pipe.

Testing strategy: TCB tests included.

PR Close #29698
2019-04-19 11:15:25 -07:00
Alex Rickabaugh 98f86de8da perf(ivy): template type-check the entire program in 1 file if possible (#29698)
The template type-checking engine previously would assemble a type-checking
program by inserting Type Check Blocks (TCBs) into existing user files. This
approach proved expensive, as TypeScript has to re-parse and re-type-check
those files when processing the type-checking program.

Instead, a far more performant approach is to augment the program with a
single type-checking file, into which all TCBs are generated. Additionally,
type constructors are also inlined into this file.

This is not always possible - both TCBs and type constructors can sometimes
require inlining into user code, particularly if bound generic type
parameters are present, so the approach taken is actually a hybrid. These
operations are inlined if necessary, but are otherwise generated in a single
file.

It is critically important that the original program also include an empty
version of the type-checking file, otherwise the shape of the two programs
will be different and TypeScript will throw away all the old program
information. This leads to a painfully slow type checking pass, on the same
order as the original program creation. A shim to generate this file in the
original program is therefore added.

Testing strategy: this commit is largely a refactor with no externally
observable behavioral differences, and thus no tests are needed.

PR Close #29698
2019-04-19 11:15:25 -07:00
Alex Rickabaugh cd1277cfb7 fix(ivy): include directive base class metadata when generating TCBs (#29698)
Previously the template type-checking code only considered the metadata of
directive classes actually referenced in the template. If those directives
had base classes, any inputs/outputs/etc of the base classes were not
tracked when generating the TCB. This resulted in bindings to those inputs
being incorrectly attributed to the host component or element.

This commit uses the new metadata package to follow directive inheritance
chains and use the full metadata for a directive for TCB generation.

Testing strategy: Template type-checking tests included.

PR Close #29698
2019-04-19 11:15:25 -07:00
Alex Rickabaugh 0df719a461 feat(ivy): register NgModules with ids when compiled with AOT (#29980)
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
2019-04-19 11:12:21 -07:00
Alex Rickabaugh 4229b41057 test(ivy): replace ɵ with escape code (#29980)
PR Close #29980
2019-04-19 11:12:20 -07:00
JoostK 83291f01b0 fix(ivy): let ngtsc unwrap expressions when resolving `forwardRef` (#29886)
Previously, ngtsc would fail to resolve `forwardRef` calls if they
contained additional parenthesis or casts. This commit changes the
behavior to first unwrap the AST nodes to see past such insignificant
nodes, resolving the issue.

Fixes #29639

PR Close #29886
2019-04-17 12:52:34 -07:00
Alex Rickabaugh b0578061ce refactor(ivy): use ɵɵ instead of Δ for now (#29850)
The `Δ` caused issue with other infrastructure, and we are temporarily
changing it to `ɵɵ`.

This commit also patches ts_api_guardian_test and AIO to understand `ɵɵ`.

PR Close #29850
2019-04-11 16:27:56 -07:00
Olivier Combe 91c7b451d5 feat(ivy): support i18n without closure (#28689)
So far using runtime i18n with ivy meant that you needed to use Closure and `goog.getMsg` (or a polyfill). This PR changes the compiler to output both closure & non-closure code, while the unused option will be tree-shaken by minifiers.
This means that if you use the Angular CLI with ivy and load a translations file, you can use i18n and the application will not throw at runtime.
For now it will not translate your application, but at least you can try ivy without having to remove all of your i18n code and configuration.
PR Close #28689
2019-04-11 08:28:45 -07:00
Ben Lesh 138ca5a246 refactor(ivy): prefix all generated instructions (#29692)
- Updates all instructions to be prefixed with the Greek delta symbol

PR Close #29692
2019-04-10 12:11:40 -07:00
JoostK 60afe88bcc feat(ivy): do not emit empty providers/imports for defineInjector (#29598)
The defineInjector function specifies its providers and imports array to
be optional, so if no providers/imports are present these keys may be
omitted. This commit updates the compiler to only generate the keys when
necessary.

PR Close #29598
2019-04-02 16:03:54 -07:00
JoostK 2d372f48db feat(ivy): exclude declarations from injector imports (#29598)
Prior to this change, a module's imports and exports would be used verbatim
as an injectors' imports. This is detrimental for tree-shaking, as a
module's exports could reference declarations that would then prevent such
declarations from being eligible for tree-shaking.

Since an injector actually only needs NgModule references as its imports,
we may safely filter out any declarations from the list of module exports.
This makes them eligible for tree-shaking once again.

PR Close #29598
2019-04-02 16:03:54 -07:00
JoostK 45c6360e5a feat(ivy): emit module scope metadata using pure function call (#29598)
Prior to this change, all module metadata would be included in the
`defineNgModule` call that is set as the `ngModuleDef` field of module
types. Part of the metadata is scope information like declarations,
imports and exports that is used for computing the transitive module
scope in JIT environments, preventing those references from being
tree-shaken for production builds.

This change moves the metadata for scope computations to a pure function
call that patches the scope references onto the module type. Because the
function is marked pure, it may be tree-shaken out during production builds
such that references to declarations and exports are dropped, which in turn
allows for tree-shaken any declaration that is not otherwise referenced.

Fixes #28077, FW-1035

PR Close #29598
2019-04-02 16:03:54 -07:00
Pete Bacon Darwin 63013f1aeb fix(ivy): support finding the import of namespace-imported identifiers (#27675)
Currently there is no support in ngtsc for imports of the form:

```
import * as core from `@angular/core`

export function forRoot(): core.ModuleWithProviders;
```

This commit modifies the `ReflectionHost.getImportOfIdentifier(id)`
method, so that it supports this kind of return type.

PR Close #27675
2019-04-01 16:06:14 -07:00
Alex Rickabaugh 7041e61562 perf(ivy): basic incremental compilation for ngtsc (#29380)
This commit introduces a mechanism for incremental compilation to the ngtsc
compiler.

Previously, incremental information was used in the construction of the
ts.Program for subsequent compilations, but was not used in ngtsc itself.

This commit adds an IncrementalState class, which tracks state between ngtsc
compilations. Currently, this supports skipping the TypeScript emit step
when the compiler can prove the contents of emit have not changed.

This is implemented for @Injectables as well as for files which don't
contain any Angular decorated types. These are the only files which can be
proven to be safe today.

See ngtsc/incremental/README.md for more details.

PR Close #29380
2019-04-01 15:13:56 -07:00
Alex Rickabaugh 7316212c1e test(ivy): support multiple compilations in the ngtsc test env (#29380)
This commit adds support for compiling the same program repeatedly in a way
that's similar to how incremental builds work in a tool such as the CLI.

* support is added to the compiler entrypoint for reuse of the Program
  object between compilations. This is the basis of the compiler's
  incremental compilation model.

* support is added to wrap the CompilerHost the compiler creates and cache
  ts.SourceFiles in between compilations.

* support is added to track when files are emitted, for assertion purposes.

* an 'exclude' section is added to the base tsconfig to prevent .d.ts
  outputs from the first compilation from becoming inputs to any subsequent
  compilations.

PR Close #29380
2019-04-01 15:13:56 -07:00
Alex Rickabaugh 3e569767e3 fix(ivy): avoid remote scoping if it's not actually required (#29404)
Currently, ngtsc decides to use remote scoping if the compilation of a
component may create a cyclic import. This happens if there are two
components in a scope (say, A and B) and A directly uses B. During
compilation of B ngtsc will then note that if B were to use A, a cycle would
be generated, and so it will opt to use remote scoping for B.

ngtsc already uses the R3TargetBinder to correctly track the imports that
are actually required, for future cycle tracking. This commit expands that
usage to not trigger remote scoping unless B actually does consume A in its
template.

PR Close #29404
2019-04-01 15:13:35 -07:00
Paul Gschwendtner 1e5a818719 fix(ivy): ngtsc is unable to detect flat module entry-point on windows (#29453)
Currently when building an Angular project with `ngtsc`
and `flatModuleOutFile` enabled, the Ngtsc build will fail
if there are multiple source files as root file names.

Ngtsc and NGC currently determine the entry-point for multiple
root file names by looking for files ending with `/index.ts`.

This functionality is technically deprecated, but still supported
and currently breaks on Windows as the root file names are not
guaranteed to be normalized POSIX-like paths.

In order to make this logic more reliable in the future, this commit
also switches the shim generators and entry-point logic to the branded
path types. This ensures that we don't break this in the future.

PR Close #29453
2019-03-27 13:46:37 -07:00
Greg Magolan 861d6f1523 build(bazel): back out of @bazel/jasmine 0.27.7 with shard count (#29444)
PR Close #29444
2019-03-21 09:59:13 -07:00
JoostK 9eb8274991 fix(ivy): emit generic type arguments in Pipe metadata (#29403)
Previously, only directives and services with generic type parameters
would emit `any` as generic type when emitting Ivy metadata into .d.ts
files. Pipes can also have generic type parameters but did not emit
`any` for all type parameters, resulting in the omission of those
parameters which causes compilation errors.

This commit adds support for pipes with generic type arguments and emits
`any` as generic type in the Ivy metadata.

Fixes #29400

PR Close #29403
2019-03-20 16:11:22 -04:00
Greg Magolan 7c4afb0da7 build: enable shard_count for some jasmine tests that have many specs (#29375)
PR Close #29375
2019-03-19 23:39:36 -04:00
Matias Niemelä 8714daf276 fix(ivy): introduce host-specific styling instructions (#29292)
This patch is the first of a few patches which separates the
styling logic between template bindings (e.g. <div [style])
from host bindings (e.g. @HostBinding('style')). This patch
in particular introduces a series of host-specific styling
instructions and changes the existing set of template styling
instructions not to accept directives. The underyling code (which
communicates with the styling algorithm) still works as it did
before.

This PR also separates the styling instruction code into a separate
file and moves over all other instructions into an dedicated
instructions directory.

PR Close #29292
2019-03-19 16:33:39 -04:00
Alex Rickabaugh ae4a86e3b5 fix(ivy): don't track identifiers of ffr-resolved references (#29387)
This fix is for a bug in the ngtsc PartialEvaluator, which statically
evaluates expressions.

Sometimes, evaluating a reference requires resolving a function which is
declared in another module, and thus no function body is available. To
support this case, the PartialEvaluator has the concept of a foreign
function resolver.

This allows the interpretation of expressions like:

const router = RouterModule.forRoot([]);

even though the definition of the 'forRoot' function has no body. In
ngtsc today, this will be resolved to a Reference to RouterModule itself,
via the ModuleWithProviders foreign function resolver.

However, the PartialEvaluator also associates any Identifiers in the path
of this resolution with the Reference. This is done so that if the user
writes

const x = imported.y;

'x' can be generated as a local identifier instead of adding an import for
'y'.

This was at the heart of a bug. In the above case with 'router', the
PartialEvaluator added the identifier 'router' to the Reference generated
(through FFR) to RouterModule.

This is not correct. References that result from FFR expressions may not
have the same value at runtime as they do at compile time (indeed, this is
not the case for ModuleWithProviders). The Reference generated via FFR is
"synthetic" in the sense that it's constructed based on a useful
interpretation of the code, not an accurate representation of the runtime
value. Therefore, it may not be legal to refer to the Reference via the
'router' identifier.

This commit adds the ability to mark such a Reference as 'synthetic', which
allows the PartialEvaluator to not add the 'router' identifier down the
line. Tests are included for both the PartialEvaluator itself as well as the
resultant buggy behavior in ngtsc overall.

PR Close #29387
2019-03-19 01:10:17 -04:00
Alex Eagle 4d912b6b12 Revert "build: enable shard_count for some jasmine tests that have many specs (#29196)" (#29347)
This reverts commit a5c747f46d.

PR Close #29347
2019-03-15 19:47:00 -04:00
Alex Eagle a5c747f46d build: enable shard_count for some jasmine tests that have many specs (#29196)
This partitions the spects across multiple processes so they run in parallel.

PR Close #29196
2019-03-14 13:14:03 -04:00
Kristiyan Kostadinov 0ffa2f2e73 fix(ivy): unable to inherit view queries into component from directive (#29203)
Fixes components not being able to inherit their view queries from a directive.

This PR resolves FW-1146.

PR Close #29203
2019-03-13 17:12:14 -04:00
Igor Minar 75748d6044 feat: add support for TypeScript 3.3 (and drop older versions) (#29004)
https://blogs.msdn.microsoft.com/typescript/2019/01/31/announcing-typescript-3-3/

BREAKING CHANGE: TypeScript 3.1 and 3.2 are no longer supported.

Please update your TypeScript version to 3.3

PR Close #29004
2019-03-13 10:38:37 -07:00
Alex Rickabaugh 73da2792c9 fix(ivy): properly compile NgModules with forward referenced types (#29198)
Previously, ngtsc would resolve forward references while evaluating the
bootstrap, declaration, imports, and exports fields of NgModule types.
However, when generating the resulting ngModuleDef, the forward nature of
these references was not taken into consideration, and so the generated JS
code would incorrectly reference types not yet declared.

This commit fixes this issue by introducing function closures in the
NgModuleDef type, similarly to how NgComponentDef uses them for forward
declarations of its directives and pipes arrays. ngtsc will then generate
closures when required, and the runtime will unwrap them if present.

PR Close #29198
2019-03-12 18:26:42 -07:00
Alex Rickabaugh ccb70e1c64 fix(ivy): reuse default imports in type-to-value references (#29266)
This fixes an issue with commit b6f6b117. In this commit, default imports
processed in a type-to-value conversion were recorded as non-local imports
with a '*' name, and the ImportManager generated a new default import for
them. When transpiled to ES2015 modules, this resulted in the following
correct code:

import i3 from './module';

// somewhere in the file, a value reference of i3:
{type: i3}

However, when the AST with this synthetic import and reference was
transpiled to non-ES2015 modules (for example, to commonjs) an issue
appeared:

var module_1 = require('./module');
{type: i3}

TypeScript renames the imported identifier from i3 to module_1, but doesn't
substitute later references to i3. This is because the import and reference
are both synthetic, and never went through the TypeScript AST step of
"binding" which associates the reference to its import. This association is
important during emit when the identifiers might change.

Synthetic (transformer-added) imports will never be bound properly. The only
possible solution is to reuse the user's original import and the identifier
from it, which will be properly downleveled. The issue with this approach
(which prompted the fix in b6f6b117) is that if the import is only used in a
type position, TypeScript will mark it for deletion in the generated JS,
even though additional non-type usages are added in the transformer. This
again would leave a dangling import.

To work around this, it's necessary for the compiler to keep track of
identifiers that it emits which came from default imports, and tell TS not
to remove those imports during transpilation. A `DefaultImportTracker` class
is implemented to perform this tracking. It implements a
`DefaultImportRecorder` interface, which is used to record two significant
pieces of information:

* when a WrappedNodeExpr is generated which refers to a default imported
  value, the ts.Identifier is associated to the ts.ImportDeclaration via
  the recorder.
* when that WrappedNodeExpr is later emitted as part of the statement /
  expression translators, the fact that the ts.Identifier was used is
  also recorded.

Combined, this tracking gives the `DefaultImportTracker` enough information
to implement another TS transformer, which can recognize default imports
which were used in the output of the Ivy transform and can prevent them
from being elided. This is done by creating a new ts.ImportDeclaration for
the imports with the same ts.ImportClause. A test verifies that this works.

PR Close #29266
2019-03-12 18:02:08 -07:00
Andrew Kushnir fe76494759 fix(ivy): use default selector for Components if selector is empty (#29239)
Prior to this change default selector for Components was not applied in case selector is missing or defined as an empty string. This update aligns this behavior between Ivy and VE: now default selector is used for Components when it's needed. Directives with empty selector are not allowed and trigger a compile-time error in both Ivy and VE.

PR Close #29239
2019-03-12 14:09:46 -07:00
Andrew Kushnir 1d88c2bb81 fix(ivy): handle aliased Angular decorators (#29195)
Prior to this change the code didn't take into account the fact that decorators can be aliases while importing into a script. As a result, these decorators were not recognized by Angular and various failures happened because of that. Now we take aliases into account and resolve decorator name properly.

PR Close #29195
2019-03-11 11:20:41 -07:00
Alex Rickabaugh 49dccf4bfc fix(ivy): process separate declarations and exports for summaries (#29193)
ngsummary files were generated with an export for each class declaration.
However, some Angular code declares classes (class Foo) and exports them
(export {Foo}) separately, which was causing incomplete summary files.

This commit expands the set of symbol names for which summary exports will
be generated, fixing this issue.

PR Close #29193
2019-03-08 16:11:32 -08:00
Alex Rickabaugh 3a6ba00286 fix(ivy): escape all required characters in reexport aliases (#29194)
Previously, the compiler did not escape . or $, and this was causing issues
in google3. Now these characters are escaped.

PR Close #29194
2019-03-08 16:10:57 -08:00
Alex Rickabaugh c37ec8b255 fix(ivy): produce ts.Diagnostics for NgModule scope errors (#29191)
Previously, when the NgModule scope resolver discovered semantic errors
within a users NgModules, it would throw assertion errors. TODOs in the
codebase indicated these should become ts.Diagnostics eventually.

Besides producing better-looking errors, there is another reason to make
this change asap: these assertions were shadowing actual errors, via an
interesting mechanism:

1) a component would produce a ts.Diagnostic during its analyze() step
2) as a result, it wouldn't register component metadata with the scope
   resolver
3) the NgModule for the component references it in exports, which was
   detected as an invalid export (no metadata registering it as a
   component).
4) the resulting assertion error would crash the compiler, hiding the
   real cause of the problem (an invalid component).

This commit should mitigate this problem by converting scoping errors to
proper ts.Diagnostics. Additionally, we should consider registering some
marker indicating a class is a directive/component/pipe without actually
requiring full metadata to be produced for it, which would allow suppression
of errors like "invalid export" for such invalid types.

PR Close #29191
2019-03-08 14:21:48 -08:00
Alex Rickabaugh b6f6b1178f fix(ivy): generate type references to a default import (#29146)
This commit refactors and expands ngtsc's support for generating imports of
values from imports of types (this is used for example when importing a
class referenced in a type annotation in a constructor).

Previously, this logic handled "import {Foo} from" and "import * as foo
from" style imports, but failed on imports of default values ("import
Foo from"). This commit moves the type-to-value logic to a separate file and
expands it to cover the default import case. Doing this also required
augmenting the ImportManager to track default as well as non-default import
generation. The APIs were made a little cleaner at the same time.

PR Close #29146
2019-03-08 11:57:08 -08:00
Andrew Kushnir dc6192c8e5 fix(ivy): properly detect "inputs" and "outputs" field names that should be wrapped in quotes (#29126)
Prior to this change, the RegExp that was used to check for dashes in field names used "g" (global) flag that retains lastIndex, which might result in skipping some fields that should be wrapped in quotes (since lastIndex advanced beyond the next "-" location). This commit removes this flag and updates the test to make sure there are no regressions.

PR Close #29126
2019-03-06 11:01:53 -08:00
Alex Rickabaugh 881807dc36 fix(ivy): never use imported type references as values (#29111)
ngtsc occasionally converts a type reference (such as the type of a
parameter in a constructor) to a value reference (argument to a
directiveInject call). TypeScript has a bad habit of sometimes removing
the import statement associated with this type reference, because it's a
type only import when it initially looks at the file.

A solution to this is to always add an import to refer to a type position
value that's imported, and not rely on the existing import.

PR Close #29111
2019-03-05 16:47:41 -08:00
Alex Rickabaugh 866d500324 fix(ivy): copy top-level comments into generated factory shims (#29065)
When ngtsc generates a .ngfactory shim, it does so based on the contents of
an original file in the program. Occasionally these original files have
comments at the top which are load-bearing (e.g. they contain jsdoc
annotations which are significant to downstream bundling tools). The
generated factory shims should preserve this comment.

This commit adds a step to the ngfactory generator to preserve the top-level
comment from the original source file.

FW-1006 #resolve
FW-1095 #resolve

PR Close #29065
2019-03-04 15:59:07 -08:00
Andrew Kushnir aa57bdbf90 fix(ivy): wrap "inputs" and "outputs" keys if they contain unsafe characters (#28919)
Prior to this change, keys in "inputs" and "outputs" objects generated by compiler were not checked against unsafe characters. As a result, in some cases the generated code was throwing JS error. Now we check whether a given key contains any unsafe chars and wrap it in quotes if needed.

PR Close #28919
2019-03-04 14:40:42 -08:00
Alex Rickabaugh b1df9a30f4 fix(ivy): use the imported name of decorators for detection (#29061)
Currently, ngtsc has a bug where if you alias the name of a decorator when
importing it, it won't be detected properly. This is because the compiler
uses the aliased name and not the original, declared name of the decorator
for detection.

This commit fixes the compiler to compare against the declared name of
decorators when available, and adds a test to prevent regression.

PR Close #29061
2019-03-01 15:19:34 -08:00
Alex Rickabaugh 3e5c1bcb9f fix(ivy): track cyclic imports that are added (#29040)
ngtsc has cyclic import detection, to determine when adding an import to a
directive or pipe would create a cycle. However, this detection must also
account for already inserted imports, as it's possible for both directions
of a circular import to be inserted by Ivy (as opposed to at least one of
those edges existing in the user's program).

This commit fixes the circular import detection for components to take into
consideration already added edges. This is difficult for one critical
reason: only edges to files which will *actually* be imported should be
considered. However, that depends on which directives & pipes are used in
a given template, which is currently only known by running the
TemplateDefinitionBuilder during the 'compile' phase. This is too late; the
decision whether to use remote scoping (which consults the import graph) is
made during the 'resolve' phase, before any compilation has taken place.

Thus, the only way to correctly consider synthetic edges is for the compiler
to know exactly which directives & pipes are used in a template during
'resolve'. There are two ways to achieve this:

1) refactor `TemplateDefinitionBuilder` to do its work in two phases, with
directive matching occurring as a separate step which can be performed
earlier.

2) use the `R3TargetBinder` in the 'resolve' phase to independently bind the
template and get information about used directives.

Option 1 is ideal, but option 2 is currently used for practical reasons. The
cost of binding the template can be shared with template-typechecking.

PR Close #29040
2019-03-01 15:18:50 -08:00
Alex Rickabaugh b50283ed67 fix(ivy): support dynamic host attribute bindings (#29033)
In the @Component decorator, the 'host' field is an object which represents
host bindings. The type of this field is complex, but is generally of the
form {[key: string]: string}. Several different kinds of bindings can be
specified, depending on the structure of the key.

For example:

```
@Component({
  host: {'[prop]': 'someExpr'}
})
```

will bind an expression 'someExpr' to the property 'prop'. This is known to
be a property binding because of the square brackets in the binding key.

If the binding key is a plain string (no brackets or parentheses), then it
is known as an attribute binding. In this case, the right-hand side is not
interpreted as an expression, but is instead a constant string.

There is no actual requirement that at build time, these constant strings
are known to the compiler, but this was previously enforced as a side effect
of requiring the binding expressions for property and event bindings to be
statically known (as they need to be parsed). This commit breaks that
relationship and allows the attribute bindings to be dynamic. In the case
that they are dynamic, the references to the dynamic values are reflected
into the Ivy instructions for attribute bindings.

PR Close #29033
2019-03-01 15:18:13 -08:00
Greg Magolan ea09430039 build: rules_nodejs 0.26.0 & use @npm instead of @ngdeps now that downstream angular build uses angular bundles (#28871)
PR Close #28871
2019-02-28 12:06:36 -08:00
Andrew Kushnir 772b24ccc3 fix(ivy): avoid missing imports for types that can be represented as values (#28941)
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
2019-02-27 15:13:40 -08:00
Alex Rickabaugh 827e89cfc4 feat(ivy): support inline <style> and <link> tags in components (#28997)
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
2019-02-27 11:56:40 -08:00
Wassim Chegham dad5a258b8 style: enforce buildifier lint on CI (#28186)
PR Close #28186
2019-02-26 16:57:41 -08:00
Wassim Chegham ce68b4d839 style: enforce buildifier lint on CI (#28186)
PR Close #28186
2019-02-26 16:57:41 -08:00
Alex Rickabaugh c1392ce618 feat(ivy): produce and consume ES2015 re-exports for NgModule re-exports (#28852)
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
2019-02-22 12:15:58 -08:00
Alex Rickabaugh 15c065f9a0 refactor(ivy): extract selector scope logic to a new ngtsc package (#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
2019-02-22 12:15:58 -08:00
Andrew Kushnir 95d9aa22ef fix(ivy): allow HTML comments to be present inside <ng-content> (#28849)
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
2019-02-21 00:13:40 -08:00
Andrew Kushnir df627e65df fix(ivy): correct absolute path processing for templateUrl and styleUrls (#28789)
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
2019-02-21 00:13:12 -08:00
Andrew Kushnir 72d043f669 fix(ivy): check the presence of .css resource for styleUrls (#28770)
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
2019-02-21 00:12:43 -08:00