Compare commits
169 Commits
2.0.0-beta
...
2.0.0-beta
Author | SHA1 | Date | |
---|---|---|---|
e6c8637cb8 | |||
dae1b1e7a6 | |||
f1f5b45361 | |||
50548fb565 | |||
8f47aa3530 | |||
df7885c9f5 | |||
0f10624b08 | |||
6f1ef33e32 | |||
231773ea76 | |||
e725542703 | |||
2337469753 | |||
55122cd57a | |||
7e0f02f96e | |||
e7ad03cba6 | |||
74be3d3fde | |||
a15ca23469 | |||
de77700da0 | |||
e73fee7156 | |||
72ab35bceb | |||
0f22dce036 | |||
c6036435f0 | |||
d86be245b8 | |||
a26053d3ff | |||
24d5b665e1 | |||
aa98fad338 | |||
9cb6dbbbab | |||
e21718faa9 | |||
b0f7d59e64 | |||
b86829f492 | |||
22929a1671 | |||
86c40f8474 | |||
16b521794c | |||
2a70f4e4c7 | |||
2f31c4c1c5 | |||
1435763383 | |||
05238df89b | |||
772d60d9fe | |||
24086bf0bb | |||
9b0e10e9a7 | |||
995a9e0cf8 | |||
b55f1764b5 | |||
5e9daed2e8 | |||
aa8c5aa2e2 | |||
f2c7946cca | |||
da1fcfd820 | |||
dbeff6f548 | |||
26e60d658a | |||
c2ceb7fba4 | |||
4bfe49cd42 | |||
cee2318110 | |||
cfef76f683 | |||
f56df65d48 | |||
3a40cd79f0 | |||
6acc99729c | |||
99e6500a2d | |||
5c782d6ba8 | |||
4e43d6f769 | |||
3529ee9973 | |||
29aa6a6c1c | |||
7918f3c1fc | |||
2f4e176054 | |||
d4565fdaf3 | |||
2a302aa73a | |||
31b819e9c2 | |||
27daeaff5e | |||
3e9b532409 | |||
c5aa6d17ef | |||
e480b0798e | |||
8a645d5e44 | |||
321193889f | |||
566d3ede04 | |||
8c36aa866a | |||
ed2dbf2db7 | |||
36a0e04604 | |||
8867afdaab | |||
a199772508 | |||
b008f542fa | |||
a78dcfa5f3 | |||
e1bf3d33f8 | |||
ae7d2ab515 | |||
c6adbf602c | |||
1f7a41c963 | |||
f4f614f3a9 | |||
94139c351f | |||
fc5b128b43 | |||
68a799af2e | |||
16d9c60a0e | |||
c0b5e7a672 | |||
6932b29acb | |||
c2a38c05aa | |||
8bea667a0b | |||
800c8f196f | |||
42231f5719 | |||
db87baeb98 | |||
c4c43f5a77 | |||
0ae77753f3 | |||
5f0baaac73 | |||
b5b6ece65a | |||
4282297c24 | |||
9c96b8affc | |||
132829e5e2 | |||
4a414420e9 | |||
fb6335ab60 | |||
89bd008445 | |||
caafb41eb5 | |||
31b81a7439 | |||
f7b1973358 | |||
32f01da49a | |||
59684c97b0 | |||
a32a0a3a97 | |||
96f5b0929d | |||
8e6cf7fca8 | |||
fdbe8741c9 | |||
775fb2c340 | |||
b60f594798 | |||
cc49790bdb | |||
a4bc19c530 | |||
f7985dbdb7 | |||
0bdcb5c1e0 | |||
a0d25db4a5 | |||
625474c4e2 | |||
1cd2a6328a | |||
d6bafe4fe3 | |||
6a2ef15355 | |||
a8ca560503 | |||
ad361808ec | |||
c47639f2b1 | |||
ba90a85f7b | |||
d3b569557f | |||
c9090ffa31 | |||
341bf39d23 | |||
3778ac26aa | |||
6cfc6f5bb2 | |||
47a3b4d56b | |||
c72ed991ad | |||
78bfdf78ea | |||
a24ee6add4 | |||
df3074fdfe | |||
f7424d5aeb | |||
a593ffa6f3 | |||
761c6d0df7 | |||
3e65d1458e | |||
a4b5cb8376 | |||
c785a1e474 | |||
3adc472f06 | |||
e7081b8b7c | |||
9b3a548f6f | |||
90b3502bb8 | |||
e19b31db29 | |||
bd015f14e8 | |||
ca7ba12fc6 | |||
ae05ec69c4 | |||
92dc3b91d8 | |||
8bd697b316 | |||
eda4c3eb4c | |||
4d0c2ed1f6 | |||
eda6a5d52a | |||
c1c54ed0f2 | |||
6b73d09ba1 | |||
ac85cbb28a | |||
b0cebdba6b | |||
933a9112da | |||
8c37b7e8f2 | |||
c8e909f8c9 | |||
69ae3634c7 | |||
95248f46a1 | |||
b3c7df1783 | |||
c56679e8e1 | |||
041c599511 |
15
.travis.yml
15
.travis.yml
@ -1,11 +1,11 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
node_js:
|
||||
- '4.2.1'
|
||||
- '5.4.1'
|
||||
|
||||
branches:
|
||||
except:
|
||||
- g3sync
|
||||
- g3_v2_0
|
||||
|
||||
cache:
|
||||
directories:
|
||||
@ -36,12 +36,13 @@ env:
|
||||
matrix:
|
||||
# Order: a slower build first, so that we don't occupy an idle travis worker waiting for others to complete.
|
||||
- MODE=dart DART_CHANNEL=stable DART_VERSION=$DART_STABLE_VERSION
|
||||
- MODE=dart DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||
# Disable dart dev build, which is timing out after 2h. #6823
|
||||
# - MODE=dart DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||
- MODE=saucelabs_required DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||
- MODE=browserstack_required DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||
- MODE=saucelabs_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||
- MODE=browserstack_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||
- MODE=dart_experimental DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||
- MODE=dart_ddc DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||
- MODE=js DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||
- MODE=router DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||
- MODE=build_only DART_CHANNEL=stable DART_VERSION=$DART_STABLE_VERSION
|
||||
@ -52,7 +53,6 @@ matrix:
|
||||
allow_failures:
|
||||
- env: "MODE=saucelabs_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
|
||||
- env: "MODE=browserstack_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
|
||||
- env: "MODE=dart_experimental DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
|
||||
# TODO(alxhub): remove when dartdoc #1039 is in dev channel
|
||||
- env: "MODE=dart DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
|
||||
|
||||
@ -60,6 +60,7 @@ addons:
|
||||
firefox: "38.0"
|
||||
|
||||
before_install:
|
||||
- npm install -g npm@3.5.3
|
||||
- node tools/analytics/build-analytics start ci job
|
||||
- node tools/analytics/build-analytics start ci before_install
|
||||
- echo ${TSDRC} > .tsdrc
|
||||
@ -77,7 +78,9 @@ install:
|
||||
# Check the size of caches
|
||||
- du -sh ./node_modules || true
|
||||
# Install npm dependecies
|
||||
- npm install
|
||||
# check-node-modules will exit(1) if we don't need to install
|
||||
# we need to manually kick off the postinstall script if check-node-modules exit(0)s
|
||||
- node tools/npm/check-node-modules --purge && npm install || npm run postinstall
|
||||
- node tools/analytics/build-analytics success ci install
|
||||
|
||||
before_script:
|
||||
|
1943
CHANGELOG.md
1943
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@ -180,7 +180,8 @@ Must be one of the following:
|
||||
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
||||
* **perf**: A code change that improves performance
|
||||
* **test**: Adding missing tests or correcting existing tests
|
||||
* **build** Changes that affect the build system, CI configuration or external dependencies (example scopes: gulp, broccoli, npm)
|
||||
* **build**: Changes that affect the build system, CI configuration or external dependencies (example scopes: gulp, broccoli, npm)
|
||||
* **ci**: Any changes to our CI configuration files and scripts (Travis, Circle CI, BrowserStack, SauceLabs)
|
||||
* **chore**: Other changes that don't modify `src` or `test` files
|
||||
|
||||
### Scope
|
||||
|
44
DEVELOPER.md
44
DEVELOPER.md
@ -9,7 +9,7 @@ JS and Dart versions. It also explains the basic mechanics of using `git`, `node
|
||||
* [Installing NPM Modules and Dart Packages](#installing-npm-modules-and-dart-packages)
|
||||
* [Build commands](#build-commands)
|
||||
* [Running Tests Locally](#running-tests-locally)
|
||||
* [Formatting](#clang-format)
|
||||
* [Code Style](#code-style)
|
||||
* [Project Information](#project-information)
|
||||
* [CI using Travis](#ci-using-travis)
|
||||
* [Transforming Dart code](#transforming-dart-code)
|
||||
@ -23,7 +23,16 @@ if you'd like to contribute to Angular.
|
||||
Before you can build and test Angular, you must install and configure the
|
||||
following products on your development machine:
|
||||
|
||||
* [Dart](https://www.dartlang.org) (version ` >=1.12.0 <2.0.0`), specifically the Dart-SDK and
|
||||
* [Git](http://git-scm.com) and/or the **GitHub app** (for [Mac](http://mac.github.com) or
|
||||
[Windows](http://windows.github.com)); [GitHub's Guide to Installing
|
||||
Git](https://help.github.com/articles/set-up-git) is a good source of information.
|
||||
|
||||
* [Node.js](http://nodejs.org), (version `>=5.4.1 <6`) which is used to run a development web server,
|
||||
run tests, and generate distributable files. We also use Node's Package Manager, `npm`
|
||||
(version `>=3.5.3 <4.0`), which comes with Node. Depending on your system, you can install Node either from
|
||||
source or as a pre-packaged bundle.
|
||||
|
||||
* *Optional*: [Dart](https://www.dartlang.org) (version ` >=1.13.2 <2.0.0`), specifically the Dart-SDK and
|
||||
Dartium (a version of [Chromium](http://www.chromium.org) with native support for Dart through
|
||||
the Dart VM). One of the **simplest** ways to get both is to install the **Dart Editor bundle**,
|
||||
which includes the editor, SDK and Dartium. See the [Dart tools](https://www.dartlang.org/tools)
|
||||
@ -33,19 +42,6 @@ following products on your development machine:
|
||||
to the `Path` (e.g. `path-to-dart-sdk-folder\bin`) and a new `DARTIUM_BIN` environment variable must be
|
||||
created, pointing to the executable (e.g. `path-to-dartium-folder\chrome.exe).`
|
||||
|
||||
* [Git](http://git-scm.com) and/or the **GitHub app** (for [Mac](http://mac.github.com) or
|
||||
[Windows](http://windows.github.com)); [GitHub's Guide to Installing
|
||||
Git](https://help.github.com/articles/set-up-git) is a good source of information.
|
||||
|
||||
* [Node.js](http://nodejs.org), (version `>=4.2.1 <5`) which is used to run a development web server,
|
||||
run tests, and generate distributable files. We also use Node's Package Manager, `npm`
|
||||
(version `>=2.14.7 <3.0`), which comes with Node. Depending on your system, you can install Node either from
|
||||
source or as a pre-packaged bundle.
|
||||
|
||||
* [Chrome Canary](https://www.google.com/chrome/browser/canary.html), a version of Chrome with
|
||||
bleeding edge functionality, built especially for developers (and early adopters).
|
||||
|
||||
* [Bower](http://bower.io/).
|
||||
|
||||
|
||||
## Getting the Sources
|
||||
@ -200,15 +196,15 @@ Then, in another terminal:
|
||||
export SAUCE_USERNAME='my_user'; export SAUCE_ACCESS_KEY='my_key';
|
||||
export BROWSER_STACK_USERNAME='my_user'; export BROWSER_STACK_ACCESS_KEY='my_key';
|
||||
```
|
||||
- Then run `gulp test.unit.js.(saucelabs|browserstack) --browsers=option1,option2,..,optionN`
|
||||
- Then run `gulp test.unit.js.(sauce|browserstack) --browsers=option1,option2,..,optionN`
|
||||
The options are any mix of browsers and aliases which are defined in the [browser-providers.conf.js](https://github.com/angular/angular/blob/master/browser-providers.conf.js) file.
|
||||
They are case insensitive, and the `SL_` or `BS_` prefix must not be added for browsers.
|
||||
|
||||
Some examples of commands:
|
||||
```
|
||||
gulp test.unit.js.saucelabs --browsers=Safari8,ie11 //run in Sauce Labs with Safari 8 and IE11
|
||||
gulp test.unit.js.sauce --browsers=Safari8,ie11 //run in Sauce Labs with Safari 8 and IE11
|
||||
gulp test.unit.js.browserstack --browsers=Safari,IE //run in Browser Stack with Safari 7, Safari 8, Safari 9, IE 9, IE 10 and IE 11
|
||||
gulp test.unit.js.saucelabs --browsers=IOS,safari8,android5.1 //run in Sauce Labs with iOS 7, iOS 8, iOs 9, Safari 8 and Android 5.1
|
||||
gulp test.unit.js.sauce --browsers=IOS,safari8,android5.1 //run in Sauce Labs with iOS 7, iOS 8, iOs 9, Safari 8 and Android 5.1
|
||||
```
|
||||
|
||||
### E2E tests
|
||||
@ -231,7 +227,9 @@ Angular specific command line options when running protractor:
|
||||
Angular specific command line options when running protractor (e.g. force gc, ...):
|
||||
`$(npm bin)/protractor protractor-{js|dart2js}-conf.js --ng-help`
|
||||
|
||||
## Formatting with <a name="clang-format">clang-format</a>
|
||||
## Code Style
|
||||
|
||||
### Formatting with <a name="clang-format">clang-format</a>
|
||||
|
||||
We use [clang-format](http://clang.llvm.org/docs/ClangFormat.html) to automatically enforce code
|
||||
style for our TypeScript code. This allows us to focus our code reviews more on the content, and
|
||||
@ -277,6 +275,14 @@ to some whitespace difference.
|
||||
* `clang-format` integrations are also available for many popular editors (`vim`, `emacs`,
|
||||
`Sublime Text`, etc.).
|
||||
|
||||
### Linting
|
||||
|
||||
We use [tslint](https://github.com/palantir/tslint) for linting. See linting rules in [gulpfile](gulpfile.js). To lint, run
|
||||
|
||||
```shell
|
||||
$ gulp lint
|
||||
```
|
||||
|
||||
## Generating the API documentation
|
||||
|
||||
The following gulp task will generate the API docs in the `dist/angular.io/partials/api/angular2`:
|
||||
|
215
LICENSE
215
LICENSE
@ -1,202 +1,21 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
The MIT License
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
Copyright (c) 2014-2016 Google, Inc. http://angular.io
|
||||
|
||||
1. Definitions.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
21
circle.yml
Normal file
21
circle.yml
Normal file
@ -0,0 +1,21 @@
|
||||
machine:
|
||||
node:
|
||||
version: 5.4.1
|
||||
|
||||
dependencies:
|
||||
pre:
|
||||
- npm install -g npm
|
||||
override:
|
||||
- npm install:
|
||||
environment:
|
||||
# Token for tsd to increase github rate limit
|
||||
# See https://github.com/DefinitelyTyped/tsd#tsdrc
|
||||
# This is not hidden using https://circleci.com/docs/fork-pr-builds#details
|
||||
# because those are not visible for pull requests, and those should also be reliable.
|
||||
# This SSO token belongs to github account angular-github-ratelimit-token which has no access
|
||||
# (password is in Valentine)
|
||||
TSD_GITHUB_TOKEN: ef474500309daea53d5991b3079159a29520a40b
|
||||
|
||||
test:
|
||||
override:
|
||||
- npm run build
|
192
gulpfile.js
192
gulpfile.js
@ -3,10 +3,10 @@
|
||||
// THIS CHECK SHOULD BE THE FIRST THING IN THIS FILE
|
||||
// This is to ensure that we catch env issues before we error while requiring other dependencies.
|
||||
require('./tools/check-environment')(
|
||||
{requiredNpmVersion: '>=2.14.7 <3.0.0', requiredNodeVersion: '>=4.2.1 <5.0.0'});
|
||||
{requiredNpmVersion: '>=3.5.3 <4.0.0', requiredNodeVersion: '>=5.4.1 <6.0.0'});
|
||||
|
||||
|
||||
var del = require('del');
|
||||
var fse = require('fs-extra');
|
||||
var gulp = require('gulp');
|
||||
var gulpPlugins = require('gulp-load-plugins')();
|
||||
var merge = require('merge');
|
||||
@ -42,7 +42,7 @@ if (cliArgs.projects) {
|
||||
|
||||
// --projects=angular2,angular2_material => {angular2: true, angular2_material: true}
|
||||
var allProjects =
|
||||
'angular1_router,angular2,angular2_material,benchmarks,benchmarks_external,benchpress,playground,bundle_deps';
|
||||
'angular1_router,angular2,angular2_material,benchmarks,benchmarks_external,benchpress,playground,payload_tests,bundle_deps';
|
||||
var cliArgsProjects = (cliArgs.projects || allProjects)
|
||||
.split(',')
|
||||
.reduce((map, projectName) => {
|
||||
@ -155,7 +155,7 @@ var HTTP_BUNDLE_CONTENT = 'angular2/http - rxjs/* - ' + ANGULAR2_BUNDLE_CONFIG.j
|
||||
var ROUTER_BUNDLE_CONTENT = 'angular2/router + angular2/router/router_link_dsl - rxjs/* - ' +
|
||||
ANGULAR2_BUNDLE_CONFIG.join(' - ');
|
||||
var TESTING_BUNDLE_CONTENT =
|
||||
'angular2/testing + angular2/http/testing + angular2/router/testing - rxjs/* - ' +
|
||||
'angular2/testing + angular2/http/testing + angular2/router/testing + angular2/platform/testing/browser - rxjs/* - ' +
|
||||
ANGULAR2_BUNDLE_CONFIG.join(' - ');
|
||||
var UPGRADE_BUNDLE_CONTENT = 'angular2/upgrade - rxjs/* - ' + ANGULAR2_BUNDLE_CONFIG.join(' - ');
|
||||
|
||||
@ -168,24 +168,36 @@ var BENCHPRESS_BUNDLE_CONFIG = {
|
||||
dest: CONFIG.dest.bundles.benchpress
|
||||
};
|
||||
|
||||
var PAYLOAD_TESTS_CONFIG = {
|
||||
ts: {
|
||||
bundleName: 'app-bundle-deps.min.js',
|
||||
cases: ['hello_world'],
|
||||
dist: function(caseName, packaging) {
|
||||
return path.join(__dirname, CONFIG.dest.js.prod.es5, 'payload_tests', caseName,
|
||||
'ts/' + packaging);
|
||||
},
|
||||
systemjs: {sizeLimits: {'uncompressed': 850 * 1024, 'gzip level=9': 165 * 1024}},
|
||||
webpack: {sizeLimits: {'uncompressed': 550 * 1024, 'gzip level=9': 120 * 1024}}
|
||||
}
|
||||
};
|
||||
|
||||
// ------------
|
||||
// clean
|
||||
|
||||
gulp.task('build/clean.tools', function() { del(path.join('dist', 'tools')); });
|
||||
gulp.task('build/clean.tools', (done) => fse.remove(path.join('dist', 'tools'), done));
|
||||
|
||||
gulp.task('build/clean.js', function(done) { del(CONFIG.dest.js.all, done); });
|
||||
gulp.task('build/clean.js', (done) => fse.remove(CONFIG.dest.js.all, done));
|
||||
|
||||
gulp.task('build/clean.dart', function(done) { del(CONFIG.dest.dart, done); });
|
||||
gulp.task('build/clean.dart', (done) => fse.remove(CONFIG.dest.dart, done));
|
||||
|
||||
gulp.task('build/clean.docs', function(done) { del(CONFIG.dest.docs, done); });
|
||||
gulp.task('build/clean.docs', (done) => fse.remove(CONFIG.dest.docs, done));
|
||||
|
||||
gulp.task('build/clean.docs_angular_io',
|
||||
function(done) { del(CONFIG.dest.docs_angular_io, done); });
|
||||
gulp.task('build/clean.docs_angular_io', (done) => fse.remove(CONFIG.dest.docs_angular_io, done));
|
||||
|
||||
gulp.task('build/clean.bundles', function(done) { del(CONFIG.dest.bundles.all, done); });
|
||||
gulp.task('build/clean.bundles', (done) => fse.remove(CONFIG.dest.bundles.all, done));
|
||||
|
||||
gulp.task('build/clean.bundles.benchpress',
|
||||
function(done) { del(CONFIG.dest.bundles.benchpress, done); });
|
||||
(done) => fse.remove(CONFIG.dest.bundles.benchpress, done));
|
||||
|
||||
// ------------
|
||||
// transpile
|
||||
@ -313,7 +325,9 @@ gulp.task('lint', ['build.tools'], function() {
|
||||
"requireParameterType": true,
|
||||
"requireReturnType": true,
|
||||
"semicolon": true,
|
||||
"variable-name": [true, "ban-keywords"]
|
||||
|
||||
// TODO: find a way to just screen for reserved names
|
||||
"variable-name": false
|
||||
}
|
||||
};
|
||||
return gulp.src(['modules/angular2/src/**/*.ts', '!modules/angular2/src/testing/**'])
|
||||
@ -449,7 +463,7 @@ function runKarma(configFile, done) {
|
||||
|
||||
gulp.task('test.js', function(done) {
|
||||
runSequence('test.unit.tools/ci', 'test.transpiler.unittest', 'test.unit.js/ci',
|
||||
'test.unit.cjs/ci', 'test.typings', sequenceComplete(done));
|
||||
'test.unit.cjs/ci', 'test.typings', 'check-public-api', sequenceComplete(done));
|
||||
});
|
||||
|
||||
gulp.task('test.dart', function(done) {
|
||||
@ -613,7 +627,11 @@ gulp.task('!test.unit.router/karma-run', function(done) {
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('buildRouter.dev', function() { buildRouter(); });
|
||||
gulp.task('buildRouter.dev', function() {
|
||||
var modulesSrcDir = __dirname + '/modules';
|
||||
var distDir = __dirname + '/dist';
|
||||
buildRouter(modulesSrcDir, distDir);
|
||||
});
|
||||
|
||||
gulp.task('test.unit.dart', function(done) {
|
||||
printModulesWarning();
|
||||
@ -638,7 +656,7 @@ gulp.task('test.unit.dart', function(done) {
|
||||
// This test will fail if the size of our hello_world app goes beyond one of
|
||||
// these values when compressed at the specified level.
|
||||
// Measure in bytes.
|
||||
var _DART_PAYLOAD_SIZE_LIMITS = {'uncompressed': 320 * 1024, 'gzip level=6': 90 * 1024};
|
||||
var _DART_PAYLOAD_SIZE_LIMITS = {'uncompressed': 320 * 1024, 'gzip level=9': 90 * 1024};
|
||||
gulp.task('test.payload.dart/ci', function(done) {
|
||||
runSequence('build/packages.dart', '!pubget.payload.dart', '!pubbuild.payload.dart',
|
||||
'!checkAndReport.payload.dart', done);
|
||||
@ -658,6 +676,103 @@ gulp.task('!checkAndReport.payload.dart', function() {
|
||||
{failConditions: _DART_PAYLOAD_SIZE_LIMITS, prefix: 'hello_world'});
|
||||
});
|
||||
|
||||
// JS payload size tracking
|
||||
gulp.task('test.payload.js/ci', function(done) {
|
||||
runSequence('build.payload.js', '!checkAndReport.payload.js', sequenceComplete(done));
|
||||
});
|
||||
|
||||
gulp.task('build.payload.js', ['build.js'], function(done) {
|
||||
runSequence('!build.payload.js.webpack', '!build.payload.js.systemjs', sequenceComplete(done));
|
||||
});
|
||||
|
||||
gulp.task('!build.payload.js.webpack', function() {
|
||||
var q = require('q');
|
||||
var webpack = q.denodeify(require('webpack'));
|
||||
|
||||
var ES5_PROD_ROOT = __dirname + '/' + CONFIG.dest.js.prod.es5;
|
||||
|
||||
return q.all(PAYLOAD_TESTS_CONFIG.ts.cases.map(function(caseName) {
|
||||
var CASE_PATH = PAYLOAD_TESTS_CONFIG.ts.dist(caseName, 'webpack');
|
||||
|
||||
return webpack({
|
||||
// bundle app + framework
|
||||
entry: CASE_PATH + '/index.js',
|
||||
output: {path: CASE_PATH, filename: "app-bundle.js"},
|
||||
resolve: {
|
||||
extensions: ['', '.js'],
|
||||
packageAlias: '', // option added to ignore "broken" package.json in our dist folder
|
||||
root: [ES5_PROD_ROOT]
|
||||
}
|
||||
})
|
||||
.then(function() { // pad bundle with mandatory dependencies
|
||||
return new Promise(function(resolve, reject) {
|
||||
gulp.src([
|
||||
'node_modules/zone.js/dist/zone-microtask.js',
|
||||
'node_modules/zone.js/dist/long-stack-trace-zone.js',
|
||||
'node_modules/reflect-metadata/Reflect.js',
|
||||
CASE_PATH + '/app-bundle.js'
|
||||
])
|
||||
.pipe(gulpPlugins.concat(PAYLOAD_TESTS_CONFIG.ts.bundleName))
|
||||
.pipe(gulpPlugins.uglify())
|
||||
.pipe(gulp.dest(CASE_PATH))
|
||||
.on('end', resolve)
|
||||
.on('error', reject);
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
gulp.task('!build.payload.js.systemjs', function() {
|
||||
var bundler = require('./tools/build/bundle');
|
||||
|
||||
return Promise.all(PAYLOAD_TESTS_CONFIG.ts.cases.map(function(caseName) {
|
||||
var CASE_PATH = PAYLOAD_TESTS_CONFIG.ts.dist(caseName, 'systemjs');
|
||||
|
||||
return bundler
|
||||
.bundle(
|
||||
{
|
||||
paths: {'index': CASE_PATH + '/index.js'},
|
||||
meta: {'angular2/core': {build: false}, 'angular2/platform/browser': {build: false}}
|
||||
},
|
||||
'index', CASE_PATH + '/index.register.js', {})
|
||||
.then(function() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
gulp.src([
|
||||
'node_modules/systemjs/dist/system.src.js',
|
||||
'dist/js/prod/es5/bundle/angular2-polyfills.js',
|
||||
'dist/js/prod/es5/bundle/angular2.js',
|
||||
'dist/js/prod/es5//rxjs/bundles/Rx.js',
|
||||
CASE_PATH + '/index.register.js',
|
||||
'tools/build/systemjs/payload_tests_import.js'
|
||||
])
|
||||
.pipe(gulpPlugins.concat(PAYLOAD_TESTS_CONFIG.ts.bundleName))
|
||||
.pipe(gulpPlugins.uglify())
|
||||
.pipe(gulp.dest(CASE_PATH))
|
||||
.on('end', resolve)
|
||||
.on('error', reject);
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
gulp.task('!checkAndReport.payload.js', function() {
|
||||
var reportSize = require('./tools/analytics/reportsize');
|
||||
|
||||
function caseSizeStream(caseName, packaging) {
|
||||
return reportSize(PAYLOAD_TESTS_CONFIG.ts.dist(caseName, packaging) + '/' +
|
||||
PAYLOAD_TESTS_CONFIG.ts.bundleName,
|
||||
{
|
||||
failConditions: PAYLOAD_TESTS_CONFIG.ts[packaging].sizeLimits,
|
||||
prefix: caseName + '_' + packaging
|
||||
})
|
||||
}
|
||||
|
||||
return PAYLOAD_TESTS_CONFIG.ts.cases.reduce(function(sizeReportingStreams, caseName) {
|
||||
sizeReportingStreams.add(caseSizeStream(caseName, 'systemjs'));
|
||||
sizeReportingStreams.add(caseSizeStream(caseName, 'webpack'));
|
||||
}, merge2());
|
||||
});
|
||||
|
||||
gulp.task('watch.dart.dev', function(done) {
|
||||
runSequence('build/tree.dart', 'build/pure-packages.dart', '!build/pubget.angular2.dart',
|
||||
'!build/change_detect.dart', '!build/remove-pub-symlinks', 'build.dart.material.css',
|
||||
@ -715,7 +830,7 @@ gulp.task('test.unit.js/ci', function(done) {
|
||||
reporters: ['dots'],
|
||||
browsers: browserConf.browsersToRun
|
||||
},
|
||||
done)
|
||||
function(err) { done(); })
|
||||
.start();
|
||||
});
|
||||
|
||||
@ -755,6 +870,8 @@ gulp.task('test.unit.cjs/ci', function(done) {
|
||||
runJasmineTests(['dist/js/cjs/{angular2,benchpress}/test/**/*_spec.js'], done);
|
||||
});
|
||||
|
||||
gulp.task('check-public-api',
|
||||
function(done) { runJasmineTests(['dist/tools/public_api_guard/**/*_spec.js'], done); });
|
||||
|
||||
gulp.task('test.unit.cjs', ['build/clean.js', 'build.tools'], function(neverDone) {
|
||||
var watch = require('./tools/build/watch');
|
||||
@ -864,15 +981,16 @@ gulp.task('!pre.test.typings.layoutNodeModule', ['build.js.cjs'], function() {
|
||||
.pipe(gulp.dest(path.join(tmpdir, 'node_modules')));
|
||||
});
|
||||
gulp.task('!pre.test.typings.copyTypingsSpec', function() {
|
||||
return gulp.src(['typing_spec/*.ts'], {base: 'typing_spec'}).pipe(gulp.dest(path.join(tmpdir)));
|
||||
return gulp.src(['typing_spec/*.ts'], {base: 'typing_spec'}).pipe(gulp.dest(tmpdir));
|
||||
});
|
||||
|
||||
gulp.task('test.typings',
|
||||
['!pre.test.typings.layoutNodeModule', '!pre.test.typings.copyTypingsSpec'], function() {
|
||||
var tsc = require('gulp-typescript');
|
||||
|
||||
return gulp.src([tmpdir + '/**'])
|
||||
return gulp.src([tmpdir + '/*.ts'])
|
||||
.pipe(tsc({
|
||||
target: 'ES5',
|
||||
target: 'ES6',
|
||||
module: 'commonjs',
|
||||
experimentalDecorators: true,
|
||||
noImplicitAny: true,
|
||||
@ -906,24 +1024,20 @@ gulp.task('build/pure-packages.dart/standalone', function() {
|
||||
.pipe(gulp.dest(CONFIG.dest.dart));
|
||||
});
|
||||
|
||||
gulp.task('build/pure-packages.dart/license',
|
||||
function() {
|
||||
return gulp.src(['LICENSE'])
|
||||
.pipe(gulp.dest(path.join(CONFIG.dest.dart, 'angular2_testing')));
|
||||
})
|
||||
gulp.task('build/pure-packages.dart/license', function() {
|
||||
return gulp.src(['LICENSE']).pipe(gulp.dest(path.join(CONFIG.dest.dart, 'angular2_testing')));
|
||||
});
|
||||
|
||||
|
||||
gulp.task('build/pure-packages.dart/angular2', function() {
|
||||
var yaml = require('js-yaml');
|
||||
|
||||
return gulp.src([
|
||||
'modules_dart/transform/**/*',
|
||||
'!modules_dart/transform/**/*.proto',
|
||||
'!modules_dart/transform/pubspec.yaml',
|
||||
'!modules_dart/transform/**/packages{,/**}',
|
||||
])
|
||||
.pipe(gulp.dest(path.join(CONFIG.dest.dart, 'angular2')));
|
||||
});
|
||||
gulp.task('build/pure-packages.dart/angular2', function() {
|
||||
return gulp.src([
|
||||
'modules_dart/transform/**/*',
|
||||
'!modules_dart/transform/**/*.proto',
|
||||
'!modules_dart/transform/pubspec.yaml',
|
||||
'!modules_dart/transform/**/packages{,/**}',
|
||||
])
|
||||
.pipe(gulp.dest(path.join(CONFIG.dest.dart, 'angular2')));
|
||||
});
|
||||
|
||||
// Builds all Dart packages, but does not compile them
|
||||
gulp.task('build/packages.dart', function(done) {
|
||||
@ -1127,8 +1241,8 @@ gulp.task('!bundle.testing', ['build.js.dev'], function() {
|
||||
{sourceMaps: true});
|
||||
});
|
||||
|
||||
gulp.task('!bundles.js.docs', function() {
|
||||
gulp.src('modules/angular2/docs/bundles/*').pipe(gulp.dest('dist/js/bundle'));
|
||||
gulp.task('!bundles.js.docs', ['clean'], function() {
|
||||
return gulp.src('modules/angular2/docs/bundles/*').pipe(gulp.dest('dist/js/bundle'));
|
||||
});
|
||||
|
||||
gulp.task('!bundles.js.umd', ['build.js.dev'], function() {
|
||||
@ -1276,7 +1390,7 @@ gulp.task('!bundle.copy', function() {
|
||||
|
||||
gulp.task('!bundles.js.checksize', function(done) {
|
||||
var reportSize = require('./tools/analytics/reportsize');
|
||||
return reportSize('dist/js/bundle/**', {printToConsole: ['gzip level=2']});
|
||||
return reportSize('dist/js/bundle/**/*.js', {printToConsole: ['gzip level=2']});
|
||||
});
|
||||
|
||||
gulp.task('bundles.js',
|
||||
|
50
modules/angular1_router/build.js
vendored
50
modules/angular1_router/build.js
vendored
@ -21,18 +21,25 @@ var files = [
|
||||
|
||||
var PRELUDE = '(function(){\n';
|
||||
var POSTLUDE = '\n}());\n';
|
||||
var FACADES = fs.readFileSync(__dirname + '/lib/facades.es5', 'utf8');
|
||||
var DIRECTIVES = fs.readFileSync(__dirname + '/src/ng_outlet.ts', 'utf8');
|
||||
var moduleTemplate = fs.readFileSync(__dirname + '/src/module_template.js', 'utf8');
|
||||
|
||||
function main() {
|
||||
var dir = __dirname + '/../angular2/src/router/';
|
||||
function main(modulesDirectory) {
|
||||
var angular1RouterModuleDirectory = modulesDirectory + '/angular1_router';
|
||||
|
||||
var facades = fs.readFileSync(
|
||||
angular1RouterModuleDirectory + '/lib/facades.es5', 'utf8');
|
||||
var directives = fs.readFileSync(
|
||||
angular1RouterModuleDirectory + '/src/ng_outlet.ts', 'utf8');
|
||||
var moduleTemplate = fs.readFileSync(
|
||||
angular1RouterModuleDirectory + '/src/module_template.js', 'utf8');
|
||||
|
||||
var dir = modulesDirectory + '/angular2/src/router/';
|
||||
var sharedCode = files.reduce(function (prev, file) {
|
||||
return prev + transform(fs.readFileSync(dir + file, 'utf8'));
|
||||
}, '');
|
||||
|
||||
var out = moduleTemplate.replace('//{{FACADES}}', FACADES).replace('//{{SHARED_CODE}}', sharedCode);
|
||||
return PRELUDE + transform(DIRECTIVES) + out + POSTLUDE;
|
||||
var out = moduleTemplate.replace('//{{FACADES}}', facades)
|
||||
.replace('//{{SHARED_CODE}}', sharedCode);
|
||||
return PRELUDE + transform(directives) + out + POSTLUDE;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -62,10 +69,29 @@ function isFacadeModule(modulePath) {
|
||||
modulePath === 'angular2/src/core/reflection/reflection';
|
||||
}
|
||||
|
||||
module.exports = function () {
|
||||
var dist = __dirname + '/../../dist';
|
||||
if (!fs.existsSync(dist)) {
|
||||
fs.mkdirSync(dist);
|
||||
module.exports = function(modulesDirectory, outputDirectory) {
|
||||
if (!fs.existsSync(outputDirectory)) {
|
||||
fs.mkdirSync(outputDirectory);
|
||||
}
|
||||
fs.writeFileSync(dist + '/angular_1_router.js', main());
|
||||
fs.writeFileSync(
|
||||
outputDirectory + '/angular_1_router.js', main(modulesDirectory));
|
||||
};
|
||||
|
||||
// CLI entry point
|
||||
if (require.main === module) {
|
||||
try {
|
||||
var args = process.argv;
|
||||
args.shift(); // node
|
||||
args.shift(); // scriptfile.js
|
||||
if (args.length < 2) {
|
||||
console.log("usage: $0 outFile path/to/modules");
|
||||
process.exit(1);
|
||||
}
|
||||
var outfile = args.shift();
|
||||
var directory = args.shift();
|
||||
fs.writeFileSync(outfile, main(directory));
|
||||
} catch (e) {
|
||||
console.log(e.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -173,6 +173,10 @@ var StringMapWrapper = {
|
||||
|
||||
var List = Array;
|
||||
var ListWrapper = {
|
||||
toJSON: function(l) {
|
||||
return JSON.stringify(l);
|
||||
},
|
||||
|
||||
clear: function (l) {
|
||||
l.length = 0;
|
||||
},
|
||||
@ -247,6 +251,10 @@ var ListWrapper = {
|
||||
};
|
||||
|
||||
var StringWrapper = {
|
||||
charCodeAt: function(s, i) {
|
||||
return s.charCodeAt(i);
|
||||
},
|
||||
|
||||
equals: function (s1, s2) {
|
||||
return s1 === s2;
|
||||
},
|
||||
@ -303,8 +311,8 @@ Location.prototype.subscribe = function () {
|
||||
//TODO: implement
|
||||
};
|
||||
Location.prototype.path = function () {
|
||||
return $location.path();
|
||||
return $location.url();
|
||||
};
|
||||
Location.prototype.go = function (url) {
|
||||
return $location.path(url);
|
||||
Location.prototype.go = function (path, query) {
|
||||
return $location.url(path + query);
|
||||
};
|
||||
|
@ -57,7 +57,7 @@ function routerFactory($q, $location, $$directiveIntrospector, $browser, $rootSc
|
||||
});
|
||||
|
||||
var router = new RootRouter(registry, location, $routerRootComponent);
|
||||
$rootScope.$watch(function () { return $location.path(); }, function (path) {
|
||||
$rootScope.$watch(function () { return $location.url(); }, function (path) {
|
||||
if (router.lastNavigationAttempt !== path) {
|
||||
router.navigateByUrl(path);
|
||||
}
|
||||
|
@ -155,10 +155,12 @@ function ngOutletDirective($animate, $q: ng.IQService, $router) {
|
||||
}
|
||||
|
||||
this.controller.$$routeParams = instruction.params;
|
||||
this.controller.$$template = '<div ' + dashCase(componentName) + '></div>';
|
||||
this.controller.$$template =
|
||||
'<' + dashCase(componentName) + ' router="$$router"></' + dashCase(componentName) + '>';
|
||||
this.controller.$$router = this.router.childRouter(instruction.componentType);
|
||||
|
||||
let newScope = scope.$new();
|
||||
newScope.$$router = this.controller.$$router;
|
||||
|
||||
let clone = $transclude(newScope, clone => {
|
||||
$animate.enter(clone, null, this.currentElement || element);
|
||||
|
2
modules/angular1_router/src/ng_route_shim.js
vendored
2
modules/angular1_router/src/ng_route_shim.js
vendored
@ -1,4 +1,4 @@
|
||||
/** @license Copyright 2014-2015 Google, Inc. http://github.com/angular/angular/LICENSE */
|
||||
/** @license Copyright 2014-2016 Google, Inc. http://github.com/angular/angular/LICENSE */
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
@ -21,17 +21,29 @@ describe('navigation', function () {
|
||||
$router = _$router_;
|
||||
});
|
||||
|
||||
registerComponent('userCmp', {
|
||||
registerDirective('userCmp', {
|
||||
template: '<div>hello {{userCmp.$routeParams.name}}</div>'
|
||||
});
|
||||
registerComponent('oneCmp', {
|
||||
registerDirective('oneCmp', {
|
||||
template: '<div>{{oneCmp.number}}</div>',
|
||||
controller: function () {this.number = 'one'}
|
||||
});
|
||||
registerComponent('twoCmp', {
|
||||
registerDirective('twoCmp', {
|
||||
template: '<div>{{twoCmp.number}}</div>',
|
||||
controller: function () {this.number = 'two'}
|
||||
});
|
||||
registerComponent('threeCmp', {
|
||||
template: '<div>{{$ctrl.number}}</div>',
|
||||
controller: function () {this.number = 'three'}
|
||||
});
|
||||
registerComponent('getParams', {
|
||||
template: '<div>{{$ctrl.params.x}}</div>',
|
||||
controller: function () {
|
||||
this.$routerOnActivate = function(next) {
|
||||
this.params = next.params;
|
||||
};
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
it('should work in a simple case', function () {
|
||||
@ -47,6 +59,21 @@ describe('navigation', function () {
|
||||
expect(elt.text()).toBe('one');
|
||||
});
|
||||
|
||||
|
||||
it('should work with components created by the `mod.component()` helper', function () {
|
||||
compile('<ng-outlet></ng-outlet>');
|
||||
|
||||
$router.config([
|
||||
{ path: '/', component: 'threeCmp' }
|
||||
]);
|
||||
|
||||
$router.navigateByUrl('/');
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(elt.text()).toBe('three');
|
||||
});
|
||||
|
||||
|
||||
it('should navigate between components with different parameters', function () {
|
||||
$router.config([
|
||||
{ path: '/user/:name', component: 'userCmp' }
|
||||
@ -68,7 +95,7 @@ describe('navigation', function () {
|
||||
function ParentController() {
|
||||
instanceCount += 1;
|
||||
}
|
||||
registerComponent('parentCmp', {
|
||||
registerDirective('parentCmp', {
|
||||
template: 'parent { <ng-outlet></ng-outlet> }',
|
||||
$routeConfig: [
|
||||
{ path: '/user/:name', component: 'userCmp' }
|
||||
@ -94,7 +121,7 @@ describe('navigation', function () {
|
||||
|
||||
|
||||
it('should work with nested outlets', function () {
|
||||
registerComponent('childCmp', {
|
||||
registerDirective('childCmp', {
|
||||
template: '<div>inner { <div ng-outlet></div> }</div>',
|
||||
$routeConfig: [
|
||||
{ path: '/b', component: 'oneCmp' }
|
||||
@ -112,9 +139,29 @@ describe('navigation', function () {
|
||||
expect(elt.text()).toBe('outer { inner { one } }');
|
||||
});
|
||||
|
||||
it('should work when parent route has empty path', inject(function ($location) {
|
||||
registerComponent('childCmp', {
|
||||
template: '<div>inner { <div ng-outlet></div> }</div>',
|
||||
$routeConfig: [
|
||||
{ path: '/b', component: 'oneCmp' }
|
||||
]
|
||||
});
|
||||
|
||||
$router.config([
|
||||
{ path: '/...', component: 'childCmp' }
|
||||
]);
|
||||
compile('<div>outer { <div ng-outlet></div> }</div>');
|
||||
|
||||
$router.navigateByUrl('/b');
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(elt.text()).toBe('outer { inner { one } }');
|
||||
expect($location.path()).toBe('/b');
|
||||
}));
|
||||
|
||||
|
||||
it('should work with recursive nested outlets', function () {
|
||||
registerComponent('recurCmp', {
|
||||
registerDirective('recurCmp', {
|
||||
template: '<div>recur { <div ng-outlet></div> }</div>',
|
||||
$routeConfig: [
|
||||
{ path: '/recur', component: 'recurCmp' },
|
||||
@ -147,6 +194,21 @@ describe('navigation', function () {
|
||||
}));
|
||||
|
||||
|
||||
it('should pass through query terms to the location', inject(function ($location) {
|
||||
$router.config([
|
||||
{ path: '/user', component: 'userCmp' }
|
||||
]);
|
||||
|
||||
compile('<div ng-outlet></div>');
|
||||
|
||||
$router.navigateByUrl('/user?x=y');
|
||||
$rootScope.$digest();
|
||||
|
||||
expect($location.path()).toBe('/user');
|
||||
expect($location.search()).toEqual({ x: 'y'});
|
||||
}));
|
||||
|
||||
|
||||
it('should change location to the canonical route', inject(function ($location) {
|
||||
compile('<div ng-outlet></div>');
|
||||
|
||||
@ -163,7 +225,7 @@ describe('navigation', function () {
|
||||
|
||||
|
||||
it('should change location to the canonical route with nested components', inject(function ($location) {
|
||||
registerComponent('childRouter', {
|
||||
registerDirective('childRouter', {
|
||||
template: '<div>inner { <div ng-outlet></div> }</div>',
|
||||
$routeConfig: [
|
||||
{ path: '/new-child', component: 'oneCmp', name: 'NewChild'},
|
||||
@ -206,9 +268,22 @@ describe('navigation', function () {
|
||||
}));
|
||||
|
||||
|
||||
it('should navigate when the location query changes', inject(function ($location) {
|
||||
$router.config([
|
||||
{ path: '/get/params', component: 'getParams' }
|
||||
]);
|
||||
compile('<div ng-outlet></div>');
|
||||
|
||||
$location.url('/get/params?x=y');
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(elt.text()).toBe('y');
|
||||
}));
|
||||
|
||||
|
||||
it('should expose a "navigating" property on $router', inject(function ($q) {
|
||||
var defer;
|
||||
registerComponent('pendingActivate', {
|
||||
registerDirective('pendingActivate', {
|
||||
$canActivate: function () {
|
||||
defer = $q.defer();
|
||||
return defer.promise;
|
||||
@ -227,36 +302,54 @@ describe('navigation', function () {
|
||||
expect($router.navigating).toBe(false);
|
||||
}));
|
||||
|
||||
function registerComponent(name, options) {
|
||||
var controller = options.controller || function () {};
|
||||
|
||||
['$routerOnActivate', '$routerOnDeactivate', '$routerOnReuse', '$routerCanReuse', '$routerCanDeactivate'].forEach(function (hookName) {
|
||||
if (options[hookName]) {
|
||||
controller.prototype[hookName] = options[hookName];
|
||||
}
|
||||
});
|
||||
|
||||
function registerDirective(name, options) {
|
||||
function factory() {
|
||||
return {
|
||||
template: options.template || '',
|
||||
controllerAs: name,
|
||||
controller: controller
|
||||
controller: getController(options)
|
||||
};
|
||||
}
|
||||
|
||||
if (options.$canActivate) {
|
||||
factory.$canActivate = options.$canActivate;
|
||||
}
|
||||
if (options.$routeConfig) {
|
||||
factory.$routeConfig = options.$routeConfig;
|
||||
}
|
||||
|
||||
applyStaticProperties(factory, options);
|
||||
$compileProvider.directive(name, factory);
|
||||
}
|
||||
|
||||
function registerComponent(name, options) {
|
||||
|
||||
var definition = {
|
||||
template: options.template || '',
|
||||
controller: getController(options),
|
||||
}
|
||||
applyStaticProperties(definition, options);
|
||||
$compileProvider.component(name, definition);
|
||||
}
|
||||
|
||||
function compile(template) {
|
||||
elt = $compile('<div>' + template + '</div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
return elt;
|
||||
}
|
||||
|
||||
function getController(options) {
|
||||
var controller = options.controller || function () {};
|
||||
[
|
||||
'$routerOnActivate', '$routerOnDeactivate',
|
||||
'$routerOnReuse', '$routerCanReuse',
|
||||
'$routerCanDeactivate'
|
||||
].forEach(function (hookName) {
|
||||
if (options[hookName]) {
|
||||
controller.prototype[hookName] = options[hookName];
|
||||
}
|
||||
});
|
||||
return controller;
|
||||
}
|
||||
|
||||
function applyStaticProperties(target, options) {
|
||||
['$canActivate', '$routeConfig'].forEach(function(property) {
|
||||
if (options[property]) {
|
||||
target[property] = options[property];
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -44,36 +44,105 @@ describe('router', function () {
|
||||
expect(elt.text()).toBe('Home');
|
||||
}));
|
||||
|
||||
function registerComponent(name, options) {
|
||||
var controller = options.controller || function () {};
|
||||
it('should bind the component to the current router', inject(function($location) {
|
||||
var router;
|
||||
registerComponent('homeCmp', {
|
||||
bindings: { router: '=' },
|
||||
controller: function($scope, $element) {
|
||||
this.$routerOnActivate = function() {
|
||||
router = this.router;
|
||||
};
|
||||
},
|
||||
template: 'Home'
|
||||
});
|
||||
|
||||
['$onActivate', '$onDeactivate', '$onReuse', '$canReuse', '$canDeactivate'].forEach(function (hookName) {
|
||||
if (options[hookName]) {
|
||||
controller.prototype[hookName] = options[hookName];
|
||||
registerComponent('app', {
|
||||
template: '<div ng-outlet></div>',
|
||||
$routeConfig: [
|
||||
{ path: '/', component: 'homeCmp' }
|
||||
]
|
||||
});
|
||||
|
||||
compile('<app></app>');
|
||||
|
||||
$location.path('/');
|
||||
$rootScope.$digest();
|
||||
var homeElement = elt.find('home-cmp');
|
||||
expect(homeElement.text()).toBe('Home');
|
||||
expect(homeElement.isolateScope().$ctrl.router).toBeDefined();
|
||||
expect(router).toBeDefined();
|
||||
}));
|
||||
|
||||
it('should work when an async route is provided route data', inject(function($location, $q) {
|
||||
registerDirective('homeCmp', {
|
||||
template: 'Home ({{homeCmp.isAdmin}})',
|
||||
$routerOnActivate: function(next, prev) {
|
||||
this.isAdmin = next.routeData.data.isAdmin;
|
||||
}
|
||||
});
|
||||
|
||||
registerDirective('app', {
|
||||
template: '<div ng-outlet></div>',
|
||||
$routeConfig: [
|
||||
{ path: '/', loader: function() { return $q.when('homeCmp'); }, data: { isAdmin: true } }
|
||||
]
|
||||
});
|
||||
|
||||
compile('<app></app>');
|
||||
|
||||
$location.path('/');
|
||||
$rootScope.$digest();
|
||||
expect(elt.text()).toBe('Home (true)');
|
||||
}));
|
||||
|
||||
function registerDirective(name, options) {
|
||||
function factory() {
|
||||
return {
|
||||
template: options.template || '',
|
||||
controllerAs: name,
|
||||
controller: controller
|
||||
controller: getController(options)
|
||||
};
|
||||
}
|
||||
|
||||
if (options.$canActivate) {
|
||||
factory.$canActivate = options.$canActivate;
|
||||
}
|
||||
if (options.$routeConfig) {
|
||||
factory.$routeConfig = options.$routeConfig;
|
||||
}
|
||||
|
||||
applyStaticProperties(factory, options);
|
||||
$compileProvider.directive(name, factory);
|
||||
}
|
||||
|
||||
function registerComponent(name, options) {
|
||||
|
||||
var definition = {
|
||||
bindings: options.bindings,
|
||||
template: options.template || '',
|
||||
controller: getController(options),
|
||||
}
|
||||
applyStaticProperties(definition, options);
|
||||
$compileProvider.component(name, definition);
|
||||
}
|
||||
|
||||
function compile(template) {
|
||||
elt = $compile('<div>' + template + '</div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
return elt;
|
||||
}
|
||||
|
||||
function getController(options) {
|
||||
var controller = options.controller || function () {};
|
||||
[
|
||||
'$routerOnActivate', '$routerOnDeactivate',
|
||||
'$routerOnReuse', '$routerCanReuse',
|
||||
'$routerCanDeactivate'
|
||||
].forEach(function (hookName) {
|
||||
if (options[hookName]) {
|
||||
controller.prototype[hookName] = options[hookName];
|
||||
}
|
||||
});
|
||||
return controller;
|
||||
}
|
||||
|
||||
function applyStaticProperties(target, options) {
|
||||
['$canActivate', '$routeConfig'].forEach(function(property) {
|
||||
if (options[property]) {
|
||||
target[property] = options[property];
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"version": "v4",
|
||||
"repo": "angular/DefinitelyTyped",
|
||||
"repo": "DefinitelyTyped/DefinitelyTyped",
|
||||
"ref": "master",
|
||||
"path": "typings",
|
||||
"bundle": "typings/tsd.d.ts",
|
||||
"installed": {
|
||||
"angularjs/angular.d.ts": {
|
||||
"commit": "746b9a892629060bc853e792afff536e0ec4655e"
|
||||
"commit": "6eebd5e90a1cbd6b47b0705ba72dbcd5baf846f3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,7 @@ library angular2;
|
||||
*
|
||||
* This library does not include `bootstrap`. Import `bootstrap.dart` instead.
|
||||
*/
|
||||
export 'package:angular2/core.dart'
|
||||
hide forwardRef, resolveForwardRef, ForwardRefFn;
|
||||
export 'package:angular2/core.dart';
|
||||
export 'package:angular2/common.dart';
|
||||
export 'package:angular2/instrumentation.dart';
|
||||
export 'package:angular2/src/core/angular_entrypoint.dart' show AngularEntrypoint;
|
||||
|
@ -1,5 +1,6 @@
|
||||
library angular2.core;
|
||||
|
||||
export './src/core/angular_entrypoint.dart' show AngularEntrypoint;
|
||||
export './src/core/metadata.dart';
|
||||
export './src/core/util.dart';
|
||||
export 'package:angular2/src/facade/lang.dart' show enableProdMode;
|
||||
@ -14,9 +15,8 @@ export './src/core/application_tokens.dart' show APP_ID,
|
||||
export './src/core/zone.dart';
|
||||
export './src/core/render.dart';
|
||||
export './src/core/linker.dart';
|
||||
export './src/core/debug/debug_element.dart' show DebugElement,
|
||||
Scope,
|
||||
inspectElement,
|
||||
export './src/core/debug/debug_node.dart' show DebugElement,
|
||||
DebugNode,
|
||||
asNativeElements;
|
||||
export './src/core/testability/testability.dart';
|
||||
export './src/core/change_detection.dart';
|
||||
|
@ -20,12 +20,7 @@ export {
|
||||
export * from './src/core/zone';
|
||||
export * from './src/core/render';
|
||||
export * from './src/core/linker';
|
||||
export {
|
||||
DebugElement,
|
||||
Scope,
|
||||
inspectElement,
|
||||
asNativeElements
|
||||
} from './src/core/debug/debug_element';
|
||||
export {DebugElement, DebugNode, asNativeElements} from './src/core/debug/debug_node';
|
||||
export * from './src/core/testability/testability';
|
||||
export * from './src/core/change_detection';
|
||||
export * from './src/core/platform_directives_and_pipes';
|
||||
|
@ -8,7 +8,7 @@
|
||||
# Modules, barrels and bundles
|
||||
|
||||
Angular2 source code is authored using the ES2015 standardized module format where one module corresponds to exactly one file. Multiple modules (files) can be logically grouped into so-called "barrels".
|
||||
A bundle is a file the contains all the code for one or more barrels.
|
||||
A bundle is a file that contains all the code for one or more barrels.
|
||||
|
||||
Most bundles come in several flavors:
|
||||
* regular and minified (got `.min` in their name);
|
||||
@ -32,7 +32,7 @@ filename | list of barrels | dev/prod | minified?
|
||||
`angular2-all.umd.js` | `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade`| prod | no
|
||||
`angular2-all.umd.min.js` | `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade` | prod | yes
|
||||
`angular2-all.umd.dev.js` | `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade` | dev | no
|
||||
`angular2-all-testing.umd.dev.js` | `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade`, `angular2/testing`, `angular2/http/testing`, `angular2/router/testing` | dev | no
|
||||
`angular2-all-testing.umd.dev.js` | `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade`, `angular2/testing`, `angular2/http/testing`, `angular2/router/testing`, `angular2/platform/testing/browser` | dev | no
|
||||
|
||||
**Warning**: bundles in the `UMD` format are _not_ "additive". A single application should use only one bundle from the above list.
|
||||
|
||||
@ -55,7 +55,7 @@ filename | list of barrels | dev/prod | minified?
|
||||
`upgrade.js` | `angular2/upgrade` | prod | no
|
||||
`upgrade.min.js` | `angular2/upgrade` | prod | yes
|
||||
`upgrade.dev.js` | `angular2/upgrade` | dev | no
|
||||
`testing.dev.js` | `angular2/testing`, `angular2/http/testing`, `angular2/router/testing` | dev | no
|
||||
`testing.dev.js` | `angular2/testing`, `angular2/http/testing`, `angular2/router/testing`, `angular2/platform/testing/browser` | dev | no
|
||||
|
||||
**Note**: bundles in the `System.register` format are "additive" - it is quite common to include several bundles in one application.
|
||||
For example people using Angular 2 with `http` and `router` would include: `angular2.js`, `http.js` and `router.js`.
|
||||
@ -89,4 +89,4 @@ Depending on if you are using Angular bundles or not you can either use RxJS bun
|
||||
|
||||
## ES6 shims (optional)
|
||||
|
||||
Users of pre-ES6 browsers might need to add an ES6 shim (e.g. [es6-shim](https://github.com/paulmillr/es6-shim))
|
||||
Users of pre-ES6 browsers might need to add an ES6 shim (e.g. [es6-shim](https://github.com/paulmillr/es6-shim))
|
||||
|
@ -2,8 +2,8 @@
|
||||
Bootstrapping
|
||||
@cheatsheetIndex 0
|
||||
@description
|
||||
{@target ts}`import {bootstrap} from 'angular2/angular2';`{@endtarget}
|
||||
{@target js}Available from the `ng.platform.browser` namespace.{@endtarget}
|
||||
{@target ts}`import {bootstrap} from 'angular2/platform/browser';`{@endtarget}
|
||||
{@target js}Available from the `ng.platform.browser` namespace{@endtarget}
|
||||
{@target dart}`import 'package:angular2/bootstrap.dart';`{@endtarget}
|
||||
|
||||
@cheatsheetItem
|
||||
|
@ -4,7 +4,7 @@ Built-in directives
|
||||
@description
|
||||
{@target ts}`import {NgIf, ...} from 'angular2/common';`{@endtarget}
|
||||
{@target js}Available from the `ng.common` namespace{@endtarget}
|
||||
{@target dart}`import 'package:angular2/common.dart';`{@endtarget}
|
||||
{@target dart}Available using `platform_directives` in pubspec{@endtarget}
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
|
@ -4,7 +4,7 @@ Class decorators
|
||||
@description
|
||||
{@target ts}`import {Directive, ...} from 'angular2/core';`{@endtarget}
|
||||
{@target js}Available from the `ng.core` namespace{@endtarget}
|
||||
{@target dart}`import 'package:angular2/core.dart';`{@endtarget}
|
||||
{@target dart}`import 'package:angular2/angular2.dart';`{@endtarget}
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
|
@ -4,7 +4,7 @@ Dependency injection configuration
|
||||
@description
|
||||
{@target ts}`import {provide} from 'angular2/core';`{@endtarget}
|
||||
{@target js}Available from the `ng.core` namespace{@endtarget}
|
||||
{@target dart}`import 'package:angular2/core.dart';`{@endtarget}
|
||||
{@target dart}`import 'package:angular2/angular2.dart';`{@endtarget}
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts dart):
|
||||
|
@ -4,7 +4,7 @@ Class field decorators for directives and components
|
||||
@description
|
||||
{@target ts}`import {Input, ...} from 'angular2/core';`{@endtarget}
|
||||
{@target js}Available from the `ng.core` namespace{@endtarget}
|
||||
{@target dart}`import 'package:angular2/core.dart';`{@endtarget}
|
||||
{@target dart}`import 'package:angular2/angular2.dart';`{@endtarget}
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts dart):
|
||||
|
@ -4,7 +4,7 @@ Forms
|
||||
@description
|
||||
{@target ts}`import {FORM_DIRECTIVES} from 'angular2/common';`{@endtarget}
|
||||
{@target js}Available from `ng.common.FORM_DIRECTIVES`{@endtarget}
|
||||
{@target dart}`import 'package:angular2/common.dart';`{@endtarget}
|
||||
{@target dart}Available using `platform_directives` in pubspec{@endtarget}
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
|
@ -4,22 +4,22 @@ Routing and navigation
|
||||
@description
|
||||
{@target ts}`import {RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, ...} from 'angular2/router';`{@endtarget}
|
||||
{@target js}Available from the `ng.router` namespace{@endtarget}
|
||||
{@target dart}`import 'package:angular2/router.dart';`{@endtarget}
|
||||
{@target dart}`import 'package:angular2/angular2.dart';`{@endtarget}
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`@RouteConfig([
|
||||
{ path: '/:myParam', component: MyComponent, as: 'MyCmp' },
|
||||
{ path: '/staticPath', component: ..., as: ...},
|
||||
{ path: '/*wildCardParam', component: ..., as: ...}
|
||||
{ path: '/:myParam', component: MyComponent, name: 'MyCmp' },
|
||||
{ path: '/staticPath', component: ..., name: ...},
|
||||
{ path: '/*wildCardParam', component: ..., name: ...}
|
||||
])
|
||||
class MyComponent() {}`|`@RouteConfig`
|
||||
syntax(js):
|
||||
`var MyComponent = ng.router.RouteConfig([
|
||||
{ path: '/:myParam', component: MyComponent, as: 'MyCmp' },
|
||||
{ path: '/staticPath', component: ..., as: ...},
|
||||
{ path: '/*wildCardParam', component: ..., as: ...}
|
||||
{ path: '/:myParam', component: MyComponent, name: 'MyCmp' },
|
||||
{ path: '/staticPath', component: ..., name: ...},
|
||||
{ path: '/*wildCardParam', component: ..., name: ...}
|
||||
]).Class({
|
||||
constructor: function() {}
|
||||
});`|`ng.router.RouteConfig`
|
||||
|
@ -71,7 +71,7 @@ The `*` symbol means that the current element will be turned into an embedded te
|
||||
syntax:
|
||||
`<p>Card No.: {{cardNumber | myCreditCardNumberFormatter}}</p>`|`{{cardNumber | myCreditCardNumberFormatter}}`
|
||||
description:
|
||||
Transforms the current value of expression `cardNumber` via the pipe called `creditCardNumberFormatter`.
|
||||
Transforms the current value of expression `cardNumber` via the pipe called `myCreditCardNumberFormatter`.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
|
@ -456,7 +456,7 @@ Where
|
||||
* `local` is a local identifier for local variables.
|
||||
* `internal` is an internal variable which the directive exports for binding.
|
||||
* `key` is an attribute name usually only used to trigger a specific directive.
|
||||
* `keyExpression` is an property name to which the expression will be bound to.
|
||||
* `keyExpression` is a property name to which the expression will be bound to.
|
||||
* `varExport` allows exporting of directive internal state as variables for further binding. If no `internal` name
|
||||
is specified, the exporting is to an implicit variable.
|
||||
* `microsyntax` allows you to build a simple microsyntax which can still clearly identify which expressions bind to
|
||||
|
@ -371,14 +371,14 @@ In TypeScript:
|
||||
import {platform, Provider, APP_INITIALIZER, Injector} from 'angular2/core';
|
||||
import {
|
||||
WORKER_RENDER_PLATFORM,
|
||||
WORKER_RENDER_APP_COMMON,
|
||||
WORKER_RENDER_APPLICATION_COMMON,
|
||||
initializeGenericWorkerRenderer,
|
||||
MessageBus
|
||||
} from 'angular2/platform/worker_render';
|
||||
|
||||
var bus = new MyAwesomeMessageBus();
|
||||
platform([WORKER_RENDER_PLATFORM])
|
||||
.application([WORKER_RENDER_APP_COMMON, new Provider(MessageBus, {useValue: bus}),
|
||||
.application([WORKER_RENDER_APPLICATION_COMMON, new Provider(MessageBus, {useValue: bus}),
|
||||
new Provider(APP_INITIALIZER, {
|
||||
useFactory: (injector) => () => initializeGenericWorkerRenderer(injector),
|
||||
deps: [Injector],
|
||||
@ -419,7 +419,7 @@ import 'package:angular2/platform/worker_render.dart';
|
||||
main() {
|
||||
var bus = new MyAwesomeMessageBus();
|
||||
platform([WORKER_RENDER_PLATFORM])
|
||||
.application([WORKER_RENDER_APP_COMMON, new Provider(MessageBus, useValue: bus),
|
||||
.application([WORKER_RENDER_APPLICATION_COMMON, new Provider(MessageBus, useValue: bus),
|
||||
new Provider(APP_INITIALIZER,
|
||||
useFactory: (injector) => () => initializeGenericWorkerRenderer(injector),
|
||||
deps: [Injector],
|
||||
@ -456,9 +456,9 @@ void initAppThread(NgZone zone) {
|
||||
*/
|
||||
}
|
||||
```
|
||||
Notice how we use the `WORKER_RENDER_APP_COMMON` providers instead of the `WORKER_RENDER_APP` providers on the render thread.
|
||||
This is because the `WORKER_RENDER_APP` providers include an application initializer that starts a new WebWorker/Isolate.
|
||||
The `WORKER_RENDER_APP_COMMON` providers make no assumption about where your application code lives.
|
||||
Notice how we use the `WORKER_RENDER_APPLICTION_COMMON` providers instead of the `WORKER_RENDER_APPLICATION` providers on the render thread.
|
||||
This is because the `WORKER_RENDER_APPLICATION` providers include an application initializer that starts a new WebWorker/Isolate.
|
||||
The `WORKER_RENDER_APPLICATION_COMMON` providers make no assumption about where your application code lives.
|
||||
However, we now need to provide our own app initializer. At the very least this initializer needs to call `initializeGenericWorkerRenderer`.
|
||||
|
||||
## MessageBroker
|
||||
|
@ -1,16 +1,8 @@
|
||||
import {DebugElement, Scope} from 'angular2/core';
|
||||
import {DebugElement} from 'angular2/core';
|
||||
|
||||
var debugElement: DebugElement;
|
||||
var predicate;
|
||||
|
||||
// #docregion scope_all
|
||||
debugElement.query(predicate, Scope.all);
|
||||
// #enddocregion
|
||||
|
||||
// #docregion scope_light
|
||||
debugElement.query(predicate, Scope.light);
|
||||
// #enddocregion
|
||||
|
||||
// #docregion scope_view
|
||||
debugElement.query(predicate, Scope.view);
|
||||
debugElement.query(predicate);
|
||||
// #enddocregion
|
||||
|
@ -1,17 +1,17 @@
|
||||
import {By} from 'angular2/platform/browser';
|
||||
import {DebugElement, Scope} from 'angular2/core';
|
||||
import {DebugElement} from 'angular2/core';
|
||||
|
||||
var debugElement: DebugElement;
|
||||
class MyDirective {}
|
||||
|
||||
// #docregion by_all
|
||||
debugElement.query(By.all(), Scope.all);
|
||||
debugElement.query(By.all());
|
||||
// #enddocregion
|
||||
|
||||
// #docregion by_css
|
||||
debugElement.query(By.css('[attribute]'), Scope.all);
|
||||
debugElement.query(By.css('[attribute]'));
|
||||
// #enddocregion
|
||||
|
||||
// #docregion by_directive
|
||||
debugElement.query(By.directive(MyDirective), Scope.all);
|
||||
debugElement.query(By.directive(MyDirective));
|
||||
// #enddocregion
|
||||
|
@ -141,7 +141,8 @@ export {URLSearchParams} from './src/http/url_search_params';
|
||||
* // Send a response to the request
|
||||
* connection.mockRespond(response);
|
||||
* });
|
||||
* });
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* http.get('people.json').observer({
|
||||
* next: res => {
|
||||
@ -156,7 +157,8 @@ export const HTTP_PROVIDERS: any[] = [
|
||||
// issue: https://github.com/angular/angular/issues/3183
|
||||
provide(Http,
|
||||
{
|
||||
useFactory: (xhrBackend, requestOptions) => new Http(xhrBackend, requestOptions),
|
||||
useFactory: (xhrBackend: XHRBackend, requestOptions: RequestOptions) =>
|
||||
new Http(xhrBackend, requestOptions),
|
||||
deps: [XHRBackend, RequestOptions]
|
||||
}),
|
||||
BrowserXhr,
|
||||
@ -268,7 +270,8 @@ export const HTTP_BINDINGS = HTTP_PROVIDERS;
|
||||
* // Send a response to the request
|
||||
* connection.mockRespond(response);
|
||||
* });
|
||||
* });
|
||||
* }
|
||||
* });
|
||||
|
||||
* jsonp.get('people.json').observer({
|
||||
* next: res => {
|
||||
@ -283,7 +286,8 @@ export const JSONP_PROVIDERS: any[] = [
|
||||
// issue: https://github.com/angular/angular/issues/3183
|
||||
provide(Jsonp,
|
||||
{
|
||||
useFactory: (jsonpBackend, requestOptions) => new Jsonp(jsonpBackend, requestOptions),
|
||||
useFactory: (jsonpBackend: JSONPBackend, requestOptions: RequestOptions) =>
|
||||
new Jsonp(jsonpBackend, requestOptions),
|
||||
deps: [JSONPBackend, RequestOptions]
|
||||
}),
|
||||
BrowserJsonp,
|
||||
|
37
modules/angular2/manual_typings/globals-es6.d.ts
vendored
37
modules/angular2/manual_typings/globals-es6.d.ts
vendored
@ -1,37 +0,0 @@
|
||||
/**
|
||||
* Declarations angular depends on for compilation to ES6.
|
||||
* This file is also used to propagate our transitive typings
|
||||
* to users.
|
||||
*/
|
||||
|
||||
/// <reference path="../typings/zone/zone.d.ts"/>
|
||||
/// <reference path="../typings/hammerjs/hammerjs.d.ts"/>
|
||||
/// <reference path="../typings/jasmine/jasmine.d.ts"/>
|
||||
/// <reference path="../typings/angular-protractor/angular-protractor.d.ts"/>
|
||||
|
||||
// TODO: ideally the node.d.ts reference should be scoped only for files that need and not to all
|
||||
// the code including client code
|
||||
/// <reference path="../typings/node/node.d.ts" />
|
||||
|
||||
declare var assert: any;
|
||||
|
||||
|
||||
interface BrowserNodeGlobal {
|
||||
Object: typeof Object;
|
||||
Array: typeof Array;
|
||||
Map: typeof Map;
|
||||
Set: typeof Set;
|
||||
Date: typeof Date;
|
||||
RegExp: typeof RegExp;
|
||||
JSON: typeof JSON;
|
||||
Math: typeof Math;
|
||||
assert(condition: any): void;
|
||||
Reflect: any;
|
||||
zone: Zone;
|
||||
getAngularTestability: Function;
|
||||
getAllAngularTestabilities: Function;
|
||||
setTimeout: Function;
|
||||
clearTimeout: Function;
|
||||
setInterval: Function;
|
||||
clearInterval: Function;
|
||||
}
|
55
modules/angular2/manual_typings/globals.d.ts
vendored
55
modules/angular2/manual_typings/globals.d.ts
vendored
@ -1,7 +1,52 @@
|
||||
/**
|
||||
* Declarations angular depends on for compilation to ES6.
|
||||
* This file is also used to propagate our transitive typings
|
||||
* to users.
|
||||
* Subset of es6-shim typings.
|
||||
* Angular should not require use of ES6 runtime but some API usages are already present.
|
||||
* See https://github.com/angular/angular/issues/5242
|
||||
* TODO(alexeagle): remove methods below which may not be present in targeted browser
|
||||
*/
|
||||
/// <reference path="../typings/es6-shim/es6-shim.d.ts"/>
|
||||
/// <reference path="./globals-es6.d.ts"/>
|
||||
|
||||
declare type PromiseConstructor = typeof Promise;
|
||||
|
||||
interface String {
|
||||
/**
|
||||
* Returns true if the sequence of elements of searchString converted to a String is the
|
||||
* same as the corresponding elements of this object (converted to a String) starting at
|
||||
* position. Otherwise returns false.
|
||||
*/
|
||||
startsWith(searchString: string, position?: number): boolean;
|
||||
|
||||
/**
|
||||
* Returns true if the sequence of elements of searchString converted to a String is the
|
||||
* same as the corresponding elements of this object (converted to a String) starting at
|
||||
* endPosition – length(this). Otherwise returns false.
|
||||
*/
|
||||
endsWith(searchString: string, endPosition?: number): boolean;
|
||||
}
|
||||
interface Array<T> {
|
||||
/**
|
||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
||||
* otherwise.
|
||||
* @param predicate find calls predicate once for each element of the array, in ascending
|
||||
* order, until it finds one where predicate returns true. If such an element is found, find
|
||||
* immediately returns that element value. Otherwise, find returns undefined.
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find(predicate: (value: T, index: number, obj: Array<T>) => boolean, thisArg?: any): T;
|
||||
/**
|
||||
* Returns the this object after filling the section identified by start and end with value
|
||||
* @param value value to fill array section with
|
||||
* @param start index to start filling the array at. If start is negative, it is treated as
|
||||
* length+start where length is the length of the array.
|
||||
* @param end index to stop filling the array at. If end is negative, it is treated as
|
||||
* length+end.
|
||||
*/
|
||||
fill(value: T, start?: number, end?: number): T[];
|
||||
}
|
||||
interface NumberConstructor {
|
||||
/**
|
||||
* Returns true if the value passed is an integer, false otherwise.
|
||||
* @param number A numeric value.
|
||||
*/
|
||||
isInteger(number: number): boolean;
|
||||
}
|
||||
|
@ -8,6 +8,12 @@
|
||||
"license": "<%= packageJson.license %>",
|
||||
"repository": <%= JSON.stringify(packageJson.repository) %>,
|
||||
"devDependencies": <%= JSON.stringify(packageJson.defaultDevDependencies) %>,
|
||||
"dependencies": {
|
||||
"typings": "0.6.6"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "typings install --ambient --name es6-promise github:DefinitelyTyped/DefinitelyTyped/es6-promise/es6-promise.d.ts#830e8ebd9ef137d039d5c7ede24a421f08595f83; typings install --ambient --name es6-collections github:DefinitelyTyped/DefinitelyTyped/es6-collections/es6-collections.d.ts#9f97e2a2bc1f502550c9b4fcaad1c48df5521d37"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"es6-promise": "<%= packageJson.dependencies['es6-promise'] %>",
|
||||
"es6-shim": "<%= packageJson.dependencies['es6-shim'] %>",
|
||||
|
@ -1,8 +1,8 @@
|
||||
export {AngularEntrypoint} from 'angular2/src/core/angular_entrypoint';
|
||||
export {
|
||||
BROWSER_PROVIDERS,
|
||||
ELEMENT_PROBE_BINDINGS,
|
||||
ELEMENT_PROBE_PROVIDERS,
|
||||
ELEMENT_PROBE_PROVIDERS_PROD_MODE,
|
||||
inspectNativeElement,
|
||||
BrowserDomAdapter,
|
||||
By,
|
||||
|
@ -1,8 +1,8 @@
|
||||
export {AngularEntrypoint} from 'angular2/src/core/angular_entrypoint';
|
||||
export {
|
||||
BROWSER_PROVIDERS,
|
||||
ELEMENT_PROBE_BINDINGS,
|
||||
ELEMENT_PROBE_PROVIDERS,
|
||||
ELEMENT_PROBE_PROVIDERS_PROD_MODE,
|
||||
inspectNativeElement,
|
||||
BrowserDomAdapter,
|
||||
By,
|
||||
|
@ -12,4 +12,4 @@ export {
|
||||
EventManagerPlugin
|
||||
} from 'angular2/src/platform/dom/events/event_manager';
|
||||
export * from 'angular2/src/platform/dom/debug/by';
|
||||
export * from 'angular2/src/platform/dom/debug/debug_element_view_listener';
|
||||
export * from 'angular2/src/platform/dom/debug/ng_probe';
|
||||
|
21
modules/angular2/platform/testing/browser.ts
Normal file
21
modules/angular2/platform/testing/browser.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import {
|
||||
TEST_BROWSER_STATIC_PLATFORM_PROVIDERS,
|
||||
ADDITIONAL_TEST_BROWSER_PROVIDERS
|
||||
} from 'angular2/platform/testing/browser_static';
|
||||
|
||||
import {BROWSER_APP_PROVIDERS} from 'angular2/platform/browser';
|
||||
|
||||
|
||||
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
|
||||
/**
|
||||
* Default patform providers for testing.
|
||||
*/
|
||||
export const TEST_BROWSER_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
|
||||
CONST_EXPR([TEST_BROWSER_STATIC_PLATFORM_PROVIDERS]);
|
||||
|
||||
/**
|
||||
* Default application providers for testing.
|
||||
*/
|
||||
export const TEST_BROWSER_APPLICATION_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
|
||||
CONST_EXPR([BROWSER_APP_PROVIDERS, ADDITIONAL_TEST_BROWSER_PROVIDERS]);
|
69
modules/angular2/platform/testing/browser_static.ts
Normal file
69
modules/angular2/platform/testing/browser_static.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import {
|
||||
APP_ID,
|
||||
DirectiveResolver,
|
||||
NgZone,
|
||||
Provider,
|
||||
ViewResolver,
|
||||
PLATFORM_COMMON_PROVIDERS,
|
||||
PLATFORM_INITIALIZER
|
||||
} from 'angular2/core';
|
||||
import {BROWSER_APP_COMMON_PROVIDERS} from 'angular2/src/platform/browser_common';
|
||||
import {BrowserDomAdapter} from 'angular2/src/platform/browser/browser_adapter';
|
||||
|
||||
import {AnimationBuilder} from 'angular2/src/animate/animation_builder';
|
||||
import {MockAnimationBuilder} from 'angular2/src/mock/animation_builder_mock';
|
||||
import {MockDirectiveResolver} from 'angular2/src/mock/directive_resolver_mock';
|
||||
import {MockViewResolver} from 'angular2/src/mock/view_resolver_mock';
|
||||
import {MockLocationStrategy} from 'angular2/src/mock/mock_location_strategy';
|
||||
import {LocationStrategy} from 'angular2/src/router/location_strategy';
|
||||
import {MockNgZone} from 'angular2/src/mock/ng_zone_mock';
|
||||
|
||||
import {XHRImpl} from "angular2/src/platform/browser/xhr_impl";
|
||||
import {XHR} from 'angular2/compiler';
|
||||
|
||||
import {TestComponentBuilder} from 'angular2/src/testing/test_component_builder';
|
||||
|
||||
import {BrowserDetection} from 'angular2/src/testing/utils';
|
||||
|
||||
import {ELEMENT_PROBE_PROVIDERS} from 'angular2/platform/common_dom';
|
||||
|
||||
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
|
||||
import {Log} from 'angular2/src/testing/utils';
|
||||
|
||||
function initBrowserTests() {
|
||||
BrowserDomAdapter.makeCurrent();
|
||||
BrowserDetection.setup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default patform providers for testing without a compiler.
|
||||
*/
|
||||
export const TEST_BROWSER_STATIC_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
|
||||
CONST_EXPR([
|
||||
PLATFORM_COMMON_PROVIDERS,
|
||||
new Provider(PLATFORM_INITIALIZER, {useValue: initBrowserTests, multi: true})
|
||||
]);
|
||||
|
||||
export const ADDITIONAL_TEST_BROWSER_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
|
||||
CONST_EXPR([
|
||||
new Provider(APP_ID, {useValue: 'a'}),
|
||||
ELEMENT_PROBE_PROVIDERS,
|
||||
new Provider(DirectiveResolver, {useClass: MockDirectiveResolver}),
|
||||
new Provider(ViewResolver, {useClass: MockViewResolver}),
|
||||
Log,
|
||||
TestComponentBuilder,
|
||||
new Provider(NgZone, {useClass: MockNgZone}),
|
||||
new Provider(LocationStrategy, {useClass: MockLocationStrategy}),
|
||||
new Provider(AnimationBuilder, {useClass: MockAnimationBuilder}),
|
||||
]);
|
||||
|
||||
/**
|
||||
* Default application providers for testing without a compiler.
|
||||
*/
|
||||
export const TEST_BROWSER_STATIC_APPLICATION_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
|
||||
CONST_EXPR([
|
||||
BROWSER_APP_COMMON_PROVIDERS,
|
||||
new Provider(XHR, {useClass: XHRImpl}),
|
||||
ADDITIONAL_TEST_BROWSER_PROVIDERS
|
||||
]);
|
1
modules/angular2/platform/testing/server.dart
Normal file
1
modules/angular2/platform/testing/server.dart
Normal file
@ -0,0 +1 @@
|
||||
// Intentionally blank, the Parse5Adapater bindings for JavaScript don't apply.
|
90
modules/angular2/platform/testing/server.ts
Normal file
90
modules/angular2/platform/testing/server.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import {
|
||||
APP_ID,
|
||||
DirectiveResolver,
|
||||
NgZone,
|
||||
Provider,
|
||||
ViewResolver,
|
||||
PLATFORM_COMMON_PROVIDERS,
|
||||
PLATFORM_INITIALIZER,
|
||||
APPLICATION_COMMON_PROVIDERS,
|
||||
Renderer
|
||||
} from 'angular2/core';
|
||||
import {Parse5DomAdapter} from 'angular2/src/platform/server/parse5_adapter';
|
||||
|
||||
import {AnimationBuilder} from 'angular2/src/animate/animation_builder';
|
||||
import {MockAnimationBuilder} from 'angular2/src/mock/animation_builder_mock';
|
||||
import {MockDirectiveResolver} from 'angular2/src/mock/directive_resolver_mock';
|
||||
import {MockViewResolver} from 'angular2/src/mock/view_resolver_mock';
|
||||
import {MockLocationStrategy} from 'angular2/src/mock/mock_location_strategy';
|
||||
import {LocationStrategy} from 'angular2/src/router/location_strategy';
|
||||
import {MockNgZone} from 'angular2/src/mock/ng_zone_mock';
|
||||
|
||||
import {TestComponentBuilder} from 'angular2/src/testing/test_component_builder';
|
||||
import {XHR} from 'angular2/src/compiler/xhr';
|
||||
import {BrowserDetection} from 'angular2/src/testing/utils';
|
||||
|
||||
import {COMPILER_PROVIDERS} from 'angular2/src/compiler/compiler';
|
||||
import {DOCUMENT} from 'angular2/src/platform/dom/dom_tokens';
|
||||
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
|
||||
import {RootRenderer} from 'angular2/src/core/render/api';
|
||||
import {DomRootRenderer, DomRootRenderer_} from 'angular2/src/platform/dom/dom_renderer';
|
||||
import {DomSharedStylesHost} from 'angular2/src/platform/dom/shared_styles_host';
|
||||
|
||||
import {
|
||||
EventManager,
|
||||
EVENT_MANAGER_PLUGINS,
|
||||
ELEMENT_PROBE_PROVIDERS
|
||||
} from 'angular2/platform/common_dom';
|
||||
import {DomEventsPlugin} from 'angular2/src/platform/dom/events/dom_events';
|
||||
|
||||
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
|
||||
import {Log} from 'angular2/src/testing/utils';
|
||||
|
||||
function initServerTests() {
|
||||
Parse5DomAdapter.makeCurrent();
|
||||
BrowserDetection.setup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default patform providers for testing.
|
||||
*/
|
||||
export const TEST_SERVER_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> = CONST_EXPR([
|
||||
PLATFORM_COMMON_PROVIDERS,
|
||||
new Provider(PLATFORM_INITIALIZER, {useValue: initServerTests, multi: true})
|
||||
]);
|
||||
|
||||
function appDoc() {
|
||||
try {
|
||||
return DOM.defaultDoc();
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default application providers for testing.
|
||||
*/
|
||||
export const TEST_SERVER_APPLICATION_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
|
||||
CONST_EXPR([
|
||||
// TODO(julie): when angular2/platform/server is available, use that instead of making our own
|
||||
// list here.
|
||||
APPLICATION_COMMON_PROVIDERS,
|
||||
COMPILER_PROVIDERS,
|
||||
new Provider(DOCUMENT, {useFactory: appDoc}),
|
||||
new Provider(DomRootRenderer, {useClass: DomRootRenderer_}),
|
||||
new Provider(RootRenderer, {useExisting: DomRootRenderer}),
|
||||
EventManager,
|
||||
new Provider(EVENT_MANAGER_PLUGINS, {useClass: DomEventsPlugin, multi: true}),
|
||||
new Provider(XHR, {useClass: XHR}),
|
||||
new Provider(APP_ID, {useValue: 'a'}),
|
||||
DomSharedStylesHost,
|
||||
ELEMENT_PROBE_PROVIDERS,
|
||||
new Provider(DirectiveResolver, {useClass: MockDirectiveResolver}),
|
||||
new Provider(ViewResolver, {useClass: MockViewResolver}),
|
||||
Log,
|
||||
TestComponentBuilder,
|
||||
new Provider(NgZone, {useClass: MockNgZone}),
|
||||
new Provider(LocationStrategy, {useClass: MockLocationStrategy}),
|
||||
new Provider(AnimationBuilder, {useClass: MockAnimationBuilder}),
|
||||
]);
|
@ -12,3 +12,5 @@ export 'package:angular2/src/web_workers/shared/service_message_broker.dart'
|
||||
show ReceivedMessage, ServiceMessageBroker, ServiceMessageBrokerFactory;
|
||||
export 'package:angular2/src/web_workers/shared/serializer.dart' show PRIMITIVE;
|
||||
export 'package:angular2/src/web_workers/shared/message_bus.dart';
|
||||
export 'package:angular2/src/web_workers/worker/router_providers.dart'
|
||||
show WORKER_APP_ROUTER;
|
||||
|
@ -8,12 +8,13 @@ export {
|
||||
ClientMessageBrokerFactory,
|
||||
FnArg,
|
||||
UiArguments
|
||||
} from '../src/web_workers/shared/client_message_broker';
|
||||
} from 'angular2/src/web_workers/shared/client_message_broker';
|
||||
export {
|
||||
ReceivedMessage,
|
||||
ServiceMessageBroker,
|
||||
ServiceMessageBrokerFactory
|
||||
} from '../src/web_workers/shared/service_message_broker';
|
||||
export {PRIMITIVE} from '../src/web_workers/shared/serializer';
|
||||
export * from '../src/web_workers/shared/message_bus';
|
||||
} from 'angular2/src/web_workers/shared/service_message_broker';
|
||||
export {PRIMITIVE} from 'angular2/src/web_workers/shared/serializer';
|
||||
export * from 'angular2/src/web_workers/shared/message_bus';
|
||||
export {AngularEntrypoint} from 'angular2/src/core/angular_entrypoint';
|
||||
export {WORKER_APP_ROUTER} from 'angular2/src/web_workers/worker/router_providers';
|
||||
|
@ -4,11 +4,11 @@ export 'package:angular2/src/platform/worker_render_common.dart'
|
||||
show
|
||||
WORKER_SCRIPT,
|
||||
WORKER_RENDER_PLATFORM,
|
||||
WORKER_RENDER_APP_COMMON,
|
||||
WORKER_RENDER_APPLICATION_COMMON,
|
||||
initializeGenericWorkerRenderer;
|
||||
|
||||
export 'package:angular2/src/platform/worker_render.dart'
|
||||
show WORKER_RENDER_APP, initIsolate, WebWorkerInstance;
|
||||
show WORKER_RENDER_APPLICATION, initIsolate, WebWorkerInstance;
|
||||
|
||||
export '../src/web_workers/shared/client_message_broker.dart'
|
||||
show ClientMessageBroker, ClientMessageBrokerFactory, FnArg, UiArguments;
|
||||
@ -18,3 +18,9 @@ export '../src/web_workers/shared/service_message_broker.dart'
|
||||
|
||||
export '../src/web_workers/shared/serializer.dart' show PRIMITIVE;
|
||||
export '../src/web_workers/shared/message_bus.dart';
|
||||
export '../src/web_workers/ui/router_providers.dart' show WORKER_RENDER_ROUTER;
|
||||
|
||||
import 'package:angular2/src/platform/worker_render_common.dart';
|
||||
|
||||
const WORKER_RENDER_APP = WORKER_RENDER_APPLICATION_COMMON;
|
||||
|
||||
|
@ -2,9 +2,9 @@ export {
|
||||
WORKER_SCRIPT,
|
||||
WORKER_RENDER_PLATFORM,
|
||||
initializeGenericWorkerRenderer,
|
||||
WORKER_RENDER_APP_COMMON
|
||||
WORKER_RENDER_APPLICATION_COMMON
|
||||
} from 'angular2/src/platform/worker_render_common';
|
||||
export * from 'angular2/src/platform/worker_render';
|
||||
export {WORKER_RENDER_APPLICATION, WebWorkerInstance} from 'angular2/src/platform/worker_render';
|
||||
export {
|
||||
ClientMessageBroker,
|
||||
ClientMessageBrokerFactory,
|
||||
@ -18,3 +18,10 @@ export {
|
||||
} from '../src/web_workers/shared/service_message_broker';
|
||||
export {PRIMITIVE} from '../src/web_workers/shared/serializer';
|
||||
export * from '../src/web_workers/shared/message_bus';
|
||||
import {WORKER_RENDER_APPLICATION} from 'angular2/src/platform/worker_render';
|
||||
|
||||
/**
|
||||
* @deprecated Use WORKER_RENDER_APPLICATION
|
||||
*/
|
||||
export const WORKER_RENDER_APP = WORKER_RENDER_APPLICATION;
|
||||
export {WORKER_RENDER_ROUTER} from 'angular2/src/web_workers/ui/router_providers';
|
||||
|
@ -9,9 +9,8 @@ homepage: <%= packageJson.homepage %>
|
||||
environment:
|
||||
sdk: '>=1.10.0 <2.0.0'
|
||||
dependencies:
|
||||
analyzer: '>=0.24.4 <0.27.0'
|
||||
analyzer: '>=0.24.4 <0.28.0'
|
||||
barback: '^0.15.2+2'
|
||||
code_transformers: '0.2.9+4'
|
||||
dart_style: '>=0.1.8 <0.3.0'
|
||||
glob: '^1.0.0'
|
||||
html: '^0.12.0'
|
||||
@ -23,7 +22,9 @@ dependencies:
|
||||
source_span: '^1.0.0'
|
||||
stack_trace: '^1.1.1'
|
||||
dev_dependencies:
|
||||
code_transformers: '>=0.2.9+4 <0.4.0'
|
||||
guinness: '^0.1.18'
|
||||
test: '^0.12.6'
|
||||
transformers:
|
||||
- angular2
|
||||
- $dart2js:
|
||||
|
@ -20,18 +20,12 @@ export {OnActivate, OnDeactivate, OnReuse, CanDeactivate, CanReuse} from './src/
|
||||
export {CanActivate} from './src/router/lifecycle_annotations';
|
||||
export {Instruction, ComponentInstruction} from './src/router/instruction';
|
||||
export {OpaqueToken} from 'angular2/core';
|
||||
export {ROUTER_PROVIDERS_COMMON} from 'angular2/src/router/router_providers_common';
|
||||
export {ROUTER_PROVIDERS, ROUTER_BINDINGS} from 'angular2/src/router/router_providers';
|
||||
|
||||
import {PlatformLocation} from './src/router/platform_location';
|
||||
import {LocationStrategy} from './src/router/location_strategy';
|
||||
import {PathLocationStrategy} from './src/router/path_location_strategy';
|
||||
import {Router, RootRouter} from './src/router/router';
|
||||
import {RouterOutlet} from './src/router/router_outlet';
|
||||
import {RouterLink} from './src/router/router_link';
|
||||
import {RouteRegistry, ROUTER_PRIMARY_COMPONENT} from './src/router/route_registry';
|
||||
import {Location} from './src/router/location';
|
||||
import {ApplicationRef, provide, OpaqueToken, Provider} from 'angular2/core';
|
||||
import {CONST_EXPR} from './src/facade/lang';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
|
||||
/**
|
||||
* A list of directives. To use the router directives like {@link RouterOutlet} and
|
||||
@ -56,63 +50,3 @@ import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
* ```
|
||||
*/
|
||||
export const ROUTER_DIRECTIVES: any[] = CONST_EXPR([RouterOutlet, RouterLink]);
|
||||
|
||||
/**
|
||||
* A list of {@link Provider}s. To use the router, you must add this to your application.
|
||||
*
|
||||
* ### Example ([live demo](http://plnkr.co/edit/iRUP8B5OUbxCWQ3AcIDm))
|
||||
*
|
||||
* ```
|
||||
* import {Component} from 'angular2/core';
|
||||
* import {
|
||||
* ROUTER_DIRECTIVES,
|
||||
* ROUTER_PROVIDERS,
|
||||
* RouteConfig
|
||||
* } from 'angular2/router';
|
||||
*
|
||||
* @Component({directives: [ROUTER_DIRECTIVES]})
|
||||
* @RouteConfig([
|
||||
* {...},
|
||||
* ])
|
||||
* class AppCmp {
|
||||
* // ...
|
||||
* }
|
||||
*
|
||||
* bootstrap(AppCmp, [ROUTER_PROVIDERS]);
|
||||
* ```
|
||||
*/
|
||||
export const ROUTER_PROVIDERS: any[] = CONST_EXPR([
|
||||
RouteRegistry,
|
||||
CONST_EXPR(new Provider(LocationStrategy, {useClass: PathLocationStrategy})),
|
||||
PlatformLocation,
|
||||
Location,
|
||||
CONST_EXPR(new Provider(
|
||||
Router,
|
||||
{
|
||||
useFactory: routerFactory,
|
||||
deps: CONST_EXPR([RouteRegistry, Location, ROUTER_PRIMARY_COMPONENT, ApplicationRef])
|
||||
})),
|
||||
CONST_EXPR(new Provider(
|
||||
ROUTER_PRIMARY_COMPONENT,
|
||||
{useFactory: routerPrimaryComponentFactory, deps: CONST_EXPR([ApplicationRef])}))
|
||||
]);
|
||||
|
||||
/**
|
||||
* Use {@link ROUTER_PROVIDERS} instead.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
export const ROUTER_BINDINGS = ROUTER_PROVIDERS;
|
||||
|
||||
function routerFactory(registry, location, primaryComponent, appRef) {
|
||||
var rootRouter = new RootRouter(registry, location, primaryComponent);
|
||||
appRef.registerDisposeListener(() => rootRouter.dispose());
|
||||
return rootRouter;
|
||||
}
|
||||
|
||||
function routerPrimaryComponentFactory(app) {
|
||||
if (app.componentTypes.length == 0) {
|
||||
throw new BaseException("Bootstrap at least one component before injecting Router.");
|
||||
}
|
||||
return app.componentTypes[0];
|
||||
}
|
||||
|
@ -6,7 +6,8 @@ import {
|
||||
IterableDiffers,
|
||||
ViewContainerRef,
|
||||
TemplateRef,
|
||||
EmbeddedViewRef
|
||||
EmbeddedViewRef,
|
||||
TrackByFn
|
||||
} from 'angular2/core';
|
||||
import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||
|
||||
@ -59,10 +60,11 @@ import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||
* See a [live demo](http://plnkr.co/edit/KVuXxDp0qinGDyo307QW?p=preview) for a more detailed
|
||||
* example.
|
||||
*/
|
||||
@Directive({selector: '[ngFor][ngForOf]', inputs: ['ngForOf', 'ngForTemplate']})
|
||||
@Directive({selector: '[ngFor][ngForOf]', inputs: ['ngForTrackBy', 'ngForOf', 'ngForTemplate']})
|
||||
export class NgFor implements DoCheck {
|
||||
/** @internal */
|
||||
_ngForOf: any;
|
||||
_ngForTrackBy: TrackByFn;
|
||||
private _differ: IterableDiffer;
|
||||
|
||||
constructor(private _viewContainer: ViewContainerRef, private _templateRef: TemplateRef,
|
||||
@ -71,7 +73,7 @@ export class NgFor implements DoCheck {
|
||||
set ngForOf(value: any) {
|
||||
this._ngForOf = value;
|
||||
if (isBlank(this._differ) && isPresent(value)) {
|
||||
this._differ = this._iterableDiffers.find(value).create(this._cdr);
|
||||
this._differ = this._iterableDiffers.find(value).create(this._cdr, this._ngForTrackBy);
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,6 +83,8 @@ export class NgFor implements DoCheck {
|
||||
}
|
||||
}
|
||||
|
||||
set ngForTrackBy(value: TrackByFn) { this._ngForTrackBy = value; }
|
||||
|
||||
ngDoCheck() {
|
||||
if (isPresent(this._differ)) {
|
||||
var changes = this._differ.diff(this._ngForOf);
|
||||
@ -113,6 +117,11 @@ export class NgFor implements DoCheck {
|
||||
var viewRef = <EmbeddedViewRef>this._viewContainer.get(i);
|
||||
viewRef.setLocal('last', i === ilen - 1);
|
||||
}
|
||||
|
||||
changes.forEachIdentityChange((record) => {
|
||||
var viewRef = <EmbeddedViewRef>this._viewContainer.get(record.currentIndex);
|
||||
viewRef.setLocal('\$implicit', record.item);
|
||||
});
|
||||
}
|
||||
|
||||
private _perViewChange(view, record) {
|
||||
|
@ -4,7 +4,8 @@ import {ListWrapper, Map} from 'angular2/src/facade/collection';
|
||||
|
||||
const _WHEN_DEFAULT = CONST_EXPR(new Object());
|
||||
|
||||
class SwitchView {
|
||||
/** @internal */
|
||||
export class SwitchView {
|
||||
constructor(private _viewContainerRef: ViewContainerRef, private _templateRef: TemplateRef) {}
|
||||
|
||||
create(): void { this._viewContainerRef.createEmbeddedView(this._templateRef); }
|
||||
|
@ -21,7 +21,7 @@ class ObservableListDiff extends DefaultIterableDiffer {
|
||||
}
|
||||
}
|
||||
|
||||
dynamic diff(ObservableList collection) {
|
||||
DefaultIterableDiffer diff(ObservableList collection) {
|
||||
if (collection is! ObservableList) {
|
||||
throw "Cannot change the type of a collection";
|
||||
}
|
||||
@ -57,7 +57,7 @@ class ObservableListDiff extends DefaultIterableDiffer {
|
||||
class ObservableListDiffFactory implements IterableDifferFactory {
|
||||
const ObservableListDiffFactory();
|
||||
bool supports(obj) => obj is ObservableList;
|
||||
IterableDiffer create(ChangeDetectorRef cdRef) {
|
||||
IterableDiffer create(ChangeDetectorRef cdRef, [Function trackByFn]) {
|
||||
return new ObservableListDiff(cdRef);
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ export {
|
||||
NgSelectOption,
|
||||
SelectControlValueAccessor
|
||||
} from './forms/directives/select_control_value_accessor';
|
||||
export {FORM_DIRECTIVES} from './forms/directives';
|
||||
export {FORM_DIRECTIVES, RadioButtonState} from './forms/directives';
|
||||
export {NG_VALIDATORS, NG_ASYNC_VALIDATORS, Validators} from './forms/validators';
|
||||
export {
|
||||
RequiredValidator,
|
||||
@ -39,4 +39,25 @@ export {
|
||||
MaxLengthValidator,
|
||||
Validator
|
||||
} from './forms/directives/validators';
|
||||
export {FormBuilder, FORM_PROVIDERS, FORM_BINDINGS} from './forms/form_builder';
|
||||
export {FormBuilder} from './forms/form_builder';
|
||||
import {FormBuilder} from './forms/form_builder';
|
||||
import {RadioControlRegistry} from './forms/directives/radio_control_value_accessor';
|
||||
import {Type, CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
|
||||
/**
|
||||
* Shorthand set of providers used for building Angular forms.
|
||||
*
|
||||
* ### Example
|
||||
*
|
||||
* ```typescript
|
||||
* bootstrap(MyApp, [FORM_PROVIDERS]);
|
||||
* ```
|
||||
*/
|
||||
export const FORM_PROVIDERS: Type[] = CONST_EXPR([FormBuilder, RadioControlRegistry]);
|
||||
|
||||
/**
|
||||
* See {@link FORM_PROVIDERS} instead.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
export const FORM_BINDINGS = FORM_PROVIDERS;
|
||||
|
@ -8,6 +8,7 @@ import {NgForm} from './directives/ng_form';
|
||||
import {DefaultValueAccessor} from './directives/default_value_accessor';
|
||||
import {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor';
|
||||
import {NumberValueAccessor} from './directives/number_value_accessor';
|
||||
import {RadioControlValueAccessor} from './directives/radio_control_value_accessor';
|
||||
import {NgControlStatus} from './directives/ng_control_status';
|
||||
import {
|
||||
SelectControlValueAccessor,
|
||||
@ -23,6 +24,10 @@ export {NgFormModel} from './directives/ng_form_model';
|
||||
export {NgForm} from './directives/ng_form';
|
||||
export {DefaultValueAccessor} from './directives/default_value_accessor';
|
||||
export {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor';
|
||||
export {
|
||||
RadioControlValueAccessor,
|
||||
RadioButtonState
|
||||
} from './directives/radio_control_value_accessor';
|
||||
export {NumberValueAccessor} from './directives/number_value_accessor';
|
||||
export {NgControlStatus} from './directives/ng_control_status';
|
||||
export {
|
||||
@ -63,6 +68,7 @@ export const FORM_DIRECTIVES: Type[] = CONST_EXPR([
|
||||
NumberValueAccessor,
|
||||
CheckboxControlValueAccessor,
|
||||
SelectControlValueAccessor,
|
||||
RadioControlValueAccessor,
|
||||
NgControlStatus,
|
||||
|
||||
RequiredValidator,
|
||||
|
@ -18,7 +18,7 @@ const CHECKBOX_VALUE_ACCESSOR = CONST_EXPR(new Provider(
|
||||
selector:
|
||||
'input[type=checkbox][ngControl],input[type=checkbox][ngFormControl],input[type=checkbox][ngModel]',
|
||||
host: {'(change)': 'onChange($event.target.checked)', '(blur)': 'onTouched()'},
|
||||
bindings: [CHECKBOX_VALUE_ACCESSOR]
|
||||
providers: [CHECKBOX_VALUE_ACCESSOR]
|
||||
})
|
||||
export class CheckboxControlValueAccessor implements ControlValueAccessor {
|
||||
onChange = (_) => {};
|
||||
|
@ -0,0 +1,126 @@
|
||||
import {
|
||||
Directive,
|
||||
ElementRef,
|
||||
Renderer,
|
||||
Self,
|
||||
forwardRef,
|
||||
Provider,
|
||||
Attribute,
|
||||
Input,
|
||||
OnInit,
|
||||
OnDestroy,
|
||||
Injector,
|
||||
Injectable
|
||||
} from 'angular2/core';
|
||||
import {
|
||||
NG_VALUE_ACCESSOR,
|
||||
ControlValueAccessor
|
||||
} from 'angular2/src/common/forms/directives/control_value_accessor';
|
||||
import {NgControl} from 'angular2/src/common/forms/directives/ng_control';
|
||||
import {CONST_EXPR, looseIdentical, isPresent} from 'angular2/src/facade/lang';
|
||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||
|
||||
const RADIO_VALUE_ACCESSOR = CONST_EXPR(new Provider(
|
||||
NG_VALUE_ACCESSOR, {useExisting: forwardRef(() => RadioControlValueAccessor), multi: true}));
|
||||
|
||||
|
||||
/**
|
||||
* Internal class used by Angular to uncheck radio buttons with the matching name.
|
||||
*/
|
||||
@Injectable()
|
||||
export class RadioControlRegistry {
|
||||
private _accessors: any[] = [];
|
||||
|
||||
add(control: NgControl, accessor: RadioControlValueAccessor) {
|
||||
this._accessors.push([control, accessor]);
|
||||
}
|
||||
|
||||
remove(accessor: RadioControlValueAccessor) {
|
||||
var indexToRemove = -1;
|
||||
for (var i = 0; i < this._accessors.length; ++i) {
|
||||
if (this._accessors[i][1] === accessor) {
|
||||
indexToRemove = i;
|
||||
}
|
||||
}
|
||||
ListWrapper.removeAt(this._accessors, indexToRemove);
|
||||
}
|
||||
|
||||
select(accessor: RadioControlValueAccessor) {
|
||||
this._accessors.forEach((c) => {
|
||||
if (c[0].control.root === accessor._control.control.root && c[1] !== accessor) {
|
||||
c[1].fireUncheck();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The value provided by the forms API for radio buttons.
|
||||
*/
|
||||
export class RadioButtonState {
|
||||
constructor(public checked: boolean, public value: string) {}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The accessor for writing a radio control value and listening to changes that is used by the
|
||||
* {@link NgModel}, {@link NgFormControl}, and {@link NgControlName} directives.
|
||||
*
|
||||
* ### Example
|
||||
* ```
|
||||
* @Component({
|
||||
* template: `
|
||||
* <input type="radio" name="food" [(ngModel)]="foodChicken">
|
||||
* <input type="radio" name="food" [(ngModel)]="foodFish">
|
||||
* `
|
||||
* })
|
||||
* class FoodCmp {
|
||||
* foodChicken = new RadioButtonState(true, "chicken");
|
||||
* foodFish = new RadioButtonState(false, "fish");
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
@Directive({
|
||||
selector:
|
||||
'input[type=radio][ngControl],input[type=radio][ngFormControl],input[type=radio][ngModel]',
|
||||
host: {'(change)': 'onChange()', '(blur)': 'onTouched()'},
|
||||
providers: [RADIO_VALUE_ACCESSOR]
|
||||
})
|
||||
export class RadioControlValueAccessor implements ControlValueAccessor,
|
||||
OnDestroy, OnInit {
|
||||
_state: RadioButtonState;
|
||||
_control: NgControl;
|
||||
@Input() name: string;
|
||||
_fn: Function;
|
||||
onChange = () => {};
|
||||
onTouched = () => {};
|
||||
|
||||
constructor(private _renderer: Renderer, private _elementRef: ElementRef,
|
||||
private _registry: RadioControlRegistry, private _injector: Injector) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this._control = this._injector.get(NgControl);
|
||||
this._registry.add(this._control, this);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void { this._registry.remove(this); }
|
||||
|
||||
writeValue(value: any): void {
|
||||
this._state = value;
|
||||
if (isPresent(value) && value.checked) {
|
||||
this._renderer.setElementProperty(this._elementRef.nativeElement, 'checked', true);
|
||||
}
|
||||
}
|
||||
|
||||
registerOnChange(fn: (_: any) => {}): void {
|
||||
this._fn = fn;
|
||||
this.onChange = () => {
|
||||
fn(new RadioButtonState(true, this._state.value));
|
||||
this._registry.select(this);
|
||||
};
|
||||
}
|
||||
|
||||
fireUncheck(): void { this._fn(new RadioButtonState(false, this._state.value)); }
|
||||
|
||||
registerOnTouched(fn: () => {}): void { this.onTouched = fn; }
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||
import {isBlank, isPresent, looseIdentical} from 'angular2/src/facade/lang';
|
||||
import {isBlank, isPresent, looseIdentical, hasConstructor} from 'angular2/src/facade/lang';
|
||||
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
||||
|
||||
import {ControlContainer} from './control_container';
|
||||
@ -13,6 +13,7 @@ import {DefaultValueAccessor} from './default_value_accessor';
|
||||
import {NumberValueAccessor} from './number_value_accessor';
|
||||
import {CheckboxControlValueAccessor} from './checkbox_value_accessor';
|
||||
import {SelectControlValueAccessor} from './select_control_value_accessor';
|
||||
import {RadioControlValueAccessor} from './radio_control_value_accessor';
|
||||
import {normalizeValidator} from './normalize_validator';
|
||||
|
||||
|
||||
@ -81,11 +82,13 @@ export function selectValueAccessor(dir: NgControl,
|
||||
var builtinAccessor;
|
||||
var customAccessor;
|
||||
valueAccessors.forEach(v => {
|
||||
if (v instanceof DefaultValueAccessor) {
|
||||
if (hasConstructor(v, DefaultValueAccessor)) {
|
||||
defaultAccessor = v;
|
||||
|
||||
} else if (v instanceof CheckboxControlValueAccessor || v instanceof NumberValueAccessor ||
|
||||
v instanceof SelectControlValueAccessor) {
|
||||
} else if (hasConstructor(v, CheckboxControlValueAccessor) ||
|
||||
hasConstructor(v, NumberValueAccessor) ||
|
||||
hasConstructor(v, SelectControlValueAccessor) ||
|
||||
hasConstructor(v, RadioControlValueAccessor)) {
|
||||
if (isPresent(builtinAccessor))
|
||||
_throwError(dir, "More than one built-in value accessor matches");
|
||||
builtinAccessor = v;
|
||||
|
@ -105,22 +105,4 @@ export class FormBuilder {
|
||||
return this.control(controlConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shorthand set of providers used for building Angular forms.
|
||||
*
|
||||
* ### Example
|
||||
*
|
||||
* ```typescript
|
||||
* bootstrap(MyApp, [FORM_PROVIDERS]);
|
||||
* ```
|
||||
*/
|
||||
export const FORM_PROVIDERS: Type[] = CONST_EXPR([FormBuilder]);
|
||||
|
||||
/**
|
||||
* See {@link FORM_PROVIDERS} instead.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
export const FORM_BINDINGS = FORM_PROVIDERS;
|
||||
}
|
@ -208,6 +208,16 @@ export abstract class AbstractControl {
|
||||
return isPresent(this.getError(errorCode, path));
|
||||
}
|
||||
|
||||
get root(): AbstractControl {
|
||||
let x: AbstractControl = this;
|
||||
|
||||
while (isPresent(x._parent)) {
|
||||
x = x._parent;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
_updateControlsErrors(): void {
|
||||
this._status = this._calculateStatus();
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {isBlank, isPresent, CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
import {isBlank, isPresent, CONST_EXPR, isString} from 'angular2/src/facade/lang';
|
||||
import {PromiseWrapper} from 'angular2/src/facade/promise';
|
||||
import {ObservableWrapper} from 'angular2/src/facade/async';
|
||||
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||
@ -44,7 +44,9 @@ export class Validators {
|
||||
* Validator that requires controls to have a non-empty value.
|
||||
*/
|
||||
static required(control: modelModule.Control): {[key: string]: boolean} {
|
||||
return isBlank(control.value) || control.value == "" ? {"required": true} : null;
|
||||
return isBlank(control.value) || (isString(control.value) && control.value == "") ?
|
||||
{"required": true} :
|
||||
null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,6 +81,7 @@ export class AsyncPipe implements PipeTransform, OnDestroy {
|
||||
if (isPresent(obj)) {
|
||||
this._subscribe(obj);
|
||||
}
|
||||
this._latestReturnedValue = this._latestValue;
|
||||
return this._latestValue;
|
||||
}
|
||||
|
||||
|
@ -73,10 +73,13 @@ const $LT = 60;
|
||||
const $EQ = 61;
|
||||
const $GT = 62;
|
||||
const $QUESTION = 63;
|
||||
const $A = 65;
|
||||
const $Z = 90;
|
||||
const $LBRACKET = 91;
|
||||
const $RBRACKET = 93;
|
||||
const $A = 65;
|
||||
const $F = 70;
|
||||
const $X = 88;
|
||||
const $Z = 90;
|
||||
|
||||
const $a = 97;
|
||||
const $f = 102;
|
||||
const $z = 122;
|
||||
@ -102,7 +105,6 @@ class ControlFlowError {
|
||||
// See http://www.w3.org/TR/html51/syntax.html#writing
|
||||
class _HtmlTokenizer {
|
||||
private input: string;
|
||||
private inputLowercase: string;
|
||||
private length: number;
|
||||
// Note: this is always lowercase!
|
||||
private peek: number = -1;
|
||||
@ -117,7 +119,6 @@ class _HtmlTokenizer {
|
||||
|
||||
constructor(private file: ParseSourceFile) {
|
||||
this.input = file.content;
|
||||
this.inputLowercase = file.content.toLowerCase();
|
||||
this.length = file.content.length;
|
||||
this._advance();
|
||||
}
|
||||
@ -133,16 +134,16 @@ class _HtmlTokenizer {
|
||||
while (this.peek !== $EOF) {
|
||||
var start = this._getLocation();
|
||||
try {
|
||||
if (this._attemptChar($LT)) {
|
||||
if (this._attemptChar($BANG)) {
|
||||
if (this._attemptChar($LBRACKET)) {
|
||||
if (this._attemptCharCode($LT)) {
|
||||
if (this._attemptCharCode($BANG)) {
|
||||
if (this._attemptCharCode($LBRACKET)) {
|
||||
this._consumeCdata(start);
|
||||
} else if (this._attemptChar($MINUS)) {
|
||||
} else if (this._attemptCharCode($MINUS)) {
|
||||
this._consumeComment(start);
|
||||
} else {
|
||||
this._consumeDocType(start);
|
||||
}
|
||||
} else if (this._attemptChar($SLASH)) {
|
||||
} else if (this._attemptCharCode($SLASH)) {
|
||||
this._consumeTagClose(start);
|
||||
} else {
|
||||
this._consumeTagOpen(start);
|
||||
@ -205,11 +206,10 @@ class _HtmlTokenizer {
|
||||
this.column++;
|
||||
}
|
||||
this.index++;
|
||||
this.peek = this.index >= this.length ? $EOF : StringWrapper.charCodeAt(this.inputLowercase,
|
||||
this.index);
|
||||
this.peek = this.index >= this.length ? $EOF : StringWrapper.charCodeAt(this.input, this.index);
|
||||
}
|
||||
|
||||
private _attemptChar(charCode: number): boolean {
|
||||
private _attemptCharCode(charCode: number): boolean {
|
||||
if (this.peek === charCode) {
|
||||
this._advance();
|
||||
return true;
|
||||
@ -217,38 +217,55 @@ class _HtmlTokenizer {
|
||||
return false;
|
||||
}
|
||||
|
||||
private _requireChar(charCode: number) {
|
||||
private _attemptCharCodeCaseInsensitive(charCode: number): boolean {
|
||||
if (compareCharCodeCaseInsensitive(this.peek, charCode)) {
|
||||
this._advance();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private _requireCharCode(charCode: number) {
|
||||
var location = this._getLocation();
|
||||
if (!this._attemptChar(charCode)) {
|
||||
if (!this._attemptCharCode(charCode)) {
|
||||
throw this._createError(unexpectedCharacterErrorMsg(this.peek), location);
|
||||
}
|
||||
}
|
||||
|
||||
private _attemptChars(chars: string): boolean {
|
||||
private _attemptStr(chars: string): boolean {
|
||||
for (var i = 0; i < chars.length; i++) {
|
||||
if (!this._attemptChar(StringWrapper.charCodeAt(chars, i))) {
|
||||
if (!this._attemptCharCode(StringWrapper.charCodeAt(chars, i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private _requireChars(chars: string) {
|
||||
private _attemptStrCaseInsensitive(chars: string): boolean {
|
||||
for (var i = 0; i < chars.length; i++) {
|
||||
if (!this._attemptCharCodeCaseInsensitive(StringWrapper.charCodeAt(chars, i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private _requireStr(chars: string) {
|
||||
var location = this._getLocation();
|
||||
if (!this._attemptChars(chars)) {
|
||||
if (!this._attemptStr(chars)) {
|
||||
throw this._createError(unexpectedCharacterErrorMsg(this.peek), location);
|
||||
}
|
||||
}
|
||||
|
||||
private _attemptUntilFn(predicate: Function) {
|
||||
private _attemptCharCodeUntilFn(predicate: Function) {
|
||||
while (!predicate(this.peek)) {
|
||||
this._advance();
|
||||
}
|
||||
}
|
||||
|
||||
private _requireUntilFn(predicate: Function, len: number) {
|
||||
private _requireCharCodeUntilFn(predicate: Function, len: number) {
|
||||
var start = this._getLocation();
|
||||
this._attemptUntilFn(predicate);
|
||||
this._attemptCharCodeUntilFn(predicate);
|
||||
if (this.index - start.offset < len) {
|
||||
throw this._createError(unexpectedCharacterErrorMsg(this.peek), start);
|
||||
}
|
||||
@ -273,10 +290,10 @@ class _HtmlTokenizer {
|
||||
private _decodeEntity(): string {
|
||||
var start = this._getLocation();
|
||||
this._advance();
|
||||
if (this._attemptChar($HASH)) {
|
||||
let isHex = this._attemptChar($x);
|
||||
if (this._attemptCharCode($HASH)) {
|
||||
let isHex = this._attemptCharCode($x) || this._attemptCharCode($X);
|
||||
let numberStart = this._getLocation().offset;
|
||||
this._attemptUntilFn(isDigitEntityEnd);
|
||||
this._attemptCharCodeUntilFn(isDigitEntityEnd);
|
||||
if (this.peek != $SEMICOLON) {
|
||||
throw this._createError(unexpectedCharacterErrorMsg(this.peek), this._getLocation());
|
||||
}
|
||||
@ -291,7 +308,7 @@ class _HtmlTokenizer {
|
||||
}
|
||||
} else {
|
||||
let startPosition = this._savePosition();
|
||||
this._attemptUntilFn(isNamedEntityEnd);
|
||||
this._attemptCharCodeUntilFn(isNamedEntityEnd);
|
||||
if (this.peek != $SEMICOLON) {
|
||||
this._restorePosition(startPosition);
|
||||
return '&';
|
||||
@ -315,7 +332,7 @@ class _HtmlTokenizer {
|
||||
var parts = [];
|
||||
while (true) {
|
||||
tagCloseStart = this._getLocation();
|
||||
if (this._attemptChar(firstCharOfEnd) && attemptEndRest()) {
|
||||
if (this._attemptCharCode(firstCharOfEnd) && attemptEndRest()) {
|
||||
break;
|
||||
}
|
||||
if (this.index > tagCloseStart.offset) {
|
||||
@ -330,18 +347,18 @@ class _HtmlTokenizer {
|
||||
|
||||
private _consumeComment(start: ParseLocation) {
|
||||
this._beginToken(HtmlTokenType.COMMENT_START, start);
|
||||
this._requireChar($MINUS);
|
||||
this._requireCharCode($MINUS);
|
||||
this._endToken([]);
|
||||
var textToken = this._consumeRawText(false, $MINUS, () => this._attemptChars('->'));
|
||||
var textToken = this._consumeRawText(false, $MINUS, () => this._attemptStr('->'));
|
||||
this._beginToken(HtmlTokenType.COMMENT_END, textToken.sourceSpan.end);
|
||||
this._endToken([]);
|
||||
}
|
||||
|
||||
private _consumeCdata(start: ParseLocation) {
|
||||
this._beginToken(HtmlTokenType.CDATA_START, start);
|
||||
this._requireChars('cdata[');
|
||||
this._requireStr('CDATA[');
|
||||
this._endToken([]);
|
||||
var textToken = this._consumeRawText(false, $RBRACKET, () => this._attemptChars(']>'));
|
||||
var textToken = this._consumeRawText(false, $RBRACKET, () => this._attemptStr(']>'));
|
||||
this._beginToken(HtmlTokenType.CDATA_END, textToken.sourceSpan.end);
|
||||
this._endToken([]);
|
||||
}
|
||||
@ -367,7 +384,7 @@ class _HtmlTokenizer {
|
||||
} else {
|
||||
nameStart = nameOrPrefixStart;
|
||||
}
|
||||
this._requireUntilFn(isNameEnd, this.index === nameStart ? 1 : 0);
|
||||
this._requireCharCodeUntilFn(isNameEnd, this.index === nameStart ? 1 : 0);
|
||||
var name = this.input.substring(nameStart, this.index);
|
||||
return [prefix, name];
|
||||
}
|
||||
@ -381,16 +398,16 @@ class _HtmlTokenizer {
|
||||
}
|
||||
var nameStart = this.index;
|
||||
this._consumeTagOpenStart(start);
|
||||
lowercaseTagName = this.inputLowercase.substring(nameStart, this.index);
|
||||
this._attemptUntilFn(isNotWhitespace);
|
||||
lowercaseTagName = this.input.substring(nameStart, this.index).toLowerCase();
|
||||
this._attemptCharCodeUntilFn(isNotWhitespace);
|
||||
while (this.peek !== $SLASH && this.peek !== $GT) {
|
||||
this._consumeAttributeName();
|
||||
this._attemptUntilFn(isNotWhitespace);
|
||||
if (this._attemptChar($EQ)) {
|
||||
this._attemptUntilFn(isNotWhitespace);
|
||||
this._attemptCharCodeUntilFn(isNotWhitespace);
|
||||
if (this._attemptCharCode($EQ)) {
|
||||
this._attemptCharCodeUntilFn(isNotWhitespace);
|
||||
this._consumeAttributeValue();
|
||||
}
|
||||
this._attemptUntilFn(isNotWhitespace);
|
||||
this._attemptCharCodeUntilFn(isNotWhitespace);
|
||||
}
|
||||
this._consumeTagOpenEnd();
|
||||
} catch (e) {
|
||||
@ -416,11 +433,11 @@ class _HtmlTokenizer {
|
||||
|
||||
private _consumeRawTextWithTagClose(lowercaseTagName: string, decodeEntities: boolean) {
|
||||
var textToken = this._consumeRawText(decodeEntities, $LT, () => {
|
||||
if (!this._attemptChar($SLASH)) return false;
|
||||
this._attemptUntilFn(isNotWhitespace);
|
||||
if (!this._attemptChars(lowercaseTagName)) return false;
|
||||
this._attemptUntilFn(isNotWhitespace);
|
||||
if (!this._attemptChar($GT)) return false;
|
||||
if (!this._attemptCharCode($SLASH)) return false;
|
||||
this._attemptCharCodeUntilFn(isNotWhitespace);
|
||||
if (!this._attemptStrCaseInsensitive(lowercaseTagName)) return false;
|
||||
this._attemptCharCodeUntilFn(isNotWhitespace);
|
||||
if (!this._attemptCharCode($GT)) return false;
|
||||
return true;
|
||||
});
|
||||
this._beginToken(HtmlTokenType.TAG_CLOSE, textToken.sourceSpan.end);
|
||||
@ -453,27 +470,27 @@ class _HtmlTokenizer {
|
||||
this._advance();
|
||||
} else {
|
||||
var valueStart = this.index;
|
||||
this._requireUntilFn(isNameEnd, 1);
|
||||
this._requireCharCodeUntilFn(isNameEnd, 1);
|
||||
value = this.input.substring(valueStart, this.index);
|
||||
}
|
||||
this._endToken([this._processCarriageReturns(value)]);
|
||||
}
|
||||
|
||||
private _consumeTagOpenEnd() {
|
||||
var tokenType =
|
||||
this._attemptChar($SLASH) ? HtmlTokenType.TAG_OPEN_END_VOID : HtmlTokenType.TAG_OPEN_END;
|
||||
var tokenType = this._attemptCharCode($SLASH) ? HtmlTokenType.TAG_OPEN_END_VOID :
|
||||
HtmlTokenType.TAG_OPEN_END;
|
||||
this._beginToken(tokenType);
|
||||
this._requireChar($GT);
|
||||
this._requireCharCode($GT);
|
||||
this._endToken([]);
|
||||
}
|
||||
|
||||
private _consumeTagClose(start: ParseLocation) {
|
||||
this._beginToken(HtmlTokenType.TAG_CLOSE, start);
|
||||
this._attemptUntilFn(isNotWhitespace);
|
||||
this._attemptCharCodeUntilFn(isNotWhitespace);
|
||||
var prefixAndName;
|
||||
prefixAndName = this._consumePrefixAndName();
|
||||
this._attemptUntilFn(isNotWhitespace);
|
||||
this._requireChar($GT);
|
||||
this._attemptCharCodeUntilFn(isNotWhitespace);
|
||||
this._requireCharCode($GT);
|
||||
this._endToken(prefixAndName);
|
||||
}
|
||||
|
||||
@ -534,11 +551,19 @@ function isTextEnd(code: number): boolean {
|
||||
}
|
||||
|
||||
function isAsciiLetter(code: number): boolean {
|
||||
return code >= $a && code <= $z;
|
||||
return code >= $a && code <= $z || code >= $A && code <= $Z;
|
||||
}
|
||||
|
||||
function isAsciiHexDigit(code: number): boolean {
|
||||
return code >= $a && code <= $f || code >= $0 && code <= $9;
|
||||
return code >= $a && code <= $f || code >= $A && code <= $F || code >= $0 && code <= $9;
|
||||
}
|
||||
|
||||
function compareCharCodeCaseInsensitive(code1: number, code2: number): boolean {
|
||||
return toUpperCaseCharCode(code1) == toUpperCaseCharCode(code2);
|
||||
}
|
||||
|
||||
function toUpperCaseCharCode(code: number): number {
|
||||
return code >= $a && code <= $z ? code - $a + $A : code;
|
||||
}
|
||||
|
||||
function mergeTextTokens(srcTokens: HtmlToken[]): HtmlToken[] {
|
||||
|
@ -124,7 +124,7 @@ export class TemplateCompiler {
|
||||
var hostMeta: CompileDirectiveMetadata =
|
||||
createHostComponentMeta(compMeta.type, compMeta.selector);
|
||||
|
||||
this._compileComponentRuntime(hostCacheKey, hostMeta, [compMeta], [], new Set());
|
||||
this._compileComponentRuntime(hostCacheKey, hostMeta, [compMeta], [], []);
|
||||
}
|
||||
return this._compiledTemplateDone.get(hostCacheKey)
|
||||
.then((compiledTemplate: CompiledTemplate) =>
|
||||
@ -172,7 +172,7 @@ export class TemplateCompiler {
|
||||
private _compileComponentRuntime(cacheKey: any, compMeta: CompileDirectiveMetadata,
|
||||
viewDirectives: CompileDirectiveMetadata[],
|
||||
pipes: CompilePipeMetadata[],
|
||||
compilingComponentCacheKeys: Set<any>): CompiledTemplate {
|
||||
compilingComponentsPath: any[]): CompiledTemplate {
|
||||
let uniqViewDirectives = <CompileDirectiveMetadata[]>removeDuplicates(viewDirectives);
|
||||
let uniqViewPipes = <CompilePipeMetadata[]>removeDuplicates(pipes);
|
||||
var compiledTemplate = this._compiledTemplateCache.get(cacheKey);
|
||||
@ -180,7 +180,6 @@ export class TemplateCompiler {
|
||||
if (isBlank(compiledTemplate)) {
|
||||
compiledTemplate = new CompiledTemplate();
|
||||
this._compiledTemplateCache.set(cacheKey, compiledTemplate);
|
||||
compilingComponentCacheKeys.add(cacheKey);
|
||||
done = PromiseWrapper
|
||||
.all([<any>this._styleCompiler.compileComponentRuntime(compMeta.template)].concat(
|
||||
uniqViewDirectives.map(dirMeta => this.normalizeDirectiveMetadata(dirMeta))))
|
||||
@ -195,14 +194,13 @@ export class TemplateCompiler {
|
||||
var usedDirectives = DirectiveCollector.findUsedDirectives(parsedTemplate);
|
||||
usedDirectives.components.forEach(
|
||||
component => this._compileNestedComponentRuntime(
|
||||
component, compilingComponentCacheKeys, childPromises));
|
||||
component, compilingComponentsPath, childPromises));
|
||||
return PromiseWrapper.all(childPromises)
|
||||
.then((_) => {
|
||||
var filteredPipes = filterPipes(parsedTemplate, uniqViewPipes);
|
||||
compiledTemplate.init(this._createViewFactoryRuntime(
|
||||
compMeta, parsedTemplate, usedDirectives.directives, styles,
|
||||
filteredPipes));
|
||||
SetWrapper.delete(compilingComponentCacheKeys, cacheKey);
|
||||
return compiledTemplate;
|
||||
});
|
||||
});
|
||||
@ -212,16 +210,19 @@ export class TemplateCompiler {
|
||||
}
|
||||
|
||||
private _compileNestedComponentRuntime(childComponentDir: CompileDirectiveMetadata,
|
||||
compilingComponentCacheKeys: Set<Type>,
|
||||
parentCompilingComponentsPath: any[],
|
||||
childPromises: Promise<any>[]) {
|
||||
var compilingComponentsPath = ListWrapper.clone(parentCompilingComponentsPath);
|
||||
|
||||
var childCacheKey = childComponentDir.type.runtime;
|
||||
var childViewDirectives: CompileDirectiveMetadata[] =
|
||||
this._runtimeMetadataResolver.getViewDirectivesMetadata(childComponentDir.type.runtime);
|
||||
var childViewPipes: CompilePipeMetadata[] =
|
||||
this._runtimeMetadataResolver.getViewPipesMetadata(childComponentDir.type.runtime);
|
||||
var childIsRecursive = SetWrapper.has(compilingComponentCacheKeys, childCacheKey);
|
||||
var childIsRecursive = ListWrapper.contains(compilingComponentsPath, childCacheKey);
|
||||
compilingComponentsPath.push(childCacheKey);
|
||||
this._compileComponentRuntime(childCacheKey, childComponentDir, childViewDirectives,
|
||||
childViewPipes, compilingComponentCacheKeys);
|
||||
childViewPipes, compilingComponentsPath);
|
||||
if (!childIsRecursive) {
|
||||
// Only wait for a child if it is not a cycle
|
||||
childPromises.push(this._compiledTemplateDone.get(childCacheKey));
|
||||
|
@ -112,6 +112,10 @@ class TemplatePreparseVisitor implements HtmlAstVisitor {
|
||||
case PreparsedElementType.STYLESHEET:
|
||||
this.styleUrls.push(preparsedElement.hrefAttr);
|
||||
break;
|
||||
default:
|
||||
// DDC reports this as error. See:
|
||||
// https://github.com/dart-lang/dev_compiler/issues/428
|
||||
break;
|
||||
}
|
||||
if (preparsedElement.nonBindable) {
|
||||
this.ngNonBindableStackCount++;
|
||||
|
@ -52,8 +52,8 @@ import {splitAtColon} from './util';
|
||||
// Group 3 = "on-"
|
||||
// Group 4 = "bindon-"
|
||||
// Group 5 = the identifier after "bind-", "var-/#", or "on-"
|
||||
// Group 6 = identifer inside [()]
|
||||
// Group 7 = identifer inside []
|
||||
// Group 6 = identifier inside [()]
|
||||
// Group 7 = identifier inside []
|
||||
// Group 8 = identifier inside ()
|
||||
var BIND_NAME_REGEXP =
|
||||
/^(?:(?:(?:(bind-)|(var-|#)|(on-)|(bindon-))(.+))|\[\(([^\)]+)\)\]|\[([^\]]+)\]|\(([^\)]+)\))$/g;
|
||||
@ -433,8 +433,9 @@ class TemplateParseVisitor implements HtmlAstVisitor {
|
||||
var parts = splitAtColon(name, [null, name]);
|
||||
var target = parts[0];
|
||||
var eventName = parts[1];
|
||||
targetEvents.push(new BoundEventAst(eventName, target,
|
||||
this._parseAction(expression, sourceSpan), sourceSpan));
|
||||
var ast = this._parseAction(expression, sourceSpan);
|
||||
targetMatchableAttrs.push([name, ast.source]);
|
||||
targetEvents.push(new BoundEventAst(eventName, target, ast, sourceSpan));
|
||||
// Don't detect directives for event names for now,
|
||||
// so don't add the event name to the matchableAttrs
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ interface ViewFactory<EXPRESSION, STATEMENT> {
|
||||
|
||||
createElementEventListener(renderer: EXPRESSION, view: EXPRESSION, boundElementIndex: number,
|
||||
renderNode: EXPRESSION, eventAst: BoundEventAst,
|
||||
targetStatements: STATEMENT[]);
|
||||
targetStatements: STATEMENT[]): EXPRESSION;
|
||||
|
||||
setElementAttribute(renderer: EXPRESSION, renderNode: EXPRESSION, attrName: string,
|
||||
attrValue: string, targetStatements: STATEMENT[]);
|
||||
@ -201,9 +201,11 @@ class CodeGenViewFactory implements ViewFactory<Expression, Statement> {
|
||||
createElementEventListener(renderer: Expression, appView: Expression, boundElementIndex: number,
|
||||
renderNode: Expression, eventAst: BoundEventAst,
|
||||
targetStatements: Statement[]) {
|
||||
var disposableVar = this._nextDisposableVar();
|
||||
var eventHandlerExpr = codeGenEventHandler(appView, boundElementIndex, eventAst.fullName);
|
||||
targetStatements.push(new Statement(
|
||||
`${renderer.expression}.listen(${renderNode.expression}, ${escapeValue(eventAst.name)}, ${eventHandlerExpr});`));
|
||||
`var ${disposableVar} = ${renderer.expression}.listen(${renderNode.expression}, ${escapeValue(eventAst.name)}, ${eventHandlerExpr});`));
|
||||
return new Expression(disposableVar);
|
||||
}
|
||||
|
||||
setElementAttribute(renderer: Expression, renderNode: Expression, attrName: string,
|
||||
@ -345,9 +347,11 @@ class RuntimeViewFactory implements ViewFactory<any, any> {
|
||||
}
|
||||
|
||||
createElementEventListener(renderer: Renderer, appView: AppView, boundElementIndex: number,
|
||||
renderNode: any, eventAst: BoundEventAst, targetStatements: any[]) {
|
||||
renderer.listen(renderNode, eventAst.name, (event) => appView.triggerEventHandlers(
|
||||
eventAst.fullName, event, boundElementIndex));
|
||||
renderNode: any, eventAst: BoundEventAst,
|
||||
targetStatements: any[]): any {
|
||||
return renderer.listen(
|
||||
renderNode, eventAst.name,
|
||||
(event) => appView.triggerEventHandlers(eventAst.fullName, event, boundElementIndex));
|
||||
}
|
||||
|
||||
setElementAttribute(renderer: Renderer, renderNode: any, attrName: string, attrValue: string,
|
||||
@ -520,14 +524,16 @@ class ViewBuilderVisitor<EXPRESSION, STATEMENT> implements TemplateAstVisitor {
|
||||
var protoEl = this.protoView.protoElements[elementIndex];
|
||||
|
||||
protoEl.renderEvents.forEach((eventAst) => {
|
||||
var disposable;
|
||||
if (isPresent(eventAst.target)) {
|
||||
var disposable = this.factory.createGlobalEventListener(
|
||||
disposable = this.factory.createGlobalEventListener(
|
||||
this.renderer, this.view, protoEl.boundElementIndex, eventAst, this.renderStmts);
|
||||
this.appDisposables.push(disposable);
|
||||
} else {
|
||||
this.factory.createElementEventListener(this.renderer, this.view, protoEl.boundElementIndex,
|
||||
renderNode, eventAst, this.renderStmts);
|
||||
disposable = this.factory.createElementEventListener(this.renderer, this.view,
|
||||
protoEl.boundElementIndex, renderNode,
|
||||
eventAst, this.renderStmts);
|
||||
}
|
||||
this.appDisposables.push(disposable);
|
||||
});
|
||||
for (var i = 0; i < protoEl.attrNameAndValues.length; i++) {
|
||||
var attrName = protoEl.attrNameAndValues[i][0];
|
||||
|
@ -15,7 +15,6 @@ import {ResolvedMetadataCache} from 'angular2/src/core/linker/resolved_metadata_
|
||||
import {AppViewManager} from './linker/view_manager';
|
||||
import {AppViewManager_} from "./linker/view_manager";
|
||||
import {ViewResolver} from './linker/view_resolver';
|
||||
import {AppViewListener} from './linker/view_listener';
|
||||
import {DirectiveResolver} from './linker/directive_resolver';
|
||||
import {PipeResolver} from './linker/pipe_resolver';
|
||||
import {Compiler} from './linker/compiler';
|
||||
@ -32,7 +31,6 @@ export const APPLICATION_COMMON_PROVIDERS: Array<Type | Provider | any[]> = CONS
|
||||
APP_ID_RANDOM_PROVIDER,
|
||||
ResolvedMetadataCache,
|
||||
new Provider(AppViewManager, {useClass: AppViewManager_}),
|
||||
AppViewListener,
|
||||
ViewResolver,
|
||||
new Provider(IterableDiffers, {useValue: defaultIterableDiffers}),
|
||||
new Provider(KeyValueDiffers, {useValue: defaultKeyValueDiffers}),
|
||||
|
@ -217,25 +217,36 @@ export class PlatformRef_ extends PlatformRef {
|
||||
|
||||
application(providers: Array<Type | Provider | any[]>): ApplicationRef {
|
||||
var app = this._initApp(createNgZone(), providers);
|
||||
return app;
|
||||
if (PromiseWrapper.isPromise(app)) {
|
||||
throw new BaseException(
|
||||
"Cannot use asyncronous app initializers with application. Use asyncApplication instead.");
|
||||
}
|
||||
return <ApplicationRef>app;
|
||||
}
|
||||
|
||||
asyncApplication(bindingFn: (zone: NgZone) => Promise<Array<Type | Provider | any[]>>,
|
||||
additionalProviders?: Array<Type | Provider | any[]>): Promise<ApplicationRef> {
|
||||
var zone = createNgZone();
|
||||
var completer = PromiseWrapper.completer();
|
||||
zone.run(() => {
|
||||
PromiseWrapper.then(bindingFn(zone), (providers: Array<Type | Provider | any[]>) => {
|
||||
if (isPresent(additionalProviders)) {
|
||||
providers = ListWrapper.concat(providers, additionalProviders);
|
||||
}
|
||||
completer.resolve(this._initApp(zone, providers));
|
||||
if (bindingFn === null) {
|
||||
completer.resolve(this._initApp(zone, additionalProviders));
|
||||
} else {
|
||||
zone.run(() => {
|
||||
PromiseWrapper.then(bindingFn(zone), (providers: Array<Type | Provider | any[]>) => {
|
||||
if (isPresent(additionalProviders)) {
|
||||
providers = ListWrapper.concat(providers, additionalProviders);
|
||||
}
|
||||
let promise = this._initApp(zone, providers);
|
||||
completer.resolve(promise);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
return completer.promise;
|
||||
}
|
||||
|
||||
private _initApp(zone: NgZone, providers: Array<Type | Provider | any[]>): ApplicationRef {
|
||||
private _initApp(zone: NgZone,
|
||||
providers: Array<Type | Provider | any[]>): Promise<ApplicationRef>|
|
||||
ApplicationRef {
|
||||
var injector: Injector;
|
||||
var app: ApplicationRef;
|
||||
zone.run(() => {
|
||||
@ -259,8 +270,12 @@ export class PlatformRef_ extends PlatformRef {
|
||||
});
|
||||
app = new ApplicationRef_(this, zone, injector);
|
||||
this._applications.push(app);
|
||||
_runAppInitializers(injector);
|
||||
return app;
|
||||
var promise = _runAppInitializers(injector);
|
||||
if (promise !== null) {
|
||||
return PromiseWrapper.then(promise, (_) => app);
|
||||
} else {
|
||||
return app;
|
||||
}
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
@ -273,9 +288,22 @@ export class PlatformRef_ extends PlatformRef {
|
||||
_applicationDisposed(app: ApplicationRef): void { ListWrapper.remove(this._applications, app); }
|
||||
}
|
||||
|
||||
function _runAppInitializers(injector: Injector): void {
|
||||
function _runAppInitializers(injector: Injector): Promise<any> {
|
||||
let inits: Function[] = injector.getOptional(APP_INITIALIZER);
|
||||
if (isPresent(inits)) inits.forEach(init => init());
|
||||
let promises: Promise<any>[] = [];
|
||||
if (isPresent(inits)) {
|
||||
inits.forEach(init => {
|
||||
var retVal = init();
|
||||
if (PromiseWrapper.isPromise(retVal)) {
|
||||
promises.push(retVal);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (promises.length > 0) {
|
||||
return PromiseWrapper.all(promises);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -428,11 +456,10 @@ export class ApplicationRef_ extends ApplicationRef {
|
||||
});
|
||||
return completer.promise.then(_ => {
|
||||
let c = this._injector.get(Console);
|
||||
let modeDescription =
|
||||
assertionsEnabled() ?
|
||||
"in the development mode. Call enableProdMode() to enable the production mode." :
|
||||
"in the production mode. Call enableDevMode() to enable the development mode.";
|
||||
c.log(`Angular 2 is running ${modeDescription}`);
|
||||
if (assertionsEnabled()) {
|
||||
c.log(
|
||||
"Angular 2 is running in the development mode. Call enableProdMode() to enable the production mode.");
|
||||
}
|
||||
return _;
|
||||
});
|
||||
}
|
||||
@ -485,5 +512,5 @@ export class ApplicationRef_ extends ApplicationRef {
|
||||
this._platform._applicationDisposed(this);
|
||||
}
|
||||
|
||||
get componentTypes(): any[] { return this._rootComponentTypes; }
|
||||
get componentTypes(): Type[] { return this._rootComponentTypes; }
|
||||
}
|
||||
|
@ -20,5 +20,6 @@ export {
|
||||
IterableDifferFactory,
|
||||
KeyValueDiffers,
|
||||
KeyValueDiffer,
|
||||
KeyValueDifferFactory
|
||||
KeyValueDifferFactory,
|
||||
TrackByFn
|
||||
} from './change_detection/change_detection';
|
||||
|
@ -17,7 +17,7 @@ import {Locals} from './parser/locals';
|
||||
import {ChangeDetectionStrategy, ChangeDetectorState} from './constants';
|
||||
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
|
||||
import {isObservable} from './observable_facade';
|
||||
|
||||
import {ObservableWrapper} from 'angular2/src/facade/async';
|
||||
|
||||
var _scope_check: WtfScopeFn = wtfCreateScope(`ChangeDetector#check(ascii id, bool throwOnChange)`);
|
||||
|
||||
@ -40,6 +40,7 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
||||
mode: ChangeDetectionStrategy = null;
|
||||
pipes: Pipes = null;
|
||||
propertyBindingIndex: number;
|
||||
outputSubscriptions: any[];
|
||||
|
||||
// This is an experimental feature. Works only in Dart.
|
||||
subscriptions: any[];
|
||||
@ -72,7 +73,7 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
||||
|
||||
handleEvent(eventName: string, elIndex: number, event: any): boolean {
|
||||
if (!this.hydrated()) {
|
||||
return true;
|
||||
this.throwDehydratedError(`${this.id} -> ${eventName}`);
|
||||
}
|
||||
try {
|
||||
var locals = new Map<string, any>();
|
||||
@ -129,7 +130,7 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
||||
// facilitate error reporting.
|
||||
detectChangesInRecords(throwOnChange: boolean): void {
|
||||
if (!this.hydrated()) {
|
||||
this.throwDehydratedError();
|
||||
this.throwDehydratedError(this.id);
|
||||
}
|
||||
try {
|
||||
this.detectChangesInRecordsInternal(throwOnChange);
|
||||
@ -180,6 +181,8 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
||||
this._unsubsribeFromObservables();
|
||||
}
|
||||
|
||||
this._unsubscribeFromOutputs();
|
||||
|
||||
this.dispatcher = null;
|
||||
this.context = null;
|
||||
this.locals = null;
|
||||
@ -258,6 +261,15 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
||||
}
|
||||
}
|
||||
|
||||
private _unsubscribeFromOutputs(): void {
|
||||
if (isPresent(this.outputSubscriptions)) {
|
||||
for (var i = 0; i < this.outputSubscriptions.length; ++i) {
|
||||
ObservableWrapper.dispose(this.outputSubscriptions[i]);
|
||||
this.outputSubscriptions[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is an experimental feature. Works only in Dart.
|
||||
observeValue(value: any, index: number): any {
|
||||
if (isObservable(value)) {
|
||||
@ -350,7 +362,7 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
||||
oldValue, newValue, null);
|
||||
}
|
||||
|
||||
throwDehydratedError(): void { throw new DehydratedException(); }
|
||||
throwDehydratedError(detail: string): void { throw new DehydratedException(detail); }
|
||||
|
||||
private _currentBinding(): BindingTarget {
|
||||
return this.bindingTargets[this.propertyBindingIndex];
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {IterableDiffers, IterableDifferFactory} from './differs/iterable_differs';
|
||||
import {IterableDiffers, IterableDifferFactory, TrackByFn} from './differs/iterable_differs';
|
||||
import {DefaultIterableDifferFactory} from './differs/default_iterable_differ';
|
||||
import {KeyValueDiffers, KeyValueDifferFactory} from './differs/keyvalue_differs';
|
||||
import {DefaultKeyValueDifferFactory} from './differs/default_keyvalue_differ';
|
||||
@ -37,7 +37,12 @@ export {BindingRecord, BindingTarget} from './binding_record';
|
||||
export {DirectiveIndex, DirectiveRecord} from './directive_record';
|
||||
export {DynamicChangeDetector} from './dynamic_change_detector';
|
||||
export {ChangeDetectorRef} from './change_detector_ref';
|
||||
export {IterableDiffers, IterableDiffer, IterableDifferFactory} from './differs/iterable_differs';
|
||||
export {
|
||||
IterableDiffers,
|
||||
IterableDiffer,
|
||||
IterableDifferFactory,
|
||||
TrackByFn
|
||||
} from './differs/iterable_differs';
|
||||
export {KeyValueDiffers, KeyValueDiffer, KeyValueDifferFactory} from './differs/keyvalue_differs';
|
||||
export {PipeTransform} from './pipe_transform';
|
||||
export {WrappedValue, SimpleChange} from './change_detection_util';
|
||||
|
@ -350,6 +350,7 @@ export class ChangeDetectorJITGenerator {
|
||||
var condition = `!${pipe}.pure || (${contexOrArgCheck.join(" || ")})`;
|
||||
|
||||
var check = `
|
||||
${this._genThrowOnChangeCheck(oldValue, newValue)}
|
||||
if (${this.changeDetectionUtilVarName}.looseNotIdentical(${oldValue}, ${newValue})) {
|
||||
${newValue} = ${this.changeDetectionUtilVarName}.unwrapValue(${newValue})
|
||||
${this._genChangeMarker(r)}
|
||||
@ -377,6 +378,7 @@ export class ChangeDetectorJITGenerator {
|
||||
`;
|
||||
|
||||
var check = `
|
||||
${this._genThrowOnChangeCheck(oldValue, newValue)}
|
||||
if (${this.changeDetectionUtilVarName}.looseNotIdentical(${oldValue}, ${newValue})) {
|
||||
${this._genChangeMarker(r)}
|
||||
${this._genUpdateDirectiveOrElement(r)}
|
||||
@ -409,7 +411,6 @@ export class ChangeDetectorJITGenerator {
|
||||
if (!r.lastInBinding) return "";
|
||||
|
||||
var newValue = this._names.getLocalName(r.selfIndex);
|
||||
var oldValue = this._names.getFieldName(r.selfIndex);
|
||||
var notifyDebug = this.genConfig.logBindingUpdate ? `this.logBindingUpdate(${newValue});` : "";
|
||||
|
||||
var br = r.bindingRecord;
|
||||
@ -417,14 +418,12 @@ export class ChangeDetectorJITGenerator {
|
||||
var directiveProperty =
|
||||
`${this._names.getDirectiveName(br.directiveRecord.directiveIndex)}.${br.target.name}`;
|
||||
return `
|
||||
${this._genThrowOnChangeCheck(oldValue, newValue)}
|
||||
${directiveProperty} = ${newValue};
|
||||
${notifyDebug}
|
||||
${IS_CHANGED_LOCAL} = true;
|
||||
`;
|
||||
} else {
|
||||
return `
|
||||
${this._genThrowOnChangeCheck(oldValue, newValue)}
|
||||
this.notifyDispatcher(${newValue});
|
||||
${notifyDebug}
|
||||
`;
|
||||
@ -435,7 +434,7 @@ export class ChangeDetectorJITGenerator {
|
||||
_genThrowOnChangeCheck(oldValue: string, newValue: string): string {
|
||||
if (assertionsEnabled()) {
|
||||
return `
|
||||
if(throwOnChange) {
|
||||
if (throwOnChange && !${this.changeDetectionUtilVarName}.devModeEqual(${oldValue}, ${newValue})) {
|
||||
this.throwOnChangeError(${oldValue}, ${newValue});
|
||||
}
|
||||
`;
|
||||
|
@ -4,10 +4,17 @@ import {
|
||||
isBlank,
|
||||
Type,
|
||||
StringWrapper,
|
||||
looseIdentical
|
||||
looseIdentical,
|
||||
isPrimitive
|
||||
} from 'angular2/src/facade/lang';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||
import {
|
||||
ListWrapper,
|
||||
MapWrapper,
|
||||
StringMapWrapper,
|
||||
isListLikeIterable,
|
||||
areIterablesEqual
|
||||
} from 'angular2/src/facade/collection';
|
||||
import {ProtoRecord} from './proto_record';
|
||||
import {ChangeDetectionStrategy, isDefaultChangeDetectionStrategy} from './constants';
|
||||
import {implementsOnDestroy} from './pipe_lifecycle_reflector';
|
||||
@ -214,4 +221,17 @@ export class ChangeDetectionUtil {
|
||||
}
|
||||
|
||||
static looseNotIdentical(a: any, b: any): boolean { return !looseIdentical(a, b); }
|
||||
|
||||
static devModeEqual(a: any, b: any): boolean {
|
||||
if (isListLikeIterable(a) && isListLikeIterable(b)) {
|
||||
return areIterablesEqual(a, b, ChangeDetectionUtil.devModeEqual);
|
||||
|
||||
} else if (!isListLikeIterable(a) && !isPrimitive(a) && !isListLikeIterable(b) &&
|
||||
!isPrimitive(b)) {
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return looseIdentical(a, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ export class CodegenLogicUtil {
|
||||
break;
|
||||
|
||||
case RecordType.Chain:
|
||||
rhs = 'null';
|
||||
rhs = `${getLocalName(protoRec.args[protoRec.args.length - 1])}`;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -153,6 +153,7 @@ export class CodegenLogicUtil {
|
||||
|
||||
genHydrateDirectives(directiveRecords: DirectiveRecord[]): string {
|
||||
var res = [];
|
||||
var outputCount = 0;
|
||||
for (var i = 0; i < directiveRecords.length; ++i) {
|
||||
var r = directiveRecords[i];
|
||||
var dirVarName = this._names.getDirectiveName(r.directiveIndex);
|
||||
@ -160,14 +161,24 @@ export class CodegenLogicUtil {
|
||||
if (isPresent(r.outputs)) {
|
||||
r.outputs.forEach(output => {
|
||||
var eventHandlerExpr = this._genEventHandler(r.directiveIndex.elementIndex, output[1]);
|
||||
var statementStart =
|
||||
`this.outputSubscriptions[${outputCount++}] = ${dirVarName}.${output[0]}`;
|
||||
if (IS_DART) {
|
||||
res.push(`${dirVarName}.${output[0]}.listen(${eventHandlerExpr});`);
|
||||
res.push(`${statementStart}.listen(${eventHandlerExpr});`);
|
||||
} else {
|
||||
res.push(`${dirVarName}.${output[0]}.subscribe({next: ${eventHandlerExpr}});`);
|
||||
res.push(`${statementStart}.subscribe({next: ${eventHandlerExpr}});`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (outputCount > 0) {
|
||||
var statementStart = 'this.outputSubscriptions';
|
||||
if (IS_DART) {
|
||||
res.unshift(`${statementStart} = new List(${outputCount});`);
|
||||
} else {
|
||||
res.unshift(`${statementStart} = new Array(${outputCount});`);
|
||||
}
|
||||
}
|
||||
return res.join("\n");
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,6 @@
|
||||
import {CONST} from 'angular2/src/facade/lang';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {
|
||||
isListLikeIterable,
|
||||
iterateListLike,
|
||||
ListWrapper,
|
||||
MapWrapper
|
||||
} from 'angular2/src/facade/collection';
|
||||
import {isListLikeIterable, iterateListLike, ListWrapper} from 'angular2/src/facade/collection';
|
||||
|
||||
import {
|
||||
isBlank,
|
||||
@ -17,17 +12,21 @@ import {
|
||||
} from 'angular2/src/facade/lang';
|
||||
|
||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
||||
import {IterableDiffer, IterableDifferFactory} from '../differs/iterable_differs';
|
||||
import {IterableDiffer, IterableDifferFactory, TrackByFn} from '../differs/iterable_differs';
|
||||
|
||||
@CONST()
|
||||
export class DefaultIterableDifferFactory implements IterableDifferFactory {
|
||||
supports(obj: Object): boolean { return isListLikeIterable(obj); }
|
||||
create(cdRef: ChangeDetectorRef): any { return new DefaultIterableDiffer(); }
|
||||
create(cdRef: ChangeDetectorRef, trackByFn?: TrackByFn): DefaultIterableDiffer {
|
||||
return new DefaultIterableDiffer(trackByFn);
|
||||
}
|
||||
}
|
||||
|
||||
var trackByIdentity = (index: number, item: any) => item;
|
||||
|
||||
export class DefaultIterableDiffer implements IterableDiffer {
|
||||
private _collection = null;
|
||||
private _length: number = null;
|
||||
private _collection = null;
|
||||
// Keeps track of the used records at any point in time (during & across `_check()` calls)
|
||||
private _linkedRecords: _DuplicateMap = null;
|
||||
// Keeps track of the removed records at any point in time during `_check()` calls.
|
||||
@ -41,6 +40,13 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
||||
private _movesTail: CollectionChangeRecord = null;
|
||||
private _removalsHead: CollectionChangeRecord = null;
|
||||
private _removalsTail: CollectionChangeRecord = null;
|
||||
// Keeps track of records where custom track by is the same, but item identity has changed
|
||||
private _identityChangesHead: CollectionChangeRecord = null;
|
||||
private _identityChangesTail: CollectionChangeRecord = null;
|
||||
|
||||
constructor(private _trackByFn?: TrackByFn) {
|
||||
this._trackByFn = isPresent(this._trackByFn) ? this._trackByFn : trackByIdentity;
|
||||
}
|
||||
|
||||
get collection() { return this._collection; }
|
||||
|
||||
@ -81,6 +87,13 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
||||
}
|
||||
}
|
||||
|
||||
forEachIdentityChange(fn: Function) {
|
||||
var record: CollectionChangeRecord;
|
||||
for (record = this._identityChangesHead; record !== null; record = record._nextIdentityChange) {
|
||||
fn(record);
|
||||
}
|
||||
}
|
||||
|
||||
diff(collection: any): DefaultIterableDiffer {
|
||||
if (isBlank(collection)) collection = [];
|
||||
if (!isListLikeIterable(collection)) {
|
||||
@ -104,31 +117,40 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
||||
var mayBeDirty: boolean = false;
|
||||
var index: number;
|
||||
var item;
|
||||
|
||||
var itemTrackBy;
|
||||
if (isArray(collection)) {
|
||||
var list = collection;
|
||||
this._length = collection.length;
|
||||
|
||||
for (index = 0; index < this._length; index++) {
|
||||
item = list[index];
|
||||
if (record === null || !looseIdentical(record.item, item)) {
|
||||
record = this._mismatch(record, item, index);
|
||||
itemTrackBy = this._trackByFn(index, item);
|
||||
if (record === null || !looseIdentical(record.trackById, itemTrackBy)) {
|
||||
record = this._mismatch(record, item, itemTrackBy, index);
|
||||
mayBeDirty = true;
|
||||
} else if (mayBeDirty) {
|
||||
// TODO(misko): can we limit this to duplicates only?
|
||||
record = this._verifyReinsertion(record, item, index);
|
||||
} else {
|
||||
if (mayBeDirty) {
|
||||
// TODO(misko): can we limit this to duplicates only?
|
||||
record = this._verifyReinsertion(record, item, itemTrackBy, index);
|
||||
}
|
||||
if (!looseIdentical(record.item, item)) this._addIdentityChange(record, item);
|
||||
}
|
||||
|
||||
record = record._next;
|
||||
}
|
||||
} else {
|
||||
index = 0;
|
||||
iterateListLike(collection, (item) => {
|
||||
if (record === null || !looseIdentical(record.item, item)) {
|
||||
record = this._mismatch(record, item, index);
|
||||
itemTrackBy = this._trackByFn(index, item);
|
||||
if (record === null || !looseIdentical(record.trackById, itemTrackBy)) {
|
||||
record = this._mismatch(record, item, itemTrackBy, index);
|
||||
mayBeDirty = true;
|
||||
} else if (mayBeDirty) {
|
||||
// TODO(misko): can we limit this to duplicates only?
|
||||
record = this._verifyReinsertion(record, item, index);
|
||||
} else {
|
||||
if (mayBeDirty) {
|
||||
// TODO(misko): can we limit this to duplicates only?
|
||||
record = this._verifyReinsertion(record, item, itemTrackBy, index);
|
||||
}
|
||||
if (!looseIdentical(record.item, item)) this._addIdentityChange(record, item);
|
||||
}
|
||||
record = record._next;
|
||||
index++;
|
||||
@ -141,9 +163,12 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
||||
return this.isDirty;
|
||||
}
|
||||
|
||||
// CollectionChanges is considered dirty if it has any additions, moves or removals.
|
||||
/* CollectionChanges is considered dirty if it has any additions, moves, removals, or identity
|
||||
* changes.
|
||||
*/
|
||||
get isDirty(): boolean {
|
||||
return this._additionsHead !== null || this._movesHead !== null || this._removalsHead !== null;
|
||||
return this._additionsHead !== null || this._movesHead !== null ||
|
||||
this._removalsHead !== null || this._identityChangesHead !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -174,6 +199,7 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
||||
}
|
||||
this._movesHead = this._movesTail = null;
|
||||
this._removalsHead = this._removalsTail = null;
|
||||
this._identityChangesHead = this._identityChangesTail = null;
|
||||
|
||||
// todo(vicb) when assert gets supported
|
||||
// assert(!this.isDirty);
|
||||
@ -190,7 +216,8 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
_mismatch(record: CollectionChangeRecord, item, index: number): CollectionChangeRecord {
|
||||
_mismatch(record: CollectionChangeRecord, item: any, itemTrackBy: any,
|
||||
index: number): CollectionChangeRecord {
|
||||
// The previous record after which we will append the current one.
|
||||
var previousRecord: CollectionChangeRecord;
|
||||
|
||||
@ -203,19 +230,26 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
||||
}
|
||||
|
||||
// Attempt to see if we have seen the item before.
|
||||
record = this._linkedRecords === null ? null : this._linkedRecords.get(item, index);
|
||||
record = this._linkedRecords === null ? null : this._linkedRecords.get(itemTrackBy, index);
|
||||
if (record !== null) {
|
||||
// We have seen this before, we need to move it forward in the collection.
|
||||
// But first we need to check if identity changed, so we can update in view if necessary
|
||||
if (!looseIdentical(record.item, item)) this._addIdentityChange(record, item);
|
||||
|
||||
this._moveAfter(record, previousRecord, index);
|
||||
} else {
|
||||
// Never seen it, check evicted list.
|
||||
record = this._unlinkedRecords === null ? null : this._unlinkedRecords.get(item);
|
||||
record = this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy);
|
||||
if (record !== null) {
|
||||
// It is an item which we have evicted earlier: reinsert it back into the list.
|
||||
// But first we need to check if identity changed, so we can update in view if necessary
|
||||
if (!looseIdentical(record.item, item)) this._addIdentityChange(record, item);
|
||||
|
||||
this._reinsertAfter(record, previousRecord, index);
|
||||
} else {
|
||||
// It is a new item: add it.
|
||||
record = this._addAfter(new CollectionChangeRecord(item), previousRecord, index);
|
||||
record =
|
||||
this._addAfter(new CollectionChangeRecord(item, itemTrackBy), previousRecord, index);
|
||||
}
|
||||
}
|
||||
return record;
|
||||
@ -248,9 +282,10 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
_verifyReinsertion(record: CollectionChangeRecord, item, index: number): CollectionChangeRecord {
|
||||
_verifyReinsertion(record: CollectionChangeRecord, item: any, itemTrackBy: any,
|
||||
index: number): CollectionChangeRecord {
|
||||
var reinsertRecord: CollectionChangeRecord =
|
||||
this._unlinkedRecords === null ? null : this._unlinkedRecords.get(item);
|
||||
this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy);
|
||||
if (reinsertRecord !== null) {
|
||||
record = this._reinsertAfter(reinsertRecord, record._prev, index);
|
||||
} else if (record.currentIndex != index) {
|
||||
@ -456,36 +491,41 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
||||
return record;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
var record: CollectionChangeRecord;
|
||||
|
||||
var list = [];
|
||||
for (record = this._itHead; record !== null; record = record._next) {
|
||||
list.push(record);
|
||||
/** @internal */
|
||||
_addIdentityChange(record: CollectionChangeRecord, item: any) {
|
||||
record.item = item;
|
||||
if (this._identityChangesTail === null) {
|
||||
this._identityChangesTail = this._identityChangesHead = record;
|
||||
} else {
|
||||
this._identityChangesTail = this._identityChangesTail._nextIdentityChange = record;
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
|
||||
toString(): string {
|
||||
var list = [];
|
||||
this.forEachItem((record) => list.push(record));
|
||||
|
||||
var previous = [];
|
||||
for (record = this._previousItHead; record !== null; record = record._nextPrevious) {
|
||||
previous.push(record);
|
||||
}
|
||||
this.forEachPreviousItem((record) => previous.push(record));
|
||||
|
||||
var additions = [];
|
||||
for (record = this._additionsHead; record !== null; record = record._nextAdded) {
|
||||
additions.push(record);
|
||||
}
|
||||
this.forEachAddedItem((record) => additions.push(record));
|
||||
|
||||
var moves = [];
|
||||
for (record = this._movesHead; record !== null; record = record._nextMoved) {
|
||||
moves.push(record);
|
||||
}
|
||||
this.forEachMovedItem((record) => moves.push(record));
|
||||
|
||||
var removals = [];
|
||||
for (record = this._removalsHead; record !== null; record = record._nextRemoved) {
|
||||
removals.push(record);
|
||||
}
|
||||
this.forEachRemovedItem((record) => removals.push(record));
|
||||
|
||||
var identityChanges = [];
|
||||
this.forEachIdentityChange((record) => identityChanges.push(record));
|
||||
|
||||
return "collection: " + list.join(', ') + "\n" + "previous: " + previous.join(', ') + "\n" +
|
||||
"additions: " + additions.join(', ') + "\n" + "moves: " + moves.join(', ') + "\n" +
|
||||
"removals: " + removals.join(', ') + "\n";
|
||||
"removals: " + removals.join(', ') + "\n" + "identityChanges: " +
|
||||
identityChanges.join(', ') + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -511,8 +551,11 @@ export class CollectionChangeRecord {
|
||||
_nextAdded: CollectionChangeRecord = null;
|
||||
/** @internal */
|
||||
_nextMoved: CollectionChangeRecord = null;
|
||||
/** @internal */
|
||||
_nextIdentityChange: CollectionChangeRecord = null;
|
||||
|
||||
constructor(public item: any) {}
|
||||
|
||||
constructor(public item: any, public trackById: any) {}
|
||||
|
||||
toString(): string {
|
||||
return this.previousIndex === this.currentIndex ?
|
||||
@ -550,13 +593,13 @@ class _DuplicateItemRecordList {
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a CollectionChangeRecord having CollectionChangeRecord.item == item and
|
||||
// Returns a CollectionChangeRecord having CollectionChangeRecord.trackById == trackById and
|
||||
// CollectionChangeRecord.currentIndex >= afterIndex
|
||||
get(item: any, afterIndex: number): CollectionChangeRecord {
|
||||
get(trackById: any, afterIndex: number): CollectionChangeRecord {
|
||||
var record: CollectionChangeRecord;
|
||||
for (record = this._head; record !== null; record = record._nextDup) {
|
||||
if ((afterIndex === null || afterIndex < record.currentIndex) &&
|
||||
looseIdentical(record.item, item)) {
|
||||
looseIdentical(record.trackById, trackById)) {
|
||||
return record;
|
||||
}
|
||||
}
|
||||
@ -599,7 +642,7 @@ class _DuplicateMap {
|
||||
|
||||
put(record: CollectionChangeRecord) {
|
||||
// todo(vicb) handle corner cases
|
||||
var key = getMapKey(record.item);
|
||||
var key = getMapKey(record.trackById);
|
||||
|
||||
var duplicates = this.map.get(key);
|
||||
if (!isPresent(duplicates)) {
|
||||
@ -610,17 +653,17 @@ class _DuplicateMap {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the `value` using key. Because the CollectionChangeRecord value maybe one which we
|
||||
* Retrieve the `value` using key. Because the CollectionChangeRecord value may be one which we
|
||||
* have already iterated over, we use the afterIndex to pretend it is not there.
|
||||
*
|
||||
* Use case: `[a, b, c, a, a]` if we are at index `3` which is the second `a` then asking if we
|
||||
* have any more `a`s needs to return the last `a` not the first or second.
|
||||
*/
|
||||
get(value: any, afterIndex: number = null): CollectionChangeRecord {
|
||||
var key = getMapKey(value);
|
||||
get(trackById: any, afterIndex: number = null): CollectionChangeRecord {
|
||||
var key = getMapKey(trackById);
|
||||
|
||||
var recordList = this.map.get(key);
|
||||
return isBlank(recordList) ? null : recordList.get(value, afterIndex);
|
||||
return isBlank(recordList) ? null : recordList.get(trackById, afterIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -629,7 +672,7 @@ class _DuplicateMap {
|
||||
* The list of duplicates also is removed from the map if it gets empty.
|
||||
*/
|
||||
remove(record: CollectionChangeRecord): CollectionChangeRecord {
|
||||
var key = getMapKey(record.item);
|
||||
var key = getMapKey(record.trackById);
|
||||
// todo(vicb)
|
||||
// assert(this.map.containsKey(key));
|
||||
var recordList: _DuplicateItemRecordList = this.map.get(key);
|
||||
|
@ -9,16 +9,23 @@ import {Provider, SkipSelfMetadata, OptionalMetadata, Injectable} from 'angular2
|
||||
* respond to changes in an iterable by effecting equivalent changes in the DOM.
|
||||
*/
|
||||
export interface IterableDiffer {
|
||||
diff(object: Object): any;
|
||||
diff(object: any): any;
|
||||
onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* An optional function passed into {@link NgFor} that defines how to track
|
||||
* items in an iterable (e.g. by index or id)
|
||||
*/
|
||||
export interface TrackByFn { (index: number, item: any): any; }
|
||||
|
||||
|
||||
/**
|
||||
* Provides a factory for {@link IterableDiffer}.
|
||||
*/
|
||||
export interface IterableDifferFactory {
|
||||
supports(objects: Object): boolean;
|
||||
create(cdRef: ChangeDetectorRef): IterableDiffer;
|
||||
supports(objects: any): boolean;
|
||||
create(cdRef: ChangeDetectorRef, trackByFn?: TrackByFn): IterableDiffer;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -74,7 +81,7 @@ export class IterableDiffers {
|
||||
});
|
||||
}
|
||||
|
||||
find(iterable: Object): IterableDifferFactory {
|
||||
find(iterable: any): IterableDifferFactory {
|
||||
var factory = this.factories.find(f => f.supports(iterable));
|
||||
if (isPresent(factory)) {
|
||||
return factory;
|
||||
|
@ -8,7 +8,7 @@ import {Provider, SkipSelfMetadata, OptionalMetadata, Injectable} from 'angular2
|
||||
* A differ that tracks changes made to an object over time.
|
||||
*/
|
||||
export interface KeyValueDiffer {
|
||||
diff(object: Object);
|
||||
diff(object: any);
|
||||
onDestroy();
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ export interface KeyValueDiffer {
|
||||
* Provides a factory for {@link KeyValueDiffer}.
|
||||
*/
|
||||
export interface KeyValueDifferFactory {
|
||||
supports(objects: Object): boolean;
|
||||
supports(objects: any): boolean;
|
||||
create(cdRef: ChangeDetectorRef): KeyValueDiffer;
|
||||
}
|
||||
|
||||
|
@ -114,6 +114,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
|
||||
super.observeDirective(this._getDirectiveFor(index), i);
|
||||
}
|
||||
}
|
||||
this.outputSubscriptions = [];
|
||||
for (var i = 0; i < this._directiveRecords.length; ++i) {
|
||||
var r = this._directiveRecords[i];
|
||||
if (isPresent(r.outputs)) {
|
||||
@ -122,7 +123,8 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
|
||||
<any>this._createEventHandler(r.directiveIndex.elementIndex, output[1]);
|
||||
var directive = this._getDirectiveFor(r.directiveIndex);
|
||||
var getter = reflector.getter(output[0]);
|
||||
ObservableWrapper.subscribe(getter(directive), eventHandler);
|
||||
this.outputSubscriptions.push(
|
||||
ObservableWrapper.subscribe(getter(directive), eventHandler));
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -302,7 +304,10 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
|
||||
|
||||
if (proto.shouldBeChecked()) {
|
||||
var prevValue = this._readSelf(proto, values);
|
||||
if (ChangeDetectionUtil.looseNotIdentical(prevValue, currValue)) {
|
||||
var detectedChange = throwOnChange ?
|
||||
!ChangeDetectionUtil.devModeEqual(prevValue, currValue) :
|
||||
ChangeDetectionUtil.looseNotIdentical(prevValue, currValue);
|
||||
if (detectedChange) {
|
||||
if (proto.lastInBinding) {
|
||||
var change = ChangeDetectionUtil.simpleChange(prevValue, currValue);
|
||||
if (throwOnChange) this.throwOnChangeError(prevValue, currValue);
|
||||
@ -403,7 +408,10 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
|
||||
|
||||
if (proto.shouldBeChecked()) {
|
||||
var prevValue = this._readSelf(proto, values);
|
||||
if (ChangeDetectionUtil.looseNotIdentical(prevValue, currValue)) {
|
||||
var detectedChange = throwOnChange ?
|
||||
!ChangeDetectionUtil.devModeEqual(prevValue, currValue) :
|
||||
ChangeDetectionUtil.looseNotIdentical(prevValue, currValue);
|
||||
if (detectedChange) {
|
||||
currValue = ChangeDetectionUtil.unwrapValue(currValue);
|
||||
|
||||
if (proto.lastInBinding) {
|
||||
|
@ -91,7 +91,7 @@ export class ChangeDetectionError extends WrappedException {
|
||||
* This is an internal Angular error.
|
||||
*/
|
||||
export class DehydratedException extends BaseException {
|
||||
constructor() { super('Attempt to detect changes on a dehydrated detector.'); }
|
||||
constructor(details: string) { super(`Attempt to use a dehydrated detector: ${details}`); }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -248,15 +248,12 @@ class _Scanner {
|
||||
}
|
||||
|
||||
scanCharacter(start: number, code: number): Token {
|
||||
assert(this.peek == code);
|
||||
this.advance();
|
||||
return newCharacterToken(start, code);
|
||||
}
|
||||
|
||||
|
||||
scanOperator(start: number, str: string): Token {
|
||||
assert(this.peek == StringWrapper.charCodeAt(str, 0));
|
||||
assert(SetWrapper.has(OPERATORS, str));
|
||||
this.advance();
|
||||
return newOperatorToken(start, str);
|
||||
}
|
||||
@ -274,7 +271,6 @@ class _Scanner {
|
||||
*/
|
||||
scanComplexOperator(start: number, one: string, twoCode: number, two: string, threeCode?: number,
|
||||
three?: string): Token {
|
||||
assert(this.peek == StringWrapper.charCodeAt(one, 0));
|
||||
this.advance();
|
||||
var str: string = one;
|
||||
if (this.peek == twoCode) {
|
||||
@ -285,12 +281,10 @@ class _Scanner {
|
||||
this.advance();
|
||||
str += three;
|
||||
}
|
||||
assert(SetWrapper.has(OPERATORS, str));
|
||||
return newOperatorToken(start, str);
|
||||
}
|
||||
|
||||
scanIdentifier(): Token {
|
||||
assert(isIdentifierStart(this.peek));
|
||||
var start: number = this.index;
|
||||
this.advance();
|
||||
while (isIdentifierPart(this.peek)) this.advance();
|
||||
@ -303,7 +297,6 @@ class _Scanner {
|
||||
}
|
||||
|
||||
scanNumber(start: number): Token {
|
||||
assert(isDigit(this.peek));
|
||||
var simple: boolean = (this.index === start);
|
||||
this.advance(); // Skip initial digit.
|
||||
while (true) {
|
||||
@ -329,7 +322,6 @@ class _Scanner {
|
||||
}
|
||||
|
||||
scanString(): Token {
|
||||
assert(this.peek == $SQ || this.peek == $DQ);
|
||||
var start: number = this.index;
|
||||
var quote: number = this.peek;
|
||||
this.advance(); // Skip initial quote.
|
||||
|
@ -49,7 +49,7 @@ import {
|
||||
|
||||
var _implicitReceiver = new ImplicitReceiver();
|
||||
// TODO(tbosch): Cannot make this const/final right now because of the transpiler...
|
||||
var INTERPOLATION_REGEXP = /\{\{(.*?)\}\}/g;
|
||||
var INTERPOLATION_REGEXP = /\{\{([\s\S]*?)\}\}/g;
|
||||
|
||||
class ParseException extends BaseException {
|
||||
constructor(message: string, input: string, errLocation: string, ctxLocation?: any) {
|
||||
|
@ -1,248 +0,0 @@
|
||||
import {Type, isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||
import {ListWrapper, MapWrapper, Predicate} from 'angular2/src/facade/collection';
|
||||
import {unimplemented} from 'angular2/src/facade/exceptions';
|
||||
|
||||
import {AppElement} from 'angular2/src/core/linker/element';
|
||||
import {AppView} from 'angular2/src/core/linker/view';
|
||||
import {ElementRef, ElementRef_} from 'angular2/src/core/linker/element_ref';
|
||||
|
||||
/**
|
||||
* A DebugElement contains information from the Angular compiler about an
|
||||
* element and provides access to the corresponding ElementInjector and
|
||||
* underlying DOM Element, as well as a way to query for children.
|
||||
*
|
||||
* A DebugElement can be obtained from a {@link ComponentFixture} or from an
|
||||
* {@link ElementRef} via {@link inspectElement}.
|
||||
*/
|
||||
export abstract class DebugElement {
|
||||
/**
|
||||
* Return the instance of the component associated with this element, if any.
|
||||
*/
|
||||
get componentInstance(): any { return unimplemented(); };
|
||||
|
||||
/**
|
||||
* Return the native HTML element for this DebugElement.
|
||||
*/
|
||||
get nativeElement(): any { return unimplemented(); };
|
||||
|
||||
/**
|
||||
* Return an Angular {@link ElementRef} for this element.
|
||||
*/
|
||||
get elementRef(): ElementRef { return unimplemented(); };
|
||||
|
||||
/**
|
||||
* Get the directive active for this element with the given index, if any.
|
||||
*/
|
||||
abstract getDirectiveInstance(directiveIndex: number): any;
|
||||
|
||||
/**
|
||||
* Get child DebugElements from within the Light DOM.
|
||||
*
|
||||
* @return {DebugElement[]}
|
||||
*/
|
||||
get children(): DebugElement[] { return unimplemented(); };
|
||||
|
||||
/**
|
||||
* Get the root DebugElement children of a component. Returns an empty
|
||||
* list if the current DebugElement is not a component root.
|
||||
*
|
||||
* @return {DebugElement[]}
|
||||
*/
|
||||
get componentViewChildren(): DebugElement[] { return unimplemented(); };
|
||||
|
||||
/**
|
||||
* Simulate an event from this element as if the user had caused
|
||||
* this event to fire from the page.
|
||||
*/
|
||||
abstract triggerEventHandler(eventName: string, eventObj: Event): void;
|
||||
|
||||
/**
|
||||
* Check whether the element has a directive with the given type.
|
||||
*/
|
||||
abstract hasDirective(type: Type): boolean;
|
||||
|
||||
/**
|
||||
* Inject the given type from the element injector.
|
||||
*/
|
||||
abstract inject(type: Type): any;
|
||||
|
||||
|
||||
/**
|
||||
* Read a local variable from the element (e.g. one defined with `#variable`).
|
||||
*/
|
||||
abstract getLocal(name: string): any;
|
||||
|
||||
/**
|
||||
* Return the first descendant TestElement matching the given predicate
|
||||
* and scope.
|
||||
*
|
||||
* @param {Function: boolean} predicate
|
||||
* @param {Scope} scope
|
||||
*
|
||||
* @return {DebugElement}
|
||||
*/
|
||||
query(predicate: Predicate<DebugElement>, scope: Function = Scope.all): DebugElement {
|
||||
var results = this.queryAll(predicate, scope);
|
||||
return results.length > 0 ? results[0] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return descendant TestElememts matching the given predicate
|
||||
* and scope.
|
||||
*
|
||||
* @param {Function: boolean} predicate
|
||||
* @param {Scope} scope
|
||||
*
|
||||
* @return {DebugElement[]}
|
||||
*/
|
||||
queryAll(predicate: Predicate<DebugElement>, scope: Function = Scope.all): DebugElement[] {
|
||||
var elementsInScope: any[] = scope(this);
|
||||
|
||||
return elementsInScope.filter(predicate);
|
||||
}
|
||||
}
|
||||
|
||||
export class DebugElement_ extends DebugElement {
|
||||
constructor(private _appElement: AppElement) { super(); }
|
||||
|
||||
get componentInstance(): any {
|
||||
if (!isPresent(this._appElement)) {
|
||||
return null;
|
||||
}
|
||||
return this._appElement.getComponent();
|
||||
}
|
||||
|
||||
get nativeElement(): any { return this.elementRef.nativeElement; }
|
||||
|
||||
get elementRef(): ElementRef { return this._appElement.ref; }
|
||||
|
||||
getDirectiveInstance(directiveIndex: number): any {
|
||||
return this._appElement.getDirectiveAtIndex(directiveIndex);
|
||||
}
|
||||
|
||||
get children(): DebugElement[] {
|
||||
return this._getChildElements(this._appElement.parentView, this._appElement);
|
||||
}
|
||||
|
||||
get componentViewChildren(): DebugElement[] {
|
||||
if (!isPresent(this._appElement.componentView)) {
|
||||
// The current element is not a component.
|
||||
return [];
|
||||
}
|
||||
|
||||
return this._getChildElements(this._appElement.componentView, null);
|
||||
}
|
||||
|
||||
triggerEventHandler(eventName: string, eventObj: Event): void {
|
||||
this._appElement.parentView.triggerEventHandlers(eventName, eventObj,
|
||||
this._appElement.proto.index);
|
||||
}
|
||||
|
||||
hasDirective(type: Type): boolean {
|
||||
if (!isPresent(this._appElement)) {
|
||||
return false;
|
||||
}
|
||||
return this._appElement.hasDirective(type);
|
||||
}
|
||||
|
||||
inject(type: Type): any {
|
||||
if (!isPresent(this._appElement)) {
|
||||
return null;
|
||||
}
|
||||
return this._appElement.get(type);
|
||||
}
|
||||
|
||||
getLocal(name: string): any { return this._appElement.parentView.locals.get(name); }
|
||||
|
||||
/** @internal */
|
||||
_getChildElements(view: AppView, parentAppElement: AppElement): DebugElement[] {
|
||||
var els = [];
|
||||
for (var i = 0; i < view.appElements.length; ++i) {
|
||||
var appEl = view.appElements[i];
|
||||
if (appEl.parent == parentAppElement) {
|
||||
els.push(new DebugElement_(appEl));
|
||||
|
||||
var views = appEl.nestedViews;
|
||||
if (isPresent(views)) {
|
||||
views.forEach(
|
||||
(nextView) => { els = els.concat(this._getChildElements(nextView, null)); });
|
||||
}
|
||||
}
|
||||
}
|
||||
return els;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link DebugElement} for an {@link ElementRef}.
|
||||
*
|
||||
* @param {ElementRef}: elementRef
|
||||
* @return {DebugElement}
|
||||
*/
|
||||
export function inspectElement(elementRef: ElementRef): DebugElement {
|
||||
return new DebugElement_((<ElementRef_>elementRef).internalElement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps an array of {@link DebugElement}s to an array of native DOM elements.
|
||||
*/
|
||||
export function asNativeElements(arr: DebugElement[]): any[] {
|
||||
return arr.map((debugEl) => debugEl.nativeElement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of scope functions used with {@link DebugElement}'s query functionality.
|
||||
*/
|
||||
export class Scope {
|
||||
/**
|
||||
* Scope queries to both the light dom and view of an element and its
|
||||
* children.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* {@example core/debug/ts/debug_element/debug_element.ts region='scope_all'}
|
||||
*/
|
||||
static all(debugElement: DebugElement): DebugElement[] {
|
||||
var scope = [];
|
||||
scope.push(debugElement);
|
||||
|
||||
debugElement.children.forEach(child => scope = scope.concat(Scope.all(child)));
|
||||
|
||||
debugElement.componentViewChildren.forEach(child => scope = scope.concat(Scope.all(child)));
|
||||
|
||||
return scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope queries to the light dom of an element and its children.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* {@example core/debug/ts/debug_element/debug_element.ts region='scope_light'}
|
||||
*/
|
||||
static light(debugElement: DebugElement): DebugElement[] {
|
||||
var scope = [];
|
||||
debugElement.children.forEach(child => {
|
||||
scope.push(child);
|
||||
scope = scope.concat(Scope.light(child));
|
||||
});
|
||||
return scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope queries to the view of an element of its children.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* {@example core/debug/ts/debug_element/debug_element.ts region='scope_view'}
|
||||
*/
|
||||
static view(debugElement: DebugElement): DebugElement[] {
|
||||
var scope = [];
|
||||
|
||||
debugElement.componentViewChildren.forEach(child => {
|
||||
scope.push(child);
|
||||
scope = scope.concat(Scope.light(child));
|
||||
});
|
||||
return scope;
|
||||
}
|
||||
}
|
171
modules/angular2/src/core/debug/debug_node.ts
Normal file
171
modules/angular2/src/core/debug/debug_node.ts
Normal file
@ -0,0 +1,171 @@
|
||||
import {isPresent} from 'angular2/src/facade/lang';
|
||||
import {Predicate} from 'angular2/src/facade/collection';
|
||||
import {Injector} from 'angular2/src/core/di';
|
||||
import {ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
||||
import {RenderDebugInfo} from 'angular2/src/core/render/api';
|
||||
|
||||
export class EventListener { constructor(public name: string, public callback: Function){}; }
|
||||
|
||||
export class DebugNode {
|
||||
nativeNode: any;
|
||||
listeners: EventListener[];
|
||||
parent: DebugElement;
|
||||
providerTokens: any[];
|
||||
locals: Map<string, any>;
|
||||
injector: Injector;
|
||||
componentInstance: any;
|
||||
|
||||
constructor(nativeNode: any, parent: DebugNode) {
|
||||
this.nativeNode = nativeNode;
|
||||
if (isPresent(parent) && parent instanceof DebugElement) {
|
||||
parent.addChild(this);
|
||||
} else {
|
||||
this.parent = null;
|
||||
}
|
||||
this.listeners = [];
|
||||
this.providerTokens = [];
|
||||
}
|
||||
|
||||
setDebugInfo(info: RenderDebugInfo) {
|
||||
this.injector = info.injector;
|
||||
this.providerTokens = info.providerTokens;
|
||||
this.locals = info.locals;
|
||||
this.componentInstance = info.component;
|
||||
}
|
||||
|
||||
inject(token: any): any { return this.injector.get(token); }
|
||||
|
||||
getLocal(name: string): any { return this.locals.get(name); }
|
||||
}
|
||||
|
||||
export class DebugElement extends DebugNode {
|
||||
name: string;
|
||||
properties: Map<string, any>;
|
||||
attributes: Map<string, any>;
|
||||
childNodes: DebugNode[];
|
||||
nativeElement: any;
|
||||
|
||||
constructor(nativeNode: any, parent: any) {
|
||||
super(nativeNode, parent);
|
||||
this.properties = new Map<string, any>();
|
||||
this.attributes = new Map<string, any>();
|
||||
this.childNodes = [];
|
||||
this.nativeElement = nativeNode;
|
||||
}
|
||||
|
||||
addChild(child: DebugNode) {
|
||||
if (isPresent(child)) {
|
||||
this.childNodes.push(child);
|
||||
child.parent = this;
|
||||
}
|
||||
}
|
||||
|
||||
removeChild(child: DebugNode) {
|
||||
var childIndex = this.childNodes.indexOf(child);
|
||||
if (childIndex !== -1) {
|
||||
child.parent = null;
|
||||
this.childNodes.splice(childIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
insertChildrenAfter(child: DebugNode, newChildren: DebugNode[]) {
|
||||
var siblingIndex = this.childNodes.indexOf(child);
|
||||
if (siblingIndex !== -1) {
|
||||
var previousChildren = this.childNodes.slice(0, siblingIndex + 1);
|
||||
var nextChildren = this.childNodes.slice(siblingIndex + 1);
|
||||
this.childNodes =
|
||||
ListWrapper.concat(ListWrapper.concat(previousChildren, newChildren), nextChildren);
|
||||
for (var i = 0; i < newChildren.length; ++i) {
|
||||
var newChild = newChildren[i];
|
||||
if (isPresent(newChild.parent)) {
|
||||
newChild.parent.removeChild(newChild);
|
||||
}
|
||||
newChild.parent = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query(predicate: Predicate<DebugElement>): DebugElement {
|
||||
var results = this.queryAll(predicate);
|
||||
return results.length > 0 ? results[0] : null;
|
||||
}
|
||||
|
||||
queryAll(predicate: Predicate<DebugElement>): DebugElement[] {
|
||||
var matches = [];
|
||||
_queryElementChildren(this, predicate, matches);
|
||||
return matches;
|
||||
}
|
||||
|
||||
queryAllNodes(predicate: Predicate<DebugNode>): DebugNode[] {
|
||||
var matches = [];
|
||||
_queryNodeChildren(this, predicate, matches);
|
||||
return matches;
|
||||
}
|
||||
|
||||
get children(): DebugElement[] {
|
||||
var children = [];
|
||||
this.childNodes.forEach((node) => {
|
||||
if (node instanceof DebugElement) {
|
||||
children.push(node);
|
||||
}
|
||||
});
|
||||
return children;
|
||||
}
|
||||
|
||||
triggerEventHandler(eventName: string, eventObj: Event) {
|
||||
this.listeners.forEach((listener) => {
|
||||
if (listener.name == eventName) {
|
||||
listener.callback(eventObj);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function asNativeElements(debugEls: DebugElement[]): any {
|
||||
return debugEls.map((el) => el.nativeElement);
|
||||
}
|
||||
|
||||
function _queryElementChildren(element: DebugElement, predicate: Predicate<DebugElement>,
|
||||
matches: DebugElement[]) {
|
||||
element.childNodes.forEach(node => {
|
||||
if (node instanceof DebugElement) {
|
||||
if (predicate(node)) {
|
||||
matches.push(node);
|
||||
}
|
||||
_queryElementChildren(node, predicate, matches);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function _queryNodeChildren(parentNode: DebugNode, predicate: Predicate<DebugNode>,
|
||||
matches: DebugNode[]) {
|
||||
if (parentNode instanceof DebugElement) {
|
||||
parentNode.childNodes.forEach(node => {
|
||||
if (predicate(node)) {
|
||||
matches.push(node);
|
||||
}
|
||||
if (node instanceof DebugElement) {
|
||||
_queryNodeChildren(node, predicate, matches);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Need to keep the nodes in a global Map so that multiple angular apps are supported.
|
||||
var _nativeNodeToDebugNode = new Map<any, DebugNode>();
|
||||
|
||||
export function getDebugNode(nativeNode: any): DebugNode {
|
||||
return _nativeNodeToDebugNode.get(nativeNode);
|
||||
}
|
||||
|
||||
export function getAllDebugNodes(): DebugNode[] {
|
||||
return MapWrapper.values(_nativeNodeToDebugNode);
|
||||
}
|
||||
|
||||
export function indexDebugNode(node: DebugNode) {
|
||||
_nativeNodeToDebugNode.set(node.nativeNode, node);
|
||||
}
|
||||
|
||||
export function removeDebugNodeFromIndex(node: DebugNode) {
|
||||
_nativeNodeToDebugNode.delete(node.nativeNode);
|
||||
}
|
157
modules/angular2/src/core/debug/debug_renderer.ts
Normal file
157
modules/angular2/src/core/debug/debug_renderer.ts
Normal file
@ -0,0 +1,157 @@
|
||||
import {isPresent} from 'angular2/src/facade/lang';
|
||||
import {
|
||||
Renderer,
|
||||
RootRenderer,
|
||||
RenderComponentType,
|
||||
RenderDebugInfo
|
||||
} from 'angular2/src/core/render/api';
|
||||
import {
|
||||
DebugNode,
|
||||
DebugElement,
|
||||
EventListener,
|
||||
getDebugNode,
|
||||
indexDebugNode,
|
||||
removeDebugNodeFromIndex
|
||||
} from 'angular2/src/core/debug/debug_node';
|
||||
|
||||
export class DebugDomRootRenderer implements RootRenderer {
|
||||
constructor(private _delegate: RootRenderer) {}
|
||||
|
||||
renderComponent(componentProto: RenderComponentType): Renderer {
|
||||
return new DebugDomRenderer(this, this._delegate.renderComponent(componentProto));
|
||||
}
|
||||
}
|
||||
|
||||
export class DebugDomRenderer implements Renderer {
|
||||
constructor(private _rootRenderer: DebugDomRootRenderer, private _delegate: Renderer) {}
|
||||
|
||||
renderComponent(componentType: RenderComponentType): Renderer {
|
||||
return this._rootRenderer.renderComponent(componentType);
|
||||
}
|
||||
|
||||
selectRootElement(selector: string): any {
|
||||
var nativeEl = this._delegate.selectRootElement(selector);
|
||||
var debugEl = new DebugElement(nativeEl, null);
|
||||
indexDebugNode(debugEl);
|
||||
return nativeEl;
|
||||
}
|
||||
|
||||
createElement(parentElement: any, name: string): any {
|
||||
var nativeEl = this._delegate.createElement(parentElement, name);
|
||||
var debugEl = new DebugElement(nativeEl, getDebugNode(parentElement));
|
||||
debugEl.name = name;
|
||||
indexDebugNode(debugEl);
|
||||
return nativeEl;
|
||||
}
|
||||
|
||||
createViewRoot(hostElement: any): any { return this._delegate.createViewRoot(hostElement); }
|
||||
|
||||
createTemplateAnchor(parentElement: any): any {
|
||||
var comment = this._delegate.createTemplateAnchor(parentElement);
|
||||
var debugEl = new DebugNode(comment, getDebugNode(parentElement));
|
||||
indexDebugNode(debugEl);
|
||||
return comment;
|
||||
}
|
||||
|
||||
createText(parentElement: any, value: string): any {
|
||||
var text = this._delegate.createText(parentElement, value);
|
||||
var debugEl = new DebugNode(text, getDebugNode(parentElement));
|
||||
indexDebugNode(debugEl);
|
||||
return text;
|
||||
}
|
||||
|
||||
projectNodes(parentElement: any, nodes: any[]) {
|
||||
var debugParent = getDebugNode(parentElement);
|
||||
if (isPresent(debugParent) && debugParent instanceof DebugElement) {
|
||||
nodes.forEach((node) => { debugParent.addChild(getDebugNode(node)); });
|
||||
}
|
||||
return this._delegate.projectNodes(parentElement, nodes);
|
||||
}
|
||||
|
||||
attachViewAfter(node: any, viewRootNodes: any[]) {
|
||||
var debugNode = getDebugNode(node);
|
||||
if (isPresent(debugNode)) {
|
||||
var debugParent = debugNode.parent;
|
||||
if (viewRootNodes.length > 0 && isPresent(debugParent)) {
|
||||
var debugViewRootNodes = [];
|
||||
viewRootNodes.forEach((rootNode) => debugViewRootNodes.push(getDebugNode(rootNode)));
|
||||
debugParent.insertChildrenAfter(debugNode, debugViewRootNodes);
|
||||
}
|
||||
}
|
||||
return this._delegate.attachViewAfter(node, viewRootNodes);
|
||||
}
|
||||
|
||||
detachView(viewRootNodes: any[]) {
|
||||
viewRootNodes.forEach((node) => {
|
||||
var debugNode = getDebugNode(node);
|
||||
if (isPresent(debugNode) && isPresent(debugNode.parent)) {
|
||||
debugNode.parent.removeChild(debugNode);
|
||||
}
|
||||
});
|
||||
return this._delegate.detachView(viewRootNodes);
|
||||
}
|
||||
|
||||
destroyView(hostElement: any, viewAllNodes: any[]) {
|
||||
viewAllNodes.forEach((node) => { removeDebugNodeFromIndex(getDebugNode(node)); });
|
||||
return this._delegate.destroyView(hostElement, viewAllNodes);
|
||||
}
|
||||
|
||||
listen(renderElement: any, name: string, callback: Function) {
|
||||
var debugEl = getDebugNode(renderElement);
|
||||
if (isPresent(debugEl)) {
|
||||
debugEl.listeners.push(new EventListener(name, callback));
|
||||
}
|
||||
return this._delegate.listen(renderElement, name, callback);
|
||||
}
|
||||
|
||||
listenGlobal(target: string, name: string, callback: Function): Function {
|
||||
return this._delegate.listenGlobal(target, name, callback);
|
||||
}
|
||||
|
||||
setElementProperty(renderElement: any, propertyName: string, propertyValue: any) {
|
||||
var debugEl = getDebugNode(renderElement);
|
||||
if (isPresent(debugEl) && debugEl instanceof DebugElement) {
|
||||
debugEl.properties.set(propertyName, propertyValue);
|
||||
}
|
||||
return this._delegate.setElementProperty(renderElement, propertyName, propertyValue);
|
||||
}
|
||||
|
||||
setElementAttribute(renderElement: any, attributeName: string, attributeValue: string) {
|
||||
var debugEl = getDebugNode(renderElement);
|
||||
if (isPresent(debugEl) && debugEl instanceof DebugElement) {
|
||||
debugEl.attributes.set(attributeName, attributeValue);
|
||||
}
|
||||
return this._delegate.setElementAttribute(renderElement, attributeName, attributeValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used only in debug mode to serialize property changes to comment nodes,
|
||||
* such as <template> placeholders.
|
||||
*/
|
||||
setBindingDebugInfo(renderElement: any, propertyName: string, propertyValue: string) {
|
||||
return this._delegate.setBindingDebugInfo(renderElement, propertyName, propertyValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used only in development mode to set information needed by the DebugNode for this element.
|
||||
*/
|
||||
setElementDebugInfo(renderElement: any, info: RenderDebugInfo) {
|
||||
var debugEl = getDebugNode(renderElement);
|
||||
debugEl.setDebugInfo(info);
|
||||
return this._delegate.setElementDebugInfo(renderElement, info);
|
||||
}
|
||||
|
||||
setElementClass(renderElement: any, className: string, isAdd: boolean) {
|
||||
return this._delegate.setElementClass(renderElement, className, isAdd);
|
||||
}
|
||||
|
||||
setElementStyle(renderElement: any, styleName: string, styleValue: string) {
|
||||
return this._delegate.setElementStyle(renderElement, styleName, styleValue);
|
||||
}
|
||||
|
||||
invokeElementMethod(renderElement: any, methodName: string, args: any[]) {
|
||||
return this._delegate.invokeElementMethod(renderElement, methodName, args);
|
||||
}
|
||||
|
||||
setText(renderNode: any, text: string) { return this._delegate.setText(renderNode, text); }
|
||||
}
|
@ -17,6 +17,7 @@ import {
|
||||
OutOfBoundsError
|
||||
} from './exceptions';
|
||||
import {FunctionWrapper, Type, isPresent, isBlank, CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {Key} from './key';
|
||||
import {SelfMetadata, HostMetadata, SkipSelfMetadata} from './metadata';
|
||||
|
||||
@ -143,7 +144,7 @@ export class ProtoInjectorInlineStrategy implements ProtoInjectorStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
getProviderAtIndex(index: number): any {
|
||||
getProviderAtIndex(index: number): ResolvedProvider {
|
||||
if (index == 0) return this.provider0;
|
||||
if (index == 1) return this.provider1;
|
||||
if (index == 2) return this.provider2;
|
||||
@ -181,7 +182,7 @@ export class ProtoInjectorDynamicStrategy implements ProtoInjectorStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
getProviderAtIndex(index: number): any {
|
||||
getProviderAtIndex(index: number): ResolvedProvider {
|
||||
if (index < 0 || index >= this.providers.length) {
|
||||
throw new OutOfBoundsError(index);
|
||||
}
|
||||
@ -210,7 +211,9 @@ export class ProtoInjector {
|
||||
new ProtoInjectorInlineStrategy(this, bwv);
|
||||
}
|
||||
|
||||
getProviderAtIndex(index: number): any { return this._strategy.getProviderAtIndex(index); }
|
||||
getProviderAtIndex(index: number): ResolvedProvider {
|
||||
return this._strategy.getProviderAtIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -872,6 +875,9 @@ export class Injector {
|
||||
obj = factory(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, d16,
|
||||
d17, d18, d19);
|
||||
break;
|
||||
default:
|
||||
throw new BaseException(
|
||||
`Cannot instantiate '${provider.key.displayName}' because it has more than 20 dependencies`);
|
||||
}
|
||||
} catch (e) {
|
||||
throw new InstantiationError(this, e, e.stack, provider.key);
|
||||
|
@ -9,7 +9,7 @@ import {CONST} from 'angular2/src/facade/lang';
|
||||
* var t = new OpaqueToken("value");
|
||||
*
|
||||
* var injector = Injector.resolveAndCreate([
|
||||
* provide(t, {useValue: "providedValue"})
|
||||
* provide(t, {useValue: "bindingValue"})
|
||||
* ]);
|
||||
*
|
||||
* expect(injector.get(t)).toEqual("bindingValue");
|
||||
|
@ -2,6 +2,7 @@ import {resolveForwardRef, Injectable} from 'angular2/src/core/di';
|
||||
import {Type, isPresent, isBlank, stringify} from 'angular2/src/facade/lang';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||
|
||||
import {
|
||||
DirectiveMetadata,
|
||||
ComponentMetadata,
|
||||
@ -38,7 +39,7 @@ export class DirectiveResolver {
|
||||
var metadata = typeMetadata.find(_isDirectiveMetadata);
|
||||
if (isPresent(metadata)) {
|
||||
var propertyMetadata = reflector.propMetadata(type);
|
||||
return this._mergeWithPropertyMetadata(metadata, propertyMetadata);
|
||||
return this._mergeWithPropertyMetadata(metadata, propertyMetadata, type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,7 +47,8 @@ export class DirectiveResolver {
|
||||
}
|
||||
|
||||
private _mergeWithPropertyMetadata(dm: DirectiveMetadata,
|
||||
propertyMetadata: {[key: string]: any[]}): DirectiveMetadata {
|
||||
propertyMetadata: {[key: string]: any[]},
|
||||
directiveType: Type): DirectiveMetadata {
|
||||
var inputs = [];
|
||||
var outputs = [];
|
||||
var host: {[key: string]: string} = {};
|
||||
@ -100,13 +102,27 @@ export class DirectiveResolver {
|
||||
}
|
||||
});
|
||||
});
|
||||
return this._merge(dm, inputs, outputs, host, queries);
|
||||
return this._merge(dm, inputs, outputs, host, queries, directiveType);
|
||||
}
|
||||
|
||||
private _merge(dm: DirectiveMetadata, inputs: string[], outputs: string[],
|
||||
host: {[key: string]: string}, queries: {[key: string]: any}): DirectiveMetadata {
|
||||
host: {[key: string]: string}, queries: {[key: string]: any},
|
||||
directiveType: Type): DirectiveMetadata {
|
||||
var mergedInputs = isPresent(dm.inputs) ? ListWrapper.concat(dm.inputs, inputs) : inputs;
|
||||
var mergedOutputs = isPresent(dm.outputs) ? ListWrapper.concat(dm.outputs, outputs) : outputs;
|
||||
|
||||
var mergedOutputs;
|
||||
if (isPresent(dm.outputs)) {
|
||||
dm.outputs.forEach((propName: string) => {
|
||||
if (ListWrapper.contains(outputs, propName)) {
|
||||
throw new BaseException(
|
||||
`Output event '${propName}' defined multiple times in '${stringify(directiveType)}'`);
|
||||
}
|
||||
});
|
||||
mergedOutputs = ListWrapper.concat(dm.outputs, outputs);
|
||||
} else {
|
||||
mergedOutputs = outputs;
|
||||
}
|
||||
|
||||
var mergedHost = isPresent(dm.host) ? StringMapWrapper.merge(dm.host, host) : host;
|
||||
var mergedQueries =
|
||||
isPresent(dm.queries) ? StringMapWrapper.merge(dm.queries, queries) : queries;
|
||||
|
@ -463,7 +463,11 @@ export class AppElement implements DependencyProvider, ElementRef, AfterViewChec
|
||||
var inj: AppElement = this;
|
||||
while (isPresent(inj)) {
|
||||
inj._setQueriesAsDirty();
|
||||
inj = inj.parent;
|
||||
if (isBlank(inj.parent) && inj.parentView.proto.type === ViewType.EMBEDDED) {
|
||||
inj = inj.parentView.containerAppElement;
|
||||
} else {
|
||||
inj = inj.parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ export abstract class TemplateRef {
|
||||
*
|
||||
*/
|
||||
// TODO(i): rename to anchor or location
|
||||
elementRef: ElementRef;
|
||||
get elementRef(): ElementRef { return null; }
|
||||
}
|
||||
|
||||
export class TemplateRef_ extends TemplateRef {
|
||||
|
@ -27,7 +27,7 @@ import {
|
||||
CONST_EXPR
|
||||
} from 'angular2/src/facade/lang';
|
||||
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
||||
import {Renderer, RootRenderer} from 'angular2/src/core/render/api';
|
||||
import {Renderer, RootRenderer, RenderDebugInfo} from 'angular2/src/core/render/api';
|
||||
import {ViewRef_, HostViewFactoryRef} from './view_ref';
|
||||
import {ProtoPipes} from 'angular2/src/core/pipes/pipes';
|
||||
import {camelCaseToDashCase} from 'angular2/src/core/render/util';
|
||||
@ -119,6 +119,12 @@ export class AppView implements ChangeDispatcher {
|
||||
(templateName, _) => { localsMap.set(templateName, null); });
|
||||
for (var i = 0; i < appElements.length; i++) {
|
||||
var appEl = appElements[i];
|
||||
var providerTokens = [];
|
||||
if (isPresent(appEl.proto.protoInjector)) {
|
||||
for (var j = 0; j < appEl.proto.protoInjector.numberOfProviders; j++) {
|
||||
providerTokens.push(appEl.proto.protoInjector.getProviderAtIndex(j).key.token);
|
||||
}
|
||||
}
|
||||
StringMapWrapper.forEach(appEl.proto.directiveVariableBindings, (directiveIndex, name) => {
|
||||
if (isBlank(directiveIndex)) {
|
||||
localsMap.set(name, appEl.nativeElement);
|
||||
@ -126,6 +132,9 @@ export class AppView implements ChangeDispatcher {
|
||||
localsMap.set(name, appEl.getDirectiveAtIndex(directiveIndex));
|
||||
}
|
||||
});
|
||||
this.renderer.setElementDebugInfo(
|
||||
appEl.nativeElement, new RenderDebugInfo(appEl.getInjector(), appEl.getComponent(),
|
||||
providerTokens, localsMap));
|
||||
}
|
||||
var parentLocals = null;
|
||||
if (this.proto.type !== ViewType.COMPONENT) {
|
||||
@ -250,7 +259,7 @@ export class AppView implements ChangeDispatcher {
|
||||
return this.appElements[directive.elementIndex].getDirectiveAtIndex(directive.directiveIndex);
|
||||
}
|
||||
|
||||
getDetectorFor(directive: DirectiveIndex): any {
|
||||
getDetectorFor(directive: DirectiveIndex): ChangeDetector {
|
||||
var componentView = this.appElements[directive.elementIndex].componentView;
|
||||
return isPresent(componentView) ? componentView.changeDetector : null;
|
||||
}
|
||||
|
@ -133,13 +133,13 @@ export class ViewContainerRef_ extends ViewContainerRef {
|
||||
|
||||
// TODO(rado): profile and decide whether bounds checks should be added
|
||||
// to the methods below.
|
||||
createEmbeddedView(templateRef: TemplateRef_, index: number = -1): EmbeddedViewRef {
|
||||
createEmbeddedView(templateRef: TemplateRef, index: number = -1): EmbeddedViewRef {
|
||||
if (index == -1) index = this.length;
|
||||
var vm = this._element.parentView.viewManager;
|
||||
return vm.createEmbeddedViewInContainer(this._element.ref, index, templateRef);
|
||||
}
|
||||
|
||||
createHostView(hostViewFactoryRef: HostViewFactoryRef_, index: number = -1,
|
||||
createHostView(hostViewFactoryRef: HostViewFactoryRef, index: number = -1,
|
||||
dynamicallyCreatedProviders: ResolvedProvider[] = null,
|
||||
projectableNodes: any[][] = null): HostViewRef {
|
||||
if (index == -1) index = this.length;
|
||||
@ -149,14 +149,14 @@ export class ViewContainerRef_ extends ViewContainerRef {
|
||||
}
|
||||
|
||||
// TODO(i): refactor insert+remove into move
|
||||
insert(viewRef: ViewRef_, index: number = -1): EmbeddedViewRef {
|
||||
insert(viewRef: ViewRef, index: number = -1): EmbeddedViewRef {
|
||||
if (index == -1) index = this.length;
|
||||
var vm = this._element.parentView.viewManager;
|
||||
return vm.attachViewInContainer(this._element.ref, index, viewRef);
|
||||
}
|
||||
|
||||
indexOf(viewRef: ViewRef_): number {
|
||||
return ListWrapper.indexOf(this._element.nestedViews, viewRef.internalView);
|
||||
indexOf(viewRef: ViewRef): number {
|
||||
return ListWrapper.indexOf(this._element.nestedViews, (<ViewRef_>viewRef).internalView);
|
||||
}
|
||||
|
||||
// TODO(i): rename to destroy
|
||||
|
@ -1,11 +0,0 @@
|
||||
import {Injectable} from 'angular2/src/core/di';
|
||||
import * as viewModule from './view';
|
||||
|
||||
/**
|
||||
* Listener for view creation / destruction.
|
||||
*/
|
||||
@Injectable()
|
||||
export class AppViewListener {
|
||||
onViewCreated(view: viewModule.AppView) {}
|
||||
onViewDestroyed(view: viewModule.AppView) {}
|
||||
}
|
@ -17,11 +17,11 @@ import {
|
||||
HostViewFactoryRef_,
|
||||
EmbeddedViewRef,
|
||||
HostViewRef,
|
||||
ViewRef,
|
||||
ViewRef_
|
||||
} from './view_ref';
|
||||
import {ViewContainerRef} from './view_container_ref';
|
||||
import {TemplateRef, TemplateRef_} from './template_ref';
|
||||
import {AppViewListener} from './view_listener';
|
||||
import {RootRenderer, RenderComponentType} from 'angular2/src/core/render/api';
|
||||
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
|
||||
import {APP_ID} from 'angular2/src/core/application_tokens';
|
||||
@ -184,25 +184,22 @@ export abstract class AppViewManager {
|
||||
export class AppViewManager_ extends AppViewManager {
|
||||
private _nextCompTypeId: number = 0;
|
||||
|
||||
constructor(private _renderer: RootRenderer, private _viewListener: AppViewListener,
|
||||
@Inject(APP_ID) private _appId: string) {
|
||||
super();
|
||||
constructor(private _renderer: RootRenderer, @Inject(APP_ID) private _appId: string) { super(); }
|
||||
|
||||
getViewContainer(location: ElementRef): ViewContainerRef {
|
||||
return (<ElementRef_>location).internalElement.getViewContainerRef();
|
||||
}
|
||||
|
||||
getViewContainer(location: ElementRef_): ViewContainerRef {
|
||||
return location.internalElement.getViewContainerRef();
|
||||
}
|
||||
|
||||
getHostElement(hostViewRef: ViewRef_): ElementRef {
|
||||
var hostView = hostViewRef.internalView;
|
||||
getHostElement(hostViewRef: ViewRef): ElementRef {
|
||||
var hostView = (<ViewRef_>hostViewRef).internalView;
|
||||
if (hostView.proto.type !== ViewType.HOST) {
|
||||
throw new BaseException('This operation is only allowed on host views');
|
||||
}
|
||||
return hostView.appElements[0].ref;
|
||||
}
|
||||
|
||||
getNamedElementInComponentView(hostLocation: ElementRef_, variableName: string): ElementRef {
|
||||
var appEl = hostLocation.internalElement;
|
||||
getNamedElementInComponentView(hostLocation: ElementRef, variableName: string): ElementRef {
|
||||
var appEl = (<ElementRef_>hostLocation).internalElement;
|
||||
var componentView = appEl.componentView;
|
||||
if (isBlank(componentView)) {
|
||||
throw new BaseException(`There is no component directive at element ${hostLocation}`);
|
||||
@ -216,17 +213,17 @@ export class AppViewManager_ extends AppViewManager {
|
||||
throw new BaseException(`Could not find variable ${variableName}`);
|
||||
}
|
||||
|
||||
getComponent(hostLocation: ElementRef_): any {
|
||||
return hostLocation.internalElement.getComponent();
|
||||
getComponent(hostLocation: ElementRef): any {
|
||||
return (<ElementRef_>hostLocation).internalElement.getComponent();
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
_createRootHostViewScope: WtfScopeFn = wtfCreateScope('AppViewManager#createRootHostView()');
|
||||
|
||||
createRootHostView(hostViewFactoryRef: HostViewFactoryRef_, overrideSelector: string,
|
||||
createRootHostView(hostViewFactoryRef: HostViewFactoryRef, overrideSelector: string,
|
||||
injector: Injector, projectableNodes: any[][] = null): HostViewRef {
|
||||
var s = this._createRootHostViewScope();
|
||||
var hostViewFactory = hostViewFactoryRef.internalHostViewFactory;
|
||||
var hostViewFactory = (<HostViewFactoryRef_>hostViewFactoryRef).internalHostViewFactory;
|
||||
var selector = isPresent(overrideSelector) ? overrideSelector : hostViewFactory.selector;
|
||||
var view = hostViewFactory.viewFactory(this._renderer, this, null, projectableNodes, selector,
|
||||
null, injector);
|
||||
@ -236,9 +233,9 @@ export class AppViewManager_ extends AppViewManager {
|
||||
/** @internal */
|
||||
_destroyRootHostViewScope: WtfScopeFn = wtfCreateScope('AppViewManager#destroyRootHostView()');
|
||||
|
||||
destroyRootHostView(hostViewRef: ViewRef_) {
|
||||
destroyRootHostView(hostViewRef: ViewRef) {
|
||||
var s = this._destroyRootHostViewScope();
|
||||
var hostView = hostViewRef.internalView;
|
||||
var hostView = (<ViewRef_>hostViewRef).internalView;
|
||||
hostView.renderer.detachView(flattenNestedViewRenderNodes(hostView.rootNodesOrAppElements));
|
||||
hostView.destroy();
|
||||
wtfLeave(s);
|
||||
@ -248,14 +245,14 @@ export class AppViewManager_ extends AppViewManager {
|
||||
_createEmbeddedViewInContainerScope: WtfScopeFn =
|
||||
wtfCreateScope('AppViewManager#createEmbeddedViewInContainer()');
|
||||
|
||||
createEmbeddedViewInContainer(viewContainerLocation: ElementRef_, index: number,
|
||||
templateRef: TemplateRef_): EmbeddedViewRef {
|
||||
createEmbeddedViewInContainer(viewContainerLocation: ElementRef, index: number,
|
||||
templateRef: TemplateRef): EmbeddedViewRef {
|
||||
var s = this._createEmbeddedViewInContainerScope();
|
||||
var contextEl = templateRef.elementRef.internalElement;
|
||||
var contextEl = (<TemplateRef_>templateRef).elementRef.internalElement;
|
||||
var view: AppView =
|
||||
contextEl.embeddedViewFactory(contextEl.parentView.renderer, this, contextEl,
|
||||
contextEl.parentView.projectableNodes, null, null, null);
|
||||
this._attachViewToContainer(view, viewContainerLocation.internalElement, index);
|
||||
this._attachViewToContainer(view, (<ElementRef_>viewContainerLocation).internalElement, index);
|
||||
return wtfLeave(s, view.ref);
|
||||
}
|
||||
|
||||
@ -263,27 +260,29 @@ export class AppViewManager_ extends AppViewManager {
|
||||
_createHostViewInContainerScope: WtfScopeFn =
|
||||
wtfCreateScope('AppViewManager#createHostViewInContainer()');
|
||||
|
||||
createHostViewInContainer(viewContainerLocation: ElementRef_, index: number,
|
||||
hostViewFactoryRef: HostViewFactoryRef_,
|
||||
createHostViewInContainer(viewContainerLocation: ElementRef, index: number,
|
||||
hostViewFactoryRef: HostViewFactoryRef,
|
||||
dynamicallyCreatedProviders: ResolvedProvider[],
|
||||
projectableNodes: any[][]): HostViewRef {
|
||||
var s = this._createHostViewInContainerScope();
|
||||
// TODO(tbosch): This should be specifiable via an additional argument!
|
||||
var contextEl = viewContainerLocation.internalElement;
|
||||
var hostViewFactory = hostViewFactoryRef.internalHostViewFactory;
|
||||
var viewContainerLocation_ = <ElementRef_>viewContainerLocation;
|
||||
var contextEl = viewContainerLocation_.internalElement;
|
||||
var hostViewFactory = (<HostViewFactoryRef_>hostViewFactoryRef).internalHostViewFactory;
|
||||
var view = hostViewFactory.viewFactory(
|
||||
contextEl.parentView.renderer, contextEl.parentView.viewManager, contextEl,
|
||||
projectableNodes, null, dynamicallyCreatedProviders, null);
|
||||
this._attachViewToContainer(view, viewContainerLocation.internalElement, index);
|
||||
this._attachViewToContainer(view, viewContainerLocation_.internalElement, index);
|
||||
return wtfLeave(s, view.ref);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
_destroyViewInContainerScope = wtfCreateScope('AppViewMananger#destroyViewInContainer()');
|
||||
|
||||
destroyViewInContainer(viewContainerLocation: ElementRef_, index: number) {
|
||||
destroyViewInContainer(viewContainerLocation: ElementRef, index: number) {
|
||||
var s = this._destroyViewInContainerScope();
|
||||
var view = this._detachViewInContainer(viewContainerLocation.internalElement, index);
|
||||
var view =
|
||||
this._detachViewInContainer((<ElementRef_>viewContainerLocation).internalElement, index);
|
||||
view.destroy();
|
||||
wtfLeave(s);
|
||||
}
|
||||
@ -292,28 +291,31 @@ export class AppViewManager_ extends AppViewManager {
|
||||
_attachViewInContainerScope = wtfCreateScope('AppViewMananger#attachViewInContainer()');
|
||||
|
||||
// TODO(i): refactor detachViewInContainer+attachViewInContainer to moveViewInContainer
|
||||
attachViewInContainer(viewContainerLocation: ElementRef_, index: number,
|
||||
viewRef: ViewRef_): EmbeddedViewRef {
|
||||
attachViewInContainer(viewContainerLocation: ElementRef, index: number,
|
||||
viewRef: ViewRef): EmbeddedViewRef {
|
||||
var viewRef_ = <ViewRef_>viewRef;
|
||||
var s = this._attachViewInContainerScope();
|
||||
this._attachViewToContainer(viewRef.internalView, viewContainerLocation.internalElement, index);
|
||||
return wtfLeave(s, viewRef);
|
||||
this._attachViewToContainer(viewRef_.internalView,
|
||||
(<ElementRef_>viewContainerLocation).internalElement, index);
|
||||
return wtfLeave(s, viewRef_);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
_detachViewInContainerScope = wtfCreateScope('AppViewMananger#detachViewInContainer()');
|
||||
|
||||
// TODO(i): refactor detachViewInContainer+attachViewInContainer to moveViewInContainer
|
||||
detachViewInContainer(viewContainerLocation: ElementRef_, index: number): EmbeddedViewRef {
|
||||
detachViewInContainer(viewContainerLocation: ElementRef, index: number): EmbeddedViewRef {
|
||||
var s = this._detachViewInContainerScope();
|
||||
var view = this._detachViewInContainer(viewContainerLocation.internalElement, index);
|
||||
var view =
|
||||
this._detachViewInContainer((<ElementRef_>viewContainerLocation).internalElement, index);
|
||||
return wtfLeave(s, view.ref);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
onViewCreated(view: AppView) { this._viewListener.onViewCreated(view); }
|
||||
onViewCreated(view: AppView) {}
|
||||
|
||||
/** @internal */
|
||||
onViewDestroyed(view: AppView) { this._viewListener.onViewDestroyed(view); }
|
||||
onViewDestroyed(view: AppView) {}
|
||||
|
||||
/** @internal */
|
||||
createRenderComponentType(encapsulation: ViewEncapsulation,
|
||||
|
@ -1166,7 +1166,7 @@ export var ViewChild: ViewChildFactory = makePropDecorator(ViewChildMetadata);
|
||||
* shown: boolean;
|
||||
*
|
||||
* constructor(private @Query(Item) items:QueryList<Item>) {
|
||||
* items.onChange(() => console.log(items.length));
|
||||
* items.changes.subscribe(() => console.log(items.length));
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
@ -1268,7 +1268,7 @@ export var Input: InputFactory = makePropDecorator(InputMetadata);
|
||||
* @Component({
|
||||
* selector: 'app',
|
||||
* template: `
|
||||
* <interval-dir (every-second)="everySecond()" (every-five-seconds)="everyFiveSeconds()">
|
||||
* <interval-dir (everySecond)="everySecond()" (everyFiveSeconds)="everyFiveSeconds()">
|
||||
* </interval-dir>
|
||||
* `,
|
||||
* directives: [IntervalDir]
|
||||
|
@ -254,7 +254,7 @@ export class ContentChildMetadata extends QueryMetadata {
|
||||
* shown: boolean;
|
||||
*
|
||||
* constructor(private @Query(Item) items:QueryList<Item>) {
|
||||
* items.onChange(() => console.log(items.length));
|
||||
* items.changes.subscribe(() => console.log(items.length));
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
|
@ -504,7 +504,7 @@ export class DirectiveMetadata extends InjectableMetadata {
|
||||
* @Component({
|
||||
* selector: 'app',
|
||||
* template: `
|
||||
* <interval-dir (every-second)="everySecond()" (every-five-seconds)="everyFiveSeconds()">
|
||||
* <interval-dir (everySecond)="everySecond()" (everyFiveSeconds)="everyFiveSeconds()">
|
||||
* </interval-dir>
|
||||
* `,
|
||||
* directives: [IntervalDir]
|
||||
@ -1035,7 +1035,7 @@ export class InputMetadata {
|
||||
* @Component({
|
||||
* selector: 'app',
|
||||
* template: `
|
||||
* <interval-dir (every-second)="everySecond()" (every-five-seconds)="everyFiveSeconds()">
|
||||
* <interval-dir (everySecond)="everySecond()" (everyFiveSeconds)="everyFiveSeconds()">
|
||||
* </interval-dir>
|
||||
* `,
|
||||
* directives: [IntervalDir]
|
||||
@ -1071,8 +1071,8 @@ export class OutputMetadata {
|
||||
* @Directive({selector: '[ngModel]'})
|
||||
* class NgModelStatus {
|
||||
* constructor(public control:NgModel) {}
|
||||
* @HostBinding('[class.valid]') get valid { return this.control.valid; }
|
||||
* @HostBinding('[class.invalid]') get invalid { return this.control.invalid; }
|
||||
* @HostBinding('class.valid') get valid { return this.control.valid; }
|
||||
* @HostBinding('class.invalid') get invalid { return this.control.invalid; }
|
||||
* }
|
||||
*
|
||||
* @Component({
|
||||
|
@ -23,7 +23,7 @@ class NoReflectionCapabilities implements PlatformReflectionCapabilities {
|
||||
}
|
||||
|
||||
@override
|
||||
List parameters(dynamic type) {
|
||||
List<List> parameters(dynamic type) {
|
||||
throw "Cannot find reflection information on ${stringify(type)}";
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ class NoReflectionCapabilities implements PlatformReflectionCapabilities {
|
||||
}
|
||||
|
||||
@override
|
||||
Map propMetadata(dynamic type) {
|
||||
Map<String, List> propMetadata(dynamic type) {
|
||||
throw "Cannot find reflection information on ${stringify(type)}";
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
_zipTypesAndAnnotaions(paramTypes, paramAnnotations): any[][] {
|
||||
_zipTypesAndAnnotations(paramTypes, paramAnnotations): any[][] {
|
||||
var result;
|
||||
|
||||
if (typeof paramTypes === 'undefined') {
|
||||
@ -119,7 +119,7 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
|
||||
var paramAnnotations = this._reflect.getMetadata('parameters', typeOrFunc);
|
||||
var paramTypes = this._reflect.getMetadata('design:paramtypes', typeOrFunc);
|
||||
if (isPresent(paramTypes) || isPresent(paramAnnotations)) {
|
||||
return this._zipTypesAndAnnotaions(paramTypes, paramAnnotations);
|
||||
return this._zipTypesAndAnnotations(paramTypes, paramAnnotations);
|
||||
}
|
||||
}
|
||||
// The array has to be filled with `undefined` because holes would be skipped by `some`
|
||||
|
@ -1,5 +1,5 @@
|
||||
library reflection.types;
|
||||
|
||||
typedef SetterFn(Object obj, value);
|
||||
typedef GetterFn(Object obj);
|
||||
typedef MethodFn(Object obj, List args);
|
||||
typedef SetterFn(obj, value);
|
||||
typedef GetterFn(obj);
|
||||
typedef MethodFn(obj, List args);
|
||||
|
@ -1,10 +1,16 @@
|
||||
import {ViewEncapsulation} from 'angular2/src/core/metadata/view';
|
||||
import {Injector} from 'angular2/src/core/di/injector';
|
||||
|
||||
export class RenderComponentType {
|
||||
constructor(public id: string, public encapsulation: ViewEncapsulation,
|
||||
public styles: Array<string | any[]>) {}
|
||||
}
|
||||
|
||||
export class RenderDebugInfo {
|
||||
constructor(public injector: Injector, public component: any, public providerTokens: any[],
|
||||
public locals: Map<string, any>) {}
|
||||
}
|
||||
|
||||
export interface ParentRenderer { renderComponent(componentType: RenderComponentType): Renderer; }
|
||||
|
||||
export abstract class Renderer implements ParentRenderer {
|
||||
@ -28,7 +34,7 @@ export abstract class Renderer implements ParentRenderer {
|
||||
|
||||
abstract destroyView(hostElement: any, viewAllNodes: any[]);
|
||||
|
||||
abstract listen(renderElement: any, name: string, callback: Function);
|
||||
abstract listen(renderElement: any, name: string, callback: Function): Function;
|
||||
|
||||
abstract listenGlobal(target: string, name: string, callback: Function): Function;
|
||||
|
||||
@ -42,6 +48,8 @@ export abstract class Renderer implements ParentRenderer {
|
||||
*/
|
||||
abstract setBindingDebugInfo(renderElement: any, propertyName: string, propertyValue: string);
|
||||
|
||||
abstract setElementDebugInfo(renderElement: any, info: RenderDebugInfo);
|
||||
|
||||
abstract setElementClass(renderElement: any, className: string, isAdd: boolean);
|
||||
|
||||
abstract setElementStyle(renderElement: any, styleName: string, styleValue: string);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user