Compare commits

..

33 Commits

Author SHA1 Message Date
c066281bad docs(changelog): add changelog for 2.3.0-rc.0 2016-11-30 15:42:56 -08:00
1b9493f725 chore(release): cut the 2.3.0-rc.0 release 2016-11-30 15:42:56 -08:00
ae26504e84 fix(core): update peer dep on zone.js to ^0.7.2 2016-11-30 15:42:56 -08:00
d420080b3b docs(changelog): add changelog for 2.2.4 2016-11-30 15:19:09 -08:00
2975d8933c fix(language-service): harden against partial normalization of directives 2016-11-30 14:55:56 -08:00
43c0e9a6bb fix(compiler): fix performance regression caused by 5b0f9e2
Fixes #13146
2016-11-30 14:55:56 -08:00
f275f36081 fix(version): take all of version string after patch version 2016-11-30 14:25:11 -08:00
e628b66cca feat(build): record angular version in the dom (#13164) 2016-11-30 13:52:08 -08:00
3e73bea3e7 refactor(compiler): convert metadata classes used in summaries into interfaces (#13123)
Part of #12787
2016-11-30 10:52:51 -08:00
42cf06fa12 feat(router): add support for custom route reuse strategies 2016-11-29 23:21:41 -08:00
c4bbafc291 feat: upgrade zone.js to v0.7.1 2016-11-29 17:24:00 -08:00
2d6a003dba feat: update RxJS peer dependency to 5.0.0-rc.4
Closes #13125

RxJS from beta-12 to rc.4, has removed the `cache`
operator. (See https://github.com/ReactiveX/rxjs/blob/master/CHANGELOG.md#breaking-changes-1)
If your application relies on it, then we suggest 
that you use the one from this gist:
https://gist.github.com/robwormald/19dea0c70a6e01aadced6731aed4f9f7
2016-11-29 16:27:33 -08:00
e45b7ffcd9 fix: shrinkwrap was out of date with packages.
Rerun shrinkwrap on a clean workspace
2016-11-29 16:27:33 -08:00
627282d2c8 fix(compiler): correctly evaluate references to static functions (#13133) 2016-11-29 12:02:50 -08:00
2f7492c986 refactor(compiler): remove unneeded fields from metadata
Removes `CompileIdentifierMetadata.name` / `.moduleUrl`,
as well as `CompileTypeMetadata.name / moduleUrl` and
`CompileFactoryMetadata.name / moduleUrl`.
2016-11-28 15:19:23 -08:00
2452cd14e0 refactor(compiler): drop old codegen tests that run inside of test.sh
These tests were hard to maintain and only yielded little value,
now that we have the full integration with TypeScript.
2016-11-28 15:19:23 -08:00
bc69c74be0 fix(tsc-wrapped): still emit version 1 metadata to allow to use new components in old setups 2016-11-28 15:18:57 -08:00
897555ca78 fix(tsc-wrapped): set correct version number 2016-11-28 15:18:56 -08:00
966bcbad5a fix(compiler-cli): pin the version of tsc-wrapped 2016-11-28 15:18:56 -08:00
94b8612e4e Fix(http): invalidStateError response body
Check on null value failed with last version of mozilla.
Check on undefined type instead.
2016-11-28 14:36:32 -08:00
b2b72190f8 fix(common): update DatePipe to allow closure compilation
Quote the date formats to prevent closure renaming.  These are specified as strings in templates using DatePipes and also need to be quoted here.
2016-11-28 14:36:12 -08:00
f5c8e0989d feat(core): properly support inheritance
## Inheritance Semantics:

Decorators:
1) list the decorators of the class and its parents in the ancestor first order
2) only use the last decorator of each kind (e.g. @Component / ...)

Constructor parameters:
If a class inherits from a parent class and does not declare
a constructor, it inherits the parent class constructor,
and with it the parameter metadata of that parent class.

Lifecycle hooks:
Follow the normal class inheritance model,
i.e. lifecycle hooks of parent classes will be called
even if the method is not overwritten in the child class.

## Example

E.g. the following is a valid use of inheritance and it will
also inherit all metadata:

```
@Directive({selector: 'someDir'})
class ParentDirective {
  constructor(someDep: SomeDep) {}

  ngOnInit() {}
}

class ChildDirective extends ParentDirective {}
```

Closes #11606
Closes #12892
2016-11-28 14:12:12 -08:00
4a09251921 doc(common): fix a typo in async pipe 2016-11-28 14:11:45 -08:00
36caaaa8e4 refactor(core): remove unused import
APP_ID  was removed after 2.2.x
2016-11-28 14:11:25 -08:00
808275a9d5 feat(core): expose destroy() method on ViewRef 2016-11-28 14:10:42 -08:00
be3784c957 revert: fix(animations): blend in all previously transitioned styles into next animation if interrupted
This reverts commit ef96763fa4.
2016-11-28 13:23:52 -08:00
555301ce3a docs(changelog): add changelog for 2.2.3
original SHA: 380377139b
2016-11-27 22:11:04 -08:00
7194fc2b9e fix(language-service): make link check pass 2016-11-23 16:21:06 -08:00
2a3ca7bfcf fix(compiler-cli): fix paths in source maps to be relative
The change looks bigger than it really is because I reordered the properties to match other tsconfigs we have.

The only real change is removal of sourceRoot property.

Fixes #13040
2016-11-23 15:48:24 -08:00
4cbf8ccf05 Keep console.log that are not called during compilation. 2016-11-23 15:47:02 -08:00
a6c4490fce Check if console.error is defined 2016-11-23 15:47:02 -08:00
2c02d34c05 refactor(lint): Don't allow console.log
Enable tslint check for `console.log` as a follow-up to
https://github.com/angular/angular/issues/13018
2016-11-23 15:47:01 -08:00
6c2d931744 chore: make test.sh work again
Previously, `test.sh` relied on calling `build.sh` first
2016-11-23 14:23:05 -08:00
166 changed files with 2673 additions and 1807 deletions

View File

@ -1,35 +1,66 @@
<a name="2.3.0-beta.1"></a>
# [2.3.0-beta.1](https://github.com/angular/angular/compare/2.3.0-beta.0...2.3.0-beta.1) (2016-11-22)
<a name="2.3.0-rc.0"></a>
# [2.3.0-rc.0](https://github.com/angular/angular/compare/2.3.0-beta.0...2.3.0-rc.0) (2016-11-30)
### Bug Fixes
Note: The 2.3.0-beta.1 release also contains all the changes present in the 2.2.2 release.
* **animations:** blend in all previously transitioned styles into next animation if interrupted ([#13014](https://github.com/angular/angular/issues/13014)) ([ef96763](https://github.com/angular/angular/commit/ef96763)), closes [#13013](https://github.com/angular/angular/issues/13013)
* **benchmarks:** use sanitized style values ([#12943](https://github.com/angular/angular/issues/12943)) ([fc5ac1e](https://github.com/angular/angular/commit/fc5ac1e))
* **build:** update versions of umd bundles ([#13038](https://github.com/angular/angular/issues/13038)) ([86ffa88](https://github.com/angular/angular/commit/86ffa88)), closes [#13037](https://github.com/angular/angular/issues/13037)
* **changelog:** replace beta.1 with beta.0 ([#12961](https://github.com/angular/angular/issues/12961)) ([07a986d](https://github.com/angular/angular/commit/07a986d))
* **ci:** pin version of npm on CircleCI ([#12954](https://github.com/angular/angular/issues/12954)) ([a3884db](https://github.com/angular/angular/commit/a3884db))
* **closure:** quote date pattern aliases ([#13012](https://github.com/angular/angular/issues/13012)) ([7dcca30](https://github.com/angular/angular/commit/7dcca30))
* **common:** update DatePipe to allow closure compilation ([b2b7219](https://github.com/angular/angular/commit/b2b7219))
* **compiler:** correctly evaluate references to static functions ([#13133](https://github.com/angular/angular/issues/13133)) ([627282d](https://github.com/angular/angular/commit/627282d))
* **compiler:** fix performance regression caused by 5b0f9e2 ([43c0e9a](https://github.com/angular/angular/commit/43c0e9a)), closes [#13146](https://github.com/angular/angular/issues/13146)
* **compiler:** fix versions of `@angular/tsc-wrapped` ([bccf0e6](https://github.com/angular/angular/commit/bccf0e6))
* **compiler-cli:** fix paths in source maps to be relative ([2a3ca7b](https://github.com/angular/angular/commit/2a3ca7b)), closes [#13040](https://github.com/angular/angular/issues/13040)
* **compiler-cli:** pin the version of `tsc-wrapped` ([966bcba](https://github.com/angular/angular/commit/966bcba))
* **language-service:** harden against partial normalization of directives ([2975d89](https://github.com/angular/angular/commit/2975d89))
* **core:** shrinkwrap was out of date with packages. ([e45b7ff](https://github.com/angular/angular/commit/e45b7ff))
* **language-service:** make link check pass ([7194fc2](https://github.com/angular/angular/commit/7194fc2))
* **router:** guards restore an incorrect url when used with skipLocationChange ([ad20d7d](https://github.com/angular/angular/commit/ad20d7d)), closes [#12825](https://github.com/angular/angular/issues/12825)
* **router:** support redirects to named outlets ([602522b](https://github.com/angular/angular/commit/602522b)), closes [#12740](https://github.com/angular/angular/issues/12740) [#9921](https://github.com/angular/angular/issues/9921)
* **tsc-wrapped:** set correct version number ([897555c](https://github.com/angular/angular/commit/897555c))
* **tsc-wrapped:** still emit version 1 metadata to allow use of new components in old setups ([bc69c74](https://github.com/angular/angular/commit/bc69c74))
* **upgrade:** call ng1 lifecycle hooks ([#12875](https://github.com/angular/angular/issues/12875)) ([1ef4696](https://github.com/angular/angular/commit/1ef4696))
* **version:** take all of version string after patch version ([f275f36](https://github.com/angular/angular/commit/f275f36))
### Features
* **core:** update RxJS peer dependency to 5.0.0-rc.4 ([2d6a003](https://github.com/angular/angular/commit/2d6a003)), closes [#13125](https://github.com/angular/angular/issues/13125)
* **core:** upgrade zone.js to v0.7.1 ([c4bbafc](https://github.com/angular/angular/commit/c4bbafc))
* **build:** record angular version in the dom ([#13164](https://github.com/angular/angular/issues/13164)) ([e628b66](https://github.com/angular/angular/commit/e628b66))
* **core:** expose destroy() method on ViewRef ([808275a](https://github.com/angular/angular/commit/808275a))
* **core:** properly support inheritance ([f5c8e09](https://github.com/angular/angular/commit/f5c8e09)), closes [#11606](https://github.com/angular/angular/issues/11606) [#12892](https://github.com/angular/angular/issues/12892)
* **language-service:** add services to support editors ([#12987](https://github.com/angular/angular/issues/12987)) ([519a324](https://github.com/angular/angular/commit/519a324))
* **router:** add support for custom route reuse strategies ([42cf06f](https://github.com/angular/angular/commit/42cf06f))
* **tools:** allow disabling annotation lowering ([c1a62e2](https://github.com/angular/angular/commit/c1a62e2))
<a name="2.2.2"></a>
## [2.2.2](https://github.com/angular/angular/compare/2.2.1...2.2.2) (2016-11-22)
<a name="2.2.4"></a>
## [2.2.4](https://github.com/angular/angular/compare/2.2.3...2.2.4) (2016-11-30)
### Bug Fixes
* **animations:** blend in all previously transitioned styles into next animation if interrupted ([#13014](https://github.com/angular/angular/issues/13014)) ([ea4fc9b](https://github.com/angular/angular/commit/ea4fc9b)), closes [#13013](https://github.com/angular/angular/issues/13013)
* **benchmarks:** use sanitized style values ([#12943](https://github.com/angular/angular/issues/12943)) ([33a7902](https://github.com/angular/angular/commit/33a7902))
* **closure:** quote date pattern aliases ([#13012](https://github.com/angular/angular/issues/13012)) ([0956ace](https://github.com/angular/angular/commit/0956ace))
* **compiler:** fix versions of `@angular/tsc-wrapped` ([2fe6fb1](https://github.com/angular/angular/commit/2fe6fb1))
* **router:** add a banner file for the router ([#12919](https://github.com/angular/angular/issues/12919)) ([8df328b](https://github.com/angular/angular/commit/8df328b))
* **router:** add a banner file for the router ([#12919](https://github.com/angular/angular/issues/12919)) ([511cd4d](https://github.com/angular/angular/commit/511cd4d))
* **router:** removes a peer dependency from router to upgrade ([115f18f](https://github.com/angular/angular/commit/115f18f))
* **router:** removes a peer dependency from router to upgrade ([87d5d49](https://github.com/angular/angular/commit/87d5d49))
* **router:** support redirects to named outlets ([09226d9](https://github.com/angular/angular/commit/09226d9)), closes [#12740](https://github.com/angular/angular/issues/12740) [#9921](https://github.com/angular/angular/issues/9921)
* **upgrade:** call ng1 lifecycle hooks ([#12875](https://github.com/angular/angular/issues/12875)) ([462316b](https://github.com/angular/angular/commit/462316b))
* **common:** update DatePipe to allow closure compilation ([eba53fd](https://github.com/angular/angular/commit/eba53fd))
* **compiler:** fix performance regression caused by 5b0f9e2 ([ee2d6e5](https://github.com/angular/angular/commit/ee2d6e5)), closes [#13146](https://github.com/angular/angular/issues/13146)
* **compiler-cli:** fix paths in source maps to be relative ([eb173bc](https://github.com/angular/angular/commit/eb173bc)), closes [#13040](https://github.com/angular/angular/issues/13040)
<a name="2.2.3"></a>
## [2.2.3](https://github.com/angular/angular/compare/2.2.2...2.2.3) (2016-11-23)
### Bug Fixes
* **compiler:** Revert: fix versions of `@angular/tsc-wrapped` ([015ca47](https://github.com/angular/angular/commit/015ca47))
* **animations:** Revert: blend in all previously transitioned styles into next animation if interrupted ([c12e56e](https://github.com/angular/angular/commit/c12e56e))
<a name="2.3.0-beta.0"></a>
# [2.3.0-beta.0](https://github.com/angular/angular/compare/2.2.0...2.3.0-beta.0) (2016-11-17)

View File

@ -7,7 +7,7 @@
"dependencies": {
"@angular/core": "^2.0.0-rc.7",
"reflect-metadata": "^0.1.2",
"rxjs": "5.0.0-beta.12",
"rxjs": "5.0.0-rc.4",
"jpm": "1.1.4",
"firefox-profile": "0.4.0",
"selenium-webdriver": "^2.53.3"

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
/* tslint:disable:no-console */
import {browser} from 'protractor';
const assertEventsContainsName = function(events: any[], eventName: string) {

View File

@ -14,6 +14,10 @@
export * from './src/location';
export {NgLocalization} from './src/localization';
export {CommonModule} from './src/common_module';
export {NgClass, NgFor, NgIf, NgPlural, NgPluralCase, NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault, NgTemplateOutlet} from './src/directives/index';
export {AsyncPipe, DatePipe, I18nPluralPipe, I18nSelectPipe, JsonPipe, LowerCasePipe, CurrencyPipe, DecimalPipe, PercentPipe, SlicePipe, UpperCasePipe} from './src/pipes/index';
export {AsyncPipe, DatePipe, I18nPluralPipe, I18nSelectPipe, JsonPipe, LowerCasePipe, CurrencyPipe, DecimalPipe, PercentPipe, SlicePipe, UpperCasePipe} from './src/pipes/index';
import {Version} from '@angular/core';
/**
* @stable
*/
export const VERSION = new Version('0.0.0-PLACEHOLDER');

View File

@ -59,7 +59,7 @@ const _observableStrategy = new ObservableStrategy();
* {@example common/pipes/ts/async_pipe.ts region='AsyncPipePromise'}
*
* It's also possible to use `async` with Observables. The example below binds the `time` Observable
* to the view. The Observable continuesly updates the view with the current time.
* to the view. The Observable continuously updates the view with the current time.
*
* {@example common/pipes/ts/async_pipe.ts region='AsyncPipeObservable'}
*

View File

@ -5,10 +5,14 @@
* 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
*/
export {AotCompilerHost, AotCompilerHost as StaticReflectorHost, StaticReflector, StaticSymbol} from '@angular/compiler';
export {CodeGenerator} from './src/codegen';
export {CompilerHost, CompilerHostContext, NodeCompilerHostContext} from './src/compiler_host';
export {Extractor} from './src/extractor';
export * from '@angular/tsc-wrapped';
import {Version} from '@angular/core';
/**
* @stable
*/
export const VERSION = new Version('0.0.0-PLACEHOLDER');

View File

@ -19,7 +19,7 @@ import {BasicComp} from './basic';
import {ComponentUsingThirdParty} from './comp_using_3rdp';
import {CompWithAnalyzeEntryComponentsProvider, CompWithEntryComponents} from './entry_components';
import {CompConsumingEvents, CompUsingPipes, CompWithProviders, CompWithReferences, DirPublishingEvents, ModuleUsingCustomElements} from './features';
import {CompUsingRootModuleDirectiveAndPipe, SomeDirectiveInRootModule, SomePipeInRootModule, SomeService, someLibModuleWithProviders} from './module_fixtures';
import {CompUsingRootModuleDirectiveAndPipe, SomeDirectiveInRootModule, SomeLibModule, SomePipeInRootModule, SomeService} from './module_fixtures';
import {CompWithNgContent, ProjectingComp} from './projection';
import {CompForChildQuery, CompWithChildQuery, CompWithDirectiveChild, DirectiveForQuery} from './queries';
@ -52,7 +52,7 @@ import {CompForChildQuery, CompWithChildQuery, CompWithDirectiveChild, Directive
FormsModule,
MdButtonModule,
ModuleUsingCustomElements,
someLibModuleWithProviders(),
SomeLibModule.withProviders(),
ThirdpartyModule,
],
providers: [SomeService],

View File

@ -63,17 +63,13 @@ export function provideValueWithEntryComponents(value: any) {
entryComponents: [CompUsingLibModuleDirectiveAndPipe],
})
export class SomeLibModule {
}
// TODO(tbosch): Make this a static method in `SomeLibModule` once
// our static reflector supports it.
// See https://github.com/angular/angular/issues/10266.
export function someLibModuleWithProviders(): ModuleWithProviders {
return {
ngModule: SomeLibModule,
providers: [
ServiceUsingLibModule,
provideValueWithEntryComponents([{a: 'b', component: CompUsingLibModuleDirectiveAndPipe}])
]
};
static withProviders() {
return {
ngModule: SomeLibModule,
providers: [
ServiceUsingLibModule, provideValueWithEntryComponents(
[{a: 'b', component: CompUsingLibModuleDirectiveAndPipe}])
]
};
}
}

View File

@ -9,7 +9,7 @@
"ng-xi18n": "./src/extract_i18n.js"
},
"dependencies": {
"@angular/tsc-wrapped": "^0.4.0",
"@angular/tsc-wrapped": "0.4.1",
"reflect-metadata": "^0.1.2",
"minimist": "^1.2.0"
},

View File

@ -44,7 +44,7 @@ export class CodeGenerator {
let root = this.options.basePath;
for (const eachRootDir of this.options.rootDirs || []) {
if (this.options.trace) {
console.log(`Check if ${filePath} is under rootDirs element ${eachRootDir}`);
console.error(`Check if ${filePath} is under rootDirs element ${eachRootDir}`);
}
if (path.relative(eachRootDir, filePath).indexOf('.') !== 0) {
root = eachRootDir;

View File

@ -186,7 +186,7 @@ export class CompilerHost implements AotCompilerHost {
if (!v2Metadata && v1Metadata) {
// patch up v1 to v2 by merging the metadata with metadata collected from the d.ts file
// as the only difference between the versions is whether all exports are contained in
// the metadata
// the metadata and the `extends` clause.
v2Metadata = {'__symbolic': 'module', 'version': 2, 'metadata': {}};
if (v1Metadata.exports) {
v2Metadata.exports = v1Metadata.exports;

View File

@ -56,7 +56,7 @@ export class PathMappedCompilerHost extends CompilerHost {
ts.resolveModuleName(m, rootedContainingFile, this.options, this.context).resolvedModule;
if (resolved) {
if (this.options.traceResolution) {
console.log('resolve', m, containingFile, '=>', resolved.resolvedFileName);
console.error('resolve', m, containingFile, '=>', resolved.resolvedFileName);
}
return this.getCanonicalFileName(resolved.resolvedFileName);
}
@ -71,7 +71,7 @@ export class PathMappedCompilerHost extends CompilerHost {
*/
fileNameToModuleName(importedFile: string, containingFile: string): string {
if (this.options.traceResolution) {
console.log(
console.error(
'getImportPath from containingFile', containingFile, 'to importedFile', importedFile);
}

View File

@ -163,7 +163,11 @@ describe('CompilerHost', () => {
{__symbolic: 'module', version: 1, metadata: {foo: {__symbolic: 'class'}}}, {
__symbolic: 'module',
version: 2,
metadata: {foo: {__symbolic: 'class'}, bar: {__symbolic: 'class'}}
metadata: {
foo: {__symbolic: 'class'},
Bar: {__symbolic: 'class', members: {ngOnInit: [{__symbolic: 'method'}]}},
BarChild: {__symbolic: 'class', extends: {__symbolic: 'reference', name: 'Bar'}}
}
}
]);
});
@ -198,7 +202,12 @@ const FILES: Entry = {
}
},
'metadata_versions': {
'v1.d.ts': 'export declare class bar {}',
'v1.d.ts': `
export declare class Bar {
ngOnInit() {}
}
export declare class BarChild extends Bar {}
`,
'v1.metadata.json':
`{"__symbolic":"module", "version": 1, "metadata": {"foo": {"__symbolic": "class"}}}`,
}

View File

@ -1,11 +1,11 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": ["es6", "dom"],
"noImplicitAny": true,
"sourceMap": true,
"baseUrl": ".",
"declaration": true,
"experimentalDecorators": true,
"noImplicitAny": true,
"module": "commonjs",
"outDir": "../../../dist/packages-dist/compiler-cli",
"paths": {
"@angular/core": ["../../../dist/packages-dist/core"],
"@angular/common": ["../../../dist/packages-dist/common"],
@ -14,11 +14,11 @@
"@angular/platform-browser": ["../../../dist/packages-dist/platform-browser"],
"@angular/tsc-wrapped": ["../../../dist/tools/@angular/tsc-wrapped"]
},
"experimentalDecorators": true,
"rootDir": ".",
"sourceRoot": ".",
"outDir": "../../../dist/packages-dist/compiler-cli",
"declaration": true,
"sourceMap": true,
"inlineSources": true,
"target": "es5",
"lib": ["es6", "dom"],
"skipLibCheck": true
},
"exclude": ["integrationtest"],

View File

@ -21,6 +21,11 @@
* </p>
* </div>
*/
import {Version} from '@angular/core';
/**
* @stable
*/
export const VERSION = new Version('0.0.0-PLACEHOLDER');
export * from './src/template_parser/template_ast';
export {TEMPLATE_TRANSFORMS} from './src/template_parser/template_parser';
export {CompilerConfig, RenderTypes} from './src/config';
@ -58,5 +63,4 @@ export * from './src/style_compiler';
export * from './src/template_parser/template_parser';
export {ViewCompiler} from './src/view_compiler/view_compiler';
export {AnimationParser} from './src/animation/animation_parser';
// This file only reexports content of the `src` folder. Keep it that way.

View File

@ -8,7 +8,7 @@
import {isPresent} from '../facade/lang';
import {Identifiers, resolveIdentifier} from '../identifiers';
import {Identifiers, createIdentifier} from '../identifiers';
import * as o from '../output/output_ast';
import {ANY_STATE, DEFAULT_STATE, EMPTY_STATE} from '../private_import_core';
@ -69,8 +69,8 @@ class _AnimationBuilder implements AnimationAstVisitor {
stylesArr.push(o.literalMap(entries));
});
return o.importExpr(resolveIdentifier(Identifiers.AnimationStyles)).instantiate([
o.importExpr(resolveIdentifier(Identifiers.collectAndResolveStyles)).callFn([
return o.importExpr(createIdentifier(Identifiers.AnimationStyles)).instantiate([
o.importExpr(createIdentifier(Identifiers.collectAndResolveStyles)).callFn([
_ANIMATION_COLLECTED_STYLES, o.literalArr(stylesArr)
])
]);
@ -78,7 +78,7 @@ class _AnimationBuilder implements AnimationAstVisitor {
visitAnimationKeyframe(ast: AnimationKeyframeAst, context: _AnimationBuilderContext):
o.Expression {
return o.importExpr(resolveIdentifier(Identifiers.AnimationKeyframe)).instantiate([
return o.importExpr(createIdentifier(Identifiers.AnimationKeyframe)).instantiate([
o.literal(ast.offset), ast.styles.visit(this, context)
]);
}
@ -100,7 +100,7 @@ class _AnimationBuilder implements AnimationAstVisitor {
const startingStylesExpr = ast.startingStyles.visit(this, context);
const keyframeExpressions = ast.keyframes.map(keyframe => keyframe.visit(this, context));
const keyframesExpr =
o.importExpr(resolveIdentifier(Identifiers.balanceAnimationKeyframes)).callFn([
o.importExpr(createIdentifier(Identifiers.balanceAnimationKeyframes)).callFn([
_ANIMATION_COLLECTED_STYLES, _ANIMATION_END_STATE_STYLES_VAR,
o.literalArr(keyframeExpressions)
]);
@ -127,14 +127,14 @@ class _AnimationBuilder implements AnimationAstVisitor {
visitAnimationSequence(ast: AnimationSequenceAst, context: _AnimationBuilderContext):
o.Expression {
const playerExprs = ast.steps.map(step => step.visit(this, context));
return o.importExpr(resolveIdentifier(Identifiers.AnimationSequencePlayer)).instantiate([
return o.importExpr(createIdentifier(Identifiers.AnimationSequencePlayer)).instantiate([
o.literalArr(playerExprs)
]);
}
visitAnimationGroup(ast: AnimationGroupAst, context: _AnimationBuilderContext): o.Expression {
const playerExprs = ast.steps.map(step => step.visit(this, context));
return o.importExpr(resolveIdentifier(Identifiers.AnimationGroupPlayer)).instantiate([
return o.importExpr(createIdentifier(Identifiers.AnimationGroupPlayer)).instantiate([
o.literalArr(playerExprs)
]);
}
@ -228,7 +228,7 @@ class _AnimationBuilder implements AnimationAstVisitor {
_ANIMATION_END_STATE_STYLES_VAR.equals(o.NULL_EXPR),
[_ANIMATION_END_STATE_STYLES_VAR.set(_ANIMATION_DEFAULT_STATE_VAR).toStmt()]));
const RENDER_STYLES_FN = o.importExpr(resolveIdentifier(Identifiers.renderStyles));
const RENDER_STYLES_FN = o.importExpr(createIdentifier(Identifiers.renderStyles));
ast.stateTransitions.forEach(transAst => statements.push(transAst.visit(this, context)));
@ -237,7 +237,7 @@ class _AnimationBuilder implements AnimationAstVisitor {
statements.push(new o.IfStmt(
_ANIMATION_PLAYER_VAR.equals(o.NULL_EXPR),
[_ANIMATION_PLAYER_VAR
.set(o.importExpr(resolveIdentifier(Identifiers.NoOpAnimationPlayer)).instantiate([]))
.set(o.importExpr(createIdentifier(Identifiers.NoOpAnimationPlayer)).instantiate([]))
.toStmt()]));
// once complete we want to apply the styles on the element
@ -255,17 +255,18 @@ class _AnimationBuilder implements AnimationAstVisitor {
.callFn([
_ANIMATION_FACTORY_ELEMENT_VAR, _ANIMATION_FACTORY_RENDERER_VAR,
o.importExpr(
resolveIdentifier(Identifiers.prepareFinalAnimationStyles))
.callFn([
_ANIMATION_START_STATE_STYLES_VAR,
_ANIMATION_END_STATE_STYLES_VAR
])
createIdentifier(Identifiers.prepareFinalAnimationStyles))
.callFn(
[
_ANIMATION_START_STATE_STYLES_VAR,
_ANIMATION_END_STATE_STYLES_VAR
])
])
.toStmt()
])])
.toStmt());
statements.push(o.importExpr(resolveIdentifier(Identifiers.AnimationSequencePlayer))
statements.push(o.importExpr(createIdentifier(Identifiers.AnimationSequencePlayer))
.instantiate([_PREVIOUS_ANIMATION_PLAYERS])
.callMethod('destroy', [])
.toStmt());
@ -276,7 +277,7 @@ class _AnimationBuilder implements AnimationAstVisitor {
statements.push(RENDER_STYLES_FN
.callFn([
_ANIMATION_FACTORY_ELEMENT_VAR, _ANIMATION_FACTORY_RENDERER_VAR,
o.importExpr(resolveIdentifier(Identifiers.clearStyles))
o.importExpr(createIdentifier(Identifiers.clearStyles))
.callFn([_ANIMATION_START_STATE_STYLES_VAR])
])
.toStmt());
@ -291,7 +292,7 @@ class _AnimationBuilder implements AnimationAstVisitor {
.toStmt());
statements.push(new o.ReturnStatement(
o.importExpr(resolveIdentifier(Identifiers.AnimationTransition)).instantiate([
o.importExpr(createIdentifier(Identifiers.AnimationTransition)).instantiate([
_ANIMATION_PLAYER_VAR, _ANIMATION_CURRENT_STATE_VAR, _ANIMATION_NEXT_STATE_VAR,
_ANIMATION_TIME_VAR
])));
@ -300,12 +301,12 @@ class _AnimationBuilder implements AnimationAstVisitor {
[
new o.FnParam(
_ANIMATION_FACTORY_VIEW_VAR.name,
o.importType(resolveIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
o.importType(createIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
new o.FnParam(_ANIMATION_FACTORY_ELEMENT_VAR.name, o.DYNAMIC_TYPE),
new o.FnParam(_ANIMATION_CURRENT_STATE_VAR.name, o.DYNAMIC_TYPE),
new o.FnParam(_ANIMATION_NEXT_STATE_VAR.name, o.DYNAMIC_TYPE)
],
statements, o.importType(resolveIdentifier(Identifiers.AnimationTransition)));
statements, o.importType(createIdentifier(Identifiers.AnimationTransition)));
}
build(ast: AnimationAst): AnimationEntryCompileResult {

View File

@ -8,7 +8,7 @@
import {Injectable} from '@angular/core';
import {CompileAnimationAnimateMetadata, CompileAnimationEntryMetadata, CompileAnimationGroupMetadata, CompileAnimationKeyframesSequenceMetadata, CompileAnimationMetadata, CompileAnimationSequenceMetadata, CompileAnimationStateDeclarationMetadata, CompileAnimationStateTransitionMetadata, CompileAnimationStyleMetadata, CompileAnimationWithStepsMetadata, CompileDirectiveMetadata} from '../compile_metadata';
import {CompileAnimationAnimateMetadata, CompileAnimationEntryMetadata, CompileAnimationGroupMetadata, CompileAnimationKeyframesSequenceMetadata, CompileAnimationMetadata, CompileAnimationSequenceMetadata, CompileAnimationStateDeclarationMetadata, CompileAnimationStateTransitionMetadata, CompileAnimationStyleMetadata, CompileAnimationWithStepsMetadata, CompileDirectiveMetadata, identifierName} from '../compile_metadata';
import {StringMapWrapper} from '../facade/collection';
import {isBlank, isPresent} from '../facade/lang';
import {ParseError} from '../parse_util';
@ -41,7 +41,7 @@ export class AnimationParser {
parseComponent(component: CompileDirectiveMetadata): AnimationEntryAst[] {
const errors: string[] = [];
const componentName = component.type.name;
const componentName = identifierName(component.type);
const animationTriggerNames = new Set<string>();
const asts = component.template.animations.map(entry => {
const result = this.parseEntry(entry);

View File

@ -10,11 +10,11 @@ import {SchemaMetadata} from '@angular/core';
import {AnimationCompiler} from '../animation/animation_compiler';
import {AnimationParser} from '../animation/animation_parser';
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeMetadata, CompileProviderMetadata, createHostComponentMeta} from '../compile_metadata';
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeMetadata, CompileProviderMetadata, createHostComponentMeta, identifierModuleUrl, identifierName} from '../compile_metadata';
import {DirectiveNormalizer} from '../directive_normalizer';
import {DirectiveWrapperCompileResult, DirectiveWrapperCompiler} from '../directive_wrapper_compiler';
import {ListWrapper} from '../facade/collection';
import {Identifiers, resolveIdentifier, resolveIdentifierToken} from '../identifiers';
import {Identifiers, createIdentifier, createIdentifierToken} from '../identifiers';
import {CompileMetadataResolver} from '../metadata_resolver';
import {NgModuleCompiler} from '../ng_module_compiler';
import {OutputEmitter} from '../output/abstract_emitter';
@ -82,7 +82,7 @@ export class AotCompiler {
const ngModule = ngModuleByPipeOrDirective.get(dirType);
if (!ngModule) {
throw new Error(
`Internal Error: cannot determine the module for component ${compMeta.type.name}!`);
`Internal Error: cannot determine the module for component ${identifierName(compMeta.type)}!`);
}
_assertComponent(compMeta);
@ -113,24 +113,24 @@ export class AotCompiler {
const providers: CompileProviderMetadata[] = [];
if (this._localeId) {
providers.push(new CompileProviderMetadata({
token: resolveIdentifierToken(Identifiers.LOCALE_ID),
providers.push({
token: createIdentifierToken(Identifiers.LOCALE_ID),
useValue: this._localeId,
}));
});
}
if (this._translationFormat) {
providers.push(new CompileProviderMetadata({
token: resolveIdentifierToken(Identifiers.TRANSLATIONS_FORMAT),
providers.push({
token: createIdentifierToken(Identifiers.TRANSLATIONS_FORMAT),
useValue: this._translationFormat
}));
});
}
const appCompileResult = this._ngModuleCompiler.compile(ngModule, providers);
appCompileResult.dependencies.forEach((dep) => {
dep.placeholder.name = _componentFactoryName(dep.comp);
dep.placeholder.moduleUrl = _ngfactoryModuleUrl(dep.comp.moduleUrl);
dep.placeholder.reference = this._staticReflector.getStaticSymbol(
_ngfactoryModuleUrl(identifierModuleUrl(dep.comp)), _componentFactoryName(dep.comp));
});
targetStatements.push(...appCompileResult.statements);
@ -149,14 +149,17 @@ export class AotCompiler {
private _compileComponentFactory(
compMeta: CompileDirectiveMetadata, ngModule: CompileNgModuleMetadata, fileSuffix: string,
targetStatements: o.Statement[]): string {
const hostMeta = createHostComponentMeta(compMeta);
const hostMeta = createHostComponentMeta(
this._staticReflector.getStaticSymbol(
identifierModuleUrl(compMeta.type), `${identifierName(compMeta.type)}_Host`),
compMeta);
const hostViewFactoryVar = this._compileComponent(
hostMeta, ngModule, [compMeta.type], null, fileSuffix, targetStatements);
const compFactoryVar = _componentFactoryName(compMeta.type);
targetStatements.push(
o.variable(compFactoryVar)
.set(o.importExpr(resolveIdentifier(Identifiers.ComponentFactory), [o.importType(
compMeta.type)])
.set(o.importExpr(
createIdentifier(Identifiers.ComponentFactory), [o.importType(compMeta.type)])
.instantiate(
[
o.literal(compMeta.selector),
@ -164,7 +167,7 @@ export class AotCompiler {
o.importExpr(compMeta.type),
],
o.importType(
resolveIdentifier(Identifiers.ComponentFactory),
createIdentifier(Identifiers.ComponentFactory),
[o.importType(compMeta.type)], [o.TypeModifier.Const])))
.toDeclStmt(null, [o.StmtModifier.Final]));
return compFactoryVar;
@ -182,23 +185,24 @@ export class AotCompiler {
const parsedTemplate = this._templateParser.parse(
compMeta, compMeta.template.template, directives, pipes, ngModule.schemas,
compMeta.type.name);
identifierName(compMeta.type));
const stylesExpr = componentStyles ? o.variable(componentStyles.stylesVar) : o.literalArr([]);
const compiledAnimations =
this._animationCompiler.compile(compMeta.type.name, parsedAnimations);
this._animationCompiler.compile(identifierName(compMeta.type), parsedAnimations);
const viewResult = this._viewCompiler.compileComponent(
compMeta, parsedTemplate, stylesExpr, pipes, compiledAnimations);
if (componentStyles) {
targetStatements.push(..._resolveStyleStatements(componentStyles, fileSuffix));
targetStatements.push(
..._resolveStyleStatements(this._staticReflector, componentStyles, fileSuffix));
}
compiledAnimations.forEach(entry => targetStatements.push(...entry.statements));
targetStatements.push(..._resolveViewStatements(viewResult));
targetStatements.push(..._resolveViewStatements(this._staticReflector, viewResult));
return viewResult.viewClassVar;
}
private _codgenStyles(
fileUrl: string, stylesCompileResult: CompiledStylesheet, fileSuffix: string): SourceModule {
_resolveStyleStatements(stylesCompileResult, fileSuffix);
_resolveStyleStatements(this._staticReflector, stylesCompileResult, fileSuffix);
return this._codegenSourceModule(
fileUrl, _stylesModuleUrl(
stylesCompileResult.meta.moduleUrl, stylesCompileResult.isShimmed, fileSuffix),
@ -214,18 +218,21 @@ export class AotCompiler {
}
}
function _resolveViewStatements(compileResult: ViewCompileResult): o.Statement[] {
function _resolveViewStatements(
reflector: StaticReflector, compileResult: ViewCompileResult): o.Statement[] {
compileResult.dependencies.forEach((dep) => {
if (dep instanceof ViewClassDependency) {
const vfd = <ViewClassDependency>dep;
vfd.placeholder.moduleUrl = _ngfactoryModuleUrl(vfd.comp.moduleUrl);
vfd.placeholder.reference =
reflector.getStaticSymbol(_ngfactoryModuleUrl(identifierModuleUrl(vfd.comp)), dep.name);
} else if (dep instanceof ComponentFactoryDependency) {
const cfd = <ComponentFactoryDependency>dep;
cfd.placeholder.name = _componentFactoryName(cfd.comp);
cfd.placeholder.moduleUrl = _ngfactoryModuleUrl(cfd.comp.moduleUrl);
cfd.placeholder.reference = reflector.getStaticSymbol(
_ngfactoryModuleUrl(identifierModuleUrl(cfd.comp)), _componentFactoryName(cfd.comp));
} else if (dep instanceof DirectiveWrapperDependency) {
const dwd = <DirectiveWrapperDependency>dep;
dwd.placeholder.moduleUrl = _ngfactoryModuleUrl(dwd.dir.moduleUrl);
dwd.placeholder.reference =
reflector.getStaticSymbol(_ngfactoryModuleUrl(identifierModuleUrl(dwd.dir)), dwd.name);
}
});
return compileResult.statements;
@ -233,9 +240,11 @@ function _resolveViewStatements(compileResult: ViewCompileResult): o.Statement[]
function _resolveStyleStatements(
compileResult: CompiledStylesheet, fileSuffix: string): o.Statement[] {
reflector: StaticReflector, compileResult: CompiledStylesheet,
fileSuffix: string): o.Statement[] {
compileResult.dependencies.forEach((dep) => {
dep.valuePlaceholder.moduleUrl = _stylesModuleUrl(dep.moduleUrl, dep.isShimmed, fileSuffix);
dep.valuePlaceholder.reference = reflector.getStaticSymbol(
_stylesModuleUrl(dep.moduleUrl, dep.isShimmed, fileSuffix), dep.name);
});
return compileResult.statements;
}
@ -246,7 +255,7 @@ function _ngfactoryModuleUrl(dirUrl: string): string {
}
function _componentFactoryName(comp: CompileIdentifierMetadata): string {
return `${comp.name}NgFactory`;
return `${identifierName(comp)}NgFactory`;
}
function _stylesModuleUrl(stylesheetUrl: string, shim: boolean, suffix: string): string {
@ -255,7 +264,8 @@ function _stylesModuleUrl(stylesheetUrl: string, shim: boolean, suffix: string):
function _assertComponent(meta: CompileDirectiveMetadata) {
if (!meta.isComponent) {
throw new Error(`Could not compile '${meta.type.name}' because it is not a component.`);
throw new Error(
`Could not compile '${identifierName(meta.type)}' because it is not a component.`);
}
}
@ -369,7 +379,7 @@ export function extractProgramSymbols(
files.filter(fileName => _filterFileByPatterns(fileName, options)).forEach(sourceFile => {
const moduleMetadata = staticReflector.getModuleMetadata(sourceFile);
if (!moduleMetadata) {
console.log(`WARNING: no metadata found for ${sourceFile}`);
console.error(`WARNING: no metadata found for ${sourceFile}`);
return;
}

View File

@ -70,16 +70,24 @@ export class StaticSymbolCache {
export class StaticReflector implements ReflectorReader {
private declarationCache = new Map<string, StaticSymbol>();
private annotationCache = new Map<StaticSymbol, any[]>();
private propertyCache = new Map<StaticSymbol, {[key: string]: any}>();
private propertyCache = new Map<StaticSymbol, {[key: string]: any[]}>();
private parameterCache = new Map<StaticSymbol, any[]>();
private methodCache = new Map<StaticSymbol, {[key: string]: boolean}>();
private metadataCache = new Map<string, {[key: string]: any}>();
private conversionMap = new Map<StaticSymbol, (context: StaticSymbol, args: any[]) => any>();
private opaqueToken: StaticSymbol;
constructor(
private host: StaticReflectorHost,
private staticSymbolCache: StaticSymbolCache = new StaticSymbolCache()) {
private staticSymbolCache: StaticSymbolCache = new StaticSymbolCache(),
knownMetadataClasses: {name: string, filePath: string, ctor: any}[] = [],
knownMetadataFunctions: {name: string, filePath: string, fn: any}[] = []) {
this.initializeConversionMap();
knownMetadataClasses.forEach(
(kc) => this._registerDecoratorOrConstructor(
this.getStaticSymbol(kc.filePath, kc.name), kc.ctor));
knownMetadataFunctions.forEach(
(kf) => this._registerFunction(this.getStaticSymbol(kf.filePath, kf.name), kf.fn));
}
importUri(typeOrFunc: StaticSymbol): string {
@ -99,29 +107,45 @@ export class StaticReflector implements ReflectorReader {
public annotations(type: StaticSymbol): any[] {
let annotations = this.annotationCache.get(type);
if (!annotations) {
annotations = [];
const classMetadata = this.getTypeMetadata(type);
if (classMetadata['extends']) {
const parentAnnotations = this.annotations(this.simplify(type, classMetadata['extends']));
annotations.push(...parentAnnotations);
}
if (classMetadata['decorators']) {
annotations = this.simplify(type, classMetadata['decorators']);
} else {
annotations = [];
const ownAnnotations: any[] = this.simplify(type, classMetadata['decorators']);
annotations.push(...ownAnnotations);
}
this.annotationCache.set(type, annotations.filter(ann => !!ann));
}
return annotations;
}
public propMetadata(type: StaticSymbol): {[key: string]: any} {
public propMetadata(type: StaticSymbol): {[key: string]: any[]} {
let propMetadata = this.propertyCache.get(type);
if (!propMetadata) {
const classMetadata = this.getTypeMetadata(type);
const members = classMetadata ? classMetadata['members'] : {};
propMetadata = mapStringMap(members, (propData, propName) => {
const classMetadata = this.getTypeMetadata(type) || {};
propMetadata = {};
if (classMetadata['extends']) {
const parentPropMetadata = this.propMetadata(this.simplify(type, classMetadata['extends']));
Object.keys(parentPropMetadata).forEach((parentProp) => {
propMetadata[parentProp] = parentPropMetadata[parentProp];
});
}
const members = classMetadata['members'] || {};
Object.keys(members).forEach((propName) => {
const propData = members[propName];
const prop = (<any[]>propData)
.find(a => a['__symbolic'] == 'property' || a['__symbolic'] == 'method');
const decorators: any[] = [];
if (propMetadata[propName]) {
decorators.push(...propMetadata[propName]);
}
propMetadata[propName] = decorators;
if (prop && prop['decorators']) {
return this.simplify(type, prop['decorators']);
} else {
return [];
decorators.push(...this.simplify(type, prop['decorators']));
}
});
this.propertyCache.set(type, propMetadata);
@ -155,6 +179,8 @@ export class StaticReflector implements ReflectorReader {
}
parameters.push(nestedResult);
});
} else if (classMetadata['extends']) {
parameters = this.parameters(this.simplify(type, classMetadata['extends']));
}
if (!parameters) {
parameters = [];
@ -163,28 +189,52 @@ export class StaticReflector implements ReflectorReader {
}
return parameters;
} catch (e) {
console.log(`Failed on type ${JSON.stringify(type)} with error ${e}`);
console.error(`Failed on type ${JSON.stringify(type)} with error ${e}`);
throw e;
}
}
private _methodNames(type: any): {[key: string]: boolean} {
let methodNames = this.methodCache.get(type);
if (!methodNames) {
const classMetadata = this.getTypeMetadata(type) || {};
methodNames = {};
if (classMetadata['extends']) {
const parentMethodNames = this._methodNames(this.simplify(type, classMetadata['extends']));
Object.keys(parentMethodNames).forEach((parentProp) => {
methodNames[parentProp] = parentMethodNames[parentProp];
});
}
const members = classMetadata['members'] || {};
Object.keys(members).forEach((propName) => {
const propData = members[propName];
const isMethod = (<any[]>propData).some(a => a['__symbolic'] == 'method');
methodNames[propName] = methodNames[propName] || isMethod;
});
this.methodCache.set(type, methodNames);
}
return methodNames;
}
hasLifecycleHook(type: any, lcProperty: string): boolean {
if (!(type instanceof StaticSymbol)) {
throw new Error(
`hasLifecycleHook received ${JSON.stringify(type)} which is not a StaticSymbol`);
}
const classMetadata = this.getTypeMetadata(type);
const members = classMetadata ? classMetadata['members'] : null;
const member: any[] =
members && members.hasOwnProperty(lcProperty) ? members[lcProperty] : null;
return member ? member.some(a => a['__symbolic'] == 'method') : false;
try {
return !!this._methodNames(type)[lcProperty];
} catch (e) {
console.error(`Failed on type ${JSON.stringify(type)} with error ${e}`);
throw e;
}
}
private registerDecoratorOrConstructor(type: StaticSymbol, ctor: any): void {
private _registerDecoratorOrConstructor(type: StaticSymbol, ctor: any): void {
this.conversionMap.set(type, (context: StaticSymbol, args: any[]) => new ctor(...args));
}
private registerFunction(type: StaticSymbol, fn: any): void {
private _registerFunction(type: StaticSymbol, fn: any): void {
this.conversionMap.set(type, (context: StaticSymbol, args: any[]) => fn.apply(undefined, args));
}
@ -193,50 +243,51 @@ export class StaticReflector implements ReflectorReader {
ANGULAR_IMPORT_LOCATIONS;
this.opaqueToken = this.findDeclaration(diOpaqueToken, 'OpaqueToken');
this.registerDecoratorOrConstructor(this.findDeclaration(diDecorators, 'Host'), Host);
this.registerDecoratorOrConstructor(
this._registerDecoratorOrConstructor(this.findDeclaration(diDecorators, 'Host'), Host);
this._registerDecoratorOrConstructor(
this.findDeclaration(diDecorators, 'Injectable'), Injectable);
this.registerDecoratorOrConstructor(this.findDeclaration(diDecorators, 'Self'), Self);
this.registerDecoratorOrConstructor(this.findDeclaration(diDecorators, 'SkipSelf'), SkipSelf);
this.registerDecoratorOrConstructor(this.findDeclaration(diDecorators, 'Inject'), Inject);
this.registerDecoratorOrConstructor(this.findDeclaration(diDecorators, 'Optional'), Optional);
this.registerDecoratorOrConstructor(
this._registerDecoratorOrConstructor(this.findDeclaration(diDecorators, 'Self'), Self);
this._registerDecoratorOrConstructor(this.findDeclaration(diDecorators, 'SkipSelf'), SkipSelf);
this._registerDecoratorOrConstructor(this.findDeclaration(diDecorators, 'Inject'), Inject);
this._registerDecoratorOrConstructor(this.findDeclaration(diDecorators, 'Optional'), Optional);
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'Attribute'), Attribute);
this.registerDecoratorOrConstructor(
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'ContentChild'), ContentChild);
this.registerDecoratorOrConstructor(
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'ContentChildren'), ContentChildren);
this.registerDecoratorOrConstructor(
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'ViewChild'), ViewChild);
this.registerDecoratorOrConstructor(
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'ViewChildren'), ViewChildren);
this.registerDecoratorOrConstructor(this.findDeclaration(coreDecorators, 'Input'), Input);
this.registerDecoratorOrConstructor(this.findDeclaration(coreDecorators, 'Output'), Output);
this.registerDecoratorOrConstructor(this.findDeclaration(coreDecorators, 'Pipe'), Pipe);
this.registerDecoratorOrConstructor(
this._registerDecoratorOrConstructor(this.findDeclaration(coreDecorators, 'Input'), Input);
this._registerDecoratorOrConstructor(this.findDeclaration(coreDecorators, 'Output'), Output);
this._registerDecoratorOrConstructor(this.findDeclaration(coreDecorators, 'Pipe'), Pipe);
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'HostBinding'), HostBinding);
this.registerDecoratorOrConstructor(
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'HostListener'), HostListener);
this.registerDecoratorOrConstructor(
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'Directive'), Directive);
this.registerDecoratorOrConstructor(
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'Component'), Component);
this.registerDecoratorOrConstructor(this.findDeclaration(coreDecorators, 'NgModule'), NgModule);
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'NgModule'), NgModule);
// Note: Some metadata classes can be used directly with Provider.deps.
this.registerDecoratorOrConstructor(this.findDeclaration(diMetadata, 'Host'), Host);
this.registerDecoratorOrConstructor(this.findDeclaration(diMetadata, 'Self'), Self);
this.registerDecoratorOrConstructor(this.findDeclaration(diMetadata, 'SkipSelf'), SkipSelf);
this.registerDecoratorOrConstructor(this.findDeclaration(diMetadata, 'Optional'), Optional);
this._registerDecoratorOrConstructor(this.findDeclaration(diMetadata, 'Host'), Host);
this._registerDecoratorOrConstructor(this.findDeclaration(diMetadata, 'Self'), Self);
this._registerDecoratorOrConstructor(this.findDeclaration(diMetadata, 'SkipSelf'), SkipSelf);
this._registerDecoratorOrConstructor(this.findDeclaration(diMetadata, 'Optional'), Optional);
this.registerFunction(this.findDeclaration(animationMetadata, 'trigger'), trigger);
this.registerFunction(this.findDeclaration(animationMetadata, 'state'), state);
this.registerFunction(this.findDeclaration(animationMetadata, 'transition'), transition);
this.registerFunction(this.findDeclaration(animationMetadata, 'style'), style);
this.registerFunction(this.findDeclaration(animationMetadata, 'animate'), animate);
this.registerFunction(this.findDeclaration(animationMetadata, 'keyframes'), keyframes);
this.registerFunction(this.findDeclaration(animationMetadata, 'sequence'), sequence);
this.registerFunction(this.findDeclaration(animationMetadata, 'group'), group);
this._registerFunction(this.findDeclaration(animationMetadata, 'trigger'), trigger);
this._registerFunction(this.findDeclaration(animationMetadata, 'state'), state);
this._registerFunction(this.findDeclaration(animationMetadata, 'transition'), transition);
this._registerFunction(this.findDeclaration(animationMetadata, 'style'), style);
this._registerFunction(this.findDeclaration(animationMetadata, 'animate'), animate);
this._registerFunction(this.findDeclaration(animationMetadata, 'keyframes'), keyframes);
this._registerFunction(this.findDeclaration(animationMetadata, 'sequence'), sequence);
this._registerFunction(this.findDeclaration(animationMetadata, 'group'), group);
}
/**
@ -333,7 +384,7 @@ export class StaticReflector implements ReflectorReader {
/** @internal */
public simplify(context: StaticSymbol, value: any): any {
const _this = this;
const self = this;
let scope = BindingScope.empty;
const calling = new Map<StaticSymbol, boolean>();
@ -342,15 +393,15 @@ export class StaticReflector implements ReflectorReader {
let staticSymbol: StaticSymbol;
if (expression['module']) {
staticSymbol =
_this.findDeclaration(expression['module'], expression['name'], context.filePath);
self.findDeclaration(expression['module'], expression['name'], context.filePath);
} else {
staticSymbol = _this.getStaticSymbol(context.filePath, expression['name']);
staticSymbol = self.getStaticSymbol(context.filePath, expression['name']);
}
return staticSymbol;
}
function resolveReferenceValue(staticSymbol: StaticSymbol): any {
const moduleMetadata = _this.getModuleMetadata(staticSymbol.filePath);
const moduleMetadata = self.getModuleMetadata(staticSymbol.filePath);
const declarationValue =
moduleMetadata ? moduleMetadata['metadata'][staticSymbol.name] : null;
return declarationValue;
@ -360,7 +411,7 @@ export class StaticReflector implements ReflectorReader {
if (value && value.__symbolic === 'new' && value.expression) {
const target = value.expression;
if (target.__symbolic == 'reference') {
return sameSymbol(resolveReference(context, target), _this.opaqueToken);
return sameSymbol(resolveReference(context, target), self.opaqueToken);
}
}
return false;
@ -542,22 +593,26 @@ export class StaticReflector implements ReflectorReader {
if (indexTarget && isPrimitive(index)) return indexTarget[index];
return null;
case 'select':
let selectContext = context;
let selectTarget = simplify(expression['expression']);
if (selectTarget instanceof StaticSymbol) {
// Access to a static instance variable
const member: string = expression['member'];
const members = selectTarget.members ?
(selectTarget.members as string[]).concat(member) :
[member];
const declarationValue = resolveReferenceValue(selectTarget);
selectContext =
self.getStaticSymbol(selectTarget.filePath, selectTarget.name, members);
if (declarationValue && declarationValue.statics) {
selectTarget = declarationValue.statics;
} else {
const member: string = expression['member'];
const members = selectTarget.members ?
(selectTarget.members as string[]).concat(member) :
[member];
return _this.getStaticSymbol(selectTarget.filePath, selectTarget.name, members);
return selectContext;
}
}
const member = simplify(expression['member']);
if (selectTarget && isPrimitive(member)) return simplify(selectTarget[member]);
const member = simplifyInContext(selectContext, expression['member'], depth + 1);
if (selectTarget && isPrimitive(member))
return simplifyInContext(selectContext, selectTarget[member], depth + 1);
return null;
case 'reference':
if (!expression.module) {
@ -589,11 +644,11 @@ export class StaticReflector implements ReflectorReader {
let target = expression['expression'];
if (target['module']) {
staticSymbol =
_this.findDeclaration(target['module'], target['name'], context.filePath);
self.findDeclaration(target['module'], target['name'], context.filePath);
} else {
staticSymbol = _this.getStaticSymbol(context.filePath, target['name']);
staticSymbol = self.getStaticSymbol(context.filePath, target['name']);
}
let converter = _this.conversionMap.get(staticSymbol);
let converter = self.conversionMap.get(staticSymbol);
if (converter) {
let args: any[] = expression['arguments'];
if (!args) {

View File

@ -8,11 +8,12 @@
import {ChangeDetectionStrategy, SchemaMetadata, Type, ViewEncapsulation} from '@angular/core';
import {StaticSymbol, isStaticSymbol} from './aot/static_symbol';
import {ListWrapper} from './facade/collection';
import {isPresent} from './facade/lang';
import {LifecycleHooks} from './private_import_core';
import {isPresent, stringify} from './facade/lang';
import {LifecycleHooks, reflector} from './private_import_core';
import {CssSelector} from './selector';
import {sanitizeIdentifier, splitAtColon} from './util';
import {splitAtColon} from './util';
function unimplemented(): any {
throw new Error('unimplemented');
@ -24,10 +25,6 @@ function unimplemented(): any {
// group 3: "@trigger" from "@trigger"
const HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))|(\@[-\w]+)$/;
export abstract class CompileMetadataWithIdentifier {
get identifier(): CompileIdentifierMetadata { return <CompileIdentifierMetadata>unimplemented(); }
}
export class CompileAnimationEntryMetadata {
constructor(
public name: string = null, public definitions: CompileAnimationStateMetadata[] = null) {}
@ -78,26 +75,45 @@ export class CompileAnimationGroupMetadata extends CompileAnimationWithStepsMeta
constructor(steps: CompileAnimationMetadata[] = null) { super(steps); }
}
export class CompileIdentifierMetadata implements CompileMetadataWithIdentifier {
reference: any;
name: string;
prefix: string;
moduleUrl: string;
value: any;
constructor(
{reference, name, moduleUrl, prefix, value}:
{reference?: any, name?: string, moduleUrl?: string, prefix?: string, value?: any} = {}) {
this.reference = reference;
this.name = name;
this.prefix = prefix;
this.moduleUrl = moduleUrl;
this.value = value;
}
get identifier(): CompileIdentifierMetadata { return this; }
function _sanitizeIdentifier(name: string): string {
return name.replace(/\W/g, '_');
}
let _anonymousTypeIndex = 0;
export function identifierName(compileIdentifier: CompileIdentifierMetadata): string {
if (!compileIdentifier || !compileIdentifier.reference) {
return null;
}
const ref = compileIdentifier.reference;
if (isStaticSymbol(ref)) {
return ref.name;
}
if (ref['__anonymousType']) {
return ref['__anonymousType'];
}
let identifier = stringify(ref);
if (identifier.indexOf('(') >= 0) {
// case: anonymous functions!
identifier = `anonymous_${_anonymousTypeIndex++}`;
ref['__anonymousType'] = identifier;
} else {
identifier = _sanitizeIdentifier(identifier);
}
return identifier;
}
export function identifierModuleUrl(compileIdentifier: CompileIdentifierMetadata): string {
const ref = compileIdentifier.reference;
if (isStaticSymbol(ref)) {
return ref.filePath;
}
return reflector.importUri(ref);
}
export interface CompileIdentifierMetadata { reference: any; }
/**
* A CompileSummary is the data needed to use a directive / pipe / module
* in other modules / components. However, this data is not enough to compile
@ -107,154 +123,65 @@ export interface CompileSummary {
isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */;
}
export class CompileDiDependencyMetadata {
isAttribute: boolean;
isSelf: boolean;
isHost: boolean;
isSkipSelf: boolean;
isOptional: boolean;
isValue: boolean;
token: CompileTokenMetadata;
value: any;
constructor({isAttribute, isSelf, isHost, isSkipSelf, isOptional, isValue, token, value}: {
isAttribute?: boolean,
isSelf?: boolean,
isHost?: boolean,
isSkipSelf?: boolean,
isOptional?: boolean,
isValue?: boolean,
query?: CompileQueryMetadata,
viewQuery?: CompileQueryMetadata,
token?: CompileTokenMetadata,
value?: any
} = {}) {
this.isAttribute = !!isAttribute;
this.isSelf = !!isSelf;
this.isHost = !!isHost;
this.isSkipSelf = !!isSkipSelf;
this.isOptional = !!isOptional;
this.isValue = !!isValue;
this.token = token;
this.value = value;
}
export interface CompileDiDependencyMetadata {
isAttribute?: boolean;
isSelf?: boolean;
isHost?: boolean;
isSkipSelf?: boolean;
isOptional?: boolean;
isValue?: boolean;
token?: CompileTokenMetadata;
value?: any;
}
export class CompileProviderMetadata {
export interface CompileProviderMetadata {
token: CompileTokenMetadata;
useClass: CompileTypeMetadata;
useValue: any;
useExisting: CompileTokenMetadata;
useFactory: CompileFactoryMetadata;
deps: CompileDiDependencyMetadata[];
multi: boolean;
constructor({token, useClass, useValue, useExisting, useFactory, deps, multi}: {
token?: CompileTokenMetadata,
useClass?: CompileTypeMetadata,
useValue?: any,
useExisting?: CompileTokenMetadata,
useFactory?: CompileFactoryMetadata,
deps?: CompileDiDependencyMetadata[],
multi?: boolean
}) {
this.token = token;
this.useClass = useClass;
this.useValue = useValue;
this.useExisting = useExisting;
this.useFactory = useFactory;
this.deps = deps || null;
this.multi = !!multi;
}
useClass?: CompileTypeMetadata;
useValue?: any;
useExisting?: CompileTokenMetadata;
useFactory?: CompileFactoryMetadata;
deps?: CompileDiDependencyMetadata[];
multi?: boolean;
}
export class CompileFactoryMetadata extends CompileIdentifierMetadata {
export interface CompileFactoryMetadata extends CompileIdentifierMetadata {
diDeps: CompileDiDependencyMetadata[];
reference: any;
}
constructor({reference, name, moduleUrl, prefix, diDeps, value}: {
reference?: Function,
name?: string,
prefix?: string,
moduleUrl?: string,
value?: boolean,
diDeps?: CompileDiDependencyMetadata[]
}) {
super({reference: reference, name: name, prefix: prefix, moduleUrl: moduleUrl, value: value});
this.diDeps = _normalizeArray(diDeps);
export function tokenName(token: CompileTokenMetadata) {
return isPresent(token.value) ? _sanitizeIdentifier(token.value) :
identifierName(token.identifier);
}
export function tokenReference(token: CompileTokenMetadata) {
if (isPresent(token.identifier)) {
return token.identifier.reference;
} else {
return token.value;
}
}
export class CompileTokenMetadata implements CompileMetadataWithIdentifier {
value: any;
identifier: CompileIdentifierMetadata;
identifierIsInstance: boolean;
constructor(
{value, identifier, identifierIsInstance}:
{value?: any, identifier?: CompileIdentifierMetadata, identifierIsInstance?: boolean}) {
this.value = value;
this.identifier = identifier;
this.identifierIsInstance = !!identifierIsInstance;
}
get reference(): any {
if (isPresent(this.identifier)) {
return this.identifier.reference;
} else {
return this.value;
}
}
get name(): string {
return isPresent(this.value) ? sanitizeIdentifier(this.value) : this.identifier.name;
}
export interface CompileTokenMetadata {
value?: any;
identifier?: CompileIdentifierMetadata|CompileTypeMetadata;
}
/**
* Metadata regarding compilation of a type.
*/
export class CompileTypeMetadata extends CompileIdentifierMetadata {
isHost: boolean;
export interface CompileTypeMetadata extends CompileIdentifierMetadata {
diDeps: CompileDiDependencyMetadata[];
lifecycleHooks: LifecycleHooks[];
constructor({reference, name, moduleUrl, prefix, isHost, value, diDeps, lifecycleHooks}: {
reference?: Type<any>,
name?: string,
moduleUrl?: string,
prefix?: string,
isHost?: boolean,
value?: any,
diDeps?: CompileDiDependencyMetadata[],
lifecycleHooks?: LifecycleHooks[];
} = {}) {
super({reference: reference, name: name, moduleUrl: moduleUrl, prefix: prefix, value: value});
this.isHost = !!isHost;
this.diDeps = _normalizeArray(diDeps);
this.lifecycleHooks = _normalizeArray(lifecycleHooks);
}
reference: any;
}
export class CompileQueryMetadata {
export interface CompileQueryMetadata {
selectors: Array<CompileTokenMetadata>;
descendants: boolean;
first: boolean;
propertyName: string;
read: CompileTokenMetadata;
constructor({selectors, descendants, first, propertyName, read}: {
selectors?: Array<CompileTokenMetadata>,
descendants?: boolean,
first?: boolean,
propertyName?: string,
read?: CompileTokenMetadata
} = {}) {
this.selectors = selectors;
this.descendants = !!descendants;
this.first = !!first;
this.propertyName = propertyName;
this.read = read;
}
}
/**
@ -333,6 +260,8 @@ export class CompileTemplateMetadata {
}
}
// Note: This should only use interfaces as nested data types
// as we need to be able to serialize this from/to JSON!
export interface CompileDirectiveSummary extends CompileSummary {
isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */;
type: CompileTypeMetadata;
@ -355,10 +284,11 @@ export interface CompileDirectiveSummary extends CompileSummary {
/**
* Metadata regarding compilation of a directive.
*/
export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
export class CompileDirectiveMetadata {
static create(
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host, providers,
viewProviders, queries, viewQueries, entryComponents, template}: {
{isHost, type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host,
providers, viewProviders, queries, viewQueries, entryComponents, template}: {
isHost?: boolean,
type?: CompileTypeMetadata,
isComponent?: boolean,
selector?: string,
@ -367,10 +297,8 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
inputs?: string[],
outputs?: string[],
host?: {[key: string]: string},
providers?:
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
viewProviders?:
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
providers?: CompileProviderMetadata[],
viewProviders?: CompileProviderMetadata[],
queries?: CompileQueryMetadata[],
viewQueries?: CompileQueryMetadata[],
entryComponents?: CompileIdentifierMetadata[],
@ -412,6 +340,7 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
}
return new CompileDirectiveMetadata({
isHost,
type,
isComponent: !!isComponent, selector, exportAs, changeDetection,
inputs: inputsMap,
@ -427,6 +356,7 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
template,
});
}
isHost: boolean;
type: CompileTypeMetadata;
isComponent: boolean;
selector: string;
@ -446,9 +376,10 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
template: CompileTemplateMetadata;
constructor(
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, hostListeners,
hostProperties, hostAttributes, providers, viewProviders, queries, viewQueries,
entryComponents, template}: {
{isHost, type, isComponent, selector, exportAs, changeDetection, inputs, outputs,
hostListeners, hostProperties, hostAttributes, providers, viewProviders, queries,
viewQueries, entryComponents, template}: {
isHost?: boolean,
type?: CompileTypeMetadata,
isComponent?: boolean,
selector?: string,
@ -459,15 +390,14 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
hostListeners?: {[key: string]: string},
hostProperties?: {[key: string]: string},
hostAttributes?: {[key: string]: string},
providers?:
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
viewProviders?:
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
providers?: CompileProviderMetadata[],
viewProviders?: CompileProviderMetadata[],
queries?: CompileQueryMetadata[],
viewQueries?: CompileQueryMetadata[],
entryComponents?: CompileIdentifierMetadata[],
template?: CompileTemplateMetadata,
} = {}) {
this.isHost = !!isHost;
this.type = type;
this.isComponent = isComponent;
this.selector = selector;
@ -487,8 +417,6 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
this.template = template;
}
get identifier(): CompileIdentifierMetadata { return this.type; }
toSummary(): CompileDirectiveSummary {
return {
isSummary: true,
@ -514,16 +442,12 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
/**
* Construct {@link CompileDirectiveMetadata} from {@link ComponentTypeMetadata} and a selector.
*/
export function createHostComponentMeta(compMeta: CompileDirectiveMetadata):
CompileDirectiveMetadata {
export function createHostComponentMeta(
typeReference: any, compMeta: CompileDirectiveMetadata): CompileDirectiveMetadata {
const template = CssSelector.parse(compMeta.selector)[0].getMatchingElementTemplate();
return CompileDirectiveMetadata.create({
type: new CompileTypeMetadata({
reference: Object,
name: `${compMeta.type.name}_Host`,
moduleUrl: compMeta.type.moduleUrl,
isHost: true
}),
isHost: true,
type: {reference: typeReference, diDeps: [], lifecycleHooks: []},
template: new CompileTemplateMetadata({
encapsulation: ViewEncapsulation.None,
template: template,
@ -553,7 +477,7 @@ export interface CompilePipeSummary extends CompileSummary {
pure: boolean;
}
export class CompilePipeMetadata implements CompileMetadataWithIdentifier {
export class CompilePipeMetadata {
type: CompileTypeMetadata;
name: string;
pure: boolean;
@ -567,13 +491,14 @@ export class CompilePipeMetadata implements CompileMetadataWithIdentifier {
this.name = name;
this.pure = !!pure;
}
get identifier(): CompileIdentifierMetadata { return this.type; }
toSummary(): CompilePipeSummary {
return {isSummary: true, type: this.type, name: this.name, pure: this.pure};
}
}
// Note: This should only use interfaces as nested data types
// as we need to be able to serialize this from/to JSON!
export interface CompileNgModuleInjectorSummary extends CompileSummary {
isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */;
type: CompileTypeMetadata;
@ -583,6 +508,8 @@ export interface CompileNgModuleInjectorSummary extends CompileSummary {
exportedModules: CompileNgModuleInjectorSummary[];
}
// Note: This should only use interfaces as nested data types
// as we need to be able to serialize this from/to JSON!
export interface CompileNgModuleDirectiveSummary extends CompileSummary {
isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */;
type: CompileTypeMetadata;
@ -592,13 +519,15 @@ export interface CompileNgModuleDirectiveSummary extends CompileSummary {
directiveLoaders: (() => Promise<void>)[];
}
// Note: This should only use interfaces as nested data types
// as we need to be able to serialize this from/to JSON!
export type CompileNgModuleSummary =
CompileNgModuleInjectorSummary & CompileNgModuleDirectiveSummary;
/**
* Metadata regarding compilation of a module.
*/
export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier {
export class CompileNgModuleMetadata {
type: CompileTypeMetadata;
declaredDirectives: CompileIdentifierMetadata[];
exportedDirectives: CompileIdentifierMetadata[];
@ -620,8 +549,7 @@ export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier {
entryComponents, bootstrapComponents, importedModules, exportedModules, schemas,
transitiveModule, id}: {
type?: CompileTypeMetadata,
providers?:
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
providers?: CompileProviderMetadata[],
declaredDirectives?: CompileIdentifierMetadata[],
exportedDirectives?: CompileIdentifierMetadata[],
declaredPipes?: CompileIdentifierMetadata[],
@ -649,8 +577,6 @@ export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier {
this.transitiveModule = transitiveModule;
}
get identifier(): CompileIdentifierMetadata { return this.type; }
toSummary(): CompileNgModuleSummary {
return {
isSummary: true,
@ -701,19 +627,6 @@ export class TransitiveCompileNgModuleMetadata {
}
}
export function removeIdentifierDuplicates<T extends CompileMetadataWithIdentifier>(items: T[]):
T[] {
const map = new Map<any, T>();
items.forEach((item) => {
if (!map.get(item.identifier.reference)) {
map.set(item.identifier.reference, item);
}
});
return Array.from(map.values());
}
function _normalizeArray(obj: any[]): any[] {
return obj || [];
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Identifiers, resolveIdentifier} from '../identifiers';
import {Identifiers, createIdentifier} from '../identifiers';
import {ClassBuilder} from '../output/class_builder';
import * as o from '../output/output_ast';
@ -22,7 +22,7 @@ export function createCheckBindingField(builder: ClassBuilder): CheckBindingFiel
// private is fine here as no child view will reference the cached value...
builder.fields.push(new o.ClassField(fieldExpr.name, null, [o.StmtModifier.Private]));
builder.ctorStmts.push(o.THIS_EXPR.prop(fieldExpr.name)
.set(o.importExpr(resolveIdentifier(Identifiers.UNINITIALIZED)))
.set(o.importExpr(createIdentifier(Identifiers.UNINITIALIZED)))
.toStmt());
return new CheckBindingField(fieldExpr, bindingId);
}
@ -30,7 +30,7 @@ export function createCheckBindingField(builder: ClassBuilder): CheckBindingFiel
export function createCheckBindingStmt(
evalResult: ConvertPropertyBindingResult, fieldExpr: o.ReadPropExpr,
throwOnChangeVar: o.Expression, actions: o.Statement[]): o.Statement[] {
let condition: o.Expression = o.importExpr(resolveIdentifier(Identifiers.checkBinding)).callFn([
let condition: o.Expression = o.importExpr(createIdentifier(Identifiers.checkBinding)).callFn([
throwOnChangeVar, fieldExpr, evalResult.currValExpr
]);
if (evalResult.forceUpdate) {

View File

@ -9,7 +9,7 @@
import * as cdAst from '../expression_parser/ast';
import {isBlank, isPresent} from '../facade/lang';
import {Identifiers, resolveIdentifier} from '../identifiers';
import {Identifiers, createIdentifier} from '../identifiers';
import {ClassBuilder} from '../output/class_builder';
import * as o from '../output/output_ast';
@ -116,7 +116,7 @@ export function createSharedBindingVariablesIfNeeded(stmts: o.Statement[]): o.St
if (readVars.has(VAL_UNWRAPPER_VAR.name)) {
unwrapperStmts.push(
VAL_UNWRAPPER_VAR
.set(o.importExpr(resolveIdentifier(Identifiers.ValueUnwrapper)).instantiate([]))
.set(o.importExpr(createIdentifier(Identifiers.ValueUnwrapper)).instantiate([]))
.toDeclStmt(null, [o.StmtModifier.Final]));
}
return unwrapperStmts;
@ -277,8 +277,8 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
args.push(o.literal(ast.strings[ast.strings.length - 1]));
return ast.expressions.length <= 9 ?
o.importExpr(resolveIdentifier(Identifiers.inlineInterpolate)).callFn(args) :
o.importExpr(resolveIdentifier(Identifiers.interpolate)).callFn([
o.importExpr(createIdentifier(Identifiers.inlineInterpolate)).callFn(args) :
o.importExpr(createIdentifier(Identifiers.interpolate)).callFn([
args[0], o.literalArr(args.slice(1))
]);
}
@ -578,7 +578,7 @@ function flattenStatements(arg: any, output: o.Statement[]) {
function createCachedLiteralArray(builder: ClassBuilder, values: o.Expression[]): o.Expression {
if (values.length === 0) {
return o.importExpr(resolveIdentifier(Identifiers.EMPTY_ARRAY));
return o.importExpr(createIdentifier(Identifiers.EMPTY_ARRAY));
}
const proxyExpr = o.THIS_EXPR.prop(`_arr_${builder.fields.length}`);
const proxyParams: o.FnParam[] = [];
@ -599,7 +599,7 @@ function createCachedLiteralArray(builder: ClassBuilder, values: o.Expression[])
function createCachedLiteralMap(
builder: ClassBuilder, entries: [string, o.Expression][]): o.Expression {
if (entries.length === 0) {
return o.importExpr(resolveIdentifier(Identifiers.EMPTY_MAP));
return o.importExpr(createIdentifier(Identifiers.EMPTY_MAP));
}
const proxyExpr = o.THIS_EXPR.prop(`_map_${builder.fields.length}`);
const proxyParams: o.FnParam[] = [];

View File

@ -8,15 +8,12 @@
import {CompileTokenMetadata} from '../compile_metadata';
import {isPresent} from '../facade/lang';
import {IdentifierSpec, Identifiers, resolveEnumIdentifier, resolveIdentifier} from '../identifiers';
import {IdentifierSpec, Identifiers, createEnumIdentifier, createIdentifier} from '../identifiers';
import * as o from '../output/output_ast';
export function createDiTokenExpression(token: CompileTokenMetadata): o.Expression {
if (isPresent(token.value)) {
return o.literal(token.value);
} else if (token.identifierIsInstance) {
return o.importExpr(token.identifier)
.instantiate([], o.importType(token.identifier, [], [o.TypeModifier.Const]));
} else {
return o.importExpr(token.identifier);
}
@ -24,13 +21,13 @@ export function createDiTokenExpression(token: CompileTokenMetadata): o.Expressi
export function createInlineArray(values: o.Expression[]): o.Expression {
if (values.length === 0) {
return o.importExpr(resolveIdentifier(Identifiers.EMPTY_INLINE_ARRAY));
return o.importExpr(createIdentifier(Identifiers.EMPTY_INLINE_ARRAY));
}
const log2 = Math.log(values.length) / Math.log(2);
const index = Math.ceil(log2);
const identifierSpec = index < Identifiers.inlineArrays.length ? Identifiers.inlineArrays[index] :
Identifiers.InlineArrayDynamic;
const identifier = resolveIdentifier(identifierSpec);
const identifier = createIdentifier(identifierSpec);
return o.importExpr(identifier).instantiate([
<o.Expression>o.literal(values.length)
].concat(values));
@ -46,7 +43,7 @@ export function createPureProxy(
throw new Error(`Unsupported number of argument for pure functions: ${argCount}`);
}
builder.ctorStmts.push(o.THIS_EXPR.prop(pureProxyProp.name)
.set(o.importExpr(resolveIdentifier(pureProxyId)).callFn([fn]))
.set(o.importExpr(createIdentifier(pureProxyId)).callFn([fn]))
.toStmt());
}
@ -56,5 +53,5 @@ export function createEnumExpression(enumType: IdentifierSpec, enumValue: any):
if (!enumName) {
throw new Error(`Unknown enum value ${enumValue} in ${enumType.name}`);
}
return o.importExpr(resolveEnumIdentifier(resolveIdentifier(enumType), enumName));
return o.importExpr(createEnumIdentifier(enumType, enumName));
}

View File

@ -8,7 +8,7 @@
import {SecurityContext} from '@angular/core';
import {isPresent} from '../facade/lang';
import {Identifiers, resolveIdentifier} from '../identifiers';
import {Identifiers, createIdentifier} from '../identifiers';
import * as o from '../output/output_ast';
import {EMPTY_STATE as EMPTY_ANIMATION_STATE} from '../private_import_core';
import {BoundElementPropertyAst, BoundEventAst, PropertyBindingType} from '../template_parser/template_ast';
@ -26,7 +26,7 @@ export function writeToRenderer(
case PropertyBindingType.Property:
if (logBindingUpdate) {
updateStmts.push(
o.importExpr(resolveIdentifier(Identifiers.setBindingDebugInfo))
o.importExpr(createIdentifier(Identifiers.setBindingDebugInfo))
.callFn([renderer, renderElement, o.literal(boundProp.name), renderValue])
.toStmt());
}
@ -104,7 +104,7 @@ export function triggerAnimation(
// it's important to normalize the void value as `void` explicitly
// so that the styles data can be obtained from the stringmap
const emptyStateValue = o.literal(EMPTY_ANIMATION_STATE);
const unitializedValue = o.importExpr(resolveIdentifier(Identifiers.UNINITIALIZED));
const unitializedValue = o.importExpr(createIdentifier(Identifiers.UNINITIALIZED));
const animationTransitionVar = o.variable('animationTransition_' + animationName);
updateStmts.push(

View File

@ -9,7 +9,7 @@
import {ViewEncapsulation, isDevMode} from '@angular/core';
import {CompileIdentifierMetadata} from './compile_metadata';
import {Identifiers, resolveIdentifier} from './identifiers';
import {Identifiers, createIdentifier} from './identifiers';
function unimplemented(): any {
throw new Error('unimplemented');
@ -61,7 +61,7 @@ export abstract class RenderTypes {
}
export class DefaultRenderTypes implements RenderTypes {
get renderer() { return resolveIdentifier(Identifiers.Renderer); };
get renderer() { return createIdentifier(Identifiers.Renderer); };
renderText: any = null;
renderElement: any = null;
renderComment: any = null;

View File

@ -8,11 +8,12 @@
import {Component, Directive, HostBinding, HostListener, Injectable, Input, Output, Query, Type, resolveForwardRef} from '@angular/core';
import {StringMapWrapper} from './facade/collection';
import {ListWrapper, StringMapWrapper} from './facade/collection';
import {stringify} from './facade/lang';
import {ReflectorReader, reflector} from './private_import_core';
import {splitAtColon} from './util';
/*
* Resolve a `Type` for {@link Directive}.
*
@ -35,7 +36,7 @@ export class DirectiveResolver {
resolve(type: Type<any>, throwIfNotFound = true): Directive {
const typeMetadata = this._reflector.annotations(resolveForwardRef(type));
if (typeMetadata) {
const metadata = typeMetadata.find(isDirectiveMetadata);
const metadata = ListWrapper.findLast(typeMetadata, isDirectiveMetadata);
if (metadata) {
const propertyMetadata = this._reflector.propMetadata(type);
return this._mergeWithPropertyMetadata(metadata, propertyMetadata, type);
@ -58,85 +59,76 @@ export class DirectiveResolver {
const queries: {[key: string]: any} = {};
Object.keys(propertyMetadata).forEach((propName: string) => {
propertyMetadata[propName].forEach(a => {
if (a instanceof Input) {
if (a.bindingPropertyName) {
inputs.push(`${propName}: ${a.bindingPropertyName}`);
} else {
inputs.push(propName);
}
} else if (a instanceof Output) {
const output: Output = a;
if (output.bindingPropertyName) {
outputs.push(`${propName}: ${output.bindingPropertyName}`);
} else {
outputs.push(propName);
}
} else if (a instanceof HostBinding) {
const hostBinding: HostBinding = a;
if (hostBinding.hostPropertyName) {
const startWith = hostBinding.hostPropertyName[0];
if (startWith === '(') {
throw new Error(`@HostBinding can not bind to events. Use @HostListener instead.`);
} else if (startWith === '[') {
throw new Error(
`@HostBinding parameter should be a property name, 'class.<name>', or 'attr.<name>'.`);
}
host[`[${hostBinding.hostPropertyName}]`] = propName;
} else {
host[`[${propName}]`] = propName;
}
} else if (a instanceof HostListener) {
const hostListener: HostListener = a;
const args = hostListener.args || [];
host[`(${hostListener.eventName})`] = `${propName}(${args.join(',')})`;
} else if (a instanceof Query) {
queries[propName] = a;
const input = ListWrapper.findLast(propertyMetadata[propName], (a) => a instanceof Input);
if (input) {
if (input.bindingPropertyName) {
inputs.push(`${propName}: ${input.bindingPropertyName}`);
} else {
inputs.push(propName);
}
});
}
const output = ListWrapper.findLast(propertyMetadata[propName], (a) => a instanceof Output);
if (output) {
if (output.bindingPropertyName) {
outputs.push(`${propName}: ${output.bindingPropertyName}`);
} else {
outputs.push(propName);
}
}
const hostBinding =
ListWrapper.findLast(propertyMetadata[propName], (a) => a instanceof HostBinding);
if (hostBinding) {
if (hostBinding.hostPropertyName) {
const startWith = hostBinding.hostPropertyName[0];
if (startWith === '(') {
throw new Error(`@HostBinding can not bind to events. Use @HostListener instead.`);
} else if (startWith === '[') {
throw new Error(
`@HostBinding parameter should be a property name, 'class.<name>', or 'attr.<name>'.`);
}
host[`[${hostBinding.hostPropertyName}]`] = propName;
} else {
host[`[${propName}]`] = propName;
}
}
const hostListener =
ListWrapper.findLast(propertyMetadata[propName], (a) => a instanceof HostListener);
if (hostListener) {
const args = hostListener.args || [];
host[`(${hostListener.eventName})`] = `${propName}(${args.join(',')})`;
}
const query = ListWrapper.findLast(propertyMetadata[propName], (a) => a instanceof Query);
if (query) {
queries[propName] = query;
}
});
return this._merge(dm, inputs, outputs, host, queries, directiveType);
}
private _extractPublicName(def: string) { return splitAtColon(def, [null, def])[1].trim(); }
private _dedupeBindings(bindings: string[]): string[] {
const names = new Set<string>();
const reversedResult: string[] = [];
// go last to first to allow later entries to overwrite previous entries
for (let i = bindings.length - 1; i >= 0; i--) {
const binding = bindings[i];
const name = this._extractPublicName(binding);
if (!names.has(name)) {
names.add(name);
reversedResult.push(binding);
}
}
return reversedResult.reverse();
}
private _merge(
directive: Directive, inputs: string[], outputs: string[], host: {[key: string]: string},
queries: {[key: string]: any}, directiveType: Type<any>): Directive {
const mergedInputs: string[] = inputs;
if (directive.inputs) {
const inputNames: string[] =
directive.inputs.map((def: string): string => this._extractPublicName(def));
inputs.forEach((inputDef: string) => {
const publicName = this._extractPublicName(inputDef);
if (inputNames.indexOf(publicName) > -1) {
throw new Error(
`Input '${publicName}' defined multiple times in '${stringify(directiveType)}'`);
}
});
mergedInputs.unshift(...directive.inputs);
}
const mergedOutputs: string[] = outputs;
if (directive.outputs) {
const outputNames: string[] =
directive.outputs.map((def: string): string => this._extractPublicName(def));
outputs.forEach((outputDef: string) => {
const publicName = this._extractPublicName(outputDef);
if (outputNames.indexOf(publicName) > -1) {
throw new Error(
`Output event '${publicName}' defined multiple times in '${stringify(directiveType)}'`);
}
});
mergedOutputs.unshift(...directive.outputs);
}
const mergedInputs =
this._dedupeBindings(directive.inputs ? directive.inputs.concat(inputs) : inputs);
const mergedOutputs =
this._dedupeBindings(directive.outputs ? directive.outputs.concat(outputs) : outputs);
const mergedHost = directive.host ? StringMapWrapper.merge(directive.host, host) : host;
const mergedQueries =
directive.queries ? StringMapWrapper.merge(directive.queries, queries) : queries;

View File

@ -8,13 +8,13 @@
import {Injectable} from '@angular/core';
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata} from './compile_metadata';
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, identifierModuleUrl, identifierName} from './compile_metadata';
import {createCheckBindingField, createCheckBindingStmt} from './compiler_util/binding_util';
import {EventHandlerVars, convertActionBinding, convertPropertyBinding} from './compiler_util/expression_converter';
import {triggerAnimation, writeToRenderer} from './compiler_util/render_util';
import {CompilerConfig} from './config';
import {Parser} from './expression_parser/parser';
import {Identifiers, resolveIdentifier} from './identifiers';
import {Identifiers, createIdentifier} from './identifiers';
import {DEFAULT_INTERPOLATION_CONFIG} from './ml_parser/interpolation_config';
import {ClassBuilder, createClassStmt} from './output/class_builder';
import * as o from './output/output_ast';
@ -53,7 +53,9 @@ const RESET_CHANGES_STMT = o.THIS_EXPR.prop(CHANGES_FIELD_NAME).set(o.literalMap
*/
@Injectable()
export class DirectiveWrapperCompiler {
static dirWrapperClassName(id: CompileIdentifierMetadata) { return `Wrapper_${id.name}`; }
static dirWrapperClassName(id: CompileIdentifierMetadata) {
return `Wrapper_${identifierName(id)}`;
}
constructor(
private compilerConfig: CompilerConfig, private _exprParser: Parser,
@ -117,10 +119,10 @@ class DirectiveWrapperBuilder implements ClassBuilder {
[
new o.FnParam(
VIEW_VAR.name,
o.importType(resolveIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
o.importType(createIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
new o.FnParam(
COMPONENT_VIEW_VAR.name,
o.importType(resolveIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
o.importType(createIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
new o.FnParam(RENDER_EL_VAR.name, o.DYNAMIC_TYPE),
],
this.detachStmts),
@ -172,7 +174,7 @@ function addNgDoCheckMethod(builder: DirectiveWrapperBuilder) {
}
if (builder.compilerConfig.logBindingUpdate) {
onChangesStmts.push(
o.importExpr(resolveIdentifier(Identifiers.setBindingDebugInfoForChanges))
o.importExpr(createIdentifier(Identifiers.setBindingDebugInfoForChanges))
.callFn(
[VIEW_VAR.prop('renderer'), RENDER_EL_VAR, o.THIS_EXPR.prop(CHANGES_FIELD_NAME)])
.toStmt());
@ -198,7 +200,7 @@ function addNgDoCheckMethod(builder: DirectiveWrapperBuilder) {
'ngDoCheck',
[
new o.FnParam(
VIEW_VAR.name, o.importType(resolveIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
VIEW_VAR.name, o.importType(createIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
new o.FnParam(RENDER_EL_VAR.name, o.DYNAMIC_TYPE),
new o.FnParam(THROW_ON_CHANGE_VAR.name, o.BOOL_TYPE),
],
@ -214,7 +216,7 @@ function addCheckInputMethod(input: string, builder: DirectiveWrapperBuilder) {
if (builder.genChanges) {
onChangeStatements.push(o.THIS_EXPR.prop(CHANGES_FIELD_NAME)
.key(o.literal(input))
.set(o.importExpr(resolveIdentifier(Identifiers.SimpleChange))
.set(o.importExpr(createIdentifier(Identifiers.SimpleChange))
.instantiate([field.expression, CURR_VALUE_VAR]))
.toStmt());
}
@ -237,10 +239,10 @@ function addCheckHostMethod(
const stmts: o.Statement[] = [];
const methodParams: o.FnParam[] = [
new o.FnParam(
VIEW_VAR.name, o.importType(resolveIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
VIEW_VAR.name, o.importType(createIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
new o.FnParam(
COMPONENT_VIEW_VAR.name,
o.importType(resolveIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
o.importType(createIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
new o.FnParam(RENDER_EL_VAR.name, o.DYNAMIC_TYPE),
new o.FnParam(THROW_ON_CHANGE_VAR.name, o.BOOL_TYPE),
];
@ -255,14 +257,14 @@ function addCheckHostMethod(
if (hostProp.needsRuntimeSecurityContext) {
securityContextExpr = o.variable(`secCtx_${methodParams.length}`);
methodParams.push(new o.FnParam(
securityContextExpr.name, o.importType(resolveIdentifier(Identifiers.SecurityContext))));
securityContextExpr.name, o.importType(createIdentifier(Identifiers.SecurityContext))));
}
let checkBindingStmts: o.Statement[];
if (hostProp.isAnimation) {
const {updateStmts, detachStmts} = triggerAnimation(
VIEW_VAR, COMPONENT_VIEW_VAR, hostProp,
o.THIS_EXPR.prop(EVENT_HANDLER_FIELD_NAME)
.or(o.importExpr(resolveIdentifier(Identifiers.noop))),
.or(o.importExpr(createIdentifier(Identifiers.noop))),
RENDER_EL_VAR, evalResult.currValExpr, field.expression);
checkBindingStmts = updateStmts;
builder.detachStmts.push(...detachStmts);
@ -306,7 +308,7 @@ function addHandleEventMethod(hostListeners: BoundEventAst[], builder: Directive
function addSubscribeMethod(dirMeta: CompileDirectiveMetadata, builder: DirectiveWrapperBuilder) {
const methodParams: o.FnParam[] = [
new o.FnParam(
VIEW_VAR.name, o.importType(resolveIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
VIEW_VAR.name, o.importType(createIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
new o.FnParam(EVENT_HANDLER_FIELD_NAME, o.DYNAMIC_TYPE)
];
const stmts: o.Statement[] = [
@ -348,9 +350,10 @@ function parseHostBindings(
const errors: ParseError[] = [];
const parser =
new BindingParser(exprParser, DEFAULT_INTERPOLATION_CONFIG, schemaRegistry, [], errors);
const sourceFileName = dirMeta.type.moduleUrl ?
`in Directive ${dirMeta.type.name} in ${dirMeta.type.moduleUrl}` :
`in Directive ${dirMeta.type.name}`;
const moduleUrl = identifierModuleUrl(dirMeta.type);
const sourceFileName = moduleUrl ?
`in Directive ${identifierName(dirMeta.type)} in ${moduleUrl}` :
`in Directive ${identifierName(dirMeta.type)}`;
const sourceFile = new ParseSourceFile('', sourceFileName);
const sourceSpan = new ParseSourceSpan(
new ParseLocation(sourceFile, null, null, null),

View File

@ -9,7 +9,7 @@
import {ANALYZE_FOR_ENTRY_COMPONENTS, AnimationTransitionEvent, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ComponentRef, ElementRef, Injector, LOCALE_ID, NgModuleFactory, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TRANSLATIONS_FORMAT, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
import {StaticSymbol, isStaticSymbol} from './aot/static_symbol';
import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadata';
import {CompileIdentifierMetadata, CompileTokenMetadata, identifierModuleUrl, identifierName} from './compile_metadata';
import {AnimationGroupPlayer, AnimationKeyframe, AnimationSequencePlayer, AnimationStyles, AnimationTransition, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, ComponentRef_, DebugAppView, DebugContext, NgModuleInjector, NoOpAnimationPlayer, StaticNodeDebugInfo, TemplateRef_, UNINITIALIZED, ValueUnwrapper, ViewContainer, ViewType, balanceAnimationKeyframes, clearStyles, collectAndResolveStyles, devModeEqual, prepareFinalAnimationStyles, reflector, registerModuleFactory, renderStyles, view_utils} from './private_import_core';
const APP_VIEW_MODULE_URL = assetUrl('core', 'linker/view');
@ -347,27 +347,25 @@ export function assetUrl(pkg: string, path: string = null, type: string = 'src')
}
export function resolveIdentifier(identifier: IdentifierSpec) {
let moduleUrl = identifier.moduleUrl;
return reflector.resolveIdentifier(identifier.name, identifier.moduleUrl, identifier.runtime);
}
export function createIdentifier(identifier: IdentifierSpec): CompileIdentifierMetadata {
const reference =
reflector.resolveIdentifier(identifier.name, identifier.moduleUrl, identifier.runtime);
if (isStaticSymbol(reference)) {
moduleUrl = reference.filePath;
}
return new CompileIdentifierMetadata(
{name: identifier.name, moduleUrl: moduleUrl, reference: reference});
return {reference: reference};
}
export function identifierToken(identifier: CompileIdentifierMetadata): CompileTokenMetadata {
return new CompileTokenMetadata({identifier: identifier});
return {identifier: identifier};
}
export function resolveIdentifierToken(identifier: IdentifierSpec): CompileTokenMetadata {
return identifierToken(resolveIdentifier(identifier));
export function createIdentifierToken(identifier: IdentifierSpec): CompileTokenMetadata {
return identifierToken(createIdentifier(identifier));
}
export function resolveEnumIdentifier(
enumType: CompileIdentifierMetadata, name: string): CompileIdentifierMetadata {
const resolvedEnum = reflector.resolveEnum(enumType.reference, name);
return new CompileIdentifierMetadata(
{name: `${enumType.name}.${name}`, moduleUrl: enumType.moduleUrl, reference: resolvedEnum});
export function createEnumIdentifier(
enumType: IdentifierSpec, name: string): CompileIdentifierMetadata {
const resolvedEnum = reflector.resolveEnum(resolveIdentifier(enumType), name);
return {reference: resolvedEnum};
}

View File

@ -10,7 +10,7 @@ import {Compiler, ComponentFactory, Injectable, Injector, ModuleWithComponentFac
import {AnimationCompiler} from '../animation/animation_compiler';
import {AnimationParser} from '../animation/animation_parser';
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeMetadata, ProviderMeta, createHostComponentMeta} from '../compile_metadata';
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeMetadata, ProviderMeta, createHostComponentMeta, identifierName} from '../compile_metadata';
import {CompilerConfig} from '../config';
import {DirectiveNormalizer} from '../directive_normalizer';
import {DirectiveWrapperCompiler} from '../directive_wrapper_compiler';
@ -126,14 +126,13 @@ export class JitCompiler implements Compiler {
compileResult.dependencies.forEach((dep) => {
dep.placeholder.reference =
this._assertComponentKnown(dep.comp.reference, true).proxyComponentFactory;
dep.placeholder.name = `compFactory_${dep.comp.name}`;
});
if (!this._compilerConfig.useJit) {
ngModuleFactory =
interpretStatements(compileResult.statements, compileResult.ngModuleFactoryVar);
} else {
ngModuleFactory = jitStatements(
`/${moduleMeta.type.name}/module.ngfactory.js`, compileResult.statements,
`/${identifierName(moduleMeta.type)}/module.ngfactory.js`, compileResult.statements,
compileResult.ngModuleFactoryVar);
}
this._compiledNgModuleCache.set(moduleMeta.type.reference, ngModuleFactory);
@ -215,7 +214,12 @@ export class JitCompiler implements Compiler {
if (!compiledTemplate) {
const compMeta = this._metadataResolver.getDirectiveMetadata(compType);
assertComponent(compMeta);
const hostMeta = createHostComponentMeta(compMeta);
class HostClass {
static overriddenName = `${identifierName(compMeta.type)}_Host`;
}
const hostMeta = createHostComponentMeta(HostClass, compMeta);
compiledTemplate = new CompiledTemplate(
true, compMeta.selector, compMeta.type, hostMeta, ngModule, [compMeta.type]);
this._compiledHostTemplateCache.set(compType, compiledTemplate);
@ -264,8 +268,8 @@ export class JitCompiler implements Compiler {
directiveWrapperClass = interpretStatements(statements, compileResult.dirWrapperClassVar);
} else {
directiveWrapperClass = jitStatements(
`/${moduleMeta.type.name}/${dirMeta.type.name}/wrapper.ngfactory.js`, statements,
compileResult.dirWrapperClassVar);
`/${identifierName(moduleMeta.type)}/${identifierName(dirMeta.type)}/wrapper.ngfactory.js`,
statements, compileResult.dirWrapperClassVar);
}
this._compiledDirectiveWrapperCache.set(dirMeta.type.reference, directiveWrapperClass);
}
@ -288,9 +292,9 @@ export class JitCompiler implements Compiler {
pipe => this._metadataResolver.getPipeSummary(pipe.reference));
const parsedTemplate = this._templateParser.parse(
compMeta, compMeta.template.template, directives, pipes, template.ngModule.schemas,
compMeta.type.name);
identifierName(compMeta.type));
const compiledAnimations =
this._animationCompiler.compile(compMeta.type.name, parsedAnimations);
this._animationCompiler.compile(identifierName(compMeta.type), parsedAnimations);
const compileResult = this._viewCompiler.compileComponent(
compMeta, parsedTemplate, ir.variable(stylesCompileResult.componentStylesheet.stylesVar),
pipes, compiledAnimations);
@ -300,12 +304,10 @@ export class JitCompiler implements Compiler {
const vfd = <ViewClassDependency>dep;
depTemplate = this._assertComponentKnown(vfd.comp.reference, false);
vfd.placeholder.reference = depTemplate.proxyViewClass;
vfd.placeholder.name = `View_${vfd.comp.name}`;
} else if (dep instanceof ComponentFactoryDependency) {
const cfd = <ComponentFactoryDependency>dep;
depTemplate = this._assertComponentKnown(cfd.comp.reference, true);
cfd.placeholder.reference = depTemplate.proxyComponentFactory;
cfd.placeholder.name = `compFactory_${cfd.comp.name}`;
} else if (dep instanceof DirectiveWrapperDependency) {
const dwd = <DirectiveWrapperDependency>dep;
dwd.placeholder.reference = this._assertDirectiveWrapper(dwd.dir.reference);
@ -319,7 +321,7 @@ export class JitCompiler implements Compiler {
viewClass = interpretStatements(statements, compileResult.viewClassVar);
} else {
viewClass = jitStatements(
`/${template.ngModule.type.name}/${template.compType.name}/${template.isHost?'host':'component'}.ngfactory.js`,
`/${identifierName(template.ngModule.type)}/${identifierName(template.compType)}/${template.isHost?'host':'component'}.ngfactory.js`,
statements, compileResult.viewClassVar);
}
template.compiled(viewClass);
@ -332,7 +334,6 @@ export class JitCompiler implements Compiler {
const nestedStylesArr = this._resolveAndEvalStylesCompileResult(
nestedCompileResult, externalStylesheetsByModuleUrl);
dep.valuePlaceholder.reference = nestedStylesArr;
dep.valuePlaceholder.name = `importedStyles${i}`;
});
}
@ -380,7 +381,8 @@ class CompiledTemplate {
function assertComponent(meta: CompileDirectiveMetadata) {
if (!meta.isComponent) {
throw new Error(`Could not compile '${meta.type.name}' because it is not a component.`);
throw new Error(
`Could not compile '${identifierName(meta.type)}' because it is not a component.`);
}
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AnimationAnimateMetadata, AnimationEntryMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationStateDeclarationMetadata, AnimationStateMetadata, AnimationStateTransitionMetadata, AnimationStyleMetadata, AnimationWithStepsMetadata, Attribute, ChangeDetectionStrategy, Component, Host, Inject, Injectable, ModuleWithProviders, Optional, Provider, Query, SchemaMetadata, Self, SkipSelf, Type, resolveForwardRef} from '@angular/core';
import {AnimationAnimateMetadata, AnimationEntryMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationStateDeclarationMetadata, AnimationStateMetadata, AnimationStateTransitionMetadata, AnimationStyleMetadata, AnimationWithStepsMetadata, Attribute, ChangeDetectionStrategy, Component, Directive, Host, Inject, Injectable, ModuleWithProviders, Optional, Provider, Query, SchemaMetadata, Self, SkipSelf, Type, resolveForwardRef} from '@angular/core';
import {isStaticSymbol} from './aot/static_symbol';
import {assertArrayOfStrings, assertInterpolationSymbols} from './assertions';
@ -15,14 +15,14 @@ import {DirectiveNormalizer} from './directive_normalizer';
import {DirectiveResolver} from './directive_resolver';
import {ListWrapper, StringMapWrapper} from './facade/collection';
import {isBlank, isPresent, stringify} from './facade/lang';
import {Identifiers, resolveIdentifierToken} from './identifiers';
import {Identifiers, createIdentifierToken, resolveIdentifier} from './identifiers';
import {hasLifecycleHook} from './lifecycle_reflector';
import {NgModuleResolver} from './ng_module_resolver';
import {PipeResolver} from './pipe_resolver';
import {ComponentStillLoadingError, LIFECYCLE_HOOKS_VALUES, ReflectorReader, reflector} from './private_import_core';
import {ElementSchemaRegistry} from './schema/element_schema_registry';
import {getUrlScheme} from './url_resolver';
import {MODULE_SUFFIX, SyncAsyncResult, ValueTransformer, sanitizeIdentifier, visitValue} from './util';
import {MODULE_SUFFIX, SyncAsyncResult, ValueTransformer, visitValue} from './util';
@ -41,8 +41,6 @@ export class CompileMetadataResolver {
private _pipeSummaryCache = new Map<Type<any>, cpl.CompilePipeSummary>();
private _ngModuleCache = new Map<Type<any>, cpl.CompileNgModuleMetadata>();
private _ngModuleOfTypes = new Map<Type<any>, Type<any>>();
private _anonymousTypes = new Map<Object, number>();
private _anonymousTypeIndex = 0;
constructor(
private _ngModuleResolver: NgModuleResolver, private _directiveResolver: DirectiveResolver,
@ -50,20 +48,6 @@ export class CompileMetadataResolver {
private _directiveNormalizer: DirectiveNormalizer,
private _reflector: ReflectorReader = reflector) {}
private sanitizeTokenName(token: any): string {
let identifier = stringify(token);
if (identifier.indexOf('(') >= 0) {
// case: anonymous functions!
let found = this._anonymousTypes.get(token);
if (!found) {
this._anonymousTypes.set(token, this._anonymousTypeIndex++);
found = this._anonymousTypes.get(token);
}
identifier = `anonymous_token_${found}_`;
}
return sanitizeIdentifier(identifier);
}
clearCacheFor(type: Type<any>) {
const dirMeta = this._directiveCache.get(type);
this._directiveCache.delete(type);
@ -142,30 +126,30 @@ export class CompileMetadataResolver {
return null;
}
private _loadDirectiveMetadata(directiveType: any, isSync: boolean): Promise<any> {
private _loadDirectiveMetadata(directiveType: any, isSync: boolean): () => Promise<any> {
if (this._directiveCache.has(directiveType)) {
return;
}
directiveType = resolveForwardRef(directiveType);
const nonNormalizedMetadata = this.getNonNormalizedDirectiveMetadata(directiveType);
const {annotation, metadata} = this.getNonNormalizedDirectiveMetadata(directiveType);
const createDirectiveMetadata = (templateMetadata: cpl.CompileTemplateMetadata) => {
const normalizedDirMeta = new cpl.CompileDirectiveMetadata({
type: nonNormalizedMetadata.type,
isComponent: nonNormalizedMetadata.isComponent,
selector: nonNormalizedMetadata.selector,
exportAs: nonNormalizedMetadata.exportAs,
changeDetection: nonNormalizedMetadata.changeDetection,
inputs: nonNormalizedMetadata.inputs,
outputs: nonNormalizedMetadata.outputs,
hostListeners: nonNormalizedMetadata.hostListeners,
hostProperties: nonNormalizedMetadata.hostProperties,
hostAttributes: nonNormalizedMetadata.hostAttributes,
providers: nonNormalizedMetadata.providers,
viewProviders: nonNormalizedMetadata.viewProviders,
queries: nonNormalizedMetadata.queries,
viewQueries: nonNormalizedMetadata.viewQueries,
entryComponents: nonNormalizedMetadata.entryComponents,
type: metadata.type,
isComponent: metadata.isComponent,
selector: metadata.selector,
exportAs: metadata.exportAs,
changeDetection: metadata.changeDetection,
inputs: metadata.inputs,
outputs: metadata.outputs,
hostListeners: metadata.hostListeners,
hostProperties: metadata.hostProperties,
hostAttributes: metadata.hostAttributes,
providers: metadata.providers,
viewProviders: metadata.viewProviders,
queries: metadata.queries,
viewQueries: metadata.viewQueries,
entryComponents: metadata.entryComponents,
template: templateMetadata
});
this._directiveCache.set(directiveType, normalizedDirMeta);
@ -173,17 +157,17 @@ export class CompileMetadataResolver {
return normalizedDirMeta;
};
if (nonNormalizedMetadata.isComponent) {
if (metadata.isComponent) {
const templateMeta = this._directiveNormalizer.normalizeTemplate({
componentType: directiveType,
moduleUrl: nonNormalizedMetadata.type.moduleUrl,
encapsulation: nonNormalizedMetadata.template.encapsulation,
template: nonNormalizedMetadata.template.template,
templateUrl: nonNormalizedMetadata.template.templateUrl,
styles: nonNormalizedMetadata.template.styles,
styleUrls: nonNormalizedMetadata.template.styleUrls,
animations: nonNormalizedMetadata.template.animations,
interpolation: nonNormalizedMetadata.template.interpolation
moduleUrl: componentModuleUrl(this._reflector, directiveType, annotation),
encapsulation: metadata.template.encapsulation,
template: metadata.template.template,
templateUrl: metadata.template.templateUrl,
styles: metadata.template.styles,
styleUrls: metadata.template.styleUrls,
animations: metadata.template.animations,
interpolation: metadata.template.interpolation
});
if (templateMeta.syncResult) {
createDirectiveMetadata(templateMeta.syncResult);
@ -192,7 +176,7 @@ export class CompileMetadataResolver {
if (isSync) {
throw new ComponentStillLoadingError(directiveType);
}
return templateMeta.asyncResult.then(createDirectiveMetadata);
return () => templateMeta.asyncResult.then(createDirectiveMetadata);
}
} else {
// directive
@ -201,18 +185,17 @@ export class CompileMetadataResolver {
}
}
getNonNormalizedDirectiveMetadata(directiveType: any): cpl.CompileDirectiveMetadata {
getNonNormalizedDirectiveMetadata(directiveType: any):
{annotation: Directive, metadata: cpl.CompileDirectiveMetadata} {
directiveType = resolveForwardRef(directiveType);
const dirMeta = this._directiveResolver.resolve(directiveType);
if (!dirMeta) {
return null;
}
let moduleUrl = staticTypeModuleUrl(directiveType);
let nonNormalizedTemplateMetadata: cpl.CompileTemplateMetadata;
if (dirMeta instanceof Component) {
// component
moduleUrl = componentModuleUrl(this._reflector, directiveType, dirMeta);
assertArrayOfStrings('styles', dirMeta.styles);
assertArrayOfStrings('styleUrls', dirMeta.styleUrls);
assertInterpolationSymbols('interpolation', dirMeta.interpolation);
@ -233,7 +216,7 @@ export class CompileMetadataResolver {
}
let changeDetectionStrategy: ChangeDetectionStrategy = null;
let viewProviders: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = [];
let viewProviders: cpl.CompileProviderMetadata[] = [];
let entryComponentMetadata: cpl.CompileIdentifierMetadata[] = [];
let selector = dirMeta.selector;
@ -246,10 +229,9 @@ export class CompileMetadataResolver {
`viewProviders for "${stringify(directiveType)}"`);
}
if (dirMeta.entryComponents) {
entryComponentMetadata =
flattenAndDedupeArray(dirMeta.entryComponents)
.map((type) => this._getIdentifierMetadata(type, staticTypeModuleUrl(type)))
.concat(entryComponentMetadata);
entryComponentMetadata = flattenAndDedupeArray(dirMeta.entryComponents)
.map((type) => this._getIdentifierMetadata(type))
.concat(entryComponentMetadata);
}
if (!selector) {
selector = this._schemaRegistry.getDefaultComponentElementName();
@ -261,7 +243,7 @@ export class CompileMetadataResolver {
}
}
let providers: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = [];
let providers: cpl.CompileProviderMetadata[] = [];
if (isPresent(dirMeta.providers)) {
providers = this._getProvidersMetadata(
dirMeta.providers, entryComponentMetadata, `providers for "${stringify(directiveType)}"`);
@ -273,11 +255,11 @@ export class CompileMetadataResolver {
viewQueries = this._getQueriesMetadata(dirMeta.queries, true, directiveType);
}
return cpl.CompileDirectiveMetadata.create({
const metadata = cpl.CompileDirectiveMetadata.create({
selector: selector,
exportAs: dirMeta.exportAs,
isComponent: !!nonNormalizedTemplateMetadata,
type: this._getTypeMetadata(directiveType, moduleUrl),
type: this._getTypeMetadata(directiveType),
template: nonNormalizedTemplateMetadata,
changeDetection: changeDetectionStrategy,
inputs: dirMeta.inputs,
@ -289,6 +271,7 @@ export class CompileMetadataResolver {
viewQueries: viewQueries,
entryComponents: entryComponentMetadata
});
return {metadata, annotation: dirMeta};
}
/**
@ -420,8 +403,7 @@ export class CompileMetadataResolver {
if (exportedModuleSummary) {
exportedModules.push(exportedModuleSummary);
} else {
exportedNonModuleIdentifiers.push(
this._getIdentifierMetadata(exportedType, staticTypeModuleUrl(exportedType)));
exportedNonModuleIdentifiers.push(this._getIdentifierMetadata(exportedType));
}
});
}
@ -435,15 +417,16 @@ export class CompileMetadataResolver {
throw new Error(
`Unexpected value '${stringify(declaredType)}' declared by the module '${stringify(moduleType)}'`);
}
const declaredIdentifier =
this._getIdentifierMetadata(declaredType, staticTypeModuleUrl(declaredType));
const declaredIdentifier = this._getIdentifierMetadata(declaredType);
if (this._directiveResolver.isDirective(declaredType)) {
transitiveModule.directivesSet.add(declaredType);
transitiveModule.directives.push(declaredIdentifier);
declaredDirectives.push(declaredIdentifier);
this._addTypeToModule(declaredType, moduleType);
transitiveModule.directiveLoaders.push(
() => this._loadDirectiveMetadata(declaredType, isSync));
const loader = this._loadDirectiveMetadata(declaredType, isSync);
if (loader) {
transitiveModule.directiveLoaders.push(loader);
}
} else if (this._pipeResolver.isPipe(declaredType)) {
transitiveModule.pipesSet.add(declaredType);
transitiveModule.pipes.push(declaredIdentifier);
@ -479,8 +462,7 @@ export class CompileMetadataResolver {
if (meta.entryComponents) {
entryComponents.push(
...flattenAndDedupeArray(meta.entryComponents)
.map(type => this._getTypeMetadata(type, staticTypeModuleUrl(type))));
...flattenAndDedupeArray(meta.entryComponents).map(type => this._getTypeMetadata(type)));
}
if (meta.bootstrap) {
@ -489,7 +471,7 @@ export class CompileMetadataResolver {
throw new Error(
`Unexpected value '${stringify(type)}' used in the bootstrap property of module '${stringify(moduleType)}'`);
}
return this._getTypeMetadata(type, staticTypeModuleUrl(type));
return this._getTypeMetadata(type);
});
bootstrapComponents.push(...typeMetadata);
}
@ -504,7 +486,7 @@ export class CompileMetadataResolver {
transitiveModule.providers.push(...providers);
compileMeta = new cpl.CompileNgModuleMetadata({
type: this._getTypeMetadata(moduleType, staticTypeModuleUrl(moduleType)),
type: this._getTypeMetadata(moduleType),
providers,
entryComponents,
bootstrapComponents,
@ -575,35 +557,25 @@ export class CompileMetadataResolver {
transitiveModules, providers, entryComponents, directives, pipes, directiveLoaders);
}
private _getIdentifierMetadata(type: Type<any>, moduleUrl: string):
cpl.CompileIdentifierMetadata {
private _getIdentifierMetadata(type: Type<any>): cpl.CompileIdentifierMetadata {
type = resolveForwardRef(type);
return new cpl.CompileIdentifierMetadata(
{name: this.sanitizeTokenName(type), moduleUrl, reference: type});
return {reference: type};
}
private _getTypeMetadata(type: Type<any>, moduleUrl: string, dependencies: any[] = null):
cpl.CompileTypeMetadata {
const identifier = this._getIdentifierMetadata(type, moduleUrl);
return new cpl.CompileTypeMetadata({
name: identifier.name,
moduleUrl: identifier.moduleUrl,
private _getTypeMetadata(type: Type<any>, dependencies: any[] = null): cpl.CompileTypeMetadata {
const identifier = this._getIdentifierMetadata(type);
return {
reference: identifier.reference,
diDeps: this._getDependenciesMetadata(identifier.reference, dependencies),
lifecycleHooks:
LIFECYCLE_HOOKS_VALUES.filter(hook => hasLifecycleHook(hook, identifier.reference)),
});
};
}
private _getFactoryMetadata(factory: Function, moduleUrl: string, dependencies: any[] = null):
private _getFactoryMetadata(factory: Function, dependencies: any[] = null):
cpl.CompileFactoryMetadata {
factory = resolveForwardRef(factory);
return new cpl.CompileFactoryMetadata({
name: this.sanitizeTokenName(factory),
moduleUrl,
reference: factory,
diDeps: this._getDependenciesMetadata(factory, dependencies)
});
return {reference: factory, diDeps: this._getDependenciesMetadata(factory, dependencies)};
}
/**
@ -641,7 +613,7 @@ export class CompileMetadataResolver {
const pipeAnnotation = this._pipeResolver.resolve(pipeType);
const pipeMeta = new cpl.CompilePipeMetadata({
type: this._getTypeMetadata(pipeType, staticTypeModuleUrl(pipeType)),
type: this._getTypeMetadata(pipeType),
name: pipeAnnotation.name,
pure: pipeAnnotation.pure
});
@ -689,14 +661,14 @@ export class CompileMetadataResolver {
return null;
}
return new cpl.CompileDiDependencyMetadata({
return {
isAttribute,
isHost,
isSelf,
isSkipSelf,
isOptional,
token: this._getTokenMetadata(token)
});
};
});
@ -714,62 +686,50 @@ export class CompileMetadataResolver {
token = resolveForwardRef(token);
let compileToken: cpl.CompileTokenMetadata;
if (typeof token === 'string') {
compileToken = new cpl.CompileTokenMetadata({value: token});
compileToken = {value: token};
} else {
compileToken = new cpl.CompileTokenMetadata({
identifier: new cpl.CompileIdentifierMetadata({
reference: token,
name: this.sanitizeTokenName(token),
moduleUrl: staticTypeModuleUrl(token)
})
});
compileToken = {identifier: {reference: token}};
}
return compileToken;
}
private _getProvidersMetadata(
providers: Provider[], targetEntryComponents: cpl.CompileIdentifierMetadata[],
debugInfo?: string): Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> {
const compileProviders: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = [];
debugInfo?: string,
compileProviders: cpl.CompileProviderMetadata[] = []): cpl.CompileProviderMetadata[] {
providers.forEach((provider: any, providerIdx: number) => {
provider = resolveForwardRef(provider);
if (provider && typeof provider == 'object' && provider.hasOwnProperty('provide')) {
provider = new cpl.ProviderMeta(provider.provide, provider);
}
let compileProvider: cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[];
if (Array.isArray(provider)) {
compileProvider = this._getProvidersMetadata(provider, targetEntryComponents, debugInfo);
} else if (provider instanceof cpl.ProviderMeta) {
const tokenMeta = this._getTokenMetadata(provider.token);
if (tokenMeta.reference ===
resolveIdentifierToken(Identifiers.ANALYZE_FOR_ENTRY_COMPONENTS).reference) {
targetEntryComponents.push(...this._getEntryComponentsFromProvider(provider));
} else {
compileProvider = this.getProviderMetadata(provider);
}
} else if (isValidType(provider)) {
compileProvider = this._getTypeMetadata(provider, staticTypeModuleUrl(provider));
this._getProvidersMetadata(provider, targetEntryComponents, debugInfo, compileProviders);
} else {
const providersInfo =
(<string[]>providers.reduce(
(soFar: string[], seenProvider: any, seenProviderIdx: number) => {
if (seenProviderIdx < providerIdx) {
soFar.push(`${stringify(seenProvider)}`);
} else if (seenProviderIdx == providerIdx) {
soFar.push(`?${stringify(seenProvider)}?`);
} else if (seenProviderIdx == providerIdx + 1) {
soFar.push('...');
}
return soFar;
},
[]))
.join(', ');
throw new Error(
`Invalid ${debugInfo ? debugInfo : 'provider'} - only instances of Provider and Type are allowed, got: [${providersInfo}]`);
}
if (compileProvider) {
compileProviders.push(compileProvider);
provider = resolveForwardRef(provider);
let providerMeta: cpl.ProviderMeta;
if (provider && typeof provider == 'object' && provider.hasOwnProperty('provide')) {
providerMeta = new cpl.ProviderMeta(provider.provide, provider);
} else if (isValidType(provider)) {
providerMeta = new cpl.ProviderMeta(provider, {useClass: provider});
} else {
const providersInfo =
(<string[]>providers.reduce(
(soFar: string[], seenProvider: any, seenProviderIdx: number) => {
if (seenProviderIdx < providerIdx) {
soFar.push(`${stringify(seenProvider)}`);
} else if (seenProviderIdx == providerIdx) {
soFar.push(`?${stringify(seenProvider)}?`);
} else if (seenProviderIdx == providerIdx + 1) {
soFar.push('...');
}
return soFar;
},
[]))
.join(', ');
throw new Error(
`Invalid ${debugInfo ? debugInfo : 'provider'} - only instances of Provider and Type are allowed, got: [${providersInfo}]`);
}
if (providerMeta.token === resolveIdentifier(Identifiers.ANALYZE_FOR_ENTRY_COMPONENTS)) {
targetEntryComponents.push(...this._getEntryComponentsFromProvider(providerMeta));
} else {
compileProviders.push(this.getProviderMetadata(providerMeta));
}
}
});
return compileProviders;
@ -788,7 +748,7 @@ export class CompileMetadataResolver {
throw new Error(`The ANALYZE_FOR_ENTRY_COMPONENTS token only supports 'multi = true'!`);
}
convertToCompileValue(provider.useValue, collectedIdentifiers);
extractIdentifiers(provider.useValue, collectedIdentifiers);
collectedIdentifiers.forEach((identifier) => {
if (this._directiveResolver.isDirective(identifier.reference)) {
components.push(identifier);
@ -801,26 +761,29 @@ export class CompileMetadataResolver {
let compileDeps: cpl.CompileDiDependencyMetadata[];
let compileTypeMetadata: cpl.CompileTypeMetadata = null;
let compileFactoryMetadata: cpl.CompileFactoryMetadata = null;
let token: cpl.CompileTokenMetadata = this._getTokenMetadata(provider.token);
if (provider.useClass) {
compileTypeMetadata = this._getTypeMetadata(
provider.useClass, staticTypeModuleUrl(provider.useClass), provider.dependencies);
compileTypeMetadata = this._getTypeMetadata(provider.useClass, provider.dependencies);
compileDeps = compileTypeMetadata.diDeps;
if (provider.token === provider.useClass) {
// use the compileTypeMetadata as it contains information about lifecycleHooks...
token = {identifier: compileTypeMetadata};
}
} else if (provider.useFactory) {
compileFactoryMetadata = this._getFactoryMetadata(
provider.useFactory, staticTypeModuleUrl(provider.useFactory), provider.dependencies);
compileFactoryMetadata = this._getFactoryMetadata(provider.useFactory, provider.dependencies);
compileDeps = compileFactoryMetadata.diDeps;
}
return new cpl.CompileProviderMetadata({
token: this._getTokenMetadata(provider.token),
return {
token: token,
useClass: compileTypeMetadata,
useValue: convertToCompileValue(provider.useValue, []),
useValue: provider.useValue,
useFactory: compileFactoryMetadata,
useExisting: provider.useExisting ? this._getTokenMetadata(provider.useExisting) : null,
deps: compileDeps,
multi: provider.multi
});
};
}
private _getQueriesMetadata(
@ -854,12 +817,12 @@ export class CompileMetadataResolver {
selectors = [this._getTokenMetadata(q.selector)];
}
return new cpl.CompileQueryMetadata({
return {
selectors,
first: q.first,
descendants: q.descendants, propertyName,
read: q.read ? this._getTokenMetadata(q.read) : null
});
};
}
}
@ -925,14 +888,10 @@ function isValidType(value: any): boolean {
return isStaticSymbol(value) || (value instanceof Type);
}
function staticTypeModuleUrl(value: any): string {
return isStaticSymbol(value) ? value.filePath : null;
}
function componentModuleUrl(
export function componentModuleUrl(
reflector: ReflectorReader, type: Type<any>, cmpMetadata: Component): string {
if (isStaticSymbol(type)) {
return staticTypeModuleUrl(type);
return type.filePath;
}
const moduleId = cmpMetadata.moduleId;
@ -949,21 +908,12 @@ function componentModuleUrl(
return reflector.importUri(type);
}
function convertToCompileValue(
value: any, targetIdentifiers: cpl.CompileIdentifierMetadata[]): any {
return visitValue(value, new _CompileValueConverter(), targetIdentifiers);
function extractIdentifiers(value: any, targetIdentifiers: cpl.CompileIdentifierMetadata[]) {
visitValue(value, new _CompileValueConverter(), targetIdentifiers);
}
class _CompileValueConverter extends ValueTransformer {
visitOther(value: any, targetIdentifiers: cpl.CompileIdentifierMetadata[]): any {
let identifier: cpl.CompileIdentifierMetadata;
if (isStaticSymbol(value)) {
identifier = new cpl.CompileIdentifierMetadata(
{name: value.name, moduleUrl: value.filePath, reference: value});
} else {
identifier = new cpl.CompileIdentifierMetadata({reference: value});
}
targetIdentifiers.push(identifier);
return identifier;
targetIdentifiers.push({reference: value});
}
}

View File

@ -8,10 +8,10 @@
import {Injectable} from '@angular/core';
import {CompileDiDependencyMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileProviderMetadata, CompileTokenMetadata} from './compile_metadata';
import {CompileDiDependencyMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileProviderMetadata, CompileTokenMetadata, identifierModuleUrl, identifierName, tokenName, tokenReference} from './compile_metadata';
import {createDiTokenExpression} from './compiler_util/identifier_util';
import {isPresent} from './facade/lang';
import {Identifiers, resolveIdentifier, resolveIdentifierToken} from './identifiers';
import {Identifiers, createIdentifier, createIdentifierToken, resolveIdentifier} from './identifiers';
import {ClassBuilder, createClassStmt} from './output/class_builder';
import * as o from './output/output_ast';
import {convertValueToOutputAst} from './output/value_util';
@ -35,9 +35,10 @@ export class NgModuleCompileResult {
export class NgModuleCompiler {
compile(ngModuleMeta: CompileNgModuleMetadata, extraProviders: CompileProviderMetadata[]):
NgModuleCompileResult {
const sourceFileName = isPresent(ngModuleMeta.type.moduleUrl) ?
`in NgModule ${ngModuleMeta.type.name} in ${ngModuleMeta.type.moduleUrl}` :
`in NgModule ${ngModuleMeta.type.name}`;
const moduleUrl = identifierModuleUrl(ngModuleMeta.type);
const sourceFileName = isPresent(moduleUrl) ?
`in NgModule ${identifierName(ngModuleMeta.type)} in ${moduleUrl}` :
`in NgModule ${identifierName(ngModuleMeta.type)}`;
const sourceFile = new ParseSourceFile('', sourceFileName);
const sourceSpan = new ParseSourceSpan(
new ParseLocation(sourceFile, null, null, null),
@ -46,7 +47,7 @@ export class NgModuleCompiler {
const bootstrapComponentFactories: CompileIdentifierMetadata[] = [];
const entryComponentFactories =
ngModuleMeta.transitiveModule.entryComponents.map((entryComponent) => {
const id = new CompileIdentifierMetadata({name: entryComponent.name});
const id: CompileIdentifierMetadata = {reference: null};
if (ngModuleMeta.bootstrapComponents.indexOf(entryComponent) > -1) {
bootstrapComponentFactories.push(id);
}
@ -59,21 +60,21 @@ export class NgModuleCompiler {
const providerParser = new NgModuleProviderAnalyzer(ngModuleMeta, extraProviders, sourceSpan);
providerParser.parse().forEach((provider) => builder.addProvider(provider));
const injectorClass = builder.build();
const ngModuleFactoryVar = `${ngModuleMeta.type.name}NgFactory`;
const ngModuleFactoryVar = `${identifierName(ngModuleMeta.type)}NgFactory`;
const ngModuleFactoryStmt =
o.variable(ngModuleFactoryVar)
.set(o.importExpr(resolveIdentifier(Identifiers.NgModuleFactory))
.set(o.importExpr(createIdentifier(Identifiers.NgModuleFactory))
.instantiate(
[o.variable(injectorClass.name), o.importExpr(ngModuleMeta.type)],
o.importType(
resolveIdentifier(Identifiers.NgModuleFactory),
createIdentifier(Identifiers.NgModuleFactory),
[o.importType(ngModuleMeta.type)], [o.TypeModifier.Const])))
.toDeclStmt(null, [o.StmtModifier.Final]);
const stmts: o.Statement[] = [injectorClass, ngModuleFactoryStmt];
if (ngModuleMeta.id) {
const registerFactoryStmt =
o.importExpr(resolveIdentifier(Identifiers.RegisterModuleFactoryFn))
o.importExpr(createIdentifier(Identifiers.RegisterModuleFactoryFn))
.callFn([o.literal(ngModuleMeta.id), o.variable(ngModuleFactoryVar)])
.toStmt();
stmts.push(registerFactoryStmt);
@ -102,7 +103,7 @@ class _InjectorBuilder implements ClassBuilder {
addProvider(resolvedProvider: ProviderAst) {
const providerValueExpressions =
resolvedProvider.providers.map((provider) => this._getProviderValue(provider));
const propName = `_${resolvedProvider.token.name}_${this._instances.size}`;
const propName = `_${tokenName(resolvedProvider.token)}_${this._instances.size}`;
const instance = this._createProviderProperty(
propName, resolvedProvider, providerValueExpressions, resolvedProvider.multiProvider,
resolvedProvider.eager);
@ -110,12 +111,12 @@ class _InjectorBuilder implements ClassBuilder {
this._destroyStmts.push(instance.callMethod('ngOnDestroy', []).toStmt());
}
this._tokens.push(resolvedProvider.token);
this._instances.set(resolvedProvider.token.reference, instance);
this._instances.set(tokenReference(resolvedProvider.token), instance);
}
build(): o.ClassStmt {
const getMethodStmts: o.Statement[] = this._tokens.map((token) => {
const providerExpr = this._instances.get(token.reference);
const providerExpr = this._instances.get(tokenReference(token));
return new o.IfStmt(
InjectMethodVars.token.identical(createDiTokenExpression(token)),
[new o.ReturnStatement(providerExpr)]);
@ -143,13 +144,13 @@ class _InjectorBuilder implements ClassBuilder {
o.literalArr(this._bootstrapComponentFactories.map(
(componentFactory) => o.importExpr(componentFactory)))
];
const injClassName = `${this._ngModuleMeta.type.name}Injector`;
const injClassName = `${identifierName(this._ngModuleMeta.type)}Injector`;
return createClassStmt({
name: injClassName,
ctorParams: [new o.FnParam(
InjectorProps.parent.name, o.importType(resolveIdentifier(Identifiers.Injector)))],
InjectorProps.parent.name, o.importType(createIdentifier(Identifiers.Injector)))],
parent: o.importExpr(
resolveIdentifier(Identifiers.NgModuleInjector), [o.importType(this._ngModuleMeta.type)]),
createIdentifier(Identifiers.NgModuleInjector), [o.importType(this._ngModuleMeta.type)]),
parentArgs: parentArgs,
builders: [{methods}, this]
});
@ -158,7 +159,7 @@ class _InjectorBuilder implements ClassBuilder {
private _getProviderValue(provider: CompileProviderMetadata): o.Expression {
let result: o.Expression;
if (isPresent(provider.useExisting)) {
result = this._getDependency(new CompileDiDependencyMetadata({token: provider.useExisting}));
result = this._getDependency({token: provider.useExisting});
} else if (isPresent(provider.useFactory)) {
const deps = provider.deps || provider.useFactory.diDeps;
const depsExpr = deps.map((dep) => this._getDependency(dep));
@ -215,13 +216,12 @@ class _InjectorBuilder implements ClassBuilder {
}
if (!dep.isSkipSelf) {
if (dep.token &&
(dep.token.reference === resolveIdentifierToken(Identifiers.Injector).reference ||
dep.token.reference ===
resolveIdentifierToken(Identifiers.ComponentFactoryResolver).reference)) {
(tokenReference(dep.token) === resolveIdentifier(Identifiers.Injector) ||
tokenReference(dep.token) === resolveIdentifier(Identifiers.ComponentFactoryResolver))) {
result = o.THIS_EXPR;
}
if (!result) {
result = this._instances.get(dep.token.reference);
result = this._instances.get(tokenReference(dep.token));
}
}
if (!result) {

View File

@ -8,6 +8,7 @@
import {Injectable, NgModule, Type} from '@angular/core';
import {ListWrapper} from './facade/collection';
import {isPresent, stringify} from './facade/lang';
import {ReflectorReader, reflector} from './private_import_core';
@ -25,7 +26,8 @@ export class NgModuleResolver {
isNgModule(type: any) { return this._reflector.annotations(type).some(_isNgModuleMetadata); }
resolve(type: Type<any>, throwIfNotFound = true): NgModule {
const ngModuleMeta: NgModule = this._reflector.annotations(type).find(_isNgModuleMetadata);
const ngModuleMeta: NgModule =
ListWrapper.findLast(this._reflector.annotations(type), _isNgModuleMetadata);
if (isPresent(ngModuleMeta)) {
return ngModuleMeta;

View File

@ -7,6 +7,7 @@
*/
import {identifierModuleUrl, identifierName} from '../compile_metadata';
import {isBlank, isPresent} from '../facade/lang';
import {EmitterVisitorContext, OutputEmitter} from './abstract_emitter';
@ -38,18 +39,21 @@ class JsEmitterVisitor extends AbstractJsEmitterVisitor {
constructor(private _moduleUrl: string) { super(); }
visitExternalExpr(ast: o.ExternalExpr, ctx: EmitterVisitorContext): any {
if (isBlank(ast.value.name)) {
const name = identifierName(ast.value);
const moduleUrl = identifierModuleUrl(ast.value);
if (isBlank(name)) {
console.error('>>>', ast.value);
throw new Error(`Internal error: unknown identifier ${ast.value}`);
}
if (isPresent(ast.value.moduleUrl) && ast.value.moduleUrl != this._moduleUrl) {
let prefix = this.importsWithPrefixes.get(ast.value.moduleUrl);
if (isPresent(moduleUrl) && moduleUrl != this._moduleUrl) {
let prefix = this.importsWithPrefixes.get(moduleUrl);
if (isBlank(prefix)) {
prefix = `import${this.importsWithPrefixes.size}`;
this.importsWithPrefixes.set(ast.value.moduleUrl, prefix);
this.importsWithPrefixes.set(moduleUrl, prefix);
}
ctx.print(`${prefix}.`);
}
ctx.print(ast.value.name);
ctx.print(name);
return null;
}
visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: EmitterVisitorContext): any {

View File

@ -43,14 +43,14 @@ export class BuiltinType extends Type {
}
}
export class ExternalType extends Type {
export class ExpressionType extends Type {
constructor(
public value: CompileIdentifierMetadata, public typeParams: Type[] = null,
public value: Expression, public typeParams: Type[] = null,
modifiers: TypeModifier[] = null) {
super(modifiers);
}
visitType(visitor: TypeVisitor, context: any): any {
return visitor.visitExternalType(this, context);
return visitor.visitExpressionType(this, context);
}
}
@ -78,7 +78,7 @@ export var NULL_TYPE = new BuiltinType(BuiltinTypeName.Null);
export interface TypeVisitor {
visitBuiltintType(type: BuiltinType, context: any): any;
visitExternalType(type: ExternalType, context: any): any;
visitExpressionType(type: ExpressionType, context: any): any;
visitArrayType(type: ArrayType, context: any): any;
visitMapType(type: MapType, context: any): any;
}
@ -876,8 +876,14 @@ export function importExpr(id: CompileIdentifierMetadata, typeParams: Type[] = n
export function importType(
id: CompileIdentifierMetadata, typeParams: Type[] = null,
typeModifiers: TypeModifier[] = null): ExternalType {
return isPresent(id) ? new ExternalType(id, typeParams, typeModifiers) : null;
typeModifiers: TypeModifier[] = null): ExpressionType {
return isPresent(id) ? expressionType(importExpr(id), typeParams, typeModifiers) : null;
}
export function expressionType(
expr: Expression, typeParams: Type[] = null,
typeModifiers: TypeModifier[] = null): ExpressionType {
return isPresent(expr) ? new ExpressionType(expr, typeParams, typeModifiers) : null;
}
export function literalArr(values: Expression[], type: Type = null): LiteralArrayExpr {

View File

@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {identifierName} from '../compile_metadata';
import {isPresent} from '../facade/lang';
import {sanitizeIdentifier} from '../util';
import {EmitterVisitorContext} from './abstract_emitter';
import {AbstractJsEmitterVisitor} from './abstract_js_emitter';
@ -52,8 +52,8 @@ class JitEmitterVisitor extends AbstractJsEmitterVisitor {
if (id === -1) {
id = this._evalArgValues.length;
this._evalArgValues.push(value);
const name = isPresent(ast.value.name) ? sanitizeIdentifier(ast.value.name) : 'val';
this._evalArgNames.push(sanitizeIdentifier(`jit_${name}${id}`));
const name = identifierName(ast.value) || 'val';
this._evalArgNames.push(`jit_${name}${id}`);
}
ctx.print(this._evalArgNames[id]);
return null;

View File

@ -7,7 +7,7 @@
*/
import {CompileIdentifierMetadata} from '../compile_metadata';
import {CompileIdentifierMetadata, identifierModuleUrl, identifierName} from '../compile_metadata';
import {isBlank, isPresent} from '../facade/lang';
import {AbstractEmitterVisitor, CATCH_ERROR_VAR, CATCH_STACK_VAR, EmitterVisitorContext, OutputEmitter} from './abstract_emitter';
@ -271,8 +271,13 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
return null;
}
visitExternalType(ast: o.ExternalType, ctx: EmitterVisitorContext): any {
this._visitIdentifier(ast.value, ast.typeParams, ctx);
visitExpressionType(ast: o.ExpressionType, ctx: EmitterVisitorContext): any {
ast.value.visitExpression(this, ctx);
if (isPresent(ast.typeParams) && ast.typeParams.length > 0) {
ctx.print(`<`);
this.visitAllObjects(type => type.visitType(this, ctx), ast.typeParams, ctx, ',');
ctx.print(`>`);
}
return null;
}
@ -317,14 +322,16 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
private _visitIdentifier(
value: CompileIdentifierMetadata, typeParams: o.Type[], ctx: EmitterVisitorContext): void {
if (isBlank(value.name)) {
const name = identifierName(value);
const moduleUrl = identifierModuleUrl(value);
if (isBlank(name)) {
throw new Error(`Internal error: unknown identifier ${value}`);
}
if (isPresent(value.moduleUrl) && value.moduleUrl != this._moduleUrl) {
let prefix = this.importsWithPrefixes.get(value.moduleUrl);
if (isPresent(moduleUrl) && moduleUrl != this._moduleUrl) {
let prefix = this.importsWithPrefixes.get(moduleUrl);
if (isBlank(prefix)) {
prefix = `import${this.importsWithPrefixes.size}`;
this.importsWithPrefixes.set(value.moduleUrl, prefix);
this.importsWithPrefixes.set(moduleUrl, prefix);
}
ctx.print(`${prefix}.`);
}
@ -333,7 +340,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
ctx.print('.');
ctx.print(value.reference.members.join('.'));
} else {
ctx.print(value.name);
ctx.print(name);
}
if (isPresent(typeParams) && typeParams.length > 0) {
ctx.print(`<`);

View File

@ -30,12 +30,10 @@ class _ValueOutputAstTransformer implements ValueTransformer {
visitPrimitive(value: any, type: o.Type): o.Expression { return o.literal(value, type); }
visitOther(value: any, type: o.Type): o.Expression {
if (value instanceof CompileIdentifierMetadata) {
return o.importExpr(value);
} else if (value instanceof o.Expression) {
if (value instanceof o.Expression) {
return value;
} else {
throw new Error(`Illegal state: Don't now how to compile value ${value}`);
return o.importExpr({reference: value});
}
}
}

View File

@ -8,6 +8,7 @@
import {Injectable, Pipe, Type, resolveForwardRef} from '@angular/core';
import {ListWrapper} from './facade/collection';
import {isPresent, stringify} from './facade/lang';
import {ReflectorReader, reflector} from './private_import_core';
@ -37,7 +38,7 @@ export class PipeResolver {
resolve(type: Type<any>, throwIfNotFound = true): Pipe {
const metas = this._reflector.annotations(resolveForwardRef(type));
if (isPresent(metas)) {
const annotation = metas.find(_isPipeMetadata);
const annotation = ListWrapper.findLast(metas, _isPipeMetadata);
if (isPresent(annotation)) {
return annotation;
}

View File

@ -7,9 +7,9 @@
*/
import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompileNgModuleMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata, CompileTypeMetadata} from './compile_metadata';
import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompileNgModuleMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata, CompileTypeMetadata, tokenName, tokenReference} from './compile_metadata';
import {isBlank, isPresent} from './facade/lang';
import {Identifiers, resolveIdentifierToken} from './identifiers';
import {Identifiers, createIdentifierToken, resolveIdentifier} from './identifiers';
import {ParseError, ParseSourceSpan} from './parse_util';
import {AttrAst, DirectiveAst, ProviderAst, ProviderAstType, ReferenceAst} from './template_parser/template_ast';
@ -31,9 +31,9 @@ export class ProviderViewContext {
constructor(public component: CompileDirectiveMetadata, public sourceSpan: ParseSourceSpan) {
this.viewQueries = _getViewQueries(component);
this.viewProviders = new Map<any, boolean>();
_normalizeProviders(component.viewProviders, sourceSpan, this.errors).forEach((provider) => {
if (isBlank(this.viewProviders.get(provider.token.reference))) {
this.viewProviders.set(provider.token.reference, true);
component.viewProviders.forEach((provider) => {
if (isBlank(this.viewProviders.get(tokenReference(provider.token)))) {
this.viewProviders.set(tokenReference(provider.token), true);
}
});
}
@ -62,17 +62,14 @@ export class ProviderElementContext {
Array.from(this._allProviders.values()).forEach((provider) => {
this._addQueryReadsTo(provider.token, queriedTokens);
});
refs.forEach((refAst) => {
this._addQueryReadsTo(new CompileTokenMetadata({value: refAst.name}), queriedTokens);
});
if (isPresent(
queriedTokens.get(resolveIdentifierToken(Identifiers.ViewContainerRef).reference))) {
refs.forEach((refAst) => { this._addQueryReadsTo({value: refAst.name}, queriedTokens); });
if (isPresent(queriedTokens.get(resolveIdentifier(Identifiers.ViewContainerRef)))) {
this._hasViewContainer = true;
}
// create the providers that we know are eager first
Array.from(this._allProviders.values()).forEach((provider) => {
const eager = provider.eager || isPresent(queriedTokens.get(provider.token.reference));
const eager = provider.eager || isPresent(queriedTokens.get(tokenReference(provider.token)));
if (eager) {
this._getOrCreateLocalProvider(provider.providerType, provider.token, true);
}
@ -104,8 +101,8 @@ export class ProviderElementContext {
private _addQueryReadsTo(token: CompileTokenMetadata, queryReadTokens: Map<any, boolean>) {
this._getQueriesFor(token).forEach((query) => {
const queryReadToken = query.read || token;
if (isBlank(queryReadTokens.get(queryReadToken.reference))) {
queryReadTokens.set(queryReadToken.reference, true);
if (isBlank(queryReadTokens.get(tokenReference(queryReadToken)))) {
queryReadTokens.set(tokenReference(queryReadToken), true);
}
});
}
@ -116,7 +113,7 @@ export class ProviderElementContext {
let distance = 0;
let queries: CompileQueryMetadata[];
while (currentEl !== null) {
queries = currentEl._contentQueries.get(token.reference);
queries = currentEl._contentQueries.get(tokenReference(token));
if (isPresent(queries)) {
result.push(...queries.filter((query) => query.descendants || distance <= 1));
}
@ -125,7 +122,7 @@ export class ProviderElementContext {
}
currentEl = currentEl._parent;
}
queries = this.viewContext.viewQueries.get(token.reference);
queries = this.viewContext.viewQueries.get(tokenReference(token));
if (isPresent(queries)) {
result.push(...queries);
}
@ -136,7 +133,7 @@ export class ProviderElementContext {
private _getOrCreateLocalProvider(
requestingProviderType: ProviderAstType, token: CompileTokenMetadata,
eager: boolean): ProviderAst {
const resolvedProvider = this._allProviders.get(token.reference);
const resolvedProvider = this._allProviders.get(tokenReference(token));
if (!resolvedProvider || ((requestingProviderType === ProviderAstType.Directive ||
requestingProviderType === ProviderAstType.PublicService) &&
resolvedProvider.providerType === ProviderAstType.PrivateService) ||
@ -145,24 +142,23 @@ export class ProviderElementContext {
resolvedProvider.providerType === ProviderAstType.Builtin)) {
return null;
}
let transformedProviderAst = this._transformedProviders.get(token.reference);
let transformedProviderAst = this._transformedProviders.get(tokenReference(token));
if (isPresent(transformedProviderAst)) {
return transformedProviderAst;
}
if (isPresent(this._seenProviders.get(token.reference))) {
if (isPresent(this._seenProviders.get(tokenReference(token)))) {
this.viewContext.errors.push(new ProviderError(
`Cannot instantiate cyclic dependency! ${token.name}`, this._sourceSpan));
`Cannot instantiate cyclic dependency! ${tokenName(token)}`, this._sourceSpan));
return null;
}
this._seenProviders.set(token.reference, true);
this._seenProviders.set(tokenReference(token), true);
const transformedProviders = resolvedProvider.providers.map((provider) => {
let transformedUseValue = provider.useValue;
let transformedUseExisting = provider.useExisting;
let transformedDeps: CompileDiDependencyMetadata[];
if (isPresent(provider.useExisting)) {
const existingDiDep = this._getDependency(
resolvedProvider.providerType,
new CompileDiDependencyMetadata({token: provider.useExisting}), eager);
resolvedProvider.providerType, {token: provider.useExisting}, eager);
if (isPresent(existingDiDep.token)) {
transformedUseExisting = existingDiDep.token;
} else {
@ -186,7 +182,7 @@ export class ProviderElementContext {
});
transformedProviderAst =
_transformProviderAst(resolvedProvider, {eager: eager, providers: transformedProviders});
this._transformedProviders.set(token.reference, transformedProviderAst);
this._transformedProviders.set(tokenReference(token), transformedProviderAst);
return transformedProviderAst;
}
@ -195,28 +191,25 @@ export class ProviderElementContext {
eager: boolean = null): CompileDiDependencyMetadata {
if (dep.isAttribute) {
const attrValue = this._attrs[dep.token.value];
return new CompileDiDependencyMetadata(
{isValue: true, value: attrValue == null ? null : attrValue});
return {isValue: true, value: attrValue == null ? null : attrValue};
}
if (isPresent(dep.token)) {
// access builtints
if ((requestingProviderType === ProviderAstType.Directive ||
requestingProviderType === ProviderAstType.Component)) {
if (dep.token.reference === resolveIdentifierToken(Identifiers.Renderer).reference ||
dep.token.reference === resolveIdentifierToken(Identifiers.ElementRef).reference ||
dep.token.reference ===
resolveIdentifierToken(Identifiers.ChangeDetectorRef).reference ||
dep.token.reference === resolveIdentifierToken(Identifiers.TemplateRef).reference) {
if (tokenReference(dep.token) === resolveIdentifier(Identifiers.Renderer) ||
tokenReference(dep.token) === resolveIdentifier(Identifiers.ElementRef) ||
tokenReference(dep.token) === resolveIdentifier(Identifiers.ChangeDetectorRef) ||
tokenReference(dep.token) === resolveIdentifier(Identifiers.TemplateRef)) {
return dep;
}
if (dep.token.reference ===
resolveIdentifierToken(Identifiers.ViewContainerRef).reference) {
if (tokenReference(dep.token) === resolveIdentifier(Identifiers.ViewContainerRef)) {
this._hasViewContainer = true;
}
}
// access the injector
if (dep.token.reference === resolveIdentifierToken(Identifiers.Injector).reference) {
if (tokenReference(dep.token) === resolveIdentifier(Identifiers.Injector)) {
return dep;
}
// access providers
@ -238,7 +231,7 @@ export class ProviderElementContext {
}
if (dep.isSelf) {
if (!result && dep.isOptional) {
result = new CompileDiDependencyMetadata({isValue: true, value: null});
result = {isValue: true, value: null};
}
} else {
// check parent elements
@ -252,20 +245,18 @@ export class ProviderElementContext {
}
// check @Host restriction
if (!result) {
if (!dep.isHost || this.viewContext.component.type.isHost ||
this.viewContext.component.type.reference === dep.token.reference ||
isPresent(this.viewContext.viewProviders.get(dep.token.reference))) {
if (!dep.isHost || this.viewContext.component.isHost ||
this.viewContext.component.type.reference === tokenReference(dep.token) ||
isPresent(this.viewContext.viewProviders.get(tokenReference(dep.token)))) {
result = dep;
} else {
result = dep.isOptional ?
result = new CompileDiDependencyMetadata({isValue: true, value: null}) :
null;
result = dep.isOptional ? result = {isValue: true, value: null} : null;
}
}
}
if (!result) {
this.viewContext.errors.push(
new ProviderError(`No provider for ${dep.token.name}`, this._sourceSpan));
new ProviderError(`No provider for ${tokenName(dep.token)}`, this._sourceSpan));
}
return result;
}
@ -284,16 +275,14 @@ export class NgModuleProviderAnalyzer {
this._allProviders = new Map<any, ProviderAst>();
const ngModuleTypes = ngModule.transitiveModule.modules.map((moduleMeta) => moduleMeta.type);
ngModuleTypes.forEach((ngModuleType: CompileTypeMetadata) => {
const ngModuleProvider = new CompileProviderMetadata(
{token: new CompileTokenMetadata({identifier: ngModuleType}), useClass: ngModuleType});
const ngModuleProvider = {token: {identifier: ngModuleType}, useClass: ngModuleType};
_resolveProviders(
[ngModuleProvider], ProviderAstType.PublicService, true, sourceSpan, this._errors,
this._allProviders);
});
_resolveProviders(
_normalizeProviders(
ngModule.transitiveModule.providers.concat(extraProviders), sourceSpan, this._errors),
ProviderAstType.PublicService, false, sourceSpan, this._errors, this._allProviders);
ngModule.transitiveModule.providers.concat(extraProviders), ProviderAstType.PublicService,
false, sourceSpan, this._errors, this._allProviders);
}
parse(): ProviderAst[] {
@ -308,28 +297,28 @@ export class NgModuleProviderAnalyzer {
}
private _getOrCreateLocalProvider(token: CompileTokenMetadata, eager: boolean): ProviderAst {
const resolvedProvider = this._allProviders.get(token.reference);
const resolvedProvider = this._allProviders.get(tokenReference(token));
if (!resolvedProvider) {
return null;
}
let transformedProviderAst = this._transformedProviders.get(token.reference);
let transformedProviderAst = this._transformedProviders.get(tokenReference(token));
if (isPresent(transformedProviderAst)) {
return transformedProviderAst;
}
if (isPresent(this._seenProviders.get(token.reference))) {
if (isPresent(this._seenProviders.get(tokenReference(token)))) {
this._errors.push(new ProviderError(
`Cannot instantiate cyclic dependency! ${token.name}`, resolvedProvider.sourceSpan));
`Cannot instantiate cyclic dependency! ${tokenName(token)}`,
resolvedProvider.sourceSpan));
return null;
}
this._seenProviders.set(token.reference, true);
this._seenProviders.set(tokenReference(token), true);
const transformedProviders = resolvedProvider.providers.map((provider) => {
let transformedUseValue = provider.useValue;
let transformedUseExisting = provider.useExisting;
let transformedDeps: CompileDiDependencyMetadata[];
if (isPresent(provider.useExisting)) {
const existingDiDep = this._getDependency(
new CompileDiDependencyMetadata({token: provider.useExisting}), eager,
resolvedProvider.sourceSpan);
const existingDiDep =
this._getDependency({token: provider.useExisting}, eager, resolvedProvider.sourceSpan);
if (isPresent(existingDiDep.token)) {
transformedUseExisting = existingDiDep.token;
} else {
@ -353,7 +342,7 @@ export class NgModuleProviderAnalyzer {
});
transformedProviderAst =
_transformProviderAst(resolvedProvider, {eager: eager, providers: transformedProviders});
this._transformedProviders.set(token.reference, transformedProviderAst);
this._transformedProviders.set(tokenReference(token), transformedProviderAst);
return transformedProviderAst;
}
@ -363,9 +352,8 @@ export class NgModuleProviderAnalyzer {
let foundLocal = false;
if (!dep.isSkipSelf && isPresent(dep.token)) {
// access the injector
if (dep.token.reference === resolveIdentifierToken(Identifiers.Injector).reference ||
dep.token.reference ===
resolveIdentifierToken(Identifiers.ComponentFactoryResolver).reference) {
if (tokenReference(dep.token) === resolveIdentifier(Identifiers.Injector) ||
tokenReference(dep.token) === resolveIdentifier(Identifiers.ComponentFactoryResolver)) {
foundLocal = true;
// access providers
} else if (isPresent(this._getOrCreateLocalProvider(dep.token, eager))) {
@ -375,10 +363,10 @@ export class NgModuleProviderAnalyzer {
let result: CompileDiDependencyMetadata = dep;
if (dep.isSelf && !foundLocal) {
if (dep.isOptional) {
result = new CompileDiDependencyMetadata({isValue: true, value: null});
result = {isValue: true, value: null};
} else {
this._errors.push(
new ProviderError(`No provider for ${dep.token.name}`, requestorSourceSpan));
new ProviderError(`No provider for ${tokenName(dep.token)}`, requestorSourceSpan));
}
}
return result;
@ -389,7 +377,7 @@ function _transformProvider(
provider: CompileProviderMetadata,
{useExisting, useValue, deps}:
{useExisting: CompileTokenMetadata, useValue: any, deps: CompileDiDependencyMetadata[]}) {
return new CompileProviderMetadata({
return {
token: provider.token,
useClass: provider.useClass,
useExisting: useExisting,
@ -397,7 +385,7 @@ function _transformProvider(
useValue: useValue,
deps: deps,
multi: provider.multi
});
};
}
function _transformProviderAst(
@ -408,44 +396,13 @@ function _transformProviderAst(
provider.providerType, provider.lifecycleHooks, provider.sourceSpan);
}
function _normalizeProviders(
providers: Array<CompileProviderMetadata|CompileTypeMetadata|any[]>,
sourceSpan: ParseSourceSpan, targetErrors: ParseError[],
targetProviders: CompileProviderMetadata[] = null): CompileProviderMetadata[] {
if (!targetProviders) {
targetProviders = [];
}
if (isPresent(providers)) {
providers.forEach((provider) => {
if (Array.isArray(provider)) {
_normalizeProviders(<any[]>provider, sourceSpan, targetErrors, targetProviders);
} else {
let normalizeProvider: CompileProviderMetadata;
if (provider instanceof CompileProviderMetadata) {
normalizeProvider = provider;
} else if (provider instanceof CompileTypeMetadata) {
normalizeProvider = new CompileProviderMetadata(
{token: new CompileTokenMetadata({identifier: provider}), useClass: provider});
} else {
targetErrors.push(new ProviderError(`Unknown provider type ${provider}`, sourceSpan));
}
if (isPresent(normalizeProvider)) {
targetProviders.push(normalizeProvider);
}
}
});
}
return targetProviders;
}
function _resolveProvidersFromDirectives(
directives: CompileDirectiveSummary[], sourceSpan: ParseSourceSpan,
targetErrors: ParseError[]): Map<any, ProviderAst> {
const providersByToken = new Map<any, ProviderAst>();
directives.forEach((directive) => {
const dirProvider = new CompileProviderMetadata(
{token: new CompileTokenMetadata({identifier: directive.type}), useClass: directive.type});
const dirProvider:
CompileProviderMetadata = {token: {identifier: directive.type}, useClass: directive.type};
_resolveProviders(
[dirProvider],
directive.isComponent ? ProviderAstType.Component : ProviderAstType.Directive, true,
@ -457,11 +414,11 @@ function _resolveProvidersFromDirectives(
directives.filter(dir => dir.isComponent).concat(directives.filter(dir => !dir.isComponent));
directivesWithComponentFirst.forEach((directive) => {
_resolveProviders(
_normalizeProviders(directive.providers, sourceSpan, targetErrors),
ProviderAstType.PublicService, false, sourceSpan, targetErrors, providersByToken);
directive.providers, ProviderAstType.PublicService, false, sourceSpan, targetErrors,
providersByToken);
_resolveProviders(
_normalizeProviders(directive.viewProviders, sourceSpan, targetErrors),
ProviderAstType.PrivateService, false, sourceSpan, targetErrors, providersByToken);
directive.viewProviders, ProviderAstType.PrivateService, false, sourceSpan, targetErrors,
providersByToken);
});
return providersByToken;
}
@ -471,21 +428,21 @@ function _resolveProviders(
sourceSpan: ParseSourceSpan, targetErrors: ParseError[],
targetProvidersByToken: Map<any, ProviderAst>) {
providers.forEach((provider) => {
let resolvedProvider = targetProvidersByToken.get(provider.token.reference);
if (isPresent(resolvedProvider) && resolvedProvider.multiProvider !== provider.multi) {
let resolvedProvider = targetProvidersByToken.get(tokenReference(provider.token));
if (isPresent(resolvedProvider) && !!resolvedProvider.multiProvider !== !!provider.multi) {
targetErrors.push(new ProviderError(
`Mixing multi and non multi provider is not possible for token ${resolvedProvider.token.name}`,
`Mixing multi and non multi provider is not possible for token ${tokenName(resolvedProvider.token)}`,
sourceSpan));
}
if (!resolvedProvider) {
const lifecycleHooks =
provider.token.identifier && provider.token.identifier instanceof CompileTypeMetadata ?
provider.token.identifier.lifecycleHooks :
const lifecycleHooks = provider.token.identifier &&
(<CompileTypeMetadata>provider.token.identifier).lifecycleHooks ?
(<CompileTypeMetadata>provider.token.identifier).lifecycleHooks :
[];
resolvedProvider = new ProviderAst(
provider.token, provider.multi, eager || lifecycleHooks.length > 0, [provider],
providerType, lifecycleHooks, sourceSpan);
targetProvidersByToken.set(provider.token.reference, resolvedProvider);
targetProvidersByToken.set(tokenReference(provider.token), resolvedProvider);
} else {
if (!provider.multi) {
resolvedProvider.providers.length = 0;
@ -517,10 +474,10 @@ function _getContentQueries(directives: CompileDirectiveSummary[]):
function _addQueryToTokenMap(map: Map<any, CompileQueryMetadata[]>, query: CompileQueryMetadata) {
query.selectors.forEach((token: CompileTokenMetadata) => {
let entry = map.get(token.reference);
let entry = map.get(tokenReference(token));
if (!entry) {
entry = [];
map.set(token.reference, entry);
map.set(tokenReference(token), entry);
}
entry.push(query);
});

View File

@ -7,7 +7,8 @@
*/
import {Injectable, ViewEncapsulation} from '@angular/core';
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileStylesheetMetadata} from './compile_metadata';
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileStylesheetMetadata, identifierModuleUrl, identifierName} from './compile_metadata';
import * as o from './output/output_ast';
import {ShadowCss} from './shadow_css';
import {UrlResolver} from './url_resolver';
@ -18,7 +19,7 @@ const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;
export class StylesCompileDependency {
constructor(
public moduleUrl: string, public isShimmed: boolean,
public name: string, public moduleUrl: string, public isShimmed: boolean,
public valuePlaceholder: CompileIdentifierMetadata) {}
}
@ -47,7 +48,7 @@ export class StyleCompiler {
comp, new CompileStylesheetMetadata({
styles: comp.template.styles,
styleUrls: comp.template.styleUrls,
moduleUrl: comp.type.moduleUrl
moduleUrl: identifierModuleUrl(comp.type)
}),
true);
comp.template.externalStylesheets.forEach((stylesheetMeta) => {
@ -65,8 +66,9 @@ export class StyleCompiler {
stylesheet.styles.map(plainStyle => o.literal(this._shimIfNeeded(plainStyle, shim)));
const dependencies: StylesCompileDependency[] = [];
for (let i = 0; i < stylesheet.styleUrls.length; i++) {
const identifier = new CompileIdentifierMetadata({name: getStylesVarName(null)});
dependencies.push(new StylesCompileDependency(stylesheet.styleUrls[i], shim, identifier));
const identifier: CompileIdentifierMetadata = {reference: null};
dependencies.push(new StylesCompileDependency(
getStylesVarName(null), stylesheet.styleUrls[i], shim, identifier));
styleExpressions.push(new o.ExternalExpr(identifier));
}
// styles variable contains plain strings and arrays of other styles arrays (recursive),
@ -87,7 +89,7 @@ export class StyleCompiler {
function getStylesVarName(component: CompileDirectiveMetadata): string {
let result = `styles`;
if (component) {
result += `_${component.type.name}`;
result += `_${identifierName(component.type)}`;
}
return result;
}

View File

@ -8,12 +8,12 @@
import {Inject, Injectable, OpaqueToken, Optional, SchemaMetadata, SecurityContext} from '@angular/core';
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeSummary, CompileTemplateMetadata, CompileTemplateSummary, CompileTokenMetadata, CompileTypeMetadata, removeIdentifierDuplicates} from '../compile_metadata';
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeSummary, CompileTemplateMetadata, CompileTemplateSummary, CompileTokenMetadata, CompileTypeMetadata, identifierName} from '../compile_metadata';
import {AST, ASTWithSource, BindingPipe, EmptyExpr, Interpolation, ParserError, RecursiveAstVisitor, TemplateBinding} from '../expression_parser/ast';
import {Parser} from '../expression_parser/parser';
import {isPresent} from '../facade/lang';
import {I18NHtmlParser} from '../i18n/i18n_html_parser';
import {Identifiers, identifierToken, resolveIdentifierToken} from '../identifiers';
import {Identifiers, createIdentifierToken, identifierToken} from '../identifiers';
import * as html from '../ml_parser/ast';
import {ParseTreeResult} from '../ml_parser/html_parser';
import {expandNodes} from '../ml_parser/icu_ast_expander';
@ -546,7 +546,8 @@ class TemplateParseVisitor implements html.Visitor {
let component: CompileDirectiveSummary = null;
const directiveAsts = directives.map((directive) => {
const sourceSpan = new ParseSourceSpan(
elementSourceSpan.start, elementSourceSpan.end, `Directive ${directive.type.name}`);
elementSourceSpan.start, elementSourceSpan.end,
`Directive ${identifierName(directive.type)}`);
if (directive.isComponent) {
component = directive;
}
@ -579,7 +580,7 @@ class TemplateParseVisitor implements html.Visitor {
} else if (!component) {
let refToken: CompileTokenMetadata = null;
if (isTemplateElement) {
refToken = resolveIdentifierToken(Identifiers.TemplateRef);
refToken = createIdentifierToken(Identifiers.TemplateRef);
}
targetReferences.push(new ReferenceAst(elOrDirRef.name, refToken, elOrDirRef.sourceSpan));
}
@ -640,7 +641,7 @@ class TemplateParseVisitor implements html.Visitor {
private _findComponentDirectiveNames(directives: DirectiveAst[]): string[] {
return this._findComponentDirectives(directives)
.map(directive => directive.directive.type.name);
.map(directive => identifierName(directive.directive.type));
}
private _assertOnlyOneComponent(directives: DirectiveAst[], sourceSpan: ParseSourceSpan) {

View File

@ -35,10 +35,6 @@ function _splitAt(input: string, character: string, defaultValues: string[]): st
return [input.slice(0, characterIndex).trim(), input.slice(characterIndex + 1).trim()];
}
export function sanitizeIdentifier(name: string): string {
return name.replace(/\W/g, '_');
}
export function visitValue(value: any, visitor: ValueVisitor, context: any): any {
if (Array.isArray(value)) {
return visitor.visitArray(<any[]>value, context);

View File

@ -7,11 +7,11 @@
*/
import {CompileDiDependencyMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata} from '../compile_metadata';
import {CompileDiDependencyMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata, identifierName, tokenName, tokenReference} from '../compile_metadata';
import {createDiTokenExpression} from '../compiler_util/identifier_util';
import {DirectiveWrapperCompiler, DirectiveWrapperExpressions} from '../directive_wrapper_compiler';
import {isPresent} from '../facade/lang';
import {Identifiers, identifierToken, resolveIdentifier, resolveIdentifierToken} from '../identifiers';
import {Identifiers, createIdentifier, createIdentifierToken, identifierToken, resolveIdentifier} from '../identifiers';
import * as o from '../output/output_ast';
import {convertValueToOutputAst} from '../output/value_util';
import {ProviderAst, ProviderAstType, ReferenceAst, TemplateAst} from '../template_parser/template_ast';
@ -20,7 +20,7 @@ import {CompileMethod} from './compile_method';
import {CompileQuery, addQueryToTokenMap, createQueryList} from './compile_query';
import {CompileView, CompileViewRootNode} from './compile_view';
import {InjectMethodVars, ViewProperties} from './constants';
import {ComponentFactoryDependency, DirectiveWrapperDependency, ViewClassDependency} from './deps';
import {ComponentFactoryDependency, DirectiveWrapperDependency} from './deps';
import {getPropertyInView, injectFromViewParentInjector} from './util';
export class CompileNode {
@ -35,7 +35,7 @@ export class CompileNode {
export class CompileElement extends CompileNode {
static createNull(): CompileElement {
return new CompileElement(null, null, null, null, null, null, [], [], false, false, [], []);
return new CompileElement(null, null, null, null, null, null, [], [], false, false, []);
}
public compViewExpr: o.Expression = null;
@ -57,21 +57,18 @@ export class CompileElement extends CompileNode {
sourceAst: TemplateAst, public component: CompileDirectiveSummary,
private _directives: CompileDirectiveSummary[],
private _resolvedProvidersArray: ProviderAst[], public hasViewContainer: boolean,
public hasEmbeddedView: boolean, references: ReferenceAst[],
private _targetDependencies:
Array<ViewClassDependency|ComponentFactoryDependency|DirectiveWrapperDependency>) {
public hasEmbeddedView: boolean, references: ReferenceAst[]) {
super(parent, view, nodeIndex, renderNode, sourceAst);
this.referenceTokens = {};
references.forEach(ref => this.referenceTokens[ref.name] = ref.value);
this.elementRef =
o.importExpr(resolveIdentifier(Identifiers.ElementRef)).instantiate([this.renderNode]);
this.instances.set(resolveIdentifierToken(Identifiers.ElementRef).reference, this.elementRef);
o.importExpr(createIdentifier(Identifiers.ElementRef)).instantiate([this.renderNode]);
this.instances.set(resolveIdentifier(Identifiers.ElementRef), this.elementRef);
this.instances.set(
resolveIdentifierToken(Identifiers.Injector).reference,
resolveIdentifier(Identifiers.Injector),
o.THIS_EXPR.callMethod('injector', [o.literal(this.nodeIndex)]));
this.instances.set(
resolveIdentifierToken(Identifiers.Renderer).reference, o.THIS_EXPR.prop('renderer'));
this.instances.set(resolveIdentifier(Identifiers.Renderer), o.THIS_EXPR.prop('renderer'));
if (this.hasViewContainer || this.hasEmbeddedView) {
this._createViewContainer();
}
@ -85,41 +82,40 @@ export class CompileElement extends CompileNode {
const parentNodeIndex = this.isRootElement() ? null : this.parent.nodeIndex;
// private is fine here as no child view will reference a ViewContainer
this.view.fields.push(new o.ClassField(
fieldName, o.importType(resolveIdentifier(Identifiers.ViewContainer)),
fieldName, o.importType(createIdentifier(Identifiers.ViewContainer)),
[o.StmtModifier.Private]));
const statement =
o.THIS_EXPR.prop(fieldName)
.set(o.importExpr(resolveIdentifier(Identifiers.ViewContainer)).instantiate([
.set(o.importExpr(createIdentifier(Identifiers.ViewContainer)).instantiate([
o.literal(this.nodeIndex), o.literal(parentNodeIndex), o.THIS_EXPR, this.renderNode
]))
.toStmt();
this.view.createMethod.addStmt(statement);
this.viewContainer = o.THIS_EXPR.prop(fieldName);
this.instances.set(
resolveIdentifierToken(Identifiers.ViewContainer).reference, this.viewContainer);
this.instances.set(resolveIdentifier(Identifiers.ViewContainer), this.viewContainer);
this.view.viewContainers.push(this.viewContainer);
}
private _createComponentFactoryResolver() {
const entryComponents =
this.component.entryComponents.map((entryComponent: CompileIdentifierMetadata) => {
const id = new CompileIdentifierMetadata({name: entryComponent.name});
this._targetDependencies.push(new ComponentFactoryDependency(entryComponent, id));
const id: CompileIdentifierMetadata = {reference: null};
this.view.targetDependencies.push(new ComponentFactoryDependency(entryComponent, id));
return id;
});
if (!entryComponents || entryComponents.length === 0) {
return;
}
const createComponentFactoryResolverExpr =
o.importExpr(resolveIdentifier(Identifiers.CodegenComponentFactoryResolver)).instantiate([
o.importExpr(createIdentifier(Identifiers.CodegenComponentFactoryResolver)).instantiate([
o.literalArr(entryComponents.map((entryComponent) => o.importExpr(entryComponent))),
injectFromViewParentInjector(
this.view, resolveIdentifierToken(Identifiers.ComponentFactoryResolver), false)
this.view, createIdentifierToken(Identifiers.ComponentFactoryResolver), false)
]);
const provider = new CompileProviderMetadata({
token: resolveIdentifierToken(Identifiers.ComponentFactoryResolver),
const provider: CompileProviderMetadata = {
token: createIdentifierToken(Identifiers.ComponentFactoryResolver),
useValue: createComponentFactoryResolverExpr
});
};
// Add ComponentFactoryResolver as first provider as it does not have deps on other providers
// ProviderAstType.PrivateService as only the component and its view can see it,
// but nobody else
@ -141,13 +137,13 @@ export class CompileElement extends CompileNode {
this.embeddedView = embeddedView;
if (isPresent(embeddedView)) {
const createTemplateRefExpr =
o.importExpr(resolveIdentifier(Identifiers.TemplateRef_)).instantiate([
o.importExpr(createIdentifier(Identifiers.TemplateRef_)).instantiate([
o.THIS_EXPR, o.literal(this.nodeIndex), this.renderNode
]);
const provider = new CompileProviderMetadata({
token: resolveIdentifierToken(Identifiers.TemplateRef),
const provider: CompileProviderMetadata = {
token: createIdentifierToken(Identifiers.TemplateRef),
useValue: createTemplateRefExpr
});
};
// Add TemplateRef as first provider as it does not have deps on other providers
this._resolvedProvidersArray.unshift(new ProviderAst(
provider.token, false, true, [provider], ProviderAstType.Builtin, [],
@ -158,13 +154,12 @@ export class CompileElement extends CompileNode {
beforeChildren(): void {
if (this.hasViewContainer) {
this.instances.set(
resolveIdentifierToken(Identifiers.ViewContainerRef).reference,
this.viewContainer.prop('vcRef'));
resolveIdentifier(Identifiers.ViewContainerRef), this.viewContainer.prop('vcRef'));
}
this._resolvedProviders = new Map<any, ProviderAst>();
this._resolvedProvidersArray.forEach(
provider => this._resolvedProviders.set(provider.token.reference, provider));
provider => this._resolvedProviders.set(tokenReference(provider.token), provider));
// create all the provider instances, some in the view constructor,
// some as getters. We rely on the fact that they are already sorted topologically.
@ -173,9 +168,7 @@ export class CompileElement extends CompileNode {
resolvedProvider.providerType === ProviderAstType.Directive;
const providerValueExpressions = resolvedProvider.providers.map((provider) => {
if (provider.useExisting) {
return this._getDependency(
resolvedProvider.providerType,
new CompileDiDependencyMetadata({token: provider.useExisting}));
return this._getDependency(resolvedProvider.providerType, {token: provider.useExisting});
} else if (provider.useFactory) {
const deps = provider.deps || provider.useFactory.diDeps;
const depsExpr =
@ -186,10 +179,10 @@ export class CompileElement extends CompileNode {
const depsExpr =
deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep));
if (isDirectiveWrapper) {
const directiveWrapperIdentifier = new CompileIdentifierMetadata(
{name: DirectiveWrapperCompiler.dirWrapperClassName(provider.useClass)});
this._targetDependencies.push(
new DirectiveWrapperDependency(provider.useClass, directiveWrapperIdentifier));
const directiveWrapperIdentifier: CompileIdentifierMetadata = {reference: null};
this.view.targetDependencies.push(new DirectiveWrapperDependency(
provider.useClass, DirectiveWrapperCompiler.dirWrapperClassName(provider.useClass),
directiveWrapperIdentifier));
return DirectiveWrapperExpressions.create(directiveWrapperIdentifier, depsExpr);
} else {
return o.importExpr(provider.useClass)
@ -199,22 +192,23 @@ export class CompileElement extends CompileNode {
return convertValueToOutputAst(provider.useValue);
}
});
const propName = `_${resolvedProvider.token.name}_${this.nodeIndex}_${this.instances.size}`;
const propName =
`_${tokenName(resolvedProvider.token)}_${this.nodeIndex}_${this.instances.size}`;
const instance = createProviderProperty(
propName, resolvedProvider, providerValueExpressions, resolvedProvider.multiProvider,
resolvedProvider.eager, this);
if (isDirectiveWrapper) {
this.directiveWrapperInstance.set(resolvedProvider.token.reference, instance);
this.directiveWrapperInstance.set(tokenReference(resolvedProvider.token), instance);
this.instances.set(
resolvedProvider.token.reference, DirectiveWrapperExpressions.context(instance));
tokenReference(resolvedProvider.token), DirectiveWrapperExpressions.context(instance));
} else {
this.instances.set(resolvedProvider.token.reference, instance);
this.instances.set(tokenReference(resolvedProvider.token), instance);
}
});
for (let i = 0; i < this._directives.length; i++) {
const directive = this._directives[i];
const directiveInstance = this.instances.get(identifierToken(directive.type).reference);
const directiveInstance = this.instances.get(tokenReference(identifierToken(directive.type)));
directive.queries.forEach((queryMeta) => { this._addQuery(queryMeta, directiveInstance); });
}
const queriesWithReads: _QueryWithRead[] = [];
@ -227,12 +221,12 @@ export class CompileElement extends CompileNode {
const token = this.referenceTokens[varName];
let varValue: o.Expression;
if (token) {
varValue = this.instances.get(token.reference);
varValue = this.instances.get(tokenReference(token));
} else {
varValue = this.renderNode;
}
this.view.locals.set(varName, varValue);
const varToken = new CompileTokenMetadata({value: varName});
const varToken = {value: varName};
queriesWithReads.push(
...this._getQueriesFor(varToken).map(query => new _QueryWithRead(query, varToken)));
});
@ -240,12 +234,12 @@ export class CompileElement extends CompileNode {
let value: o.Expression;
if (isPresent(queryWithRead.read.identifier)) {
// query for an identifier
value = this.instances.get(queryWithRead.read.reference);
value = this.instances.get(tokenReference(queryWithRead.read));
} else {
// query for a reference
const token = this.referenceTokens[queryWithRead.read.value];
if (isPresent(token)) {
value = this.instances.get(token.reference);
value = this.instances.get(tokenReference(token));
} else {
value = this.elementRef;
}
@ -261,7 +255,7 @@ export class CompileElement extends CompileNode {
// Note: afterChildren is called after recursing into children.
// This is good so that an injector match in an element that is closer to a requesting element
// matches first.
const providerExpr = this.instances.get(resolvedProvider.token.reference);
const providerExpr = this.instances.get(tokenReference(resolvedProvider.token));
// Note: view providers are only visible on the injector of that element.
// This is not fully correct as the rules during codegen don't allow a directive
// to get hold of a view provdier on the same element. We still do this semantic
@ -285,7 +279,7 @@ export class CompileElement extends CompileNode {
getComponent(): o.Expression {
return isPresent(this.component) ?
this.instances.get(identifierToken(this.component.type).reference) :
this.instances.get(tokenReference(identifierToken(this.component.type))) :
null;
}
@ -300,7 +294,7 @@ export class CompileElement extends CompileNode {
let distance = 0;
let queries: CompileQuery[];
while (!currentEl.isNull()) {
queries = currentEl._queries.get(token.reference);
queries = currentEl._queries.get(tokenReference(token));
if (isPresent(queries)) {
result.push(...queries.filter((query) => query.meta.descendants || distance <= 1));
}
@ -309,7 +303,7 @@ export class CompileElement extends CompileNode {
}
currentEl = currentEl.parent;
}
queries = this.view.componentView.viewQueries.get(token.reference);
queries = this.view.componentView.viewQueries.get(tokenReference(token));
if (isPresent(queries)) {
result.push(...queries);
}
@ -319,7 +313,7 @@ export class CompileElement extends CompileNode {
private _addQuery(queryMeta: CompileQueryMetadata, directiveInstance: o.Expression):
CompileQuery {
const propName =
`_query_${queryMeta.selectors[0].name}_${this.nodeIndex}_${this._queryCount++}`;
`_query_${tokenName(queryMeta.selectors[0])}_${this.nodeIndex}_${this._queryCount++}`;
const queryList = createQueryList(queryMeta, directiveInstance, propName, this.view);
const query = new CompileQuery(queryMeta, queryList, directiveInstance, this.view);
addQueryToTokenMap(this._queries, query);
@ -332,8 +326,7 @@ export class CompileElement extends CompileNode {
if (isPresent(dep.token)) {
// access builtins with special visibility
if (!result) {
if (dep.token.reference ===
resolveIdentifierToken(Identifiers.ChangeDetectorRef).reference) {
if (tokenReference(dep.token) === resolveIdentifier(Identifiers.ChangeDetectorRef)) {
if (requestingProviderType === ProviderAstType.Component) {
return this.compViewExpr.prop('ref');
} else {
@ -343,7 +336,7 @@ export class CompileElement extends CompileNode {
}
// access regular providers on the element
if (!result) {
const resolvedProvider = this._resolvedProviders.get(dep.token.reference);
const resolvedProvider = this._resolvedProviders.get(tokenReference(dep.token));
// don't allow directives / public services to access private services.
// only components and private services can access private services.
if (resolvedProvider && (requestingProviderType === ProviderAstType.Directive ||
@ -351,7 +344,7 @@ export class CompileElement extends CompileNode {
resolvedProvider.providerType === ProviderAstType.PrivateService) {
return null;
}
result = this.instances.get(dep.token.reference);
result = this.instances.get(tokenReference(dep.token));
}
}
return result;
@ -370,8 +363,7 @@ export class CompileElement extends CompileNode {
// check parent elements
while (!result && !currElement.parent.isNull()) {
currElement = currElement.parent;
result = currElement._getLocalDependency(
ProviderAstType.PublicService, new CompileDiDependencyMetadata({token: dep.token}));
result = currElement._getLocalDependency(ProviderAstType.PublicService, {token: dep.token});
}
if (!result) {

View File

@ -7,9 +7,9 @@
*/
import {CompilePipeSummary} from '../compile_metadata';
import {CompilePipeSummary, tokenReference} from '../compile_metadata';
import {createPureProxy} from '../compiler_util/identifier_util';
import {Identifiers, resolveIdentifier, resolveIdentifierToken} from '../identifiers';
import {Identifiers, createIdentifier, resolveIdentifier} from '../identifiers';
import * as o from '../output/output_ast';
import {CompileView} from './compile_view';
@ -42,8 +42,7 @@ export class CompilePipe {
constructor(public view: CompileView, public meta: CompilePipeSummary) {
this.instance = o.THIS_EXPR.prop(`_pipe_${meta.name}_${view.pipeCount++}`);
const deps = this.meta.type.diDeps.map((diDep) => {
if (diDep.token.reference ===
resolveIdentifierToken(Identifiers.ChangeDetectorRef).reference) {
if (tokenReference(diDep.token) === resolveIdentifier(Identifiers.ChangeDetectorRef)) {
return getPropertyInView(o.THIS_EXPR.prop('ref'), this.view, this.view.componentView);
}
return injectFromViewParentInjector(view, diDep.token, false);
@ -69,7 +68,7 @@ export class CompilePipe {
.callMethod(o.BuiltinMethod.Bind, [pipeInstanceSeenFromPureProxy]),
args.length, purePipeProxyInstance,
{fields: callingView.fields, ctorStmts: callingView.createMethod});
return o.importExpr(resolveIdentifier(Identifiers.castByValue))
return o.importExpr(createIdentifier(Identifiers.castByValue))
.callFn([purePipeProxyInstance, pipeInstanceSeenFromPureProxy.prop('transform')])
.callFn(args);
} else {

View File

@ -6,10 +6,10 @@
* found in the LICENSE file at https://angular.io/license
*/
import {CompileQueryMetadata} from '../compile_metadata';
import {CompileQueryMetadata, tokenReference} from '../compile_metadata';
import {ListWrapper} from '../facade/collection';
import {isPresent} from '../facade/lang';
import {Identifiers, resolveIdentifier} from '../identifiers';
import {Identifiers, createIdentifier} from '../identifiers';
import * as o from '../output/output_ast';
import {CompileElement} from './compile_element';
@ -114,22 +114,22 @@ export function createQueryList(
query: CompileQueryMetadata, directiveInstance: o.Expression, propertyName: string,
compileView: CompileView): o.Expression {
compileView.fields.push(new o.ClassField(
propertyName, o.importType(resolveIdentifier(Identifiers.QueryList), [o.DYNAMIC_TYPE])));
propertyName, o.importType(createIdentifier(Identifiers.QueryList), [o.DYNAMIC_TYPE])));
const expr = o.THIS_EXPR.prop(propertyName);
compileView.createMethod.addStmt(
o.THIS_EXPR.prop(propertyName)
.set(o.importExpr(resolveIdentifier(Identifiers.QueryList), [o.DYNAMIC_TYPE])
.instantiate([]))
.set(o.importExpr(createIdentifier(Identifiers.QueryList), [o.DYNAMIC_TYPE]).instantiate([
]))
.toStmt());
return expr;
}
export function addQueryToTokenMap(map: Map<any, CompileQuery[]>, query: CompileQuery) {
query.meta.selectors.forEach((selector) => {
let entry = map.get(selector.reference);
let entry = map.get(tokenReference(selector));
if (!entry) {
entry = [];
map.set(selector.reference, entry);
map.set(tokenReference(selector), entry);
}
entry.push(query);
});

View File

@ -7,12 +7,12 @@
*/
import {AnimationEntryCompileResult} from '../animation/animation_compiler';
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompilePipeSummary} from '../compile_metadata';
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompilePipeSummary, tokenName} from '../compile_metadata';
import {EventHandlerVars, NameResolver} from '../compiler_util/expression_converter';
import {createPureProxy} from '../compiler_util/identifier_util';
import {CompilerConfig} from '../config';
import {isPresent} from '../facade/lang';
import {Identifiers, resolveIdentifier} from '../identifiers';
import {Identifiers, createIdentifier} from '../identifiers';
import * as o from '../output/output_ast';
import {ViewType} from '../private_import_core';
@ -20,6 +20,7 @@ import {CompileElement, CompileNode} from './compile_element';
import {CompileMethod} from './compile_method';
import {CompilePipe} from './compile_pipe';
import {CompileQuery, addQueryToTokenMap, createQueryList} from './compile_query';
import {ComponentFactoryDependency, DirectiveWrapperDependency, ViewClassDependency} from './deps';
import {getPropertyInView, getViewClassName} from './util';
export enum CompileViewRootNodeType {
@ -84,7 +85,9 @@ export class CompileView implements NameResolver {
public component: CompileDirectiveMetadata, public genConfig: CompilerConfig,
public pipeMetas: CompilePipeSummary[], public styles: o.Expression,
public animations: AnimationEntryCompileResult[], public viewIndex: number,
public declarationElement: CompileElement, public templateVariableBindings: string[][]) {
public declarationElement: CompileElement, public templateVariableBindings: string[][],
public targetDependencies:
Array<ViewClassDependency|ComponentFactoryDependency|DirectiveWrapperDependency>) {
this.createMethod = new CompileMethod(this);
this.animationBindingsMethod = new CompileMethod(this);
this.injectorGetMethod = new CompileMethod(this);
@ -101,7 +104,7 @@ export class CompileView implements NameResolver {
this.viewType = getViewType(component, viewIndex);
this.className = getViewClassName(component, viewIndex);
this.classType = o.importType(new CompileIdentifierMetadata({name: this.className}));
this.classType = o.expressionType(o.variable(this.className));
this.classExpr = o.variable(this.className);
if (this.viewType === ViewType.COMPONENT || this.viewType === ViewType.HOST) {
this.componentView = this;
@ -115,7 +118,7 @@ export class CompileView implements NameResolver {
if (this.viewType === ViewType.COMPONENT) {
const directiveInstance = o.THIS_EXPR.prop('context');
this.component.viewQueries.forEach((queryMeta, queryIndex) => {
const propName = `_viewQuery_${queryMeta.selectors[0].name}_${queryIndex}`;
const propName = `_viewQuery_${tokenName(queryMeta.selectors[0])}_${queryIndex}`;
const queryList = createQueryList(queryMeta, directiveInstance, propName, this);
const query = new CompileQuery(queryMeta, queryList, directiveInstance, this);
addQueryToTokenMap(viewQueries, query);
@ -164,7 +167,7 @@ function getViewType(component: CompileDirectiveMetadata, embeddedTemplateIndex:
return ViewType.EMBEDDED;
}
if (component.type.isHost) {
if (component.isHost) {
return ViewType.HOST;
}

View File

@ -10,7 +10,8 @@ import {CompileIdentifierMetadata} from '../compile_metadata';
export class ViewClassDependency {
constructor(
public comp: CompileIdentifierMetadata, public placeholder: CompileIdentifierMetadata) {}
public comp: CompileIdentifierMetadata, public name: string,
public placeholder: CompileIdentifierMetadata) {}
}
export class ComponentFactoryDependency {
@ -20,5 +21,6 @@ export class ComponentFactoryDependency {
export class DirectiveWrapperDependency {
constructor(
public dir: CompileIdentifierMetadata, public placeholder: CompileIdentifierMetadata) {}
public dir: CompileIdentifierMetadata, public name: string,
public placeholder: CompileIdentifierMetadata) {}
}

View File

@ -9,7 +9,7 @@
import {EventHandlerVars, convertActionBinding} from '../compiler_util/expression_converter';
import {createInlineArray} from '../compiler_util/identifier_util';
import {DirectiveWrapperExpressions} from '../directive_wrapper_compiler';
import {Identifiers, resolveIdentifier} from '../identifiers';
import {Identifiers, createIdentifier} from '../identifiers';
import * as o from '../output/output_ast';
import {BoundEventAst, DirectiveAst} from '../template_parser/template_ast';
@ -56,7 +56,7 @@ function subscribeToRenderEvents(
compileElement.view.disposables.push(disposableVar);
compileElement.view.createMethod.addStmt(
disposableVar
.set(o.importExpr(resolveIdentifier(Identifiers.subscribeToRenderElement)).callFn([
.set(o.importExpr(createIdentifier(Identifiers.subscribeToRenderElement)).callFn([
o.THIS_EXPR, compileElement.renderNode, createInlineArray(eventAndTargetExprs),
handleEventExpr(compileElement)
]))

View File

@ -13,7 +13,7 @@ import {ConvertPropertyBindingResult, convertPropertyBinding} from '../compiler_
import {createEnumExpression} from '../compiler_util/identifier_util';
import {triggerAnimation, writeToRenderer} from '../compiler_util/render_util';
import {DirectiveWrapperExpressions} from '../directive_wrapper_compiler';
import {Identifiers, resolveIdentifier} from '../identifiers';
import {Identifiers, createIdentifier} from '../identifiers';
import * as o from '../output/output_ast';
import {isDefaultChangeDetectionStrategy} from '../private_import_core';
import {ElementSchemaRegistry} from '../schema/element_schema_registry';
@ -69,7 +69,7 @@ export function bindRenderInputs(
const {updateStmts, detachStmts} = triggerAnimation(
o.THIS_EXPR, o.THIS_EXPR, boundProp,
(hasEvents ? o.THIS_EXPR.prop(getHandleEventMethodName(compileElement.nodeIndex)) :
o.importExpr(resolveIdentifier(Identifiers.noop)))
o.importExpr(createIdentifier(Identifiers.noop)))
.callMethod(o.BuiltinMethod.Bind, [o.THIS_EXPR]),
compileElement.renderNode, evalResult.currValExpr, bindingField.expression);
checkBindingStmts.push(...updateStmts);

View File

@ -7,10 +7,10 @@
*/
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileTokenMetadata} from '../compile_metadata';
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileTokenMetadata, identifierName} from '../compile_metadata';
import {createDiTokenExpression} from '../compiler_util/identifier_util';
import {isPresent} from '../facade/lang';
import {Identifiers, resolveIdentifier} from '../identifiers';
import {Identifiers, createIdentifier} from '../identifiers';
import * as o from '../output/output_ast';
import {ViewType} from '../private_import_core';
@ -74,7 +74,7 @@ export function injectFromViewParentInjector(
export function getViewClassName(
component: CompileDirectiveSummary | CompileDirectiveMetadata,
embeddedTemplateIndex: number): string {
return `View_${component.type.name}${embeddedTemplateIndex}`;
return `View_${identifierName(component.type)}${embeddedTemplateIndex}`;
}
export function getHandleEventMethodName(elementIndex: number): string {

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {tokenReference} from '../compile_metadata';
import {ElementSchemaRegistry} from '../schema/element_schema_registry';
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '../template_parser/template_ast';
@ -66,7 +67,7 @@ class ViewBinderVisitor implements TemplateAstVisitor {
directiveAst, directiveWrapperInstance, compileElement);
});
ast.providers.forEach((providerAst) => {
const providerInstance = compileElement.instances.get(providerAst.token.reference);
const providerInstance = compileElement.instances.get(tokenReference(providerAst.token));
bindInjectableDestroyLifecycleCallbacks(providerAst, providerInstance, compileElement);
});
return null;
@ -89,7 +90,7 @@ class ViewBinderVisitor implements TemplateAstVisitor {
directiveAst, directiveWrapperInstance, compileElement);
});
ast.providers.forEach((providerAst) => {
const providerInstance = compileElement.instances.get(providerAst.token.reference);
const providerInstance = compileElement.instances.get(tokenReference(providerAst.token));
bindInjectableDestroyLifecycleCallbacks(providerAst, providerInstance, compileElement);
});
bindView(compileElement.embeddedView, ast.children, this._schemaRegistry);

View File

@ -8,11 +8,11 @@
import {ViewEncapsulation} from '@angular/core';
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileTokenMetadata} from '../compile_metadata';
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileTokenMetadata, identifierModuleUrl, identifierName} from '../compile_metadata';
import {createSharedBindingVariablesIfNeeded} from '../compiler_util/expression_converter';
import {createDiTokenExpression, createInlineArray} from '../compiler_util/identifier_util';
import {isPresent} from '../facade/lang';
import {Identifiers, identifierToken, resolveIdentifier} from '../identifiers';
import {Identifiers, createIdentifier, identifierToken} from '../identifiers';
import {createClassStmt} from '../output/class_builder';
import * as o from '../output/output_ast';
import {ParseSourceSpan} from '../parse_util';
@ -189,13 +189,13 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
_mergeHtmlAndDirectiveAttrs(htmlAttrs, directives).map(v => o.literal(v)));
if (nodeIndex === 0 && this.view.viewType === ViewType.HOST) {
createRenderNodeExpr =
o.importExpr(resolveIdentifier(Identifiers.selectOrCreateRenderHostElement)).callFn([
o.importExpr(createIdentifier(Identifiers.selectOrCreateRenderHostElement)).callFn([
ViewProperties.renderer, o.literal(ast.name), attrNameAndValues, rootSelectorVar,
debugContextExpr
]);
} else {
createRenderNodeExpr =
o.importExpr(resolveIdentifier(Identifiers.createRenderElement)).callFn([
o.importExpr(createIdentifier(Identifiers.createRenderElement)).callFn([
ViewProperties.renderer, this._getParentRenderNode(parent), o.literal(ast.name),
attrNameAndValues, debugContextExpr
]);
@ -210,19 +210,18 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
const compileElement = new CompileElement(
parent, this.view, nodeIndex, renderNode, ast, component, directives, ast.providers,
ast.hasViewContainer, false, ast.references, this.targetDependencies);
ast.hasViewContainer, false, ast.references);
this.view.nodes.push(compileElement);
let compViewExpr: o.ReadPropExpr = null;
if (isPresent(component)) {
const nestedComponentIdentifier =
new CompileIdentifierMetadata({name: getViewClassName(component, 0)});
this.targetDependencies.push(
new ViewClassDependency(component.type, nestedComponentIdentifier));
const nestedComponentIdentifier: CompileIdentifierMetadata = {reference: null};
this.targetDependencies.push(new ViewClassDependency(
component.type, getViewClassName(component, 0), nestedComponentIdentifier));
compViewExpr = o.THIS_EXPR.prop(`compView_${nodeIndex}`); // fix highlighting: `
this.view.fields.push(new o.ClassField(
compViewExpr.name,
o.importType(resolveIdentifier(Identifiers.AppView), [o.importType(component.type)])));
o.importType(createIdentifier(Identifiers.AppView), [o.importType(component.type)])));
this.view.viewChildren.push(compViewExpr);
compileElement.setComponentView(compViewExpr);
this.view.createMethod.addStmt(
@ -266,14 +265,14 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
const directives = ast.directives.map(directiveAst => directiveAst.directive);
const compileElement = new CompileElement(
parent, this.view, nodeIndex, renderNode, ast, null, directives, ast.providers,
ast.hasViewContainer, true, ast.references, this.targetDependencies);
ast.hasViewContainer, true, ast.references);
this.view.nodes.push(compileElement);
this.nestedViewCount++;
const embeddedView = new CompileView(
this.view.component, this.view.genConfig, this.view.pipeMetas, o.NULL_EXPR,
this.view.animations, this.view.viewIndex + this.nestedViewCount, compileElement,
templateVariableBindings);
templateVariableBindings, this.targetDependencies);
this.nestedViewCount += buildView(embeddedView, ast.children, this.targetDependencies);
compileElement.beforeChildren();
@ -372,31 +371,33 @@ function createViewTopLevelStmts(view: CompileView, targetStatements: o.Statemen
let nodeDebugInfosVar: o.Expression = o.NULL_EXPR;
if (view.genConfig.genDebugInfo) {
nodeDebugInfosVar = o.variable(
`nodeDebugInfos_${view.component.type.name}${view.viewIndex}`); // fix highlighting: `
`nodeDebugInfos_${identifierName(view.component.type)}${view.viewIndex}`); // fix
// highlighting:
// `
targetStatements.push(
(<o.ReadVarExpr>nodeDebugInfosVar)
.set(o.literalArr(
view.nodes.map(createStaticNodeDebugInfo),
new o.ArrayType(
new o.ExternalType(resolveIdentifier(Identifiers.StaticNodeDebugInfo)),
o.importType(createIdentifier(Identifiers.StaticNodeDebugInfo)),
[o.TypeModifier.Const])))
.toDeclStmt(null, [o.StmtModifier.Final]));
}
const renderCompTypeVar: o.ReadVarExpr =
o.variable(`renderType_${view.component.type.name}`); // fix highlighting: `
o.variable(`renderType_${identifierName(view.component.type)}`); // fix highlighting: `
if (view.viewIndex === 0) {
let templateUrlInfo: string;
if (view.component.template.templateUrl == view.component.type.moduleUrl) {
if (view.component.template.templateUrl == identifierModuleUrl(view.component.type)) {
templateUrlInfo =
`${view.component.type.moduleUrl} class ${view.component.type.name} - inline template`;
`${identifierModuleUrl(view.component.type)} class ${identifierName(view.component.type)} - inline template`;
} else {
templateUrlInfo = view.component.template.templateUrl;
}
targetStatements.push(
renderCompTypeVar
.set(o.importExpr(resolveIdentifier(Identifiers.createRenderComponentType)).callFn([
.set(o.importExpr(createIdentifier(Identifiers.createRenderComponentType)).callFn([
view.genConfig.genDebugInfo ? o.literal(templateUrlInfo) : o.literal(''),
o.literal(view.component.template.ngContentSelectors.length),
ViewEncapsulationEnum.fromValue(view.component.template.encapsulation),
@ -404,7 +405,7 @@ function createViewTopLevelStmts(view: CompileView, targetStatements: o.Statemen
o.literalMap(view.animations.map(
(entry): [string, o.Expression] => [entry.name, entry.fnExp])),
]))
.toDeclStmt(o.importType(resolveIdentifier(Identifiers.RenderComponentType))));
.toDeclStmt(o.importType(createIdentifier(Identifiers.RenderComponentType))));
}
const viewClass = createViewClass(view, renderCompTypeVar, nodeDebugInfosVar);
@ -427,7 +428,7 @@ function createStaticNodeDebugInfo(node: CompileNode): o.Expression {
[varName, isPresent(token) ? createDiTokenExpression(token) : o.NULL_EXPR]);
});
}
return o.importExpr(resolveIdentifier(Identifiers.StaticNodeDebugInfo))
return o.importExpr(createIdentifier(Identifiers.StaticNodeDebugInfo))
.instantiate(
[
o.literalArr(providerTokens, new o.ArrayType(o.DYNAMIC_TYPE, [o.TypeModifier.Const])),
@ -435,7 +436,7 @@ function createStaticNodeDebugInfo(node: CompileNode): o.Expression {
o.literalMap(varTokenEntries, new o.MapType(o.DYNAMIC_TYPE, [o.TypeModifier.Const]))
],
o.importType(
resolveIdentifier(Identifiers.StaticNodeDebugInfo), null, [o.TypeModifier.Const]));
createIdentifier(Identifiers.StaticNodeDebugInfo), null, [o.TypeModifier.Const]));
}
function createViewClass(
@ -443,10 +444,10 @@ function createViewClass(
nodeDebugInfosVar: o.Expression): o.ClassStmt {
const viewConstructorArgs = [
new o.FnParam(
ViewConstructorVars.viewUtils.name, o.importType(resolveIdentifier(Identifiers.ViewUtils))),
ViewConstructorVars.viewUtils.name, o.importType(createIdentifier(Identifiers.ViewUtils))),
new o.FnParam(
ViewConstructorVars.parentView.name,
o.importType(resolveIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
o.importType(createIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
new o.FnParam(ViewConstructorVars.parentIndex.name, o.NUMBER_TYPE),
new o.FnParam(ViewConstructorVars.parentElement.name, o.DYNAMIC_TYPE)
];
@ -461,14 +462,14 @@ function createViewClass(
}
if (view.viewType === ViewType.EMBEDDED) {
viewConstructorArgs.push(new o.FnParam(
'declaredViewContainer', o.importType(resolveIdentifier(Identifiers.ViewContainer))));
'declaredViewContainer', o.importType(createIdentifier(Identifiers.ViewContainer))));
superConstructorArgs.push(o.variable('declaredViewContainer'));
}
const viewMethods = [
new o.ClassMethod(
'createInternal', [new o.FnParam(rootSelectorVar.name, o.STRING_TYPE)],
generateCreateMethod(view),
o.importType(resolveIdentifier(Identifiers.ComponentRef), [o.DYNAMIC_TYPE])),
o.importType(createIdentifier(Identifiers.ComponentRef), [o.DYNAMIC_TYPE])),
new o.ClassMethod(
'injectorGetInternal',
[
@ -492,7 +493,7 @@ function createViewClass(
const viewClass = createClassStmt({
name: view.className,
parent: o.importExpr(resolveIdentifier(superClass), [getContextType(view)]),
parent: o.importExpr(createIdentifier(superClass), [getContextType(view)]),
parentArgs: superConstructorArgs,
ctorParams: viewConstructorArgs,
builders: [{methods: viewMethods}, view]
@ -526,7 +527,7 @@ function generateCreateMethod(view: CompileView): o.Statement[] {
if (view.viewType === ViewType.HOST) {
const hostEl = <CompileElement>view.nodes[0];
resultExpr =
o.importExpr(resolveIdentifier(Identifiers.ComponentRef_), [o.DYNAMIC_TYPE]).instantiate([
o.importExpr(createIdentifier(Identifiers.ComponentRef_), [o.DYNAMIC_TYPE]).instantiate([
o.literal(hostEl.nodeIndex), o.THIS_EXPR, hostEl.renderNode, hostEl.getComponent()
]);
} else {
@ -591,7 +592,7 @@ function generateDetectChangesMethod(view: CompileView): o.Statement[] {
if (readVars.has(DetectChangesVars.changes.name)) {
varStmts.push(
DetectChangesVars.changes.set(o.NULL_EXPR)
.toDeclStmt(new o.MapType(o.importType(resolveIdentifier(Identifiers.SimpleChange)))));
.toDeclStmt(new o.MapType(o.importType(createIdentifier(Identifiers.SimpleChange)))));
}
varStmts.push(...createSharedBindingVariablesIfNeeded(stmts));
return varStmts.concat(stmts);
@ -703,5 +704,5 @@ function generateCreateEmbeddedViewsMethod(view: CompileView): o.ClassMethod {
}
return new o.ClassMethod(
'createEmbeddedViewInternal', [new o.FnParam(nodeIndexVar.name, o.NUMBER_TYPE)], stmts,
o.importType(resolveIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE]));
o.importType(createIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE]));
}

View File

@ -42,7 +42,7 @@ export class ViewCompiler {
Array<ViewClassDependency|ComponentFactoryDependency|DirectiveWrapperDependency> = [];
const view = new CompileView(
component, this._genConfig, pipes, styles, compiledAnimations, 0,
CompileElement.createNull(), []);
CompileElement.createNull(), [], dependencies);
const statements: o.Statement[] = [];
buildView(view, template, dependencies);

View File

@ -10,7 +10,7 @@ import {AnimationMetadata, animate, sequence, style, transition, trigger} from '
import {beforeEach, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
import {AnimationCompiler, AnimationEntryCompileResult} from '../../src/animation/animation_compiler';
import {AnimationParser} from '../../src/animation/animation_parser';
import {CompileAnimationEntryMetadata, CompileDirectiveMetadata, CompileTemplateMetadata, CompileTypeMetadata} from '../../src/compile_metadata';
import {CompileAnimationEntryMetadata, CompileDirectiveMetadata, CompileTemplateMetadata, CompileTypeMetadata, identifierName} from '../../src/compile_metadata';
import {CompileMetadataResolver} from '../../src/metadata_resolver';
import {ElementSchemaRegistry} from '../../src/schema/element_schema_registry';
@ -30,7 +30,7 @@ export function main() {
const compileAnimations =
(component: CompileDirectiveMetadata): AnimationEntryCompileResult[] => {
const parsedAnimations = parser.parseComponent(component);
return compiler.compile(component.type.name, parsedAnimations);
return compiler.compile(identifierName(component.type), parsedAnimations);
};
const compileTriggers = (input: any[]) => {
@ -40,7 +40,7 @@ export function main() {
});
const component = CompileDirectiveMetadata.create({
type: new CompileTypeMetadata({name: 'myCmp'}),
type: {reference: {name: 'myCmp', filePath: ''}, diDeps: [], lifecycleHooks: []},
template: new CompileTemplateMetadata({animations: entries})
});

View File

@ -21,10 +21,14 @@ describe('StaticReflector', () => {
let host: StaticReflectorHost;
let reflector: StaticReflector;
beforeEach(() => {
host = new MockStaticReflectorHost();
reflector = new StaticReflector(host);
});
function init(
testData: {[key: string]: any} = DEFAULT_TEST_DATA,
decorators: {name: string, filePath: string, ctor: any}[] = []) {
host = new MockStaticReflectorHost(testData);
reflector = new StaticReflector(host, undefined, decorators);
}
beforeEach(() => init());
function simplify(context: StaticSymbol, value: any) {
return reflector.simplify(context, value);
@ -446,6 +450,17 @@ describe('StaticReflector', () => {
]);
});
it('should be able to get metadata for a class with nested method calls', () => {
const annotations = reflector.annotations(
reflector.getStaticSymbol('/tmp/src/static-method-call.ts', 'MyFactoryComponent'));
expect(annotations.length).toBe(1);
expect(annotations[0].providers).toEqual({
provide: 'c',
useFactory:
reflector.getStaticSymbol('/tmp/src/static-method.ts', 'AnotherModule', ['someFactory'])
});
});
it('should be able to get the metadata for a class calling a method with default parameters',
() => {
const annotations = reflector.annotations(
@ -517,11 +532,173 @@ describe('StaticReflector', () => {
expect(symbol.filePath).toEqual('/tmp/src/reexport/src/origin1.d.ts');
});
describe('inheritance', () => {
class ClassDecorator {
constructor(public value: any) {}
}
class ParamDecorator {
constructor(public value: any) {}
}
class PropDecorator {
constructor(public value: any) {}
}
function initWithDecorator(testData: {[key: string]: any}) {
testData['/tmp/src/decorator.ts'] = `
export function ClassDecorator(): any {}
export function ParamDecorator(): any {}
export function PropDecorator(): any {}
`;
init(testData, [
{filePath: '/tmp/src/decorator.ts', name: 'ClassDecorator', ctor: ClassDecorator},
{filePath: '/tmp/src/decorator.ts', name: 'ParamDecorator', ctor: ParamDecorator},
{filePath: '/tmp/src/decorator.ts', name: 'PropDecorator', ctor: PropDecorator}
]);
}
it('should inherit annotations', () => {
initWithDecorator({
'/tmp/src/main.ts': `
import {ClassDecorator} from './decorator';
@ClassDecorator('parent')
export class Parent {}
@ClassDecorator('child')
export class Child extends Parent {}
export class ChildNoDecorators extends Parent {}
`
});
// Check that metadata for Parent was not changed!
expect(reflector.annotations(reflector.getStaticSymbol('/tmp/src/main.ts', 'Parent')))
.toEqual([new ClassDecorator('parent')]);
expect(reflector.annotations(reflector.getStaticSymbol('/tmp/src/main.ts', 'Child')))
.toEqual([new ClassDecorator('parent'), new ClassDecorator('child')]);
expect(
reflector.annotations(reflector.getStaticSymbol('/tmp/src/main.ts', 'ChildNoDecorators')))
.toEqual([new ClassDecorator('parent')]);
});
it('should inherit parameters', () => {
initWithDecorator({
'/tmp/src/main.ts': `
import {ParamDecorator} from './decorator';
export class A {}
export class B {}
export class C {}
export class Parent {
constructor(@ParamDecorator('a') a: A, @ParamDecorator('b') b: B) {}
}
export class Child extends Parent {}
export class ChildWithCtor extends Parent {
constructor(@ParamDecorator('c') c: C) {}
}
`
});
// Check that metadata for Parent was not changed!
expect(reflector.parameters(reflector.getStaticSymbol('/tmp/src/main.ts', 'Parent')))
.toEqual([
[reflector.getStaticSymbol('/tmp/src/main.ts', 'A'), new ParamDecorator('a')],
[reflector.getStaticSymbol('/tmp/src/main.ts', 'B'), new ParamDecorator('b')]
]);
expect(reflector.parameters(reflector.getStaticSymbol('/tmp/src/main.ts', 'Child'))).toEqual([
[reflector.getStaticSymbol('/tmp/src/main.ts', 'A'), new ParamDecorator('a')],
[reflector.getStaticSymbol('/tmp/src/main.ts', 'B'), new ParamDecorator('b')]
]);
expect(reflector.parameters(reflector.getStaticSymbol('/tmp/src/main.ts', 'ChildWithCtor')))
.toEqual([[reflector.getStaticSymbol('/tmp/src/main.ts', 'C'), new ParamDecorator('c')]]);
});
it('should inherit property metadata', () => {
initWithDecorator({
'/tmp/src/main.ts': `
import {PropDecorator} from './decorator';
export class A {}
export class B {}
export class C {}
export class Parent {
@PropDecorator('a')
a: A;
@PropDecorator('b1')
b: B;
}
export class Child extends Parent {
@PropDecorator('b2')
b: B;
@PropDecorator('c')
c: C;
}
`
});
// Check that metadata for Parent was not changed!
expect(reflector.propMetadata(reflector.getStaticSymbol('/tmp/src/main.ts', 'Parent')))
.toEqual({
'a': [new PropDecorator('a')],
'b': [new PropDecorator('b1')],
});
expect(reflector.propMetadata(reflector.getStaticSymbol('/tmp/src/main.ts', 'Child')))
.toEqual({
'a': [new PropDecorator('a')],
'b': [new PropDecorator('b1'), new PropDecorator('b2')],
'c': [new PropDecorator('c')]
});
});
it('should inherit lifecycle hooks', () => {
initWithDecorator({
'/tmp/src/main.ts': `
export class Parent {
hook1() {}
hook2() {}
}
export class Child extends Parent {
hook2() {}
hook3() {}
}
`
});
function hooks(symbol: StaticSymbol, names: string[]): boolean[] {
return names.map(name => reflector.hasLifecycleHook(symbol, name));
}
// Check that metadata for Parent was not changed!
expect(hooks(reflector.getStaticSymbol('/tmp/src/main.ts', 'Parent'), [
'hook1', 'hook2', 'hook3'
])).toEqual([true, true, false]);
expect(hooks(reflector.getStaticSymbol('/tmp/src/main.ts', 'Child'), [
'hook1', 'hook2', 'hook3'
])).toEqual([true, true, true]);
});
});
});
class MockStaticReflectorHost implements StaticReflectorHost {
private collector = new MetadataCollector();
constructor(private data: {[key: string]: any}) {}
// In tests, assume that symbols are not re-exported
moduleNameToFileName(modulePath: string, containingFile?: string): string {
function splitPath(path: string): string[] { return path.split(/\/|\\/g); }
@ -568,7 +745,28 @@ class MockStaticReflectorHost implements StaticReflectorHost {
getMetadataFor(moduleId: string): any { return this._getMetadataFor(moduleId); }
private _getMetadataFor(moduleId: string): any {
const data: {[key: string]: any} = {
if (this.data[moduleId] && moduleId.match(TS_EXT)) {
const text = this.data[moduleId];
if (typeof text === 'string') {
const sf = ts.createSourceFile(
moduleId, this.data[moduleId], ts.ScriptTarget.ES5, /* setParentNodes */ true);
const diagnostics: ts.Diagnostic[] = (<any>sf).parseDiagnostics;
if (diagnostics && diagnostics.length) {
throw Error(`Error encountered during parse of file ${moduleId}`);
}
return [this.collector.getMetadata(sf)];
}
}
const result = this.data[moduleId];
if (result) {
return Array.isArray(result) ? result : [result];
} else {
return null;
}
}
}
const DEFAULT_TEST_DATA: {[key: string]: any} = {
'/tmp/@angular/common/src/forms-deprecated/directives.d.ts': [{
'__symbolic': 'module',
'version': 2,
@ -1044,6 +1242,15 @@ class MockStaticReflectorHost implements StaticReflectorHost {
static defaultsMethod(a, b = true, c = false) {
return [a, b, c];
}
static withFactory() {
return { provide: 'c', useFactory: AnotherModule.someFactory };
}
}
export class AnotherModule {
static someFactory() {
return 'e';
}
}
`,
'/tmp/src/static-method-call.ts': `
@ -1064,6 +1271,11 @@ class MockStaticReflectorHost implements StaticReflectorHost {
providers: [MyModule.defaultsMethod('a')]
})
export class MyDefaultsComponent { }
@Component({
providers: MyModule.withFactory()
})
export class MyFactoryComponent { }
`,
'/tmp/src/static-field.ts': `
import {Injectable} from '@angular/core';
@ -1162,25 +1374,3 @@ class MockStaticReflectorHost implements StaticReflectorHost {
exports: [{from: './originNone'}, {from: './origin30'}]
}
};
if (data[moduleId] && moduleId.match(TS_EXT)) {
const text = data[moduleId];
if (typeof text === 'string') {
const sf = ts.createSourceFile(
moduleId, data[moduleId], ts.ScriptTarget.ES5, /* setParentNodes */ true);
const diagnostics: ts.Diagnostic[] = (<any>sf).parseDiagnostics;
if (diagnostics && diagnostics.length) {
throw Error(`Error encountered during parse of file ${moduleId}`);
}
return [this.collector.getMetadata(sf)];
}
}
const result = data[moduleId];
if (result) {
return Array.isArray(result) ? result : [result];
} else {
return null;
}
}
}

View File

@ -7,7 +7,7 @@
*/
import {createInlineArray} from '../../src/compiler_util/identifier_util';
import {Identifiers, resolveIdentifier} from '../../src/identifiers';
import {Identifiers, createIdentifier} from '../../src/identifiers';
import * as o from '../../src/output/output_ast';
export function main() {
@ -16,7 +16,7 @@ export function main() {
function check(argCount: number, expectedIdentifier: any) {
const args = createArgs(argCount);
expect(createInlineArray(args))
.toEqual(o.importExpr(resolveIdentifier(expectedIdentifier)).instantiate([
.toEqual(o.importExpr(createIdentifier(expectedIdentifier)).instantiate([
<o.Expression>o.literal(argCount)
].concat(args)));
}
@ -31,7 +31,7 @@ export function main() {
it('should work for arrays of length 0', () => {
expect(createInlineArray([
])).toEqual(o.importExpr(resolveIdentifier(Identifiers.EMPTY_INLINE_ARRAY)));
])).toEqual(o.importExpr(createIdentifier(Identifiers.EMPTY_INLINE_ARRAY)));
});
it('should work for arrays of length 1 - 2', () => {

View File

@ -8,15 +8,12 @@
import {DirectiveResolver} from '@angular/compiler/src/directive_resolver';
import {Component, ContentChild, ContentChildren, Directive, HostBinding, HostListener, Input, Output, ViewChild, ViewChildren} from '@angular/core/src/metadata';
import {reflector} from '@angular/core/src/reflection/reflection';
@Directive({selector: 'someDirective'})
class SomeDirective {
}
@Directive({selector: 'someChildDirective'})
class SomeChildDirective extends SomeDirective {
}
@Directive({selector: 'someDirective', inputs: ['c']})
class SomeDirectiveWithInputs {
@Input() a: any;
@ -31,28 +28,6 @@ class SomeDirectiveWithOutputs {
c: any;
}
@Directive({selector: 'someDirective', outputs: ['a']})
class SomeDirectiveWithDuplicateOutputs {
@Output() a: any;
}
@Directive({selector: 'someDirective', outputs: ['localA: a']})
class SomeDirectiveWithDuplicateRenamedOutputs {
@Output() a: any;
localA: any;
}
@Directive({selector: 'someDirective', inputs: ['a']})
class SomeDirectiveWithDuplicateInputs {
@Input() a: any;
}
@Directive({selector: 'someDirective', inputs: ['localA: a']})
class SomeDirectiveWithDuplicateRenamedInputs {
@Input() a: any;
localA: any;
}
@Directive({selector: 'someDirective'})
class SomeDirectiveWithSetterProps {
@Input('renamed')
@ -150,11 +125,22 @@ export function main() {
}).toThrowError('No Directive annotation found on SomeDirectiveWithoutMetadata');
});
it('should not read parent class Directive metadata', function() {
const directiveMetadata = resolver.resolve(SomeChildDirective);
expect(directiveMetadata)
.toEqual(new Directive(
{selector: 'someChildDirective', inputs: [], outputs: [], host: {}, queries: {}}));
it('should support inheriting the Directive metadata', function() {
@Directive({selector: 'p'})
class Parent {
}
class ChildNoDecorator extends Parent {}
@Directive({selector: 'c'})
class ChildWithDecorator extends Parent {
}
expect(resolver.resolve(ChildNoDecorator))
.toEqual(new Directive({selector: 'p', inputs: [], outputs: [], host: {}, queries: {}}));
expect(resolver.resolve(ChildWithDecorator))
.toEqual(new Directive({selector: 'c', inputs: [], outputs: [], host: {}, queries: {}}));
});
describe('inputs', () => {
@ -168,16 +154,52 @@ export function main() {
expect(directiveMetadata.inputs).toEqual(['a: renamed']);
});
it('should throw if duplicate inputs', () => {
expect(() => {
resolver.resolve(SomeDirectiveWithDuplicateInputs);
}).toThrowError(`Input 'a' defined multiple times in 'SomeDirectiveWithDuplicateInputs'`);
it('should remove duplicate inputs', () => {
@Directive({selector: 'someDirective', inputs: ['a', 'a']})
class SomeDirectiveWithDuplicateInputs {
}
const directiveMetadata = resolver.resolve(SomeDirectiveWithDuplicateInputs);
expect(directiveMetadata.inputs).toEqual(['a']);
});
it('should throw if duplicate inputs (with rename)', () => {
expect(() => { resolver.resolve(SomeDirectiveWithDuplicateRenamedInputs); })
.toThrowError(
`Input 'a' defined multiple times in 'SomeDirectiveWithDuplicateRenamedInputs'`);
it('should use the last input if duplicate inputs (with rename)', () => {
@Directive({selector: 'someDirective', inputs: ['a', 'localA: a']})
class SomeDirectiveWithDuplicateInputs {
}
const directiveMetadata = resolver.resolve(SomeDirectiveWithDuplicateInputs);
expect(directiveMetadata.inputs).toEqual(['localA: a']);
});
it('should prefer @Input over @Directive.inputs', () => {
@Directive({selector: 'someDirective', inputs: ['a']})
class SomeDirectiveWithDuplicateInputs {
@Input('a')
propA: any;
}
const directiveMetadata = resolver.resolve(SomeDirectiveWithDuplicateInputs);
expect(directiveMetadata.inputs).toEqual(['propA: a']);
});
it('should support inheriting inputs', () => {
@Directive({selector: 'p'})
class Parent {
@Input()
p1: any;
@Input('p21')
p2: any;
}
class Child extends Parent {
@Input('p22')
p2: any;
@Input()
p3: any;
}
const directiveMetadata = resolver.resolve(Child);
expect(directiveMetadata.inputs).toEqual(['p1', 'p2: p22', 'p3']);
});
});
@ -192,16 +214,52 @@ export function main() {
expect(directiveMetadata.outputs).toEqual(['a: renamed']);
});
it('should throw if duplicate outputs', () => {
expect(() => { resolver.resolve(SomeDirectiveWithDuplicateOutputs); })
.toThrowError(
`Output event 'a' defined multiple times in 'SomeDirectiveWithDuplicateOutputs'`);
it('should remove duplicate outputs', () => {
@Directive({selector: 'someDirective', outputs: ['a', 'a']})
class SomeDirectiveWithDuplicateOutputs {
}
const directiveMetadata = resolver.resolve(SomeDirectiveWithDuplicateOutputs);
expect(directiveMetadata.outputs).toEqual(['a']);
});
it('should throw if duplicate outputs (with rename)', () => {
expect(() => { resolver.resolve(SomeDirectiveWithDuplicateRenamedOutputs); })
.toThrowError(
`Output event 'a' defined multiple times in 'SomeDirectiveWithDuplicateRenamedOutputs'`);
it('should use the last output if duplicate outputs (with rename)', () => {
@Directive({selector: 'someDirective', outputs: ['a', 'localA: a']})
class SomeDirectiveWithDuplicateOutputs {
}
const directiveMetadata = resolver.resolve(SomeDirectiveWithDuplicateOutputs);
expect(directiveMetadata.outputs).toEqual(['localA: a']);
});
it('should prefer @Output over @Directive.outputs', () => {
@Directive({selector: 'someDirective', outputs: ['a']})
class SomeDirectiveWithDuplicateOutputs {
@Output('a')
propA: any;
}
const directiveMetadata = resolver.resolve(SomeDirectiveWithDuplicateOutputs);
expect(directiveMetadata.outputs).toEqual(['propA: a']);
});
it('should support inheriting outputs', () => {
@Directive({selector: 'p'})
class Parent {
@Output()
p1: any;
@Output('p21')
p2: any;
}
class Child extends Parent {
@Output('p22')
p2: any;
@Output()
p3: any;
}
const directiveMetadata = resolver.resolve(Child);
expect(directiveMetadata.outputs).toEqual(['p1', 'p2: p22', 'p3']);
});
});
@ -233,6 +291,46 @@ export function main() {
.toThrowError(
`@HostBinding parameter should be a property name, 'class.<name>', or 'attr.<name>'.`);
});
it('should support inheriting host bindings', () => {
@Directive({selector: 'p'})
class Parent {
@HostBinding()
p1: any;
@HostBinding('p21')
p2: any;
}
class Child extends Parent {
@HostBinding('p22')
p2: any;
@HostBinding()
p3: any;
}
const directiveMetadata = resolver.resolve(Child);
expect(directiveMetadata.host).toEqual({'[p1]': 'p1', '[p22]': 'p2', '[p3]': 'p3'});
});
it('should support inheriting host listeners', () => {
@Directive({selector: 'p'})
class Parent {
@HostListener('p1')
p1() {}
@HostListener('p21')
p2() {}
}
class Child extends Parent {
@HostListener('p22')
p2() {}
@HostListener('p3')
p3() {}
}
const directiveMetadata = resolver.resolve(Child);
expect(directiveMetadata.host).toEqual({'(p1)': 'p1()', '(p22)': 'p2()', '(p3)': 'p3()'});
});
});
describe('queries', () => {
@ -259,6 +357,30 @@ export function main() {
expect(directiveMetadata.queries)
.toEqual({'c': new ViewChild('c'), 'a': new ViewChild('a')});
});
it('should support inheriting queries', () => {
@Directive({selector: 'p'})
class Parent {
@ContentChild('p1')
p1: any;
@ContentChild('p21')
p2: any;
}
class Child extends Parent {
@ContentChild('p22')
p2: any;
@ContentChild('p3')
p3: any;
}
const directiveMetadata = resolver.resolve(Child);
expect(directiveMetadata.queries).toEqual({
'p1': new ContentChild('p1'),
'p2': new ContentChild('p22'),
'p3': new ContentChild('p3')
});
});
});
describe('Component', () => {

View File

@ -11,6 +11,7 @@ import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit,
import {LIFECYCLE_HOOKS_VALUES} from '@angular/core/src/metadata/lifecycle_hooks';
import {TestBed, async, inject} from '@angular/core/testing';
import {identifierName} from '../src/compile_metadata';
import {stringify} from '../src/facade/lang';
import {CompileMetadataResolver} from '../src/metadata_resolver';
import {ResourceLoader} from '../src/resource_loader';
@ -50,7 +51,7 @@ export function main() {
expect(meta.exportAs).toEqual('someExportAs');
expect(meta.isComponent).toBe(true);
expect(meta.type.reference).toBe(ComponentWithEverythingInline);
expect(meta.type.name).toEqual(stringify(ComponentWithEverythingInline));
expect(identifierName(meta.type)).toEqual(stringify(ComponentWithEverythingInline));
expect(meta.type.lifecycleHooks).toEqual(LIFECYCLE_HOOKS_VALUES);
expect(meta.changeDetection).toBe(ChangeDetectionStrategy.Default);
expect(meta.inputs).toEqual({'someProp': 'someProp'});
@ -114,18 +115,24 @@ export function main() {
resourceLoader.flush();
})));
it('should use the moduleUrl from the reflector if none is given',
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
it('should use `./` as base url for templates during runtime compilation if no moduleId is given',
async(inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
@Component({selector: 'someComponent', templateUrl: 'someUrl'})
class ComponentWithoutModuleId {
}
@NgModule({declarations: [ComponentWithoutModuleId]})
class SomeModule {
}
resolver.loadNgModuleMetadata(SomeModule, true);
const value: string =
resolver.getDirectiveMetadata(ComponentWithoutModuleId).type.moduleUrl;
const expectedEndValue = './ComponentWithoutModuleId';
expect(value.endsWith(expectedEndValue)).toBe(true);
}));
resolver.loadNgModuleMetadata(SomeModule, false).loading.then(() => {
const value: string =
resolver.getDirectiveMetadata(ComponentWithoutModuleId).template.templateUrl;
const expectedEndValue = './someUrl';
expect(value.endsWith(expectedEndValue)).toBe(true);
});
})));
it('should throw when the moduleId is not a string',
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {

View File

@ -45,9 +45,26 @@ export function main() {
}));
});
it('should throw when simple class has no component decorator', () => {
it('should throw when simple class has no NgModule decorator', () => {
expect(() => resolver.resolve(SimpleClass))
.toThrowError(`No NgModule metadata found for '${stringify(SimpleClass)}'.`);
});
it('should support inheriting the metadata', function() {
@NgModule({id: 'p'})
class Parent {
}
class ChildNoDecorator extends Parent {}
@NgModule({id: 'c'})
class ChildWithDecorator extends Parent {
}
expect(resolver.resolve(ChildNoDecorator)).toEqual(new NgModule({id: 'p'}));
expect(resolver.resolve(ChildWithDecorator)).toEqual(new NgModule({id: 'c'}));
});
});
}

View File

@ -9,18 +9,23 @@
import {CompileIdentifierMetadata} from '@angular/compiler/src/compile_metadata';
import {JavaScriptEmitter} from '@angular/compiler/src/output/js_emitter';
import * as o from '@angular/compiler/src/output/output_ast';
import {beforeEach, describe, expect, it} from '@angular/core/testing/testing_internal';
import {SimpleJsImportGenerator} from './output_emitter_util';
import {ImportResolver} from '@angular/compiler/src/output/path_util';
const someModuleUrl = 'somePackage/somePath';
const anotherModuleUrl = 'somePackage/someOtherPath';
const sameModuleIdentifier =
new CompileIdentifierMetadata({name: 'someLocalId', moduleUrl: someModuleUrl});
const sameModuleIdentifier: CompileIdentifierMetadata = {
reference: {name: 'someLocalId', filePath: someModuleUrl}
};
const externalModuleIdentifier: CompileIdentifierMetadata = {
reference: {name: 'someExternalId', filePath: anotherModuleUrl}
};
const externalModuleIdentifier =
new CompileIdentifierMetadata({name: 'someExternalId', moduleUrl: anotherModuleUrl});
class SimpleJsImportGenerator implements ImportResolver {
fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string {
return importedUrlStr;
}
}
export function main() {
// Note supported features of our OutputAstin JavaScript / ES5:

View File

@ -1,38 +0,0 @@
/**
* @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
*/
// ATTENTION: This file will be overwritten with generated code by main()
import {TypeScriptEmitter} from '@angular/compiler/src/output/ts_emitter';
import {print} from '../../src/facade/lang';
import {assetUrl} from '../../src/identifiers';
function unimplemented(): any {
throw new Error('unimplemented');
}
import {SimpleJsImportGenerator, codegenExportsVars, codegenStmts} from './output_emitter_util';
export function getExpressions(): any {
return unimplemented();
}
// Generator
export function emit() {
const emitter = new TypeScriptEmitter(new SimpleJsImportGenerator());
const emittedCode = emitter.emitStatements(
assetUrl('compiler', 'output/output_emitter_codegen_typed', 'test'), codegenStmts,
codegenExportsVars);
return emittedCode;
}
export function main(args: string[]) {
const emittedCode = emit();
print(emittedCode);
}

View File

@ -1,34 +0,0 @@
/**
* @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
*/
// ATTENTION: This file will be overwritten with generated code by main()
import {JavaScriptEmitter} from '@angular/compiler/src/output/js_emitter';
import {print} from '../../src/facade/lang';
import {assetUrl} from '../../src/identifiers';
import {SimpleJsImportGenerator, codegenExportsVars, codegenStmts} from './output_emitter_util';
export function getExpressions(): any {
throw new Error('unimplemented');
}
// Generator
export function emit() {
const emitter = new JavaScriptEmitter(new SimpleJsImportGenerator());
const emittedCode = emitter.emitStatements(
assetUrl('compiler', 'output/output_emitter_codegen_untyped', 'test'), codegenStmts,
codegenExportsVars);
return emittedCode;
}
export function main(args: string[]) {
const emittedCode = emit();
// debug: console.error(emittedCode);
print(emittedCode);
}

View File

@ -1,197 +0,0 @@
/**
* @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
*/
import {interpretStatements} from '@angular/compiler/src/output/output_interpreter';
import {jitStatements} from '@angular/compiler/src/output/output_jit';
import {EventEmitter} from '@angular/core';
import {ViewType} from '@angular/core/src/linker/view_type';
import {beforeEach, describe, it} from '@angular/core/testing/testing_internal';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {browserDetection} from '@angular/platform-browser/testing/browser_util';
import {expect} from '@angular/platform-browser/testing/matchers';
import * as typed from './output_emitter_codegen_typed';
import * as untyped from './output_emitter_codegen_untyped';
import {ExternalClass, codegenStmts} from './output_emitter_util';
export function main() {
const outputDefs: any[] /** TODO #9100 */ = [];
outputDefs.push({
'getExpressions': () => interpretStatements(codegenStmts, 'getExpressions'),
'name': 'interpreted'
});
if (!getDOM().supportsDOMEvents()) {
// Our generator only works on node.js
outputDefs.push({'getExpressions': () => typed.getExpressions, 'name': 'typed'});
} else {
// Our generator only works on node.js
if (!getDOM().supportsDOMEvents()) {
outputDefs.push({'getExpressions': () => untyped.getExpressions, 'name': 'untyped'});
}
outputDefs.push({
'getExpressions': () => jitStatements('output_emitter_spec', codegenStmts, 'getExpressions'),
'name': 'jit'
});
}
describe('output emitter', () => {
outputDefs.forEach((outputDef) => {
describe(`${outputDef['name']}`, () => {
let expressions: {[k: string]: any};
beforeEach(() => { expressions = outputDef['getExpressions']()(); });
it('should support literals', () => {
expect(expressions['stringLiteral']).toEqual('Hello World!');
expect(expressions['intLiteral']).toEqual(42);
expect(expressions['boolLiteral']).toEqual(true);
expect(expressions['arrayLiteral']).toEqual([0]);
expect(expressions['mapLiteral']).toEqual({'key0': 0});
});
it('should support reading vars/keys/props', () => {
expect(expressions['readVar']).toEqual('someValue');
expect(expressions['readKey']).toEqual('someValue');
expect(expressions['readPropExternalInstance']).toEqual('someValue');
expect(expressions['readPropDynamicInstance']).toEqual('dynamicValue');
expect(expressions['readGetterDynamicInstance'])
.toEqual({'data': 'someValue', 'dynamicProp': 'dynamicValue'});
});
it('should support writing to vars / keys / props', () => {
expect(expressions['changedVar']).toEqual('changedValue');
expect(expressions['changedKey']).toEqual('changedValue');
expect(expressions['changedPropExternalInstance']).toEqual('changedValue');
expect(expressions['changedPropDynamicInstance']).toEqual('changedValue');
});
it('should support declaring functions with parameters and return', () => {
expect(expressions['fn']('someParam')).toEqual({'param': 'someParam'});
expect(expressions['closureInDynamicInstance']('someParam'))
.toEqual({'param': 'someParam', 'data': 'someValue', 'dynamicProp': 'dynamicValue'});
});
it('should support invoking functions and methods', () => {
expect(expressions['invokeFn']).toEqual({'param': 'someParam'});
expect(expressions['concatedArray']).toEqual([0, 1]);
expect(expressions['invokeMethodExternalInstance'])
.toEqual({'data': 'someValue', 'param': 'someParam'});
expect(expressions['invokeMethodExternalInstanceViaBind'])
.toEqual({'data': 'someValue', 'param': 'someParam'});
expect(expressions['invokeMethodDynamicInstance'])
.toEqual({'data': 'someValue', 'dynamicProp': 'dynamicValue', 'param': 'someParam'});
expect(expressions['invokeMethodDynamicInstanceViaBind'])
.toEqual({'data': 'someValue', 'dynamicProp': 'dynamicValue', 'param': 'someParam'});
});
it('should support conditionals', () => {
expect(expressions['conditionalTrue']).toEqual('true');
expect(expressions['conditionalFalse']).toEqual('false');
});
it('should support not', () => { expect(expressions['not']).toEqual(true); });
it('should support reading external identifiers', () => {
expect(expressions['externalTestIdentifier']).toBe(ExternalClass);
expect(expressions['externalSrcIdentifier']).toBe(EventEmitter);
expect(expressions['externalEnumIdentifier']).toBe(ViewType.HOST);
});
it('should support instantiating classes', () => {
expect(expressions['externalInstance']).toBeAnInstanceOf(ExternalClass);
// Note: toBeAnInstanceOf does not check super classes in Dart...
expect(expressions['dynamicInstance'] instanceof ExternalClass).toBe(true);
});
describe('operators', () => {
let ops: {[k: string]: Function};
let aObj: any;
let bObj: any;
beforeEach(() => {
ops = expressions['operators'];
aObj = {};
bObj = {};
});
it('should support ==', () => {
expect(ops['=='](aObj, aObj)).toBe(true);
expect(ops['=='](aObj, bObj)).toBe(false);
expect(ops['=='](1, 1)).toBe(true);
expect(ops['=='](0, 1)).toBe(false);
expect(ops['==']('a', 'a')).toBe(true);
expect(ops['==']('a', 'b')).toBe(false);
});
it('should support !=', () => {
expect(ops['!='](aObj, aObj)).toBe(false);
expect(ops['!='](aObj, bObj)).toBe(true);
expect(ops['!='](1, 1)).toBe(false);
expect(ops['!='](0, 1)).toBe(true);
expect(ops['!=']('a', 'a')).toBe(false);
expect(ops['!=']('a', 'b')).toBe(true);
});
it('should support ===', () => {
expect(ops['==='](aObj, aObj)).toBe(true);
expect(ops['==='](aObj, bObj)).toBe(false);
expect(ops['==='](1, 1)).toBe(true);
expect(ops['==='](0, 1)).toBe(false);
});
it('should support !==', () => {
expect(ops['!=='](aObj, aObj)).toBe(false);
expect(ops['!=='](aObj, bObj)).toBe(true);
expect(ops['!=='](1, 1)).toBe(false);
expect(ops['!=='](0, 1)).toBe(true);
});
it('should support -', () => { expect(ops['-'](3, 2)).toEqual(1); });
it('should support +', () => { expect(ops['+'](1, 2)).toEqual(3); });
it('should support /', () => { expect(ops['/'](6, 2)).toEqual(3); });
it('should support *', () => { expect(ops['*'](2, 3)).toEqual(6); });
it('should support %', () => { expect(ops['%'](3, 2)).toEqual(1); });
it('should support &&', () => {
expect(ops['&&'](true, true)).toBe(true);
expect(ops['&&'](true, false)).toBe(false);
});
it('should support ||', () => {
expect(ops['||'](true, false)).toBe(true);
expect(ops['||'](false, false)).toBe(false);
});
it('should support <', () => {
expect(ops['<'](1, 2)).toBe(true);
expect(ops['<'](1, 1)).toBe(false);
});
it('should support <=', () => {
expect(ops['<='](1, 2)).toBe(true);
expect(ops['<='](1, 1)).toBe(true);
});
it('should support >', () => {
expect(ops['>'](2, 1)).toBe(true);
expect(ops['>'](1, 1)).toBe(false);
});
it('should support >=', () => {
expect(ops['>='](2, 1)).toBe(true);
expect(ops['>='](1, 1)).toBe(true);
});
});
it('should support throwing errors',
() => { expect(expressions['throwError']).toThrowError('someError'); });
it('should support catching errors', () => {
function someOperation() { throw new Error('Boom!'); }
const errorAndStack = expressions['catchError'](someOperation);
expect(errorAndStack[0].message).toEqual('Boom!');
// Somehow we don't get stacktraces on ios7...
if (!browserDetection.isIOS7 && !browserDetection.isIE) {
expect(errorAndStack[1].toString()).toContain('someOperation');
}
});
});
});
});
}

View File

@ -7,7 +7,7 @@
*/
import {CompileIdentifierMetadata} from '@angular/compiler/src/compile_metadata';
import {assetUrl} from '@angular/compiler/src/identifiers';
import {assetUrl, createIdentifier} from '@angular/compiler/src/identifiers';
import * as o from '@angular/compiler/src/output/output_ast';
import {ImportResolver} from '@angular/compiler/src/output/path_util';
import {EventEmitter} from '@angular/core';
@ -20,23 +20,29 @@ export class ExternalClass {
someMethod(a: any /** TODO #9100 */) { return {'param': a, 'data': this.data}; }
}
const testDataIdentifier = new CompileIdentifierMetadata({
const testDataIdentifier = {
name: 'ExternalClass',
moduleUrl: `@angular/compiler/test/output/output_emitter_util`,
reference: ExternalClass
});
runtime: ExternalClass
};
const eventEmitterIdentifier = new CompileIdentifierMetadata(
{name: 'EventEmitter', moduleUrl: assetUrl('core'), reference: EventEmitter});
const eventEmitterIdentifier = {
name: 'EventEmitter',
moduleUrl: assetUrl('core'),
runtime: EventEmitter
};
const enumIdentifier = new CompileIdentifierMetadata({
const enumIdentifier = {
name: 'ViewType.HOST',
moduleUrl: assetUrl('core', 'linker/view_type'),
reference: ViewType.HOST
});
runtime: ViewType.HOST
};
const baseErrorIdentifier = new CompileIdentifierMetadata(
{name: 'BaseError', moduleUrl: assetUrl('core', 'facade/errors'), reference: BaseError});
const baseErrorIdentifier = {
name: 'BaseError',
moduleUrl: assetUrl('core', 'facade/errors'),
runtime: BaseError
};
export var codegenExportsVars = [
'getExpressions',
@ -58,7 +64,7 @@ const _getExpressionsStmts: o.Statement[] = [
o.variable('map').key(o.literal('changeable')).set(o.literal('changedValue')).toStmt(),
o.variable('externalInstance')
.set(o.importExpr(testDataIdentifier).instantiate([o.literal('someValue')]))
.set(o.importExpr(createIdentifier(testDataIdentifier)).instantiate([o.literal('someValue')]))
.toDeclStmt(),
o.variable('externalInstance').prop('changeable').set(o.literal('changedValue')).toStmt(),
@ -69,8 +75,8 @@ const _getExpressionsStmts: o.Statement[] = [
.toDeclStmt(),
o.variable('throwError')
.set(o.fn([], [new o.ThrowStmt(
o.importExpr(baseErrorIdentifier).instantiate([o.literal('someError')]))]))
.set(o.fn([], [new o.ThrowStmt(o.importExpr(createIdentifier(baseErrorIdentifier))
.instantiate([o.literal('someError')]))]))
.toDeclStmt(),
o.variable('catchError')
@ -152,9 +158,9 @@ const _getExpressionsStmts: o.Statement[] = [
['not', o.not(o.literal(false))],
['externalTestIdentifier', o.importExpr(testDataIdentifier)],
['externalSrcIdentifier', o.importExpr(eventEmitterIdentifier)],
['externalEnumIdentifier', o.importExpr(enumIdentifier)],
['externalTestIdentifier', o.importExpr(createIdentifier(testDataIdentifier))],
['externalSrcIdentifier', o.importExpr(createIdentifier(eventEmitterIdentifier))],
['externalEnumIdentifier', o.importExpr(createIdentifier(enumIdentifier))],
['externalInstance', o.variable('externalInstance')],
['dynamicInstance', o.variable('dynamicInstance')],
@ -188,7 +194,7 @@ export var codegenStmts: o.Statement[] = [
new o.CommentStmt('This is a comment'),
new o.ClassStmt(
'DynamicClass', o.importExpr(testDataIdentifier),
'DynamicClass', o.importExpr(createIdentifier(testDataIdentifier)),
[
new o.ClassField('dynamicProp', o.DYNAMIC_TYPE),
new o.ClassField('dynamicChangeable', o.DYNAMIC_TYPE),

View File

@ -8,19 +8,25 @@
import {CompileIdentifierMetadata} from '@angular/compiler/src/compile_metadata';
import * as o from '@angular/compiler/src/output/output_ast';
import {ImportResolver} from '@angular/compiler/src/output/path_util';
import {TypeScriptEmitter} from '@angular/compiler/src/output/ts_emitter';
import {beforeEach, describe, expect, it} from '@angular/core/testing/testing_internal';
import {SimpleJsImportGenerator} from './output_emitter_util';
const someModuleUrl = 'somePackage/somePath';
const anotherModuleUrl = 'somePackage/someOtherPath';
const sameModuleIdentifier =
new CompileIdentifierMetadata({name: 'someLocalId', moduleUrl: someModuleUrl});
const sameModuleIdentifier: CompileIdentifierMetadata = {
reference: {name: 'someLocalId', filePath: someModuleUrl}
};
const externalModuleIdentifier =
new CompileIdentifierMetadata({name: 'someExternalId', moduleUrl: anotherModuleUrl});
const externalModuleIdentifier: CompileIdentifierMetadata = {
reference: {name: 'someExternalId', filePath: anotherModuleUrl}
};
class SimpleJsImportGenerator implements ImportResolver {
fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string {
return importedUrlStr;
}
}
export function main() {
// Note supported features of our OutputAsti n TS:
@ -318,6 +324,14 @@ export function main() {
].join('\n'));
});
it('should support expression types', () => {
expect(emitStmt(o.variable('a')
.set(o.NULL_EXPR)
.toDeclStmt(o.expressionType(
o.variable('b'), [o.expressionType(o.variable('c'))]))))
.toEqual('var a:b<c> = (null as any);');
});
it('should support combined types', () => {
const writeVarExpr = o.variable('a').set(o.NULL_EXPR);
expect(emitStmt(writeVarExpr.toDeclStmt(new o.ArrayType(null))))

View File

@ -0,0 +1,52 @@
/**
* @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
*/
import {PipeResolver} from '@angular/compiler/src/pipe_resolver';
import {Pipe} from '@angular/core/src/metadata';
import {stringify} from '../src/facade/lang';
@Pipe({name: 'somePipe', pure: true})
class SomePipe {
}
class SimpleClass {}
export function main() {
describe('PipeResolver', () => {
let resolver: PipeResolver;
beforeEach(() => { resolver = new PipeResolver(); });
it('should read out the metadata from the class', () => {
const moduleMetadata = resolver.resolve(SomePipe);
expect(moduleMetadata).toEqual(new Pipe({name: 'somePipe', pure: true}));
});
it('should throw when simple class has no pipe decorator', () => {
expect(() => resolver.resolve(SimpleClass))
.toThrowError(`No Pipe decorator found on ${stringify(SimpleClass)}`);
});
it('should support inheriting the metadata', function() {
@Pipe({name: 'p'})
class Parent {
}
class ChildNoDecorator extends Parent {}
@Pipe({name: 'c'})
class ChildWithDecorator extends Parent {
}
expect(resolver.resolve(ChildNoDecorator)).toEqual(new Pipe({name: 'p'}));
expect(resolver.resolve(ChildWithDecorator)).toEqual(new Pipe({name: 'c'}));
});
});
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {CompileAnimationEntryMetadata, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeMetadata, CompilePipeSummary, CompileProviderMetadata, CompileQueryMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata} from '@angular/compiler/src/compile_metadata';
import {CompileAnimationEntryMetadata, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeMetadata, CompilePipeSummary, CompileProviderMetadata, CompileQueryMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata, tokenReference} from '@angular/compiler/src/compile_metadata';
import {DomElementSchemaRegistry} from '@angular/compiler/src/schema/dom_element_schema_registry';
import {ElementSchemaRegistry} from '@angular/compiler/src/schema/element_schema_registry';
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, PropertyBindingType, ProviderAstType, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '@angular/compiler/src/template_parser/template_ast';
@ -14,10 +14,9 @@ import {TEMPLATE_TRANSFORMS, TemplateParser, splitClasses} from '@angular/compil
import {TEST_COMPILER_PROVIDERS} from '@angular/compiler/testing/test_bindings';
import {SchemaMetadata, SecurityContext, Type} from '@angular/core';
import {Console} from '@angular/core/src/console';
import {TestBed} from '@angular/core/testing';
import {beforeEach, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
import {TestBed, inject} from '@angular/core/testing';
import {Identifiers, identifierToken, resolveIdentifierToken} from '../../src/identifiers';
import {Identifiers, createIdentifierToken, identifierToken} from '../../src/identifiers';
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../../src/ml_parser/interpolation_config';
import {MockSchemaRegistry} from '../../testing/index';
import {unparse} from '../expression_parser/unparser';
@ -31,6 +30,11 @@ const MOCK_SCHEMA_REGISTRY = [{
['onEvent'], ['onEvent']),
}];
function createTypeMeta({reference, diDeps}: {reference: any, diDeps?: any[]}):
CompileTypeMetadata {
return {reference: reference, diDeps: diDeps || [], lifecycleHooks: []};
}
export function main() {
let ngIf: CompileDirectiveSummary;
let parse: (
@ -49,16 +53,14 @@ export function main() {
const component = CompileDirectiveMetadata.create({
selector: 'root',
template: someTemplate,
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'Root', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'Root'}}),
isComponent: true
});
ngIf = CompileDirectiveMetadata
.create({
selector: '[ngIf]',
template: someTemplate,
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'NgIf', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'NgIf'}}),
inputs: ['ngIf']
})
.toSummary();
@ -302,8 +304,7 @@ export function main() {
inject([TemplateParser], (parser: TemplateParser) => {
const component = CompileDirectiveMetadata.create({
selector: 'test',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'Test', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'Test'}}),
isComponent: true,
template: new CompileTemplateMetadata({interpolation: ['{%', '%}']})
});
@ -470,10 +471,8 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
.create({
selector: 'div',
template: new CompileTemplateMetadata({animations: animationEntries}),
type: new CompileTypeMetadata({
moduleUrl: someModuleUrl,
name: 'DirA',
reference: {} as Type<any>
type: createTypeMeta({
reference: {filePath: someModuleUrl, name: 'DirA'},
}),
host: {'[@prop]': 'expr'}
})
@ -488,8 +487,7 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
CompileDirectiveMetadata
.create({
selector: 'broken',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
host: {'[class.foo]': null}
})
.toSummary();
@ -504,8 +502,7 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
CompileDirectiveMetadata
.create({
selector: 'broken',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
host: {'(click)': null}
})
.toSummary();
@ -572,11 +569,8 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
.create({
selector: 'template',
outputs: ['e'],
type: new CompileTypeMetadata({
moduleUrl: someModuleUrl,
name: 'DirA',
reference: {} as Type<any>
})
type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'DirA'}})
})
.toSummary();
expect(humanizeTplAst(parse('<template (e)="f"></template>', [dirA]))).toEqual([
@ -614,31 +608,22 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
const dirA = CompileDirectiveMetadata
.create({
selector: '[a]',
type: new CompileTypeMetadata({
moduleUrl: someModuleUrl,
name: 'DirA',
reference: {} as Type<any>
})
type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'DirA'}})
})
.toSummary();
const dirB = CompileDirectiveMetadata
.create({
selector: '[b]',
type: new CompileTypeMetadata({
moduleUrl: someModuleUrl,
name: 'DirB',
reference: {} as Type<any>
})
type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'DirB'}})
})
.toSummary();
const dirC = CompileDirectiveMetadata
.create({
selector: '[c]',
type: new CompileTypeMetadata({
moduleUrl: someModuleUrl,
name: 'DirC',
reference: {} as Type<any>
})
type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'DirC'}})
})
.toSummary();
expect(humanizeTplAst(parse('<div a c b a b>', [dirA, dirB, dirC]))).toEqual([
@ -653,16 +638,14 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
CompileDirectiveMetadata
.create({
selector: '[a=b]',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>})
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}})
})
.toSummary();
const dirB =
CompileDirectiveMetadata
.create({
selector: '[b]',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirB', reference: {} as Type<any>})
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirB'}})
})
.toSummary();
expect(humanizeTplAst(parse('<div [a]="b">', [dirA, dirB]))).toEqual([
@ -677,8 +660,7 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
CompileDirectiveMetadata
.create({
selector: '[a]',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirB', reference: {} as Type<any>})
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirB'}})
})
.toSummary();
@ -692,8 +674,7 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
CompileDirectiveMetadata
.create({
selector: 'div',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
host: {'[a]': 'expr'}
})
.toSummary();
@ -708,8 +689,7 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
CompileDirectiveMetadata
.create({
selector: 'div',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
host: {'(a)': 'expr'}
})
.toSummary();
@ -723,8 +703,7 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
CompileDirectiveMetadata
.create({
selector: 'div',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
inputs: ['aProp']
})
.toSummary();
@ -739,8 +718,7 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
CompileDirectiveMetadata
.create({
selector: 'div',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
inputs: ['b:a']
})
.toSummary();
@ -755,8 +733,7 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
CompileDirectiveMetadata
.create({
selector: 'div',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
inputs: ['a']
})
.toSummary();
@ -771,8 +748,7 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
CompileDirectiveMetadata
.create({
selector: 'div',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
inputs: ['a']
})
.toSummary();
@ -788,8 +764,7 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
CompileDirectiveMetadata
.create({
selector: 'div',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
inputs: ['a']
})
.toSummary();
@ -807,12 +782,9 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
let token: CompileTokenMetadata;
if (value.startsWith('type:')) {
const name = value.substring(5);
token = new CompileTokenMetadata({
identifier: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name, reference: name as any as Type<any>})
});
token = {identifier: createTypeMeta({reference: <any>name})};
} else {
token = new CompileTokenMetadata({value: value});
token = {value: value};
}
return token;
}
@ -833,24 +805,28 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
isHost = true;
value = value.substring(5);
}
return new CompileDiDependencyMetadata({
return {
token: createToken(value),
isOptional: isOptional,
isSelf: isSelf,
isHost: isHost
});
};
}
function createProvider(
token: string, {multi = false, deps = []}: {multi?: boolean, deps?: string[]} = {}):
CompileProviderMetadata {
const name = `provider${nextProviderId++}`;
return new CompileProviderMetadata({
token: createToken(token),
const compileToken = createToken(token);
return {
token: compileToken,
multi: multi,
useClass: new CompileTypeMetadata({name, reference: name as any as Type<any>}),
deps: deps.map(createDep)
});
useClass: createTypeMeta({reference: tokenReference(compileToken)}),
deps: deps.map(createDep),
useExisting: undefined,
useFactory: undefined,
useValue: undefined
};
}
function createDir(
@ -865,18 +841,23 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
return CompileDirectiveMetadata
.create({
selector: selector,
type: new CompileTypeMetadata({
moduleUrl: someModuleUrl,
name: selector,
type: createTypeMeta({
reference: <any>selector,
diDeps: deps.map(createDep),
reference: selector as any as Type<any>
}),
isComponent: isComponent,
template: new CompileTemplateMetadata({ngContentSelectors: []}),
providers: providers,
viewProviders: viewProviders,
queries: queries.map(
(value) => new CompileQueryMetadata({selectors: [createToken(value)]}))
queries: queries.map((value) => {
return {
selectors: [createToken(value)],
descendants: false,
first: false,
propertyName: 'test',
read: undefined
};
})
})
.toSummary();
}
@ -1122,8 +1103,7 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
CompileDirectiveMetadata
.create({
selector: '[a]',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
exportAs: 'dirA'
})
.toSummary();
@ -1170,8 +1150,7 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
.create({
selector: '[a]',
isComponent: true,
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
exportAs: 'dirA',
template: new CompileTemplateMetadata({ngContentSelectors: []})
})
@ -1189,8 +1168,7 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
CompileDirectiveMetadata
.create({
selector: '[a]',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>})
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}})
})
.toSummary();
expect(humanizeTplAst(parse('<div ref-a>', [dirA]))).toEqual([
@ -1218,14 +1196,14 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
it('should support references via #...', () => {
expect(humanizeTplAst(parse('<template #a>', []))).toEqual([
[EmbeddedTemplateAst],
[ReferenceAst, 'a', resolveIdentifierToken(Identifiers.TemplateRef)]
[ReferenceAst, 'a', createIdentifierToken(Identifiers.TemplateRef)]
]);
});
it('should support references via ref-...', () => {
expect(humanizeTplAst(parse('<template ref-a>', []))).toEqual([
[EmbeddedTemplateAst],
[ReferenceAst, 'a', resolveIdentifierToken(Identifiers.TemplateRef)]
[ReferenceAst, 'a', createIdentifierToken(Identifiers.TemplateRef)]
]);
});
@ -1239,8 +1217,7 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
CompileDirectiveMetadata
.create({
selector: '[a]',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>})
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}})
})
.toSummary();
expect(humanizeTplAst(parse('<template let-a="b"></template>', [dirA]))).toEqual([
@ -1281,23 +1258,19 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
describe('directives', () => {
it('should locate directives in property bindings', () => {
const dirA =
CompileDirectiveMetadata
.create({
selector: '[a=b]',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
inputs: ['a']
})
.toSummary();
const dirA = CompileDirectiveMetadata
.create({
selector: '[a=b]',
type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'DirA'}}),
inputs: ['a']
})
.toSummary();
const dirB = CompileDirectiveMetadata
.create({
selector: '[b]',
type: new CompileTypeMetadata({
moduleUrl: someModuleUrl,
name: 'DirB',
reference: {} as Type<any>
})
type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'DirB'}})
})
.toSummary();
expect(humanizeTplAst(parse('<div template="a b" b>', [dirA, dirB]))).toEqual([
@ -1311,11 +1284,8 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
const dirA = CompileDirectiveMetadata
.create({
selector: '[a]',
type: new CompileTypeMetadata({
moduleUrl: someModuleUrl,
name: 'DirA',
reference: {} as Type<any>
})
type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'DirA'}})
})
.toSummary();
expect(humanizeTplAst(parse('<div template="let a=b">', [dirA]))).toEqual([
@ -1327,11 +1297,8 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
const dirA = CompileDirectiveMetadata
.create({
selector: '[a]',
type: new CompileTypeMetadata({
moduleUrl: someModuleUrl,
name: 'DirA',
reference: {} as Type<any>
})
type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'DirA'}})
})
.toSummary();
expect(humanizeTplAst(parse('<div ref-a>', [dirA]))).toEqual([
@ -1367,11 +1334,8 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
.create({
selector: selector,
isComponent: true,
type: new CompileTypeMetadata({
moduleUrl: someModuleUrl,
name: `SomeComp${compCounter++}`,
reference: {} as Type<any>
}),
type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: `SomeComp${compCounter++}`}}),
template: new CompileTemplateMetadata({ngContentSelectors: ngContentSelectors})
})
.toSummary();
@ -1381,11 +1345,8 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
return CompileDirectiveMetadata
.create({
selector: selector,
type: new CompileTypeMetadata({
moduleUrl: someModuleUrl,
name: `SomeDir${compCounter++}`,
reference: {} as Type<any>
})
type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: `SomeDir${compCounter++}`}})
})
.toSummary();
}
@ -1559,8 +1520,7 @@ Can't bind to 'invalidProp' since it isn't a known property of 'div'. ("<div [ER
CompileDirectiveMetadata
.create({
selector: 'div',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
host: {'[invalidProp]': 'someProp'}
})
.toSummary();
@ -1579,8 +1539,7 @@ Parser Error: Unexpected token 'b' at column 3 in [a b] in TestComp@0:5 ("<div [
CompileDirectiveMetadata
.create({
selector: 'div',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
inputs: ['invalidProp']
})
.toSummary();
@ -1593,8 +1552,7 @@ Parser Error: Unexpected token 'b' at column 3 in [a b] in TestComp@0:5 ("<div [
.create({
selector: 'div',
isComponent: true,
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
template: new CompileTemplateMetadata({ngContentSelectors: []})
})
.toSummary();
@ -1603,8 +1561,7 @@ Parser Error: Unexpected token 'b' at column 3 in [a b] in TestComp@0:5 ("<div [
.create({
selector: 'div',
isComponent: true,
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirB', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirB'}}),
template: new CompileTemplateMetadata({ngContentSelectors: []})
})
.toSummary();
@ -1623,8 +1580,7 @@ Parser Error: Unexpected token 'b' at column 3 in [a b] in TestComp@0:5 ("<div [
.create({
selector: '[a]',
isComponent: true,
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
template: new CompileTemplateMetadata({ngContentSelectors: []})
})
.toSummary();
@ -1641,8 +1597,7 @@ Property binding a not used by any directive on an embedded template. Make sure
.create({
selector: '[a]',
isComponent: true,
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
template: new CompileTemplateMetadata({ngContentSelectors: []})
})
.toSummary();
@ -1801,8 +1756,7 @@ Property binding a not used by any directive on an embedded template. Make sure
CompileDirectiveMetadata
.create({
selector: '[a]',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>})
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}})
})
.toSummary();
const comp =
@ -1810,8 +1764,7 @@ Property binding a not used by any directive on an embedded template. Make sure
.create({
selector: 'div',
isComponent: true,
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'ZComp', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'ZComp'}}),
template: new CompileTemplateMetadata({ngContentSelectors: []})
})
.toSummary();
@ -1826,18 +1779,16 @@ Property binding a not used by any directive on an embedded template. Make sure
CompileDirectiveMetadata
.create({
selector: 'circle',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'elDir', reference: {} as Type<any>})
})
.toSummary();
const attrSel =
CompileDirectiveMetadata
.create({
selector: '[href]',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'attrDir', reference: {} as Type<any>})
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'elDir'}})
})
.toSummary();
const attrSel = CompileDirectiveMetadata
.create({
selector: '[href]',
type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'attrDir'}})
})
.toSummary();
expect(humanizeTplAstSourceSpans(
parse('<svg><circle /><use xlink:href="Port" /></svg>', [tagSel, attrSel])))
@ -1856,8 +1807,7 @@ Property binding a not used by any directive on an embedded template. Make sure
CompileDirectiveMetadata
.create({
selector: 'div',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>}),
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
inputs: ['aProp']
})
.toSummary();
@ -1873,8 +1823,7 @@ Property binding a not used by any directive on an embedded template. Make sure
CompileDirectiveMetadata
.create({
selector: 'circle',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'elDir', reference: {} as Type<any>})
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'elDir'}})
})
.toSummary();
const result = parse('<circle></circle>', [tagSel]);
@ -1889,16 +1838,14 @@ Property binding a not used by any directive on an embedded template. Make sure
CompileDirectiveMetadata
.create({
selector: 'ul',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'ulDir', reference: {} as Type<any>})
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'ulDir'}})
})
.toSummary();
const liSel =
CompileDirectiveMetadata
.create({
selector: 'li',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'liDir', reference: {} as Type<any>})
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'liDir'}})
})
.toSummary();
const result = parse('<ul><li><li></ul>', [ulSel, liSel]);
@ -1913,8 +1860,7 @@ Property binding a not used by any directive on an embedded template. Make sure
const testPipe =
new CompilePipeMetadata({
name: 'test',
type: new CompileTypeMetadata(
{moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type<any>})
type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}})
}).toSummary();
expect(() => parse('{{a | test}}', [], [testPipe])).not.toThrow();
});

View File

@ -57,7 +57,7 @@ function createCompileView(config: {className: string, parent?: CompileView, fie
config.fields.forEach((fieldName) => { fields.push(new o.ClassField(fieldName)); });
}
return <any>{
classType: o.importType(new CompileIdentifierMetadata({name: config.className})),
classType: o.importType({reference: null}),
fields: fields,
getters: [],
declarationElement: declarationElement

View File

@ -12,5 +12,10 @@
* Entry point for all public APIs of the core package.
*/
export * from './src/core';
import {Version} from './src/core';
/**
* @stable
*/
export const VERSION = new Version('0.0.0-PLACEHOLDER');
// This file only reexports content of the `src` folder. Keep it that way.

View File

@ -8,8 +8,8 @@
"author": "angular",
"license": "MIT",
"peerDependencies": {
"rxjs": "5.0.0-beta.12",
"zone.js": "^0.6.21"
"rxjs": "5.0.0-rc.4",
"zone.js": "^0.7.2"
},
"repository": {
"type": "git",

View File

@ -12,6 +12,7 @@
* Entry point from which you should import all public core APIs.
*/
export * from './metadata';
export * from './version';
export * from './util';
export * from './di';
export {createPlatform, assertPlatform, destroyPlatform, getPlatform, PlatformRef, ApplicationRef, enableProdMode, isDevMode, createPlatformFactory, NgProbeToken} from './application_ref';
@ -34,4 +35,4 @@ export * from './core_private_export';
export * from './animation/metadata';
export {AnimationTransitionEvent} from './animation/animation_transition_event';
export {AnimationPlayer} from './animation/animation_player';
export {Sanitizer, SecurityContext} from './security';
export {Sanitizer, SecurityContext} from './security';

View File

@ -6,7 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {makeParamDecorator} from '../util/decorators';
import {makeDecorator, makeParamDecorator} from '../util/decorators';
/**
* Type of the Inject decorator / constructor function.
@ -150,7 +151,7 @@ export interface Injectable {}
* @stable
* @Annotation
*/
export const Injectable: InjectableDecorator = makeParamDecorator('Injectable', []);
export const Injectable: InjectableDecorator = <InjectableDecorator>makeDecorator('Injectable', []);
/**
* Type of the Self decorator / constructor function.

View File

@ -18,6 +18,11 @@ import {AppView} from './view';
* @stable
*/
export abstract class ViewRef extends ChangeDetectorRef {
/**
* Destroys the view and all of the data structures associated with it.
*/
abstract destroy(): void;
get destroyed(): boolean { return <boolean>unimplemented(); }
abstract onDestroy(callback: Function): any /** TODO #9100 */;
@ -81,11 +86,6 @@ export abstract class EmbeddedViewRef<C> extends ViewRef {
get context(): C { return unimplemented(); }
get rootNodes(): any[] { return <any[]>unimplemented(); };
/**
* Destroys the view and all of the data structures associated with it.
*/
abstract destroy(): void;
}
export class ViewRef_<C> implements EmbeddedViewRef<C>, ChangeDetectorRef {

View File

@ -6,7 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/
import {APP_ID} from '../application_tokens';
import {SimpleChange, devModeEqual} from '../change_detection/change_detection';
import {UNINITIALIZED} from '../change_detection/change_detection_util';
import {Inject, Injectable} from '../di';

View File

@ -12,6 +12,12 @@ import {Type} from '../type';
import {PlatformReflectionCapabilities} from './platform_reflection_capabilities';
import {GetterFn, MethodFn, SetterFn} from './types';
/**
* Attention: This regex has to hold even if the code is minified!
*/
export const DELEGATE_CTOR =
/^function\s+\S+\(\)\s*{\s*("use strict";)?\s*(return\s+)?\S+\.apply\(this,\s*arguments\)/;
export class ReflectionCapabilities implements PlatformReflectionCapabilities {
private _reflect: any;
@ -49,15 +55,26 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
return result;
}
parameters(type: Type<any>): any[][] {
private _ownParameters(type: Type<any>, parentCtor: any): any[][] {
// If we have no decorators, we only have function.length as metadata.
// In that case, to detect whether a child class declared an own constructor or not,
// we need to look inside of that constructor to check whether it is
// just calling the parent.
// This also helps to work around for https://github.com/Microsoft/TypeScript/issues/12439
// that sets 'design:paramtypes' to []
// if a class inherits from another class but has no ctor declared itself.
if (DELEGATE_CTOR.exec(type.toString())) {
return null;
}
// Prefer the direct API.
if ((<any>type).parameters) {
if ((<any>type).parameters && (<any>type).parameters !== parentCtor.parameters) {
return (<any>type).parameters;
}
// API of tsickle for lowering decorators to properties on the class.
const tsickleCtorParams = (<any>type).ctorParameters;
if (tsickleCtorParams) {
if (tsickleCtorParams && tsickleCtorParams !== parentCtor.ctorParameters) {
// Newer tsickle uses a function closure
// Retain the non-function case for compatibility with older tsickle
const ctorParameters =
@ -70,20 +87,35 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
}
// API for metadata created by invoking the decorators.
if (isPresent(this._reflect) && isPresent(this._reflect.getMetadata)) {
const paramAnnotations = this._reflect.getMetadata('parameters', type);
const paramTypes = this._reflect.getMetadata('design:paramtypes', type);
if (isPresent(this._reflect) && isPresent(this._reflect.getOwnMetadata)) {
const paramAnnotations = this._reflect.getOwnMetadata('parameters', type);
const paramTypes = this._reflect.getOwnMetadata('design:paramtypes', type);
if (paramTypes || paramAnnotations) {
return this._zipTypesAndAnnotations(paramTypes, paramAnnotations);
}
}
// The array has to be filled with `undefined` because holes would be skipped by `some`
// If a class has no decorators, at least create metadata
// based on function.length.
// Note: We know that this is a real constructor as we checked
// the content of the constructor above.
return new Array((<any>type.length)).fill(undefined);
}
annotations(typeOrFunc: Type<any>): any[] {
parameters(type: Type<any>): any[][] {
// Note: only report metadata if we have at least one class decorator
// to stay in sync with the static reflector.
const parentCtor = Object.getPrototypeOf(type.prototype).constructor;
let parameters = this._ownParameters(type, parentCtor);
if (!parameters && parentCtor !== Object) {
parameters = this.parameters(parentCtor);
}
return parameters || [];
}
private _ownAnnotations(typeOrFunc: Type<any>, parentCtor: any): any[] {
// Prefer the direct API.
if ((<any>typeOrFunc).annotations) {
if ((<any>typeOrFunc).annotations && (<any>typeOrFunc).annotations !== parentCtor.annotations) {
let annotations = (<any>typeOrFunc).annotations;
if (typeof annotations === 'function' && annotations.annotations) {
annotations = annotations.annotations;
@ -92,21 +124,27 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
}
// API of tsickle for lowering decorators to properties on the class.
if ((<any>typeOrFunc).decorators) {
if ((<any>typeOrFunc).decorators && (<any>typeOrFunc).decorators !== parentCtor.decorators) {
return convertTsickleDecoratorIntoMetadata((<any>typeOrFunc).decorators);
}
// API for metadata created by invoking the decorators.
if (this._reflect && this._reflect.getMetadata) {
const annotations = this._reflect.getMetadata('annotations', typeOrFunc);
if (annotations) return annotations;
if (this._reflect && this._reflect.getOwnMetadata) {
return this._reflect.getOwnMetadata('annotations', typeOrFunc);
}
return [];
}
propMetadata(typeOrFunc: any): {[key: string]: any[]} {
annotations(typeOrFunc: Type<any>): any[] {
const parentCtor = Object.getPrototypeOf(typeOrFunc.prototype).constructor;
const ownAnnotations = this._ownAnnotations(typeOrFunc, parentCtor) || [];
const parentAnnotations = parentCtor !== Object ? this.annotations(parentCtor) : [];
return parentAnnotations.concat(ownAnnotations);
}
private _ownPropMetadata(typeOrFunc: any, parentCtor: any): {[key: string]: any[]} {
// Prefer the direct API.
if ((<any>typeOrFunc).propMetadata) {
if ((<any>typeOrFunc).propMetadata &&
(<any>typeOrFunc).propMetadata !== parentCtor.propMetadata) {
let propMetadata = (<any>typeOrFunc).propMetadata;
if (typeof propMetadata === 'function' && propMetadata.propMetadata) {
propMetadata = propMetadata.propMetadata;
@ -115,7 +153,8 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
}
// API of tsickle for lowering decorators to properties on the class.
if ((<any>typeOrFunc).propDecorators) {
if ((<any>typeOrFunc).propDecorators &&
(<any>typeOrFunc).propDecorators !== parentCtor.propDecorators) {
const propDecorators = (<any>typeOrFunc).propDecorators;
const propMetadata = <{[key: string]: any[]}>{};
Object.keys(propDecorators).forEach(prop => {
@ -125,11 +164,32 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
}
// API for metadata created by invoking the decorators.
if (this._reflect && this._reflect.getMetadata) {
const propMetadata = this._reflect.getMetadata('propMetadata', typeOrFunc);
if (propMetadata) return propMetadata;
if (this._reflect && this._reflect.getOwnMetadata) {
return this._reflect.getOwnMetadata('propMetadata', typeOrFunc);
}
return {};
}
propMetadata(typeOrFunc: any): {[key: string]: any[]} {
const parentCtor = Object.getPrototypeOf(typeOrFunc.prototype).constructor;
const propMetadata: {[key: string]: any[]} = {};
if (parentCtor !== Object) {
const parentPropMetadata = this.propMetadata(parentCtor);
Object.keys(parentPropMetadata).forEach((propName) => {
propMetadata[propName] = parentPropMetadata[propName];
});
}
const ownPropMetadata = this._ownPropMetadata(typeOrFunc, parentCtor);
if (ownPropMetadata) {
Object.keys(ownPropMetadata).forEach((propName) => {
const decorators: any[] = [];
if (propMetadata.hasOwnProperty(propName)) {
decorators.push(...propMetadata[propName]);
}
decorators.push(...ownPropMetadata[propName]);
propMetadata[propName] = decorators;
});
}
return propMetadata;
}
hasLifecycleHook(type: any, lcProperty: string): boolean {

View File

@ -262,7 +262,7 @@ export function makeDecorator(
const metaCtor = makeMetadataCtor([props]);
function DecoratorFactory(objOrType: any): (cls: any) => any {
if (!(Reflect && Reflect.getMetadata)) {
if (!(Reflect && Reflect.getOwnMetadata)) {
throw 'reflect-metadata shim is required when using class decorators';
}
@ -327,7 +327,7 @@ export function makeParamDecorator(
return ParamDecorator;
function ParamDecorator(cls: any, unusedKey: any, index: number): any {
const parameters: any[][] = Reflect.getMetadata('parameters', cls) || [];
const parameters: any[][] = Reflect.getOwnMetadata('parameters', cls) || [];
// there might be gaps if some in between parameters do not have annotations.
// we pad with nulls.

View File

@ -0,0 +1,22 @@
/**
* @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
*/
/**
* @whatItDoes Represents the version of Angular
*
* @stable
*/
export class Version {
constructor(public full: string) {}
get major(): string { return this.full.split('.')[0]; }
get minor(): string { return this.full.split('.')[1]; }
get patch(): string { return this.full.split('.').slice(2).join('.'); }
}

View File

@ -95,7 +95,7 @@ export function main() {
resolvedPromise.then((_) => { throw new Error('async'); });
flushMicrotasks();
})();
}).toThrowError('Uncaught (in promise): Error: async');
}).toThrowError(/Uncaught \(in promise\): Error: async/);
});
it('should complain if a test throws an exception', () => {

View File

@ -7,7 +7,7 @@
*/
import {Reflector} from '@angular/core/src/reflection/reflection';
import {ReflectionCapabilities} from '@angular/core/src/reflection/reflection_capabilities';
import {DELEGATE_CTOR, ReflectionCapabilities} from '@angular/core/src/reflection/reflection_capabilities';
import {makeDecorator, makeParamDecorator, makePropDecorator} from '@angular/core/src/util/decorators';
interface ClassDecoratorFactory {
@ -107,7 +107,6 @@ export function main() {
class ForwardDep {}
expect(reflector.parameters(Forward)).toEqual([[ForwardDep]]);
});
});
describe('propMetadata', () => {
@ -117,6 +116,15 @@ export function main() {
expect(p['c']).toEqual([new PropDecorator('p3')]);
expect(p['someMethod']).toEqual([new PropDecorator('p4')]);
});
it('should also return metadata if the class has no decorator', () => {
class Test {
@PropDecorator('test')
prop: any;
}
expect(reflector.propMetadata(Test)).toEqual({'prop': [new PropDecorator('test')]});
});
});
describe('annotations', () => {
@ -154,5 +162,321 @@ export function main() {
expect(func(obj, ['value'])).toEqual('value');
});
});
describe('ctor inheritance detection', () => {
it('should use the right regex', () => {
class Parent {}
class ChildNoCtor extends Parent {}
class ChildWithCtor extends Parent {
constructor() { super(); }
}
expect(DELEGATE_CTOR.exec(ChildNoCtor.toString())).toBeTruthy();
expect(DELEGATE_CTOR.exec(ChildWithCtor.toString())).toBeFalsy();
});
});
describe('inheritance with decorators', () => {
it('should inherit annotations', () => {
@ClassDecorator({value: 'parent'})
class Parent {
}
@ClassDecorator({value: 'child'})
class Child extends Parent {
}
class ChildNoDecorators extends Parent {}
// Check that metadata for Parent was not changed!
expect(reflector.annotations(Parent)).toEqual([new ClassDecorator({value: 'parent'})]);
expect(reflector.annotations(Child)).toEqual([
new ClassDecorator({value: 'parent'}), new ClassDecorator({value: 'child'})
]);
expect(reflector.annotations(ChildNoDecorators)).toEqual([new ClassDecorator(
{value: 'parent'})]);
});
it('should inherit parameters', () => {
class A {}
class B {}
class C {}
// Note: We need the class decorator as well,
// as otherwise TS won't capture the ctor arguments!
@ClassDecorator({value: 'parent'})
class Parent {
constructor(@ParamDecorator('a') a: A, @ParamDecorator('b') b: B) {}
}
class Child extends Parent {}
// Note: We need the class decorator as well,
// as otherwise TS won't capture the ctor arguments!
@ClassDecorator({value: 'child'})
class ChildWithCtor extends Parent {
constructor(@ParamDecorator('c') c: C) { super(null, null); }
}
class ChildWithCtorNoDecorator extends Parent {
constructor(a: any, b: any, c: any) { super(null, null); }
}
// Check that metadata for Parent was not changed!
expect(reflector.parameters(Parent)).toEqual([
[A, new ParamDecorator('a')], [B, new ParamDecorator('b')]
]);
expect(reflector.parameters(Child)).toEqual([
[A, new ParamDecorator('a')], [B, new ParamDecorator('b')]
]);
expect(reflector.parameters(ChildWithCtor)).toEqual([[C, new ParamDecorator('c')]]);
// If we have no decorator, we don't get metadata about the ctor params.
// But we should still get an array of the right length based on function.length.
expect(reflector.parameters(ChildWithCtorNoDecorator)).toEqual([
undefined, undefined, undefined
]);
});
it('should inherit property metadata', () => {
class A {}
class B {}
class C {}
class Parent {
@PropDecorator('a')
a: A;
@PropDecorator('b1')
b: B;
}
class Child extends Parent {
@PropDecorator('b2')
b: B;
@PropDecorator('c')
c: C;
}
// Check that metadata for Parent was not changed!
expect(reflector.propMetadata(Parent)).toEqual({
'a': [new PropDecorator('a')],
'b': [new PropDecorator('b1')],
});
expect(reflector.propMetadata(Child)).toEqual({
'a': [new PropDecorator('a')],
'b': [new PropDecorator('b1'), new PropDecorator('b2')],
'c': [new PropDecorator('c')]
});
});
it('should inherit lifecycle hooks', () => {
class Parent {
hook1() {}
hook2() {}
}
class Child extends Parent {
hook2() {}
hook3() {}
}
function hooks(symbol: any, names: string[]): boolean[] {
return names.map(name => reflector.hasLifecycleHook(symbol, name));
}
// Check that metadata for Parent was not changed!
expect(hooks(Parent, ['hook1', 'hook2', 'hook3'])).toEqual([true, true, false]);
expect(hooks(Child, ['hook1', 'hook2', 'hook3'])).toEqual([true, true, true]);
});
});
describe('inheritance with tsickle', () => {
it('should inherit annotations', () => {
class Parent {
static decorators = [{type: ClassDecorator, args: [{value: 'parent'}]}];
}
class Child extends Parent {
static decorators = [{type: ClassDecorator, args: [{value: 'child'}]}];
}
class ChildNoDecorators extends Parent {}
// Check that metadata for Parent was not changed!
expect(reflector.annotations(Parent)).toEqual([new ClassDecorator({value: 'parent'})]);
expect(reflector.annotations(Child)).toEqual([
new ClassDecorator({value: 'parent'}), new ClassDecorator({value: 'child'})
]);
expect(reflector.annotations(ChildNoDecorators)).toEqual([new ClassDecorator(
{value: 'parent'})]);
});
it('should inherit parameters', () => {
class A {}
class B {}
class C {}
class Parent {
static ctorParameters = () =>
[{type: A, decorators: [{type: ParamDecorator, args: ['a']}]},
{type: B, decorators: [{type: ParamDecorator, args: ['b']}]},
];
}
class Child extends Parent {}
class ChildWithCtor extends Parent {
static ctorParameters =
() => [{type: C, decorators: [{type: ParamDecorator, args: ['c']}]}, ];
constructor() { super(); }
}
// Check that metadata for Parent was not changed!
expect(reflector.parameters(Parent)).toEqual([
[A, new ParamDecorator('a')], [B, new ParamDecorator('b')]
]);
expect(reflector.parameters(Child)).toEqual([
[A, new ParamDecorator('a')], [B, new ParamDecorator('b')]
]);
expect(reflector.parameters(ChildWithCtor)).toEqual([[C, new ParamDecorator('c')]]);
});
it('should inherit property metadata', () => {
class A {}
class B {}
class C {}
class Parent {
static propDecorators: any = {
'a': [{type: PropDecorator, args: ['a']}],
'b': [{type: PropDecorator, args: ['b1']}],
};
}
class Child extends Parent {
static propDecorators: any = {
'b': [{type: PropDecorator, args: ['b2']}],
'c': [{type: PropDecorator, args: ['c']}],
};
}
// Check that metadata for Parent was not changed!
expect(reflector.propMetadata(Parent)).toEqual({
'a': [new PropDecorator('a')],
'b': [new PropDecorator('b1')],
});
expect(reflector.propMetadata(Child)).toEqual({
'a': [new PropDecorator('a')],
'b': [new PropDecorator('b1'), new PropDecorator('b2')],
'c': [new PropDecorator('c')]
});
});
});
describe('inheritance with es5 API', () => {
it('should inherit annotations', () => {
class Parent {
static annotations = [new ClassDecorator({value: 'parent'})];
}
class Child extends Parent {
static annotations = [new ClassDecorator({value: 'child'})];
}
class ChildNoDecorators extends Parent {}
// Check that metadata for Parent was not changed!
expect(reflector.annotations(Parent)).toEqual([new ClassDecorator({value: 'parent'})]);
expect(reflector.annotations(Child)).toEqual([
new ClassDecorator({value: 'parent'}), new ClassDecorator({value: 'child'})
]);
expect(reflector.annotations(ChildNoDecorators)).toEqual([new ClassDecorator(
{value: 'parent'})]);
});
it('should inherit parameters', () => {
class A {}
class B {}
class C {}
class Parent {
static parameters = [
[A, new ParamDecorator('a')],
[B, new ParamDecorator('b')],
];
}
class Child extends Parent {}
class ChildWithCtor extends Parent {
static parameters = [
[C, new ParamDecorator('c')],
];
constructor() { super(); }
}
// Check that metadata for Parent was not changed!
expect(reflector.parameters(Parent)).toEqual([
[A, new ParamDecorator('a')], [B, new ParamDecorator('b')]
]);
expect(reflector.parameters(Child)).toEqual([
[A, new ParamDecorator('a')], [B, new ParamDecorator('b')]
]);
expect(reflector.parameters(ChildWithCtor)).toEqual([[C, new ParamDecorator('c')]]);
});
it('should inherit property metadata', () => {
class A {}
class B {}
class C {}
class Parent {
static propMetadata: any = {
'a': [new PropDecorator('a')],
'b': [new PropDecorator('b1')],
};
}
class Child extends Parent {
static propMetadata: any = {
'b': [new PropDecorator('b2')],
'c': [new PropDecorator('c')],
};
}
// Check that metadata for Parent was not changed!
expect(reflector.propMetadata(Parent)).toEqual({
'a': [new PropDecorator('a')],
'b': [new PropDecorator('b1')],
});
expect(reflector.propMetadata(Child)).toEqual({
'a': [new PropDecorator('a')],
'b': [new PropDecorator('b1'), new PropDecorator('b2')],
'c': [new PropDecorator('c')]
});
});
});
});
}

View File

@ -53,7 +53,7 @@ export function main() {
it('should invoke as decorator', () => {
function Type() {}
TestDecorator({marker: 'WORKS'})(Type);
const annotations = Reflect.getMetadata('annotations', Type);
const annotations = Reflect.getOwnMetadata('annotations', Type);
expect(annotations[0].marker).toEqual('WORKS');
});

View File

@ -5,6 +5,7 @@
* 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
*/
/* tslint:disable:no-console */
import * as webdriver from 'selenium-webdriver';
declare var browser: any;
declare var expect: any;

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
/* tslint:disable:no-console */
// #docregion Observable
import {Observable} from 'rxjs/Observable';
import {Subscriber} from 'rxjs/Subscriber';

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
/* tslint:disable:no-console */
// #docregion Observable
import 'rxjs/add/operator/map';

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
/* tslint:disable:no-console */
// #docregion Observable
import {Observable} from 'rxjs/Observable';
import {Subscriber} from 'rxjs/Subscriber';

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
/* tslint:disable:no-console */
// #docregion Component
import {Component} from '@angular/core';
import {FormArray, FormControl, FormGroup} from '@angular/forms';

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
/* tslint:disable:no-console */
// #docregion Component
import {Component} from '@angular/core';
import {FormControl, FormGroup, Validators} from '@angular/forms';

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
/* tslint:disable:no-console */
// #docregion Component
import {Component} from '@angular/core';
import {NgForm} from '@angular/forms';

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
/* tslint:disable:no-console */
// #docregion Component
import {Component} from '@angular/core';
import {NgForm} from '@angular/forms';

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
/* tslint:disable:no-console */
// #docregion Component
import {Component} from '@angular/core';
import {FormControl, FormGroup, Validators} from '@angular/forms';

View File

@ -52,6 +52,15 @@ export class StringMapWrapper {
export interface Predicate<T> { (value: T, index?: number, array?: T[]): boolean; }
export class ListWrapper {
static findLast<T>(arr: T[], condition: (value: T) => boolean): T {
for (let i = arr.length - 1; i >= 0; i--) {
if (condition(arr[i])) {
return arr[i];
}
}
return null;
}
static removeAll<T>(list: T[], items: T[]) {
for (let i = 0; i < items.length; ++i) {
const index = list.indexOf(items[i]);

View File

@ -44,6 +44,7 @@ const DATE_FORMATS_SPLIT =
/((?:[^yMLdHhmsazZEwGjJ']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|J+|j+|m+|s+|a|z|Z|G+|w+))(.*)/;
const PATTERN_ALIASES: {[format: string]: DateFormatterFn} = {
// Keys are quoted so they do not get renamed during closure compilation.
'yMMMdjms': datePartGetterFactory(combine([
digitCondition('year', 1),
nameCondition('month', 3),
@ -72,48 +73,50 @@ const PATTERN_ALIASES: {[format: string]: DateFormatterFn} = {
};
const DATE_FORMATS: {[format: string]: DateFormatterFn} = {
yyyy: datePartGetterFactory(digitCondition('year', 4)),
yy: datePartGetterFactory(digitCondition('year', 2)),
y: datePartGetterFactory(digitCondition('year', 1)),
MMMM: datePartGetterFactory(nameCondition('month', 4)),
MMM: datePartGetterFactory(nameCondition('month', 3)),
MM: datePartGetterFactory(digitCondition('month', 2)),
M: datePartGetterFactory(digitCondition('month', 1)),
LLLL: datePartGetterFactory(nameCondition('month', 4)),
L: datePartGetterFactory(nameCondition('month', 1)),
dd: datePartGetterFactory(digitCondition('day', 2)),
d: datePartGetterFactory(digitCondition('day', 1)),
HH: digitModifier(
// Keys are quoted so they do not get renamed.
'yyyy': datePartGetterFactory(digitCondition('year', 4)),
'yy': datePartGetterFactory(digitCondition('year', 2)),
'y': datePartGetterFactory(digitCondition('year', 1)),
'MMMM': datePartGetterFactory(nameCondition('month', 4)),
'MMM': datePartGetterFactory(nameCondition('month', 3)),
'MM': datePartGetterFactory(digitCondition('month', 2)),
'M': datePartGetterFactory(digitCondition('month', 1)),
'LLLL': datePartGetterFactory(nameCondition('month', 4)),
'L': datePartGetterFactory(nameCondition('month', 1)),
'dd': datePartGetterFactory(digitCondition('day', 2)),
'd': datePartGetterFactory(digitCondition('day', 1)),
'HH': digitModifier(
hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 2), false)))),
H: hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 1), false))),
hh: digitModifier(
'H': hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 1), false))),
'hh': digitModifier(
hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 2), true)))),
h: hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 1), true))),
jj: datePartGetterFactory(digitCondition('hour', 2)),
j: datePartGetterFactory(digitCondition('hour', 1)),
mm: digitModifier(datePartGetterFactory(digitCondition('minute', 2))),
m: datePartGetterFactory(digitCondition('minute', 1)),
ss: digitModifier(datePartGetterFactory(digitCondition('second', 2))),
s: datePartGetterFactory(digitCondition('second', 1)),
'h': hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 1), true))),
'jj': datePartGetterFactory(digitCondition('hour', 2)),
'j': datePartGetterFactory(digitCondition('hour', 1)),
'mm': digitModifier(datePartGetterFactory(digitCondition('minute', 2))),
'm': datePartGetterFactory(digitCondition('minute', 1)),
'ss': digitModifier(datePartGetterFactory(digitCondition('second', 2))),
's': datePartGetterFactory(digitCondition('second', 1)),
// while ISO 8601 requires fractions to be prefixed with `.` or `,`
// we can be just safely rely on using `sss` since we currently don't support single or two digit
// fractions
sss: datePartGetterFactory(digitCondition('second', 3)),
EEEE: datePartGetterFactory(nameCondition('weekday', 4)),
EEE: datePartGetterFactory(nameCondition('weekday', 3)),
EE: datePartGetterFactory(nameCondition('weekday', 2)),
E: datePartGetterFactory(nameCondition('weekday', 1)),
a: hourClockExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 1), true))),
Z: timeZoneGetter('short'),
z: timeZoneGetter('long'),
ww: datePartGetterFactory({}), // Week of year, padded (00-53). Week 01 is the week with the
// first Thursday of the year. not support ?
w: datePartGetterFactory({}), // Week of year (0-53). Week 1 is the week with the first Thursday
'sss': datePartGetterFactory(digitCondition('second', 3)),
'EEEE': datePartGetterFactory(nameCondition('weekday', 4)),
'EEE': datePartGetterFactory(nameCondition('weekday', 3)),
'EE': datePartGetterFactory(nameCondition('weekday', 2)),
'E': datePartGetterFactory(nameCondition('weekday', 1)),
'a': hourClockExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 1), true))),
'Z': timeZoneGetter('short'),
'z': timeZoneGetter('long'),
'ww': datePartGetterFactory({}), // Week of year, padded (00-53). Week 01 is the week with the
// first Thursday of the year. not support ?
'w':
datePartGetterFactory({}), // Week of year (0-53). Week 1 is the week with the first Thursday
// of the year not support ?
G: datePartGetterFactory(nameCondition('era', 1)),
GG: datePartGetterFactory(nameCondition('era', 2)),
GGG: datePartGetterFactory(nameCondition('era', 3)),
GGGG: datePartGetterFactory(nameCondition('era', 4))
'G': datePartGetterFactory(nameCondition('era', 1)),
'GG': datePartGetterFactory(nameCondition('era', 2)),
'GGG': datePartGetterFactory(nameCondition('era', 3)),
'GGGG': datePartGetterFactory(nameCondition('era', 4))
};

View File

@ -129,6 +129,7 @@ export function isJsObject(o: any): boolean {
}
export function print(obj: Error | Object) {
// tslint:disable-next-line:no-console
console.log(obj);
}

View File

@ -11,6 +11,11 @@
* @description
* Entry point for all public APIs of the forms package.
*/
import {Version} from '@angular/core';
/**
* @stable
*/
export const VERSION = new Version('0.0.0-PLACEHOLDER');
export * from './src/forms';
// This file only reexports content of the `src` folder. Keep it that way.

View File

@ -11,6 +11,11 @@
* @description
* Entry point for all public APIs of the http package.
*/
import {Version} from '@angular/core';
/**
* @stable
*/
export const VERSION = new Version('0.0.0-PLACEHOLDER');
export * from './src/index';
// This file only reexports content of the `src` folder. Keep it that way.

View File

@ -8,7 +8,7 @@
"author": "angular",
"license": "MIT",
"peerDependencies": {
"rxjs": "5.0.0-beta.12",
"rxjs": "5.0.0-rc.4",
"@angular/core": "0.0.0-PLACEHOLDER",
"@angular/platform-browser": "0.0.0-PLACEHOLDER"
},

View File

@ -59,7 +59,7 @@ export class XHRConnection implements Connection {
// responseText is the old-school way of retrieving response (supported by IE8 & 9)
// response/responseType properties were introduced in ResourceLoader Level2 spec
// (supported by IE10)
body = _xhr.response == null ? _xhr.responseText : _xhr.response;
body = (typeof _xhr.response === 'undefined') ? _xhr.responseText : _xhr.response;
// Implicitly strip a potential XSSI prefix.
if (typeof body === 'string') {

View File

@ -11,10 +11,15 @@
* @description
* Entry point for all public APIs of the language service package.
*/
import {Version} from '@angular/core';
import * as ts from 'typescript';
import {LanguageServicePlugin} from './src/ts_plugin';
/**
* @stable
*/
export const VERSION = new Version('0.0.0-PLACEHOLDER');
export {createLanguageService} from './src/language_service';
export {Completion, Completions, Declaration, Declarations, Definition, Diagnostic, Diagnostics, Hover, HoverTextSection, LanguageService, LanguageServiceHost, Location, Span, TemplateSource, TemplateSources} from './src/types';
export {TypeScriptServiceHost, createLanguageServiceFromTypescript} from './src/typescript_host';

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {StaticSymbol} from '@angular/compiler';
import {StaticSymbol, identifierName, tokenReference} from '@angular/compiler';
import {AST, ASTWithSource, AstVisitor, Binary, BindingPipe, Chain, Conditional, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead} from '@angular/compiler/src/expression_parser/ast';
import {ElementAst, EmbeddedTemplateAst, ReferenceAst, TemplateAst, templateVisitAll} from '@angular/compiler/src/template_parser/template_ast';
@ -667,7 +667,7 @@ function getReferences(info: TemplateInfo): SymbolDeclaration[] {
for (const reference of references) {
let type: Symbol;
if (reference.value) {
type = info.template.query.getTypeSymbol(reference.value.reference);
type = info.template.query.getTypeSymbol(tokenReference(reference.value));
}
result.push({
name: reference.name,
@ -740,7 +740,8 @@ function getVarDeclarations(info: TemplateInfo, path: TemplateAstPath): SymbolDe
function refinedVariableType(
type: Symbol, info: TemplateInfo, templateElement: EmbeddedTemplateAst): Symbol {
// Special case the ngFor directive
const ngForDirective = templateElement.directives.find(d => d.directive.type.name == 'NgFor');
const ngForDirective =
templateElement.directives.find(d => identifierName(d.directive.type) == 'NgFor');
if (ngForDirective) {
const ngForOfBinding = ngForDirective.inputs.find(i => i.directiveName == 'ngForOf');
if (ngForOfBinding) {

View File

@ -107,9 +107,9 @@ class LanguageServiceImpl implements LanguageService {
getTemplateAst(template: TemplateSource, contextFile: string): AstResult {
let result: AstResult;
try {
const directive =
const {metadata} =
this.metadataResolver.getNonNormalizedDirectiveMetadata(template.type as any);
if (directive) {
if (metadata) {
const rawHtmlParser = new HtmlParser();
const htmlParser = new I18NHtmlParser(rawHtmlParser);
const expressionParser = new Parser(new Lexer());
@ -125,15 +125,17 @@ class LanguageServiceImpl implements LanguageService {
}
if (ngModule) {
const directives = ngModule.transitiveModule.directives.map(
d => this.host.resolver.getNonNormalizedDirectiveMetadata(d.reference).toSummary());
d => this.host.resolver.getNonNormalizedDirectiveMetadata(d.reference)
.metadata.toSummary());
const pipes = ngModule.transitiveModule.pipes.map(
p => this.host.resolver.getOrLoadPipeMetadata(p.reference).toSummary());
const schemas = ngModule.schemas;
const parseResult = parser.tryParseHtml(
htmlResult, directive, template.source, directives, pipes, schemas, '');
htmlResult, metadata, template.source, directives, pipes, schemas, '');
result = {
htmlAst: htmlResult.rootNodes,
templateAst: parseResult.templateAst, directive, directives, pipes,
templateAst: parseResult.templateAst,
directive: metadata, directives, pipes,
parseErrors: parseResult.errors, expressionParser, errors
};
}

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {tokenReference} from '@angular/compiler';
import {AST} from '@angular/compiler/src/expression_parser/ast';
import {Attribute} from '@angular/compiler/src/ml_parser/ast';
import {BoundDirectivePropertyAst, BoundEventAst, ElementAst, TemplateAst} from '@angular/compiler/src/template_parser/template_ast';
@ -67,7 +68,7 @@ export function locateSymbol(info: TemplateInfo): SymbolInfo {
}
},
visitReference(ast) {
symbol = info.template.query.getTypeSymbol(ast.value.reference);
symbol = info.template.query.getTypeSymbol(tokenReference(ast.value));
span = spanOf(ast);
},
visitVariable(ast) {},

Some files were not shown because too many files have changed in this diff Show More