Commit Graph

299 Commits

Author SHA1 Message Date
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