Compare commits

..

70 Commits

Author SHA1 Message Date
91f7aa3b15 docs(CHANGELOG): add changelog for 2.0.2 2016-10-05 16:25:04 -07:00
58b8091097 docs(readme): remove incorrect download count badge
npm doesn't currently support download counts for scoped packages, so there is no replacement right now.
2016-10-05 15:33:16 -07:00
0fde7ecd0f refactor: add license header to JS files & format files (#12081) 2016-10-05 15:33:16 -07:00
d25cd244af refactor(benchmarks): refactor to support AOT bootstrap in G3 (#12075) 2016-10-05 15:33:16 -07:00
e00de0c606 fix(forms): properly validate empty strings with patterns (#11450) 2016-10-05 15:33:16 -07:00
205103bdaa docs(traige): update triaging doc 2016-10-05 15:33:16 -07:00
0528dcb9dc refactor: simplify arrow functions (#12057) 2016-10-05 15:33:16 -07:00
6f7ed32154 fix(ShadowCss): fix attribute selectors in :host and :host-context (#12056)
Fix a regression introduced in #11917 while fixing #6249
2016-10-05 15:33:16 -07:00
1bd8ba80a7 refactor(facade): Remove most of StringMapWrapper facade. (#12022)
This change mostly automated by
12012b07a2
with some manual fixes.
2016-10-05 15:33:16 -07:00
adb17fed98 fix(Header): preserve case of the first init, set() or append() (#12023)
fixes #11624
2016-10-05 15:33:16 -07:00
3067ce6eb4 docs(NgModule): Fixed docs for NgModule.entryComponents (#12006)
* docs(NgModule): Corrected the wording of the documentation of `entryComponents`, fixed some minor grammar issues

* docs(NgModule): Remove redundant ComponentFactory mentions

* docs(NgModule): Restore ComponentFactory/ComponentResolver links
2016-10-05 15:33:16 -07:00
e102cd4757 docs(DEVELOPER.md): fix typos on "Tests" section (#12029) 2016-10-05 15:33:16 -07:00
db00ba7ae7 refactor(facade): remove DateWrapper (#12027) 2016-10-05 15:33:16 -07:00
5a8f116687 text(offline compiler): fix expected output 2016-10-05 15:33:16 -07:00
02a862f8af test(AstSerializer): fix serializing void tags 2016-10-05 15:33:16 -07:00
7578d8573b fix(xlif): fix <x> ctype names
fixes #12000
see http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#ctype
2016-10-05 15:33:16 -07:00
de56e31cf0 style(I18N): Carriage returns in serialized files 2016-10-05 15:33:16 -07:00
eb85a7709a docs(gh): try to improve the issue template (#11891) 2016-10-05 15:33:16 -07:00
c99ef4938f fix(ShadowCss): support @page and @document CSS rules (#11878)
fixes #11860
2016-10-05 15:33:16 -07:00
7395400066 fix(ShadowCss): support quoted attribute values
fixes #6085
2016-10-05 15:33:16 -07:00
d985cc0253 refactor(ShadowCss): add missing types 2016-10-05 15:33:16 -07:00
aca117ac56 fix(ShadowCss): fix :host(tag) and :host-context(tag)
fixes #11972
2016-10-05 15:33:16 -07:00
2c3825f2c8 fix(BrowserAdapter): correctly removes styles on IE
fixes #7916
2016-10-05 15:33:16 -07:00
ea6defcf11 refactor(BrowserAdapter): cleanup 2016-10-05 15:33:16 -07:00
975aca95bb refactor(CssSelector): misc cleanup 2016-10-05 15:33:16 -07:00
5cb78566c2 docs(CssSelector): [name*=value] is not supported
fixes #6042
2016-10-05 15:33:16 -07:00
9bacb32ec5 feat(Parse5): update to the latest version 2.2.1
fixes #6237
2016-10-05 15:33:16 -07:00
6970991546 docs: update docs for ng2_ftl benchmark 2016-10-05 15:33:16 -07:00
bd012efcc4 fix(ShadowCss): support [attr="value with space"]
fixes #6249
2016-10-05 15:33:16 -07:00
2dd399658d refactor(ShadowCss): cleanup 2016-10-05 15:33:16 -07:00
d0dea574cb test(DirectiveResolver): test that a prop can have both @Input and @HostBinding 2016-10-05 15:33:16 -07:00
f7864edd4b refactor(DirectiveResolver): cleanup 2016-10-05 15:33:16 -07:00
9cc0a4ed10 fix(UrlSearchParams): change a behavior when a param value is null or undefined (#11990) 2016-10-05 15:33:16 -07:00
3ee8c75eff refactor(routerLinkActive): optimised routerLinkActive active check code (#11968)
Modify routerLinkActive to optimise performance by removing unnecessary iteration. By replacing Array.reduce with Array.some, the loop will break when it finds an active link. Useful if used on the parent of a large group of routerLinks. Furthermore, if a RouterLink is active it will not check the RouterLinkWithHrefs.
2016-10-05 15:33:16 -07:00
b39d3a173e refactor(facade): Inline isBlank called with object-type argument (#11992) 2016-10-05 15:33:16 -07:00
a4af1561b7 benchmarks: add ng2_ftl and ng2_switch_ftl benchmarks (#11963)
These benchmarks take the output of AoT
and manually tweaks it to explore possible
future changes to the compiler to produce
this output directly.
2016-10-05 15:33:16 -07:00
0851238e78 fix(upgrade): bind optional properties when upgrading from ng1 (#11411)
Previously, optional properties of a directive/component would be wrongly mapped and thus ignored.

Closes #10181
2016-10-05 15:33:16 -07:00
d2d98dad61 docs(forms): Added FormControl initialization information (#11948) 2016-10-05 15:33:16 -07:00
826c98e50c fix(ngc): allow ReflectorHost passed as argument to CodeGenerator#create (#11951) 2016-10-05 15:33:16 -07:00
830e6352dd chore(lint): remove unused imports (#11923)
This was done automatically by tslint, which can now fix issues it finds.
The fixer is still pending in PR https://github.com/palantir/tslint/pull/1568
Also I have a local bugfix for https://github.com/palantir/tslint/issues/1569
which causes too many imports to be deleted.
2016-10-05 15:33:16 -07:00
5911c3bd43 fix(compiler): move detection of unsafe properties for binding to ElementSchemaRegistry (#11378) 2016-10-05 15:33:16 -07:00
51e1994af0 fix(compiler): Do not embed templateUrl in view factories in non-debug mode. (#11818)
Fixes #11117.
2016-10-05 15:33:16 -07:00
faf5d90bf6 refactor: remove dead code 2016-10-05 15:33:16 -07:00
7e5413da89 refactor(facade): remove useless facades 2016-10-05 15:33:16 -07:00
e82a78e641 docs(upgrade): rename undeclared Ng2 to Ng2Component (#11950) 2016-10-05 15:33:16 -07:00
c13e55c8c3 (docs): removing addProvider from UpgradeAdapter (#11934)
The `addProvider` function in the `UpgradeAdapter` was deprecated in this [commit](d21331e902 (diff-77163e956a7842149f583846c1c01651)) and has been removed in final. Given this, the documentation for downgrading ng2 providers for use in ng1 is invalid.
2016-10-05 15:33:16 -07:00
a153504212 docs(router_config): add missing quote (#11925) 2016-10-05 15:33:16 -07:00
b8a75818ee docs: remove outdated docs (#11875) 2016-10-05 15:33:16 -07:00
f633826e99 chore(CHANGELOG): fix wrong issue link (#11871) 2016-10-05 15:33:16 -07:00
0a8887240a docs(ExceptionHandler): fix API docs (#11772)
fixes #11769
2016-10-05 15:33:16 -07:00
6d606dd02b ci(travis): increase node's heap size to prevent OOM on travis (#11869) 2016-10-05 15:33:16 -07:00
5c4215ccb4 Fix(http): invalidStateError if response body without content (#11786)
Fix(http): invalidStateError if response body without content
If the responseType has been specified and other than 'text', responseText throw an InvalidStateError exception

See XHR doc => https://xhr.spec.whatwg.org/#the-responsetext-attribute

Unit Test to prevent invalidStateError
2016-10-05 15:33:16 -07:00
85489a166e refactor(animations): ensure animation input/outputs are managed within the template parser (#11782)
Closes #11782
Closes #11601
Related #11707
2016-10-05 15:33:16 -07:00
cf750e17ed fix(router): do not reset the router state when updating the component (#11867) 2016-09-24 07:14:06 +09:00
712d1a7c37 chore(release): v2.0.1 2016-09-23 11:28:36 -07:00
16601f9359 docs(changelog): add changelog for 2.0.1 2016-09-23 10:50:42 -07:00
b81e2e7a31 fix(upgrade): allow attribute selectors for components in ng2 which are not part of upgrade (#11808)
fixes #11280
2016-09-23 10:48:47 -07:00
98fac36706 docs(Component): API docs for .encapsulation and .interpolation 2016-09-23 10:22:24 -07:00
3e780c032e refactor: misc cleanup 2016-09-23 10:22:05 -07:00
e09882180e refactor(common): cleanup (#11668) 2016-09-23 10:21:58 -07:00
0e18c57a17 docs(core): mark TestBed as stable api and add preliminary docs (#11767)
TestBed was accidentaly ommited from the 'stable' api list during the API sweep before final. We do consider it to be stable.
2016-09-23 10:21:50 -07:00
51e2b9c073 docs(contributing): remove preview references (#11795) 2016-09-23 10:21:44 -07:00
f218e240d3 ci(BrowserStack): add Safari 10 (#11796) 2016-09-23 10:21:31 -07:00
af6b219f8e refactor(TemplateParser): clearer error message for on* binding (#11802)
fixes #11756
2016-09-23 10:21:15 -07:00
20addf5f9f chore(ISSUE_TEMPLATE): update Angular version field (#11821) 2016-09-23 10:21:02 -07:00
2860418a3c fix(forms): disable all radios with disable() 2016-09-23 10:19:58 -07:00
39e251eea7 fix(forms): support unbound disabled in ngModel (#11736) 2016-09-23 10:19:46 -07:00
d7d716d5db chore(zone.js): update to 0.6.25 (#11725) 2016-09-23 10:19:30 -07:00
a95d65241c fix(compiler): Safe property access expressions work in event bindings (#11724) 2016-09-23 10:19:24 -07:00
fdb22bd185 refactor: misc cleanup (#11654) 2016-09-23 10:18:38 -07:00
355 changed files with 5319 additions and 11308 deletions

View File

@ -1,131 +1,3 @@
<a name="2.2.0-beta.1"></a>
# [2.2.0-beta.1](https://github.com/angular/angular/compare/2.2.0-beta.0...2.2.0-beta.1) (2016-10-27)
### Bug Fixes
* **compiler:** don't access view local variables nor pipes in host expressions ([#12396](https://github.com/angular/angular/issues/12396)) ([867494a](https://github.com/angular/angular/commit/867494a)), closes [#12004](https://github.com/angular/angular/issues/12004) [#12071](https://github.com/angular/angular/issues/12071)
* **compiler:** walk third party modules ([#12453](https://github.com/angular/angular/issues/12453)) ([a838aba](https://github.com/angular/angular/commit/a838aba)), closes [#11889](https://github.com/angular/angular/issues/11889) [#12428](https://github.com/angular/angular/issues/12428)
* **compiler:** remove double exports of template_ast ([7742ec0](https://github.com/angular/angular/commit/7742ec0))
* **compiler:** use Maps instead of objects in selector implementation ([d321b0e](https://github.com/angular/angular/commit/d321b0e))
* **compiler-cli:** fix types ([ef15364](https://github.com/angular/angular/commit/ef15364))
* **compiler-cli:** assert that all pipes and directives are declared by a module ([7221632](https://github.com/angular/angular/commit/7221632))
* **http:** overwrite already set xsrf header ([b4265e0](https://github.com/angular/angular/commit/b4265e0))
* **router:** add a test to make sure canDeactivate guards are called for aux routes ([fc60fa7](https://github.com/angular/angular/commit/fc60fa7)), closes [#11345](https://github.com/angular/angular/issues/11345)
* **router:** canDeactivate guards are not triggered for componentless routes ([b741853](https://github.com/angular/angular/commit/b741853)), closes [#12375](https://github.com/angular/angular/issues/12375)
* **router:** change router not to deactivate aux routes when navigating from a componentless routes ([52a853e](https://github.com/angular/angular/commit/52a853e))
* **router:** disallow component routes with named outlets ([8f2fa0f](https://github.com/angular/angular/commit/8f2fa0f)), closes [#11208](https://github.com/angular/angular/issues/11208) [#11082](https://github.com/angular/angular/issues/11082)
* **router:** preserve resolve data ([6ccbfd4](https://github.com/angular/angular/commit/6ccbfd4)), closes [#12306](https://github.com/angular/angular/issues/12306)
### Code Refactoring
* **upgrade:** re-export the new static upgrade APIs on new entry ([a26dd28](https://github.com/angular/angular/commit/a26dd28))
### Features
* **router:** export routerLinkActive w/ isActive property ([c9f58cf](https://github.com/angular/angular/commit/c9f58cf))
### BREAKING CHANGES
* upgrade: Four newly added APIs in 2.2.0-beta:
downgradeComponent, downgradeInjectable, UpgradeComponent, and UpgradeModule are no longer exported by @angular/upgrade.
Import these from @angular/upgrade/static instead.
# [2.1.1](https://github.com/angular/angular/compare/2.1.0...2.1.1) (2016-10-20)
### Bug Fixes
* **compiler:** generate aot code for animation trigger output events ([#12291](https://github.com/angular/angular/issues/12291)) ([6e5f8b5](https://github.com/angular/angular/commit/6e5f8b5)), closes [#11707](https://github.com/angular/angular/issues/11707)
* **compiler:** don't redeclare a var in the same scope ([#12386](https://github.com/angular/angular/issues/12386)) ([cca4a5c](https://github.com/angular/angular/commit/cca4a5c))
* **core:** fix decorator default values ([bd1dcb5](https://github.com/angular/angular/commit/bd1dcb5))
* **core:** fix property decorators ([3993279](https://github.com/angular/angular/commit/3993279)), closes [#12224](https://github.com/angular/angular/issues/12224)
* **http:** make normalizeMethodName optimizer-compatible. ([#12370](https://github.com/angular/angular/issues/12370)) ([8409b65](https://github.com/angular/angular/commit/8409b65))
* **router:** correctly export filter operator in es5 ([#12286](https://github.com/angular/angular/issues/12286)) ([27d7677](https://github.com/angular/angular/commit/27d7677))
* **router:** do not update primary route if only secondary outlet is given ([#11797](https://github.com/angular/angular/issues/11797)) ([da5fc69](https://github.com/angular/angular/commit/da5fc69))
* **router:** fix lazy loading triggered by redirects from wildcard routes ([5ae6915](https://github.com/angular/angular/commit/5ae6915)), closes [#12183](https://github.com/angular/angular/issues/12183)
* **router:** module loader should start compiling modules when stubbedModules are set ([#11742](https://github.com/angular/angular/issues/11742)) ([b44b6ef](https://github.com/angular/angular/commit/b44b6ef))
### Performance Improvements
* **common:** optimize NgSwitch default case ([fdf4309](https://github.com/angular/angular/commit/fdf4309))
<a name="2.2.0-beta.0"></a>
# [2.2.0-beta.0](https://github.com/angular/angular/compare/2.1.0...2.2.0-beta.0) (2016-10-20)
### Features
* **common:** support narrow forms for month and weekdays in DatePipe ([#12297](https://github.com/angular/angular/issues/12297)) ([f77ab6a](https://github.com/angular/angular/commit/f77ab6a)), closes [#12294](https://github.com/angular/angular/issues/12294)
* **forms:** add hasError and getError to AbstractControlDirective ([#11985](https://github.com/angular/angular/issues/11985)) ([592f40a](https://github.com/angular/angular/commit/592f40a)), closes [#7255](https://github.com/angular/angular/issues/7255)
* **forms:** add ng-pending CSS class during async validation ([#11243](https://github.com/angular/angular/issues/11243)) ([97bc971](https://github.com/angular/angular/commit/97bc971)), closes [#10336](https://github.com/angular/angular/issues/10336)
* **forms:** Added emitEvent to AbstractControl methods ([#11949](https://github.com/angular/angular/issues/11949)) ([b9fc090](https://github.com/angular/angular/commit/b9fc090))
* **forms:** make 'parent' a public property of 'AbstractControl' ([#11855](https://github.com/angular/angular/issues/11855)) ([445e592](https://github.com/angular/angular/commit/445e592))
* **forms:** Validator.pattern accepts a RegExp ([#12323](https://github.com/angular/angular/issues/12323)) ([bf60418](https://github.com/angular/angular/commit/bf60418))
* **upgrade:** add support for AoT compiled upgrade applications ([d6791ff](https://github.com/angular/angular/commit/d6791ff)), closes [#12239](https://github.com/angular/angular/issues/12239)
* **router:** add support for ng1/ng2 migration ([#12160](https://github.com/angular/angular/issues/12160)) ([8b9ab44](https://github.com/angular/angular/commit/8b9ab44))
Note: The 2.2.0-beta.0 release also contains all the changes present in the 2.1.1 release.
<a name="2.1.0"></a>
# [2.1.0 incremental-metamorphosis](https://github.com/angular/angular/compare/2.1.0-rc.0...2.1.0) (2016-10-12)
### Bug Fixes
* **compiler:** allow whitespace as `<ng-content>` content ([#12225](https://github.com/angular/angular/issues/12225)) ([df1718d](https://github.com/angular/angular/commit/df1718d))
* **compiler:** interpolation expressions report the correct offset ([#12125](https://github.com/angular/angular/issues/12125)) ([d641c36](https://github.com/angular/angular/commit/d641c36))
* **compiler:** properly shim `:host:before` and `:host(:before)` ([#12171](https://github.com/angular/angular/issues/12171)) ([aa92512](https://github.com/angular/angular/commit/aa92512)), closes [#12165](https://github.com/angular/angular/issues/12165)
* **compiler:** validate `@HostBinding` name ([#12139](https://github.com/angular/angular/issues/12139)) ([13ecc14](https://github.com/angular/angular/commit/13ecc14))
* **compiler-cli:** don't clone static symbols when simplifying annotation metadata ([#12158](https://github.com/angular/angular/issues/12158)) ([8c477b2](https://github.com/angular/angular/commit/8c477b2))
* **compiler-cli:** remove peerDependency on [@angular](https://github.com/angular)/platform-server ([#12122](https://github.com/angular/angular/issues/12122)) ([71b7654](https://github.com/angular/angular/commit/71b7654))
* **compiler-cli:** remove unused parse5 dependency from package.json ([eaaec69](https://github.com/angular/angular/commit/eaaec69))
* **forms:** allow optional fields with pattern and minlength validators ([#12147](https://github.com/angular/angular/issues/12147)) ([d22eeb7](https://github.com/angular/angular/commit/d22eeb7))
* **forms:** properly validate blank strings with minlength ([#12091](https://github.com/angular/angular/issues/12091)) ([f50c1da](https://github.com/angular/angular/commit/f50c1da))
* **http:** fix Headers initialization from Headers and Object ([#12106](https://github.com/angular/angular/issues/12106)) ([f4566f8](https://github.com/angular/angular/commit/f4566f8))
* **http:** Headers.append should append to the list ([a67c067](https://github.com/angular/angular/commit/a67c067))
* **platform-browser-dynamic:** mark platformBrowserDynamic as stable API ([#12154](https://github.com/angular/angular/issues/12154)) ([bcef5ef](https://github.com/angular/angular/commit/bcef5ef))
* **router:** improve error message ([#12102](https://github.com/angular/angular/issues/12102)) ([e06303a](https://github.com/angular/angular/commit/e06303a))
* **router:** parent resolve should complete before merging resolved data ([1681e4f](https://github.com/angular/angular/commit/1681e4f)), closes [#12032](https://github.com/angular/angular/issues/12032)
* **router:** wildcards routes should support lazy loading ([40b92dd](https://github.com/angular/angular/commit/40b92dd)), closes [#12024](https://github.com/angular/angular/issues/12024)
* **upgrade:** allow compilerOptions in bootstrap ([#10575](https://github.com/angular/angular/issues/10575)) ([5effc33](https://github.com/angular/angular/commit/5effc33))
<a name="2.1.0-rc.0"></a>
# [2.1.0-rc.0](https://github.com/angular/angular/compare/2.1.0-beta.0...2.1.0-rc.0) (2016-10-05)
### Features
* **animations:** provide aliases for `:enter` and `:leave` transitions ([#11991](https://github.com/angular/angular/issues/11991)) ([e884f48](https://github.com/angular/angular/commit/e884f48))
Note: 2.1.0-rc.0 release also contains all the changes present in the 2.0.2 release.
<a name="2.1.0-beta.0"></a>
# [2.1.0-beta.0](https://github.com/angular/angular/compare/2.0.0...2.1.0-beta.0) (2016-09-23)
### Features
* **router:** add router preloader to optimistically preload routes ([5a84982](https://github.com/angular/angular/commit/5a84982))
### Bug Fixes
* **router:** update the router not to reset router state when updating root component ([#11799](https://github.com/angular/angular/issues/11799)) ([31dce72](https://github.com/angular/angular/commit/31dce72))
Note: 2.1.0-beta.0 release also contains all the changes present in the 2.0.1 release.
<a name="2.0.2"></a>
## [2.0.2](https://github.com/angular/angular/compare/2.0.1...2.0.2) (2016-10-05)
@ -135,18 +7,18 @@ Note: 2.1.0-beta.0 release also contains all the changes present in the 2.0.1 re
* **common:** correctly removes styles on IE ([#11953](https://github.com/angular/angular/pull/11953)), closes [#7916](https://github.com/angular/angular/issues/7916)
* **compiler:** do not embed templateUrl in view factories in non-debug mode. ([#11818](https://github.com/angular/angular/issues/11818)) ([51e1994](https://github.com/angular/angular/commit/51e1994)), closes [#11117](https://github.com/angular/angular/issues/11117)
* **compiler:** move detection of unsafe properties for binding to ElementSchemaRegistry ([#11378](https://github.com/angular/angular/issues/11378)) ([5911c3b](https://github.com/angular/angular/commit/5911c3b))
* **compiler:** fix `:host(tag)` and `:host-context(tag)` ([a6bb84e0](https://github.com/angular/angular/commit/a6bb84e02b7579f8d957ef6ba5b10d83482ed756)), closes [#11972](https://github.com/angular/angular/issues/11972)
* **compiler:** fix attribute selectors in :host and :host-context ([#12056](https://github.com/angular/angular/issues/12056)) ([6f7ed32](https://github.com/angular/angular/commit/6f7ed32)), closes [#11917](https://github.com/angular/angular/issues/11917)
* **compiler:** support `@page` and `@document` CSS rules ([#11878](https://github.com/angular/angular/issues/11878)) ([c99ef49](https://github.com/angular/angular/commit/c99ef49)), closes [#11860](https://github.com/angular/angular/issues/11860)
* **compiler:** support `[attr="value with space"]` ([bd012ef](https://github.com/angular/angular/commit/bd012ef)), closes [#6249](https://github.com/angular/angular/issues/6249)
* **compiler:** support quoted attribute values ([7395400](https://github.com/angular/angular/commit/7395400)), closes [#6085](https://github.com/angular/angular/issues/6085)
* **compiler:** fix `<x>` ctype names ([7578d85](https://github.com/angular/angular/commit/7578d85)), closes [#12000](https://github.com/angular/angular/issues/12000)
* **compiler-cli:** allow ReflectorHost passed as argument to CodeGenerator#create ([#11951](https://github.com/angular/angular/issues/11951)) ([826c98e](https://github.com/angular/angular/commit/826c98e))
* **forms:** properly validate empty strings with patterns ([#11450](https://github.com/angular/angular/issues/11450)) ([e00de0c](https://github.com/angular/angular/commit/e00de0c))
* **http:** preserve case of the first init, `set()` or `append()` ([#12023](https://github.com/angular/angular/issues/12023)) ([adb17fe](https://github.com/angular/angular/commit/adb17fe)), closes [#11624](https://github.com/angular/angular/issues/11624)
* **http:** remove url params if provided value is null or undefined ([#11990](https://github.com/angular/angular/issues/11990)) ([9cc0a4e](https://github.com/angular/angular/commit/9cc0a4e))
* **compiler-cli:** allow ReflectorHost passed as argument to CodeGenerator#create ([#11951](https://github.com/angular/angular/issues/11951)) ([826c98e](https://github.com/angular/angular/commit/826c98e))
* **router:** do not reset the router state when updating the component ([#11867](https://github.com/angular/angular/issues/11867)) ([cf750e1](https://github.com/angular/angular/commit/cf750e1))
* **compiler:** fix `:host(tag)` and `:host-context(tag)` ([a6bb84e0](https://github.com/angular/angular/commit/a6bb84e02b7579f8d957ef6ba5b10d83482ed756)), closes [#11972](https://github.com/angular/angular/issues/11972)
* **compiler:** fix attribute selectors in :host and :host-context ([#12056](https://github.com/angular/angular/issues/12056)) ([6f7ed32](https://github.com/angular/angular/commit/6f7ed32)), closes [#11917](https://github.com/angular/angular/issues/11917)
* **compiler:** support `[@page](https://github.com/page)` and `[@document](https://github.com/document)` CSS rules ([#11878](https://github.com/angular/angular/issues/11878)) ([c99ef49](https://github.com/angular/angular/commit/c99ef49)), closes [#11860](https://github.com/angular/angular/issues/11860)
* **compiler:** support `[attr="value with space"]` ([bd012ef](https://github.com/angular/angular/commit/bd012ef)), closes [#6249](https://github.com/angular/angular/issues/6249)
* **compiler:** support quoted attribute values ([7395400](https://github.com/angular/angular/commit/7395400)), closes [#6085](https://github.com/angular/angular/issues/6085)
* **upgrade:** bind optional properties when upgrading from ng1 ([#11411](https://github.com/angular/angular/issues/11411)) ([0851238](https://github.com/angular/angular/commit/0851238)), closes [#10181](https://github.com/angular/angular/issues/10181)
* **http:** change a behavior when a param value is null or undefined ([#11990](https://github.com/angular/angular/issues/11990)) ([9cc0a4e](https://github.com/angular/angular/commit/9cc0a4e))
* **compiler:** fix `<x>` ctype names ([7578d85](https://github.com/angular/angular/commit/7578d85)), closes [#12000](https://github.com/angular/angular/issues/12000)
<a name="2.0.1"></a>
@ -169,7 +41,7 @@ Note: 2.1.0-beta.0 release also contains all the changes present in the 2.0.1 re
<a name="2.0.0"></a>
# [2.0.0 proprioception-reinforcement](https://github.com/angular/angular/compare/2.0.0-rc.7...2.0.0) (2016-09-14)
# [2.0.0](https://github.com/angular/angular/compare/2.0.0-rc.7...2.0.0) (2016-09-14)
### Bug Fixes
@ -382,7 +254,7 @@ Note: 2.1.0-beta.0 release also contains all the changes present in the 2.0.1 re
use `Type<any>` in place of `Type`.
We don't expect that any user applications use the `Type` type directly.
* core: Previously inconsistently named APIs SanitizationService and DomSanitizationService were renamed to Sanitizer and DomSanitizer
* core: previously deprecated @Component.directives and @Component.pipes support was removed.
@ -396,11 +268,11 @@ use `Type<any>` in place of `Type`.
* core: deprecated ComponentResolver was removed. Please use ComponentFactoryResolver instead.
* core: animations defined using an at-symbol prefix that are not property bound are now invalid.
```html
<!-- this is now invalid -->
<div @flip="flipState"></div>
<!-- change that to -->
<div [@flip]="flipState"></div>
```
@ -426,7 +298,7 @@ prefix using `animate-` must now be preixed using `bind-animate-`.
```
{provide: MyClass, useFactory: ...}
```
* core: previously deprecated NgZoneError has been removed
* core: Exceptions are no longer part of the public API. We don't expect that anyone should be referring to the Exception types.
@ -438,7 +310,7 @@ prefix using `animate-` must now be preixed using `bind-animate-`.
```
ErrorHandler.handleError(error: any): void;
```
* core: deprecated DynamicComponentLoader was removed; see deprecation notice for migration instructions.
* core: deprecated SystemJsComponentResolver and SystemJsCmpFactoryResolver have been removed.
@ -472,13 +344,13 @@ prefix using `animate-` must now be preixed using `bind-animate-`.
* platform-browser-dynamic: `CACHED_TEMPLATE_PROVIDER` is now renamed to `RESOURCE_CACHE_PROVIDER`
Before:
```js
import {CACHED_TEMPLATE_PROVIDER} from '@angular/platform-browser-dynamic';
```
After:
```js
import {RESOURCE_CACHE_PROVIDER} from '@angular/platform-browser-dynamic';
```
@ -496,7 +368,7 @@ prefix using `animate-` must now be preixed using `bind-animate-`.
* webworkers: web worker platform is now exported via separate packages.
Please use @angular/platform-webworker and @angular/platform-webworker-dynamic
<a name="2.0.0-rc.5"></a>

View File

@ -1,6 +1,6 @@
# Contributing to Angular
# Contributing to Angular 2
We would love for you to contribute to Angular and help make it even better than it is
We would love for you to contribute to Angular 2 and help make it even better than it is
today! As a contributor, here are the guidelines we would like you to follow:
- [Code of Conduct](#coc)
@ -17,26 +17,17 @@ Help us keep Angular open and inclusive. Please read and follow our [Code of Con
## <a name="question"></a> Got a Question or Problem?
Please, do not open issues for the general support questions as we want to keep GitHub issues for bug reports and feature requests. You've got much better chances of getting your question answered on [StackOverflow](stackoverflow.com/questions/tagged/angular) where the questions should be tagged with tag `angular`.
If you have questions about how to *use* Angular, please direct them to the [Google Group][angular-group]
discussion list or [StackOverflow][stackoverflow]. Please note that the Angular team's capacity to answer usage questions is limited. We are also available on [Gitter][gitter].
StackOverflow is a much better place to ask questions since:
- there are thousands of people willing to help on StackOverflow
- questions and answers stay available for public viewing so your question / answer might help someone else
- StackOverflow's voting system assures that the best answers are prominently visible.
To save your and our time we will be systematically closing all the issues that are requests for general support and redirecting people to StackOverflow.
If you would like to chat about the question in real-time, you can reach out via [our gitter channel][gitter].
## <a name="issue"></a> Found a Bug?
## <a name="issue"></a> Found an Issue?
If you find a bug in the source code, you can help us by
[submitting an issue](#submit-issue) to our [GitHub Repository][github]. Even better, you can
[submit a Pull Request](#submit-pr) with a fix.
## <a name="feature"></a> Missing a Feature?
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub
Repository. If you would like to *implement* a new feature, please submit an issue with
## <a name="feature"></a> Want a Feature?
You can *request* a new feature by [submitting an issue](#submit-issue) to our [GitHub
Repository][github]. If you would like to *implement* a new feature, please submit an issue with
a proposal for your work first, to be sure that we can use it.
Please consider what kind of change it is:
@ -48,22 +39,24 @@ and help you to craft the change so that it is successfully accepted into the pr
## <a name="submit"></a> Submission Guidelines
### <a name="submit-issue"></a> Submitting an Issue
Before you submit an issue, search the archive, maybe your question was already answered.
Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.
If your issue appears to be a bug, and hasn't been reported, open a new issue.
Help us to maximize the effort we can spend fixing issues and adding new
features, by not reporting duplicate issues. Providing the following information will increase the
chances of your issue being dealt with quickly:
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs we will systematically ask you to provide a minimal reproduction scenario using http://plnkr.co. Having a live, reproducible scenario gives us wealth of important information without going back & forth to you with additional questions like:
* **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps
* **Angular Version** - what version of Angular is affected (e.g. 2.0.0-alpha.53)
* **Motivation for or Use Case** - explain what are you trying to do and why the current behavior is a bug for you
* **Browsers and Operating System** - is this a problem with all browsers?
* **Reproduce the Error** - provide a live example (using [Plunker][plunker],
[JSFiddle][jsfiddle] or [Runnable][runnable]) or a unambiguous set of steps
* **Related Issues** - has a similar issue been reported before?
* **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be
causing the problem (line of code or commit)
- version of Angular used
- 3rd-party libraries and their versions
- and most importantly - a use-case that fails
A minimal reproduce scenario using http://plnkr.co/ allows us to quickly confirm a bug (or point out coding problem) as well as confirm that we are fixing the right problem. If plunker is not a suitable way to demostrate the problem (for example for issues related to our npm packaging), please create a standalone git repository demostrating the problem.
We will be insisting on a minimal reproduce scenario in order to save maintainers time and ultimately be able to fix more bugs. Interestingly, from our experience users often find coding problems themselves while preparing a minimal plunk. We understand that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate the problem before we can fix it.
Unfortunately we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you we are going to close an issue that don't have enough info to be reproduced.
You can file new issues by filling out our [new issue form](https://github.com/angular/angular/issues/new).
You can file new issues by providing the above information [here](https://github.com/angular/angular/issues/new).
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
@ -101,7 +94,7 @@ Before you submit your Pull Request (PR) consider the following guidelines:
* In GitHub, send a pull request to `angular:master`.
* If we suggest changes then:
* Make the required updates.
* Re-run the Angular test suites to ensure tests are still passing.
* Re-run the Angular 2 test suites to ensure tests are still passing.
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
```shell

View File

@ -1,62 +0,0 @@
# Saved Responses for Angular's Issue Tracker
The following are canned responses that the Angular team should use to close issues on our issue tracker that fall into the listed resolution categories.
Since GitHub currently doesn't allow us to have a repository-wide or organization-wide list of [saved replies](https://help.github.com/articles/working-with-saved-replies/), these replies need to be maintained by individual team members. Since the responses can be modified in the future, all responses are versioned to simplify the process of keeping the responses up to date.
## Angular: Already Fixed (v1)
```
Thanks for reporting this issue. Luckily it has already been fixed in one of the recent releases. Please update to the most recent version to resolve the problem.
If after upgrade the problem still exists in your application please open a new issue and provide a plunker reproducing the problem and describing the difference between the expected and current behavior. You can use this plunker template: http://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5?p=catalogue
```
## Angular: Don't Understand (v1)
```
I'm sorry but we don't understand the problem you are reporting.
If the problem still exists please open a new issue and provide a plunker reproducing the problem and describing the difference between the expected and current behavior. You can use this plunker template: http://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5?p=catalogue
```
## Angular: Duplicate (v1)
```
Thanks for reporting this issue. However this issue is a duplicate of an existing issue #<ISSUE_NUMBER>. Please subscribe to that issue for future updates.
```
## Angular: Insufficient Information Provided (v1)
```
Thanks for reporting this issue. However, you didn't provide sufficient information for us to understand and reproduce the problem. Please check out [our submission guidelines](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-submitting-an-issue) to understand why we can't act on issues that are lacking important information.
If the problem still persists, please file a new issue and ensure you provide all of the required information when filling out the issue template.
```
## Angular: Issue Outside of Angular (v1)
```
I'm sorry but this issue is not caused by Angular. Please contact the author(s) of project <PROJECT NAME> or file issue on their issue tracker.
```
## Angular: Non-reproducible (v1)
```
I'm sorry but we can't reproduce the problem following the instructions you provided.
If the problem still exists please open a new issue following [our submission guidelines](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-submitting-an-issue).
```
## Angular: Obsolete (v1)
```
Thanks for reporting this issue. This issue is now obsolete due to changes in the recent releases. Please update to the most recent Angular version.
If the problem still persists, please file a new issue and ensure you provide the version of Angular affected and include the steps to reproduce the problem when filling out the issue template.
```
## Angular: Support Request (v1)
```
Hello, we reviewed this issue and determined that it doesn't fall into the bug report or feature request category. This issue tracker is not suitable for support requests, please repost your issue on [StackOverflow](http://stackoverflow.com/) using tag `angular`.
If you are wondering why we don't resolve support issues via the issue tracker, please [check out this explanation](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-got-a-question-or-problem).
```

View File

@ -1,7 +1,7 @@
# Triage Process and Github Labels for Angular 2
This document describes how the Angular team uses labels and milestones
to triage issues on github. The basic idea of the process is that
to triage issues on github. The basic idea of the new process is that
caretaker only assigns a component and type (bug, feature) label. The
owner of the component than is in full control of how the issues should
be triaged further.
@ -35,7 +35,7 @@ There are few components which are cross-cutting. They don't have
a clear location in the source tree. We will treat them as a component
even thought no specific source tree is associated with them.
* `comp: docs`: `@naomiblack`
* `comp: documentation`: `@naomiblack`
* `comp: packaging`: `@IgorMinar`
* `comp: performance`: `@tbosch`
* `comp: security`: `@IgorMinar`
@ -53,11 +53,11 @@ What kind of problem is this?
## Caretaker Triage Process
It is the caretaker's responsibility to assign `comp: *` to each new
issue as they come in. The reason why we limit the responsibility of the
caretaker to this one label is that it is likely that without domain
knowledge the caretaker could mislabel issues or lack knowledge of
duplicate issues.
It is the caretaker's responsibility to assign `comp: *` and `type: *`
to each new issue as they come in. The reason why we limit the
responsibility of the caretaker to these two labels is that it is
unlikely that without domain knowledge the caretaker could add any
additional labels of value.
## Component's owner Triage Process
@ -68,37 +68,11 @@ process for their component.
It will be up to the component owner to determine the order in which the
issues within the component will be resolved.
Several owners have adopted the issue categorization based on
[user pain](http://www.lostgarden.com/2008/05/improving-bug-triage-with-user-pain.html)
used by Angular 1. In this system every issue is assigned frequency and
severity based on which the total user pain score is calculated.
Following is the definition of various frequency and severity levels:
1. `freq(score): *` How often does this issue come up? How many developers does this affect?
* low (1) - obscure issue affecting a handful of developers
* moderate (2) - impacts auxiliary usage patterns, only small number of applications are affected
* high (3) - impacts primary usage patterns, affecting most Angular apps
* critical (4) - impacts all Angular apps
1. `severity(score): *` - How bad is the issue?
* inconvenience (1) - causes ugly/boilerplate code in apps
* confusing (2) - unexpected or inconsistent behavior; hard-to-debug
* broken expected use (3) - it's hard or impossible for a developer using Angular to accomplish something that Angular should be able to do
* memory leak (4)
* regression (5) - functionality that used to work no longer works in a new release due to an unintentional change
* security issue (6)
These criteria are then used to calculate a "user pain" score as follows:
`pain = severity × frequency`
### Assigning Issues to Milestones
Any issue that is being worked on must have:
* An `Assignee`: The person doing the work.
* An `assignee`: The person doing the work.
* A `Milestone`: When we expect to complete this work.
We aim to only have at most three milestones open at a time:

View File

@ -101,9 +101,7 @@ do
DESTDIR=${PWD}/dist/packages-dist/${PACKAGE}
UMD_ES5_PATH=${DESTDIR}/bundles/${PACKAGE}.umd.js
UMD_TESTING_ES5_PATH=${DESTDIR}/bundles/${PACKAGE}-testing.umd.js
UMD_STATIC_ES5_PATH=${DESTDIR}/bundles/${PACKAGE}-static.umd.js
UMD_ES5_MIN_PATH=${DESTDIR}/bundles/${PACKAGE}.umd.min.js
UMD_STATIC_ES5_MIN_PATH=${DESTDIR}/bundles/${PACKAGE}-static.umd.min.js
LICENSE_BANNER=${PWD}/modules/@angular/license-banner.txt
rm -rf ${DESTDIR}
@ -159,18 +157,6 @@ do
cat ${UMD_TESTING_ES5_PATH} >> ${UMD_TESTING_ES5_PATH}.tmp
mv ${UMD_TESTING_ES5_PATH}.tmp ${UMD_TESTING_ES5_PATH}
fi
if [[ -e rollup-static.config.js ]]; then
echo "====== Rollup ${PACKAGE} static"
../../../node_modules/.bin/rollup -c rollup-static.config.js
# create dir because it doesn't exist yet, we should move the src code here and remove this line
mkdir ${DESTDIR}/static
echo "{\"main\": \"../bundles/${PACKAGE}-static.umd.js\"}" > ${DESTDIR}/static/package.json
cat ${LICENSE_BANNER} > ${UMD_STATIC_ES5_PATH}.tmp
cat ${UMD_STATIC_ES5_PATH} >> ${UMD_STATIC_ES5_PATH}.tmp
mv ${UMD_STATIC_ES5_PATH}.tmp ${UMD_STATIC_ES5_PATH}
$UGLIFYJS -c --screw-ie8 --comments -o ${UMD_STATIC_ES5_MIN_PATH} ${UMD_STATIC_ES5_PATH}
fi
) 2>&1 | grep -v "as external dependency"
fi

View File

@ -1,40 +0,0 @@
# Supported Public API Surface of Angular
Our SemVer, timed-release cycle and deprecation policy currently applies to these npm packages:
- `@angular/core`
- `@angular/common`
- `@angular/platform-browser`
- `@angular/platform-browser-dynamic`
- `@angular/platform-server`
- `@angular/platform-webworker`
- `@angular/platform-webworker-dynamic`
- `@angular/upgrade`
- `@angular/router`
- `@angular/forms`
- `@angular/http`
One intentional omission from this list is `@angular/compiler`, which is currently considered a low level api and is subject to internal changes. These changes will not affect any applications or libraries using the higher-level apis (the command line interface or JIT compilation via `@angular/platform-browser-dynamic`). Only very specific use-cases require direct access to the compiler API (mostly tooling integration for IDEs, linters, etc). If you are working on this kind of integration, please reach out to us first.
Additionally only the command line usage (not direct use of APIs) of `@angular/compiler-cli` is covered.
Other projects developed by the Angular team like angular-cli, Angular Material, benchpress, will be covered by these or similar guarantees in the future as they mature.
Within the supported packages, we provide guarantees for:
- symbols exported via the main entry point (e.g. `@angular/core`) and testing entry point (e.g. `@angular/core/testing`). This applies to both runtime/JavaScript values and TypeScript types.
- symbols exported via global namespace `ng` (e.g. `ng.core`)
- bundles located in the `bundles/` directory of our npm packages (e.g. `@angular/core/bundles/core.umd.js`)
We explicitly don't consider the following to be our public API surface:
- any file/import paths within our package except for the `/`, `/testing` and `/bundles/*`
- constructors of injectable classes (services and directives) - please use DI to obtain instances of these classes
- any class members or symbols marked as `private` or prefixed with underscore
- extending any of our classes unless the support for this is specifically documented in the API docs
- the contents and API surface of the code generated by Angular's compiler (with one notable exception: the existence and name of `NgModuleFactory` instances exported from generated code is guaranteed)
Our peer dependencies (e.g. typescript, zone.js, or rxjs) are not considered part of our API surface, but they are included in our SemVer policies. We might update the required version of any of these dependencies in minor releases if the update doesn't cause breaking changes for Angular applications. Peer dependency updates that result in non-trivial breaking changes must be deferred to major Angular releases.

View File

@ -58,7 +58,6 @@ const entrypoints = [
//'dist/packages-dist/compiler/index.d.ts',
//'dist/packages-dist/compiler/testing.d.ts',
'dist/packages-dist/upgrade/index.d.ts',
'dist/packages-dist/upgrade/static.d.ts',
'dist/packages-dist/platform-browser/index.d.ts',
'dist/packages-dist/platform-browser/testing/index.d.ts',
'dist/packages-dist/platform-browser-dynamic/index.d.ts',

View File

@ -23,7 +23,7 @@ module.exports = function(config) {
'node_modules/core-js/client/core.js',
// include Angular v1 for upgrade module testing
'node_modules/angular/angular.js',
'node_modules/angular/angular.min.js',
'node_modules/zone.js/dist/zone.js', 'node_modules/zone.js/dist/long-stack-trace-zone.js',
'node_modules/zone.js/dist/proxy.js', 'node_modules/zone.js/dist/sync-test.js',

View File

@ -5,7 +5,7 @@ See [here for an example project](https://github.com/angular/benchpress-tree).
The sources for this package are in the main [Angular2](https://github.com/angular/angular) repo. Please file issues and pull requests against that repo.
License: MIT
License: Apache MIT 2.0
# Why?

View File

@ -9,6 +9,7 @@
import {Inject, Injectable} from '@angular/core';
import {Options} from '../common_options';
import {isNumber} from '../facade/lang';
import {Metric} from '../metric';
import {WebDriverAdapter} from '../web_driver_adapter';
@ -43,7 +44,7 @@ export class UserMetric extends Metric {
function getAndClearValues() {
Promise.all(names.map(name => adapter.executeScript(`return window.${name}`)))
.then((values: any[]) => {
if (values.every(v => typeof v === 'number')) {
if (values.every(isNumber)) {
Promise.all(names.map(name => adapter.executeScript(`delete window.${name}`)))
.then((_: any[]) => {
let map: {[k: string]: any} = {};

View File

@ -9,6 +9,7 @@
import {Inject, Injectable, OpaqueToken} from '@angular/core';
import {Options} from '../common_options';
import {Json} from '../facade/lang';
import {MeasureValues} from '../measure_values';
import {Reporter} from '../reporter';
import {SampleDescription} from '../sample_description';
@ -38,14 +39,12 @@ export class JsonFileReporter extends Reporter {
sortedProps(this._description.metrics).forEach((metricName) => {
stats[metricName] = formatStats(validSample, metricName);
});
var content = JSON.stringify(
{
'description': this._description,
'stats': stats,
'completeSample': completeSample,
'validSample': validSample,
},
null, 2);
var content = Json.stringify({
'description': this._description,
'stats': stats,
'completeSample': completeSample,
'validSample': validSample,
});
var filePath = `${this._path}/${this._description.id}_${this._now().getTime()}.json`;
return this._writeFile(filePath, content);
}

View File

@ -6,15 +6,20 @@
* found in the LICENSE file at https://angular.io/license
*/
import {NumberWrapper} from '../facade/lang';
import {MeasureValues} from '../measure_values';
import {Statistic} from '../statistic';
export function formatNum(n: number) {
return n.toFixed(2);
return NumberWrapper.toFixed(n, 2);
}
export function sortedProps(obj: {[key: string]: any}) {
return Object.keys(obj).sort();
var props: string[] = [];
props.push(...Object.keys(obj));
props.sort();
return props;
}
export function formatStats(validSamples: MeasureValues[], metricName: string): string {
@ -24,5 +29,5 @@ export function formatStats(validSamples: MeasureValues[], metricName: string):
var formattedMean = formatNum(mean);
// Note: Don't use the unicode character for +- as it might cause
// hickups for consoles...
return isNaN(cv) ? formattedMean : `${formattedMean}+-${Math.floor(cv)}%`;
return NumberWrapper.isNaN(cv) ? formattedMean : `${formattedMean}+-${Math.floor(cv)}%`;
}

View File

@ -6,6 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Math} from './facade/math';
export class Statistic {
static calculateCoefficientOfVariation(sample: number[], mean: number) {
return Statistic.calculateStandardDeviation(sample, mean) / mean * 100;

View File

@ -8,10 +8,13 @@
import {Inject, Injectable, OpaqueToken} from '@angular/core';
import {ListWrapper} from '../facade/collection';
import {MeasureValues} from '../measure_values';
import {Statistic} from '../statistic';
import {Validator} from '../validator';
/**
* A validator that checks the regression slope of a specific metric.
* Waits for the regression slope to be >=0.
@ -37,17 +40,17 @@ export class RegressionSlopeValidator extends Validator {
validate(completeSample: MeasureValues[]): MeasureValues[] {
if (completeSample.length >= this._sampleSize) {
const latestSample =
completeSample.slice(completeSample.length - this._sampleSize, completeSample.length);
const xValues: number[] = [];
const yValues: number[] = [];
for (let i = 0; i < latestSample.length; i++) {
var latestSample = ListWrapper.slice(
completeSample, completeSample.length - this._sampleSize, completeSample.length);
var xValues: number[] = [];
var yValues: number[] = [];
for (var i = 0; i < latestSample.length; i++) {
// For now, we only use the array index as x value.
// TODO(tbosch): think about whether we should use time here instead
xValues.push(i);
yValues.push(latestSample[i].values[this._metric]);
}
const regressionSlope = Statistic.calculateRegressionSlope(
var regressionSlope = Statistic.calculateRegressionSlope(
xValues, Statistic.calculateMean(xValues), yValues, Statistic.calculateMean(yValues));
return regressionSlope >= 0 ? latestSample : null;
} else {

View File

@ -8,9 +8,12 @@
import {Inject, Injectable, OpaqueToken} from '@angular/core';
import {ListWrapper} from '../facade/collection';
import {MeasureValues} from '../measure_values';
import {Validator} from '../validator';
/**
* A validator that waits for the sample to have a certain size.
*/
@ -25,7 +28,8 @@ export class SizeValidator extends Validator {
validate(completeSample: MeasureValues[]): MeasureValues[] {
if (completeSample.length >= this._sampleSize) {
return completeSample.slice(completeSample.length - this._sampleSize, completeSample.length);
return ListWrapper.slice(
completeSample, completeSample.length - this._sampleSize, completeSample.length);
} else {
return null;
}

View File

@ -8,7 +8,7 @@
import {Injectable} from '@angular/core';
import {isPresent} from '../facade/lang';
import {StringWrapper, isPresent} from '../facade/lang';
import {WebDriverAdapter} from '../web_driver_adapter';
import {PerfLogEvent, PerfLogFeatures, WebDriverExtension} from '../web_driver_extension';
@ -48,6 +48,6 @@ export class FirefoxDriverExtension extends WebDriverExtension {
perfLogFeatures(): PerfLogFeatures { return new PerfLogFeatures({render: true, gc: true}); }
supports(capabilities: {[key: string]: any}): boolean {
return capabilities['browserName'].toLowerCase() === 'firefox';
return StringWrapper.equals(capabilities['browserName'].toLowerCase(), 'firefox');
}
}

View File

@ -8,7 +8,7 @@
import {Injectable} from '@angular/core';
import {isBlank, isPresent} from '../facade/lang';
import {StringWrapper, isBlank, isPresent} from '../facade/lang';
import {WebDriverAdapter} from '../web_driver_adapter';
import {PerfLogEvent, PerfLogFeatures, WebDriverExtension} from '../web_driver_extension';
@ -42,7 +42,7 @@ export class IOsDriverExtension extends WebDriverExtension {
var records: any[] = [];
entries.forEach(entry => {
var message = JSON.parse(entry['message'])['message'];
if (message['method'] === 'Timeline.eventRecorded') {
if (StringWrapper.equals(message['method'], 'Timeline.eventRecorded')) {
records.push(message['params']['record']);
}
});
@ -62,16 +62,19 @@ export class IOsDriverExtension extends WebDriverExtension {
var startTime = record['startTime'];
var endTime = record['endTime'];
if (type === 'FunctionCall' && (data == null || data['scriptName'] !== 'InjectedScript')) {
if (StringWrapper.equals(type, 'FunctionCall') &&
(isBlank(data) || !StringWrapper.equals(data['scriptName'], 'InjectedScript'))) {
events.push(createStartEvent('script', startTime));
endEvent = createEndEvent('script', endTime);
} else if (type === 'Time') {
} else if (StringWrapper.equals(type, 'Time')) {
events.push(createMarkStartEvent(data['message'], startTime));
} else if (type === 'TimeEnd') {
} else if (StringWrapper.equals(type, 'TimeEnd')) {
events.push(createMarkEndEvent(data['message'], startTime));
} else if (
type === 'RecalculateStyles' || type === 'Layout' || type === 'UpdateLayerTree' ||
type === 'Paint' || type === 'Rasterize' || type === 'CompositeLayers') {
StringWrapper.equals(type, 'RecalculateStyles') || StringWrapper.equals(type, 'Layout') ||
StringWrapper.equals(type, 'UpdateLayerTree') || StringWrapper.equals(type, 'Paint') ||
StringWrapper.equals(type, 'Rasterize') ||
StringWrapper.equals(type, 'CompositeLayers')) {
events.push(createStartEvent('render', startTime));
endEvent = createEndEvent('render', endTime);
}
@ -89,7 +92,7 @@ export class IOsDriverExtension extends WebDriverExtension {
perfLogFeatures(): PerfLogFeatures { return new PerfLogFeatures({render: true}); }
supports(capabilities: {[key: string]: any}): boolean {
return capabilities['browserName'].toLowerCase() === 'safari';
return StringWrapper.equals(capabilities['browserName'].toLowerCase(), 'safari');
}
}

View File

@ -28,7 +28,7 @@ export function main() {
if (!descriptions) {
descriptions = [];
}
if (sampleId == null) {
if (isBlank(sampleId)) {
sampleId = 'null';
}
var providers: Provider[] = [

View File

@ -9,7 +9,7 @@
import {AsyncTestCompleter, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
import {JsonFileReporter, MeasureValues, Options, ReflectiveInjector, SampleDescription} from '../../index';
import {isPresent} from '../../src/facade/lang';
import {Json, isPresent} from '../../src/facade/lang';
export function main() {
describe('file reporter', () => {
@ -51,7 +51,7 @@ export function main() {
[mv(0, 0, {'a': 3, 'b': 6}), mv(1, 1, {'a': 5, 'b': 9})]);
var regExp = /somePath\/someId_\d+\.json/;
expect(isPresent(loggedFile['filename'].match(regExp))).toBe(true);
var parsedContent = JSON.parse(loggedFile['content']);
var parsedContent = Json.parse(loggedFile['content']);
expect(parsedContent).toEqual({
'description': {
'id': 'someId',

View File

@ -212,7 +212,7 @@ function createCountingValidator(
return new MockValidator(log, (completeSample: MeasureValues[]) => {
count--;
if (count === 0) {
return validSample || completeSample;
return isPresent(validSample) ? validSample : completeSample;
} else {
return null;
}

View File

@ -9,6 +9,7 @@
import {describe, expect, it} from '@angular/core/testing/testing_internal';
import {MeasureValues, ReflectiveInjector, RegressionSlopeValidator} from '../../index';
import {ListWrapper} from '../../src/facade/collection';
export function main() {
describe('regression slope validator', () => {
@ -43,15 +44,17 @@ export function main() {
it('should return the last sampleSize runs when the regression slope is ==0', () => {
createValidator({size: 2, metric: 'script'});
var sample = [mv(0, 0, {'script': 1}), mv(1, 1, {'script': 1}), mv(2, 2, {'script': 1})];
expect(validator.validate(sample.slice(0, 2))).toEqual(sample.slice(0, 2));
expect(validator.validate(sample)).toEqual(sample.slice(1, 3));
expect(validator.validate(ListWrapper.slice(sample, 0, 2)))
.toEqual(ListWrapper.slice(sample, 0, 2));
expect(validator.validate(sample)).toEqual(ListWrapper.slice(sample, 1, 3));
});
it('should return the last sampleSize runs when the regression slope is >0', () => {
createValidator({size: 2, metric: 'script'});
var sample = [mv(0, 0, {'script': 1}), mv(1, 1, {'script': 2}), mv(2, 2, {'script': 3})];
expect(validator.validate(sample.slice(0, 2))).toEqual(sample.slice(0, 2));
expect(validator.validate(sample)).toEqual(sample.slice(1, 3));
expect(validator.validate(ListWrapper.slice(sample, 0, 2)))
.toEqual(ListWrapper.slice(sample, 0, 2));
expect(validator.validate(sample)).toEqual(ListWrapper.slice(sample, 1, 3));
});
});

View File

@ -9,6 +9,7 @@
import {describe, expect, it} from '@angular/core/testing/testing_internal';
import {MeasureValues, ReflectiveInjector, SizeValidator} from '../../index';
import {ListWrapper} from '../../src/facade/collection';
export function main() {
describe('size validator', () => {
@ -36,8 +37,9 @@ export function main() {
it('should return the last sampleSize runs when it has at least the given size', () => {
createValidator(2);
var sample = [mv(0, 0, {'a': 1}), mv(1, 1, {'b': 2}), mv(2, 2, {'c': 3})];
expect(validator.validate(sample.slice(0, 2))).toEqual(sample.slice(0, 2));
expect(validator.validate(sample)).toEqual(sample.slice(1, 3));
expect(validator.validate(ListWrapper.slice(sample, 0, 2)))
.toEqual(ListWrapper.slice(sample, 0, 2));
expect(validator.validate(sample)).toEqual(ListWrapper.slice(sample, 1, 3));
});
});

View File

@ -9,7 +9,7 @@
import {AsyncTestCompleter, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
import {Options, ReflectiveInjector, WebDriverExtension} from '../index';
import {isPresent} from '../src/facade/lang';
import {StringWrapper, isPresent} from '../src/facade/lang';
export function main() {
function createExtension(ids: any[], caps: any) {
@ -52,6 +52,6 @@ class MockExtension extends WebDriverExtension {
constructor(public id: string) { super(); }
supports(capabilities: {[key: string]: any}): boolean {
return capabilities['browser'] === this.id;
return StringWrapper.equals(capabilities['browser'], this.id);
}
}

View File

@ -9,7 +9,7 @@
import {AsyncTestCompleter, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
import {ChromeDriverExtension, Options, ReflectiveInjector, WebDriverAdapter, WebDriverExtension} from '../../index';
import {isBlank} from '../../src/facade/lang';
import {Json, isBlank} from '../../src/facade/lang';
import {TraceEventFactory} from '../trace_event_factory';
export function main() {
@ -398,8 +398,8 @@ class MockDriverAdapter extends WebDriverAdapter {
if (type === 'performance') {
return Promise.resolve(this._events.map(
(event) => ({
'message': JSON.stringify(
{'message': {'method': this._messageMethod, 'params': event}}, null, 2)
'message':
Json.stringify({'message': {'method': this._messageMethod, 'params': event}})
})));
} else {
return null;

View File

@ -9,6 +9,7 @@
import {AsyncTestCompleter, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
import {IOsDriverExtension, ReflectiveInjector, WebDriverAdapter, WebDriverExtension} from '../../index';
import {Json} from '../../src/facade/lang';
import {TraceEventFactory} from '../trace_event_factory';
export function main() {
@ -183,9 +184,8 @@ class MockDriverAdapter extends WebDriverAdapter {
if (type === 'performance') {
return Promise.resolve(this._perfRecords.map(function(record) {
return {
'message': JSON.stringify(
{'message': {'method': 'Timeline.eventRecorded', 'params': {'record': record}}}, null,
2)
'message': Json.stringify(
{'message': {'method': 'Timeline.eventRecorded', 'params': {'record': record}}})
};
}));
} else {

View File

@ -11,6 +11,8 @@ import {CollectionChangeRecord, Directive, DoCheck, ElementRef, Input, IterableD
import {isListLikeIterable} from '../facade/collection';
import {isPresent} from '../facade/lang';
/**
* @ngModule CommonModule
*
@ -29,11 +31,11 @@ import {isPresent} from '../facade/lang';
*
* @description
*
* The CSS classes are updated as follows, depending on the type of the expression evaluation:
* - `string` - the CSS classes listed in the string (space delimited) are added,
* - `Array` - the CSS classes declared as Array elements are added,
* - `Object` - keys are CSS classes that get added when the expression given in the value
* evaluates to a truthy value, otherwise they are removed.
* The CSS classes are updated as follow depending on the type of the expression evaluation:
* - `string` - the CSS classes listed in a string (space delimited) are added,
* - `Array` - the CSS classes (Array elements) are added,
* - `Object` - keys are CSS class names that get added when the expression given in the value
* evaluates to a truthy value, otherwise class are removed.
*
* @stable
*/
@ -48,6 +50,7 @@ export class NgClass implements DoCheck {
private _iterableDiffers: IterableDiffers, private _keyValueDiffers: KeyValueDiffers,
private _ngEl: ElementRef, private _renderer: Renderer) {}
@Input('class')
set klass(v: string) {
this._applyInitialClasses(true);

View File

@ -11,14 +11,14 @@ import {Directive, Input, TemplateRef, ViewContainerRef} from '@angular/core';
/**
* Removes or recreates a portion of the DOM tree based on an {expression}.
*
* If the expression assigned to `ngIf` evaluates to a falsy value then the element
* If the expression assigned to `ngIf` evaluates to a false value then the element
* is removed from the DOM, otherwise a clone of the element is reinserted into the DOM.
*
* ### Example ([live demo](http://plnkr.co/edit/fe0kgemFBtmQOY31b4tw?p=preview)):
*
* ```
* <div *ngIf="errorCount > 0" class="error">
* <!-- Error message displayed when the errorCount property in the current context is greater
* <!-- Error message displayed when the errorCount property on the current context is greater
* than 0. -->
* {{errorCount}} errors detected
* </div>
@ -34,7 +34,7 @@ import {Directive, Input, TemplateRef, ViewContainerRef} from '@angular/core';
*/
@Directive({selector: '[ngIf]'})
export class NgIf {
private _hasView = false;
private _hasView: boolean = false;
constructor(private _viewContainer: ViewContainerRef, private _template: TemplateRef<Object>) {}

View File

@ -10,7 +10,7 @@ import {Directive, Host, Input, TemplateRef, ViewContainerRef} from '@angular/co
import {ListWrapper} from '../facade/collection';
const _CASE_DEFAULT = {};
const _CASE_DEFAULT = new Object();
export class SwitchView {
constructor(
@ -38,7 +38,7 @@ export class SwitchView {
* <inner-element></inner-element>
* <inner-other-element></inner-other-element>
* </ng-container>
* <some-element *ngSwitchDefault>...</some-element>
* <some-element *ngSwitchDefault>...</p>
* </container-element>
* ```
* @description
@ -53,7 +53,8 @@ export class SwitchView {
* root elements.
*
* Elements within `NgSwitch` but outside of a `NgSwitchCase` or `NgSwitchDefault` directives will
* be preserved at the location.
* be
* preserved at the location.
*
* The `ngSwitchCase` directive informs the parent `NgSwitch` of which view to display when the
* expression is evaluated.
@ -71,23 +72,18 @@ export class NgSwitch {
@Input()
set ngSwitch(value: any) {
// Set of views to display for this value
let views = this._valueViews.get(value);
if (views) {
this._useDefault = false;
} else {
// No view to display for the current value -> default case
// Nothing to do if the default case was already active
if (this._useDefault) {
return;
}
this._useDefault = true;
views = this._valueViews.get(_CASE_DEFAULT);
}
// Empty the currently active ViewContainers
this._emptyAllActiveViews();
// Add the ViewContainers matching the value (with a fallback to default)
this._useDefault = false;
let views = this._valueViews.get(value);
if (!views) {
this._useDefault = true;
views = this._valueViews.get(_CASE_DEFAULT) || null;
}
this._activateViews(views);
this._switchValue = value;
}
@ -123,7 +119,7 @@ export class NgSwitch {
this._activeViews = [];
}
private _activateViews(views?: SwitchView[]): void {
private _activateViews(views: SwitchView[]): void {
if (views) {
for (var i = 0; i < views.length; i++) {
views[i].create();

View File

@ -33,21 +33,21 @@ import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
* - `'shortTime'`: equivalent to `'jm'` (e.g. `12:05 PM` for `en-US`)
*
*
* | Component | Symbol | Narrow | Short Form | Long Form | Numeric | 2-digit |
* |-----------|:------:|--------|--------------|-------------------|-----------|-----------|
* | era | G | G (A) | GGG (AD) | GGGG (Anno Domini)| - | - |
* | year | y | - | - | - | y (2015) | yy (15) |
* | month | M | L (S) | MMM (Sep) | MMMM (September) | M (9) | MM (09) |
* | day | d | - | - | - | d (3) | dd (03) |
* | weekday | E | E (S) | EEE (Sun) | EEEE (Sunday) | - | - |
* | hour | j | - | - | - | j (13) | jj (13) |
* | hour12 | h | - | - | - | h (1 PM) | hh (01 PM)|
* | hour24 | H | - | - | - | H (13) | HH (13) |
* | minute | m | - | - | - | m (5) | mm (05) |
* | second | s | - | - | - | s (9) | ss (09) |
* | timezone | z | - | - | z (Pacific Standard Time)| - | - |
* | timezone | Z | - | Z (GMT-8:00) | - | - | - |
* | timezone | a | - | a (PM) | - | - | - |
* | Component | Symbol | Short Form | Long Form | Numeric | 2-digit |
* |-----------|:------:|--------------|-------------------|-----------|-----------|
* | era | G | G (AD) | GGGG (Anno Domini)| - | - |
* | year | y | - | - | y (2015) | yy (15) |
* | month | M | MMM (Sep) | MMMM (September) | M (9) | MM (09) |
* | day | d | - | - | d (3) | dd (03) |
* | weekday | E | EEE (Sun) | EEEE (Sunday) | - | - |
* | hour | j | - | - | j (13) | jj (13) |
* | hour12 | h | - | - | h (1 PM) | hh (01 PM)|
* | hour24 | H | - | - | H (13) | HH (13) |
* | minute | m | - | - | m (5) | mm (05) |
* | second | s | - | - | s (9) | ss (09) |
* | timezone | z | - | z (Pacific Standard Time)| - | - |
* | timezone | Z | Z (GMT-8:00) | - | - | - |
* | timezone | a | a (PM) | - | - | - |
*
* In javascript, only the components specified will be respected (not the ordering,
* punctuations, ...) and details of the formatting will be dependent on the locale.

View File

@ -7,7 +7,7 @@
*/
import {Pipe, PipeTransform} from '@angular/core';
import {isBlank} from '../facade/lang';
import {isBlank, isStringMap} from '../facade/lang';
import {NgLocalization, getPluralCategory} from '../localization';
import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
@ -37,7 +37,7 @@ export class I18nPluralPipe implements PipeTransform {
transform(value: number, pluralMap: {[count: string]: string}): string {
if (isBlank(value)) return '';
if (typeof pluralMap !== 'object' || pluralMap === null) {
if (!isStringMap(pluralMap)) {
throw new InvalidPipeArgumentError(I18nPluralPipe, pluralMap);
}

View File

@ -7,7 +7,7 @@
*/
import {Pipe, PipeTransform} from '@angular/core';
import {isBlank} from '../facade/lang';
import {isBlank, isStringMap} from '../facade/lang';
import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
/**
@ -31,10 +31,10 @@ export class I18nSelectPipe implements PipeTransform {
transform(value: string, mapping: {[key: string]: string}): string {
if (isBlank(value)) return '';
if (typeof mapping !== 'object' || mapping === null) {
if (!isStringMap(mapping)) {
throw new InvalidPipeArgumentError(I18nSelectPipe, mapping);
}
return mapping[value] || '';
return mapping.hasOwnProperty(value) ? mapping[value] : '';
}
}

View File

@ -8,6 +8,10 @@
import {Pipe, PipeTransform} from '@angular/core';
import {Json} from '../facade/lang';
/**
* @ngModule CommonModule
* @whatItDoes Converts value into JSON string.
@ -23,5 +27,5 @@ import {Pipe, PipeTransform} from '@angular/core';
*/
@Pipe({name: 'json', pure: false})
export class JsonPipe implements PipeTransform {
transform(value: any): string { return JSON.stringify(value, null, 2); }
transform(value: any): string { return Json.stringify(value); }
}

View File

@ -50,6 +50,25 @@ export function main() {
detectChangesAndExpectText('when b');
}));
// TODO(robwormald): deprecate and remove
it('should switch amongst when values using switchCase', async(() => {
const template = '<div>' +
'<ul [ngSwitch]="switchValue">' +
'<template ngSwitchCase="a"><li>when a</li></template>' +
'<template ngSwitchCase="b"><li>when b</li></template>' +
'</ul></div>';
fixture = createTestComponent(template);
detectChangesAndExpectText('');
getComponent().switchValue = 'a';
detectChangesAndExpectText('when a');
getComponent().switchValue = 'b';
detectChangesAndExpectText('when b');
}));
it('should switch amongst when values with fallback to default', async(() => {
const template = '<div>' +
'<ul [ngSwitch]="switchValue">' +
@ -65,9 +84,6 @@ export function main() {
getComponent().switchValue = 'b';
detectChangesAndExpectText('when default');
getComponent().switchValue = 'c';
detectChangesAndExpectText('when default');
}));
it('should support multiple whens with the same value', async(() => {

View File

@ -59,7 +59,7 @@ export function main() {
expect(pipe.transform(date, 'MMM')).toEqual('Jun');
expect(pipe.transform(date, 'MMMM')).toEqual('June');
expect(pipe.transform(date, 'd')).toEqual('15');
expect(pipe.transform(date, 'EEE')).toEqual('Mon');
expect(pipe.transform(date, 'E')).toEqual('Mon');
expect(pipe.transform(date, 'EEEE')).toEqual('Monday');
if (!browserDetection.isOldChrome) {
expect(pipe.transform(date, 'h')).toEqual('9');
@ -72,9 +72,6 @@ export function main() {
if (!browserDetection.isOldChrome) {
expect(pipe.transform(date, 'HH')).toEqual('09');
}
expect(pipe.transform(date, 'E')).toEqual('M');
expect(pipe.transform(date, 'L')).toEqual('J');
expect(pipe.transform(date, 'm')).toEqual('3');
expect(pipe.transform(date, 's')).toEqual('1');
expect(pipe.transform(date, 'mm')).toEqual('03');
@ -84,13 +81,13 @@ export function main() {
});
it('should format common multi component patterns', () => {
expect(pipe.transform(date, 'EEE, M/d/y')).toEqual('Mon, 6/15/2015');
expect(pipe.transform(date, 'EEE, M/d')).toEqual('Mon, 6/15');
expect(pipe.transform(date, 'E, M/d/y')).toEqual('Mon, 6/15/2015');
expect(pipe.transform(date, 'E, M/d')).toEqual('Mon, 6/15');
expect(pipe.transform(date, 'MMM d')).toEqual('Jun 15');
expect(pipe.transform(date, 'dd/MM/yyyy')).toEqual('15/06/2015');
expect(pipe.transform(date, 'MM/dd/yyyy')).toEqual('06/15/2015');
expect(pipe.transform(date, 'yMEEEd')).toEqual('20156Mon15');
expect(pipe.transform(date, 'MEEEd')).toEqual('6Mon15');
expect(pipe.transform(date, 'yMEd')).toEqual('20156Mon15');
expect(pipe.transform(date, 'MEd')).toEqual('6Mon15');
expect(pipe.transform(date, 'MMMd')).toEqual('Jun15');
expect(pipe.transform(date, 'yMMMMEEEEd')).toEqual('Monday, June 15, 2015');
// IE and Edge can't format a date to minutes and seconds without hours

View File

@ -11,6 +11,8 @@ import {Component} from '@angular/core';
import {TestBed, async} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/matchers';
import {Json, StringWrapper} from '../../src/facade/lang';
export function main() {
describe('JsonPipe', () => {
var regNewLine = '\n';
@ -18,7 +20,7 @@ export function main() {
var inceptionObjString: string;
var pipe: JsonPipe;
function normalize(obj: string): string { return obj.replace(regNewLine, ''); }
function normalize(obj: string): string { return StringWrapper.replace(obj, regNewLine, ''); }
beforeEach(() => {
inceptionObj = {dream: {dream: {dream: 'Limbo'}}};
@ -46,7 +48,7 @@ export function main() {
it('should return JSON-formatted string similar to Json.stringify', () => {
var dream1 = normalize(pipe.transform(inceptionObj));
var dream2 = normalize(JSON.stringify(inceptionObj, null, 2));
var dream2 = normalize(Json.stringify(inceptionObj));
expect(dream1).toEqual(dream2);
});
});
@ -72,6 +74,7 @@ export function main() {
mutable.push(2);
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('[\n 1,\n 2\n]');
}));
});
});

View File

@ -27,7 +27,7 @@ Then you can add an import statement in the `bootstrap` allowing you to bootstra
generated code:
```typescript
main.module.ts
main_module.ts
-------------
import {BrowserModule} from '@angular/platform-browser';
import {Component, NgModule, ApplicationRef} from '@angular/core';
@ -49,7 +49,7 @@ export class MainModule {
bootstrap.ts
-------------
import {MainModuleNgFactory} from './main.module.ngfactory';
import {MainModuleNgFactory} from './main_module.ngfactory';
import {platformBrowser} from '@angular/platform-browser';
platformBrowser().bootstrapModuleFactory(MainModuleNgFactory);

View File

@ -7,7 +7,6 @@
*/
export {CodeGenerator} from './src/codegen';
export {Extractor} from './src/extractor';
export {NodeReflectorHostContext, ReflectorHost, ReflectorHostContext} from './src/reflector_host';
export {StaticReflector, StaticReflectorHost, StaticSymbol} from './src/static_reflector';

View File

@ -1,6 +0,0 @@
# Overview
This folder will be filled with the benchmark sources
so that we can do offline compilation for them.

View File

@ -1,18 +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 {Component} from '@angular/core';
@Component({
selector: 'use-third-party',
template: '<third-party-comp [thirdParty]="title"></third-party-comp>' +
'<another-third-party-comp></another-third-party-comp>',
})
export class ComponentUsingThirdParty {
title: string = 'from 3rd party';
}

View File

@ -12,10 +12,6 @@
<source>Welcome</source>
<target>tervetuloa</target>
</trans-unit>
<trans-unit id="63a85808f03b8181e36a952e0fa38202c2304862" datatype="html">
<source>other-3rdP-component</source>
<target>other-3rdP-component</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -9,5 +9,4 @@
<translationbundle>
<translation id="76e1eccb1b772fa9f294ef9c146ea6d0efa8a2d4">käännä teksti</translation>
<translation id="65cc4ab3b4c438e07c89be2b677d08369fb62da2">tervetuloa</translation>
<translation id="63a85808f03b8181e36a952e0fa38202c2304862">other-3rdP-component</translation>
</translationbundle>

View File

@ -11,12 +11,9 @@ import {FormsModule} from '@angular/forms';
import {BrowserModule} from '@angular/platform-browser';
import {MdButtonModule} from '@angular2-material/button';
import {ThirdpartyModule} from '../third_party_src/module';
import {MultipleComponentsMyComp, NextComp} from './a/multiple_components';
import {AnimateCmp} from './animate';
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';
@ -25,47 +22,35 @@ import {CompForChildQuery, CompWithChildQuery, CompWithDirectiveChild, Directive
@NgModule({
declarations: [
AnimateCmp,
BasicComp,
CompConsumingEvents,
CompForChildQuery,
CompUsingPipes,
CompUsingRootModuleDirectiveAndPipe,
CompWithAnalyzeEntryComponentsProvider,
CompWithChildQuery,
CompWithDirectiveChild,
CompWithEntryComponents,
CompWithNgContent,
CompWithProviders,
CompWithReferences,
DirectiveForQuery,
DirPublishingEvents,
MultipleComponentsMyComp,
NextComp,
ProjectingComp,
SomeDirectiveInRootModule,
SomePipeInRootModule,
ComponentUsingThirdParty,
AnimateCmp,
BasicComp,
CompForChildQuery,
CompWithEntryComponents,
CompWithAnalyzeEntryComponentsProvider,
ProjectingComp,
CompWithChildQuery,
CompWithDirectiveChild,
CompWithNgContent,
CompUsingRootModuleDirectiveAndPipe,
CompWithProviders,
CompWithReferences,
CompUsingPipes,
CompConsumingEvents,
DirPublishingEvents,
MultipleComponentsMyComp,
DirectiveForQuery,
NextComp,
],
imports: [
BrowserModule,
FormsModule,
MdButtonModule,
ModuleUsingCustomElements,
someLibModuleWithProviders(),
ThirdpartyModule,
BrowserModule, FormsModule, someLibModuleWithProviders(), ModuleUsingCustomElements,
MdButtonModule
],
providers: [SomeService],
entryComponents: [
AnimateCmp,
BasicComp,
CompUsingRootModuleDirectiveAndPipe,
CompWithAnalyzeEntryComponentsProvider,
CompWithChildQuery,
CompWithEntryComponents,
CompWithReferences,
ProjectingComp,
ComponentUsingThirdParty,
AnimateCmp, BasicComp, CompWithEntryComponents, CompWithAnalyzeEntryComponentsProvider,
ProjectingComp, CompWithChildQuery, CompUsingRootModuleDirectiveAndPipe, CompWithReferences
]
})
export class MainModule {

View File

@ -43,13 +43,13 @@ describe('template codegen output', () => {
});
it('should be able to create the basic component', () => {
const compFixture = createComponent(BasicComp);
var compFixture = createComponent(BasicComp);
expect(compFixture.componentInstance).toBeTruthy();
});
it('should support ngIf', () => {
const compFixture = createComponent(BasicComp);
const debugElement = compFixture.debugElement;
var compFixture = createComponent(BasicComp);
var debugElement = compFixture.debugElement;
expect(debugElement.children.length).toBe(3);
compFixture.componentInstance.ctxBool = true;
@ -59,8 +59,8 @@ describe('template codegen output', () => {
});
it('should support ngFor', () => {
const compFixture = createComponent(BasicComp);
const debugElement = compFixture.debugElement;
var compFixture = createComponent(BasicComp);
var debugElement = compFixture.debugElement;
expect(debugElement.children.length).toBe(3);
// test NgFor
@ -83,9 +83,11 @@ describe('template codegen output', () => {
});
it('should support i18n for content tags', () => {
const containerElement = createComponent(BasicComp).nativeElement;
const pElement = containerElement.children.find((c: any) => c.name == 'p');
const pText = pElement.children.map((c: any) => c.data).join('').trim();
const compFixture = createComponent(BasicComp);
const debugElement = compFixture.debugElement;
const containerElement = <any>debugElement.nativeElement;
const pElement = <any>containerElement.children.find((c: any) => c.name == 'p');
const pText = <string>pElement.children.map((c: any) => c.data).join('').trim();
expect(pText).toBe('tervetuloa');
});
});

View File

@ -34,7 +34,6 @@ const EXPECTED_XMB = `<?xml version="1.0" encoding="UTF-8" ?>
<!ELEMENT ex (#PCDATA)>
]>
<messagebundle>
<msg id="63a85808f03b8181e36a952e0fa38202c2304862">other-3rdP-component</msg>
<msg id="76e1eccb1b772fa9f294ef9c146ea6d0efa8a2d4" desc="desc" meaning="meaning">translate me</msg>
<msg id="65cc4ab3b4c438e07c89be2b677d08369fb62da2">Welcome</msg>
</messagebundle>
@ -44,10 +43,6 @@ const EXPECTED_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="ng2.template">
<body>
<trans-unit id="63a85808f03b8181e36a952e0fa38202c2304862" datatype="html">
<source>other-3rdP-component</source>
<target/>
</trans-unit>
<trans-unit id="76e1eccb1b772fa9f294ef9c146ea6d0efa8a2d4" datatype="html">
<source>translate me</source>
<target/>

View File

@ -7,7 +7,6 @@
*/
import './init';
import {ComponentUsingThirdParty} from '../src/comp_using_3rdp';
import {MainModule} from '../src/module';
import {CompUsingLibModuleDirectiveAndPipe, CompUsingRootModuleDirectiveAndPipe, SOME_TOKEN, ServiceUsingLibModule, SomeLibModule, SomeService} from '../src/module_fixtures';
@ -16,9 +15,9 @@ import {createComponent, createModule} from './util';
describe('NgModule', () => {
it('should support providers', () => {
const moduleRef = createModule();
expect(moduleRef.instance instanceof MainModule).toEqual(true);
expect(moduleRef.injector.get(MainModule) instanceof MainModule).toEqual(true);
expect(moduleRef.injector.get(SomeService) instanceof SomeService).toEqual(true);
expect(moduleRef.instance instanceof MainModule).toBe(true);
expect(moduleRef.injector.get(MainModule) instanceof MainModule).toBe(true);
expect(moduleRef.injector.get(SomeService) instanceof SomeService).toBe(true);
});
it('should support entryComponents components', () => {
@ -27,7 +26,7 @@ describe('NgModule', () => {
CompUsingRootModuleDirectiveAndPipe);
expect(cf.componentType).toBe(CompUsingRootModuleDirectiveAndPipe);
const compRef = cf.create(moduleRef.injector);
expect(compRef.instance instanceof CompUsingRootModuleDirectiveAndPipe).toEqual(true);
expect(compRef.instance instanceof CompUsingRootModuleDirectiveAndPipe).toBe(true);
});
it('should support entryComponents via the ANALYZE_FOR_ENTRY_COMPONENTS provider and function providers in components',
@ -43,30 +42,12 @@ describe('NgModule', () => {
]);
});
describe('third-party modules', () => {
// https://github.com/angular/angular/issues/11889
it('should support third party entryComponents components', () => {
const fixture = createComponent(ComponentUsingThirdParty);
const thirdPComps = fixture.nativeElement.children;
expect(thirdPComps[0].children[0].children[0].data).toEqual('3rdP-component');
expect(thirdPComps[1].children[0].children[0].data).toEqual('other-3rdP-component');
});
// https://github.com/angular/angular/issues/12428
it('should support third party directives', () => {
const fixture = createComponent(ComponentUsingThirdParty);
const debugElement = fixture.debugElement;
fixture.detectChanges();
expect(debugElement.children[0].properties['title']).toEqual('from 3rd party');
});
});
it('should support module directives and pipes', () => {
const compFixture = createComponent(CompUsingRootModuleDirectiveAndPipe);
compFixture.detectChanges();
const debugElement = compFixture.debugElement;
expect(debugElement.children[0].properties['title']).toEqual('transformed someValue');
expect(debugElement.children[0].properties['title']).toBe('transformed someValue');
});
it('should support module directives and pipes on lib modules', () => {
@ -74,10 +55,10 @@ describe('NgModule', () => {
compFixture.detectChanges();
const debugElement = compFixture.debugElement;
expect(debugElement.children[0].properties['title']).toEqual('transformed someValue');
expect(debugElement.children[0].properties['title']).toBe('transformed someValue');
expect(debugElement.injector.get(SomeLibModule) instanceof SomeLibModule).toEqual(true);
expect(debugElement.injector.get(SomeLibModule) instanceof SomeLibModule).toBe(true);
expect(debugElement.injector.get(ServiceUsingLibModule) instanceof ServiceUsingLibModule)
.toEqual(true);
.toBe(true);
});
});

View File

@ -1,8 +0,0 @@
This folder emulates consuming precompiled modules and components.
It is compiled separately from the other sources under `src`
to only generate `*.js` / `*.d.ts` / `*.metadata.json` files,
but no `*.ngfactory.ts` files.
** WARNING **
Do not import components/directives from here directly as we want to test that ngc still compiles
them when they are not imported.

View File

@ -1,17 +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 {Directive, Input} from '@angular/core';
@Directive({
selector: '[thirdParty]',
host: {'[title]': 'thirdParty'},
})
export class ThirdPartyDirective {
@Input() thirdParty: string;
}

View File

@ -1,28 +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 {NgModule} from '@angular/core';
import {ThirdPartyComponent} from './comp';
import {ThirdPartyDirective} from './directive';
import {AnotherThirdPartyModule} from './other_module';
@NgModule({
declarations: [
ThirdPartyComponent,
ThirdPartyDirective,
],
exports: [
AnotherThirdPartyModule,
ThirdPartyComponent,
ThirdPartyDirective,
],
imports: [AnotherThirdPartyModule]
})
export class ThirdpartyModule {
}

View File

@ -1,16 +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 {Component} from '@angular/core';
@Component({
selector: 'another-third-party-comp',
template: '<div i18n>other-3rdP-component</div>',
})
export class AnotherThirdpartyComponent {
}

View File

@ -1,17 +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 {NgModule} from '@angular/core';
import {AnotherThirdpartyComponent} from './other_comp';
@NgModule({
declarations: [AnotherThirdpartyComponent],
exports: [AnotherThirdpartyComponent],
})
export class AnotherThirdPartyModule {
}

View File

@ -1,20 +0,0 @@
{
"angularCompilerOptions": {
// For TypeScript 1.8, we have to lay out generated files
// in the same source directory with your code.
"genDir": ".",
"debug": true
},
"compilerOptions": {
"target": "es5",
"experimentalDecorators": true,
"noImplicitAny": true,
"moduleResolution": "node",
"rootDir": "",
"declaration": true,
"lib": ["es6", "dom"],
"baseUrl": ".",
"outDir": "../node_modules/third_party"
}
}

View File

@ -1,29 +0,0 @@
{
"angularCompilerOptions": {
// For TypeScript 1.8, we have to lay out generated files
// in the same source directory with your code.
"genDir": ".",
"debug": true
},
"compilerOptions": {
"target": "es5",
"experimentalDecorators": true,
"noImplicitAny": true,
"moduleResolution": "node",
"rootDir": "",
"declaration": true,
"lib": ["es6", "dom"],
"baseUrl": "."
},
"files": [
"src/module",
"src/bootstrap",
"test/all_spec",
"benchmarks/src/tree/ng2/index_aot.ts",
"benchmarks/src/tree/ng2_switch/index_aot.ts",
"benchmarks/src/largetable/ng2/index_aot.ts",
"benchmarks/src/largetable/ng2_switch/index_aot.ts"
]
}

View File

@ -0,0 +1,19 @@
{
"angularCompilerOptions": {
// For TypeScript 1.8, we have to lay out generated files
// in the same source directory with your code.
"genDir": ".",
"debug": true
},
"compilerOptions": {
"target": "es5",
"experimentalDecorators": true,
"noImplicitAny": true,
"moduleResolution": "node",
"rootDir": "",
"declaration": true,
"lib": ["es6", "dom"],
"baseUrl": "."
}
}

View File

@ -11,11 +11,13 @@
"dependencies": {
"@angular/tsc-wrapped": "^0.3.0",
"reflect-metadata": "^0.1.2",
"parse5": "^2.2.1",
"minimist": "^1.2.0"
},
"peerDependencies": {
"typescript": "^2.0.2",
"@angular/compiler": "0.0.0-PLACEHOLDER",
"@angular/platform-server": "0.0.0-PLACEHOLDER",
"@angular/core": "0.0.0-PLACEHOLDER"
},
"repository": {

View File

@ -11,16 +11,17 @@
* Intended to be used in a build step.
*/
import * as compiler from '@angular/compiler';
import {ViewEncapsulation} from '@angular/core';
import {Component, NgModule, ViewEncapsulation} from '@angular/core';
import {AngularCompilerOptions, NgcCliOptions} from '@angular/tsc-wrapped';
import * as path from 'path';
import * as ts from 'typescript';
import {PathMappedReflectorHost} from './path_mapped_reflector_host';
import {CompileMetadataResolver, DirectiveNormalizer, DomElementSchemaRegistry, HtmlParser, Lexer, NgModuleCompiler, Parser, StyleCompiler, TemplateParser, TypeScriptEmitter, ViewCompiler} from './private_import_compiler';
import {Console} from './private_import_core';
import {ReflectorHost, ReflectorHostContext} from './reflector_host';
import {StaticAndDynamicReflectionCapabilities} from './static_reflection_capabilities';
import {StaticReflector, StaticReflectorHost, StaticSymbol} from './static_reflector';
import {StaticReflector, StaticSymbol} from './static_reflector';
const nodeFs = require('fs');
@ -39,12 +40,42 @@ export class CodeGenerator {
constructor(
private options: AngularCompilerOptions, private program: ts.Program,
public host: ts.CompilerHost, private staticReflector: StaticReflector,
private compiler: compiler.OfflineCompiler, private reflectorHost: StaticReflectorHost) {}
private compiler: compiler.OfflineCompiler, private reflectorHost: ReflectorHost) {}
private readFileMetadata(absSourcePath: string): FileMetadata {
const moduleMetadata = this.staticReflector.getModuleMetadata(absSourcePath);
const result: FileMetadata = {components: [], ngModules: [], fileUrl: absSourcePath};
if (!moduleMetadata) {
console.log(`WARNING: no metadata found for ${absSourcePath}`);
return result;
}
const metadata = moduleMetadata['metadata'];
const symbols = metadata && Object.keys(metadata);
if (!symbols || !symbols.length) {
return result;
}
for (const symbol of symbols) {
if (metadata[symbol] && metadata[symbol].__symbolic == 'error') {
// Ignore symbols that are only included to record error information.
continue;
}
const staticType = this.reflectorHost.findDeclaration(absSourcePath, symbol, absSourcePath);
const annotations = this.staticReflector.annotations(staticType);
annotations.forEach((annotation) => {
if (annotation instanceof NgModule) {
result.ngModules.push(staticType);
} else if (annotation instanceof Component) {
result.components.push(staticType);
}
});
}
return result;
}
// Write codegen in a directory structure matching the sources.
private calculateEmitPath(filePath: string): string {
let root = this.options.basePath;
for (const eachRootDir of this.options.rootDirs || []) {
for (let eachRootDir of this.options.rootDirs || []) {
if (this.options.trace) {
console.log(`Check if ${filePath} is under rootDirs element ${eachRootDir}`);
}
@ -54,28 +85,42 @@ export class CodeGenerator {
}
// transplant the codegen path to be inside the `genDir`
let relativePath: string = path.relative(root, filePath);
var relativePath: string = path.relative(root, filePath);
while (relativePath.startsWith('..' + path.sep)) {
// Strip out any `..` path such as: `../node_modules/@foo` as we want to put everything
// into `genDir`.
relativePath = relativePath.substr(3);
}
return path.join(this.options.genDir, relativePath);
}
codegen(options: {transitiveModules: boolean}): Promise<any> {
const staticSymbols =
extractProgramSymbols(this.program, this.staticReflector, this.reflectorHost, this.options);
return this.compiler.compileModules(staticSymbols, options).then(generatedModules => {
generatedModules.forEach(generatedModule => {
const sourceFile = this.program.getSourceFile(generatedModule.fileUrl);
const emitPath = this.calculateEmitPath(generatedModule.moduleUrl);
this.host.writeFile(
emitPath, PREAMBLE + generatedModule.source, false, () => {}, [sourceFile]);
});
});
codegen(): Promise<any> {
// Compare with false since the default should be true
const skipFileNames = (this.options.generateCodeForLibraries === false) ?
GENERATED_OR_DTS_FILES :
GENERATED_FILES;
let filePaths = this.program.getSourceFiles()
.filter(sf => !skipFileNames.test(sf.fileName))
.map(sf => this.reflectorHost.getCanonicalFileName(sf.fileName));
const fileMetas = filePaths.map((filePath) => this.readFileMetadata(filePath));
const ngModules = fileMetas.reduce((ngModules, fileMeta) => {
ngModules.push(...fileMeta.ngModules);
return ngModules;
}, <StaticSymbol[]>[]);
const analyzedNgModules = this.compiler.analyzeModules(ngModules);
return Promise.all(fileMetas.map(
(fileMeta) =>
this.compiler
.compile(
fileMeta.fileUrl, analyzedNgModules, fileMeta.components, fileMeta.ngModules)
.then((generatedModules) => {
generatedModules.forEach((generatedModule) => {
const sourceFile = this.program.getSourceFile(fileMeta.fileUrl);
const emitPath = this.calculateEmitPath(generatedModule.moduleUrl);
this.host.writeFile(
emitPath, PREAMBLE + generatedModule.source, false, () => {}, [sourceFile]);
});
})));
}
static create(
@ -112,72 +157,36 @@ export class CodeGenerator {
const staticReflector = new StaticReflector(reflectorHost);
StaticAndDynamicReflectionCapabilities.install(staticReflector);
const htmlParser =
new compiler.I18NHtmlParser(new compiler.HtmlParser(), transContent, cliOptions.i18nFormat);
new compiler.I18NHtmlParser(new HtmlParser(), transContent, cliOptions.i18nFormat);
const config = new compiler.CompilerConfig({
genDebugInfo: options.debug === true,
defaultEncapsulation: ViewEncapsulation.Emulated,
logBindingUpdate: false,
useJit: false
});
const normalizer =
new compiler.DirectiveNormalizer(resourceLoader, urlResolver, htmlParser, config);
const expressionParser = new compiler.Parser(new compiler.Lexer());
const elementSchemaRegistry = new compiler.DomElementSchemaRegistry();
const normalizer = new DirectiveNormalizer(resourceLoader, urlResolver, htmlParser, config);
const expressionParser = new Parser(new Lexer());
const elementSchemaRegistry = new DomElementSchemaRegistry();
const console = new Console();
const tmplParser = new compiler.TemplateParser(
expressionParser, elementSchemaRegistry, htmlParser, console, []);
const resolver = new compiler.CompileMetadataResolver(
const tmplParser =
new TemplateParser(expressionParser, elementSchemaRegistry, htmlParser, console, []);
const resolver = new CompileMetadataResolver(
new compiler.NgModuleResolver(staticReflector),
new compiler.DirectiveResolver(staticReflector), new compiler.PipeResolver(staticReflector),
elementSchemaRegistry, staticReflector);
// TODO(vicb): do not pass cliOptions.i18nFormat here
const offlineCompiler = new compiler.OfflineCompiler(
resolver, normalizer, tmplParser, new compiler.StyleCompiler(urlResolver),
new compiler.ViewCompiler(config, elementSchemaRegistry),
new compiler.DirectiveWrapperCompiler(
config, expressionParser, elementSchemaRegistry, console),
new compiler.NgModuleCompiler(), new compiler.TypeScriptEmitter(reflectorHost),
cliOptions.locale, cliOptions.i18nFormat);
resolver, normalizer, tmplParser, new StyleCompiler(urlResolver), new ViewCompiler(config),
new NgModuleCompiler(), new TypeScriptEmitter(reflectorHost), cliOptions.locale,
cliOptions.i18nFormat);
return new CodeGenerator(
options, program, compilerHost, staticReflector, offlineCompiler, reflectorHost);
}
}
export function extractProgramSymbols(
program: ts.Program, staticReflector: StaticReflector, reflectorHost: StaticReflectorHost,
options: AngularCompilerOptions): StaticSymbol[] {
// Compare with false since the default should be true
const skipFileNames =
options.generateCodeForLibraries === false ? GENERATED_OR_DTS_FILES : GENERATED_FILES;
const staticSymbols: StaticSymbol[] = [];
program.getSourceFiles()
.filter(sourceFile => !skipFileNames.test(sourceFile.fileName))
.forEach(sourceFile => {
const absSrcPath = reflectorHost.getCanonicalFileName(sourceFile.fileName);
const moduleMetadata = staticReflector.getModuleMetadata(absSrcPath);
if (!moduleMetadata) {
console.log(`WARNING: no metadata found for ${absSrcPath}`);
return;
}
const metadata = moduleMetadata['metadata'];
if (!metadata) {
return;
}
for (const symbol of Object.keys(metadata)) {
if (metadata[symbol] && metadata[symbol].__symbolic == 'error') {
// Ignore symbols that are only included to record error information.
continue;
}
staticSymbols.push(reflectorHost.findDeclaration(absSrcPath, symbol, absSrcPath));
}
});
return staticSymbols;
}
interface FileMetadata {
fileUrl: string;
components: StaticSymbol[];
ngModules: StaticSymbol[];
}

View File

@ -10,32 +10,28 @@
/**
* Extract i18n messages from source code
*
* TODO(vicb): factorize code with the CodeGenerator
*/
// Must be imported first, because angular2 decorators throws on load.
import 'reflect-metadata';
import * as compiler from '@angular/compiler';
import * as tsc from '@angular/tsc-wrapped';
import {Component, NgModule, ViewEncapsulation} from '@angular/core';
import * as path from 'path';
import * as ts from 'typescript';
import {Extractor} from './extractor';
import * as tsc from '@angular/tsc-wrapped';
import {CompileMetadataResolver, DirectiveNormalizer, DomElementSchemaRegistry, HtmlParser, Lexer, NgModuleCompiler, Parser, StyleCompiler, TemplateParser, TypeScriptEmitter, ViewCompiler, ParseError} from './private_import_compiler';
import {Console} from './private_import_core';
import {ReflectorHost, ReflectorHostContext} from './reflector_host';
import {StaticAndDynamicReflectionCapabilities} from './static_reflection_capabilities';
import {StaticReflector, StaticSymbol} from './static_reflector';
function extract(
ngOptions: tsc.AngularCompilerOptions, cliOptions: tsc.I18nExtractionCliOptions,
program: ts.Program, host: ts.CompilerHost) {
const resourceLoader: compiler.ResourceLoader = {
get: (s: string) => {
if (!host.fileExists(s)) {
// TODO: We should really have a test for error cases like this!
throw new Error(`Compilation failed. Resource file not found: ${s}`);
}
return Promise.resolve(host.readFile(s));
}
};
const extractor =
Extractor.create(ngOptions, cliOptions.i18nFormat, program, host, resourceLoader);
const htmlParser = new compiler.I18NHtmlParser(new HtmlParser());
const extractor = Extractor.create(ngOptions, cliOptions.i18nFormat, program, host, htmlParser);
const bundlePromise: Promise<compiler.MessageBundle> = extractor.extract();
return (bundlePromise).then(messageBundle => {
@ -51,7 +47,6 @@ function extract(
case 'xliff':
case 'xlf':
default:
const htmlParser = new compiler.I18NHtmlParser(new compiler.HtmlParser());
ext = 'xlf';
serializer = new compiler.Xliff(htmlParser, compiler.DEFAULT_INTERPOLATION_CONFIG);
break;
@ -62,6 +57,146 @@ function extract(
});
}
const GENERATED_FILES = /\.ngfactory\.ts$|\.css\.ts$|\.css\.shim\.ts$/;
export class Extractor {
constructor(
private program: ts.Program, public host: ts.CompilerHost,
private staticReflector: StaticReflector, private messageBundle: compiler.MessageBundle,
private reflectorHost: ReflectorHost, private metadataResolver: CompileMetadataResolver,
private directiveNormalizer: DirectiveNormalizer,
private compiler: compiler.OfflineCompiler) {}
private readFileMetadata(absSourcePath: string): FileMetadata {
const moduleMetadata = this.staticReflector.getModuleMetadata(absSourcePath);
const result: FileMetadata = {components: [], ngModules: [], fileUrl: absSourcePath};
if (!moduleMetadata) {
console.log(`WARNING: no metadata found for ${absSourcePath}`);
return result;
}
const metadata = moduleMetadata['metadata'];
const symbols = metadata && Object.keys(metadata);
if (!symbols || !symbols.length) {
return result;
}
for (const symbol of symbols) {
if (metadata[symbol] && metadata[symbol].__symbolic == 'error') {
// Ignore symbols that are only included to record error information.
continue;
}
const staticType = this.reflectorHost.findDeclaration(absSourcePath, symbol, absSourcePath);
const annotations = this.staticReflector.annotations(staticType);
annotations.forEach((annotation) => {
if (annotation instanceof NgModule) {
result.ngModules.push(staticType);
} else if (annotation instanceof Component) {
result.components.push(staticType);
}
});
}
return result;
}
extract(): Promise<compiler.MessageBundle> {
const filePaths =
this.program.getSourceFiles().map(sf => sf.fileName).filter(f => !GENERATED_FILES.test(f));
const fileMetas = filePaths.map((filePath) => this.readFileMetadata(filePath));
const ngModules = fileMetas.reduce((ngModules, fileMeta) => {
ngModules.push(...fileMeta.ngModules);
return ngModules;
}, <StaticSymbol[]>[]);
const analyzedNgModules = this.compiler.analyzeModules(ngModules);
const errors: ParseError[] = [];
let bundlePromise =
Promise
.all(fileMetas.map((fileMeta) => {
const url = fileMeta.fileUrl;
return Promise.all(fileMeta.components.map(compType => {
const compMeta = this.metadataResolver.getDirectiveMetadata(<any>compType);
const ngModule = analyzedNgModules.ngModuleByComponent.get(compType);
if (!ngModule) {
throw new Error(
`Cannot determine the module for component ${compMeta.type.name}!`);
}
return Promise
.all([compMeta, ...ngModule.transitiveModule.directives].map(
dirMeta =>
this.directiveNormalizer.normalizeDirective(dirMeta).asyncResult))
.then((normalizedCompWithDirectives) => {
const compMeta = normalizedCompWithDirectives[0];
const html = compMeta.template.template;
const interpolationConfig =
compiler.InterpolationConfig.fromArray(compMeta.template.interpolation);
errors.push(
...this.messageBundle.updateFromTemplate(html, url, interpolationConfig));
});
}));
}))
.then(_ => this.messageBundle);
if (errors.length) {
throw new Error(errors.map(e => e.toString()).join('\n'));
}
return bundlePromise;
}
static create(
options: tsc.AngularCompilerOptions, translationsFormat: string, program: ts.Program,
compilerHost: ts.CompilerHost, htmlParser: compiler.I18NHtmlParser,
reflectorHostContext?: ReflectorHostContext): Extractor {
const resourceLoader: compiler.ResourceLoader = {
get: (s: string) => {
if (!compilerHost.fileExists(s)) {
// TODO: We should really have a test for error cases like this!
throw new Error(`Compilation failed. Resource file not found: ${s}`);
}
return Promise.resolve(compilerHost.readFile(s));
}
};
const urlResolver: compiler.UrlResolver = compiler.createOfflineCompileUrlResolver();
const reflectorHost = new ReflectorHost(program, compilerHost, options, reflectorHostContext);
const staticReflector = new StaticReflector(reflectorHost);
StaticAndDynamicReflectionCapabilities.install(staticReflector);
const config = new compiler.CompilerConfig({
genDebugInfo: options.debug === true,
defaultEncapsulation: ViewEncapsulation.Emulated,
logBindingUpdate: false,
useJit: false
});
const normalizer = new DirectiveNormalizer(resourceLoader, urlResolver, htmlParser, config);
const expressionParser = new Parser(new Lexer());
const elementSchemaRegistry = new DomElementSchemaRegistry();
const console = new Console();
const tmplParser =
new TemplateParser(expressionParser, elementSchemaRegistry, htmlParser, console, []);
const resolver = new CompileMetadataResolver(
new compiler.NgModuleResolver(staticReflector),
new compiler.DirectiveResolver(staticReflector), new compiler.PipeResolver(staticReflector),
elementSchemaRegistry, staticReflector);
const offlineCompiler = new compiler.OfflineCompiler(
resolver, normalizer, tmplParser, new StyleCompiler(urlResolver), new ViewCompiler(config),
new NgModuleCompiler(), new TypeScriptEmitter(reflectorHost), null, null);
// TODO(vicb): implicit tags & attributes
let messageBundle = new compiler.MessageBundle(htmlParser, [], {});
return new Extractor(
program, compilerHost, staticReflector, messageBundle, reflectorHost, resolver, normalizer,
offlineCompiler);
}
}
interface FileMetadata {
fileUrl: string;
components: StaticSymbol[];
ngModules: StaticSymbol[];
}
// Entry point
if (require.main === module) {
const args = require('minimist')(process.argv.slice(2));

View File

@ -1,110 +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
*/
/**
* Extract i18n messages from source code
*/
// Must be imported first, because angular2 decorators throws on load.
import 'reflect-metadata';
import * as compiler from '@angular/compiler';
import {ViewEncapsulation} from '@angular/core';
import * as tsc from '@angular/tsc-wrapped';
import * as ts from 'typescript';
import {extractProgramSymbols} from './codegen';
import {ReflectorHost} from './reflector_host';
import {StaticAndDynamicReflectionCapabilities} from './static_reflection_capabilities';
import {StaticReflector, StaticSymbol} from './static_reflector';
export class Extractor {
constructor(
private options: tsc.AngularCompilerOptions, private program: ts.Program,
public host: ts.CompilerHost, private staticReflector: StaticReflector,
private messageBundle: compiler.MessageBundle, private reflectorHost: ReflectorHost,
private metadataResolver: compiler.CompileMetadataResolver,
private directiveNormalizer: compiler.DirectiveNormalizer) {}
extract(): Promise<compiler.MessageBundle> {
const programSymbols: StaticSymbol[] =
extractProgramSymbols(this.program, this.staticReflector, this.reflectorHost, this.options);
const files =
compiler.analyzeNgModules(programSymbols, {transitiveModules: true}, this.metadataResolver)
.files;
const errors: compiler.ParseError[] = [];
const filePromises: Promise<any>[] = [];
files.forEach(file => {
const cmpPromises: Promise<compiler.CompileDirectiveMetadata>[] = [];
file.directives.forEach(directiveType => {
const dirMeta = this.metadataResolver.getDirectiveMetadata(directiveType);
if (dirMeta.isComponent) {
cmpPromises.push(this.directiveNormalizer.normalizeDirective(dirMeta).asyncResult);
}
});
if (cmpPromises.length) {
const done =
Promise.all(cmpPromises).then((compMetas: compiler.CompileDirectiveMetadata[]) => {
compMetas.forEach(compMeta => {
const html = compMeta.template.template;
const interpolationConfig =
compiler.InterpolationConfig.fromArray(compMeta.template.interpolation);
errors.push(...this.messageBundle.updateFromTemplate(
html, file.srcUrl, interpolationConfig));
});
});
filePromises.push(done);
}
});
if (errors.length) {
throw new Error(errors.map(e => e.toString()).join('\n'));
}
return Promise.all(filePromises).then(_ => this.messageBundle);
}
static create(
options: tsc.AngularCompilerOptions, translationsFormat: string, program: ts.Program,
compilerHost: ts.CompilerHost, resourceLoader: compiler.ResourceLoader,
reflectorHost?: ReflectorHost): Extractor {
const htmlParser = new compiler.I18NHtmlParser(new compiler.HtmlParser());
const urlResolver: compiler.UrlResolver = compiler.createOfflineCompileUrlResolver();
if (!reflectorHost) reflectorHost = new ReflectorHost(program, compilerHost, options);
const staticReflector = new StaticReflector(reflectorHost);
StaticAndDynamicReflectionCapabilities.install(staticReflector);
const config = new compiler.CompilerConfig({
genDebugInfo: options.debug === true,
defaultEncapsulation: ViewEncapsulation.Emulated,
logBindingUpdate: false,
useJit: false
});
const normalizer =
new compiler.DirectiveNormalizer(resourceLoader, urlResolver, htmlParser, config);
const elementSchemaRegistry = new compiler.DomElementSchemaRegistry();
const resolver = new compiler.CompileMetadataResolver(
new compiler.NgModuleResolver(staticReflector),
new compiler.DirectiveResolver(staticReflector), new compiler.PipeResolver(staticReflector),
elementSchemaRegistry, staticReflector);
// TODO(vicb): implicit tags & attributes
let messageBundle = new compiler.MessageBundle(htmlParser, [], {});
return new Extractor(
options, program, compilerHost, staticReflector, messageBundle, reflectorHost, resolver,
normalizer);
}
}

View File

@ -19,9 +19,7 @@ import {CodeGenerator} from './codegen';
function codegen(
ngOptions: tsc.AngularCompilerOptions, cliOptions: tsc.NgcCliOptions, program: ts.Program,
host: ts.CompilerHost) {
return CodeGenerator.create(ngOptions, cliOptions, program, host).codegen({
transitiveModules: true
});
return CodeGenerator.create(ngOptions, cliOptions, program, host).codegen();
}
// CLI entry point

View File

@ -0,0 +1,54 @@
/**
* @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 {__compiler_private__ as _} from '@angular/compiler';
export type AssetUrl = typeof _._AssetUrl;
export var AssetUrl: typeof _.AssetUrl = _.AssetUrl;
export type ImportGenerator = typeof _._ImportGenerator;
export var ImportGenerator: typeof _.ImportGenerator = _.ImportGenerator;
export type CompileMetadataResolver = typeof _._CompileMetadataResolver;
export var CompileMetadataResolver: typeof _.CompileMetadataResolver = _.CompileMetadataResolver;
export type HtmlParser = typeof _._HtmlParser;
export var HtmlParser: typeof _.HtmlParser = _.HtmlParser;
export type ParseError = typeof _._ParseError;
export var ParseError: typeof _.ParseError = _.ParseError;
export type InterpolationConfig = typeof _._InterpolationConfig;
export var InterpolationConfig: typeof _.InterpolationConfig = _.InterpolationConfig;
export type DirectiveNormalizer = typeof _._DirectiveNormalizer;
export var DirectiveNormalizer: typeof _.DirectiveNormalizer = _.DirectiveNormalizer;
export type Lexer = typeof _._Lexer;
export var Lexer: typeof _.Lexer = _.Lexer;
export type Parser = typeof _._Parser;
export var Parser: typeof _.Parser = _.Parser;
export type TemplateParser = typeof _._TemplateParser;
export var TemplateParser: typeof _.TemplateParser = _.TemplateParser;
export type DomElementSchemaRegistry = typeof _._DomElementSchemaRegistry;
export var DomElementSchemaRegistry: typeof _.DomElementSchemaRegistry = _.DomElementSchemaRegistry;
export type StyleCompiler = typeof _._StyleCompiler;
export var StyleCompiler: typeof _.StyleCompiler = _.StyleCompiler;
export type ViewCompiler = typeof _._ViewCompiler;
export var ViewCompiler: typeof _.ViewCompiler = _.ViewCompiler;
export type NgModuleCompiler = typeof _._NgModuleCompiler;
export var NgModuleCompiler: typeof _.NgModuleCompiler = _.NgModuleCompiler;
export type TypeScriptEmitter = typeof _._TypeScriptEmitter;
export var TypeScriptEmitter: typeof _.TypeScriptEmitter = _.TypeScriptEmitter;

View File

@ -6,12 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AssetUrl, ImportGenerator} from '@angular/compiler';
import {AngularCompilerOptions, MetadataCollector, ModuleMetadata} from '@angular/tsc-wrapped';
import * as fs from 'fs';
import * as path from 'path';
import * as ts from 'typescript';
import {AssetUrl, ImportGenerator} from './private_import_compiler';
import {StaticReflectorHost, StaticSymbol} from './static_reflector';
const EXT = /(\.ts|\.d\.ts|\.js|\.jsx|\.tsx)$/;
@ -250,12 +250,6 @@ export class ReflectorHost implements StaticReflectorHost, ImportGenerator {
} else {
const sf = this.program.getSourceFile(filePath);
if (!sf) {
if (this.context.fileExists(filePath)) {
const sourceText = this.context.readFile(filePath);
return this.metadataCollector.getMetadata(
ts.createSourceFile(filePath, sourceText, ts.ScriptTarget.Latest, true));
}
throw new Error(`Source file ${filePath} not present in program.`);
}
return this.metadataCollector.getMetadata(sf);

View File

@ -20,10 +20,11 @@ export class StaticAndDynamicReflectionCapabilities {
isReflectionEnabled(): boolean { return true; }
factory(type: any): Function { return this.dynamicDelegate.factory(type); }
hasLifecycleHook(type: any, lcProperty: string): boolean {
return isStaticType(type) ? this.staticDelegate.hasLifecycleHook(type, lcProperty) :
this.dynamicDelegate.hasLifecycleHook(type, lcProperty);
interfaces(type: any): any[] { return this.dynamicDelegate.interfaces(type); }
hasLifecycleHook(type: any, lcInterface: /*Type*/ any, lcProperty: string): boolean {
return isStaticType(type) ?
this.staticDelegate.hasLifecycleHook(type, lcInterface, lcProperty) :
this.dynamicDelegate.hasLifecycleHook(type, lcInterface, lcProperty);
}
parameters(type: any): any[][] {
return isStaticType(type) ? this.staticDelegate.parameters(type) :

View File

@ -25,7 +25,7 @@ export interface StaticReflectorHost {
* @param modulePath is a string identifier for a module as an absolute path.
* @returns the metadata for the given module.
*/
getMetadataFor(modulePath: string): {[key: string]: any}|{[key: string]: any}[];
getMetadataFor(modulePath: string): {[key: string]: any};
/**
* Resolve a symbol from an import statement form, to the file where it is declared.
@ -44,8 +44,6 @@ export interface StaticReflectorHost {
animationMetadata: string,
provider: string
};
getCanonicalFileName(fileName: string): string;
}
/**
@ -72,12 +70,13 @@ export class StaticReflector implements ReflectorReader {
constructor(private host: StaticReflectorHost) { this.initializeConversionMap(); }
importUri(typeOrFunc: StaticSymbol): string {
const staticSymbol = this.host.findDeclaration(typeOrFunc.filePath, typeOrFunc.name, '');
var staticSymbol = this.host.findDeclaration(typeOrFunc.filePath, typeOrFunc.name, '');
return staticSymbol ? staticSymbol.filePath : null;
}
resolveIdentifier(name: string, moduleUrl: string, runtime: any): any {
return this.host.findDeclaration(moduleUrl, name, '');
const result = this.host.findDeclaration(moduleUrl, name, '');
return result;
}
resolveEnum(enumIdentifier: any, name: string): any {
@ -158,15 +157,14 @@ export class StaticReflector implements ReflectorReader {
}
}
hasLifecycleHook(type: any, lcProperty: string): boolean {
hasLifecycleHook(type: any, lcInterface: /*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;
let classMetadata = this.getTypeMetadata(type);
let members = classMetadata ? classMetadata['members'] : null;
let member: any[] = members ? members[lcProperty] : null;
return member ? member.some(a => a['__symbolic'] == 'method') : false;
}
@ -237,9 +235,9 @@ export class StaticReflector implements ReflectorReader {
/** @internal */
public simplify(context: StaticSymbol, value: any): any {
const _this = this;
let _this = this;
let scope = BindingScope.empty;
const calling = new Map<StaticSymbol, boolean>();
let calling = new Map<StaticSymbol, boolean>();
function simplifyInContext(context: StaticSymbol, value: any, depth: number): any {
function resolveReference(context: StaticSymbol, expression: any): StaticSymbol {
@ -254,15 +252,16 @@ export class StaticReflector implements ReflectorReader {
}
function resolveReferenceValue(staticSymbol: StaticSymbol): any {
const moduleMetadata = _this.getModuleMetadata(staticSymbol.filePath);
const declarationValue =
let result: any = staticSymbol;
let moduleMetadata = _this.getModuleMetadata(staticSymbol.filePath);
let declarationValue =
moduleMetadata ? moduleMetadata['metadata'][staticSymbol.name] : null;
return declarationValue;
}
function isOpaqueToken(context: StaticSymbol, value: any): boolean {
if (value && value.__symbolic === 'new' && value.expression) {
const target = value.expression;
let target = value.expression;
if (target.__symbolic == 'reference') {
return sameSymbol(resolveReference(context, target), _this.opaqueToken);
}
@ -367,9 +366,6 @@ export class StaticReflector implements ReflectorReader {
}
return result;
}
if (expression instanceof StaticSymbol) {
return expression;
}
if (expression) {
if (expression['__symbolic']) {
let staticSymbol: StaticSymbol;
@ -533,7 +529,7 @@ export class StaticReflector implements ReflectorReader {
}
}
const result = simplifyInContext(context, value, 0);
let result = simplifyInContext(context, value, 0);
if (shouldIgnore(result)) {
return undefined;
}
@ -548,7 +544,8 @@ export class StaticReflector implements ReflectorReader {
if (!moduleMetadata) {
moduleMetadata = this.host.getMetadataFor(module);
if (Array.isArray(moduleMetadata)) {
moduleMetadata = moduleMetadata.find(md => md['version'] === SUPPORTED_SCHEMA_VERSION) ||
moduleMetadata = (<Array<any>>moduleMetadata)
.find(element => element.version === SUPPORTED_SCHEMA_VERSION) ||
moduleMetadata[0];
}
if (!moduleMetadata) {
@ -565,8 +562,12 @@ export class StaticReflector implements ReflectorReader {
}
private getTypeMetadata(type: StaticSymbol): {[key: string]: any} {
const moduleMetadata = this.getModuleMetadata(type.filePath);
return moduleMetadata['metadata'][type.name] || {__symbolic: 'class'};
let moduleMetadata = this.getModuleMetadata(type.filePath);
let result = moduleMetadata['metadata'][type.name];
if (!result) {
result = {__symbolic: 'class'};
}
return result;
}
}
@ -606,7 +607,7 @@ function produceErrorMessage(error: any): string {
function mapStringMap(input: {[key: string]: any}, transform: (value: any, key: string) => any):
{[key: string]: any} {
if (!input) return {};
const result: {[key: string]: any} = {};
var result: {[key: string]: any} = {};
Object.keys(input).forEach((key) => {
let value = transform(input[key], key);
if (!shouldIgnore(value)) {
@ -631,7 +632,8 @@ abstract class BindingScope {
public static empty: BindingScope = {resolve: name => BindingScope.missing};
public static build(): BindingScopeBuilder {
const current = new Map<string, any>();
let current = new Map<string, any>();
let parent: BindingScope = undefined;
return {
define: function(name, value) {
current.set(name, value);

View File

@ -8,6 +8,7 @@
import {StaticReflector, StaticReflectorHost, StaticSymbol} from '@angular/compiler-cli/src/static_reflector';
import {HostListener, animate, group, keyframes, sequence, state, style, transition, trigger} from '@angular/core';
import {ListWrapper} from '@angular/facade/src/collection';
import {MetadataCollector} from '@angular/tsc-wrapped';
import * as ts from 'typescript';
@ -118,11 +119,6 @@ describe('StaticReflector', () => {
expect(simplify(noContext, 'some value')).toBe('some value');
});
it('should simplify a static symbol into itself', () => {
const staticSymbol = new StaticSymbol('', '');
expect(simplify(noContext, staticSymbol)).toBe(staticSymbol);
});
it('should simplify an array into a copy of the array', () => {
expect(simplify(noContext, [1, 2, 3])).toEqual([1, 2, 3]);
});
@ -454,9 +450,6 @@ class MockReflectorHost implements StaticReflectorHost {
provider: 'angular2/src/core/di/provider'
};
}
getCanonicalFileName(fileName: string): string { return fileName; }
getStaticSymbol(declarationFile: string, name: string, members?: string[]): StaticSymbol {
var cacheKey = `${declarationFile}:${name}${members?'.'+members.join('.'):''}`;
var result = this.staticTypeCache.get(cacheKey);
@ -473,7 +466,7 @@ class MockReflectorHost implements StaticReflectorHost {
function resolvePath(pathParts: string[]): string {
let result: string[] = [];
pathParts.forEach((part, index) => {
ListWrapper.forEachWithIndex(pathParts, (part, index) => {
switch (part) {
case '':
case '.':

View File

@ -21,36 +21,6 @@
* </p>
* </div>
*/
export * from './src/template_parser/template_ast';
export {TEMPLATE_TRANSFORMS} from './src/template_parser/template_parser';
export {CompilerConfig, RenderTypes} from './src/config';
export * from './src/compile_metadata';
export * from './src/offline_compiler';
export {RuntimeCompiler} from './src/runtime_compiler';
export * from './src/url_resolver';
export * from './src/resource_loader';
export * from './src/compiler';
export {DirectiveResolver} from './src/directive_resolver';
export {PipeResolver} from './src/pipe_resolver';
export {NgModuleResolver} from './src/ng_module_resolver';
export {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from './src/ml_parser/interpolation_config';
export * from './src/schema/element_schema_registry';
export * from './src/i18n/index';
export * from './src/directive_normalizer';
export * from './src/expression_parser/lexer';
export * from './src/expression_parser/parser';
export * from './src/metadata_resolver';
export * from './src/ml_parser/html_parser';
export * from './src/ml_parser/interpolation_config';
export {NgModuleCompiler} from './src/ng_module_compiler';
export {DirectiveWrapperCompiler} from './src/directive_wrapper_compiler';
export * from './src/output/path_util';
export * from './src/output/ts_emitter';
export * from './src/parse_util';
export * from './src/schema/dom_element_schema_registry';
export * from './src/selector';
export * from './src/style_compiler';
export * from './src/template_parser/template_parser';
export {ViewCompiler} from './src/view_compiler/view_compiler';
export * from './src/index';
// This file only reexports content of the `src` folder. Keep it that way.

View File

@ -32,7 +32,6 @@ export class AnimationCompiler {
var _ANIMATION_FACTORY_ELEMENT_VAR = o.variable('element');
var _ANIMATION_DEFAULT_STATE_VAR = o.variable('defaultStateStyles');
var _ANIMATION_FACTORY_VIEW_VAR = o.variable('view');
var _ANIMATION_FACTORY_VIEW_CONTEXT = _ANIMATION_FACTORY_VIEW_VAR.prop('animationContext');
var _ANIMATION_FACTORY_RENDERER_VAR = _ANIMATION_FACTORY_VIEW_VAR.prop('renderer');
var _ANIMATION_CURRENT_STATE_VAR = o.variable('currentState');
var _ANIMATION_NEXT_STATE_VAR = o.variable('nextState');
@ -62,9 +61,7 @@ class _AnimationBuilder implements AnimationAstVisitor {
}
ast.styles.forEach(entry => {
const entries =
Object.keys(entry).map((key): [string, o.Expression] => [key, o.literal(entry[key])]);
stylesArr.push(o.literalMap(entries));
stylesArr.push(o.literalMap(Object.keys(entry).map(key => [key, o.literal(entry[key])])));
});
return o.importExpr(resolveIdentifier(Identifiers.AnimationStyles)).instantiate([
@ -187,7 +184,7 @@ class _AnimationBuilder implements AnimationAstVisitor {
context.stateMap.registerState(DEFAULT_STATE, {});
var statements: o.Statement[] = [];
statements.push(_ANIMATION_FACTORY_VIEW_CONTEXT
statements.push(_ANIMATION_FACTORY_VIEW_VAR
.callMethod(
'cancelActiveAnimation',
[
@ -264,21 +261,16 @@ class _AnimationBuilder implements AnimationAstVisitor {
.toStmt()])])
.toStmt());
statements.push(_ANIMATION_FACTORY_VIEW_CONTEXT
statements.push(_ANIMATION_FACTORY_VIEW_VAR
.callMethod(
'queueAnimation',
[
_ANIMATION_FACTORY_ELEMENT_VAR, o.literal(this.animationName),
_ANIMATION_PLAYER_VAR
_ANIMATION_PLAYER_VAR, _ANIMATION_TIME_VAR,
_ANIMATION_CURRENT_STATE_VAR, _ANIMATION_NEXT_STATE_VAR
])
.toStmt());
statements.push(new o.ReturnStatement(
o.importExpr(resolveIdentifier(Identifiers.AnimationTransition)).instantiate([
_ANIMATION_PLAYER_VAR, _ANIMATION_CURRENT_STATE_VAR, _ANIMATION_NEXT_STATE_VAR,
_ANIMATION_TIME_VAR
])));
return o.fn(
[
new o.FnParam(
@ -288,7 +280,7 @@ class _AnimationBuilder implements AnimationAstVisitor {
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);
}
build(ast: AnimationAst): AnimationEntryCompileResult {

View File

@ -7,8 +7,9 @@
*/
import {CompileAnimationAnimateMetadata, CompileAnimationEntryMetadata, CompileAnimationGroupMetadata, CompileAnimationKeyframesSequenceMetadata, CompileAnimationMetadata, CompileAnimationSequenceMetadata, CompileAnimationStateDeclarationMetadata, CompileAnimationStateTransitionMetadata, CompileAnimationStyleMetadata, CompileAnimationWithStepsMetadata, CompileDirectiveMetadata} from '../compile_metadata';
import {StringMapWrapper} from '../facade/collection';
import {isBlank, isPresent} from '../facade/lang';
import {ListWrapper, StringMapWrapper} from '../facade/collection';
import {isArray, isBlank, isPresent, isString, isStringMap} from '../facade/lang';
import {Math} from '../facade/math';
import {ParseError} from '../parse_util';
import {ANY_STATE, FILL_STYLE_FLAG} from '../private_import_core';
@ -96,7 +97,7 @@ function _parseAnimationDeclarationStates(
var styleValues: Styles[] = [];
stateMetadata.styles.styles.forEach(stylesEntry => {
// TODO (matsko): change this when we get CSS class integration support
if (typeof stylesEntry === 'object' && stylesEntry !== null) {
if (isStringMap(stylesEntry)) {
styleValues.push(stylesEntry as Styles);
} else {
errors.push(new AnimationParseError(
@ -114,10 +115,13 @@ function _parseAnimationStateTransition(
stateStyles: {[key: string]: AnimationStylesAst},
errors: AnimationParseError[]): AnimationStateTransitionAst {
var styles = new StylesCollection();
var transitionExprs: AnimationStateTransitionExpression[] = [];
var transitionExprs: any[] /** TODO #9100 */ = [];
var transitionStates = transitionStateMetadata.stateChangeExpr.split(/\s*,\s*/);
transitionStates.forEach(
expr => { transitionExprs.push(..._parseAnimationTransitionExpr(expr, errors)); });
transitionStates.forEach(expr => {
_parseAnimationTransitionExpr(expr, errors).forEach(transExpr => {
transitionExprs.push(transExpr);
});
});
var entry = _normalizeAnimationEntry(transitionStateMetadata.steps);
var animation = _normalizeStyleSteps(entry, stateStyles, errors);
var animationAst = _parseTransitionAnimation(animation, 0, styles, stateStyles, errors);
@ -132,25 +136,9 @@ function _parseAnimationStateTransition(
return new AnimationStateTransitionAst(transitionExprs, stepsAst);
}
function _parseAnimationAlias(alias: string, errors: AnimationParseError[]): string {
switch (alias) {
case ':enter':
return 'void => *';
case ':leave':
return '* => void';
default:
errors.push(
new AnimationParseError(`the transition alias value "${alias}" is not supported`));
return '* => *';
}
}
function _parseAnimationTransitionExpr(
eventStr: string, errors: AnimationParseError[]): AnimationStateTransitionExpression[] {
var expressions: AnimationStateTransitionExpression[] = [];
if (eventStr[0] == ':') {
eventStr = _parseAnimationAlias(eventStr, errors);
}
var expressions: any[] /** TODO #9100 */ = [];
var match = eventStr.match(/^(\*|[-\w]+)\s*(<?[=-]>)\s*(\*|[-\w]+)$/);
if (!isPresent(match) || match.length < 4) {
errors.push(new AnimationParseError(`the provided ${eventStr} is not of a supported format`));
@ -171,16 +159,18 @@ function _parseAnimationTransitionExpr(
function _normalizeAnimationEntry(entry: CompileAnimationMetadata | CompileAnimationMetadata[]):
CompileAnimationMetadata {
return Array.isArray(entry) ? new CompileAnimationSequenceMetadata(entry) : entry;
return isArray(entry) ? new CompileAnimationSequenceMetadata(<CompileAnimationMetadata[]>entry) :
<CompileAnimationMetadata>entry;
}
function _normalizeStyleMetadata(
entry: CompileAnimationStyleMetadata, stateStyles: {[key: string]: AnimationStylesAst},
errors: AnimationParseError[]): {[key: string]: string | number}[] {
var normalizedStyles: {[key: string]: string | number}[] = [];
errors: AnimationParseError[]): Array<{[key: string]: string | number}> {
var normalizedStyles: any[] /** TODO #9100 */ = [];
entry.styles.forEach(styleEntry => {
if (typeof styleEntry === 'string') {
normalizedStyles.push(..._resolveStylesFromState(<string>styleEntry, stateStyles, errors));
if (isString(styleEntry)) {
ListWrapper.addAll(
normalizedStyles, _resolveStylesFromState(<string>styleEntry, stateStyles, errors));
} else {
normalizedStyles.push(<{[key: string]: string | number}>styleEntry);
}
@ -199,10 +189,10 @@ function _normalizeStyleSteps(
function _mergeAnimationStyles(
stylesList: any[], newItem: {[key: string]: string | number} | string) {
if (typeof newItem === 'object' && newItem !== null && stylesList.length > 0) {
if (isStringMap(newItem) && stylesList.length > 0) {
var lastIndex = stylesList.length - 1;
var lastItem = stylesList[lastIndex];
if (typeof lastItem === 'object' && lastItem !== null) {
if (isStringMap(lastItem)) {
stylesList[lastIndex] = StringMapWrapper.merge(
<{[key: string]: string | number}>lastItem, <{[key: string]: string | number}>newItem);
return;
@ -289,7 +279,7 @@ function _resolveStylesFromState(
`Unable to apply styles due to missing a state: "${normalizedStateName}"`));
} else {
value.styles.forEach(stylesEntry => {
if (typeof stylesEntry === 'object' && stylesEntry !== null) {
if (isStringMap(stylesEntry)) {
styles.push(stylesEntry as Styles);
}
});
@ -345,12 +335,13 @@ function _parseAnimationKeyframes(
});
if (doSortKeyframes) {
rawKeyframes.sort((a, b) => a[0] <= b[0] ? -1 : 1);
ListWrapper.sort(rawKeyframes, (a, b) => a[0] <= b[0] ? -1 : 1);
}
var i: any /** TODO #9100 */;
var firstKeyframe = rawKeyframes[0];
if (firstKeyframe[0] != _INITIAL_KEYFRAME) {
rawKeyframes.splice(0, 0, firstKeyframe = [_INITIAL_KEYFRAME, {}]);
ListWrapper.insert(rawKeyframes, 0, firstKeyframe = [_INITIAL_KEYFRAME, {}]);
}
var firstKeyframeStyles = firstKeyframe[1];
@ -362,7 +353,7 @@ function _parseAnimationKeyframes(
}
var lastKeyframeStyles = lastKeyframe[1];
for (let i = 1; i <= limit; i++) {
for (i = 1; i <= limit; i++) {
let entry = rawKeyframes[i];
let styles = entry[1];
@ -373,7 +364,7 @@ function _parseAnimationKeyframes(
});
}
for (let i = limit - 1; i >= 0; i--) {
for (i = limit - 1; i >= 0; i--) {
let entry = rawKeyframes[i];
let styles = entry[1];
@ -420,7 +411,7 @@ function _parseTransitionAnimation(
steps.push(new AnimationStepAst(startingStyles, [], 0, 0, ''));
} else {
var innerStep = <AnimationStepAst>innerAst;
innerStep.startingStyles.styles.push(...previousStyles);
ListWrapper.addAll(innerStep.startingStyles.styles, previousStyles);
}
previousStyles = null;
}
@ -501,7 +492,7 @@ function _parseTimeExpression(
var duration: number;
var delay: number = 0;
var easing: string = null;
if (typeof exp === 'string') {
if (isString(exp)) {
const matches = exp.match(regex);
if (matches === null) {
errors.push(new AnimationParseError(`The provided timing value "${exp}" is invalid.`));

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ListWrapper} from '../facade/collection';
import {isPresent} from '../facade/lang';
export class StylesCollectionEntry {
@ -36,7 +37,7 @@ export class StylesCollection {
}
}
entries.splice(insertionIndex, 0, tuple);
ListWrapper.insert(entries, insertionIndex, tuple);
}
getByIndex(property: string, index: number): StylesCollectionEntry {

View File

@ -8,17 +8,17 @@
import {isDevMode} from '@angular/core';
import {isBlank, isPresent} from '../src/facade/lang';
import {isArray, isBlank, isPresent, isString} from '../src/facade/lang';
export function assertArrayOfStrings(identifier: string, value: any) {
if (!isDevMode() || isBlank(value)) {
return;
}
if (!Array.isArray(value)) {
if (!isArray(value)) {
throw new Error(`Expected '${identifier}' to be an array of strings.`);
}
for (var i = 0; i < value.length; i += 1) {
if (typeof value[i] !== 'string') {
if (!isString(value[i])) {
throw new Error(`Expected '${identifier}' to be an array of strings.`);
}
}
@ -33,7 +33,7 @@ const INTERPOLATION_BLACKLIST_REGEXPS = [
];
export function assertInterpolationSymbols(identifier: string, value: any): void {
if (isPresent(value) && !(Array.isArray(value) && value.length == 2)) {
if (isPresent(value) && !(isArray(value) && value.length == 2)) {
throw new Error(`Expected '${identifier}' to be an array, [start, end].`);
} else if (isDevMode() && !isBlank(value)) {
const start = value[0] as string;

View File

@ -9,7 +9,7 @@
import {ChangeDetectionStrategy, SchemaMetadata, Type, ViewEncapsulation} from '@angular/core';
import {ListWrapper, MapWrapper} from './facade/collection';
import {isPresent} from './facade/lang';
import {isPresent, isStringMap, normalizeBlank, normalizeBool} from './facade/lang';
import {LifecycleHooks} from './private_import_core';
import {CssSelector} from './selector';
import {sanitizeIdentifier, splitAtColon} from './util';
@ -23,6 +23,7 @@ function unimplemented(): any {
// group 2: "event" from "(event)"
// group 3: "@trigger" from "@trigger"
const HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))|(\@[-\w]+)$/;
const UNDEFINED = new Object();
export abstract class CompileMetadataWithIdentifier {
get identifier(): CompileIdentifierMetadata { return <CompileIdentifierMetadata>unimplemented(); }
@ -124,12 +125,12 @@ export class CompileDiDependencyMetadata {
token?: CompileTokenMetadata,
value?: any
} = {}) {
this.isAttribute = !!isAttribute;
this.isSelf = !!isSelf;
this.isHost = !!isHost;
this.isSkipSelf = !!isSkipSelf;
this.isOptional = !!isOptional;
this.isValue = !!isValue;
this.isAttribute = normalizeBool(isAttribute);
this.isSelf = normalizeBool(isSelf);
this.isHost = normalizeBool(isHost);
this.isSkipSelf = normalizeBool(isSkipSelf);
this.isOptional = normalizeBool(isOptional);
this.isValue = normalizeBool(isValue);
this.query = query;
this.viewQuery = viewQuery;
this.token = token;
@ -160,8 +161,8 @@ export class CompileProviderMetadata {
this.useValue = useValue;
this.useExisting = useExisting;
this.useFactory = useFactory;
this.deps = deps || null;
this.multi = !!multi;
this.deps = normalizeBlank(deps);
this.multi = normalizeBool(multi);
}
}
@ -191,7 +192,7 @@ export class CompileTokenMetadata implements CompileMetadataWithIdentifier {
{value?: any, identifier?: CompileIdentifierMetadata, identifierIsInstance?: boolean}) {
this.value = value;
this.identifier = identifier;
this.identifierIsInstance = !!identifierIsInstance;
this.identifierIsInstance = normalizeBool(identifierIsInstance);
}
get reference(): any {
@ -226,7 +227,7 @@ export class CompileTypeMetadata extends CompileIdentifierMetadata {
lifecycleHooks?: LifecycleHooks[];
} = {}) {
super({reference: reference, name: name, moduleUrl: moduleUrl, prefix: prefix, value: value});
this.isHost = !!isHost;
this.isHost = normalizeBool(isHost);
this.diDeps = _normalizeArray(diDeps);
this.lifecycleHooks = _normalizeArray(lifecycleHooks);
}
@ -247,8 +248,8 @@ export class CompileQueryMetadata {
read?: CompileTokenMetadata
} = {}) {
this.selectors = selectors;
this.descendants = !!descendants;
this.first = !!first;
this.descendants = normalizeBool(descendants);
this.first = normalizeBool(first);
this.propertyName = propertyName;
this.read = read;
}
@ -302,9 +303,9 @@ export class CompileTemplateMetadata {
this.styles = _normalizeArray(styles);
this.styleUrls = _normalizeArray(styleUrls);
this.externalStylesheets = _normalizeArray(externalStylesheets);
this.animations = animations ? ListWrapper.flatten(animations) : [];
this.ngContentSelectors = ngContentSelectors || [];
if (interpolation && interpolation.length != 2) {
this.animations = isPresent(animations) ? ListWrapper.flatten(animations) : [];
this.ngContentSelectors = isPresent(ngContentSelectors) ? ngContentSelectors : [];
if (isPresent(interpolation) && interpolation.length != 2) {
throw new Error(`'interpolation' should have a start and an end symbol.`);
}
this.interpolation = interpolation;
@ -374,7 +375,7 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
return new CompileDirectiveMetadata({
type,
isComponent: !!isComponent, selector, exportAs, changeDetection,
isComponent: normalizeBool(isComponent), selector, exportAs, changeDetection,
inputs: inputsMap,
outputs: outputsMap,
hostListeners,
@ -502,13 +503,13 @@ export class CompilePipeMetadata implements CompileMetadataWithIdentifier {
} = {}) {
this.type = type;
this.name = name;
this.pure = !!pure;
this.pure = normalizeBool(pure);
}
get identifier(): CompileIdentifierMetadata { return this.type; }
}
/**
* Metadata regarding compilation of a module.
* Metadata regarding compilation of a directive.
*/
export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier {
type: CompileTypeMetadata;
@ -568,7 +569,6 @@ export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier {
export class TransitiveCompileNgModuleMetadata {
directivesSet = new Set<Type<any>>();
pipesSet = new Set<Type<any>>();
constructor(
public modules: CompileNgModuleMetadata[], public providers: CompileProviderMetadata[],
public entryComponents: CompileTypeMetadata[], public directives: CompileDirectiveMetadata[],
@ -581,22 +581,20 @@ 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 MapWrapper.values(map);
}
function _normalizeArray(obj: any[]): any[] {
return obj || [];
return isPresent(obj) ? obj : [];
}
export function isStaticSymbol(value: any): value is StaticSymbol {
return typeof value === 'object' && value !== null && value['name'] && value['filePath'];
return isStringMap(value) && isPresent(value['name']) && isPresent(value['filePath']);
}
export interface StaticSymbol {

View File

@ -8,27 +8,39 @@
import {COMPILER_OPTIONS, Compiler, CompilerFactory, CompilerOptions, Inject, Injectable, Optional, PLATFORM_INITIALIZER, PlatformRef, Provider, ReflectiveInjector, TRANSLATIONS, TRANSLATIONS_FORMAT, Type, ViewEncapsulation, createPlatformFactory, isDevMode, platformCore} from '@angular/core';
import {CompilerConfig} from './config';
import {DirectiveNormalizer} from './directive_normalizer';
import {DirectiveResolver} from './directive_resolver';
import {DirectiveWrapperCompiler} from './directive_wrapper_compiler';
import {Lexer} from './expression_parser/lexer';
import {Parser} from './expression_parser/parser';
import * as i18n from './i18n/index';
import {CompileMetadataResolver} from './metadata_resolver';
import {HtmlParser} from './ml_parser/html_parser';
import {NgModuleCompiler} from './ng_module_compiler';
import {NgModuleResolver} from './ng_module_resolver';
import {PipeResolver} from './pipe_resolver';
import {Console, ReflectionCapabilities, Reflector, ReflectorReader, reflector} from './private_import_core';
import {ResourceLoader} from './resource_loader';
import {RuntimeCompiler} from './runtime_compiler';
import {DomElementSchemaRegistry} from './schema/dom_element_schema_registry';
import {ElementSchemaRegistry} from './schema/element_schema_registry';
import {StyleCompiler} from './style_compiler';
export * from './template_parser/template_ast';
export {TEMPLATE_TRANSFORMS} from './template_parser/template_parser';
export {CompilerConfig, RenderTypes} from './config';
export * from './compile_metadata';
export * from './offline_compiler';
export {RuntimeCompiler} from './runtime_compiler';
export * from './url_resolver';
export * from './resource_loader';
export {DirectiveResolver} from './directive_resolver';
export {PipeResolver} from './pipe_resolver';
export {NgModuleResolver} from './ng_module_resolver';
import {TemplateParser} from './template_parser/template_parser';
import {DEFAULT_PACKAGE_URL_PROVIDER, UrlResolver} from './url_resolver';
import {HtmlParser} from './ml_parser/html_parser';
import {DirectiveNormalizer} from './directive_normalizer';
import {CompileMetadataResolver} from './metadata_resolver';
import {StyleCompiler} from './style_compiler';
import {ViewCompiler} from './view_compiler/view_compiler';
import {NgModuleCompiler} from './ng_module_compiler';
import {CompilerConfig} from './config';
import {RuntimeCompiler} from './runtime_compiler';
import {ElementSchemaRegistry} from './schema/element_schema_registry';
import {DomElementSchemaRegistry} from './schema/dom_element_schema_registry';
import {UrlResolver, DEFAULT_PACKAGE_URL_PROVIDER} from './url_resolver';
import {Parser} from './expression_parser/parser';
import {Lexer} from './expression_parser/lexer';
import {DirectiveResolver} from './directive_resolver';
import {PipeResolver} from './pipe_resolver';
import {NgModuleResolver} from './ng_module_resolver';
import {Console, Reflector, reflector, ReflectorReader, ReflectionCapabilities} from './private_import_core';
import {ResourceLoader} from './resource_loader';
import * as i18n from './i18n/index';
const _NO_RESOURCE_LOADER: ResourceLoader = {
get(url: string): Promise<string>{
@ -65,7 +77,6 @@ export const COMPILER_PROVIDERS: Array<any|Type<any>|{[k: string]: any}|any[]> =
StyleCompiler,
ViewCompiler,
NgModuleCompiler,
DirectiveWrapperCompiler,
{provide: CompilerConfig, useValue: new CompilerConfig()},
RuntimeCompiler,
{provide: Compiler, useExisting: RuntimeCompiler},

View File

@ -1,48 +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 {Identifiers, resolveIdentifier} from '../identifiers';
import {ClassBuilder} from '../output/class_builder';
import * as o from '../output/output_ast';
import {ConvertPropertyBindingResult} from './expression_converter';
export class CheckBindingField {
constructor(public expression: o.ReadPropExpr, public bindingId: string) {}
}
export function createCheckBindingField(builder: ClassBuilder): CheckBindingField {
const bindingId = `${builder.fields.length}`;
const fieldExpr = createBindFieldExpr(bindingId);
// 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)))
.toStmt());
return new CheckBindingField(fieldExpr, bindingId);
}
export function createCheckBindingStmt(
evalResult: ConvertPropertyBindingResult, fieldExpr: o.ReadPropExpr,
throwOnChangeVar: o.Expression, actions: o.Statement[]): o.Statement[] {
var condition: o.Expression = o.importExpr(resolveIdentifier(Identifiers.checkBinding)).callFn([
throwOnChangeVar, fieldExpr, evalResult.currValExpr
]);
if (evalResult.forceUpdate) {
condition = evalResult.forceUpdate.or(condition);
}
return [
...evalResult.stmts, new o.IfStmt(condition, actions.concat([
<o.Statement>o.THIS_EXPR.prop(fieldExpr.name).set(evalResult.currValExpr).toStmt()
]))
];
}
function createBindFieldExpr(bindingId: string): o.ReadPropExpr {
return o.THIS_EXPR.prop(`_expr_${bindingId}`);
}

View File

@ -1,60 +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 {CompileTokenMetadata} from '../compile_metadata';
import {isPresent} from '../facade/lang';
import {IdentifierSpec, Identifiers, resolveEnumIdentifier, resolveIdentifier} 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);
}
}
export function createInlineArray(values: o.Expression[]): o.Expression {
if (values.length === 0) {
return o.importExpr(resolveIdentifier(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);
return o.importExpr(identifier).instantiate([
<o.Expression>o.literal(values.length)
].concat(values));
}
export function createPureProxy(
fn: o.Expression, argCount: number, pureProxyProp: o.ReadPropExpr,
builder: {fields: o.ClassField[], ctorStmts: {push: (stmt: o.Statement) => void}}) {
builder.fields.push(new o.ClassField(pureProxyProp.name, null));
var pureProxyId =
argCount < Identifiers.pureProxies.length ? Identifiers.pureProxies[argCount] : null;
if (!pureProxyId) {
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]))
.toStmt());
}
export function createEnumExpression(enumType: IdentifierSpec, enumValue: any): o.Expression {
const enumName =
Object.keys(enumType.runtime).find((propName) => enumType.runtime[propName] === enumValue);
if (!enumName) {
throw new Error(`Unknown enum value ${enumValue} in ${enumType.name}`);
}
return o.importExpr(resolveEnumIdentifier(resolveIdentifier(enumType), enumName));
}

View File

@ -1,89 +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 {SecurityContext} from '@angular/core';
import {isPresent} from '../facade/lang';
import {Identifiers, resolveIdentifier} from '../identifiers';
import * as o from '../output/output_ast';
import {BoundElementPropertyAst, PropertyBindingType} from '../template_parser/template_ast';
import {createEnumExpression} from './identifier_util';
export function writeToRenderer(
view: o.Expression, boundProp: BoundElementPropertyAst, renderElement: o.Expression,
renderValue: o.Expression, logBindingUpdate: boolean,
securityContextExpression?: o.Expression): o.Statement[] {
const updateStmts: o.Statement[] = [];
const renderer = view.prop('renderer');
renderValue = sanitizedValue(view, boundProp, renderValue, securityContextExpression);
switch (boundProp.type) {
case PropertyBindingType.Property:
if (logBindingUpdate) {
updateStmts.push(
o.importExpr(resolveIdentifier(Identifiers.setBindingDebugInfo))
.callFn([renderer, renderElement, o.literal(boundProp.name), renderValue])
.toStmt());
}
updateStmts.push(
renderer
.callMethod(
'setElementProperty', [renderElement, o.literal(boundProp.name), renderValue])
.toStmt());
break;
case PropertyBindingType.Attribute:
renderValue =
renderValue.isBlank().conditional(o.NULL_EXPR, renderValue.callMethod('toString', []));
updateStmts.push(
renderer
.callMethod(
'setElementAttribute', [renderElement, o.literal(boundProp.name), renderValue])
.toStmt());
break;
case PropertyBindingType.Class:
updateStmts.push(
renderer
.callMethod(
'setElementClass', [renderElement, o.literal(boundProp.name), renderValue])
.toStmt());
break;
case PropertyBindingType.Style:
var strValue: o.Expression = renderValue.callMethod('toString', []);
if (isPresent(boundProp.unit)) {
strValue = strValue.plus(o.literal(boundProp.unit));
}
renderValue = renderValue.isBlank().conditional(o.NULL_EXPR, strValue);
updateStmts.push(
renderer
.callMethod(
'setElementStyle', [renderElement, o.literal(boundProp.name), renderValue])
.toStmt());
break;
case PropertyBindingType.Animation:
throw new Error('Illegal state: Should not come here!');
}
return updateStmts;
}
function sanitizedValue(
view: o.Expression, boundProp: BoundElementPropertyAst, renderValue: o.Expression,
securityContextExpression?: o.Expression): o.Expression {
if (boundProp.securityContext === SecurityContext.NONE) {
return renderValue; // No sanitization needed.
}
if (!boundProp.needsRuntimeSecurityContext) {
securityContextExpression =
createEnumExpression(Identifiers.SecurityContext, boundProp.securityContext);
}
if (!securityContextExpression) {
throw new Error(`internal error, no SecurityContext given ${boundProp.name}`);
}
let ctx = view.prop('viewUtils').prop('sanitizer');
let args = [securityContextExpression, renderValue];
return ctx.callMethod('sanitize', args);
}

View File

@ -9,7 +9,7 @@
import * as chars from '../chars';
import {BaseError} from '../facade/errors';
import {isPresent} from '../facade/lang';
import {StringWrapper, isPresent} from '../facade/lang';
export enum CssTokenType {
EOF,
@ -155,7 +155,7 @@ export class CssScanner {
}
peekAt(index: number): number {
return index >= this.length ? chars.$EOF : this.input.charCodeAt(index);
return index >= this.length ? chars.$EOF : StringWrapper.charCodeAt(this.input, index);
}
consumeEmptyStatements(): void {
@ -310,7 +310,7 @@ export class CssScanner {
return this.scanCharacter();
}
return this.error(`Unexpected character [${String.fromCharCode(peek)}]`);
return this.error(`Unexpected character [${StringWrapper.fromCharCode(peek)}]`);
}
scanComment(): CssToken {
@ -476,7 +476,8 @@ export class CssScanner {
var index: number = this.index;
var column: number = this.column;
var line: number = this.line;
errorTokenValue = errorTokenValue || String.fromCharCode(this.peek);
errorTokenValue =
isPresent(errorTokenValue) ? errorTokenValue : StringWrapper.fromCharCode(this.peek);
var invalidToken = new CssToken(index, column, line, CssTokenType.Invalid, errorTokenValue);
var errorMessage =
generateErrorMessage(this.input, message, errorTokenValue, index, line, column);
@ -695,11 +696,11 @@ function isValidCssCharacter(code: number, mode: CssLexerMode): boolean {
}
function charCode(input: string, index: number): number {
return index >= input.length ? chars.$EOF : input.charCodeAt(index);
return index >= input.length ? chars.$EOF : StringWrapper.charCodeAt(input, index);
}
function charStr(code: number): string {
return String.fromCharCode(code);
return StringWrapper.fromCharCode(code);
}
export function isNewline(code: number): boolean {

View File

@ -330,7 +330,7 @@ export class CssParser {
var span: ParseSourceSpan;
var startSelector = selectors[0];
if (isPresent(block)) {
span = this._generateSourceSpan(startSelector, block);
var span = this._generateSourceSpan(startSelector, block);
ruleAst = new CssSelectorRuleAst(span, selectors, block);
} else {
var name = this._extractSourceContent(start, this._getScannerIndex() - 1);

View File

@ -71,13 +71,6 @@ export class DirectiveResolver {
} 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;

View File

@ -1,277 +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 {Injectable} from '@angular/core';
import {CompileDirectiveMetadata, CompileIdentifierMetadata} from './compile_metadata';
import {createCheckBindingField, createCheckBindingStmt} from './compiler_util/binding_util';
import {convertPropertyBinding} from './compiler_util/expression_converter';
import {writeToRenderer} from './compiler_util/render_util';
import {CompilerConfig} from './config';
import {Parser} from './expression_parser/parser';
import {Identifiers, resolveIdentifier} 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';
import {ParseError, ParseErrorLevel, ParseLocation, ParseSourceFile, ParseSourceSpan} from './parse_util';
import {Console, LifecycleHooks, isDefaultChangeDetectionStrategy} from './private_import_core';
import {ElementSchemaRegistry} from './schema/element_schema_registry';
import {BindingParser} from './template_parser/binding_parser';
import {BoundElementPropertyAst, BoundEventAst} from './template_parser/template_ast';
export class DirectiveWrapperCompileResult {
constructor(public statements: o.Statement[], public dirWrapperClassVar: string) {}
}
const CONTEXT_FIELD_NAME = 'context';
const CHANGES_FIELD_NAME = 'changes';
const CHANGED_FIELD_NAME = 'changed';
const CURR_VALUE_VAR = o.variable('currValue');
const THROW_ON_CHANGE_VAR = o.variable('throwOnChange');
const FORCE_UPDATE_VAR = o.variable('forceUpdate');
const VIEW_VAR = o.variable('view');
const RENDER_EL_VAR = o.variable('el');
const RESET_CHANGES_STMT = o.THIS_EXPR.prop(CHANGES_FIELD_NAME).set(o.literalMap([])).toStmt();
/**
* We generate directive wrappers to prevent code bloat when a directive is used.
* A directive wrapper encapsulates
* the dirty checking for `@Input`, the handling of `@HostListener` / `@HostBinding`
* and calling the lifecyclehooks `ngOnInit`, `ngOnChanges`, `ngDoCheck`.
*
* So far, only `@Input` and the lifecycle hooks have been implemented.
*/
@Injectable()
export class DirectiveWrapperCompiler {
static dirWrapperClassName(id: CompileIdentifierMetadata) { return `Wrapper_${id.name}`; }
constructor(
private compilerConfig: CompilerConfig, private _exprParser: Parser,
private _schemaRegistry: ElementSchemaRegistry, private _console: Console) {}
compile(dirMeta: CompileDirectiveMetadata): DirectiveWrapperCompileResult {
const builder = new DirectiveWrapperBuilder(this.compilerConfig, dirMeta);
Object.keys(dirMeta.inputs).forEach((inputFieldName) => {
addCheckInputMethod(inputFieldName, builder);
});
addDetectChangesInInputPropsMethod(builder);
const hostParseResult = parseHostBindings(dirMeta, this._exprParser, this._schemaRegistry);
reportParseErrors(hostParseResult.errors, this._console);
// host properties are change detected by the DirectiveWrappers,
// except for the animation properties as they need close integration with animation events
// and DirectiveWrappers don't support
// event listeners right now.
addDetectChangesInHostPropsMethod(
hostParseResult.hostProps.filter(hostProp => !hostProp.isAnimation), builder);
// TODO(tbosch): implement hostListeners via DirectiveWrapper as well!
const classStmt = builder.build();
return new DirectiveWrapperCompileResult([classStmt], classStmt.name);
}
}
class DirectiveWrapperBuilder implements ClassBuilder {
fields: o.ClassField[] = [];
getters: o.ClassGetter[] = [];
methods: o.ClassMethod[] = [];
ctorStmts: o.Statement[] = [];
genChanges: boolean;
ngOnChanges: boolean;
ngOnInit: boolean;
ngDoCheck: boolean;
constructor(public compilerConfig: CompilerConfig, public dirMeta: CompileDirectiveMetadata) {
const dirLifecycleHooks = dirMeta.type.lifecycleHooks;
this.genChanges = dirLifecycleHooks.indexOf(LifecycleHooks.OnChanges) !== -1 ||
this.compilerConfig.logBindingUpdate;
this.ngOnChanges = dirLifecycleHooks.indexOf(LifecycleHooks.OnChanges) !== -1;
this.ngOnInit = dirLifecycleHooks.indexOf(LifecycleHooks.OnInit) !== -1;
this.ngDoCheck = dirLifecycleHooks.indexOf(LifecycleHooks.DoCheck) !== -1;
}
build(): o.ClassStmt {
const dirDepParamNames: string[] = [];
for (let i = 0; i < this.dirMeta.type.diDeps.length; i++) {
dirDepParamNames.push(`p${i}`);
}
const fields: o.ClassField[] = [
new o.ClassField(CONTEXT_FIELD_NAME, o.importType(this.dirMeta.type)),
new o.ClassField(CHANGED_FIELD_NAME, o.BOOL_TYPE),
];
const ctorStmts: o.Statement[] =
[o.THIS_EXPR.prop(CHANGED_FIELD_NAME).set(o.literal(false)).toStmt()];
if (this.genChanges) {
fields.push(new o.ClassField(CHANGES_FIELD_NAME, new o.MapType(o.DYNAMIC_TYPE)));
ctorStmts.push(RESET_CHANGES_STMT);
}
ctorStmts.push(
o.THIS_EXPR.prop(CONTEXT_FIELD_NAME)
.set(o.importExpr(this.dirMeta.type)
.instantiate(dirDepParamNames.map((paramName) => o.variable(paramName))))
.toStmt());
return createClassStmt({
name: DirectiveWrapperCompiler.dirWrapperClassName(this.dirMeta.type),
ctorParams: dirDepParamNames.map((paramName) => new o.FnParam(paramName, o.DYNAMIC_TYPE)),
builders: [{fields, ctorStmts}, this]
});
}
}
function addDetectChangesInInputPropsMethod(builder: DirectiveWrapperBuilder) {
const changedVar = o.variable('changed');
const stmts: o.Statement[] = [
changedVar.set(o.THIS_EXPR.prop(CHANGED_FIELD_NAME)).toDeclStmt(),
o.THIS_EXPR.prop(CHANGED_FIELD_NAME).set(o.literal(false)).toStmt(),
];
const lifecycleStmts: o.Statement[] = [];
if (builder.genChanges) {
const onChangesStmts: o.Statement[] = [];
if (builder.ngOnChanges) {
onChangesStmts.push(o.THIS_EXPR.prop(CONTEXT_FIELD_NAME)
.callMethod('ngOnChanges', [o.THIS_EXPR.prop(CHANGES_FIELD_NAME)])
.toStmt());
}
if (builder.compilerConfig.logBindingUpdate) {
onChangesStmts.push(
o.importExpr(resolveIdentifier(Identifiers.setBindingDebugInfoForChanges))
.callFn(
[VIEW_VAR.prop('renderer'), RENDER_EL_VAR, o.THIS_EXPR.prop(CHANGES_FIELD_NAME)])
.toStmt());
}
onChangesStmts.push(RESET_CHANGES_STMT);
lifecycleStmts.push(new o.IfStmt(changedVar, onChangesStmts));
}
if (builder.ngOnInit) {
lifecycleStmts.push(new o.IfStmt(
VIEW_VAR.prop('numberOfChecks').identical(new o.LiteralExpr(0)),
[o.THIS_EXPR.prop(CONTEXT_FIELD_NAME).callMethod('ngOnInit', []).toStmt()]));
}
if (builder.ngDoCheck) {
lifecycleStmts.push(o.THIS_EXPR.prop(CONTEXT_FIELD_NAME).callMethod('ngDoCheck', []).toStmt());
}
if (lifecycleStmts.length > 0) {
stmts.push(new o.IfStmt(o.not(THROW_ON_CHANGE_VAR), lifecycleStmts));
}
stmts.push(new o.ReturnStatement(changedVar));
builder.methods.push(new o.ClassMethod(
'detectChangesInInputProps',
[
new o.FnParam(
VIEW_VAR.name, o.importType(resolveIdentifier(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),
],
stmts, o.BOOL_TYPE));
}
function addCheckInputMethod(input: string, builder: DirectiveWrapperBuilder) {
const field = createCheckBindingField(builder);
var onChangeStatements: o.Statement[] = [
o.THIS_EXPR.prop(CHANGED_FIELD_NAME).set(o.literal(true)).toStmt(),
o.THIS_EXPR.prop(CONTEXT_FIELD_NAME).prop(input).set(CURR_VALUE_VAR).toStmt(),
];
if (builder.genChanges) {
onChangeStatements.push(o.THIS_EXPR.prop(CHANGES_FIELD_NAME)
.key(o.literal(input))
.set(o.importExpr(resolveIdentifier(Identifiers.SimpleChange))
.instantiate([field.expression, CURR_VALUE_VAR]))
.toStmt());
}
var methodBody: o.Statement[] = createCheckBindingStmt(
{currValExpr: CURR_VALUE_VAR, forceUpdate: FORCE_UPDATE_VAR, stmts: []}, field.expression,
THROW_ON_CHANGE_VAR, onChangeStatements);
builder.methods.push(new o.ClassMethod(
`check_${input}`,
[
new o.FnParam(CURR_VALUE_VAR.name, o.DYNAMIC_TYPE),
new o.FnParam(THROW_ON_CHANGE_VAR.name, o.BOOL_TYPE),
new o.FnParam(FORCE_UPDATE_VAR.name, o.BOOL_TYPE),
],
methodBody));
}
function addDetectChangesInHostPropsMethod(
hostProps: BoundElementPropertyAst[], builder: DirectiveWrapperBuilder) {
const stmts: o.Statement[] = [];
const methodParams: o.FnParam[] = [
new o.FnParam(
VIEW_VAR.name, o.importType(resolveIdentifier(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),
];
hostProps.forEach((hostProp) => {
const field = createCheckBindingField(builder);
const evalResult = convertPropertyBinding(
builder, null, o.THIS_EXPR.prop(CONTEXT_FIELD_NAME), hostProp.value, field.bindingId);
if (!evalResult) {
return;
}
let securityContextExpr: o.ReadVarExpr;
if (hostProp.needsRuntimeSecurityContext) {
securityContextExpr = o.variable(`secCtx_${methodParams.length}`);
methodParams.push(new o.FnParam(
securityContextExpr.name, o.importType(resolveIdentifier(Identifiers.SecurityContext))));
}
stmts.push(...createCheckBindingStmt(
evalResult, field.expression, THROW_ON_CHANGE_VAR,
writeToRenderer(
VIEW_VAR, hostProp, RENDER_EL_VAR, evalResult.currValExpr,
builder.compilerConfig.logBindingUpdate, securityContextExpr)));
});
builder.methods.push(new o.ClassMethod('detectChangesInHostProps', methodParams, stmts));
}
class ParseResult {
constructor(
public hostProps: BoundElementPropertyAst[], public hostListeners: BoundEventAst[],
public errors: ParseError[]) {}
}
function parseHostBindings(
dirMeta: CompileDirectiveMetadata, exprParser: Parser,
schemaRegistry: ElementSchemaRegistry): ParseResult {
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 sourceFile = new ParseSourceFile('', sourceFileName);
const sourceSpan = new ParseSourceSpan(
new ParseLocation(sourceFile, null, null, null),
new ParseLocation(sourceFile, null, null, null));
const parsedHostProps = parser.createDirectiveHostPropertyAsts(dirMeta, sourceSpan);
const parsedHostListeners = parser.createDirectiveHostEventAsts(dirMeta, sourceSpan);
return new ParseResult(parsedHostProps, parsedHostListeners, errors);
}
function reportParseErrors(parseErrors: ParseError[], console: Console) {
const warnings = parseErrors.filter(error => error.level === ParseErrorLevel.WARNING);
const errors = parseErrors.filter(error => error.level === ParseErrorLevel.FATAL);
if (warnings.length > 0) {
this._console.warn(`Directive parse warnings:\n${warnings.join('\n')}`);
}
if (errors.length > 0) {
throw new Error(`Directive parse errors:\n${errors.join('\n')}`);
}
}

View File

@ -8,7 +8,7 @@
import {Injectable} from '@angular/core';
import * as chars from '../chars';
import {NumberWrapper, isPresent} from '../facade/lang';
import {NumberWrapper, StringJoiner, StringWrapper, isPresent} from '../facade/lang';
export enum TokenType {
Character,
@ -93,7 +93,7 @@ export class Token {
}
function newCharacterToken(index: number, code: number): Token {
return new Token(index, TokenType.Character, code, String.fromCharCode(code));
return new Token(index, TokenType.Character, code, StringWrapper.fromCharCode(code));
}
function newIdentifierToken(index: number, text: string): Token {
@ -133,7 +133,8 @@ class _Scanner {
}
advance() {
this.peek = ++this.index >= this.length ? chars.$EOF : this.input.charCodeAt(this.index);
this.peek =
++this.index >= this.length ? chars.$EOF : StringWrapper.charCodeAt(this.input, this.index);
}
scanToken(): Token {
@ -145,7 +146,7 @@ class _Scanner {
peek = chars.$EOF;
break;
} else {
peek = input.charCodeAt(index);
peek = StringWrapper.charCodeAt(input, index);
}
}
@ -186,16 +187,16 @@ class _Scanner {
case chars.$SLASH:
case chars.$PERCENT:
case chars.$CARET:
return this.scanOperator(start, String.fromCharCode(peek));
return this.scanOperator(start, StringWrapper.fromCharCode(peek));
case chars.$QUESTION:
return this.scanComplexOperator(start, '?', chars.$PERIOD, '.');
case chars.$LT:
case chars.$GT:
return this.scanComplexOperator(start, String.fromCharCode(peek), chars.$EQ, '=');
return this.scanComplexOperator(start, StringWrapper.fromCharCode(peek), chars.$EQ, '=');
case chars.$BANG:
case chars.$EQ:
return this.scanComplexOperator(
start, String.fromCharCode(peek), chars.$EQ, '=', chars.$EQ, '=');
start, StringWrapper.fromCharCode(peek), chars.$EQ, '=', chars.$EQ, '=');
case chars.$AMPERSAND:
return this.scanComplexOperator(start, '&', chars.$AMPERSAND, '&');
case chars.$BAR:
@ -206,7 +207,7 @@ class _Scanner {
}
this.advance();
return this.error(`Unexpected character [${String.fromCharCode(peek)}]`, 0);
return this.error(`Unexpected character [${StringWrapper.fromCharCode(peek)}]`, 0);
}
scanCharacter(start: number, code: number): Token {
@ -274,41 +275,42 @@ class _Scanner {
}
this.advance();
}
const str: string = this.input.substring(start, this.index);
const value: number = simple ? NumberWrapper.parseIntAutoRadix(str) : parseFloat(str);
var str: string = this.input.substring(start, this.index);
var value: number = simple ? NumberWrapper.parseIntAutoRadix(str) : parseFloat(str);
return newNumberToken(start, value);
}
scanString(): Token {
const start: number = this.index;
const quote: number = this.peek;
var start: number = this.index;
var quote: number = this.peek;
this.advance(); // Skip initial quote.
let buffer: string = '';
let marker: number = this.index;
let input: string = this.input;
var buffer: StringJoiner;
var marker: number = this.index;
var input: string = this.input;
while (this.peek != quote) {
if (this.peek == chars.$BACKSLASH) {
buffer += input.substring(marker, this.index);
if (buffer == null) buffer = new StringJoiner();
buffer.add(input.substring(marker, this.index));
this.advance();
let unescapedCode: number;
var unescapedCode: number;
if (this.peek == chars.$u) {
// 4 character hex code for unicode character.
const hex: string = input.substring(this.index + 1, this.index + 5);
var hex: string = input.substring(this.index + 1, this.index + 5);
try {
unescapedCode = NumberWrapper.parseInt(hex, 16);
} catch (e) {
return this.error(`Invalid unicode escape [\\u${hex}]`, 0);
}
for (let i: number = 0; i < 5; i++) {
for (var i: number = 0; i < 5; i++) {
this.advance();
}
} else {
unescapedCode = unescape(this.peek);
this.advance();
}
buffer += String.fromCharCode(unescapedCode);
buffer.add(StringWrapper.fromCharCode(unescapedCode));
marker = this.index;
} else if (this.peek == chars.$EOF) {
return this.error('Unterminated quote', 0);
@ -317,10 +319,16 @@ class _Scanner {
}
}
const last: string = input.substring(marker, this.index);
var last: string = input.substring(marker, this.index);
this.advance(); // Skip terminating quote.
return newStringToken(start, buffer + last);
// Compute the unescaped string value.
var unescaped: string = last;
if (buffer != null) {
buffer.add(last);
unescaped = buffer.toString();
}
return newStringToken(start, unescaped);
}
error(message: string, offset: number): Token {

View File

@ -9,7 +9,7 @@
import {Injectable} from '@angular/core';
import * as chars from '../chars';
import {escapeRegExp, isBlank, isPresent} from '../facade/lang';
import {StringWrapper, escapeRegExp, isBlank, isPresent} from '../facade/lang';
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../ml_parser/interpolation_config';
import {AST, ASTWithSource, AstVisitor, Binary, BindingPipe, Chain, Conditional, EmptyExpr, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, ParseSpan, ParserError, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead, TemplateBinding} from './ast';
@ -17,7 +17,7 @@ import {EOF, Lexer, Token, TokenType, isIdentifier, isQuote} from './lexer';
export class SplitInterpolation {
constructor(public strings: string[], public expressions: string[], public offsets: number[]) {}
constructor(public strings: string[], public expressions: string[]) {}
}
export class TemplateBindingParseResult {
@ -41,12 +41,8 @@ export class Parser {
input: string, location: any,
interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG): ASTWithSource {
this._checkNoInterpolation(input, location, interpolationConfig);
const sourceToLex = this._stripComments(input);
const tokens = this._lexer.tokenize(this._stripComments(input));
const ast = new _ParseAST(
input, location, tokens, sourceToLex.length, true, this.errors,
input.length - sourceToLex.length)
.parseChain();
const ast = new _ParseAST(input, location, tokens, true, this.errors).parseChain();
return new ASTWithSource(ast, input, location, this.errors);
}
@ -60,11 +56,10 @@ export class Parser {
parseSimpleBinding(
input: string, location: string,
interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG): ASTWithSource {
const ast = this._parseBindingAst(input, location, interpolationConfig);
const errors = SimpleExpressionChecker.check(ast);
if (errors.length > 0) {
var ast = this._parseBindingAst(input, location, interpolationConfig);
if (!SimpleExpressionChecker.check(ast)) {
this._reportError(
`Host binding expression cannot contain ${errors.join(' ')}`, input, location);
'Host binding expression can only contain field access and constants', input, location);
}
return new ASTWithSource(ast, input, location, this.errors);
}
@ -84,12 +79,8 @@ export class Parser {
}
this._checkNoInterpolation(input, location, interpolationConfig);
const sourceToLex = this._stripComments(input);
const tokens = this._lexer.tokenize(sourceToLex);
return new _ParseAST(
input, location, tokens, sourceToLex.length, false, this.errors,
input.length - sourceToLex.length)
.parseChain();
var tokens = this._lexer.tokenize(this._stripComments(input));
return new _ParseAST(input, location, tokens, false, this.errors).parseChain();
}
private _parseQuote(input: string, location: any): AST {
@ -104,8 +95,7 @@ export class Parser {
parseTemplateBindings(input: string, location: any): TemplateBindingParseResult {
var tokens = this._lexer.tokenize(input);
return new _ParseAST(input, location, tokens, input.length, false, this.errors, 0)
.parseTemplateBindings();
return new _ParseAST(input, location, tokens, false, this.errors).parseTemplateBindings();
}
parseInterpolation(
@ -117,13 +107,8 @@ export class Parser {
let expressions: AST[] = [];
for (let i = 0; i < split.expressions.length; ++i) {
const expressionText = split.expressions[i];
const sourceToLex = this._stripComments(expressionText);
const tokens = this._lexer.tokenize(this._stripComments(split.expressions[i]));
const ast = new _ParseAST(
input, location, tokens, sourceToLex.length, false, this.errors,
split.offsets[i] + (expressionText.length - sourceToLex.length))
.parseChain();
var tokens = this._lexer.tokenize(this._stripComments(split.expressions[i]));
var ast = new _ParseAST(input, location, tokens, false, this.errors).parseChain();
expressions.push(ast);
}
@ -137,25 +122,20 @@ export class Parser {
input: string, location: string,
interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG): SplitInterpolation {
const regexp = _createInterpolateRegExp(interpolationConfig);
const parts = input.split(regexp);
const parts = StringWrapper.split(input, regexp);
if (parts.length <= 1) {
return null;
}
const strings: string[] = [];
const expressions: string[] = [];
const offsets: number[] = [];
let offset = 0;
for (let i = 0; i < parts.length; i++) {
var part: string = parts[i];
if (i % 2 === 0) {
// fixed string
strings.push(part);
offset += part.length;
} else if (part.trim().length > 0) {
offset += interpolationConfig.start.length;
expressions.push(part);
offsets.push(offset);
offset += part.length + interpolationConfig.end.length;
} else {
this._reportError(
'Blank expressions are not allowed in interpolated strings', input,
@ -163,7 +143,7 @@ export class Parser {
location);
}
}
return new SplitInterpolation(strings, expressions, offsets);
return new SplitInterpolation(strings, expressions);
}
wrapLiteralPrimitive(input: string, location: any): ASTWithSource {
@ -180,8 +160,8 @@ export class Parser {
private _commentStart(input: string): number {
var outerQuote: number = null;
for (let i = 0; i < input.length - 1; i++) {
const char = input.charCodeAt(i);
const nextChar = input.charCodeAt(i + 1);
const char = StringWrapper.charCodeAt(input, i);
const nextChar = StringWrapper.charCodeAt(input, i + 1);
if (char === chars.$SLASH && nextChar == chars.$SLASH && isBlank(outerQuote)) return i;
@ -197,7 +177,7 @@ export class Parser {
private _checkNoInterpolation(
input: string, location: any, interpolationConfig: InterpolationConfig): void {
var regexp = _createInterpolateRegExp(interpolationConfig);
var parts = input.split(regexp);
var parts = StringWrapper.split(input, regexp);
if (parts.length > 1) {
this._reportError(
`Got interpolation (${interpolationConfig.start}${interpolationConfig.end}) where expression was expected`,
@ -228,9 +208,8 @@ export class _ParseAST {
index: number = 0;
constructor(
public input: string, public location: any, public tokens: Token[],
public inputLength: number, public parseAction: boolean, private errors: ParserError[],
private offset: number) {}
public input: string, public location: any, public tokens: any[], public parseAction: boolean,
private errors: ParserError[]) {}
peek(offset: number): Token {
var i = this.index + offset;
@ -240,8 +219,7 @@ export class _ParseAST {
get next(): Token { return this.peek(0); }
get inputIndex(): number {
return (this.index < this.tokens.length) ? this.next.index + this.offset :
this.inputLength + this.offset;
return (this.index < this.tokens.length) ? this.next.index : this.input.length;
}
span(start: number) { return new ParseSpan(start, this.inputIndex); }
@ -261,7 +239,7 @@ export class _ParseAST {
expectCharacter(code: number) {
if (this.optionalCharacter(code)) return;
this.error(`Missing expected ${String.fromCharCode(code)}`);
this.error(`Missing expected ${StringWrapper.fromCharCode(code)}`);
}
optionalOperator(op: string): boolean {
@ -333,7 +311,7 @@ export class _ParseAST {
while (this.optionalCharacter(chars.$COLON)) {
args.push(this.parseExpression());
}
result = new BindingPipe(this.span(result.span.start - this.offset), result, name, args);
result = new BindingPipe(this.span(result.span.start), result, name, args);
} while (this.optionalOperator('|'));
}
@ -752,51 +730,51 @@ export class _ParseAST {
}
class SimpleExpressionChecker implements AstVisitor {
static check(ast: AST): string[] {
static check(ast: AST): boolean {
var s = new SimpleExpressionChecker();
ast.visit(s);
return s.errors;
return s.simple;
}
errors: string[] = [];
simple = true;
visitImplicitReceiver(ast: ImplicitReceiver, context: any) {}
visitInterpolation(ast: Interpolation, context: any) {}
visitInterpolation(ast: Interpolation, context: any) { this.simple = false; }
visitLiteralPrimitive(ast: LiteralPrimitive, context: any) {}
visitPropertyRead(ast: PropertyRead, context: any) {}
visitPropertyWrite(ast: PropertyWrite, context: any) {}
visitPropertyWrite(ast: PropertyWrite, context: any) { this.simple = false; }
visitSafePropertyRead(ast: SafePropertyRead, context: any) {}
visitSafePropertyRead(ast: SafePropertyRead, context: any) { this.simple = false; }
visitMethodCall(ast: MethodCall, context: any) {}
visitMethodCall(ast: MethodCall, context: any) { this.simple = false; }
visitSafeMethodCall(ast: SafeMethodCall, context: any) {}
visitSafeMethodCall(ast: SafeMethodCall, context: any) { this.simple = false; }
visitFunctionCall(ast: FunctionCall, context: any) {}
visitFunctionCall(ast: FunctionCall, context: any) { this.simple = false; }
visitLiteralArray(ast: LiteralArray, context: any) { this.visitAll(ast.expressions); }
visitLiteralMap(ast: LiteralMap, context: any) { this.visitAll(ast.values); }
visitBinary(ast: Binary, context: any) {}
visitBinary(ast: Binary, context: any) { this.simple = false; }
visitPrefixNot(ast: PrefixNot, context: any) {}
visitPrefixNot(ast: PrefixNot, context: any) { this.simple = false; }
visitConditional(ast: Conditional, context: any) {}
visitConditional(ast: Conditional, context: any) { this.simple = false; }
visitPipe(ast: BindingPipe, context: any) { this.errors.push('pipes'); }
visitPipe(ast: BindingPipe, context: any) { this.simple = false; }
visitKeyedRead(ast: KeyedRead, context: any) {}
visitKeyedRead(ast: KeyedRead, context: any) { this.simple = false; }
visitKeyedWrite(ast: KeyedWrite, context: any) {}
visitKeyedWrite(ast: KeyedWrite, context: any) { this.simple = false; }
visitAll(asts: any[]): any[] { return asts.map(node => node.visit(this)); }
visitChain(ast: Chain, context: any) {}
visitChain(ast: Chain, context: any) { this.simple = false; }
visitQuote(ast: Quote, context: any) {}
visitQuote(ast: Quote, context: any) { this.simple = false; }
}

View File

@ -6,10 +6,11 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ANALYZE_FOR_ENTRY_COMPONENTS, AnimationTransitionEvent, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ElementRef, Injector, LOCALE_ID, NgModuleFactory, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TRANSLATIONS_FORMAT, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
import {ANALYZE_FOR_ENTRY_COMPONENTS, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ElementRef, Injector, LOCALE_ID as LOCALE_ID_, NgModuleFactory, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TRANSLATIONS_FORMAT as TRANSLATIONS_FORMAT_, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadata';
import {AnimationGroupPlayer, AnimationKeyframe, AnimationSequencePlayer, AnimationStyles, AnimationTransition, AppElement, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, DebugAppView, DebugContext, NgModuleInjector, NoOpAnimationPlayer, StaticNodeDebugInfo, TemplateRef_, UNINITIALIZED, ValueUnwrapper, ViewType, balanceAnimationKeyframes, clearStyles, collectAndResolveStyles, devModeEqual, prepareFinalAnimationStyles, reflector, registerModuleFactory, renderStyles, view_utils} from './private_import_core';
import {AnimationGroupPlayer, AnimationKeyframe, AnimationSequencePlayer, AnimationStyles, AppElement, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, DebugAppView, DebugContext, EMPTY_ARRAY, EMPTY_MAP, NgModuleInjector, NoOpAnimationPlayer, StaticNodeDebugInfo, TemplateRef_, UNINITIALIZED, ValueUnwrapper, ViewType, ViewUtils, balanceAnimationKeyframes, castByValue, checkBinding, clearStyles, collectAndResolveStyles, devModeEqual, flattenNestedViewRenderNodes, interpolate, prepareFinalAnimationStyles, pureProxy1, pureProxy10, pureProxy2, pureProxy3, pureProxy4, pureProxy5, pureProxy6, pureProxy7, pureProxy8, pureProxy9, reflector, registerModuleFactory, renderStyles} from './private_import_core';
import {assetUrl} from './util';
var APP_VIEW_MODULE_URL = assetUrl('core', 'linker/view');
var VIEW_UTILS_MODULE_URL = assetUrl('core', 'linker/view_utils');
@ -32,7 +33,7 @@ export class Identifiers {
static ViewUtils: IdentifierSpec = {
name: 'ViewUtils',
moduleUrl: assetUrl('core', 'linker/view_utils'),
runtime: view_utils.ViewUtils
runtime: ViewUtils
};
static AppView:
IdentifierSpec = {name: 'AppView', moduleUrl: APP_VIEW_MODULE_URL, runtime: AppView};
@ -160,57 +161,45 @@ export class Identifiers {
static checkBinding: IdentifierSpec = {
name: 'checkBinding',
moduleUrl: VIEW_UTILS_MODULE_URL,
runtime: view_utils.checkBinding
runtime: checkBinding
};
static flattenNestedViewRenderNodes: IdentifierSpec = {
name: 'flattenNestedViewRenderNodes',
moduleUrl: VIEW_UTILS_MODULE_URL,
runtime: view_utils.flattenNestedViewRenderNodes
runtime: flattenNestedViewRenderNodes
};
static devModeEqual:
IdentifierSpec = {name: 'devModeEqual', moduleUrl: CD_MODULE_URL, runtime: devModeEqual};
static interpolate: IdentifierSpec = {
name: 'interpolate',
moduleUrl: VIEW_UTILS_MODULE_URL,
runtime: view_utils.interpolate
runtime: interpolate
};
static castByValue: IdentifierSpec = {
name: 'castByValue',
moduleUrl: VIEW_UTILS_MODULE_URL,
runtime: view_utils.castByValue
runtime: castByValue
};
static EMPTY_ARRAY: IdentifierSpec = {
name: 'EMPTY_ARRAY',
moduleUrl: VIEW_UTILS_MODULE_URL,
runtime: view_utils.EMPTY_ARRAY
runtime: EMPTY_ARRAY
};
static EMPTY_MAP: IdentifierSpec = {
name: 'EMPTY_MAP',
moduleUrl: VIEW_UTILS_MODULE_URL,
runtime: view_utils.EMPTY_MAP
};
static createRenderElement: IdentifierSpec = {
name: 'createRenderElement',
moduleUrl: VIEW_UTILS_MODULE_URL,
runtime: view_utils.createRenderElement
};
static selectOrCreateRenderHostElement: IdentifierSpec = {
name: 'selectOrCreateRenderHostElement',
moduleUrl: VIEW_UTILS_MODULE_URL,
runtime: view_utils.selectOrCreateRenderHostElement
};
static pureProxies: IdentifierSpec[] = [
static EMPTY_MAP:
IdentifierSpec = {name: 'EMPTY_MAP', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: EMPTY_MAP};
static pureProxies = [
null,
{name: 'pureProxy1', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy1},
{name: 'pureProxy2', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy2},
{name: 'pureProxy3', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy3},
{name: 'pureProxy4', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy4},
{name: 'pureProxy5', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy5},
{name: 'pureProxy6', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy6},
{name: 'pureProxy7', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy7},
{name: 'pureProxy8', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy8},
{name: 'pureProxy9', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy9},
{name: 'pureProxy10', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy10},
{name: 'pureProxy1', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy1},
{name: 'pureProxy2', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy2},
{name: 'pureProxy3', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy3},
{name: 'pureProxy4', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy4},
{name: 'pureProxy5', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy5},
{name: 'pureProxy6', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy6},
{name: 'pureProxy7', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy7},
{name: 'pureProxy8', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy8},
{name: 'pureProxy9', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy9},
{name: 'pureProxy10', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy10},
];
static SecurityContext: IdentifierSpec = {
name: 'SecurityContext',
@ -270,57 +259,13 @@ export class Identifiers {
static LOCALE_ID: IdentifierSpec = {
name: 'LOCALE_ID',
moduleUrl: assetUrl('core', 'i18n/tokens'),
runtime: LOCALE_ID
runtime: LOCALE_ID_
};
static TRANSLATIONS_FORMAT: IdentifierSpec = {
name: 'TRANSLATIONS_FORMAT',
moduleUrl: assetUrl('core', 'i18n/tokens'),
runtime: TRANSLATIONS_FORMAT
runtime: TRANSLATIONS_FORMAT_
};
static setBindingDebugInfo: IdentifierSpec = {
name: 'setBindingDebugInfo',
moduleUrl: VIEW_UTILS_MODULE_URL,
runtime: view_utils.setBindingDebugInfo
};
static setBindingDebugInfoForChanges: IdentifierSpec = {
name: 'setBindingDebugInfoForChanges',
moduleUrl: VIEW_UTILS_MODULE_URL,
runtime: view_utils.setBindingDebugInfoForChanges
};
static AnimationTransition: IdentifierSpec = {
name: 'AnimationTransition',
moduleUrl: assetUrl('core', 'animation/animation_transition'),
runtime: AnimationTransition
};
// This is just the interface!
static InlineArray:
IdentifierSpec = {name: 'InlineArray', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: null};
static inlineArrays: IdentifierSpec[] = [
{name: 'InlineArray2', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.InlineArray2},
{name: 'InlineArray2', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.InlineArray2},
{name: 'InlineArray4', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.InlineArray4},
{name: 'InlineArray8', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.InlineArray8},
{name: 'InlineArray16', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.InlineArray16},
];
static EMPTY_INLINE_ARRAY: IdentifierSpec = {
name: 'EMPTY_INLINE_ARRAY',
moduleUrl: VIEW_UTILS_MODULE_URL,
runtime: view_utils.EMPTY_INLINE_ARRAY
};
static InlineArrayDynamic: IdentifierSpec = {
name: 'InlineArrayDynamic',
moduleUrl: VIEW_UTILS_MODULE_URL,
runtime: view_utils.InlineArrayDynamic
};
}
export function assetUrl(pkg: string, path: string = null, type: string = 'src'): string {
if (path == null) {
return `asset:@angular/lib/${pkg}/index`;
} else {
return `asset:@angular/lib/${pkg}/src/${path}`;
}
}
export function resolveIdentifier(identifier: IdentifierSpec) {

View File

@ -0,0 +1,20 @@
/**
* @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
*/
/**
* @module
* @description
* Starting point to import all compiler APIs.
*/
export {COMPILER_PROVIDERS, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileFactoryMetadata, CompileIdentifierMetadata, CompileMetadataWithIdentifier, CompilePipeMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata, CompilerConfig, DEFAULT_PACKAGE_URL_PROVIDER, DirectiveResolver, NgModuleResolver, OfflineCompiler, PipeResolver, RenderTypes, ResourceLoader, RuntimeCompiler, SourceModule, TEMPLATE_TRANSFORMS, UrlResolver, createOfflineCompileUrlResolver, platformCoreDynamic} from './compiler';
export {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from './ml_parser/interpolation_config';
export {ElementSchemaRegistry} from './schema/element_schema_registry';
export * from './i18n/index';
export * from './template_parser/template_ast';
export * from './private_export';

View File

@ -6,30 +6,35 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, DoCheck, OnChanges, OnDestroy, OnInit, Type} from '@angular/core';
import {MapWrapper} from './facade/collection';
import {LifecycleHooks, reflector} from './private_import_core';
const LIFECYCLE_INTERFACES: Map<any, Type<any>> = MapWrapper.createFromPairs([
[LifecycleHooks.OnInit, OnInit],
[LifecycleHooks.OnDestroy, OnDestroy],
[LifecycleHooks.DoCheck, DoCheck],
[LifecycleHooks.OnChanges, OnChanges],
[LifecycleHooks.AfterContentInit, AfterContentInit],
[LifecycleHooks.AfterContentChecked, AfterContentChecked],
[LifecycleHooks.AfterViewInit, AfterViewInit],
[LifecycleHooks.AfterViewChecked, AfterViewChecked],
]);
const LIFECYCLE_PROPS: Map<any, string> = MapWrapper.createFromPairs([
[LifecycleHooks.OnInit, 'ngOnInit'],
[LifecycleHooks.OnDestroy, 'ngOnDestroy'],
[LifecycleHooks.DoCheck, 'ngDoCheck'],
[LifecycleHooks.OnChanges, 'ngOnChanges'],
[LifecycleHooks.AfterContentInit, 'ngAfterContentInit'],
[LifecycleHooks.AfterContentChecked, 'ngAfterContentChecked'],
[LifecycleHooks.AfterViewInit, 'ngAfterViewInit'],
[LifecycleHooks.AfterViewChecked, 'ngAfterViewChecked'],
]);
export function hasLifecycleHook(hook: LifecycleHooks, token: any): boolean {
return reflector.hasLifecycleHook(token, getHookName(hook));
var lcInterface = LIFECYCLE_INTERFACES.get(hook);
var lcProp = LIFECYCLE_PROPS.get(hook);
return reflector.hasLifecycleHook(token, lcInterface, lcProp);
}
function getHookName(hook: LifecycleHooks): string {
switch (hook) {
case LifecycleHooks.OnInit:
return 'ngOnInit';
case LifecycleHooks.OnDestroy:
return 'ngOnDestroy';
case LifecycleHooks.DoCheck:
return 'ngDoCheck';
case LifecycleHooks.OnChanges:
return 'ngOnChanges';
case LifecycleHooks.AfterContentInit:
return 'ngAfterContentInit';
case LifecycleHooks.AfterContentChecked:
return 'ngAfterContentChecked';
case LifecycleHooks.AfterViewInit:
return 'ngAfterViewInit';
case LifecycleHooks.AfterViewChecked:
return 'ngAfterViewChecked';
}
}

View File

@ -11,7 +11,7 @@ import {AnimationAnimateMetadata, AnimationEntryMetadata, AnimationGroupMetadata
import {assertArrayOfStrings, assertInterpolationSymbols} from './assertions';
import * as cpl from './compile_metadata';
import {DirectiveResolver} from './directive_resolver';
import {isBlank, isPresent, stringify} from './facade/lang';
import {isBlank, isPresent, isString, stringify} from './facade/lang';
import {Identifiers, resolveIdentifierToken} from './identifiers';
import {hasLifecycleHook} from './lifecycle_reflector';
import {NgModuleResolver} from './ng_module_resolver';
@ -116,7 +116,8 @@ export class CompileMetadataResolver {
return null;
}
getDirectiveMetadata(directiveType: any, throwIfNotFound = true): cpl.CompileDirectiveMetadata {
getDirectiveMetadata(directiveType: Type<any>, throwIfNotFound = true):
cpl.CompileDirectiveMetadata {
directiveType = resolveForwardRef(directiveType);
let meta = this._directiveCache.get(directiveType);
if (!meta) {
@ -378,15 +379,15 @@ export class CompileMetadataResolver {
}
private _getTypeDescriptor(type: Type<any>): string {
if (this._directiveResolver.resolve(type, false)) {
if (this._directiveResolver.resolve(type, false) !== null) {
return 'directive';
}
if (this._pipeResolver.resolve(type, false)) {
if (this._pipeResolver.resolve(type, false) !== null) {
return 'pipe';
}
if (this._ngModuleResolver.resolve(type, false)) {
if (this._ngModuleResolver.resolve(type, false) !== null) {
return 'module';
}
@ -508,7 +509,7 @@ export class CompileMetadataResolver {
let isOptional = false;
let query: Query = null;
let viewQuery: Query = null;
let token: any = null;
var token: any = null;
if (Array.isArray(param)) {
param.forEach((paramEntry) => {
if (paramEntry instanceof Host) {
@ -568,7 +569,7 @@ export class CompileMetadataResolver {
getTokenMetadata(token: any): cpl.CompileTokenMetadata {
token = resolveForwardRef(token);
let compileToken: cpl.CompileTokenMetadata;
if (typeof token === 'string') {
if (isString(token)) {
compileToken = new cpl.CompileTokenMetadata({value: token});
} else {
compileToken = new cpl.CompileTokenMetadata({
@ -605,20 +606,19 @@ export class CompileMetadataResolver {
} else if (isValidType(provider)) {
compileProvider = this.getTypeMetadata(provider, staticTypeModuleUrl(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(', ');
let 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}]`);

View File

@ -34,9 +34,7 @@ export class ExpansionCase implements Node {
}
export class Attribute implements Node {
constructor(
public name: string, public value: string, public sourceSpan: ParseSourceSpan,
public valueSpan?: ParseSourceSpan) {}
constructor(public name: string, public value: string, public sourceSpan: ParseSourceSpan) {}
visit(visitor: Visitor, context: any): any { return visitor.visitAttribute(this, context); }
}
@ -54,10 +52,6 @@ export class Comment implements Node {
}
export interface Visitor {
// Returning a truthy value from `visit()` will prevent `visitAll()` from the call to the typed
// method and result returned will become the result included in `visitAll()`s result array.
visit?(node: Node, context: any): any;
visitElement(element: Element, context: any): any;
visitAttribute(attribute: Attribute, context: any): any;
visitText(text: Text, context: any): any;
@ -68,12 +62,8 @@ export interface Visitor {
export function visitAll(visitor: Visitor, nodes: Node[], context: any = null): any[] {
let result: any[] = [];
let visit = visitor.visit ?
(ast: Node) => visitor.visit(ast, context) || ast.visit(visitor, context) :
(ast: Node) => ast.visit(visitor, context);
nodes.forEach(ast => {
const astResult = visit(ast);
const astResult = ast.visit(visitor, context);
if (astResult) {
result.push(astResult);
}

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ListWrapper} from '../facade/collection';
import {isBlank, isPresent} from '../facade/lang';
import {ParseError, ParseSourceSpan} from '../parse_util';
@ -230,7 +231,7 @@ class _TreeBuilder {
private _closeVoidElement(): void {
if (this._elementStack.length > 0) {
const el = this._elementStack[this._elementStack.length - 1];
const el = ListWrapper.last(this._elementStack);
if (this.getTagDefinition(el.name).isVoid) {
this._elementStack.pop();
@ -274,7 +275,7 @@ class _TreeBuilder {
private _pushElement(el: html.Element) {
if (this._elementStack.length > 0) {
const parentEl = this._elementStack[this._elementStack.length - 1];
const parentEl = ListWrapper.last(this._elementStack);
if (this.getTagDefinition(parentEl.name).isClosedByChild(el.name)) {
this._elementStack.pop();
}
@ -315,7 +316,7 @@ class _TreeBuilder {
for (let stackIndex = this._elementStack.length - 1; stackIndex >= 0; stackIndex--) {
const el = this._elementStack[stackIndex];
if (el.name == fullName) {
this._elementStack.splice(stackIndex, this._elementStack.length - stackIndex);
ListWrapper.splice(this._elementStack, stackIndex, this._elementStack.length - stackIndex);
return true;
}
@ -330,19 +331,16 @@ class _TreeBuilder {
const fullName = mergeNsAndName(attrName.parts[0], attrName.parts[1]);
let end = attrName.sourceSpan.end;
let value = '';
let valueSpan: ParseSourceSpan;
if (this._peek.type === lex.TokenType.ATTR_VALUE) {
const valueToken = this._advance();
value = valueToken.parts[0];
end = valueToken.sourceSpan.end;
valueSpan = valueToken.sourceSpan;
}
return new html.Attribute(
fullName, value, new ParseSourceSpan(attrName.sourceSpan.start, end), valueSpan);
return new html.Attribute(fullName, value, new ParseSourceSpan(attrName.sourceSpan.start, end));
}
private _getParentElement(): html.Element {
return this._elementStack.length > 0 ? this._elementStack[this._elementStack.length - 1] : null;
return this._elementStack.length > 0 ? ListWrapper.last(this._elementStack) : null;
}
/**
@ -360,7 +358,7 @@ class _TreeBuilder {
container = this._elementStack[i];
}
return {parent: this._elementStack[this._elementStack.length - 1], container};
return {parent: ListWrapper.last(this._elementStack), container};
}
private _addToParent(node: html.Node) {

View File

@ -9,16 +9,15 @@
import {Injectable} from '@angular/core';
import {CompileDiDependencyMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileProviderMetadata, CompileTokenMetadata} from './compile_metadata';
import {createDiTokenExpression} from './compiler_util/identifier_util';
import {isPresent} from './facade/lang';
import {Identifiers, resolveIdentifier, resolveIdentifierToken} from './identifiers';
import {ClassBuilder, createClassStmt} from './output/class_builder';
import * as o from './output/output_ast';
import {convertValueToOutputAst} from './output/value_util';
import {ParseLocation, ParseSourceFile, ParseSourceSpan} from './parse_util';
import {LifecycleHooks} from './private_import_core';
import {NgModuleProviderAnalyzer} from './provider_analyzer';
import {ProviderAst} from './template_parser/template_ast';
import {createDiTokenExpression} from './util';
export class ComponentFactoryDependency {
constructor(
@ -83,15 +82,13 @@ export class NgModuleCompiler {
}
}
class _InjectorBuilder implements ClassBuilder {
fields: o.ClassField[] = [];
getters: o.ClassGetter[] = [];
methods: o.ClassMethod[] = [];
ctorStmts: o.Statement[] = [];
class _InjectorBuilder {
private _tokens: CompileTokenMetadata[] = [];
private _instances = new Map<any, o.Expression>();
private _fields: o.ClassField[] = [];
private _createStmts: o.Statement[] = [];
private _destroyStmts: o.Statement[] = [];
private _getters: o.ClassGetter[] = [];
constructor(
private _ngModuleMeta: CompileNgModuleMetadata,
@ -139,23 +136,26 @@ class _InjectorBuilder implements ClassBuilder {
),
];
var parentArgs = [
o.variable(InjectorProps.parent.name),
o.literalArr(
this._entryComponentFactories.map((componentFactory) => o.importExpr(componentFactory))),
o.literalArr(this._bootstrapComponentFactories.map(
(componentFactory) => o.importExpr(componentFactory)))
];
var ctor = new o.ClassMethod(
null,
[new o.FnParam(
InjectorProps.parent.name, o.importType(resolveIdentifier(Identifiers.Injector)))],
[o.SUPER_EXPR
.callFn([
o.variable(InjectorProps.parent.name),
o.literalArr(this._entryComponentFactories.map(
(componentFactory) => o.importExpr(componentFactory))),
o.literalArr(this._bootstrapComponentFactories.map(
(componentFactory) => o.importExpr(componentFactory)))
])
.toStmt()]);
var injClassName = `${this._ngModuleMeta.type.name}Injector`;
return createClassStmt({
name: injClassName,
ctorParams: [new o.FnParam(
InjectorProps.parent.name, o.importType(resolveIdentifier(Identifiers.Injector)))],
parent: o.importExpr(
resolveIdentifier(Identifiers.NgModuleInjector), [o.importType(this._ngModuleMeta.type)]),
parentArgs: parentArgs,
builders: [{methods}, this]
});
return new o.ClassStmt(
injClassName, o.importExpr(
resolveIdentifier(Identifiers.NgModuleInjector),
[o.importType(this._ngModuleMeta.type)]),
this._fields, this._getters, ctor, methods);
}
private _getProviderValue(provider: CompileProviderMetadata): o.Expression {
@ -163,11 +163,11 @@ class _InjectorBuilder implements ClassBuilder {
if (isPresent(provider.useExisting)) {
result = this._getDependency(new CompileDiDependencyMetadata({token: provider.useExisting}));
} else if (isPresent(provider.useFactory)) {
var deps = provider.deps || provider.useFactory.diDeps;
var deps = isPresent(provider.deps) ? provider.deps : provider.useFactory.diDeps;
var depsExpr = deps.map((dep) => this._getDependency(dep));
result = o.importExpr(provider.useFactory).callFn(depsExpr);
} else if (isPresent(provider.useClass)) {
var deps = provider.deps || provider.useClass.diDeps;
var deps = isPresent(provider.deps) ? provider.deps : provider.useClass.diDeps;
var depsExpr = deps.map((dep) => this._getDependency(dep));
result =
o.importExpr(provider.useClass).instantiate(depsExpr, o.importType(provider.useClass));
@ -194,11 +194,11 @@ class _InjectorBuilder implements ClassBuilder {
type = o.DYNAMIC_TYPE;
}
if (isEager) {
this.fields.push(new o.ClassField(propName, type));
this._fields.push(new o.ClassField(propName, type));
this._createStmts.push(o.THIS_EXPR.prop(propName).set(resolvedProviderValueExpr).toStmt());
} else {
var internalField = `_${propName}`;
this.fields.push(new o.ClassField(internalField, type));
this._fields.push(new o.ClassField(internalField, type));
// Note: Equals is important for JS so that it also checks the undefined case!
var getterStmts = [
new o.IfStmt(
@ -206,7 +206,7 @@ class _InjectorBuilder implements ClassBuilder {
[o.THIS_EXPR.prop(internalField).set(resolvedProviderValueExpr).toStmt()]),
new o.ReturnStatement(o.THIS_EXPR.prop(internalField))
];
this.getters.push(new o.ClassGetter(propName, getterStmts, type));
this._getters.push(new o.ClassGetter(propName, getterStmts, type));
}
return o.THIS_EXPR.prop(propName);
}

View File

@ -12,8 +12,6 @@ import {AnimationCompiler} from './animation/animation_compiler';
import {AnimationParser} from './animation/animation_parser';
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeMetadata, CompileProviderMetadata, StaticSymbol, createHostComponentMeta} from './compile_metadata';
import {DirectiveNormalizer} from './directive_normalizer';
import {DirectiveWrapperCompileResult, DirectiveWrapperCompiler} from './directive_wrapper_compiler';
import {ListWrapper, MapWrapper} from './facade/collection';
import {Identifiers, resolveIdentifier, resolveIdentifierToken} from './identifiers';
import {CompileMetadataResolver} from './metadata_resolver';
import {NgModuleCompiler} from './ng_module_compiler';
@ -21,91 +19,14 @@ import {OutputEmitter} from './output/abstract_emitter';
import * as o from './output/output_ast';
import {CompiledStylesheet, StyleCompiler} from './style_compiler';
import {TemplateParser} from './template_parser/template_parser';
import {ComponentFactoryDependency, DirectiveWrapperDependency, ViewCompileResult, ViewCompiler, ViewFactoryDependency} from './view_compiler/view_compiler';
import {ComponentFactoryDependency, ViewCompileResult, ViewCompiler, ViewFactoryDependency} from './view_compiler/view_compiler';
export class SourceModule {
constructor(public fileUrl: string, public moduleUrl: string, public source: string) {}
constructor(public moduleUrl: string, public source: string) {}
}
// Returns all the source files and a mapping from modules to directives
export function analyzeNgModules(
programStaticSymbols: StaticSymbol[], options: {transitiveModules: boolean},
metadataResolver: CompileMetadataResolver): {
ngModuleByPipeOrDirective: Map<StaticSymbol, CompileNgModuleMetadata>,
files: Array<{srcUrl: string, directives: StaticSymbol[], ngModules: StaticSymbol[]}>
} {
const {
ngModules: programNgModules,
pipesAndDirectives: programPipesOrDirectives,
} = _extractModulesAndPipesOrDirectives(programStaticSymbols, metadataResolver);
const moduleMetasByRef = new Map<any, CompileNgModuleMetadata>();
programNgModules.forEach(modMeta => {
if (options.transitiveModules) {
// For every input modules add the list of transitively included modules
modMeta.transitiveModule.modules.forEach(
modMeta => { moduleMetasByRef.set(modMeta.type.reference, modMeta); });
} else {
moduleMetasByRef.set(modMeta.type.reference, modMeta);
}
});
const ngModuleMetas = MapWrapper.values(moduleMetasByRef);
const ngModuleByPipeOrDirective = new Map<StaticSymbol, CompileNgModuleMetadata>();
const ngModulesByFile = new Map<string, StaticSymbol[]>();
const ngDirectivesByFile = new Map<string, StaticSymbol[]>();
const filePaths = new Set<string>();
// Looping over all modules to construct:
// - a map from file to modules `ngModulesByFile`,
// - a map from file to directives `ngDirectivesByFile`,
// - a map from directive/pipe to module `ngModuleByPipeOrDirective`.
ngModuleMetas.forEach((ngModuleMeta) => {
const srcFileUrl = ngModuleMeta.type.reference.filePath;
filePaths.add(srcFileUrl);
ngModulesByFile.set(
srcFileUrl, (ngModulesByFile.get(srcFileUrl) || []).concat(ngModuleMeta.type.reference));
ngModuleMeta.declaredDirectives.forEach((dirMeta: CompileDirectiveMetadata) => {
const fileUrl = dirMeta.type.reference.filePath;
filePaths.add(fileUrl);
ngDirectivesByFile.set(
fileUrl, (ngDirectivesByFile.get(fileUrl) || []).concat(dirMeta.type.reference));
ngModuleByPipeOrDirective.set(dirMeta.type.reference, ngModuleMeta);
});
ngModuleMeta.declaredPipes.forEach((pipeMeta: CompilePipeMetadata) => {
const fileUrl = pipeMeta.type.reference.filePath;
filePaths.add(fileUrl);
ngModuleByPipeOrDirective.set(pipeMeta.type.reference, ngModuleMeta);
});
});
// Throw an error if any of the program pipe or directives is not declared by a module
const symbolsMissingModule =
programPipesOrDirectives.filter(s => !ngModuleByPipeOrDirective.has(s));
if (symbolsMissingModule.length) {
const messages = symbolsMissingModule.map(
s => `Cannot determine the module for class ${s.name} in ${s.filePath}!`);
throw new Error(messages.join('\n'));
}
const files: {srcUrl: string, directives: StaticSymbol[], ngModules: StaticSymbol[]}[] = [];
filePaths.forEach((srcUrl) => {
const directives = ngDirectivesByFile.get(srcUrl) || [];
const ngModules = ngModulesByFile.get(srcUrl) || [];
files.push({srcUrl, directives, ngModules});
});
return {
// map directive/pipe to module
ngModuleByPipeOrDirective,
// list modules and directives for every source file
files,
};
export class NgModulesSummary {
constructor(public ngModuleByComponent: Map<StaticSymbol, CompileNgModuleMetadata>) {}
}
export class OfflineCompiler {
@ -116,32 +37,32 @@ export class OfflineCompiler {
private _metadataResolver: CompileMetadataResolver,
private _directiveNormalizer: DirectiveNormalizer, private _templateParser: TemplateParser,
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
private _dirWrapperCompiler: DirectiveWrapperCompiler,
private _ngModuleCompiler: NgModuleCompiler, private _outputEmitter: OutputEmitter,
private _localeId: string, private _translationFormat: string) {}
analyzeModules(ngModules: StaticSymbol[]): NgModulesSummary {
const ngModuleByComponent = new Map<StaticSymbol, CompileNgModuleMetadata>();
ngModules.forEach((ngModule) => {
const ngModuleMeta = this._metadataResolver.getNgModuleMetadata(<any>ngModule);
ngModuleMeta.declaredDirectives.forEach((dirMeta) => {
if (dirMeta.isComponent) {
ngModuleByComponent.set(dirMeta.type.reference, ngModuleMeta);
}
});
});
return new NgModulesSummary(ngModuleByComponent);
}
clearCache() {
this._directiveNormalizer.clearCache();
this._metadataResolver.clearCache();
}
compileModules(staticSymbols: StaticSymbol[], options: {transitiveModules: boolean}):
Promise<SourceModule[]> {
const {ngModuleByPipeOrDirective, files} =
analyzeNgModules(staticSymbols, options, this._metadataResolver);
const sourceModules = files.map(
file => this._compileSrcFile(
file.srcUrl, ngModuleByPipeOrDirective, file.directives, file.ngModules));
return Promise.all(sourceModules)
.then((modules: SourceModule[][]) => ListWrapper.flatten(modules));
}
private _compileSrcFile(
srcFileUrl: string, ngModuleByPipeOrDirective: Map<StaticSymbol, CompileNgModuleMetadata>,
directives: StaticSymbol[], ngModules: StaticSymbol[]): Promise<SourceModule[]> {
const fileSuffix = _splitTypescriptSuffix(srcFileUrl)[1];
compile(
moduleUrl: string, ngModulesSummary: NgModulesSummary, components: StaticSymbol[],
ngModules: StaticSymbol[]): Promise<SourceModule[]> {
const fileSuffix = _splitTypescriptSuffix(moduleUrl)[1];
const statements: o.Statement[] = [];
const exportedVars: string[] = [];
const outputSourceModules: SourceModule[] = [];
@ -150,21 +71,13 @@ export class OfflineCompiler {
exportedVars.push(
...ngModules.map((ngModuleType) => this._compileModule(ngModuleType, statements)));
// compile directive wrappers
exportedVars.push(...directives.map(
(directiveType) => this._compileDirectiveWrapper(directiveType, statements)));
// compile components
return Promise
.all(directives.map((dirType) => {
const compMeta = this._metadataResolver.getDirectiveMetadata(<any>dirType);
if (!compMeta.isComponent) {
return Promise.resolve(null);
}
const ngModule = ngModuleByPipeOrDirective.get(dirType);
.all(components.map((compType) => {
const compMeta = this._metadataResolver.getDirectiveMetadata(<any>compType);
const ngModule = ngModulesSummary.ngModuleByComponent.get(compType);
if (!ngModule) {
throw new Error(
`Internal Error: cannot determine the module for component ${compMeta.type.name}!`);
throw new Error(`Cannot determine the module for component ${compMeta.type.name}!`);
}
return Promise
@ -177,8 +90,7 @@ export class OfflineCompiler {
// compile styles
const stylesCompileResults = this._styleCompiler.compileComponent(compMeta);
stylesCompileResults.externalStylesheets.forEach((compiledStyleSheet) => {
outputSourceModules.push(
this._codgenStyles(srcFileUrl, compiledStyleSheet, fileSuffix));
outputSourceModules.push(this._codgenStyles(compiledStyleSheet, fileSuffix));
});
// compile components
@ -191,9 +103,8 @@ export class OfflineCompiler {
}))
.then(() => {
if (statements.length > 0) {
const srcModule = this._codegenSourceModule(
srcFileUrl, _ngfactoryModuleUrl(srcFileUrl), statements, exportedVars);
outputSourceModules.unshift(srcModule);
outputSourceModules.unshift(this._codegenSourceModule(
_ngfactoryModuleUrl(moduleUrl), statements, exportedVars));
}
return outputSourceModules;
});
@ -228,15 +139,6 @@ export class OfflineCompiler {
return appCompileResult.ngModuleFactoryVar;
}
private _compileDirectiveWrapper(directiveType: StaticSymbol, targetStatements: o.Statement[]):
string {
const dirMeta = this._metadataResolver.getDirectiveMetadata(directiveType);
const dirCompileResult = this._dirWrapperCompiler.compile(dirMeta);
targetStatements.push(...dirCompileResult.statements);
return dirCompileResult.dirWrapperClassVar;
}
private _compileComponentFactory(
compMeta: CompileDirectiveMetadata, fileSuffix: string,
targetStatements: o.Statement[]): string {
@ -282,21 +184,18 @@ export class OfflineCompiler {
return viewResult.viewFactoryVar;
}
private _codgenStyles(
fileUrl: string, stylesCompileResult: CompiledStylesheet, fileSuffix: string): SourceModule {
private _codgenStyles(stylesCompileResult: CompiledStylesheet, fileSuffix: string): SourceModule {
_resolveStyleStatements(stylesCompileResult, fileSuffix);
return this._codegenSourceModule(
fileUrl, _stylesModuleUrl(
stylesCompileResult.meta.moduleUrl, stylesCompileResult.isShimmed, fileSuffix),
_stylesModuleUrl(
stylesCompileResult.meta.moduleUrl, stylesCompileResult.isShimmed, fileSuffix),
stylesCompileResult.statements, [stylesCompileResult.stylesVar]);
}
private _codegenSourceModule(
fileUrl: string, moduleUrl: string, statements: o.Statement[],
exportedVars: string[]): SourceModule {
moduleUrl: string, statements: o.Statement[], exportedVars: string[]): SourceModule {
return new SourceModule(
fileUrl, moduleUrl,
this._outputEmitter.emitStatements(moduleUrl, statements, exportedVars));
moduleUrl, this._outputEmitter.emitStatements(moduleUrl, statements, exportedVars));
}
}
@ -309,9 +208,6 @@ function _resolveViewStatements(compileResult: ViewCompileResult): o.Statement[]
const cfd = <ComponentFactoryDependency>dep;
cfd.placeholder.name = _componentFactoryName(cfd.comp);
cfd.placeholder.moduleUrl = _ngfactoryModuleUrl(cfd.comp.moduleUrl);
} else if (dep instanceof DirectiveWrapperDependency) {
const dwd = <DirectiveWrapperDependency>dep;
dwd.placeholder.moduleUrl = _ngfactoryModuleUrl(dwd.dir.moduleUrl);
}
});
return compileResult.statements;
@ -326,8 +222,8 @@ function _resolveStyleStatements(
return compileResult.statements;
}
function _ngfactoryModuleUrl(dirUrl: string): string {
const urlWithSuffix = _splitTypescriptSuffix(dirUrl);
function _ngfactoryModuleUrl(compUrl: string): string {
const urlWithSuffix = _splitTypescriptSuffix(compUrl);
return `${urlWithSuffix[0]}.ngfactory${urlWithSuffix[1]}`;
}
@ -358,28 +254,3 @@ function _splitTypescriptSuffix(path: string): string[] {
return [path, ''];
}
// Group the symbols by types:
// - NgModules,
// - Pipes and Directives.
function _extractModulesAndPipesOrDirectives(
programStaticSymbols: StaticSymbol[], metadataResolver: CompileMetadataResolver) {
const ngModules: CompileNgModuleMetadata[] = [];
const pipesAndDirectives: StaticSymbol[] = [];
programStaticSymbols.forEach(staticSymbol => {
const ngModule = metadataResolver.getNgModuleMetadata(staticSymbol, false);
const directive = metadataResolver.getDirectiveMetadata(staticSymbol, false);
const pipe = metadataResolver.getPipeMetadata(<any>staticSymbol, false);
if (ngModule) {
ngModules.push(ngModule);
} else if (directive) {
pipesAndDirectives.push(staticSymbol);
} else if (pipe) {
pipesAndDirectives.push(staticSymbol);
}
});
return {ngModules, pipesAndDirectives};
}

View File

@ -6,14 +6,14 @@
* found in the LICENSE file at https://angular.io/license
*/
import {isBlank, isPresent} from '../facade/lang';
import {StringWrapper, isBlank, isPresent, isString} from '../facade/lang';
import * as o from './output_ast';
const _SINGLE_QUOTE_ESCAPE_STRING_RE = /'|\\|\n|\r|\$/g;
const _LEGAL_IDENTIFIER_RE = /^[$A-Z_][0-9A-Z_$]*$/i;
export const CATCH_ERROR_VAR = o.variable('error');
export const CATCH_STACK_VAR = o.variable('stack');
var _SINGLE_QUOTE_ESCAPE_STRING_RE = /'|\\|\n|\r|\$/g;
var _LEGAL_IDENTIFIER_RE = /^[$A-Z_][0-9A-Z_$]*$/i;
export var CATCH_ERROR_VAR = o.variable('error');
export var CATCH_STACK_VAR = o.variable('stack');
export abstract class OutputEmitter {
abstract emitStatements(moduleUrl: string, stmts: o.Statement[], exportedVars: string[]): string;
@ -253,7 +253,7 @@ export abstract class AbstractEmitterVisitor implements o.StatementVisitor, o.Ex
visitLiteralExpr(ast: o.LiteralExpr, ctx: EmitterVisitorContext, absentValue: string = 'null'):
any {
var value = ast.value;
if (typeof value === 'string') {
if (isString(value)) {
ctx.print(escapeIdentifier(value, this._escapeDollarInStrings));
} else if (isBlank(value)) {
ctx.print(absentValue);
@ -368,7 +368,7 @@ export abstract class AbstractEmitterVisitor implements o.StatementVisitor, o.Ex
var useNewLine = ast.entries.length > 1;
ctx.print(`{`, useNewLine);
ctx.incIndent();
this.visitAllObjects(entry => {
this.visitAllObjects((entry: any /** TODO #9100 */) => {
ctx.print(`${escapeIdentifier(entry[0], this._escapeDollarInStrings, false)}: `);
entry[1].visitExpression(this, ctx);
}, ast.entries, ctx, ',', useNewLine);
@ -381,11 +381,12 @@ export abstract class AbstractEmitterVisitor implements o.StatementVisitor, o.Ex
expressions: o.Expression[], ctx: EmitterVisitorContext, separator: string,
newLine: boolean = false): void {
this.visitAllObjects(
expr => expr.visitExpression(this, ctx), expressions, ctx, separator, newLine);
(expr: any /** TODO #9100 */) => expr.visitExpression(this, ctx), expressions, ctx,
separator, newLine);
}
visitAllObjects<T>(
handler: (t: T) => void, expressions: T[], ctx: EmitterVisitorContext, separator: string,
visitAllObjects(
handler: Function, expressions: any, ctx: EmitterVisitorContext, separator: string,
newLine: boolean = false): void {
for (var i = 0; i < expressions.length; i++) {
if (i > 0) {
@ -408,17 +409,18 @@ export function escapeIdentifier(
if (isBlank(input)) {
return null;
}
var body = input.replace(_SINGLE_QUOTE_ESCAPE_STRING_RE, (...match: string[]) => {
if (match[0] == '$') {
return escapeDollar ? '\\$' : '$';
} else if (match[0] == '\n') {
return '\\n';
} else if (match[0] == '\r') {
return '\\r';
} else {
return `\\${match[0]}`;
}
});
var body = StringWrapper.replaceAllMapped(
input, _SINGLE_QUOTE_ESCAPE_STRING_RE, (match: any /** TODO #9100 */) => {
if (match[0] == '$') {
return escapeDollar ? '\\$' : '$';
} else if (match[0] == '\n') {
return '\\n';
} else if (match[0] == '\r') {
return '\\r';
} else {
return `\\${match[0]}`;
}
});
let requiresQuotes = alwaysQuote || !_LEGAL_IDENTIFIER_RE.test(body);
return requiresQuotes ? `'${body}'` : body;
}

View File

@ -144,11 +144,11 @@ export abstract class AbstractJsEmitterVisitor extends AbstractEmitterVisitor {
}
private _visitParams(params: o.FnParam[], ctx: EmitterVisitorContext): void {
this.visitAllObjects(param => ctx.print(param.name), params, ctx, ',');
this.visitAllObjects((param: any /** TODO #9100 */) => ctx.print(param.name), params, ctx, ',');
}
getBuiltinMethodName(method: o.BuiltinMethod): string {
var name: string;
var name: any /** TODO #9100 */;
switch (method) {
case o.BuiltinMethod.ConcatArray:
name = 'concat';

View File

@ -1,60 +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 * as o from './output_ast';
/**
* Create a new class stmts based on the given data.
*/
export function createClassStmt(config: {
name: string,
parent?: o.Expression,
parentArgs?: o.Expression[],
ctorParams?: o.FnParam[],
builders: ClassBuilderPart | ClassBuilderPart[], modifiers?: o.StmtModifier[]
}): o.ClassStmt {
const parentArgs = config.parentArgs || [];
const superCtorStmts = config.parent ? [o.SUPER_EXPR.callFn(parentArgs).toStmt()] : [];
const builder =
concatClassBuilderParts(Array.isArray(config.builders) ? config.builders : [config.builders]);
const ctor =
new o.ClassMethod(null, config.ctorParams || [], superCtorStmts.concat(builder.ctorStmts));
return new o.ClassStmt(
config.name, config.parent, builder.fields, builder.getters, ctor, builder.methods,
config.modifiers || []);
}
function concatClassBuilderParts(builders: ClassBuilderPart[]) {
return {
fields: [].concat(...builders.map(builder => builder.fields || [])),
methods: [].concat(...builders.map(builder => builder.methods || [])),
getters: [].concat(...builders.map(builder => builder.getters || [])),
ctorStmts: [].concat(...builders.map(builder => builder.ctorStmts || [])),
};
}
/**
* Collects data for a generated class.
*/
export interface ClassBuilderPart {
fields?: o.ClassField[];
methods?: o.ClassMethod[];
getters?: o.ClassGetter[];
ctorStmts?: o.Statement[];
}
/**
* Collects data for a generated class.
*/
export interface ClassBuilder {
fields: o.ClassField[];
methods: o.ClassMethod[];
getters: o.ClassGetter[];
ctorStmts: o.Statement[];
}

View File

@ -20,7 +20,7 @@ export class JavaScriptEmitter implements OutputEmitter {
var converter = new JsEmitterVisitor(moduleUrl);
var ctx = EmitterVisitorContext.createRoot(exportedVars);
converter.visitAllStatements(stmts, ctx);
var srcParts: string[] = [];
var srcParts: any[] /** TODO #9100 */ = [];
converter.importsWithPrefixes.forEach((prefix, importedModuleUrl) => {
// Note: can't write the real word for import as it screws up system.js auto detection...
srcParts.push(

View File

@ -8,7 +8,9 @@
import {CompileIdentifierMetadata} from '../compile_metadata';
import {isPresent} from '../facade/lang';
import {isPresent, isString} from '../facade/lang';
//// Types
export enum TypeModifier {
@ -194,7 +196,7 @@ export class ReadVarExpr extends Expression {
constructor(name: string|BuiltinVar, type: Type = null) {
super(type);
if (typeof name === 'string') {
if (isString(name)) {
this.name = name;
this.builtin = null;
} else {
@ -213,7 +215,7 @@ export class ReadVarExpr extends Expression {
export class WriteVarExpr extends Expression {
public value: Expression;
constructor(public name: string, value: Expression, type: Type = null) {
super(type || value.type);
super(isPresent(type) ? type : value.type);
this.value = value;
}
@ -231,7 +233,7 @@ export class WriteKeyExpr extends Expression {
public value: Expression;
constructor(
public receiver: Expression, public index: Expression, value: Expression, type: Type = null) {
super(type || value.type);
super(isPresent(type) ? type : value.type);
this.value = value;
}
visitExpression(visitor: ExpressionVisitor, context: any): any {
@ -244,7 +246,7 @@ export class WritePropExpr extends Expression {
public value: Expression;
constructor(
public receiver: Expression, public name: string, value: Expression, type: Type = null) {
super(type || value.type);
super(isPresent(type) ? type : value.type);
this.value = value;
}
visitExpression(visitor: ExpressionVisitor, context: any): any {
@ -265,7 +267,7 @@ export class InvokeMethodExpr extends Expression {
public receiver: Expression, method: string|BuiltinMethod, public args: Expression[],
type: Type = null) {
super(type);
if (typeof method === 'string') {
if (isString(method)) {
this.name = method;
this.builtin = null;
} else {
@ -320,7 +322,7 @@ export class ConditionalExpr extends Expression {
constructor(
public condition: Expression, trueCase: Expression, public falseCase: Expression = null,
type: Type = null) {
super(type || trueCase.type);
super(isPresent(type) ? type : trueCase.type);
this.trueCase = trueCase;
}
visitExpression(visitor: ExpressionVisitor, context: any): any {
@ -367,7 +369,7 @@ export class BinaryOperatorExpr extends Expression {
public lhs: Expression;
constructor(
public operator: BinaryOperator, lhs: Expression, public rhs: Expression, type: Type = null) {
super(type || lhs.type);
super(isPresent(type) ? type : lhs.type);
this.lhs = lhs;
}
visitExpression(visitor: ExpressionVisitor, context: any): any {
@ -414,7 +416,7 @@ export class LiteralArrayExpr extends Expression {
export class LiteralMapExpr extends Expression {
public valueType: Type = null;
constructor(public entries: [string, Expression][], type: MapType = null) {
constructor(public entries: Array<Array<string|Expression>>, type: MapType = null) {
super(type);
if (isPresent(type)) {
this.valueType = type.valueType;
@ -477,7 +479,7 @@ export class DeclareVarStmt extends Statement {
public name: string, public value: Expression, type: Type = null,
modifiers: StmtModifier[] = null) {
super(modifiers);
this.type = type || value.type;
this.type = isPresent(type) ? type : value.type;
}
visitStatement(visitor: StatementVisitor, context: any): any {
@ -623,7 +625,7 @@ export class ExpressionTransformer implements StatementVisitor, ExpressionVisito
expr.value.visitExpression(this, context));
}
visitInvokeMethodExpr(ast: InvokeMethodExpr, context: any): any {
var method = ast.builtin || ast.name;
var method = isPresent(ast.builtin) ? ast.builtin : ast.name;
return new InvokeMethodExpr(
ast.receiver.visitExpression(this, context), method,
this.visitAllExpressions(ast.args, context), ast.type);
@ -671,11 +673,9 @@ export class ExpressionTransformer implements StatementVisitor, ExpressionVisito
visitLiteralArrayExpr(ast: LiteralArrayExpr, context: any): any {
return new LiteralArrayExpr(this.visitAllExpressions(ast.entries, context));
}
visitLiteralMapExpr(ast: LiteralMapExpr, context: any): any {
const entries = ast.entries.map(
(entry): [string, Expression] => [entry[0], entry[1].visitExpression(this, context), ]);
return new LiteralMapExpr(entries);
return new LiteralMapExpr(ast.entries.map(
(entry) => [entry[0], (<Expression>entry[1]).visitExpression(this, context)]));
}
visitAllExpressions(exprs: Expression[], context: any): Expression[] {
return exprs.map(expr => expr.visitExpression(this, context));
@ -881,7 +881,8 @@ export function literalArr(values: Expression[], type: Type = null): LiteralArra
return new LiteralArrayExpr(values, type);
}
export function literalMap(values: [string, Expression][], type: MapType = null): LiteralMapExpr {
export function literalMap(
values: Array<Array<string|Expression>>, type: MapType = null): LiteralMapExpr {
return new LiteralMapExpr(values, type);
}

View File

@ -7,6 +7,7 @@
*/
import {ListWrapper} from '../facade/collection';
import {isPresent} from '../facade/lang';
import * as o from './output_ast';
@ -80,7 +81,7 @@ function createDynamicClass(
_executeFunctionStatements(
ctorParamNames, args, _classStmt.constructorMethod.body, instanceCtx, _visitor);
};
var superClass = _classStmt.parent ? _classStmt.parent.visitExpression(_visitor, _ctx) : Object;
var superClass = _classStmt.parent.visitExpression(_visitor, _ctx);
ctor.prototype = Object.create(superClass.prototype, propertyDescriptors);
return ctor;
}
@ -152,7 +153,7 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
if (isPresent(expr.builtin)) {
switch (expr.builtin) {
case o.BuiltinMethod.ConcatArray:
result = receiver.concat(args[0]);
result = ListWrapper.concat(receiver, args[0]);
break;
case o.BuiltinMethod.SubscribeObservable:
result = receiver.subscribe({next: args[0]});

View File

@ -6,26 +6,13 @@
* found in the LICENSE file at https://angular.io/license
*/
import {isPresent} from '../facade/lang';
import {evalExpression, isPresent} from '../facade/lang';
import {sanitizeIdentifier} from '../util';
import {EmitterVisitorContext} from './abstract_emitter';
import {AbstractJsEmitterVisitor} from './abstract_js_emitter';
import * as o from './output_ast';
function evalExpression(
sourceUrl: string, expr: string, declarations: string, vars: {[key: string]: any}): any {
const fnBody = `${declarations}\nreturn ${expr}\n//# sourceURL=${sourceUrl}`;
const fnArgNames: string[] = [];
const fnArgValues: any[] = [];
for (const argName in vars) {
fnArgNames.push(argName);
fnArgValues.push(vars[argName]);
}
return new Function(...fnArgNames.concat(fnBody))(...fnArgValues);
}
export function jitStatements(
sourceUrl: string, statements: o.Statement[], resultVar: string): any {
var converter = new JitEmitterVisitor();
@ -39,9 +26,9 @@ class JitEmitterVisitor extends AbstractJsEmitterVisitor {
private _evalArgValues: any[] = [];
getArgs(): {[key: string]: any} {
var result: {[key: string]: any} = {};
var result = {};
for (var i = 0; i < this._evalArgNames.length; i++) {
result[this._evalArgNames[i]] = this._evalArgValues[i];
(result as any /** TODO #9100 */)[this._evalArgNames[i]] = this._evalArgValues[i];
}
return result;
}

View File

@ -8,20 +8,24 @@
import {CompileIdentifierMetadata} from '../compile_metadata';
import {isBlank, isPresent} from '../facade/lang';
import {isArray, isBlank, isPresent} from '../facade/lang';
import {AbstractEmitterVisitor, CATCH_ERROR_VAR, CATCH_STACK_VAR, EmitterVisitorContext, OutputEmitter} from './abstract_emitter';
import * as o from './output_ast';
import {ImportGenerator} from './path_util';
const _debugModuleUrl = 'asset://debug/lib';
var _debugModuleUrl = 'asset://debug/lib';
export function debugOutputAstAsTypeScript(ast: o.Statement | o.Expression | o.Type | any[]):
string {
const converter = new _TsEmitterVisitor(_debugModuleUrl);
const ctx = EmitterVisitorContext.createRoot([]);
const asts: any[] = Array.isArray(ast) ? ast : [ast];
var converter = new _TsEmitterVisitor(_debugModuleUrl);
var ctx = EmitterVisitorContext.createRoot([]);
var asts: any[];
if (isArray(ast)) {
asts = <any[]>ast;
} else {
asts = [ast];
}
asts.forEach((ast) => {
if (ast instanceof o.Statement) {
ast.visitStatement(converter, ctx);
@ -42,7 +46,7 @@ export class TypeScriptEmitter implements OutputEmitter {
var converter = new _TsEmitterVisitor(moduleUrl);
var ctx = EmitterVisitorContext.createRoot(exportedVars);
converter.visitAllStatements(stmts, ctx);
var srcParts: string[] = [];
var srcParts: any[] /** TODO #9100 */ = [];
converter.importsWithPrefixes.forEach((prefix, importedModuleUrl) => {
// Note: can't write the real word for import as it screws up system.js auto detection...
srcParts.push(
@ -71,22 +75,6 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
super.visitLiteralExpr(ast, ctx, '(null as any)');
}
// Temporary workaround to support strictNullCheck enabled consumers of ngc emit.
// In SNC mode, [] have the type never[], so we cast here to any[].
// TODO: narrow the cast to a more explicit type, or use a pattern that does not
// start with [].concat. see https://github.com/angular/angular/pull/11846
visitLiteralArrayExpr(ast: o.LiteralArrayExpr, ctx: EmitterVisitorContext): any {
if (ast.entries.length === 0) {
ctx.print('(');
}
const result = super.visitLiteralArrayExpr(ast, ctx);
if (ast.entries.length === 0) {
ctx.print(' as any[])');
}
return result;
}
visitExternalExpr(ast: o.ExternalExpr, ctx: EmitterVisitorContext): any {
this._visitIdentifier(ast.value, ast.typeParams, ctx);
return null;
@ -239,7 +227,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
}
visitBuiltintType(type: o.BuiltinType, ctx: EmitterVisitorContext): any {
var typeStr: string;
var typeStr: any /** TODO #9100 */;
switch (type.name) {
case o.BuiltinTypeName.Bool:
typeStr = 'boolean';
@ -303,7 +291,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
}
private _visitParams(params: o.FnParam[], ctx: EmitterVisitorContext): void {
this.visitAllObjects(param => {
this.visitAllObjects((param: any /** TODO #9100 */) => {
ctx.print(param.name);
ctx.print(':');
this.visitType(param.type, ctx);
@ -332,7 +320,8 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
}
if (isPresent(typeParams) && typeParams.length > 0) {
ctx.print(`<`);
this.visitAllObjects(type => type.visitType(this, ctx), typeParams, ctx, ',');
this.visitAllObjects(
(type: any /** TODO #9100 */) => type.visitType(this, ctx), typeParams, ctx, ',');
ctx.print(`>`);
}
}

View File

@ -22,7 +22,7 @@ class _ValueOutputAstTransformer implements ValueTransformer {
}
visitStringMap(map: {[key: string]: any}, type: o.MapType): o.Expression {
const entries: [string, o.Expression][] = [];
var entries: Array<string|o.Expression>[] = [];
Object.keys(map).forEach(key => { entries.push([key, visitValue(map[key], this, null)]); });
return o.literalMap(entries, type);
}

View File

@ -35,7 +35,7 @@ export enum ParseErrorLevel {
FATAL
}
export class ParseError {
export abstract class ParseError {
constructor(
public span: ParseSourceSpan, public msg: string,
public level: ParseErrorLevel = ParseErrorLevel.FATAL) {}

View File

@ -0,0 +1,112 @@
/**
* @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 * as directive_normalizer from './directive_normalizer';
import * as lexer from './expression_parser/lexer';
import * as parser from './expression_parser/parser';
import * as metadata_resolver from './metadata_resolver';
import * as html_parser from './ml_parser/html_parser';
import * as interpolation_config from './ml_parser/interpolation_config';
import * as ng_module_compiler from './ng_module_compiler';
import * as path_util from './output/path_util';
import * as ts_emitter from './output/ts_emitter';
import * as parse_util from './parse_util';
import * as dom_element_schema_registry from './schema/dom_element_schema_registry';
import * as selector from './selector';
import * as style_compiler from './style_compiler';
import * as template_parser from './template_parser/template_parser';
import * as view_compiler from './view_compiler/view_compiler';
export const __compiler_private__: {
_SelectorMatcher?: selector.SelectorMatcher; SelectorMatcher: typeof selector.SelectorMatcher;
_CssSelector?: selector.CssSelector;
CssSelector: typeof selector.CssSelector;
_AssetUrl?: path_util.AssetUrl;
AssetUrl: typeof path_util.AssetUrl;
_ImportGenerator?: path_util.ImportGenerator;
ImportGenerator: typeof path_util.ImportGenerator;
_CompileMetadataResolver?: metadata_resolver.CompileMetadataResolver;
CompileMetadataResolver: typeof metadata_resolver.CompileMetadataResolver;
_HtmlParser?: html_parser.HtmlParser;
HtmlParser: typeof html_parser.HtmlParser;
_InterpolationConfig?: interpolation_config.InterpolationConfig;
InterpolationConfig: typeof interpolation_config.InterpolationConfig;
_DirectiveNormalizer?: directive_normalizer.DirectiveNormalizer;
DirectiveNormalizer: typeof directive_normalizer.DirectiveNormalizer;
_Lexer?: lexer.Lexer;
Lexer: typeof lexer.Lexer;
_Parser?: parser.Parser;
Parser: typeof parser.Parser;
_ParseLocation?: parse_util.ParseLocation;
ParseLocation: typeof parse_util.ParseLocation;
_ParseError?: parse_util.ParseError;
ParseError: typeof parse_util.ParseError;
_ParseErrorLevel?: parse_util.ParseErrorLevel;
ParseErrorLevel: typeof parse_util.ParseErrorLevel;
_ParseSourceFile?: parse_util.ParseSourceFile;
ParseSourceFile: typeof parse_util.ParseSourceFile;
_ParseSourceSpan?: parse_util.ParseSourceSpan;
ParseSourceSpan: typeof parse_util.ParseSourceSpan;
_TemplateParser?: template_parser.TemplateParser;
TemplateParser: typeof template_parser.TemplateParser;
_TemplateParseResult?: template_parser.TemplateParseResult;
_DomElementSchemaRegistry?: dom_element_schema_registry.DomElementSchemaRegistry;
DomElementSchemaRegistry: typeof dom_element_schema_registry.DomElementSchemaRegistry;
_StyleCompiler?: style_compiler.StyleCompiler;
StyleCompiler: typeof style_compiler.StyleCompiler;
_ViewCompiler?: view_compiler.ViewCompiler;
ViewCompiler: typeof view_compiler.ViewCompiler;
_NgModuleCompiler?: ng_module_compiler.NgModuleCompiler;
NgModuleCompiler: typeof ng_module_compiler.NgModuleCompiler;
_TypeScriptEmitter?: ts_emitter.TypeScriptEmitter;
TypeScriptEmitter: typeof ts_emitter.TypeScriptEmitter;
} = {
SelectorMatcher: selector.SelectorMatcher,
CssSelector: selector.CssSelector,
AssetUrl: path_util.AssetUrl,
ImportGenerator: path_util.ImportGenerator,
CompileMetadataResolver: metadata_resolver.CompileMetadataResolver,
HtmlParser: html_parser.HtmlParser,
InterpolationConfig: interpolation_config.InterpolationConfig,
DirectiveNormalizer: directive_normalizer.DirectiveNormalizer,
Lexer: lexer.Lexer,
Parser: parser.Parser,
ParseLocation: parse_util.ParseLocation,
ParseError: parse_util.ParseError,
ParseErrorLevel: parse_util.ParseErrorLevel,
ParseSourceFile: parse_util.ParseSourceFile,
ParseSourceSpan: parse_util.ParseSourceSpan,
TemplateParser: template_parser.TemplateParser,
DomElementSchemaRegistry: dom_element_schema_registry.DomElementSchemaRegistry,
StyleCompiler: style_compiler.StyleCompiler,
ViewCompiler: view_compiler.ViewCompiler,
NgModuleCompiler: ng_module_compiler.NgModuleCompiler,
TypeScriptEmitter: ts_emitter.TypeScriptEmitter
};

View File

@ -27,7 +27,13 @@ export const NgModuleInjector: typeof r.NgModuleInjector = r.NgModuleInjector;
export const registerModuleFactory: typeof r.registerModuleFactory = r.registerModuleFactory;
export type ViewType = typeof r._ViewType;
export const ViewType: typeof r.ViewType = r.ViewType;
export const view_utils: typeof r.view_utils = r.view_utils;
export const MAX_INTERPOLATION_VALUES: typeof r.MAX_INTERPOLATION_VALUES =
r.MAX_INTERPOLATION_VALUES;
export const checkBinding: typeof r.checkBinding = r.checkBinding;
export const flattenNestedViewRenderNodes: typeof r.flattenNestedViewRenderNodes =
r.flattenNestedViewRenderNodes;
export const interpolate: typeof r.interpolate = r.interpolate;
export const ViewUtils: typeof r.ViewUtils = r.ViewUtils;
export const DebugContext: typeof r.DebugContext = r.DebugContext;
export const StaticNodeDebugInfo: typeof r.StaticNodeDebugInfo = r.StaticNodeDebugInfo;
export const devModeEqual: typeof r.devModeEqual = r.devModeEqual;
@ -36,6 +42,19 @@ export const ValueUnwrapper: typeof r.ValueUnwrapper = r.ValueUnwrapper;
export const TemplateRef_: typeof r.TemplateRef_ = r.TemplateRef_;
export type RenderDebugInfo = typeof r._RenderDebugInfo;
export const RenderDebugInfo: typeof r.RenderDebugInfo = r.RenderDebugInfo;
export const EMPTY_ARRAY: typeof r.EMPTY_ARRAY = r.EMPTY_ARRAY;
export const EMPTY_MAP: typeof r.EMPTY_MAP = r.EMPTY_MAP;
export const pureProxy1: typeof r.pureProxy1 = r.pureProxy1;
export const pureProxy2: typeof r.pureProxy2 = r.pureProxy2;
export const pureProxy3: typeof r.pureProxy3 = r.pureProxy3;
export const pureProxy4: typeof r.pureProxy4 = r.pureProxy4;
export const pureProxy5: typeof r.pureProxy5 = r.pureProxy5;
export const pureProxy6: typeof r.pureProxy6 = r.pureProxy6;
export const pureProxy7: typeof r.pureProxy7 = r.pureProxy7;
export const pureProxy8: typeof r.pureProxy8 = r.pureProxy8;
export const pureProxy9: typeof r.pureProxy9 = r.pureProxy9;
export const pureProxy10: typeof r.pureProxy10 = r.pureProxy10;
export const castByValue: typeof r.castByValue = r.castByValue;
export type Console = typeof r._Console;
export const Console: typeof r.Console = r.Console;
export const reflector: typeof r.reflector = r.reflector;
@ -71,4 +90,3 @@ export const ViewMetadata: typeof r.ViewMetadata = r.ViewMetadata;
export type ComponentStillLoadingError = typeof r._ComponentStillLoadingError;
export const ComponentStillLoadingError: typeof r.ComponentStillLoadingError =
r.ComponentStillLoadingError;
export const AnimationTransition: typeof r.AnimationTransition = r.AnimationTransition;

View File

@ -8,8 +8,8 @@
import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileNgModuleMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata, CompileTypeMetadata} from './compile_metadata';
import {MapWrapper} from './facade/collection';
import {isBlank, isPresent} from './facade/lang';
import {ListWrapper, MapWrapper} from './facade/collection';
import {isArray, isBlank, isPresent, normalizeBlank} from './facade/lang';
import {Identifiers, resolveIdentifierToken} from './identifiers';
import {ParseError, ParseSourceSpan} from './parse_util';
import {AttrAst, DirectiveAst, ProviderAst, ProviderAstType, ReferenceAst} from './template_parser/template_ast';
@ -91,9 +91,9 @@ export class ProviderElementContext {
get transformedDirectiveAsts(): DirectiveAst[] {
var sortedProviderTypes = this.transformProviders.map(provider => provider.token.identifier);
var sortedDirectives = this._directiveAsts.slice();
sortedDirectives.sort(
(dir1, dir2) => sortedProviderTypes.indexOf(dir1.directive.type) -
var sortedDirectives = ListWrapper.clone(this._directiveAsts);
ListWrapper.sort(
sortedDirectives, (dir1, dir2) => sortedProviderTypes.indexOf(dir1.directive.type) -
sortedProviderTypes.indexOf(dir2.directive.type));
return sortedDirectives;
}
@ -102,7 +102,7 @@ export class ProviderElementContext {
private _addQueryReadsTo(token: CompileTokenMetadata, queryReadTokens: Map<any, boolean>) {
this._getQueriesFor(token).forEach((query) => {
const queryReadToken = query.read || token;
const queryReadToken = isPresent(query.read) ? query.read : token;
if (isBlank(queryReadTokens.get(queryReadToken.reference))) {
queryReadTokens.set(queryReadToken.reference, true);
}
@ -117,7 +117,7 @@ export class ProviderElementContext {
while (currentEl !== null) {
queries = currentEl._contentQueries.get(token.reference);
if (isPresent(queries)) {
result.push(...queries.filter((query) => query.descendants || distance <= 1));
ListWrapper.addAll(result, queries.filter((query) => query.descendants || distance <= 1));
}
if (currentEl._directiveAsts.length > 0) {
distance++;
@ -126,7 +126,7 @@ export class ProviderElementContext {
}
queries = this.viewContext.viewQueries.get(token.reference);
if (isPresent(queries)) {
result.push(...queries);
ListWrapper.addAll(result, queries);
}
return result;
}
@ -169,11 +169,11 @@ export class ProviderElementContext {
transformedUseValue = existingDiDep.value;
}
} else if (isPresent(provider.useFactory)) {
var deps = provider.deps || provider.useFactory.diDeps;
var deps = isPresent(provider.deps) ? provider.deps : provider.useFactory.diDeps;
transformedDeps =
deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep, eager));
} else if (isPresent(provider.useClass)) {
var deps = provider.deps || provider.useClass.diDeps;
var deps = isPresent(provider.deps) ? provider.deps : provider.useClass.diDeps;
transformedDeps =
deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep, eager));
}
@ -194,8 +194,7 @@ export class ProviderElementContext {
eager: boolean = null): CompileDiDependencyMetadata {
if (dep.isAttribute) {
var attrValue = this._attrs[dep.token.value];
return new CompileDiDependencyMetadata(
{isValue: true, value: attrValue == null ? null : attrValue});
return new CompileDiDependencyMetadata({isValue: true, value: normalizeBlank(attrValue)});
}
if (isPresent(dep.query) || isPresent(dep.viewQuery)) {
return dep;
@ -339,11 +338,11 @@ export class NgModuleProviderAnalyzer {
transformedUseValue = existingDiDep.value;
}
} else if (isPresent(provider.useFactory)) {
var deps = provider.deps || provider.useFactory.diDeps;
var deps = isPresent(provider.deps) ? provider.deps : provider.useFactory.diDeps;
transformedDeps =
deps.map((dep) => this._getDependency(dep, eager, resolvedProvider.sourceSpan));
} else if (isPresent(provider.useClass)) {
var deps = provider.deps || provider.useClass.diDeps;
var deps = isPresent(provider.deps) ? provider.deps : provider.useClass.diDeps;
transformedDeps =
deps.map((dep) => this._getDependency(dep, eager, resolvedProvider.sourceSpan));
}
@ -419,7 +418,7 @@ function _normalizeProviders(
}
if (isPresent(providers)) {
providers.forEach((provider) => {
if (Array.isArray(provider)) {
if (isArray(provider)) {
_normalizeProviders(<any[]>provider, sourceSpan, targetErrors, targetProviders);
} else {
let normalizeProvider: CompileProviderMetadata;
@ -490,7 +489,7 @@ function _resolveProviders(
targetProvidersByToken.set(provider.token.reference, resolvedProvider);
} else {
if (!provider.multi) {
resolvedProvider.providers.length = 0;
ListWrapper.clear(resolvedProvider.providers);
}
resolvedProvider.providers.push(provider);
}

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