467 Commits

Author SHA1 Message Date
Pete Bacon Darwin
5b32aa4486 feat(ivy): implement esm2015 and esm5 ngcc file renderers ()
PR Close 
2018-07-27 17:15:31 -07:00
Pete Bacon Darwin
844d510d3f feat(ivy): implement ngcc Analyzer ()
PR Close 
2018-07-27 17:15:31 -07:00
Pete Bacon Darwin
2f70e90493 feat(ivy): implement esm2015 and esm5 file parsers ()
PR Close 
2018-07-27 17:15:31 -07:00
Pete Bacon Darwin
45cf5b5dad feat(ivy): implement esm2015 and esm5 reflection hosts ()
PR Close 
2018-07-27 17:15:31 -07:00
Pete Bacon Darwin
4ad2f11919 test(ivy): implement ngcc specific version of makeProgram ()
PR Close 
2018-07-27 17:15:31 -07:00
Pete Bacon Darwin
d7aa20d912 feat(ivy): ngcc project skeleton ()
PR Close 
2018-07-27 17:15:31 -07:00
Pete Bacon Darwin
07e6de5788 test(ivy): allow makeProgram to be more configurable ()
This supports use cases needed by ngcc, where the compilation
needs to be configured for JavaScript differently to normal TypeScript.

PR Close 
2018-07-27 17:15:31 -07:00
Pete Bacon Darwin
6f1685ab98 fix(ivy): allow FunctionExpression to indicate a method declaration ()
In some code formats (e.g. ES5) methods can actually be function
expressions. For example:

```js
function MyClass() {}
// this static method is declared as a function expression
MyClass.staticMethod = function() { ... };
```

PR Close 
2018-07-27 17:15:31 -07:00
Pete Bacon Darwin
67588ec606 refactor(ivy): allow ImportManager to have configurable prefix ()
The ngcc compiler will want to specify its own prefix when rendering
definitions.

PR Close 
2018-07-27 17:15:31 -07:00
Pete Bacon Darwin
ee2c050521 fix(ivy): make ngtsc ClassMember node and declaration optional ()
Not all code formats have associated nodes and declarations for class members.

PR Close 
2018-07-27 17:15:30 -07:00
Pete Bacon Darwin
185b932138 refactor(ivy): TypeScriptReflectionHost.isClass cannot be a type discriminator ()
The `ReflectionHost` interface that is being implemented only expects a
return value of `boolean`.

Moreover, if you want to extend this class to support non-TS code formats,
e.g. ES5, the result of this call returning true does not mean that the `node`
is a `ClassDeclaration`. It could be a `VariableDeclaration`.

PR Close 
2018-07-27 17:15:30 -07:00
Pete Bacon Darwin
5e98421d33 style(ivy): remove underscore from TypeScriptReflectionHost._getDeclarationOfSymbol ()
The linter complains that non-private members must be marked
with `@internal` if they start with an underscore.

PR Close 
2018-07-27 17:15:30 -07:00
Alex Rickabaugh
3169edd77a fix(ivy): don't crash in listLazyRoutes() ()
This commit replaces the "not implemented" error when calling
listLazyRoutes() with an empty result, which will allow testing
in the CLI before listLazyRoutes() is implemented.

PR Close 
2018-07-26 16:38:10 -07:00
Alex Rickabaugh
8de304c15a fix(ivy): wait for preanalyze promises in loadNgStructureAsync() ()
loadNgStructureAsync() for ngtsc has a bug where it returns a
Promise<Promise[]> instead of awaiting the entire array of Promises.

This commit uses Promise.all() to await the whole set.

PR Close 
2018-07-26 16:38:09 -07:00
Alex Rickabaugh
6fe865b080 fix(ivy): don't use a custom ts.CompilerHost for ngtsc ()
ngtsc used to have a custom ts.CompilerHost which delegated to the plain
ts.CompilerHost. There's no need for this wrapper class and it causes
issues with CLI integration, so delete it.

PR Close 
2018-07-26 16:38:09 -07:00
Alex Rickabaugh
e0c0c44d99 fix(ivy): allow relative imports of .d.ts files ()
ngtsc used to assume that all .d.ts dependencies (that is, third party
packages) were imported via an absolute module path. It turns out this
assumption isn't valid; some build tools allow relative imports of
other compilation units.

In the absolute case, ngtsc assumes (and still does) that all referenced
types are available through the entrypoint from which an @NgModule was
imported. This commit adds support for relative imports, in which case
ngtsc will use relative path resolution to determine the imports.

PR Close 
2018-07-26 16:38:09 -07:00
Alex Rickabaugh
13a0d527f6 fix(ivy): correctly write cross-file references ()
There is a bug in the existing handling for cross-file references.
Suppose there are two files, module.ts and component.ts.

component.ts declares two components, one of which uses the other.
In the Ivy model, this means the component will get a directives:
reference to the other in its defineComponent call.

That reference is generated by looking at the declared components
of the module (in module.ts). However, the way ngtsc tracks this
reference, it ends up comparing the identifier of the component
in module.ts with the component.ts file, detecting they're not in
the same file, and generating a relative import.

This commit changes ngtsc to track all identifiers of a reference,
including the one by which it is declared. This allows toExpression()
to correctly decide that a local reference is okay in component.ts.

PR Close 
2018-07-26 16:38:09 -07:00
Alex Rickabaugh
ed7aa1c3e5 fix(ivy): force new imports for .d.ts files ()
When ngtsc encounters a reference to a type (for example, a Component
type listed in an NgModule declarations array), it traces the import
of that type and attempts to determine the best way to refer to it.

In the event the type is defined in the same file where a reference
is being generated, the identifier of the type is used. If the type
was imported, ngtsc has a choice. It can use the identifier from the
original import, or it can write a new import to the module where the
type came from.

ngtsc has a bug currently when it elects to rely on the user's import.
When writing a .d.ts file, the user's import may have been elided as
the type was not referred to from the type side of the program. Thus,
in .d.ts files ngtsc must always assume the import may not exist, and
generate a new one.

In .js output the import is guaranteed to still exist, so it's
preferable for ngtsc to continue using the existing import if one is
available.

This commit changes how @angular/compiler writes type definitions, and
allows it to use a different expression to write a type definition than
is used to write the value. This allows ngtsc to specify that types in
type definitions should always be imported. A corresponding change to
the staticallyResolve() Reference system allows the choice of which
type of import to use when generating an Expression from a Reference.

PR Close 
2018-07-26 16:38:09 -07:00
Alex Rickabaugh
f902b5ec59 feat(ivy): resolve forwardRef() for queries ()
@ContentChild[ren] and @ViewChild[ren] can contain a forwardRef() to a
type. This commit allows ngtsc to unwrap the forward reference and
deal with the node inside.

It includes two modes of support for forward reference resolution -
a foreign function resolver which understands deeply nested forward
references in expressions that are being statically evaluated, and
an unwrapForwardRef() function which deals only with top-level nodes.

Both will be useful in the future, but for now only unwrapForwardRef()
is used.

PR Close 
2018-07-26 16:38:09 -07:00
Alex Rickabaugh
41ef75869c fix(ivy): types in .d.ts files should account for generics ()
Ivy definition types have a generic type which specifies the return
type of the factory function. For example:

static ngDirectiveDef<NgForOf, '[ngFor][ngForOf]'>

However, in this case NgForOf itself has a type parameter <T>. Thus,
writing the above is incorrect.

This commit modifies ngtsc to understand the genericness of NgForOf and
to write the following:

static ngDirectiveDef<NgForOf<any>, '[ngFor][ngForOf]'>

PR Close 
2018-07-20 11:48:36 -07:00
Alex Rickabaugh
ed1db40322 fix(ivy): use 'typeof' and 'never' for type metadata ()
Previously ngtsc would use a tuple of class types for listing metadata
in .d.ts files. For example, an @NgModule's declarations might be
represented with the type:

[NgIf, NgForOf, NgClass]

If the module had no declarations, an empty tuple [] would be produced.

This has two problems.

1. If the class type has generic type parameters, TypeScript will
complain that they're not provided.

2. The empty tuple type is not actually legal.

This commit addresses both problems.

1. Class types are now represented using the `typeof` operator, so the
above declarations would be represented as:

[typeof NgIf, typeof NgForOf, typeof NgClass].

Since typeof operates on a value, it doesn't require generic type
arguments.

2. Instead of an empty tuple, `never` is used to indicate no metadata.

PR Close 
2018-07-20 11:48:36 -07:00
Alex Rickabaugh
d3594fc1c5 fix(ivy): correctly export all *Def symbols as private ()
Previously, some of the *Def symbols were not exported or were exported
as public API. This commit ensures every definition type is in the
private export namespace.

PR Close 
2018-07-20 11:48:36 -07:00
Alex Rickabaugh
b7bbc82e3e fix(ivy): wrap non-statement assignment expressions in parentheses ()
Previously, when translating an assignment expression (e.g. x = 3), the
translator would always print the statement as X = Y. However, if the
expression is included in a larger expression (X = (Y = Z)), the
translator would print "X = Y = Z" without regard for the outer
expression context.

Now, the translator understands when it's printing an expression
statement (X = Y;) vs an expression in a larger context (X = (Y = Z);)
and encapsulates the latter in parentheses.

PR Close 
2018-07-20 11:48:36 -07:00
Alex Rickabaugh
139f5b3672 fix(ivy): references track the identifier they were discovered under ()
Previously, references had the concept of an identifier, but would not
properly detect whether the identifier should be used or not when
generating an expression. This change fixes that logic.

Additionally, now whenever an identifier resolves to a reference (even
one imported from another module) as part of resolving an expression,
the reference is updated to use that identifier. This ensures that for
a class Foo declared in foo.ts, but referenced in an expression in
bar.ts, the Reference returned includes the identifier from bar.ts,
meaning that writing an expression in bar.ts for the Reference will not
generate an import.

PR Close 
2018-07-20 11:48:36 -07:00
Alex Rickabaugh
6f8ec256ef fix(ivy): detect ngOnChanges as a non-static method ()
Previously ngtsc had a bug where it would only detect the presence of
ngOnChanges as a static method. This commit flips the condition and only
recognizes ngOnChanges as a non-static method.

PR Close 
2018-07-20 11:48:36 -07:00
Alex Rickabaugh
5d7005eef5 feat(ivy): port the static resolver to use the ReflectionHost ()
Previously, the static resolver did its own interpretation of statements
in the TypeScript AST, which only functioned on TypeScript code. ES5
code in particular would not work with the resolver as it had hard-coded
assumptions about AST structure.

This commit changes the resolver to use a ReflectionHost instead, which
abstracts away understanding of the structural side of the AST. It adds 3
new methods to the ReflectionHost in support of this functionality:

* getDeclarationOfIdentifier
* getExportsOfModule
* isClass

PR Close 
2018-07-20 11:48:36 -07:00
Alex Rickabaugh
2e724ec68b feat(ivy): support host bindings in ngtsc ()
This change adds support for host bindings to ngtsc, and parses them
both from decorators and from the metadata in the top-level annotation.

PR Close 
2018-07-20 11:48:36 -07:00
Alex Rickabaugh
76f8f78920 feat(ivy): compile queries in ngtsc ()
This commit adds support for @ContentChild[ren] and @ViewChild[ren] in
ngtsc. Previously queries were ignored.

PR Close 
2018-07-20 11:48:36 -07:00
Alex Rickabaugh
6eb6ac7c12 fix(ivy): fix a couple issues with Input/Output compilation ()
PR Close 
2018-07-20 11:48:36 -07:00
Alex Rickabaugh
42d4287153 fix(ivy): ngInjectorDef should copy full imports/exports nodes ()
@NgModule()s get compiled to two fields: ngModuleDef and ngInjectorDef.
Both fields contain imports, as both selector scopes and injectors have
the concept of composed units of configuration. Previously these fields
were generated by static resolution of imports and exports in metadata.

Support for ModuleWithProviders requires they be generated differently.
ngModuleDef's imports/exports are generated as resolved lists of types,
whereas ngInjectorDef's imports should reflect the raw expressions that
the developer wrote in the metadata.

This change modifies the NgModule handler and properly copies raw nodes
for the imports and exports into the ngInjectorDef.

PR Close 
2018-07-20 11:48:36 -07:00
Alex Rickabaugh
f9a6a175bf fix(ivy): properly inject all special token types ()
Previously ngtsc had a few bugs handling special token types:

* Injector was not properly translated to INJECTOR
* ChangeDetectorRef was not injected via injectChangeDetectorRef()

This commit fixes these two bugs, and also adds a test to ensure
they continue to work correctly.

PR Close 
2018-07-20 11:48:36 -07:00
Alex Rickabaugh
8a986d4642 feat(ivy): statically resolve template expressions ()
This commit adds support for template substitution expressions for
ngtsc static resolution.

PR Close 
2018-07-20 11:48:35 -07:00
Alex Rickabaugh
e346c3c2f2 refactor(ivy): fix an unnecessarily deep import ()
PR Close 
2018-07-20 11:48:35 -07:00
Alex Rickabaugh
60aeee7abf feat(ivy): selector side of ModuleWithProviders via type metadata ()
Within an @NgModule it's common to include in the imports a call to
a ModuleWithProviders function, for example RouterModule.forRoot().
The old ngc compiler was able to handle this pattern because it had
global knowledge of metadata of not only the input compilation unit
but also all dependencies.

The ngtsc compiler for Ivy doesn't have this knowledge, so the
pattern of ModuleWithProviders functions is more difficult. ngtsc
must be able to determine which module is imported via the function
in order to expand the selector scope and properly tree-shake
directives and pipes.

This commit implements a solution to this problem, by adding a type
parameter to ModuleWithProviders through which the actual module
type can be passed between compilation units.

The provider side isn't a problem because the imports are always
copied directly to the ngInjectorDef.

PR Close 
2018-07-20 11:48:35 -07:00
Alex Rickabaugh
1008bb6287 fix(ivy): unwrap parenthesized or cast expressions for metadata ()
Metadata in Ivy must be literal. For example,

@NgModule({...})

is legal, whereas

const meta = {...};
@NgModule(meta)

is not.

However, some code contains additional superfluous parentheses:

@NgModule(({...}))

It is desirable that ngtsc accept this form of literal object.

PR Close 
2018-07-20 11:48:35 -07:00
Alex Rickabaugh
f58f3dc07a fix(ivy): handle ReadKeyExpr code generation ()
This implements a missing expression type in ngtsc code generation:
that of bracket access to an object property.

PR Close 
2018-07-20 11:48:35 -07:00
Alex Rickabaugh
9a6f27c34c fix(ivy): support zero-argument @NgModule() invocations ()
It's possible to declare an argument-less NgModule:

@NgModule() export class Foo {}

Update the @NgModule compiler to support this usage.

PR Close 
2018-07-12 16:36:35 -04:00
Alex Rickabaugh
48394c64ae fix(ivy): remove spurious comma in ngtsc-built .d.ts files ()
On accident a comma was emitted between imports when generating .d.ts
files. This commit removes it.

PR Close 
2018-07-12 16:36:35 -04:00
Alex Rickabaugh
cde0b4b361 fix(ivy): *Def types are private (ɵ) symbols ()
On accident a few of the definition types were emitted as public API
symbols. Much of the Ivy API surface is still prefixed with ɵ,
indicating it's a private API. The definition types should be private
for now.

PR Close 
2018-07-12 16:36:35 -04:00
Alex Rickabaugh
9f20dd937a feat(ivy): give ngtsc a basic understanding of ModuleWithProviders ()
This commit changes the @NgModule provider to understand that sometimes
an import will resolve to an object instead of a type, and that object
could be of the ModuleWithProviders type. In that case, the 'ngModule'
property is read, and its value used instead.

This still will not handle ModuleWithProviders references across
compilation units; that work is coming in a future PR.

PR Close 
2018-07-12 16:36:35 -04:00
Jeff Burn
0d5f2d3c7e fix(compiler-cli): Use typescript to resolve modules for metadata ()
The current module resolution simply attaches .ts to the import/export path, which does
not work if the path is using Node / CommonJS behavior to resolve to an index.ts file.
This patch uses typescript's module resolution logic, and will attempt to load the original
typescript file if this resolution returns a .js or .d.ts file

PR Close 
2018-07-10 11:11:48 -07:00
George Kalpakas
3d20c50156 fix(ivy): correctly resolve Array property access ()
PR Close 
2018-07-09 15:10:29 -07:00
George Kalpakas
00c110b055 build: upgrade jasmine (and related typings) to latest version ()
With these changes, the types are a little stricter now and also not
compatible with Protractor's jasmine-like syntax. So, we have to also
use `@types/jasminewd2` for e2e tests (but not for non-e2e tests).

I also had to "augment" `@types/jasminewd2`, because the latest
typings from [DefinitelyTyped][1] do not reflect the fact that the
`jasminewd2` version (v2.1.0) currently used by Protractor supports
passing a `done` callback to a spec.

[1]: 566e039485/types/jasminewd2/index.d.ts (L9-L15)

Fixes 
Closes 

PR Close 
2018-07-06 13:48:02 -07:00
cexbrayat
f62876bbcb fix(ivy): pipes are pure by default ()
PR Close 
2018-07-06 10:17:17 -07:00
Alex Rickabaugh
b6af8700ce feat(ivy): AOT support for compilation of @Pipes ()
This commit adds support to ngtsc for compilation of the @Pipe
annotation, including support for pipes in @NgModule scopes.

PR Close 
2018-07-03 18:36:02 -04:00
Igor Minar
e3064d5432 feat: typescript 2.9 support ()
PR Close 
2018-07-03 13:32:06 -07:00
Alex Rickabaugh
0c3738a780 feat(ivy): support templateUrl for ngtsc ()
This commit adds support for templateUrl in component templates within
ngtsc. The compilation pipeline is split into sync and async versions,
where asynchronous compilation invokes a special preanalyze() phase of
analysis. The preanalyze() phase can optionally return a Promise which
will delay compilation until it resolves.

A ResourceLoader interface is used to resolve templateUrls to template
strings and can return results either synchronously or asynchronously.
During sync compilation it is an error if the ResourceLoader returns a
Promise.

Two ResourceLoader implementations are provided. One uses 'fs' to read
resources directly from disk and is chosen if the CompilerHost doesn't
provide a readResource method. The other wraps the readResource method
from CompilerHost if it's provided.

PR Close 
2018-07-03 13:31:44 -07:00
Ben Lesh
9803cb011e feat(ivy): Add InheritanceDefinitionFeature to support directive inheritance ()
- Adds InheritanceDefinitionFeature to ivy
- Ensures that lifecycle hooks are inherited from super classes whether they are defined as directives or not
- Directives cannot inherit from Components
- Components can inherit from Directives or Components
- Ensures that Inputs, Outputs, and Host Bindings are inherited
- Ensures that super class Features are run

PR Close 
2018-06-29 06:42:40 -07:00
Alex Rickabaugh
ef1c6d8c26 feat(ivy): dummy handler for @Pipe to cause decorator removal ()
Currently ngtsc does not compile @Pipe. This has a side effect
of not removing the @Pipe decorator.

This adds a dummy DecoratorHandler that compiles @Pipe into an
empty ngPipeDef. Eventually this will be replaced with a full
implementation, but for now this solution allows compield code
to be tree-shaken properly.

PR Close 
2018-06-28 17:51:42 -04:00
Alex Rickabaugh
fc4dc35426 feat(ivy): strip all Angular decorators in compiled classes ()
Previously ngtsc removed the class-level decorators (@Component,
etc) but left all the ancillary decorators (@Input, @Optional,
etc).

This changes the transform to descend into the members of decorated
classes and remove any Angular decorators, not just the class-level
ones.

PR Close 
2018-06-28 17:51:41 -04:00