2016-06-23 09:47:54 -07:00
/ * *
* @license
* Copyright Google Inc . All Rights Reserved .
*
* Use of this source code is governed by an MIT - style license that can be
* found in the LICENSE file at https : //angular.io/license
* /
2016-09-27 17:12:25 -07:00
import { Attribute , Component , ContentChild , ContentChildren , Directive , Host , HostBinding , HostListener , Inject , Injectable , Input , NgModule , Optional , Output , Pipe , Self , SkipSelf , ViewChild , ViewChildren , animate , group , keyframes , sequence , state , style , transition , trigger } from '@angular/core' ;
2016-06-08 16:38:52 -07:00
2016-11-14 17:37:47 -08:00
import { ReflectorReader } from '../private_import_core' ;
import { StaticSymbol } from './static_symbol' ;
2016-06-03 15:43:09 -07:00
2016-06-02 16:40:38 -07:00
const SUPPORTED_SCHEMA_VERSION = 1 ;
2016-04-28 21:54:02 -07:00
2016-03-24 10:03:10 -07:00
/ * *
* The host of the static resolver is expected to be able to provide module metadata in the form of
* ModuleMetadata . Angular 2 CLI will produce this metadata for a module whenever a . d . ts files is
* produced and the module has exported variables or classes with decorators . Module metadata can
* also be produced directly from TypeScript sources by using MetadataCollector in tools / metadata .
* /
export interface StaticReflectorHost {
/ * *
2016-05-02 09:38:46 -07:00
* Return a ModuleMetadata for the given module .
2016-03-24 10:03:10 -07:00
*
2016-05-02 09:38:46 -07:00
* @param modulePath is a string identifier for a module as an absolute path .
2016-03-24 10:03:10 -07:00
* @returns the metadata for the given module .
* /
2016-10-21 10:29:47 -07:00
getMetadataFor ( modulePath : string ) : { [ key : string ] : any } | { [ key : string ] : any } [ ] ;
2016-04-25 21:29:06 -07:00
/ * *
2016-04-28 21:54:02 -07:00
* Resolve a symbol from an import statement form , to the file where it is declared .
* @param module the location imported from
2016-04-25 21:29:06 -07:00
* @param containingFile for relative imports , the path of the file containing the import
* /
2016-04-28 21:54:02 -07:00
findDeclaration ( modulePath : string , symbolName : string , containingFile? : string ) : StaticSymbol ;
2016-02-18 10:53:21 -08:00
2016-08-23 11:58:12 -07:00
getStaticSymbol ( declarationFile : string , name : string , members? : string [ ] ) : StaticSymbol ;
2016-05-01 11:22:39 -07:00
2016-06-08 16:38:52 -07:00
angularImportLocations ( ) : {
coreDecorators : string ,
diDecorators : string ,
diMetadata : string ,
2016-06-13 15:56:51 -07:00
diOpaqueToken : string ,
2016-06-08 16:38:52 -07:00
animationMetadata : string ,
provider : string
} ;
2016-10-06 15:10:44 -07:00
getCanonicalFileName ( fileName : string ) : string ;
2016-03-24 10:03:10 -07:00
}
/ * *
* A static reflector implements enough of the Reflector API that is necessary to compile
* templates statically .
* /
2016-02-18 10:53:21 -08:00
export class StaticReflector implements ReflectorReader {
2016-04-28 21:54:02 -07:00
private annotationCache = new Map < StaticSymbol , any [ ] > ( ) ;
private propertyCache = new Map < StaticSymbol , { [ key : string ] : any } > ( ) ;
private parameterCache = new Map < StaticSymbol , any [ ] > ( ) ;
2016-03-24 10:03:10 -07:00
private metadataCache = new Map < string , { [ key : string ] : any } > ( ) ;
2016-04-29 16:27:21 -07:00
private conversionMap = new Map < StaticSymbol , ( context : StaticSymbol , args : any [ ] ) = > any > ( ) ;
2016-06-13 15:56:51 -07:00
private opaqueToken : StaticSymbol ;
2016-02-18 10:53:21 -08:00
2016-03-24 10:03:10 -07:00
constructor ( private host : StaticReflectorHost ) { this . initializeConversionMap ( ) ; }
2016-05-03 17:31:40 -07:00
importUri ( typeOrFunc : StaticSymbol ) : string {
2016-10-21 10:29:47 -07:00
const staticSymbol = this . host . findDeclaration ( typeOrFunc . filePath , typeOrFunc . name , '' ) ;
2016-05-03 17:31:40 -07:00
return staticSymbol ? staticSymbol.filePath : null ;
}
2016-02-18 10:53:21 -08:00
2016-08-29 08:52:25 -07:00
resolveIdentifier ( name : string , moduleUrl : string , runtime : any ) : any {
2016-10-21 10:29:47 -07:00
return this . host . findDeclaration ( moduleUrl , name , '' ) ;
2016-08-24 17:39:49 -07:00
}
2016-08-29 08:52:25 -07:00
resolveEnum ( enumIdentifier : any , name : string ) : any {
const staticSymbol : StaticSymbol = enumIdentifier ;
2016-08-24 17:39:49 -07:00
return this . host . getStaticSymbol ( staticSymbol . filePath , staticSymbol . name , [ name ] ) ;
}
2016-04-28 21:54:02 -07:00
public annotations ( type : StaticSymbol ) : any [ ] {
2016-03-24 10:03:10 -07:00
let annotations = this . annotationCache . get ( type ) ;
2016-05-03 09:24:09 -07:00
if ( ! annotations ) {
2016-11-12 14:08:58 +01:00
const classMetadata = this . getTypeMetadata ( type ) ;
2016-05-03 09:24:09 -07:00
if ( classMetadata [ 'decorators' ] ) {
2016-04-29 14:34:01 -07:00
annotations = this . simplify ( type , classMetadata [ 'decorators' ] ) ;
2016-04-08 15:39:21 -07:00
} else {
annotations = [ ] ;
2016-03-24 10:03:10 -07:00
}
2016-05-03 09:24:09 -07:00
this . annotationCache . set ( type , annotations . filter ( ann = > ! ! ann ) ) ;
2016-03-24 10:03:10 -07:00
}
return annotations ;
}
2016-04-28 21:54:02 -07:00
public propMetadata ( type : StaticSymbol ) : { [ key : string ] : any } {
2016-03-24 10:03:10 -07:00
let propMetadata = this . propertyCache . get ( type ) ;
2016-05-03 09:24:09 -07:00
if ( ! propMetadata ) {
2016-11-12 14:08:58 +01:00
const classMetadata = this . getTypeMetadata ( type ) ;
const members = classMetadata ? classMetadata [ 'members' ] : { } ;
2016-02-18 10:53:21 -08:00
propMetadata = mapStringMap ( members , ( propData , propName ) = > {
2016-11-12 14:08:58 +01:00
const prop = ( < any [ ] > propData )
. find ( a = > a [ '__symbolic' ] == 'property' || a [ '__symbolic' ] == 'method' ) ;
2016-05-03 09:24:09 -07:00
if ( prop && prop [ 'decorators' ] ) {
2016-04-29 14:34:01 -07:00
return this . simplify ( type , prop [ 'decorators' ] ) ;
2016-02-18 10:53:21 -08:00
} else {
return [ ] ;
}
} ) ;
2016-03-24 10:03:10 -07:00
this . propertyCache . set ( type , propMetadata ) ;
}
return propMetadata ;
}
2016-04-28 21:54:02 -07:00
public parameters ( type : StaticSymbol ) : any [ ] {
2016-05-01 11:22:39 -07:00
if ( ! ( type instanceof StaticSymbol ) ) {
2016-05-04 10:00:59 -07:00
throw new Error ( ` parameters received ${ JSON . stringify ( type ) } which is not a StaticSymbol ` ) ;
2016-05-01 11:22:39 -07:00
}
2016-04-29 14:34:01 -07:00
try {
let parameters = this . parameterCache . get ( type ) ;
2016-05-03 09:24:09 -07:00
if ( ! parameters ) {
2016-11-12 14:08:58 +01:00
const classMetadata = this . getTypeMetadata ( type ) ;
const members = classMetadata ? classMetadata [ 'members' ] : null ;
const ctorData = members ? members [ '__ctor__' ] : null ;
2016-05-03 09:24:09 -07:00
if ( ctorData ) {
2016-11-12 14:08:58 +01:00
const ctor = ( < any [ ] > ctorData ) . find ( a = > a [ '__symbolic' ] == 'constructor' ) ;
const parameterTypes = < any [ ] > this . simplify ( type , ctor [ 'parameters' ] || [ ] ) ;
const parameterDecorators = < any [ ] > this . simplify ( type , ctor [ 'parameterDecorators' ] || [ ] ) ;
2016-04-29 14:34:01 -07:00
parameters = [ ] ;
2016-05-03 18:49:59 -07:00
parameterTypes . forEach ( ( paramType , index ) = > {
2016-11-12 14:08:58 +01:00
const nestedResult : any [ ] = [ ] ;
2016-05-03 09:24:09 -07:00
if ( paramType ) {
2016-04-29 14:34:01 -07:00
nestedResult . push ( paramType ) ;
}
2016-11-12 14:08:58 +01:00
const decorators = parameterDecorators ? parameterDecorators [ index ] : null ;
2016-05-03 09:24:09 -07:00
if ( decorators ) {
nestedResult . push ( . . . decorators ) ;
2016-04-29 14:34:01 -07:00
}
parameters . push ( nestedResult ) ;
} ) ;
}
2016-05-03 09:24:09 -07:00
if ( ! parameters ) {
2016-04-29 14:34:01 -07:00
parameters = [ ] ;
}
this . parameterCache . set ( type , parameters ) ;
2016-04-08 15:39:21 -07:00
}
2016-04-29 14:34:01 -07:00
return parameters ;
} catch ( e ) {
2016-05-01 11:22:39 -07:00
console . log ( ` Failed on type ${ JSON . stringify ( type ) } with error ${ e } ` ) ;
2016-04-29 14:34:01 -07:00
throw e ;
2016-03-24 10:03:10 -07:00
}
}
2016-10-12 10:05:32 -07:00
hasLifecycleHook ( type : any , lcProperty : string ) : boolean {
2016-05-04 10:00:59 -07:00
if ( ! ( type instanceof StaticSymbol ) ) {
throw new Error (
` hasLifecycleHook received ${ JSON . stringify ( type ) } which is not a StaticSymbol ` ) ;
}
2016-10-12 10:05:32 -07:00
const classMetadata = this . getTypeMetadata ( type ) ;
const members = classMetadata ? classMetadata [ 'members' ] : null ;
const member : any [ ] =
members && members . hasOwnProperty ( lcProperty ) ? members [ lcProperty ] : null ;
2016-05-04 10:00:59 -07:00
return member ? member . some ( a = > a [ '__symbolic' ] == 'method' ) : false ;
}
2016-04-29 14:34:01 -07:00
private registerDecoratorOrConstructor ( type : StaticSymbol , ctor : any ) : void {
2016-09-12 09:44:20 -07:00
this . conversionMap . set ( type , ( context : StaticSymbol , args : any [ ] ) = > new ctor ( . . . args ) ) ;
2016-03-24 10:03:10 -07:00
}
2016-05-31 09:15:17 -07:00
private registerFunction ( type : StaticSymbol , fn : any ) : void {
2016-09-12 09:44:20 -07:00
this . conversionMap . set ( type , ( context : StaticSymbol , args : any [ ] ) = > fn . apply ( undefined , args ) ) ;
2016-05-31 09:15:17 -07:00
}
2016-02-18 10:53:21 -08:00
private initializeConversionMap ( ) : void {
2016-06-13 15:56:51 -07:00
const { coreDecorators , diDecorators , diMetadata , diOpaqueToken , animationMetadata , provider } =
2016-06-08 16:38:52 -07:00
this . host . angularImportLocations ( ) ;
2016-06-13 15:56:51 -07:00
this . opaqueToken = this . host . findDeclaration ( diOpaqueToken , 'OpaqueToken' ) ;
2016-03-24 10:03:10 -07:00
2016-09-12 19:14:17 -07:00
this . registerDecoratorOrConstructor ( this . host . findDeclaration ( diDecorators , 'Host' ) , Host ) ;
2016-06-08 16:38:52 -07:00
this . registerDecoratorOrConstructor (
2016-09-12 19:14:17 -07:00
this . host . findDeclaration ( diDecorators , 'Injectable' ) , Injectable ) ;
this . registerDecoratorOrConstructor ( this . host . findDeclaration ( diDecorators , 'Self' ) , Self ) ;
2016-06-08 16:38:52 -07:00
this . registerDecoratorOrConstructor (
2016-09-12 19:14:17 -07:00
this . host . findDeclaration ( diDecorators , 'SkipSelf' ) , SkipSelf ) ;
this . registerDecoratorOrConstructor ( this . host . findDeclaration ( diDecorators , 'Inject' ) , Inject ) ;
2016-06-08 16:38:52 -07:00
this . registerDecoratorOrConstructor (
2016-09-12 19:14:17 -07:00
this . host . findDeclaration ( diDecorators , 'Optional' ) , Optional ) ;
2016-06-08 16:38:52 -07:00
this . registerDecoratorOrConstructor (
2016-09-12 19:14:17 -07:00
this . host . findDeclaration ( coreDecorators , 'Attribute' ) , Attribute ) ;
2016-06-08 16:38:52 -07:00
this . registerDecoratorOrConstructor (
2016-09-12 19:14:17 -07:00
this . host . findDeclaration ( coreDecorators , 'ContentChild' ) , ContentChild ) ;
2016-06-08 16:38:52 -07:00
this . registerDecoratorOrConstructor (
2016-09-12 19:14:17 -07:00
this . host . findDeclaration ( coreDecorators , 'ContentChildren' ) , ContentChildren ) ;
2016-06-08 16:38:52 -07:00
this . registerDecoratorOrConstructor (
2016-09-12 19:14:17 -07:00
this . host . findDeclaration ( coreDecorators , 'ViewChild' ) , ViewChild ) ;
2016-06-08 16:38:52 -07:00
this . registerDecoratorOrConstructor (
2016-09-12 19:14:17 -07:00
this . host . findDeclaration ( coreDecorators , 'ViewChildren' ) , ViewChildren ) ;
this . registerDecoratorOrConstructor ( this . host . findDeclaration ( coreDecorators , 'Input' ) , Input ) ;
2016-04-28 21:54:02 -07:00
this . registerDecoratorOrConstructor (
2016-09-12 19:14:17 -07:00
this . host . findDeclaration ( coreDecorators , 'Output' ) , Output ) ;
this . registerDecoratorOrConstructor ( this . host . findDeclaration ( coreDecorators , 'Pipe' ) , Pipe ) ;
2016-06-08 16:38:52 -07:00
this . registerDecoratorOrConstructor (
2016-09-12 19:14:17 -07:00
this . host . findDeclaration ( coreDecorators , 'HostBinding' ) , HostBinding ) ;
2016-06-08 16:38:52 -07:00
this . registerDecoratorOrConstructor (
2016-09-12 19:14:17 -07:00
this . host . findDeclaration ( coreDecorators , 'HostListener' ) , HostListener ) ;
2016-06-08 16:38:52 -07:00
this . registerDecoratorOrConstructor (
2016-09-12 19:14:17 -07:00
this . host . findDeclaration ( coreDecorators , 'Directive' ) , Directive ) ;
2016-06-08 16:38:52 -07:00
this . registerDecoratorOrConstructor (
2016-09-12 19:14:17 -07:00
this . host . findDeclaration ( coreDecorators , 'Component' ) , Component ) ;
2016-06-08 16:38:52 -07:00
this . registerDecoratorOrConstructor (
2016-09-12 19:14:17 -07:00
this . host . findDeclaration ( coreDecorators , 'NgModule' ) , NgModule ) ;
2016-03-24 10:03:10 -07:00
2016-02-18 10:53:21 -08:00
// Note: Some metadata classes can be used directly with Provider.deps.
2016-09-12 19:14:17 -07:00
this . registerDecoratorOrConstructor ( this . host . findDeclaration ( diMetadata , 'Host' ) , Host ) ;
this . registerDecoratorOrConstructor ( this . host . findDeclaration ( diMetadata , 'Self' ) , Self ) ;
2016-06-08 16:38:52 -07:00
this . registerDecoratorOrConstructor (
2016-09-12 19:14:17 -07:00
this . host . findDeclaration ( diMetadata , 'SkipSelf' ) , SkipSelf ) ;
2016-06-08 16:38:52 -07:00
this . registerDecoratorOrConstructor (
2016-09-12 19:14:17 -07:00
this . host . findDeclaration ( diMetadata , 'Optional' ) , Optional ) ;
2016-05-31 09:15:17 -07:00
this . registerFunction ( this . host . findDeclaration ( animationMetadata , 'trigger' ) , trigger ) ;
this . registerFunction ( this . host . findDeclaration ( animationMetadata , 'state' ) , state ) ;
this . registerFunction ( this . host . findDeclaration ( animationMetadata , 'transition' ) , transition ) ;
this . registerFunction ( this . host . findDeclaration ( animationMetadata , 'style' ) , style ) ;
this . registerFunction ( this . host . findDeclaration ( animationMetadata , 'animate' ) , animate ) ;
this . registerFunction ( this . host . findDeclaration ( animationMetadata , 'keyframes' ) , keyframes ) ;
this . registerFunction ( this . host . findDeclaration ( animationMetadata , 'sequence' ) , sequence ) ;
this . registerFunction ( this . host . findDeclaration ( animationMetadata , 'group' ) , group ) ;
2016-03-24 10:03:10 -07:00
}
/** @internal */
2016-04-29 16:27:21 -07:00
public simplify ( context : StaticSymbol , value : any ) : any {
2016-10-21 10:29:47 -07:00
const _this = this ;
2016-06-13 15:56:51 -07:00
let scope = BindingScope . empty ;
2016-10-21 10:29:47 -07:00
const calling = new Map < StaticSymbol , boolean > ( ) ;
2016-03-24 10:03:10 -07:00
2016-06-17 13:11:00 -07:00
function simplifyInContext ( context : StaticSymbol , value : any , depth : number ) : any {
feat(browser): use AppModules for bootstrap in the browser
This introduces the `BrowserModule` to be used for long form
bootstrap and offline compile bootstrap:
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {bootstrapModuleFactory} from ‘@angular/platform-browser’;
bootstrapModuleFactory(MyModuleNgFactory);
// runtime compile long form
import {bootstrapModule} from ‘@angular/platform-browser-dynamic’;
bootstrapModule(MyModule);
```
The short form, `bootstrap(...)`, can now creates a module on the fly,
given `directives`, `pipes, `providers`, `precompile` and `modules`
properties.
Related changes:
- make `SanitizationService`, `SecurityContext` public in `@angular/core` so that the offline compiler can resolve the token
- move `AnimationDriver` to `platform-browser` and make it
public so that the offline compiler can resolve the token
BREAKING CHANGES:
- short form bootstrap does no longer allow
to inject compiler internals (i.e. everything
from `@angular/compiler). Inject `Compiler` instead.
To provide custom providers for the compiler,
create a custom compiler via `browserCompiler({providers: [...]})`
and pass that into the `bootstrap` method.
2016-06-30 13:07:17 -07:00
function resolveReference ( context : StaticSymbol , expression : any ) : StaticSymbol {
2016-06-13 15:56:51 -07:00
let staticSymbol : StaticSymbol ;
if ( expression [ 'module' ] ) {
staticSymbol = _this . host . findDeclaration (
expression [ 'module' ] , expression [ 'name' ] , context . filePath ) ;
} else {
staticSymbol = _this . host . getStaticSymbol ( context . filePath , expression [ 'name' ] ) ;
}
return staticSymbol ;
2016-03-24 10:03:10 -07:00
}
2016-06-13 15:56:51 -07:00
feat(browser): use AppModules for bootstrap in the browser
This introduces the `BrowserModule` to be used for long form
bootstrap and offline compile bootstrap:
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {bootstrapModuleFactory} from ‘@angular/platform-browser’;
bootstrapModuleFactory(MyModuleNgFactory);
// runtime compile long form
import {bootstrapModule} from ‘@angular/platform-browser-dynamic’;
bootstrapModule(MyModule);
```
The short form, `bootstrap(...)`, can now creates a module on the fly,
given `directives`, `pipes, `providers`, `precompile` and `modules`
properties.
Related changes:
- make `SanitizationService`, `SecurityContext` public in `@angular/core` so that the offline compiler can resolve the token
- move `AnimationDriver` to `platform-browser` and make it
public so that the offline compiler can resolve the token
BREAKING CHANGES:
- short form bootstrap does no longer allow
to inject compiler internals (i.e. everything
from `@angular/compiler). Inject `Compiler` instead.
To provide custom providers for the compiler,
create a custom compiler via `browserCompiler({providers: [...]})`
and pass that into the `bootstrap` method.
2016-06-30 13:07:17 -07:00
function resolveReferenceValue ( staticSymbol : StaticSymbol ) : any {
2016-10-21 10:29:47 -07:00
const moduleMetadata = _this . getModuleMetadata ( staticSymbol . filePath ) ;
const declarationValue =
feat(browser): use AppModules for bootstrap in the browser
This introduces the `BrowserModule` to be used for long form
bootstrap and offline compile bootstrap:
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {bootstrapModuleFactory} from ‘@angular/platform-browser’;
bootstrapModuleFactory(MyModuleNgFactory);
// runtime compile long form
import {bootstrapModule} from ‘@angular/platform-browser-dynamic’;
bootstrapModule(MyModule);
```
The short form, `bootstrap(...)`, can now creates a module on the fly,
given `directives`, `pipes, `providers`, `precompile` and `modules`
properties.
Related changes:
- make `SanitizationService`, `SecurityContext` public in `@angular/core` so that the offline compiler can resolve the token
- move `AnimationDriver` to `platform-browser` and make it
public so that the offline compiler can resolve the token
BREAKING CHANGES:
- short form bootstrap does no longer allow
to inject compiler internals (i.e. everything
from `@angular/compiler). Inject `Compiler` instead.
To provide custom providers for the compiler,
create a custom compiler via `browserCompiler({providers: [...]})`
and pass that into the `bootstrap` method.
2016-06-30 13:07:17 -07:00
moduleMetadata ? moduleMetadata [ 'metadata' ] [ staticSymbol . name ] : null ;
return declarationValue ;
}
function isOpaqueToken ( context : StaticSymbol , value : any ) : boolean {
2016-06-13 15:56:51 -07:00
if ( value && value . __symbolic === 'new' && value . expression ) {
2016-10-21 10:29:47 -07:00
const target = value . expression ;
2016-06-13 15:56:51 -07:00
if ( target . __symbolic == 'reference' ) {
feat(browser): use AppModules for bootstrap in the browser
This introduces the `BrowserModule` to be used for long form
bootstrap and offline compile bootstrap:
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {bootstrapModuleFactory} from ‘@angular/platform-browser’;
bootstrapModuleFactory(MyModuleNgFactory);
// runtime compile long form
import {bootstrapModule} from ‘@angular/platform-browser-dynamic’;
bootstrapModule(MyModule);
```
The short form, `bootstrap(...)`, can now creates a module on the fly,
given `directives`, `pipes, `providers`, `precompile` and `modules`
properties.
Related changes:
- make `SanitizationService`, `SecurityContext` public in `@angular/core` so that the offline compiler can resolve the token
- move `AnimationDriver` to `platform-browser` and make it
public so that the offline compiler can resolve the token
BREAKING CHANGES:
- short form bootstrap does no longer allow
to inject compiler internals (i.e. everything
from `@angular/compiler). Inject `Compiler` instead.
To provide custom providers for the compiler,
create a custom compiler via `browserCompiler({providers: [...]})`
and pass that into the `bootstrap` method.
2016-06-30 13:07:17 -07:00
return sameSymbol ( resolveReference ( context , target ) , _this . opaqueToken ) ;
2016-06-13 15:56:51 -07:00
}
2016-03-24 10:03:10 -07:00
}
2016-06-13 15:56:51 -07:00
return false ;
2016-03-24 10:03:10 -07:00
}
2016-06-13 15:56:51 -07:00
function simplifyCall ( expression : any ) {
feat(browser): use AppModules for bootstrap in the browser
This introduces the `BrowserModule` to be used for long form
bootstrap and offline compile bootstrap:
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {bootstrapModuleFactory} from ‘@angular/platform-browser’;
bootstrapModuleFactory(MyModuleNgFactory);
// runtime compile long form
import {bootstrapModule} from ‘@angular/platform-browser-dynamic’;
bootstrapModule(MyModule);
```
The short form, `bootstrap(...)`, can now creates a module on the fly,
given `directives`, `pipes, `providers`, `precompile` and `modules`
properties.
Related changes:
- make `SanitizationService`, `SecurityContext` public in `@angular/core` so that the offline compiler can resolve the token
- move `AnimationDriver` to `platform-browser` and make it
public so that the offline compiler can resolve the token
BREAKING CHANGES:
- short form bootstrap does no longer allow
to inject compiler internals (i.e. everything
from `@angular/compiler). Inject `Compiler` instead.
To provide custom providers for the compiler,
create a custom compiler via `browserCompiler({providers: [...]})`
and pass that into the `bootstrap` method.
2016-06-30 13:07:17 -07:00
let callContext : { [ name : string ] : string } | undefined = undefined ;
2016-06-13 15:56:51 -07:00
if ( expression [ '__symbolic' ] == 'call' ) {
2016-11-12 14:08:58 +01:00
const target = expression [ 'expression' ] ;
2016-07-25 05:29:20 -07:00
let functionSymbol : StaticSymbol ;
feat(browser): use AppModules for bootstrap in the browser
This introduces the `BrowserModule` to be used for long form
bootstrap and offline compile bootstrap:
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {bootstrapModuleFactory} from ‘@angular/platform-browser’;
bootstrapModuleFactory(MyModuleNgFactory);
// runtime compile long form
import {bootstrapModule} from ‘@angular/platform-browser-dynamic’;
bootstrapModule(MyModule);
```
The short form, `bootstrap(...)`, can now creates a module on the fly,
given `directives`, `pipes, `providers`, `precompile` and `modules`
properties.
Related changes:
- make `SanitizationService`, `SecurityContext` public in `@angular/core` so that the offline compiler can resolve the token
- move `AnimationDriver` to `platform-browser` and make it
public so that the offline compiler can resolve the token
BREAKING CHANGES:
- short form bootstrap does no longer allow
to inject compiler internals (i.e. everything
from `@angular/compiler). Inject `Compiler` instead.
To provide custom providers for the compiler,
create a custom compiler via `browserCompiler({providers: [...]})`
and pass that into the `bootstrap` method.
2016-06-30 13:07:17 -07:00
let targetFunction : any ;
2016-07-26 10:18:35 -07:00
if ( target ) {
switch ( target . __symbolic ) {
case 'reference' :
// Find the function to call.
callContext = { name : target.name } ;
functionSymbol = resolveReference ( context , target ) ;
targetFunction = resolveReferenceValue ( functionSymbol ) ;
break ;
case 'select' :
// Find the static method to call
if ( target . expression . __symbolic == 'reference' ) {
functionSymbol = resolveReference ( context , target . expression ) ;
const classData = resolveReferenceValue ( functionSymbol ) ;
if ( classData && classData . statics ) {
targetFunction = classData . statics [ target . member ] ;
}
}
break ;
}
2016-06-17 13:11:00 -07:00
}
feat(browser): use AppModules for bootstrap in the browser
This introduces the `BrowserModule` to be used for long form
bootstrap and offline compile bootstrap:
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {bootstrapModuleFactory} from ‘@angular/platform-browser’;
bootstrapModuleFactory(MyModuleNgFactory);
// runtime compile long form
import {bootstrapModule} from ‘@angular/platform-browser-dynamic’;
bootstrapModule(MyModule);
```
The short form, `bootstrap(...)`, can now creates a module on the fly,
given `directives`, `pipes, `providers`, `precompile` and `modules`
properties.
Related changes:
- make `SanitizationService`, `SecurityContext` public in `@angular/core` so that the offline compiler can resolve the token
- move `AnimationDriver` to `platform-browser` and make it
public so that the offline compiler can resolve the token
BREAKING CHANGES:
- short form bootstrap does no longer allow
to inject compiler internals (i.e. everything
from `@angular/compiler). Inject `Compiler` instead.
To provide custom providers for the compiler,
create a custom compiler via `browserCompiler({providers: [...]})`
and pass that into the `bootstrap` method.
2016-06-30 13:07:17 -07:00
if ( targetFunction && targetFunction [ '__symbolic' ] == 'function' ) {
2016-07-25 05:29:20 -07:00
if ( calling . get ( functionSymbol ) ) {
2016-06-13 15:56:51 -07:00
throw new Error ( 'Recursion not supported' ) ;
}
2016-07-25 05:29:20 -07:00
calling . set ( functionSymbol , true ) ;
2016-07-28 17:32:29 -07:00
try {
2016-07-29 09:10:45 -07:00
const value = targetFunction [ 'value' ] ;
2016-07-28 17:32:29 -07:00
if ( value && ( depth != 0 || value . __symbolic != 'error' ) ) {
// Determine the arguments
2016-07-29 09:10:45 -07:00
const args : any [ ] =
( expression [ 'arguments' ] || [ ] ) . map ( ( arg : any ) = > simplify ( arg ) ) ;
const parameters : string [ ] = targetFunction [ 'parameters' ] ;
const defaults : any [ ] = targetFunction . defaults ;
if ( defaults && defaults . length > args . length ) {
args . push ( . . . defaults . slice ( args . length ) . map ( ( value : any ) = > simplify ( value ) ) ) ;
}
const functionScope = BindingScope . build ( ) ;
2016-07-28 17:32:29 -07:00
for ( let i = 0 ; i < parameters . length ; i ++ ) {
functionScope . define ( parameters [ i ] , args [ i ] ) ;
}
2016-11-12 14:08:58 +01:00
const oldScope = scope ;
2016-07-28 17:32:29 -07:00
let result : any ;
try {
scope = functionScope . done ( ) ;
result = simplifyInContext ( functionSymbol , value , depth + 1 ) ;
} finally {
scope = oldScope ;
}
return result ;
2016-03-24 10:03:10 -07:00
}
2016-07-28 17:32:29 -07:00
} finally {
calling . delete ( functionSymbol ) ;
2016-06-13 15:56:51 -07:00
}
}
}
2016-06-17 13:11:00 -07:00
if ( depth === 0 ) {
// If depth is 0 we are evaluating the top level expression that is describing element
// decorator. In this case, it is a decorator we don't understand, such as a custom
// non-angular decorator, and we should just ignore it.
return { __symbolic : 'ignore' } ;
}
feat(browser): use AppModules for bootstrap in the browser
This introduces the `BrowserModule` to be used for long form
bootstrap and offline compile bootstrap:
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {bootstrapModuleFactory} from ‘@angular/platform-browser’;
bootstrapModuleFactory(MyModuleNgFactory);
// runtime compile long form
import {bootstrapModule} from ‘@angular/platform-browser-dynamic’;
bootstrapModule(MyModule);
```
The short form, `bootstrap(...)`, can now creates a module on the fly,
given `directives`, `pipes, `providers`, `precompile` and `modules`
properties.
Related changes:
- make `SanitizationService`, `SecurityContext` public in `@angular/core` so that the offline compiler can resolve the token
- move `AnimationDriver` to `platform-browser` and make it
public so that the offline compiler can resolve the token
BREAKING CHANGES:
- short form bootstrap does no longer allow
to inject compiler internals (i.e. everything
from `@angular/compiler). Inject `Compiler` instead.
To provide custom providers for the compiler,
create a custom compiler via `browserCompiler({providers: [...]})`
and pass that into the `bootstrap` method.
2016-06-30 13:07:17 -07:00
return simplify (
{ __symbolic : 'error' , message : 'Function call not supported' , context : callContext } ) ;
2016-06-13 15:56:51 -07:00
}
function simplify ( expression : any ) : any {
if ( isPrimitive ( expression ) ) {
return expression ;
}
if ( expression instanceof Array ) {
2016-11-12 14:08:58 +01:00
const result : any [ ] = [ ] ;
for ( const item of ( < any > expression ) ) {
2016-06-13 15:56:51 -07:00
// Check for a spread expression
if ( item && item . __symbolic === 'spread' ) {
2016-11-12 14:08:58 +01:00
const spreadArray = simplify ( item . expression ) ;
2016-06-13 15:56:51 -07:00
if ( Array . isArray ( spreadArray ) ) {
2016-11-12 14:08:58 +01:00
for ( const spreadItem of spreadArray ) {
2016-06-13 15:56:51 -07:00
result . push ( spreadItem ) ;
}
continue ;
2016-05-07 08:58:20 -06:00
}
2016-06-13 15:56:51 -07:00
}
2016-11-12 14:08:58 +01:00
const value = simplify ( item ) ;
2016-06-17 13:11:00 -07:00
if ( shouldIgnore ( value ) ) {
continue ;
}
result . push ( value ) ;
2016-06-13 15:56:51 -07:00
}
return result ;
}
2016-10-11 15:47:44 -07:00
if ( expression instanceof StaticSymbol ) {
return expression ;
}
2016-06-13 15:56:51 -07:00
if ( expression ) {
if ( expression [ '__symbolic' ] ) {
let staticSymbol : StaticSymbol ;
switch ( expression [ '__symbolic' ] ) {
case 'binop' :
let left = simplify ( expression [ 'left' ] ) ;
2016-06-17 13:11:00 -07:00
if ( shouldIgnore ( left ) ) return left ;
2016-06-13 15:56:51 -07:00
let right = simplify ( expression [ 'right' ] ) ;
2016-06-17 13:11:00 -07:00
if ( shouldIgnore ( right ) ) return right ;
2016-06-13 15:56:51 -07:00
switch ( expression [ 'operator' ] ) {
case '&&' :
return left && right ;
case '||' :
return left || right ;
case '|' :
return left | right ;
case '^' :
return left ^ right ;
case '&' :
return left & right ;
case '==' :
return left == right ;
case '!=' :
return left != right ;
case '===' :
return left === right ;
case '!==' :
return left !== right ;
case '<' :
return left < right ;
case '>' :
return left > right ;
case '<=' :
return left <= right ;
case '>=' :
return left >= right ;
case '<<' :
return left << right ;
case '>>' :
return left >> right ;
case '+' :
return left + right ;
case '-' :
return left - right ;
case '*' :
return left * right ;
case '/' :
return left / right ;
case '%' :
return left % right ;
}
return null ;
2016-07-28 17:32:29 -07:00
case 'if' :
let condition = simplify ( expression [ 'condition' ] ) ;
return condition ? simplify ( expression [ 'thenExpression' ] ) :
simplify ( expression [ 'elseExpression' ] ) ;
2016-06-13 15:56:51 -07:00
case 'pre' :
let operand = simplify ( expression [ 'operand' ] ) ;
2016-06-17 13:11:00 -07:00
if ( shouldIgnore ( operand ) ) return operand ;
2016-06-13 15:56:51 -07:00
switch ( expression [ 'operator' ] ) {
case '+' :
return operand ;
case '-' :
return - operand ;
case '!' :
return ! operand ;
case '~' :
return ~ operand ;
}
return null ;
case 'index' :
let indexTarget = simplify ( expression [ 'expression' ] ) ;
let index = simplify ( expression [ 'index' ] ) ;
if ( indexTarget && isPrimitive ( index ) ) return indexTarget [ index ] ;
return null ;
case 'select' :
let selectTarget = simplify ( expression [ 'expression' ] ) ;
2016-07-27 19:26:59 -07:00
if ( selectTarget instanceof StaticSymbol ) {
// Access to a static instance variable
const declarationValue = resolveReferenceValue ( selectTarget ) ;
if ( declarationValue && declarationValue . statics ) {
selectTarget = declarationValue . statics ;
} else {
2016-08-23 11:58:12 -07:00
const member : string = expression [ 'member' ] ;
const members = selectTarget . members ?
( selectTarget . members as string [ ] ) . concat ( member ) :
[ member ] ;
return _this . host . getStaticSymbol (
selectTarget . filePath , selectTarget . name , members ) ;
2016-07-27 19:26:59 -07:00
}
}
const member = simplify ( expression [ 'member' ] ) ;
if ( selectTarget && isPrimitive ( member ) ) return simplify ( selectTarget [ member ] ) ;
2016-06-13 15:56:51 -07:00
return null ;
case 'reference' :
if ( ! expression . module ) {
2016-11-12 14:08:58 +01:00
const name : string = expression [ 'name' ] ;
const localValue = scope . resolve ( name ) ;
2016-06-13 15:56:51 -07:00
if ( localValue != BindingScope . missing ) {
return localValue ;
}
2016-04-29 14:34:01 -07:00
}
feat(browser): use AppModules for bootstrap in the browser
This introduces the `BrowserModule` to be used for long form
bootstrap and offline compile bootstrap:
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {bootstrapModuleFactory} from ‘@angular/platform-browser’;
bootstrapModuleFactory(MyModuleNgFactory);
// runtime compile long form
import {bootstrapModule} from ‘@angular/platform-browser-dynamic’;
bootstrapModule(MyModule);
```
The short form, `bootstrap(...)`, can now creates a module on the fly,
given `directives`, `pipes, `providers`, `precompile` and `modules`
properties.
Related changes:
- make `SanitizationService`, `SecurityContext` public in `@angular/core` so that the offline compiler can resolve the token
- move `AnimationDriver` to `platform-browser` and make it
public so that the offline compiler can resolve the token
BREAKING CHANGES:
- short form bootstrap does no longer allow
to inject compiler internals (i.e. everything
from `@angular/compiler). Inject `Compiler` instead.
To provide custom providers for the compiler,
create a custom compiler via `browserCompiler({providers: [...]})`
and pass that into the `bootstrap` method.
2016-06-30 13:07:17 -07:00
staticSymbol = resolveReference ( context , expression ) ;
2016-06-13 15:56:51 -07:00
let result : any = staticSymbol ;
feat(browser): use AppModules for bootstrap in the browser
This introduces the `BrowserModule` to be used for long form
bootstrap and offline compile bootstrap:
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {bootstrapModuleFactory} from ‘@angular/platform-browser’;
bootstrapModuleFactory(MyModuleNgFactory);
// runtime compile long form
import {bootstrapModule} from ‘@angular/platform-browser-dynamic’;
bootstrapModule(MyModule);
```
The short form, `bootstrap(...)`, can now creates a module on the fly,
given `directives`, `pipes, `providers`, `precompile` and `modules`
properties.
Related changes:
- make `SanitizationService`, `SecurityContext` public in `@angular/core` so that the offline compiler can resolve the token
- move `AnimationDriver` to `platform-browser` and make it
public so that the offline compiler can resolve the token
BREAKING CHANGES:
- short form bootstrap does no longer allow
to inject compiler internals (i.e. everything
from `@angular/compiler). Inject `Compiler` instead.
To provide custom providers for the compiler,
create a custom compiler via `browserCompiler({providers: [...]})`
and pass that into the `bootstrap` method.
2016-06-30 13:07:17 -07:00
let declarationValue = resolveReferenceValue ( result ) ;
2016-06-13 15:56:51 -07:00
if ( declarationValue ) {
feat(browser): use AppModules for bootstrap in the browser
This introduces the `BrowserModule` to be used for long form
bootstrap and offline compile bootstrap:
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {bootstrapModuleFactory} from ‘@angular/platform-browser’;
bootstrapModuleFactory(MyModuleNgFactory);
// runtime compile long form
import {bootstrapModule} from ‘@angular/platform-browser-dynamic’;
bootstrapModule(MyModule);
```
The short form, `bootstrap(...)`, can now creates a module on the fly,
given `directives`, `pipes, `providers`, `precompile` and `modules`
properties.
Related changes:
- make `SanitizationService`, `SecurityContext` public in `@angular/core` so that the offline compiler can resolve the token
- move `AnimationDriver` to `platform-browser` and make it
public so that the offline compiler can resolve the token
BREAKING CHANGES:
- short form bootstrap does no longer allow
to inject compiler internals (i.e. everything
from `@angular/compiler). Inject `Compiler` instead.
To provide custom providers for the compiler,
create a custom compiler via `browserCompiler({providers: [...]})`
and pass that into the `bootstrap` method.
2016-06-30 13:07:17 -07:00
if ( isOpaqueToken ( staticSymbol , declarationValue ) ) {
2016-06-13 15:56:51 -07:00
// If the referenced symbol is initalized by a new OpaqueToken we can keep the
// reference to the symbol.
return staticSymbol ;
}
2016-06-17 13:11:00 -07:00
result = simplifyInContext ( staticSymbol , declarationValue , depth + 1 ) ;
2016-06-13 15:56:51 -07:00
}
return result ;
case 'class' :
2016-04-29 16:27:21 -07:00
return context ;
2016-06-13 15:56:51 -07:00
case 'function' :
feat(browser): use AppModules for bootstrap in the browser
This introduces the `BrowserModule` to be used for long form
bootstrap and offline compile bootstrap:
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {bootstrapModuleFactory} from ‘@angular/platform-browser’;
bootstrapModuleFactory(MyModuleNgFactory);
// runtime compile long form
import {bootstrapModule} from ‘@angular/platform-browser-dynamic’;
bootstrapModule(MyModule);
```
The short form, `bootstrap(...)`, can now creates a module on the fly,
given `directives`, `pipes, `providers`, `precompile` and `modules`
properties.
Related changes:
- make `SanitizationService`, `SecurityContext` public in `@angular/core` so that the offline compiler can resolve the token
- move `AnimationDriver` to `platform-browser` and make it
public so that the offline compiler can resolve the token
BREAKING CHANGES:
- short form bootstrap does no longer allow
to inject compiler internals (i.e. everything
from `@angular/compiler). Inject `Compiler` instead.
To provide custom providers for the compiler,
create a custom compiler via `browserCompiler({providers: [...]})`
and pass that into the `bootstrap` method.
2016-06-30 13:07:17 -07:00
return context ;
2016-06-13 15:56:51 -07:00
case 'new' :
case 'call' :
// Determine if the function is a built-in conversion
let target = expression [ 'expression' ] ;
if ( target [ 'module' ] ) {
staticSymbol = _this . host . findDeclaration (
target [ 'module' ] , target [ 'name' ] , context . filePath ) ;
} else {
staticSymbol = _this . host . getStaticSymbol ( context . filePath , target [ 'name' ] ) ;
}
let converter = _this . conversionMap . get ( staticSymbol ) ;
if ( converter ) {
2016-06-17 13:11:00 -07:00
let args : any [ ] = expression [ 'arguments' ] ;
2016-06-13 15:56:51 -07:00
if ( ! args ) {
args = [ ] ;
}
2016-06-17 13:11:00 -07:00
return converter (
context , args . map ( arg = > simplifyInContext ( context , arg , depth + 1 ) ) ) ;
2016-06-13 15:56:51 -07:00
}
// Determine if the function is one we can simplify.
return simplifyCall ( expression ) ;
case 'error' :
let message = produceErrorMessage ( expression ) ;
if ( expression [ 'line' ] ) {
message =
2016-07-11 17:26:35 -07:00
` ${ message } (position ${ expression [ 'line' ] + 1 } : ${ expression [ 'character' ] + 1 } in the original .ts file) ` ;
2016-11-09 16:29:22 -08:00
throw positionalError (
message , context . filePath , expression [ 'line' ] , expression [ 'character' ] ) ;
2016-06-13 15:56:51 -07:00
}
throw new Error ( message ) ;
}
return null ;
2016-03-24 10:03:10 -07:00
}
2016-06-13 15:56:51 -07:00
return mapStringMap ( expression , ( value , name ) = > simplify ( value ) ) ;
2016-03-24 10:03:10 -07:00
}
2016-06-13 15:56:51 -07:00
return null ;
2016-03-24 10:03:10 -07:00
}
2016-06-13 15:56:51 -07:00
try {
return simplify ( value ) ;
} catch ( e ) {
2016-11-09 16:29:22 -08:00
const message = ` ${ e . message } , resolving symbol ${ context . name } in ${ context . filePath } ` ;
if ( e . fileName ) {
throw positionalError ( message , e . fileName , e . line , e . column ) ;
}
throw new Error ( message ) ;
2016-06-13 15:56:51 -07:00
}
2016-06-03 15:43:09 -07:00
}
2016-06-13 15:56:51 -07:00
2016-10-21 10:29:47 -07:00
const result = simplifyInContext ( context , value , 0 ) ;
2016-06-17 13:11:00 -07:00
if ( shouldIgnore ( result ) ) {
return undefined ;
}
return result ;
2016-03-24 10:03:10 -07:00
}
2016-04-25 21:29:06 -07:00
/ * *
* @param module an absolute path to a module file .
* /
2016-02-18 10:53:21 -08:00
public getModuleMetadata ( module : string ) : { [ key : string ] : any } {
2016-03-24 10:03:10 -07:00
let moduleMetadata = this . metadataCache . get ( module ) ;
2016-05-03 09:24:09 -07:00
if ( ! moduleMetadata ) {
2016-03-24 10:03:10 -07:00
moduleMetadata = this . host . getMetadataFor ( module ) ;
2016-06-02 16:40:38 -07:00
if ( Array . isArray ( moduleMetadata ) ) {
2016-10-21 10:29:47 -07:00
moduleMetadata = moduleMetadata . find ( md = > md [ 'version' ] === SUPPORTED_SCHEMA_VERSION ) ||
2016-06-08 16:38:52 -07:00
moduleMetadata [ 0 ] ;
2016-06-02 16:40:38 -07:00
}
2016-05-03 09:24:09 -07:00
if ( ! moduleMetadata ) {
2016-06-08 16:38:52 -07:00
moduleMetadata =
{ __symbolic : 'module' , version : SUPPORTED_SCHEMA_VERSION , module : module , metadata : { } } ;
2016-06-02 16:40:38 -07:00
}
if ( moduleMetadata [ 'version' ] != SUPPORTED_SCHEMA_VERSION ) {
2016-06-08 16:38:52 -07:00
throw new Error (
` Metadata version mismatch for module ${ module } , found version ${ moduleMetadata [ 'version' ] } , expected ${ SUPPORTED_SCHEMA_VERSION } ` ) ;
2016-03-24 10:03:10 -07:00
}
this . metadataCache . set ( module , moduleMetadata ) ;
}
return moduleMetadata ;
}
2016-04-28 21:54:02 -07:00
private getTypeMetadata ( type : StaticSymbol ) : { [ key : string ] : any } {
2016-10-21 10:29:47 -07:00
const moduleMetadata = this . getModuleMetadata ( type . filePath ) ;
return moduleMetadata [ 'metadata' ] [ type . name ] || { __symbolic : 'class' } ;
2016-03-24 10:03:10 -07:00
}
2016-06-03 15:43:09 -07:00
}
function expandedMessage ( error : any ) : string {
switch ( error . message ) {
case 'Reference to non-exported class' :
if ( error . context && error . context . className ) {
2016-08-22 17:37:48 -07:00
return ` Reference to a non-exported class ${ error . context . className } . Consider exporting the class ` ;
2016-06-03 15:43:09 -07:00
}
break ;
case 'Variable not initialized' :
2016-08-22 17:37:48 -07:00
return 'Only initialized variables and constants can be referenced because the value of this variable is needed by the template compiler' ;
2016-06-03 15:43:09 -07:00
case 'Destructuring not supported' :
2016-08-22 17:37:48 -07:00
return 'Referencing an exported destructured variable or constant is not supported by the template compiler. Consider simplifying this to avoid destructuring' ;
2016-06-03 15:43:09 -07:00
case 'Could not resolve type' :
if ( error . context && error . context . typeName ) {
return ` Could not resolve type ${ error . context . typeName } ` ;
}
break ;
case 'Function call not supported' :
2016-06-17 13:11:00 -07:00
let prefix =
error . context && error . context . name ? ` Calling function ' ${ error . context . name } ', f ` : 'F' ;
return prefix +
'unction calls are not supported. Consider replacing the function or lambda with a reference to an exported function' ;
2016-08-02 14:38:31 -07:00
case 'Reference to a local symbol' :
if ( error . context && error . context . name ) {
return ` Reference to a local (non-exported) symbol ' ${ error . context . name } '. Consider exporting the symbol ` ;
}
2016-06-03 15:43:09 -07:00
}
return error . message ;
}
function produceErrorMessage ( error : any ) : string {
return ` Error encountered resolving symbol values statically. ${ expandedMessage ( error ) } ` ;
2016-03-24 10:03:10 -07:00
}
2016-06-08 16:38:52 -07:00
function mapStringMap ( input : { [ key : string ] : any } , transform : ( value : any , key : string ) = > any ) :
{ [ key : string ] : any } {
2016-05-03 09:24:09 -07:00
if ( ! input ) return { } ;
2016-10-21 10:29:47 -07:00
const result : { [ key : string ] : any } = { } ;
2016-06-17 13:11:00 -07:00
Object . keys ( input ) . forEach ( ( key ) = > {
2016-11-12 14:08:58 +01:00
const value = transform ( input [ key ] , key ) ;
2016-06-17 13:11:00 -07:00
if ( ! shouldIgnore ( value ) ) {
result [ key ] = value ;
}
} ) ;
2016-02-18 10:53:21 -08:00
return result ;
}
2016-05-03 09:24:09 -07:00
2016-05-03 18:49:59 -07:00
function isPrimitive ( o : any ) : boolean {
2016-06-08 16:38:52 -07:00
return o === null || ( typeof o !== 'function' && typeof o !== 'object' ) ;
2016-05-26 15:07:51 -07:00
}
2016-06-13 15:56:51 -07:00
interface BindingScopeBuilder {
define ( name : string , value : any ) : BindingScopeBuilder ;
done ( ) : BindingScope ;
}
abstract class BindingScope {
abstract resolve ( name : string ) : any ;
public static missing = { } ;
public static empty : BindingScope = { resolve : name = > BindingScope . missing } ;
public static build ( ) : BindingScopeBuilder {
2016-10-21 10:29:47 -07:00
const current = new Map < string , any > ( ) ;
2016-06-13 15:56:51 -07:00
return {
define : function ( name , value ) {
current . set ( name , value ) ;
return this ;
} ,
done : function ( ) {
return current . size > 0 ? new PopulatedScope ( current ) : BindingScope . empty ;
}
} ;
}
}
class PopulatedScope extends BindingScope {
constructor ( private bindings : Map < string , any > ) { super ( ) ; }
resolve ( name : string ) : any {
return this . bindings . has ( name ) ? this . bindings . get ( name ) : BindingScope . missing ;
}
}
function sameSymbol ( a : StaticSymbol , b : StaticSymbol ) : boolean {
return a === b || ( a . name == b . name && a . filePath == b . filePath ) ;
}
2016-06-17 13:11:00 -07:00
function shouldIgnore ( value : any ) : boolean {
return value && value . __symbolic == 'ignore' ;
2016-07-18 03:50:31 -07:00
}
2016-11-09 16:29:22 -08:00
function positionalError ( message : string , fileName : string , line : number , column : number ) : Error {
const result = new Error ( message ) ;
( result as any ) . fileName = fileName ;
( result as any ) . line = line ;
( result as any ) . column = column ;
return result ;
}