Compare commits
170 Commits
2.0.0-beta
...
2.0.0-beta
Author | SHA1 | Date | |
---|---|---|---|
185c679563 | |||
b3f4e05b57 | |||
abd1e6e680 | |||
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
|
language: node_js
|
||||||
sudo: false
|
sudo: false
|
||||||
node_js:
|
node_js:
|
||||||
- '4.2.1'
|
- '5.4.1'
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
except:
|
except:
|
||||||
- g3sync
|
- g3_v2_0
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
@ -36,12 +36,13 @@ env:
|
|||||||
matrix:
|
matrix:
|
||||||
# Order: a slower build first, so that we don't occupy an idle travis worker waiting for others to complete.
|
# 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=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=saucelabs_required DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||||
- MODE=browserstack_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=saucelabs_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||||
- MODE=browserstack_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=js DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||||
- MODE=router 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
|
- MODE=build_only DART_CHANNEL=stable DART_VERSION=$DART_STABLE_VERSION
|
||||||
@ -52,7 +53,6 @@ matrix:
|
|||||||
allow_failures:
|
allow_failures:
|
||||||
- env: "MODE=saucelabs_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
|
- 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=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
|
# TODO(alxhub): remove when dartdoc #1039 is in dev channel
|
||||||
- env: "MODE=dart DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
|
- env: "MODE=dart DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
|
||||||
|
|
||||||
@ -60,6 +60,7 @@ addons:
|
|||||||
firefox: "38.0"
|
firefox: "38.0"
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
|
- npm install -g npm@3.5.3
|
||||||
- node tools/analytics/build-analytics start ci job
|
- node tools/analytics/build-analytics start ci job
|
||||||
- node tools/analytics/build-analytics start ci before_install
|
- node tools/analytics/build-analytics start ci before_install
|
||||||
- echo ${TSDRC} > .tsdrc
|
- echo ${TSDRC} > .tsdrc
|
||||||
@ -77,7 +78,9 @@ install:
|
|||||||
# Check the size of caches
|
# Check the size of caches
|
||||||
- du -sh ./node_modules || true
|
- du -sh ./node_modules || true
|
||||||
# Install npm dependecies
|
# 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
|
- node tools/analytics/build-analytics success ci install
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
|
1909
CHANGELOG.md
1909
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
|
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
||||||
* **perf**: A code change that improves performance
|
* **perf**: A code change that improves performance
|
||||||
* **test**: Adding missing tests or correcting existing tests
|
* **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
|
* **chore**: Other changes that don't modify `src` or `test` files
|
||||||
|
|
||||||
### Scope
|
### 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)
|
* [Installing NPM Modules and Dart Packages](#installing-npm-modules-and-dart-packages)
|
||||||
* [Build commands](#build-commands)
|
* [Build commands](#build-commands)
|
||||||
* [Running Tests Locally](#running-tests-locally)
|
* [Running Tests Locally](#running-tests-locally)
|
||||||
* [Formatting](#clang-format)
|
* [Code Style](#code-style)
|
||||||
* [Project Information](#project-information)
|
* [Project Information](#project-information)
|
||||||
* [CI using Travis](#ci-using-travis)
|
* [CI using Travis](#ci-using-travis)
|
||||||
* [Transforming Dart code](#transforming-dart-code)
|
* [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
|
Before you can build and test Angular, you must install and configure the
|
||||||
following products on your development machine:
|
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
|
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**,
|
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)
|
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
|
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).`
|
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
|
## Getting the Sources
|
||||||
@ -200,15 +196,15 @@ Then, in another terminal:
|
|||||||
export SAUCE_USERNAME='my_user'; export SAUCE_ACCESS_KEY='my_key';
|
export SAUCE_USERNAME='my_user'; export SAUCE_ACCESS_KEY='my_key';
|
||||||
export BROWSER_STACK_USERNAME='my_user'; export BROWSER_STACK_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.
|
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.
|
They are case insensitive, and the `SL_` or `BS_` prefix must not be added for browsers.
|
||||||
|
|
||||||
Some examples of commands:
|
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.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
|
### 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, ...):
|
Angular specific command line options when running protractor (e.g. force gc, ...):
|
||||||
`$(npm bin)/protractor protractor-{js|dart2js}-conf.js --ng-help`
|
`$(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
|
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
|
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`,
|
* `clang-format` integrations are also available for many popular editors (`vim`, `emacs`,
|
||||||
`Sublime Text`, etc.).
|
`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
|
## Generating the API documentation
|
||||||
|
|
||||||
The following gulp task will generate the API docs in the `dist/angular.io/partials/api/angular2`:
|
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
|
The MIT License
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
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,
|
The above copyright notice and this permission notice shall be included in
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
"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 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
|
174
gulpfile.js
174
gulpfile.js
@ -3,10 +3,10 @@
|
|||||||
// THIS CHECK SHOULD BE THE FIRST THING IN THIS FILE
|
// 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.
|
// This is to ensure that we catch env issues before we error while requiring other dependencies.
|
||||||
require('./tools/check-environment')(
|
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 gulp = require('gulp');
|
||||||
var gulpPlugins = require('gulp-load-plugins')();
|
var gulpPlugins = require('gulp-load-plugins')();
|
||||||
var merge = require('merge');
|
var merge = require('merge');
|
||||||
@ -42,7 +42,7 @@ if (cliArgs.projects) {
|
|||||||
|
|
||||||
// --projects=angular2,angular2_material => {angular2: true, angular2_material: true}
|
// --projects=angular2,angular2_material => {angular2: true, angular2_material: true}
|
||||||
var allProjects =
|
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)
|
var cliArgsProjects = (cliArgs.projects || allProjects)
|
||||||
.split(',')
|
.split(',')
|
||||||
.reduce((map, projectName) => {
|
.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/* - ' +
|
var ROUTER_BUNDLE_CONTENT = 'angular2/router + angular2/router/router_link_dsl - rxjs/* - ' +
|
||||||
ANGULAR2_BUNDLE_CONFIG.join(' - ');
|
ANGULAR2_BUNDLE_CONFIG.join(' - ');
|
||||||
var TESTING_BUNDLE_CONTENT =
|
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(' - ');
|
ANGULAR2_BUNDLE_CONFIG.join(' - ');
|
||||||
var UPGRADE_BUNDLE_CONTENT = 'angular2/upgrade - 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
|
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
|
// 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',
|
gulp.task('build/clean.docs_angular_io', (done) => fse.remove(CONFIG.dest.docs_angular_io, done));
|
||||||
function(done) { del(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',
|
gulp.task('build/clean.bundles.benchpress',
|
||||||
function(done) { del(CONFIG.dest.bundles.benchpress, done); });
|
(done) => fse.remove(CONFIG.dest.bundles.benchpress, done));
|
||||||
|
|
||||||
// ------------
|
// ------------
|
||||||
// transpile
|
// transpile
|
||||||
@ -313,7 +325,9 @@ gulp.task('lint', ['build.tools'], function() {
|
|||||||
"requireParameterType": true,
|
"requireParameterType": true,
|
||||||
"requireReturnType": true,
|
"requireReturnType": true,
|
||||||
"semicolon": 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/**'])
|
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) {
|
gulp.task('test.js', function(done) {
|
||||||
runSequence('test.unit.tools/ci', 'test.transpiler.unittest', 'test.unit.js/ci',
|
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) {
|
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) {
|
gulp.task('test.unit.dart', function(done) {
|
||||||
printModulesWarning();
|
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
|
// This test will fail if the size of our hello_world app goes beyond one of
|
||||||
// these values when compressed at the specified level.
|
// these values when compressed at the specified level.
|
||||||
// Measure in bytes.
|
// 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) {
|
gulp.task('test.payload.dart/ci', function(done) {
|
||||||
runSequence('build/packages.dart', '!pubget.payload.dart', '!pubbuild.payload.dart',
|
runSequence('build/packages.dart', '!pubget.payload.dart', '!pubbuild.payload.dart',
|
||||||
'!checkAndReport.payload.dart', done);
|
'!checkAndReport.payload.dart', done);
|
||||||
@ -658,6 +676,103 @@ gulp.task('!checkAndReport.payload.dart', function() {
|
|||||||
{failConditions: _DART_PAYLOAD_SIZE_LIMITS, prefix: 'hello_world'});
|
{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) {
|
gulp.task('watch.dart.dev', function(done) {
|
||||||
runSequence('build/tree.dart', 'build/pure-packages.dart', '!build/pubget.angular2.dart',
|
runSequence('build/tree.dart', 'build/pure-packages.dart', '!build/pubget.angular2.dart',
|
||||||
'!build/change_detect.dart', '!build/remove-pub-symlinks', 'build.dart.material.css',
|
'!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'],
|
reporters: ['dots'],
|
||||||
browsers: browserConf.browsersToRun
|
browsers: browserConf.browsersToRun
|
||||||
},
|
},
|
||||||
done)
|
function(err) { done(); })
|
||||||
.start();
|
.start();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -755,6 +870,8 @@ gulp.task('test.unit.cjs/ci', function(done) {
|
|||||||
runJasmineTests(['dist/js/cjs/{angular2,benchpress}/test/**/*_spec.js'], 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) {
|
gulp.task('test.unit.cjs', ['build/clean.js', 'build.tools'], function(neverDone) {
|
||||||
var watch = require('./tools/build/watch');
|
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')));
|
.pipe(gulp.dest(path.join(tmpdir, 'node_modules')));
|
||||||
});
|
});
|
||||||
gulp.task('!pre.test.typings.copyTypingsSpec', function() {
|
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',
|
gulp.task('test.typings',
|
||||||
['!pre.test.typings.layoutNodeModule', '!pre.test.typings.copyTypingsSpec'], function() {
|
['!pre.test.typings.layoutNodeModule', '!pre.test.typings.copyTypingsSpec'], function() {
|
||||||
var tsc = require('gulp-typescript');
|
var tsc = require('gulp-typescript');
|
||||||
|
|
||||||
return gulp.src([tmpdir + '/**'])
|
return gulp.src([tmpdir + '/*.ts'])
|
||||||
.pipe(tsc({
|
.pipe(tsc({
|
||||||
target: 'ES5',
|
target: 'ES6',
|
||||||
module: 'commonjs',
|
module: 'commonjs',
|
||||||
experimentalDecorators: true,
|
experimentalDecorators: true,
|
||||||
noImplicitAny: true,
|
noImplicitAny: true,
|
||||||
@ -906,16 +1024,12 @@ gulp.task('build/pure-packages.dart/standalone', function() {
|
|||||||
.pipe(gulp.dest(CONFIG.dest.dart));
|
.pipe(gulp.dest(CONFIG.dest.dart));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('build/pure-packages.dart/license',
|
gulp.task('build/pure-packages.dart/license', function() {
|
||||||
function() {
|
return gulp.src(['LICENSE']).pipe(gulp.dest(path.join(CONFIG.dest.dart, 'angular2_testing')));
|
||||||
return gulp.src(['LICENSE'])
|
});
|
||||||
.pipe(gulp.dest(path.join(CONFIG.dest.dart, 'angular2_testing')));
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
gulp.task('build/pure-packages.dart/angular2', function() {
|
gulp.task('build/pure-packages.dart/angular2', function() {
|
||||||
var yaml = require('js-yaml');
|
|
||||||
|
|
||||||
return gulp.src([
|
return gulp.src([
|
||||||
'modules_dart/transform/**/*',
|
'modules_dart/transform/**/*',
|
||||||
'!modules_dart/transform/**/*.proto',
|
'!modules_dart/transform/**/*.proto',
|
||||||
@ -1127,8 +1241,8 @@ gulp.task('!bundle.testing', ['build.js.dev'], function() {
|
|||||||
{sourceMaps: true});
|
{sourceMaps: true});
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('!bundles.js.docs', function() {
|
gulp.task('!bundles.js.docs', ['clean'], function() {
|
||||||
gulp.src('modules/angular2/docs/bundles/*').pipe(gulp.dest('dist/js/bundle'));
|
return gulp.src('modules/angular2/docs/bundles/*').pipe(gulp.dest('dist/js/bundle'));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('!bundles.js.umd', ['build.js.dev'], function() {
|
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) {
|
gulp.task('!bundles.js.checksize', function(done) {
|
||||||
var reportSize = require('./tools/analytics/reportsize');
|
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',
|
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 PRELUDE = '(function(){\n';
|
||||||
var POSTLUDE = '\n}());\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() {
|
function main(modulesDirectory) {
|
||||||
var dir = __dirname + '/../angular2/src/router/';
|
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) {
|
var sharedCode = files.reduce(function (prev, file) {
|
||||||
return prev + transform(fs.readFileSync(dir + file, 'utf8'));
|
return prev + transform(fs.readFileSync(dir + file, 'utf8'));
|
||||||
}, '');
|
}, '');
|
||||||
|
|
||||||
var out = moduleTemplate.replace('//{{FACADES}}', FACADES).replace('//{{SHARED_CODE}}', sharedCode);
|
var out = moduleTemplate.replace('//{{FACADES}}', facades)
|
||||||
return PRELUDE + transform(DIRECTIVES) + out + POSTLUDE;
|
.replace('//{{SHARED_CODE}}', sharedCode);
|
||||||
|
return PRELUDE + transform(directives) + out + POSTLUDE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -62,10 +69,29 @@ function isFacadeModule(modulePath) {
|
|||||||
modulePath === 'angular2/src/core/reflection/reflection';
|
modulePath === 'angular2/src/core/reflection/reflection';
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function(modulesDirectory, outputDirectory) {
|
||||||
var dist = __dirname + '/../../dist';
|
if (!fs.existsSync(outputDirectory)) {
|
||||||
if (!fs.existsSync(dist)) {
|
fs.mkdirSync(outputDirectory);
|
||||||
fs.mkdirSync(dist);
|
|
||||||
}
|
}
|
||||||
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 List = Array;
|
||||||
var ListWrapper = {
|
var ListWrapper = {
|
||||||
|
toJSON: function(l) {
|
||||||
|
return JSON.stringify(l);
|
||||||
|
},
|
||||||
|
|
||||||
clear: function (l) {
|
clear: function (l) {
|
||||||
l.length = 0;
|
l.length = 0;
|
||||||
},
|
},
|
||||||
@ -247,6 +251,10 @@ var ListWrapper = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var StringWrapper = {
|
var StringWrapper = {
|
||||||
|
charCodeAt: function(s, i) {
|
||||||
|
return s.charCodeAt(i);
|
||||||
|
},
|
||||||
|
|
||||||
equals: function (s1, s2) {
|
equals: function (s1, s2) {
|
||||||
return s1 === s2;
|
return s1 === s2;
|
||||||
},
|
},
|
||||||
@ -303,8 +311,8 @@ Location.prototype.subscribe = function () {
|
|||||||
//TODO: implement
|
//TODO: implement
|
||||||
};
|
};
|
||||||
Location.prototype.path = function () {
|
Location.prototype.path = function () {
|
||||||
return $location.path();
|
return $location.url();
|
||||||
};
|
};
|
||||||
Location.prototype.go = function (url) {
|
Location.prototype.go = function (path, query) {
|
||||||
return $location.path(url);
|
return $location.url(path + query);
|
||||||
};
|
};
|
||||||
|
@ -57,7 +57,7 @@ function routerFactory($q, $location, $$directiveIntrospector, $browser, $rootSc
|
|||||||
});
|
});
|
||||||
|
|
||||||
var router = new RootRouter(registry, location, $routerRootComponent);
|
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) {
|
if (router.lastNavigationAttempt !== path) {
|
||||||
router.navigateByUrl(path);
|
router.navigateByUrl(path);
|
||||||
}
|
}
|
||||||
|
@ -155,10 +155,12 @@ function ngOutletDirective($animate, $q: ng.IQService, $router) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.controller.$$routeParams = instruction.params;
|
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);
|
this.controller.$$router = this.router.childRouter(instruction.componentType);
|
||||||
|
|
||||||
let newScope = scope.$new();
|
let newScope = scope.$new();
|
||||||
|
newScope.$$router = this.controller.$$router;
|
||||||
|
|
||||||
let clone = $transclude(newScope, clone => {
|
let clone = $transclude(newScope, clone => {
|
||||||
$animate.enter(clone, null, this.currentElement || element);
|
$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 () {
|
(function () {
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
@ -21,17 +21,29 @@ describe('navigation', function () {
|
|||||||
$router = _$router_;
|
$router = _$router_;
|
||||||
});
|
});
|
||||||
|
|
||||||
registerComponent('userCmp', {
|
registerDirective('userCmp', {
|
||||||
template: '<div>hello {{userCmp.$routeParams.name}}</div>'
|
template: '<div>hello {{userCmp.$routeParams.name}}</div>'
|
||||||
});
|
});
|
||||||
registerComponent('oneCmp', {
|
registerDirective('oneCmp', {
|
||||||
template: '<div>{{oneCmp.number}}</div>',
|
template: '<div>{{oneCmp.number}}</div>',
|
||||||
controller: function () {this.number = 'one'}
|
controller: function () {this.number = 'one'}
|
||||||
});
|
});
|
||||||
registerComponent('twoCmp', {
|
registerDirective('twoCmp', {
|
||||||
template: '<div>{{twoCmp.number}}</div>',
|
template: '<div>{{twoCmp.number}}</div>',
|
||||||
controller: function () {this.number = 'two'}
|
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 () {
|
it('should work in a simple case', function () {
|
||||||
@ -47,6 +59,21 @@ describe('navigation', function () {
|
|||||||
expect(elt.text()).toBe('one');
|
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 () {
|
it('should navigate between components with different parameters', function () {
|
||||||
$router.config([
|
$router.config([
|
||||||
{ path: '/user/:name', component: 'userCmp' }
|
{ path: '/user/:name', component: 'userCmp' }
|
||||||
@ -68,7 +95,7 @@ describe('navigation', function () {
|
|||||||
function ParentController() {
|
function ParentController() {
|
||||||
instanceCount += 1;
|
instanceCount += 1;
|
||||||
}
|
}
|
||||||
registerComponent('parentCmp', {
|
registerDirective('parentCmp', {
|
||||||
template: 'parent { <ng-outlet></ng-outlet> }',
|
template: 'parent { <ng-outlet></ng-outlet> }',
|
||||||
$routeConfig: [
|
$routeConfig: [
|
||||||
{ path: '/user/:name', component: 'userCmp' }
|
{ path: '/user/:name', component: 'userCmp' }
|
||||||
@ -94,7 +121,7 @@ describe('navigation', function () {
|
|||||||
|
|
||||||
|
|
||||||
it('should work with nested outlets', function () {
|
it('should work with nested outlets', function () {
|
||||||
registerComponent('childCmp', {
|
registerDirective('childCmp', {
|
||||||
template: '<div>inner { <div ng-outlet></div> }</div>',
|
template: '<div>inner { <div ng-outlet></div> }</div>',
|
||||||
$routeConfig: [
|
$routeConfig: [
|
||||||
{ path: '/b', component: 'oneCmp' }
|
{ path: '/b', component: 'oneCmp' }
|
||||||
@ -112,9 +139,29 @@ describe('navigation', function () {
|
|||||||
expect(elt.text()).toBe('outer { inner { one } }');
|
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 () {
|
it('should work with recursive nested outlets', function () {
|
||||||
registerComponent('recurCmp', {
|
registerDirective('recurCmp', {
|
||||||
template: '<div>recur { <div ng-outlet></div> }</div>',
|
template: '<div>recur { <div ng-outlet></div> }</div>',
|
||||||
$routeConfig: [
|
$routeConfig: [
|
||||||
{ path: '/recur', component: 'recurCmp' },
|
{ 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) {
|
it('should change location to the canonical route', inject(function ($location) {
|
||||||
compile('<div ng-outlet></div>');
|
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) {
|
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>',
|
template: '<div>inner { <div ng-outlet></div> }</div>',
|
||||||
$routeConfig: [
|
$routeConfig: [
|
||||||
{ path: '/new-child', component: 'oneCmp', name: 'NewChild'},
|
{ 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) {
|
it('should expose a "navigating" property on $router', inject(function ($q) {
|
||||||
var defer;
|
var defer;
|
||||||
registerComponent('pendingActivate', {
|
registerDirective('pendingActivate', {
|
||||||
$canActivate: function () {
|
$canActivate: function () {
|
||||||
defer = $q.defer();
|
defer = $q.defer();
|
||||||
return defer.promise;
|
return defer.promise;
|
||||||
@ -227,36 +302,54 @@ describe('navigation', function () {
|
|||||||
expect($router.navigating).toBe(false);
|
expect($router.navigating).toBe(false);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function registerComponent(name, options) {
|
function registerDirective(name, options) {
|
||||||
var controller = options.controller || function () {};
|
|
||||||
|
|
||||||
['$routerOnActivate', '$routerOnDeactivate', '$routerOnReuse', '$routerCanReuse', '$routerCanDeactivate'].forEach(function (hookName) {
|
|
||||||
if (options[hookName]) {
|
|
||||||
controller.prototype[hookName] = options[hookName];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function factory() {
|
function factory() {
|
||||||
return {
|
return {
|
||||||
template: options.template || '',
|
template: options.template || '',
|
||||||
controllerAs: name,
|
controllerAs: name,
|
||||||
controller: controller
|
controller: getController(options)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
applyStaticProperties(factory, options);
|
||||||
if (options.$canActivate) {
|
|
||||||
factory.$canActivate = options.$canActivate;
|
|
||||||
}
|
|
||||||
if (options.$routeConfig) {
|
|
||||||
factory.$routeConfig = options.$routeConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
$compileProvider.directive(name, factory);
|
$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) {
|
function compile(template) {
|
||||||
elt = $compile('<div>' + template + '</div>')($rootScope);
|
elt = $compile('<div>' + template + '</div>')($rootScope);
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
return elt;
|
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');
|
expect(elt.text()).toBe('Home');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function registerComponent(name, options) {
|
it('should bind the component to the current router', inject(function($location) {
|
||||||
var controller = options.controller || function () {};
|
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) {
|
registerComponent('app', {
|
||||||
if (options[hookName]) {
|
template: '<div ng-outlet></div>',
|
||||||
controller.prototype[hookName] = options[hookName];
|
$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() {
|
function factory() {
|
||||||
return {
|
return {
|
||||||
template: options.template || '',
|
template: options.template || '',
|
||||||
controllerAs: name,
|
controllerAs: name,
|
||||||
controller: controller
|
controller: getController(options)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
applyStaticProperties(factory, options);
|
||||||
if (options.$canActivate) {
|
|
||||||
factory.$canActivate = options.$canActivate;
|
|
||||||
}
|
|
||||||
if (options.$routeConfig) {
|
|
||||||
factory.$routeConfig = options.$routeConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
$compileProvider.directive(name, factory);
|
$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) {
|
function compile(template) {
|
||||||
elt = $compile('<div>' + template + '</div>')($rootScope);
|
elt = $compile('<div>' + template + '</div>')($rootScope);
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
return elt;
|
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",
|
"version": "v4",
|
||||||
"repo": "angular/DefinitelyTyped",
|
"repo": "DefinitelyTyped/DefinitelyTyped",
|
||||||
"ref": "master",
|
"ref": "master",
|
||||||
"path": "typings",
|
"path": "typings",
|
||||||
"bundle": "typings/tsd.d.ts",
|
"bundle": "typings/tsd.d.ts",
|
||||||
"installed": {
|
"installed": {
|
||||||
"angularjs/angular.d.ts": {
|
"angularjs/angular.d.ts": {
|
||||||
"commit": "746b9a892629060bc853e792afff536e0ec4655e"
|
"commit": "6eebd5e90a1cbd6b47b0705ba72dbcd5baf846f3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,7 @@ library angular2;
|
|||||||
*
|
*
|
||||||
* This library does not include `bootstrap`. Import `bootstrap.dart` instead.
|
* This library does not include `bootstrap`. Import `bootstrap.dart` instead.
|
||||||
*/
|
*/
|
||||||
export 'package:angular2/core.dart'
|
export 'package:angular2/core.dart';
|
||||||
hide forwardRef, resolveForwardRef, ForwardRefFn;
|
|
||||||
export 'package:angular2/common.dart';
|
export 'package:angular2/common.dart';
|
||||||
export 'package:angular2/instrumentation.dart';
|
export 'package:angular2/instrumentation.dart';
|
||||||
export 'package:angular2/src/core/angular_entrypoint.dart' show AngularEntrypoint;
|
export 'package:angular2/src/core/angular_entrypoint.dart' show AngularEntrypoint;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
library angular2.core;
|
library angular2.core;
|
||||||
|
|
||||||
|
export './src/core/angular_entrypoint.dart' show AngularEntrypoint;
|
||||||
export './src/core/metadata.dart';
|
export './src/core/metadata.dart';
|
||||||
export './src/core/util.dart';
|
export './src/core/util.dart';
|
||||||
export 'package:angular2/src/facade/lang.dart' show enableProdMode;
|
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/zone.dart';
|
||||||
export './src/core/render.dart';
|
export './src/core/render.dart';
|
||||||
export './src/core/linker.dart';
|
export './src/core/linker.dart';
|
||||||
export './src/core/debug/debug_element.dart' show DebugElement,
|
export './src/core/debug/debug_node.dart' show DebugElement,
|
||||||
Scope,
|
DebugNode,
|
||||||
inspectElement,
|
|
||||||
asNativeElements;
|
asNativeElements;
|
||||||
export './src/core/testability/testability.dart';
|
export './src/core/testability/testability.dart';
|
||||||
export './src/core/change_detection.dart';
|
export './src/core/change_detection.dart';
|
||||||
|
@ -20,12 +20,7 @@ export {
|
|||||||
export * from './src/core/zone';
|
export * from './src/core/zone';
|
||||||
export * from './src/core/render';
|
export * from './src/core/render';
|
||||||
export * from './src/core/linker';
|
export * from './src/core/linker';
|
||||||
export {
|
export {DebugElement, DebugNode, asNativeElements} from './src/core/debug/debug_node';
|
||||||
DebugElement,
|
|
||||||
Scope,
|
|
||||||
inspectElement,
|
|
||||||
asNativeElements
|
|
||||||
} from './src/core/debug/debug_element';
|
|
||||||
export * from './src/core/testability/testability';
|
export * from './src/core/testability/testability';
|
||||||
export * from './src/core/change_detection';
|
export * from './src/core/change_detection';
|
||||||
export * from './src/core/platform_directives_and_pipes';
|
export * from './src/core/platform_directives_and_pipes';
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
# Modules, barrels and bundles
|
# 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".
|
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:
|
Most bundles come in several flavors:
|
||||||
* regular and minified (got `.min` in their name);
|
* 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.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.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.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.
|
**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.js` | `angular2/upgrade` | prod | no
|
||||||
`upgrade.min.js` | `angular2/upgrade` | prod | yes
|
`upgrade.min.js` | `angular2/upgrade` | prod | yes
|
||||||
`upgrade.dev.js` | `angular2/upgrade` | dev | no
|
`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.
|
**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`.
|
For example people using Angular 2 with `http` and `router` would include: `angular2.js`, `http.js` and `router.js`.
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
Bootstrapping
|
Bootstrapping
|
||||||
@cheatsheetIndex 0
|
@cheatsheetIndex 0
|
||||||
@description
|
@description
|
||||||
{@target ts}`import {bootstrap} from 'angular2/angular2';`{@endtarget}
|
{@target ts}`import {bootstrap} from 'angular2/platform/browser';`{@endtarget}
|
||||||
{@target js}Available from the `ng.platform.browser` namespace.{@endtarget}
|
{@target js}Available from the `ng.platform.browser` namespace{@endtarget}
|
||||||
{@target dart}`import 'package:angular2/bootstrap.dart';`{@endtarget}
|
{@target dart}`import 'package:angular2/bootstrap.dart';`{@endtarget}
|
||||||
|
|
||||||
@cheatsheetItem
|
@cheatsheetItem
|
||||||
|
@ -4,7 +4,7 @@ Built-in directives
|
|||||||
@description
|
@description
|
||||||
{@target ts}`import {NgIf, ...} from 'angular2/common';`{@endtarget}
|
{@target ts}`import {NgIf, ...} from 'angular2/common';`{@endtarget}
|
||||||
{@target js}Available from the `ng.common` namespace{@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
|
@cheatsheetItem
|
||||||
syntax:
|
syntax:
|
||||||
|
@ -4,7 +4,7 @@ Class decorators
|
|||||||
@description
|
@description
|
||||||
{@target ts}`import {Directive, ...} from 'angular2/core';`{@endtarget}
|
{@target ts}`import {Directive, ...} from 'angular2/core';`{@endtarget}
|
||||||
{@target js}Available from the `ng.core` namespace{@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
|
@cheatsheetItem
|
||||||
syntax(ts):
|
syntax(ts):
|
||||||
|
@ -4,7 +4,7 @@ Dependency injection configuration
|
|||||||
@description
|
@description
|
||||||
{@target ts}`import {provide} from 'angular2/core';`{@endtarget}
|
{@target ts}`import {provide} from 'angular2/core';`{@endtarget}
|
||||||
{@target js}Available from the `ng.core` namespace{@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
|
@cheatsheetItem
|
||||||
syntax(ts dart):
|
syntax(ts dart):
|
||||||
|
@ -4,7 +4,7 @@ Class field decorators for directives and components
|
|||||||
@description
|
@description
|
||||||
{@target ts}`import {Input, ...} from 'angular2/core';`{@endtarget}
|
{@target ts}`import {Input, ...} from 'angular2/core';`{@endtarget}
|
||||||
{@target js}Available from the `ng.core` namespace{@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
|
@cheatsheetItem
|
||||||
syntax(ts dart):
|
syntax(ts dart):
|
||||||
|
@ -4,7 +4,7 @@ Forms
|
|||||||
@description
|
@description
|
||||||
{@target ts}`import {FORM_DIRECTIVES} from 'angular2/common';`{@endtarget}
|
{@target ts}`import {FORM_DIRECTIVES} from 'angular2/common';`{@endtarget}
|
||||||
{@target js}Available from `ng.common.FORM_DIRECTIVES`{@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
|
@cheatsheetItem
|
||||||
syntax:
|
syntax:
|
||||||
|
@ -4,22 +4,22 @@ Routing and navigation
|
|||||||
@description
|
@description
|
||||||
{@target ts}`import {RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, ...} from 'angular2/router';`{@endtarget}
|
{@target ts}`import {RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, ...} from 'angular2/router';`{@endtarget}
|
||||||
{@target js}Available from the `ng.router` namespace{@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
|
@cheatsheetItem
|
||||||
syntax(ts):
|
syntax(ts):
|
||||||
`@RouteConfig([
|
`@RouteConfig([
|
||||||
{ path: '/:myParam', component: MyComponent, as: 'MyCmp' },
|
{ path: '/:myParam', component: MyComponent, name: 'MyCmp' },
|
||||||
{ path: '/staticPath', component: ..., as: ...},
|
{ path: '/staticPath', component: ..., name: ...},
|
||||||
{ path: '/*wildCardParam', component: ..., as: ...}
|
{ path: '/*wildCardParam', component: ..., name: ...}
|
||||||
])
|
])
|
||||||
class MyComponent() {}`|`@RouteConfig`
|
class MyComponent() {}`|`@RouteConfig`
|
||||||
syntax(js):
|
syntax(js):
|
||||||
`var MyComponent = ng.router.RouteConfig([
|
`var MyComponent = ng.router.RouteConfig([
|
||||||
{ path: '/:myParam', component: MyComponent, as: 'MyCmp' },
|
{ path: '/:myParam', component: MyComponent, name: 'MyCmp' },
|
||||||
{ path: '/staticPath', component: ..., as: ...},
|
{ path: '/staticPath', component: ..., name: ...},
|
||||||
{ path: '/*wildCardParam', component: ..., as: ...}
|
{ path: '/*wildCardParam', component: ..., name: ...}
|
||||||
]).Class({
|
]).Class({
|
||||||
constructor: function() {}
|
constructor: function() {}
|
||||||
});`|`ng.router.RouteConfig`
|
});`|`ng.router.RouteConfig`
|
||||||
|
@ -71,7 +71,7 @@ The `*` symbol means that the current element will be turned into an embedded te
|
|||||||
syntax:
|
syntax:
|
||||||
`<p>Card No.: {{cardNumber | myCreditCardNumberFormatter}}</p>`|`{{cardNumber | myCreditCardNumberFormatter}}`
|
`<p>Card No.: {{cardNumber | myCreditCardNumberFormatter}}</p>`|`{{cardNumber | myCreditCardNumberFormatter}}`
|
||||||
description:
|
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
|
@cheatsheetItem
|
||||||
syntax:
|
syntax:
|
||||||
|
@ -456,7 +456,7 @@ Where
|
|||||||
* `local` is a local identifier for local variables.
|
* `local` is a local identifier for local variables.
|
||||||
* `internal` is an internal variable which the directive exports for binding.
|
* `internal` is an internal variable which the directive exports for binding.
|
||||||
* `key` is an attribute name usually only used to trigger a specific directive.
|
* `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
|
* `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.
|
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
|
* `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 {platform, Provider, APP_INITIALIZER, Injector} from 'angular2/core';
|
||||||
import {
|
import {
|
||||||
WORKER_RENDER_PLATFORM,
|
WORKER_RENDER_PLATFORM,
|
||||||
WORKER_RENDER_APP_COMMON,
|
WORKER_RENDER_APPLICATION_COMMON,
|
||||||
initializeGenericWorkerRenderer,
|
initializeGenericWorkerRenderer,
|
||||||
MessageBus
|
MessageBus
|
||||||
} from 'angular2/platform/worker_render';
|
} from 'angular2/platform/worker_render';
|
||||||
|
|
||||||
var bus = new MyAwesomeMessageBus();
|
var bus = new MyAwesomeMessageBus();
|
||||||
platform([WORKER_RENDER_PLATFORM])
|
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, {
|
new Provider(APP_INITIALIZER, {
|
||||||
useFactory: (injector) => () => initializeGenericWorkerRenderer(injector),
|
useFactory: (injector) => () => initializeGenericWorkerRenderer(injector),
|
||||||
deps: [Injector],
|
deps: [Injector],
|
||||||
@ -419,7 +419,7 @@ import 'package:angular2/platform/worker_render.dart';
|
|||||||
main() {
|
main() {
|
||||||
var bus = new MyAwesomeMessageBus();
|
var bus = new MyAwesomeMessageBus();
|
||||||
platform([WORKER_RENDER_PLATFORM])
|
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,
|
new Provider(APP_INITIALIZER,
|
||||||
useFactory: (injector) => () => initializeGenericWorkerRenderer(injector),
|
useFactory: (injector) => () => initializeGenericWorkerRenderer(injector),
|
||||||
deps: [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.
|
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_APP` providers include an application initializer that starts a new WebWorker/Isolate.
|
This is because the `WORKER_RENDER_APPLICATION` 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.
|
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`.
|
However, we now need to provide our own app initializer. At the very least this initializer needs to call `initializeGenericWorkerRenderer`.
|
||||||
|
|
||||||
## MessageBroker
|
## MessageBroker
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
import {DebugElement, Scope} from 'angular2/core';
|
import {DebugElement} from 'angular2/core';
|
||||||
|
|
||||||
var debugElement: DebugElement;
|
var debugElement: DebugElement;
|
||||||
var predicate;
|
var predicate;
|
||||||
|
|
||||||
// #docregion scope_all
|
// #docregion scope_all
|
||||||
debugElement.query(predicate, Scope.all);
|
debugElement.query(predicate);
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
// #docregion scope_light
|
|
||||||
debugElement.query(predicate, Scope.light);
|
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
// #docregion scope_view
|
|
||||||
debugElement.query(predicate, Scope.view);
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
import {By} from 'angular2/platform/browser';
|
import {By} from 'angular2/platform/browser';
|
||||||
import {DebugElement, Scope} from 'angular2/core';
|
import {DebugElement} from 'angular2/core';
|
||||||
|
|
||||||
var debugElement: DebugElement;
|
var debugElement: DebugElement;
|
||||||
class MyDirective {}
|
class MyDirective {}
|
||||||
|
|
||||||
// #docregion by_all
|
// #docregion by_all
|
||||||
debugElement.query(By.all(), Scope.all);
|
debugElement.query(By.all());
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
// #docregion by_css
|
// #docregion by_css
|
||||||
debugElement.query(By.css('[attribute]'), Scope.all);
|
debugElement.query(By.css('[attribute]'));
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
// #docregion by_directive
|
// #docregion by_directive
|
||||||
debugElement.query(By.directive(MyDirective), Scope.all);
|
debugElement.query(By.directive(MyDirective));
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
@ -141,6 +141,7 @@ export {URLSearchParams} from './src/http/url_search_params';
|
|||||||
* // Send a response to the request
|
* // Send a response to the request
|
||||||
* connection.mockRespond(response);
|
* connection.mockRespond(response);
|
||||||
* });
|
* });
|
||||||
|
* }
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
* http.get('people.json').observer({
|
* http.get('people.json').observer({
|
||||||
@ -156,7 +157,8 @@ export const HTTP_PROVIDERS: any[] = [
|
|||||||
// issue: https://github.com/angular/angular/issues/3183
|
// issue: https://github.com/angular/angular/issues/3183
|
||||||
provide(Http,
|
provide(Http,
|
||||||
{
|
{
|
||||||
useFactory: (xhrBackend, requestOptions) => new Http(xhrBackend, requestOptions),
|
useFactory: (xhrBackend: XHRBackend, requestOptions: RequestOptions) =>
|
||||||
|
new Http(xhrBackend, requestOptions),
|
||||||
deps: [XHRBackend, RequestOptions]
|
deps: [XHRBackend, RequestOptions]
|
||||||
}),
|
}),
|
||||||
BrowserXhr,
|
BrowserXhr,
|
||||||
@ -268,6 +270,7 @@ export const HTTP_BINDINGS = HTTP_PROVIDERS;
|
|||||||
* // Send a response to the request
|
* // Send a response to the request
|
||||||
* connection.mockRespond(response);
|
* connection.mockRespond(response);
|
||||||
* });
|
* });
|
||||||
|
* }
|
||||||
* });
|
* });
|
||||||
|
|
||||||
* jsonp.get('people.json').observer({
|
* jsonp.get('people.json').observer({
|
||||||
@ -283,7 +286,8 @@ export const JSONP_PROVIDERS: any[] = [
|
|||||||
// issue: https://github.com/angular/angular/issues/3183
|
// issue: https://github.com/angular/angular/issues/3183
|
||||||
provide(Jsonp,
|
provide(Jsonp,
|
||||||
{
|
{
|
||||||
useFactory: (jsonpBackend, requestOptions) => new Jsonp(jsonpBackend, requestOptions),
|
useFactory: (jsonpBackend: JSONPBackend, requestOptions: RequestOptions) =>
|
||||||
|
new Jsonp(jsonpBackend, requestOptions),
|
||||||
deps: [JSONPBackend, RequestOptions]
|
deps: [JSONPBackend, RequestOptions]
|
||||||
}),
|
}),
|
||||||
BrowserJsonp,
|
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.
|
* Subset of es6-shim typings.
|
||||||
* This file is also used to propagate our transitive typings
|
* Angular should not require use of ES6 runtime but some API usages are already present.
|
||||||
* to users.
|
* 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 %>",
|
"license": "<%= packageJson.license %>",
|
||||||
"repository": <%= JSON.stringify(packageJson.repository) %>,
|
"repository": <%= JSON.stringify(packageJson.repository) %>,
|
||||||
"devDependencies": <%= JSON.stringify(packageJson.defaultDevDependencies) %>,
|
"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": {
|
"peerDependencies": {
|
||||||
"es6-promise": "<%= packageJson.dependencies['es6-promise'] %>",
|
"es6-promise": "<%= packageJson.dependencies['es6-promise'] %>",
|
||||||
"es6-shim": "<%= packageJson.dependencies['es6-shim'] %>",
|
"es6-shim": "<%= packageJson.dependencies['es6-shim'] %>",
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
export {AngularEntrypoint} from 'angular2/src/core/angular_entrypoint';
|
export {AngularEntrypoint} from 'angular2/src/core/angular_entrypoint';
|
||||||
export {
|
export {
|
||||||
BROWSER_PROVIDERS,
|
BROWSER_PROVIDERS,
|
||||||
ELEMENT_PROBE_BINDINGS,
|
|
||||||
ELEMENT_PROBE_PROVIDERS,
|
ELEMENT_PROBE_PROVIDERS,
|
||||||
|
ELEMENT_PROBE_PROVIDERS_PROD_MODE,
|
||||||
inspectNativeElement,
|
inspectNativeElement,
|
||||||
BrowserDomAdapter,
|
BrowserDomAdapter,
|
||||||
By,
|
By,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
export {AngularEntrypoint} from 'angular2/src/core/angular_entrypoint';
|
export {AngularEntrypoint} from 'angular2/src/core/angular_entrypoint';
|
||||||
export {
|
export {
|
||||||
BROWSER_PROVIDERS,
|
BROWSER_PROVIDERS,
|
||||||
ELEMENT_PROBE_BINDINGS,
|
|
||||||
ELEMENT_PROBE_PROVIDERS,
|
ELEMENT_PROBE_PROVIDERS,
|
||||||
|
ELEMENT_PROBE_PROVIDERS_PROD_MODE,
|
||||||
inspectNativeElement,
|
inspectNativeElement,
|
||||||
BrowserDomAdapter,
|
BrowserDomAdapter,
|
||||||
By,
|
By,
|
||||||
|
@ -12,4 +12,4 @@ export {
|
|||||||
EventManagerPlugin
|
EventManagerPlugin
|
||||||
} from 'angular2/src/platform/dom/events/event_manager';
|
} from 'angular2/src/platform/dom/events/event_manager';
|
||||||
export * from 'angular2/src/platform/dom/debug/by';
|
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;
|
show ReceivedMessage, ServiceMessageBroker, ServiceMessageBrokerFactory;
|
||||||
export 'package:angular2/src/web_workers/shared/serializer.dart' show PRIMITIVE;
|
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/shared/message_bus.dart';
|
||||||
|
export 'package:angular2/src/web_workers/worker/router_providers.dart'
|
||||||
|
show WORKER_APP_ROUTER;
|
||||||
|
@ -8,12 +8,13 @@ export {
|
|||||||
ClientMessageBrokerFactory,
|
ClientMessageBrokerFactory,
|
||||||
FnArg,
|
FnArg,
|
||||||
UiArguments
|
UiArguments
|
||||||
} from '../src/web_workers/shared/client_message_broker';
|
} from 'angular2/src/web_workers/shared/client_message_broker';
|
||||||
export {
|
export {
|
||||||
ReceivedMessage,
|
ReceivedMessage,
|
||||||
ServiceMessageBroker,
|
ServiceMessageBroker,
|
||||||
ServiceMessageBrokerFactory
|
ServiceMessageBrokerFactory
|
||||||
} from '../src/web_workers/shared/service_message_broker';
|
} from 'angular2/src/web_workers/shared/service_message_broker';
|
||||||
export {PRIMITIVE} from '../src/web_workers/shared/serializer';
|
export {PRIMITIVE} from 'angular2/src/web_workers/shared/serializer';
|
||||||
export * from '../src/web_workers/shared/message_bus';
|
export * from 'angular2/src/web_workers/shared/message_bus';
|
||||||
export {AngularEntrypoint} from 'angular2/src/core/angular_entrypoint';
|
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
|
show
|
||||||
WORKER_SCRIPT,
|
WORKER_SCRIPT,
|
||||||
WORKER_RENDER_PLATFORM,
|
WORKER_RENDER_PLATFORM,
|
||||||
WORKER_RENDER_APP_COMMON,
|
WORKER_RENDER_APPLICATION_COMMON,
|
||||||
initializeGenericWorkerRenderer;
|
initializeGenericWorkerRenderer;
|
||||||
|
|
||||||
export 'package:angular2/src/platform/worker_render.dart'
|
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'
|
export '../src/web_workers/shared/client_message_broker.dart'
|
||||||
show ClientMessageBroker, ClientMessageBrokerFactory, FnArg, UiArguments;
|
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/serializer.dart' show PRIMITIVE;
|
||||||
export '../src/web_workers/shared/message_bus.dart';
|
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_SCRIPT,
|
||||||
WORKER_RENDER_PLATFORM,
|
WORKER_RENDER_PLATFORM,
|
||||||
initializeGenericWorkerRenderer,
|
initializeGenericWorkerRenderer,
|
||||||
WORKER_RENDER_APP_COMMON
|
WORKER_RENDER_APPLICATION_COMMON
|
||||||
} from 'angular2/src/platform/worker_render_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 {
|
export {
|
||||||
ClientMessageBroker,
|
ClientMessageBroker,
|
||||||
ClientMessageBrokerFactory,
|
ClientMessageBrokerFactory,
|
||||||
@ -18,3 +18,10 @@ export {
|
|||||||
} from '../src/web_workers/shared/service_message_broker';
|
} from '../src/web_workers/shared/service_message_broker';
|
||||||
export {PRIMITIVE} from '../src/web_workers/shared/serializer';
|
export {PRIMITIVE} from '../src/web_workers/shared/serializer';
|
||||||
export * from '../src/web_workers/shared/message_bus';
|
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:
|
environment:
|
||||||
sdk: '>=1.10.0 <2.0.0'
|
sdk: '>=1.10.0 <2.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
analyzer: '>=0.24.4 <0.27.0'
|
analyzer: '>=0.24.4 <0.28.0'
|
||||||
barback: '^0.15.2+2'
|
barback: '^0.15.2+2'
|
||||||
code_transformers: '0.2.9+4'
|
|
||||||
dart_style: '>=0.1.8 <0.3.0'
|
dart_style: '>=0.1.8 <0.3.0'
|
||||||
glob: '^1.0.0'
|
glob: '^1.0.0'
|
||||||
html: '^0.12.0'
|
html: '^0.12.0'
|
||||||
@ -23,7 +22,9 @@ dependencies:
|
|||||||
source_span: '^1.0.0'
|
source_span: '^1.0.0'
|
||||||
stack_trace: '^1.1.1'
|
stack_trace: '^1.1.1'
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
code_transformers: '>=0.2.9+4 <0.4.0'
|
||||||
guinness: '^0.1.18'
|
guinness: '^0.1.18'
|
||||||
|
test: '^0.12.6'
|
||||||
transformers:
|
transformers:
|
||||||
- angular2
|
- angular2
|
||||||
- $dart2js:
|
- $dart2js:
|
||||||
|
@ -20,18 +20,12 @@ export {OnActivate, OnDeactivate, OnReuse, CanDeactivate, CanReuse} from './src/
|
|||||||
export {CanActivate} from './src/router/lifecycle_annotations';
|
export {CanActivate} from './src/router/lifecycle_annotations';
|
||||||
export {Instruction, ComponentInstruction} from './src/router/instruction';
|
export {Instruction, ComponentInstruction} from './src/router/instruction';
|
||||||
export {OpaqueToken} from 'angular2/core';
|
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 {RouterOutlet} from './src/router/router_outlet';
|
||||||
import {RouterLink} from './src/router/router_link';
|
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 {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
|
* 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]);
|
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,
|
IterableDiffers,
|
||||||
ViewContainerRef,
|
ViewContainerRef,
|
||||||
TemplateRef,
|
TemplateRef,
|
||||||
EmbeddedViewRef
|
EmbeddedViewRef,
|
||||||
|
TrackByFn
|
||||||
} from 'angular2/core';
|
} from 'angular2/core';
|
||||||
import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
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
|
* See a [live demo](http://plnkr.co/edit/KVuXxDp0qinGDyo307QW?p=preview) for a more detailed
|
||||||
* example.
|
* example.
|
||||||
*/
|
*/
|
||||||
@Directive({selector: '[ngFor][ngForOf]', inputs: ['ngForOf', 'ngForTemplate']})
|
@Directive({selector: '[ngFor][ngForOf]', inputs: ['ngForTrackBy', 'ngForOf', 'ngForTemplate']})
|
||||||
export class NgFor implements DoCheck {
|
export class NgFor implements DoCheck {
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_ngForOf: any;
|
_ngForOf: any;
|
||||||
|
_ngForTrackBy: TrackByFn;
|
||||||
private _differ: IterableDiffer;
|
private _differ: IterableDiffer;
|
||||||
|
|
||||||
constructor(private _viewContainer: ViewContainerRef, private _templateRef: TemplateRef,
|
constructor(private _viewContainer: ViewContainerRef, private _templateRef: TemplateRef,
|
||||||
@ -71,7 +73,7 @@ export class NgFor implements DoCheck {
|
|||||||
set ngForOf(value: any) {
|
set ngForOf(value: any) {
|
||||||
this._ngForOf = value;
|
this._ngForOf = value;
|
||||||
if (isBlank(this._differ) && isPresent(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() {
|
ngDoCheck() {
|
||||||
if (isPresent(this._differ)) {
|
if (isPresent(this._differ)) {
|
||||||
var changes = this._differ.diff(this._ngForOf);
|
var changes = this._differ.diff(this._ngForOf);
|
||||||
@ -113,6 +117,11 @@ export class NgFor implements DoCheck {
|
|||||||
var viewRef = <EmbeddedViewRef>this._viewContainer.get(i);
|
var viewRef = <EmbeddedViewRef>this._viewContainer.get(i);
|
||||||
viewRef.setLocal('last', i === ilen - 1);
|
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) {
|
private _perViewChange(view, record) {
|
||||||
|
@ -4,7 +4,8 @@ import {ListWrapper, Map} from 'angular2/src/facade/collection';
|
|||||||
|
|
||||||
const _WHEN_DEFAULT = CONST_EXPR(new Object());
|
const _WHEN_DEFAULT = CONST_EXPR(new Object());
|
||||||
|
|
||||||
class SwitchView {
|
/** @internal */
|
||||||
|
export class SwitchView {
|
||||||
constructor(private _viewContainerRef: ViewContainerRef, private _templateRef: TemplateRef) {}
|
constructor(private _viewContainerRef: ViewContainerRef, private _templateRef: TemplateRef) {}
|
||||||
|
|
||||||
create(): void { this._viewContainerRef.createEmbeddedView(this._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) {
|
if (collection is! ObservableList) {
|
||||||
throw "Cannot change the type of a collection";
|
throw "Cannot change the type of a collection";
|
||||||
}
|
}
|
||||||
@ -57,7 +57,7 @@ class ObservableListDiff extends DefaultIterableDiffer {
|
|||||||
class ObservableListDiffFactory implements IterableDifferFactory {
|
class ObservableListDiffFactory implements IterableDifferFactory {
|
||||||
const ObservableListDiffFactory();
|
const ObservableListDiffFactory();
|
||||||
bool supports(obj) => obj is ObservableList;
|
bool supports(obj) => obj is ObservableList;
|
||||||
IterableDiffer create(ChangeDetectorRef cdRef) {
|
IterableDiffer create(ChangeDetectorRef cdRef, [Function trackByFn]) {
|
||||||
return new ObservableListDiff(cdRef);
|
return new ObservableListDiff(cdRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ export {
|
|||||||
NgSelectOption,
|
NgSelectOption,
|
||||||
SelectControlValueAccessor
|
SelectControlValueAccessor
|
||||||
} from './forms/directives/select_control_value_accessor';
|
} 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 {NG_VALIDATORS, NG_ASYNC_VALIDATORS, Validators} from './forms/validators';
|
||||||
export {
|
export {
|
||||||
RequiredValidator,
|
RequiredValidator,
|
||||||
@ -39,4 +39,25 @@ export {
|
|||||||
MaxLengthValidator,
|
MaxLengthValidator,
|
||||||
Validator
|
Validator
|
||||||
} from './forms/directives/validators';
|
} 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 {DefaultValueAccessor} from './directives/default_value_accessor';
|
||||||
import {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor';
|
import {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor';
|
||||||
import {NumberValueAccessor} from './directives/number_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 {NgControlStatus} from './directives/ng_control_status';
|
||||||
import {
|
import {
|
||||||
SelectControlValueAccessor,
|
SelectControlValueAccessor,
|
||||||
@ -23,6 +24,10 @@ export {NgFormModel} from './directives/ng_form_model';
|
|||||||
export {NgForm} from './directives/ng_form';
|
export {NgForm} from './directives/ng_form';
|
||||||
export {DefaultValueAccessor} from './directives/default_value_accessor';
|
export {DefaultValueAccessor} from './directives/default_value_accessor';
|
||||||
export {CheckboxControlValueAccessor} from './directives/checkbox_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 {NumberValueAccessor} from './directives/number_value_accessor';
|
||||||
export {NgControlStatus} from './directives/ng_control_status';
|
export {NgControlStatus} from './directives/ng_control_status';
|
||||||
export {
|
export {
|
||||||
@ -63,6 +68,7 @@ export const FORM_DIRECTIVES: Type[] = CONST_EXPR([
|
|||||||
NumberValueAccessor,
|
NumberValueAccessor,
|
||||||
CheckboxControlValueAccessor,
|
CheckboxControlValueAccessor,
|
||||||
SelectControlValueAccessor,
|
SelectControlValueAccessor,
|
||||||
|
RadioControlValueAccessor,
|
||||||
NgControlStatus,
|
NgControlStatus,
|
||||||
|
|
||||||
RequiredValidator,
|
RequiredValidator,
|
||||||
|
@ -18,7 +18,7 @@ const CHECKBOX_VALUE_ACCESSOR = CONST_EXPR(new Provider(
|
|||||||
selector:
|
selector:
|
||||||
'input[type=checkbox][ngControl],input[type=checkbox][ngFormControl],input[type=checkbox][ngModel]',
|
'input[type=checkbox][ngControl],input[type=checkbox][ngFormControl],input[type=checkbox][ngModel]',
|
||||||
host: {'(change)': 'onChange($event.target.checked)', '(blur)': 'onTouched()'},
|
host: {'(change)': 'onChange($event.target.checked)', '(blur)': 'onTouched()'},
|
||||||
bindings: [CHECKBOX_VALUE_ACCESSOR]
|
providers: [CHECKBOX_VALUE_ACCESSOR]
|
||||||
})
|
})
|
||||||
export class CheckboxControlValueAccessor implements ControlValueAccessor {
|
export class CheckboxControlValueAccessor implements ControlValueAccessor {
|
||||||
onChange = (_) => {};
|
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 {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 {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
||||||
|
|
||||||
import {ControlContainer} from './control_container';
|
import {ControlContainer} from './control_container';
|
||||||
@ -13,6 +13,7 @@ import {DefaultValueAccessor} from './default_value_accessor';
|
|||||||
import {NumberValueAccessor} from './number_value_accessor';
|
import {NumberValueAccessor} from './number_value_accessor';
|
||||||
import {CheckboxControlValueAccessor} from './checkbox_value_accessor';
|
import {CheckboxControlValueAccessor} from './checkbox_value_accessor';
|
||||||
import {SelectControlValueAccessor} from './select_control_value_accessor';
|
import {SelectControlValueAccessor} from './select_control_value_accessor';
|
||||||
|
import {RadioControlValueAccessor} from './radio_control_value_accessor';
|
||||||
import {normalizeValidator} from './normalize_validator';
|
import {normalizeValidator} from './normalize_validator';
|
||||||
|
|
||||||
|
|
||||||
@ -81,11 +82,13 @@ export function selectValueAccessor(dir: NgControl,
|
|||||||
var builtinAccessor;
|
var builtinAccessor;
|
||||||
var customAccessor;
|
var customAccessor;
|
||||||
valueAccessors.forEach(v => {
|
valueAccessors.forEach(v => {
|
||||||
if (v instanceof DefaultValueAccessor) {
|
if (hasConstructor(v, DefaultValueAccessor)) {
|
||||||
defaultAccessor = v;
|
defaultAccessor = v;
|
||||||
|
|
||||||
} else if (v instanceof CheckboxControlValueAccessor || v instanceof NumberValueAccessor ||
|
} else if (hasConstructor(v, CheckboxControlValueAccessor) ||
|
||||||
v instanceof SelectControlValueAccessor) {
|
hasConstructor(v, NumberValueAccessor) ||
|
||||||
|
hasConstructor(v, SelectControlValueAccessor) ||
|
||||||
|
hasConstructor(v, RadioControlValueAccessor)) {
|
||||||
if (isPresent(builtinAccessor))
|
if (isPresent(builtinAccessor))
|
||||||
_throwError(dir, "More than one built-in value accessor matches");
|
_throwError(dir, "More than one built-in value accessor matches");
|
||||||
builtinAccessor = v;
|
builtinAccessor = v;
|
||||||
|
@ -106,21 +106,3 @@ export class FormBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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));
|
return isPresent(this.getError(errorCode, path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get root(): AbstractControl {
|
||||||
|
let x: AbstractControl = this;
|
||||||
|
|
||||||
|
while (isPresent(x._parent)) {
|
||||||
|
x = x._parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_updateControlsErrors(): void {
|
_updateControlsErrors(): void {
|
||||||
this._status = this._calculateStatus();
|
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 {PromiseWrapper} from 'angular2/src/facade/promise';
|
||||||
import {ObservableWrapper} from 'angular2/src/facade/async';
|
import {ObservableWrapper} from 'angular2/src/facade/async';
|
||||||
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
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.
|
* Validator that requires controls to have a non-empty value.
|
||||||
*/
|
*/
|
||||||
static required(control: modelModule.Control): {[key: string]: boolean} {
|
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)) {
|
if (isPresent(obj)) {
|
||||||
this._subscribe(obj);
|
this._subscribe(obj);
|
||||||
}
|
}
|
||||||
|
this._latestReturnedValue = this._latestValue;
|
||||||
return this._latestValue;
|
return this._latestValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,10 +73,13 @@ const $LT = 60;
|
|||||||
const $EQ = 61;
|
const $EQ = 61;
|
||||||
const $GT = 62;
|
const $GT = 62;
|
||||||
const $QUESTION = 63;
|
const $QUESTION = 63;
|
||||||
const $A = 65;
|
|
||||||
const $Z = 90;
|
|
||||||
const $LBRACKET = 91;
|
const $LBRACKET = 91;
|
||||||
const $RBRACKET = 93;
|
const $RBRACKET = 93;
|
||||||
|
const $A = 65;
|
||||||
|
const $F = 70;
|
||||||
|
const $X = 88;
|
||||||
|
const $Z = 90;
|
||||||
|
|
||||||
const $a = 97;
|
const $a = 97;
|
||||||
const $f = 102;
|
const $f = 102;
|
||||||
const $z = 122;
|
const $z = 122;
|
||||||
@ -102,7 +105,6 @@ class ControlFlowError {
|
|||||||
// See http://www.w3.org/TR/html51/syntax.html#writing
|
// See http://www.w3.org/TR/html51/syntax.html#writing
|
||||||
class _HtmlTokenizer {
|
class _HtmlTokenizer {
|
||||||
private input: string;
|
private input: string;
|
||||||
private inputLowercase: string;
|
|
||||||
private length: number;
|
private length: number;
|
||||||
// Note: this is always lowercase!
|
// Note: this is always lowercase!
|
||||||
private peek: number = -1;
|
private peek: number = -1;
|
||||||
@ -117,7 +119,6 @@ class _HtmlTokenizer {
|
|||||||
|
|
||||||
constructor(private file: ParseSourceFile) {
|
constructor(private file: ParseSourceFile) {
|
||||||
this.input = file.content;
|
this.input = file.content;
|
||||||
this.inputLowercase = file.content.toLowerCase();
|
|
||||||
this.length = file.content.length;
|
this.length = file.content.length;
|
||||||
this._advance();
|
this._advance();
|
||||||
}
|
}
|
||||||
@ -133,16 +134,16 @@ class _HtmlTokenizer {
|
|||||||
while (this.peek !== $EOF) {
|
while (this.peek !== $EOF) {
|
||||||
var start = this._getLocation();
|
var start = this._getLocation();
|
||||||
try {
|
try {
|
||||||
if (this._attemptChar($LT)) {
|
if (this._attemptCharCode($LT)) {
|
||||||
if (this._attemptChar($BANG)) {
|
if (this._attemptCharCode($BANG)) {
|
||||||
if (this._attemptChar($LBRACKET)) {
|
if (this._attemptCharCode($LBRACKET)) {
|
||||||
this._consumeCdata(start);
|
this._consumeCdata(start);
|
||||||
} else if (this._attemptChar($MINUS)) {
|
} else if (this._attemptCharCode($MINUS)) {
|
||||||
this._consumeComment(start);
|
this._consumeComment(start);
|
||||||
} else {
|
} else {
|
||||||
this._consumeDocType(start);
|
this._consumeDocType(start);
|
||||||
}
|
}
|
||||||
} else if (this._attemptChar($SLASH)) {
|
} else if (this._attemptCharCode($SLASH)) {
|
||||||
this._consumeTagClose(start);
|
this._consumeTagClose(start);
|
||||||
} else {
|
} else {
|
||||||
this._consumeTagOpen(start);
|
this._consumeTagOpen(start);
|
||||||
@ -205,11 +206,10 @@ class _HtmlTokenizer {
|
|||||||
this.column++;
|
this.column++;
|
||||||
}
|
}
|
||||||
this.index++;
|
this.index++;
|
||||||
this.peek = this.index >= this.length ? $EOF : StringWrapper.charCodeAt(this.inputLowercase,
|
this.peek = this.index >= this.length ? $EOF : StringWrapper.charCodeAt(this.input, this.index);
|
||||||
this.index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _attemptChar(charCode: number): boolean {
|
private _attemptCharCode(charCode: number): boolean {
|
||||||
if (this.peek === charCode) {
|
if (this.peek === charCode) {
|
||||||
this._advance();
|
this._advance();
|
||||||
return true;
|
return true;
|
||||||
@ -217,38 +217,55 @@ class _HtmlTokenizer {
|
|||||||
return false;
|
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();
|
var location = this._getLocation();
|
||||||
if (!this._attemptChar(charCode)) {
|
if (!this._attemptCharCode(charCode)) {
|
||||||
throw this._createError(unexpectedCharacterErrorMsg(this.peek), location);
|
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++) {
|
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 false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
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();
|
var location = this._getLocation();
|
||||||
if (!this._attemptChars(chars)) {
|
if (!this._attemptStr(chars)) {
|
||||||
throw this._createError(unexpectedCharacterErrorMsg(this.peek), location);
|
throw this._createError(unexpectedCharacterErrorMsg(this.peek), location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _attemptUntilFn(predicate: Function) {
|
private _attemptCharCodeUntilFn(predicate: Function) {
|
||||||
while (!predicate(this.peek)) {
|
while (!predicate(this.peek)) {
|
||||||
this._advance();
|
this._advance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _requireUntilFn(predicate: Function, len: number) {
|
private _requireCharCodeUntilFn(predicate: Function, len: number) {
|
||||||
var start = this._getLocation();
|
var start = this._getLocation();
|
||||||
this._attemptUntilFn(predicate);
|
this._attemptCharCodeUntilFn(predicate);
|
||||||
if (this.index - start.offset < len) {
|
if (this.index - start.offset < len) {
|
||||||
throw this._createError(unexpectedCharacterErrorMsg(this.peek), start);
|
throw this._createError(unexpectedCharacterErrorMsg(this.peek), start);
|
||||||
}
|
}
|
||||||
@ -273,10 +290,10 @@ class _HtmlTokenizer {
|
|||||||
private _decodeEntity(): string {
|
private _decodeEntity(): string {
|
||||||
var start = this._getLocation();
|
var start = this._getLocation();
|
||||||
this._advance();
|
this._advance();
|
||||||
if (this._attemptChar($HASH)) {
|
if (this._attemptCharCode($HASH)) {
|
||||||
let isHex = this._attemptChar($x);
|
let isHex = this._attemptCharCode($x) || this._attemptCharCode($X);
|
||||||
let numberStart = this._getLocation().offset;
|
let numberStart = this._getLocation().offset;
|
||||||
this._attemptUntilFn(isDigitEntityEnd);
|
this._attemptCharCodeUntilFn(isDigitEntityEnd);
|
||||||
if (this.peek != $SEMICOLON) {
|
if (this.peek != $SEMICOLON) {
|
||||||
throw this._createError(unexpectedCharacterErrorMsg(this.peek), this._getLocation());
|
throw this._createError(unexpectedCharacterErrorMsg(this.peek), this._getLocation());
|
||||||
}
|
}
|
||||||
@ -291,7 +308,7 @@ class _HtmlTokenizer {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let startPosition = this._savePosition();
|
let startPosition = this._savePosition();
|
||||||
this._attemptUntilFn(isNamedEntityEnd);
|
this._attemptCharCodeUntilFn(isNamedEntityEnd);
|
||||||
if (this.peek != $SEMICOLON) {
|
if (this.peek != $SEMICOLON) {
|
||||||
this._restorePosition(startPosition);
|
this._restorePosition(startPosition);
|
||||||
return '&';
|
return '&';
|
||||||
@ -315,7 +332,7 @@ class _HtmlTokenizer {
|
|||||||
var parts = [];
|
var parts = [];
|
||||||
while (true) {
|
while (true) {
|
||||||
tagCloseStart = this._getLocation();
|
tagCloseStart = this._getLocation();
|
||||||
if (this._attemptChar(firstCharOfEnd) && attemptEndRest()) {
|
if (this._attemptCharCode(firstCharOfEnd) && attemptEndRest()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (this.index > tagCloseStart.offset) {
|
if (this.index > tagCloseStart.offset) {
|
||||||
@ -330,18 +347,18 @@ class _HtmlTokenizer {
|
|||||||
|
|
||||||
private _consumeComment(start: ParseLocation) {
|
private _consumeComment(start: ParseLocation) {
|
||||||
this._beginToken(HtmlTokenType.COMMENT_START, start);
|
this._beginToken(HtmlTokenType.COMMENT_START, start);
|
||||||
this._requireChar($MINUS);
|
this._requireCharCode($MINUS);
|
||||||
this._endToken([]);
|
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._beginToken(HtmlTokenType.COMMENT_END, textToken.sourceSpan.end);
|
||||||
this._endToken([]);
|
this._endToken([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _consumeCdata(start: ParseLocation) {
|
private _consumeCdata(start: ParseLocation) {
|
||||||
this._beginToken(HtmlTokenType.CDATA_START, start);
|
this._beginToken(HtmlTokenType.CDATA_START, start);
|
||||||
this._requireChars('cdata[');
|
this._requireStr('CDATA[');
|
||||||
this._endToken([]);
|
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._beginToken(HtmlTokenType.CDATA_END, textToken.sourceSpan.end);
|
||||||
this._endToken([]);
|
this._endToken([]);
|
||||||
}
|
}
|
||||||
@ -367,7 +384,7 @@ class _HtmlTokenizer {
|
|||||||
} else {
|
} else {
|
||||||
nameStart = nameOrPrefixStart;
|
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);
|
var name = this.input.substring(nameStart, this.index);
|
||||||
return [prefix, name];
|
return [prefix, name];
|
||||||
}
|
}
|
||||||
@ -381,16 +398,16 @@ class _HtmlTokenizer {
|
|||||||
}
|
}
|
||||||
var nameStart = this.index;
|
var nameStart = this.index;
|
||||||
this._consumeTagOpenStart(start);
|
this._consumeTagOpenStart(start);
|
||||||
lowercaseTagName = this.inputLowercase.substring(nameStart, this.index);
|
lowercaseTagName = this.input.substring(nameStart, this.index).toLowerCase();
|
||||||
this._attemptUntilFn(isNotWhitespace);
|
this._attemptCharCodeUntilFn(isNotWhitespace);
|
||||||
while (this.peek !== $SLASH && this.peek !== $GT) {
|
while (this.peek !== $SLASH && this.peek !== $GT) {
|
||||||
this._consumeAttributeName();
|
this._consumeAttributeName();
|
||||||
this._attemptUntilFn(isNotWhitespace);
|
this._attemptCharCodeUntilFn(isNotWhitespace);
|
||||||
if (this._attemptChar($EQ)) {
|
if (this._attemptCharCode($EQ)) {
|
||||||
this._attemptUntilFn(isNotWhitespace);
|
this._attemptCharCodeUntilFn(isNotWhitespace);
|
||||||
this._consumeAttributeValue();
|
this._consumeAttributeValue();
|
||||||
}
|
}
|
||||||
this._attemptUntilFn(isNotWhitespace);
|
this._attemptCharCodeUntilFn(isNotWhitespace);
|
||||||
}
|
}
|
||||||
this._consumeTagOpenEnd();
|
this._consumeTagOpenEnd();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -416,11 +433,11 @@ class _HtmlTokenizer {
|
|||||||
|
|
||||||
private _consumeRawTextWithTagClose(lowercaseTagName: string, decodeEntities: boolean) {
|
private _consumeRawTextWithTagClose(lowercaseTagName: string, decodeEntities: boolean) {
|
||||||
var textToken = this._consumeRawText(decodeEntities, $LT, () => {
|
var textToken = this._consumeRawText(decodeEntities, $LT, () => {
|
||||||
if (!this._attemptChar($SLASH)) return false;
|
if (!this._attemptCharCode($SLASH)) return false;
|
||||||
this._attemptUntilFn(isNotWhitespace);
|
this._attemptCharCodeUntilFn(isNotWhitespace);
|
||||||
if (!this._attemptChars(lowercaseTagName)) return false;
|
if (!this._attemptStrCaseInsensitive(lowercaseTagName)) return false;
|
||||||
this._attemptUntilFn(isNotWhitespace);
|
this._attemptCharCodeUntilFn(isNotWhitespace);
|
||||||
if (!this._attemptChar($GT)) return false;
|
if (!this._attemptCharCode($GT)) return false;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
this._beginToken(HtmlTokenType.TAG_CLOSE, textToken.sourceSpan.end);
|
this._beginToken(HtmlTokenType.TAG_CLOSE, textToken.sourceSpan.end);
|
||||||
@ -453,27 +470,27 @@ class _HtmlTokenizer {
|
|||||||
this._advance();
|
this._advance();
|
||||||
} else {
|
} else {
|
||||||
var valueStart = this.index;
|
var valueStart = this.index;
|
||||||
this._requireUntilFn(isNameEnd, 1);
|
this._requireCharCodeUntilFn(isNameEnd, 1);
|
||||||
value = this.input.substring(valueStart, this.index);
|
value = this.input.substring(valueStart, this.index);
|
||||||
}
|
}
|
||||||
this._endToken([this._processCarriageReturns(value)]);
|
this._endToken([this._processCarriageReturns(value)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _consumeTagOpenEnd() {
|
private _consumeTagOpenEnd() {
|
||||||
var tokenType =
|
var tokenType = this._attemptCharCode($SLASH) ? HtmlTokenType.TAG_OPEN_END_VOID :
|
||||||
this._attemptChar($SLASH) ? HtmlTokenType.TAG_OPEN_END_VOID : HtmlTokenType.TAG_OPEN_END;
|
HtmlTokenType.TAG_OPEN_END;
|
||||||
this._beginToken(tokenType);
|
this._beginToken(tokenType);
|
||||||
this._requireChar($GT);
|
this._requireCharCode($GT);
|
||||||
this._endToken([]);
|
this._endToken([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _consumeTagClose(start: ParseLocation) {
|
private _consumeTagClose(start: ParseLocation) {
|
||||||
this._beginToken(HtmlTokenType.TAG_CLOSE, start);
|
this._beginToken(HtmlTokenType.TAG_CLOSE, start);
|
||||||
this._attemptUntilFn(isNotWhitespace);
|
this._attemptCharCodeUntilFn(isNotWhitespace);
|
||||||
var prefixAndName;
|
var prefixAndName;
|
||||||
prefixAndName = this._consumePrefixAndName();
|
prefixAndName = this._consumePrefixAndName();
|
||||||
this._attemptUntilFn(isNotWhitespace);
|
this._attemptCharCodeUntilFn(isNotWhitespace);
|
||||||
this._requireChar($GT);
|
this._requireCharCode($GT);
|
||||||
this._endToken(prefixAndName);
|
this._endToken(prefixAndName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -534,11 +551,19 @@ function isTextEnd(code: number): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isAsciiLetter(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 {
|
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[] {
|
function mergeTextTokens(srcTokens: HtmlToken[]): HtmlToken[] {
|
||||||
|
@ -124,7 +124,7 @@ export class TemplateCompiler {
|
|||||||
var hostMeta: CompileDirectiveMetadata =
|
var hostMeta: CompileDirectiveMetadata =
|
||||||
createHostComponentMeta(compMeta.type, compMeta.selector);
|
createHostComponentMeta(compMeta.type, compMeta.selector);
|
||||||
|
|
||||||
this._compileComponentRuntime(hostCacheKey, hostMeta, [compMeta], [], new Set());
|
this._compileComponentRuntime(hostCacheKey, hostMeta, [compMeta], [], []);
|
||||||
}
|
}
|
||||||
return this._compiledTemplateDone.get(hostCacheKey)
|
return this._compiledTemplateDone.get(hostCacheKey)
|
||||||
.then((compiledTemplate: CompiledTemplate) =>
|
.then((compiledTemplate: CompiledTemplate) =>
|
||||||
@ -172,7 +172,7 @@ export class TemplateCompiler {
|
|||||||
private _compileComponentRuntime(cacheKey: any, compMeta: CompileDirectiveMetadata,
|
private _compileComponentRuntime(cacheKey: any, compMeta: CompileDirectiveMetadata,
|
||||||
viewDirectives: CompileDirectiveMetadata[],
|
viewDirectives: CompileDirectiveMetadata[],
|
||||||
pipes: CompilePipeMetadata[],
|
pipes: CompilePipeMetadata[],
|
||||||
compilingComponentCacheKeys: Set<any>): CompiledTemplate {
|
compilingComponentsPath: any[]): CompiledTemplate {
|
||||||
let uniqViewDirectives = <CompileDirectiveMetadata[]>removeDuplicates(viewDirectives);
|
let uniqViewDirectives = <CompileDirectiveMetadata[]>removeDuplicates(viewDirectives);
|
||||||
let uniqViewPipes = <CompilePipeMetadata[]>removeDuplicates(pipes);
|
let uniqViewPipes = <CompilePipeMetadata[]>removeDuplicates(pipes);
|
||||||
var compiledTemplate = this._compiledTemplateCache.get(cacheKey);
|
var compiledTemplate = this._compiledTemplateCache.get(cacheKey);
|
||||||
@ -180,7 +180,6 @@ export class TemplateCompiler {
|
|||||||
if (isBlank(compiledTemplate)) {
|
if (isBlank(compiledTemplate)) {
|
||||||
compiledTemplate = new CompiledTemplate();
|
compiledTemplate = new CompiledTemplate();
|
||||||
this._compiledTemplateCache.set(cacheKey, compiledTemplate);
|
this._compiledTemplateCache.set(cacheKey, compiledTemplate);
|
||||||
compilingComponentCacheKeys.add(cacheKey);
|
|
||||||
done = PromiseWrapper
|
done = PromiseWrapper
|
||||||
.all([<any>this._styleCompiler.compileComponentRuntime(compMeta.template)].concat(
|
.all([<any>this._styleCompiler.compileComponentRuntime(compMeta.template)].concat(
|
||||||
uniqViewDirectives.map(dirMeta => this.normalizeDirectiveMetadata(dirMeta))))
|
uniqViewDirectives.map(dirMeta => this.normalizeDirectiveMetadata(dirMeta))))
|
||||||
@ -195,14 +194,13 @@ export class TemplateCompiler {
|
|||||||
var usedDirectives = DirectiveCollector.findUsedDirectives(parsedTemplate);
|
var usedDirectives = DirectiveCollector.findUsedDirectives(parsedTemplate);
|
||||||
usedDirectives.components.forEach(
|
usedDirectives.components.forEach(
|
||||||
component => this._compileNestedComponentRuntime(
|
component => this._compileNestedComponentRuntime(
|
||||||
component, compilingComponentCacheKeys, childPromises));
|
component, compilingComponentsPath, childPromises));
|
||||||
return PromiseWrapper.all(childPromises)
|
return PromiseWrapper.all(childPromises)
|
||||||
.then((_) => {
|
.then((_) => {
|
||||||
var filteredPipes = filterPipes(parsedTemplate, uniqViewPipes);
|
var filteredPipes = filterPipes(parsedTemplate, uniqViewPipes);
|
||||||
compiledTemplate.init(this._createViewFactoryRuntime(
|
compiledTemplate.init(this._createViewFactoryRuntime(
|
||||||
compMeta, parsedTemplate, usedDirectives.directives, styles,
|
compMeta, parsedTemplate, usedDirectives.directives, styles,
|
||||||
filteredPipes));
|
filteredPipes));
|
||||||
SetWrapper.delete(compilingComponentCacheKeys, cacheKey);
|
|
||||||
return compiledTemplate;
|
return compiledTemplate;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -212,16 +210,19 @@ export class TemplateCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _compileNestedComponentRuntime(childComponentDir: CompileDirectiveMetadata,
|
private _compileNestedComponentRuntime(childComponentDir: CompileDirectiveMetadata,
|
||||||
compilingComponentCacheKeys: Set<Type>,
|
parentCompilingComponentsPath: any[],
|
||||||
childPromises: Promise<any>[]) {
|
childPromises: Promise<any>[]) {
|
||||||
|
var compilingComponentsPath = ListWrapper.clone(parentCompilingComponentsPath);
|
||||||
|
|
||||||
var childCacheKey = childComponentDir.type.runtime;
|
var childCacheKey = childComponentDir.type.runtime;
|
||||||
var childViewDirectives: CompileDirectiveMetadata[] =
|
var childViewDirectives: CompileDirectiveMetadata[] =
|
||||||
this._runtimeMetadataResolver.getViewDirectivesMetadata(childComponentDir.type.runtime);
|
this._runtimeMetadataResolver.getViewDirectivesMetadata(childComponentDir.type.runtime);
|
||||||
var childViewPipes: CompilePipeMetadata[] =
|
var childViewPipes: CompilePipeMetadata[] =
|
||||||
this._runtimeMetadataResolver.getViewPipesMetadata(childComponentDir.type.runtime);
|
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,
|
this._compileComponentRuntime(childCacheKey, childComponentDir, childViewDirectives,
|
||||||
childViewPipes, compilingComponentCacheKeys);
|
childViewPipes, compilingComponentsPath);
|
||||||
if (!childIsRecursive) {
|
if (!childIsRecursive) {
|
||||||
// Only wait for a child if it is not a cycle
|
// Only wait for a child if it is not a cycle
|
||||||
childPromises.push(this._compiledTemplateDone.get(childCacheKey));
|
childPromises.push(this._compiledTemplateDone.get(childCacheKey));
|
||||||
|
@ -112,6 +112,10 @@ class TemplatePreparseVisitor implements HtmlAstVisitor {
|
|||||||
case PreparsedElementType.STYLESHEET:
|
case PreparsedElementType.STYLESHEET:
|
||||||
this.styleUrls.push(preparsedElement.hrefAttr);
|
this.styleUrls.push(preparsedElement.hrefAttr);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
// DDC reports this as error. See:
|
||||||
|
// https://github.com/dart-lang/dev_compiler/issues/428
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (preparsedElement.nonBindable) {
|
if (preparsedElement.nonBindable) {
|
||||||
this.ngNonBindableStackCount++;
|
this.ngNonBindableStackCount++;
|
||||||
|
@ -52,8 +52,8 @@ import {splitAtColon} from './util';
|
|||||||
// Group 3 = "on-"
|
// Group 3 = "on-"
|
||||||
// Group 4 = "bindon-"
|
// Group 4 = "bindon-"
|
||||||
// Group 5 = the identifier after "bind-", "var-/#", or "on-"
|
// Group 5 = the identifier after "bind-", "var-/#", or "on-"
|
||||||
// Group 6 = identifer inside [()]
|
// Group 6 = identifier inside [()]
|
||||||
// Group 7 = identifer inside []
|
// Group 7 = identifier inside []
|
||||||
// Group 8 = identifier inside ()
|
// Group 8 = identifier inside ()
|
||||||
var BIND_NAME_REGEXP =
|
var BIND_NAME_REGEXP =
|
||||||
/^(?:(?:(?:(bind-)|(var-|#)|(on-)|(bindon-))(.+))|\[\(([^\)]+)\)\]|\[([^\]]+)\]|\(([^\)]+)\))$/g;
|
/^(?:(?:(?:(bind-)|(var-|#)|(on-)|(bindon-))(.+))|\[\(([^\)]+)\)\]|\[([^\]]+)\]|\(([^\)]+)\))$/g;
|
||||||
@ -433,8 +433,9 @@ class TemplateParseVisitor implements HtmlAstVisitor {
|
|||||||
var parts = splitAtColon(name, [null, name]);
|
var parts = splitAtColon(name, [null, name]);
|
||||||
var target = parts[0];
|
var target = parts[0];
|
||||||
var eventName = parts[1];
|
var eventName = parts[1];
|
||||||
targetEvents.push(new BoundEventAst(eventName, target,
|
var ast = this._parseAction(expression, sourceSpan);
|
||||||
this._parseAction(expression, sourceSpan), sourceSpan));
|
targetMatchableAttrs.push([name, ast.source]);
|
||||||
|
targetEvents.push(new BoundEventAst(eventName, target, ast, sourceSpan));
|
||||||
// Don't detect directives for event names for now,
|
// Don't detect directives for event names for now,
|
||||||
// so don't add the event name to the matchableAttrs
|
// 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,
|
createElementEventListener(renderer: EXPRESSION, view: EXPRESSION, boundElementIndex: number,
|
||||||
renderNode: EXPRESSION, eventAst: BoundEventAst,
|
renderNode: EXPRESSION, eventAst: BoundEventAst,
|
||||||
targetStatements: STATEMENT[]);
|
targetStatements: STATEMENT[]): EXPRESSION;
|
||||||
|
|
||||||
setElementAttribute(renderer: EXPRESSION, renderNode: EXPRESSION, attrName: string,
|
setElementAttribute(renderer: EXPRESSION, renderNode: EXPRESSION, attrName: string,
|
||||||
attrValue: string, targetStatements: STATEMENT[]);
|
attrValue: string, targetStatements: STATEMENT[]);
|
||||||
@ -201,9 +201,11 @@ class CodeGenViewFactory implements ViewFactory<Expression, Statement> {
|
|||||||
createElementEventListener(renderer: Expression, appView: Expression, boundElementIndex: number,
|
createElementEventListener(renderer: Expression, appView: Expression, boundElementIndex: number,
|
||||||
renderNode: Expression, eventAst: BoundEventAst,
|
renderNode: Expression, eventAst: BoundEventAst,
|
||||||
targetStatements: Statement[]) {
|
targetStatements: Statement[]) {
|
||||||
|
var disposableVar = this._nextDisposableVar();
|
||||||
var eventHandlerExpr = codeGenEventHandler(appView, boundElementIndex, eventAst.fullName);
|
var eventHandlerExpr = codeGenEventHandler(appView, boundElementIndex, eventAst.fullName);
|
||||||
targetStatements.push(new Statement(
|
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,
|
setElementAttribute(renderer: Expression, renderNode: Expression, attrName: string,
|
||||||
@ -345,9 +347,11 @@ class RuntimeViewFactory implements ViewFactory<any, any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createElementEventListener(renderer: Renderer, appView: AppView, boundElementIndex: number,
|
createElementEventListener(renderer: Renderer, appView: AppView, boundElementIndex: number,
|
||||||
renderNode: any, eventAst: BoundEventAst, targetStatements: any[]) {
|
renderNode: any, eventAst: BoundEventAst,
|
||||||
renderer.listen(renderNode, eventAst.name, (event) => appView.triggerEventHandlers(
|
targetStatements: any[]): any {
|
||||||
eventAst.fullName, event, boundElementIndex));
|
return renderer.listen(
|
||||||
|
renderNode, eventAst.name,
|
||||||
|
(event) => appView.triggerEventHandlers(eventAst.fullName, event, boundElementIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
setElementAttribute(renderer: Renderer, renderNode: any, attrName: string, attrValue: string,
|
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];
|
var protoEl = this.protoView.protoElements[elementIndex];
|
||||||
|
|
||||||
protoEl.renderEvents.forEach((eventAst) => {
|
protoEl.renderEvents.forEach((eventAst) => {
|
||||||
|
var disposable;
|
||||||
if (isPresent(eventAst.target)) {
|
if (isPresent(eventAst.target)) {
|
||||||
var disposable = this.factory.createGlobalEventListener(
|
disposable = this.factory.createGlobalEventListener(
|
||||||
this.renderer, this.view, protoEl.boundElementIndex, eventAst, this.renderStmts);
|
this.renderer, this.view, protoEl.boundElementIndex, eventAst, this.renderStmts);
|
||||||
this.appDisposables.push(disposable);
|
|
||||||
} else {
|
} else {
|
||||||
this.factory.createElementEventListener(this.renderer, this.view, protoEl.boundElementIndex,
|
disposable = this.factory.createElementEventListener(this.renderer, this.view,
|
||||||
renderNode, eventAst, this.renderStmts);
|
protoEl.boundElementIndex, renderNode,
|
||||||
|
eventAst, this.renderStmts);
|
||||||
}
|
}
|
||||||
|
this.appDisposables.push(disposable);
|
||||||
});
|
});
|
||||||
for (var i = 0; i < protoEl.attrNameAndValues.length; i++) {
|
for (var i = 0; i < protoEl.attrNameAndValues.length; i++) {
|
||||||
var attrName = protoEl.attrNameAndValues[i][0];
|
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 {AppViewManager_} from "./linker/view_manager";
|
import {AppViewManager_} from "./linker/view_manager";
|
||||||
import {ViewResolver} from './linker/view_resolver';
|
import {ViewResolver} from './linker/view_resolver';
|
||||||
import {AppViewListener} from './linker/view_listener';
|
|
||||||
import {DirectiveResolver} from './linker/directive_resolver';
|
import {DirectiveResolver} from './linker/directive_resolver';
|
||||||
import {PipeResolver} from './linker/pipe_resolver';
|
import {PipeResolver} from './linker/pipe_resolver';
|
||||||
import {Compiler} from './linker/compiler';
|
import {Compiler} from './linker/compiler';
|
||||||
@ -32,7 +31,6 @@ export const APPLICATION_COMMON_PROVIDERS: Array<Type | Provider | any[]> = CONS
|
|||||||
APP_ID_RANDOM_PROVIDER,
|
APP_ID_RANDOM_PROVIDER,
|
||||||
ResolvedMetadataCache,
|
ResolvedMetadataCache,
|
||||||
new Provider(AppViewManager, {useClass: AppViewManager_}),
|
new Provider(AppViewManager, {useClass: AppViewManager_}),
|
||||||
AppViewListener,
|
|
||||||
ViewResolver,
|
ViewResolver,
|
||||||
new Provider(IterableDiffers, {useValue: defaultIterableDiffers}),
|
new Provider(IterableDiffers, {useValue: defaultIterableDiffers}),
|
||||||
new Provider(KeyValueDiffers, {useValue: defaultKeyValueDiffers}),
|
new Provider(KeyValueDiffers, {useValue: defaultKeyValueDiffers}),
|
||||||
|
@ -217,25 +217,36 @@ export class PlatformRef_ extends PlatformRef {
|
|||||||
|
|
||||||
application(providers: Array<Type | Provider | any[]>): ApplicationRef {
|
application(providers: Array<Type | Provider | any[]>): ApplicationRef {
|
||||||
var app = this._initApp(createNgZone(), providers);
|
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[]>>,
|
asyncApplication(bindingFn: (zone: NgZone) => Promise<Array<Type | Provider | any[]>>,
|
||||||
additionalProviders?: Array<Type | Provider | any[]>): Promise<ApplicationRef> {
|
additionalProviders?: Array<Type | Provider | any[]>): Promise<ApplicationRef> {
|
||||||
var zone = createNgZone();
|
var zone = createNgZone();
|
||||||
var completer = PromiseWrapper.completer();
|
var completer = PromiseWrapper.completer();
|
||||||
|
if (bindingFn === null) {
|
||||||
|
completer.resolve(this._initApp(zone, additionalProviders));
|
||||||
|
} else {
|
||||||
zone.run(() => {
|
zone.run(() => {
|
||||||
PromiseWrapper.then(bindingFn(zone), (providers: Array<Type | Provider | any[]>) => {
|
PromiseWrapper.then(bindingFn(zone), (providers: Array<Type | Provider | any[]>) => {
|
||||||
if (isPresent(additionalProviders)) {
|
if (isPresent(additionalProviders)) {
|
||||||
providers = ListWrapper.concat(providers, additionalProviders);
|
providers = ListWrapper.concat(providers, additionalProviders);
|
||||||
}
|
}
|
||||||
completer.resolve(this._initApp(zone, providers));
|
let promise = this._initApp(zone, providers);
|
||||||
|
completer.resolve(promise);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
return completer.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 injector: Injector;
|
||||||
var app: ApplicationRef;
|
var app: ApplicationRef;
|
||||||
zone.run(() => {
|
zone.run(() => {
|
||||||
@ -259,9 +270,13 @@ export class PlatformRef_ extends PlatformRef {
|
|||||||
});
|
});
|
||||||
app = new ApplicationRef_(this, zone, injector);
|
app = new ApplicationRef_(this, zone, injector);
|
||||||
this._applications.push(app);
|
this._applications.push(app);
|
||||||
_runAppInitializers(injector);
|
var promise = _runAppInitializers(injector);
|
||||||
|
if (promise !== null) {
|
||||||
|
return PromiseWrapper.then(promise, (_) => app);
|
||||||
|
} else {
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dispose(): void {
|
dispose(): void {
|
||||||
ListWrapper.clone(this._applications).forEach((app) => app.dispose());
|
ListWrapper.clone(this._applications).forEach((app) => app.dispose());
|
||||||
@ -273,9 +288,22 @@ export class PlatformRef_ extends PlatformRef {
|
|||||||
_applicationDisposed(app: ApplicationRef): void { ListWrapper.remove(this._applications, app); }
|
_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);
|
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(_ => {
|
return completer.promise.then(_ => {
|
||||||
let c = this._injector.get(Console);
|
let c = this._injector.get(Console);
|
||||||
let modeDescription =
|
if (assertionsEnabled()) {
|
||||||
assertionsEnabled() ?
|
c.log(
|
||||||
"in the development mode. Call enableProdMode() to enable the production mode." :
|
"Angular 2 is running 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}`);
|
|
||||||
return _;
|
return _;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -485,5 +512,5 @@ export class ApplicationRef_ extends ApplicationRef {
|
|||||||
this._platform._applicationDisposed(this);
|
this._platform._applicationDisposed(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
get componentTypes(): any[] { return this._rootComponentTypes; }
|
get componentTypes(): Type[] { return this._rootComponentTypes; }
|
||||||
}
|
}
|
||||||
|
@ -20,5 +20,6 @@ export {
|
|||||||
IterableDifferFactory,
|
IterableDifferFactory,
|
||||||
KeyValueDiffers,
|
KeyValueDiffers,
|
||||||
KeyValueDiffer,
|
KeyValueDiffer,
|
||||||
KeyValueDifferFactory
|
KeyValueDifferFactory,
|
||||||
|
TrackByFn
|
||||||
} from './change_detection/change_detection';
|
} from './change_detection/change_detection';
|
||||||
|
@ -17,7 +17,7 @@ import {Locals} from './parser/locals';
|
|||||||
import {ChangeDetectionStrategy, ChangeDetectorState} from './constants';
|
import {ChangeDetectionStrategy, ChangeDetectorState} from './constants';
|
||||||
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
|
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
|
||||||
import {isObservable} from './observable_facade';
|
import {isObservable} from './observable_facade';
|
||||||
|
import {ObservableWrapper} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
var _scope_check: WtfScopeFn = wtfCreateScope(`ChangeDetector#check(ascii id, bool throwOnChange)`);
|
var _scope_check: WtfScopeFn = wtfCreateScope(`ChangeDetector#check(ascii id, bool throwOnChange)`);
|
||||||
|
|
||||||
@ -40,6 +40,7 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
|||||||
mode: ChangeDetectionStrategy = null;
|
mode: ChangeDetectionStrategy = null;
|
||||||
pipes: Pipes = null;
|
pipes: Pipes = null;
|
||||||
propertyBindingIndex: number;
|
propertyBindingIndex: number;
|
||||||
|
outputSubscriptions: any[];
|
||||||
|
|
||||||
// This is an experimental feature. Works only in Dart.
|
// This is an experimental feature. Works only in Dart.
|
||||||
subscriptions: any[];
|
subscriptions: any[];
|
||||||
@ -72,7 +73,7 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
|||||||
|
|
||||||
handleEvent(eventName: string, elIndex: number, event: any): boolean {
|
handleEvent(eventName: string, elIndex: number, event: any): boolean {
|
||||||
if (!this.hydrated()) {
|
if (!this.hydrated()) {
|
||||||
return true;
|
this.throwDehydratedError(`${this.id} -> ${eventName}`);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
var locals = new Map<string, any>();
|
var locals = new Map<string, any>();
|
||||||
@ -129,7 +130,7 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
|||||||
// facilitate error reporting.
|
// facilitate error reporting.
|
||||||
detectChangesInRecords(throwOnChange: boolean): void {
|
detectChangesInRecords(throwOnChange: boolean): void {
|
||||||
if (!this.hydrated()) {
|
if (!this.hydrated()) {
|
||||||
this.throwDehydratedError();
|
this.throwDehydratedError(this.id);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
this.detectChangesInRecordsInternal(throwOnChange);
|
this.detectChangesInRecordsInternal(throwOnChange);
|
||||||
@ -180,6 +181,8 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
|||||||
this._unsubsribeFromObservables();
|
this._unsubsribeFromObservables();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._unsubscribeFromOutputs();
|
||||||
|
|
||||||
this.dispatcher = null;
|
this.dispatcher = null;
|
||||||
this.context = null;
|
this.context = null;
|
||||||
this.locals = 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.
|
// This is an experimental feature. Works only in Dart.
|
||||||
observeValue(value: any, index: number): any {
|
observeValue(value: any, index: number): any {
|
||||||
if (isObservable(value)) {
|
if (isObservable(value)) {
|
||||||
@ -350,7 +362,7 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
|||||||
oldValue, newValue, null);
|
oldValue, newValue, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
throwDehydratedError(): void { throw new DehydratedException(); }
|
throwDehydratedError(detail: string): void { throw new DehydratedException(detail); }
|
||||||
|
|
||||||
private _currentBinding(): BindingTarget {
|
private _currentBinding(): BindingTarget {
|
||||||
return this.bindingTargets[this.propertyBindingIndex];
|
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 {DefaultIterableDifferFactory} from './differs/default_iterable_differ';
|
||||||
import {KeyValueDiffers, KeyValueDifferFactory} from './differs/keyvalue_differs';
|
import {KeyValueDiffers, KeyValueDifferFactory} from './differs/keyvalue_differs';
|
||||||
import {DefaultKeyValueDifferFactory} from './differs/default_keyvalue_differ';
|
import {DefaultKeyValueDifferFactory} from './differs/default_keyvalue_differ';
|
||||||
@ -37,7 +37,12 @@ export {BindingRecord, BindingTarget} from './binding_record';
|
|||||||
export {DirectiveIndex, DirectiveRecord} from './directive_record';
|
export {DirectiveIndex, DirectiveRecord} from './directive_record';
|
||||||
export {DynamicChangeDetector} from './dynamic_change_detector';
|
export {DynamicChangeDetector} from './dynamic_change_detector';
|
||||||
export {ChangeDetectorRef} from './change_detector_ref';
|
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 {KeyValueDiffers, KeyValueDiffer, KeyValueDifferFactory} from './differs/keyvalue_differs';
|
||||||
export {PipeTransform} from './pipe_transform';
|
export {PipeTransform} from './pipe_transform';
|
||||||
export {WrappedValue, SimpleChange} from './change_detection_util';
|
export {WrappedValue, SimpleChange} from './change_detection_util';
|
||||||
|
@ -350,6 +350,7 @@ export class ChangeDetectorJITGenerator {
|
|||||||
var condition = `!${pipe}.pure || (${contexOrArgCheck.join(" || ")})`;
|
var condition = `!${pipe}.pure || (${contexOrArgCheck.join(" || ")})`;
|
||||||
|
|
||||||
var check = `
|
var check = `
|
||||||
|
${this._genThrowOnChangeCheck(oldValue, newValue)}
|
||||||
if (${this.changeDetectionUtilVarName}.looseNotIdentical(${oldValue}, ${newValue})) {
|
if (${this.changeDetectionUtilVarName}.looseNotIdentical(${oldValue}, ${newValue})) {
|
||||||
${newValue} = ${this.changeDetectionUtilVarName}.unwrapValue(${newValue})
|
${newValue} = ${this.changeDetectionUtilVarName}.unwrapValue(${newValue})
|
||||||
${this._genChangeMarker(r)}
|
${this._genChangeMarker(r)}
|
||||||
@ -377,6 +378,7 @@ export class ChangeDetectorJITGenerator {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
var check = `
|
var check = `
|
||||||
|
${this._genThrowOnChangeCheck(oldValue, newValue)}
|
||||||
if (${this.changeDetectionUtilVarName}.looseNotIdentical(${oldValue}, ${newValue})) {
|
if (${this.changeDetectionUtilVarName}.looseNotIdentical(${oldValue}, ${newValue})) {
|
||||||
${this._genChangeMarker(r)}
|
${this._genChangeMarker(r)}
|
||||||
${this._genUpdateDirectiveOrElement(r)}
|
${this._genUpdateDirectiveOrElement(r)}
|
||||||
@ -409,7 +411,6 @@ export class ChangeDetectorJITGenerator {
|
|||||||
if (!r.lastInBinding) return "";
|
if (!r.lastInBinding) return "";
|
||||||
|
|
||||||
var newValue = this._names.getLocalName(r.selfIndex);
|
var newValue = this._names.getLocalName(r.selfIndex);
|
||||||
var oldValue = this._names.getFieldName(r.selfIndex);
|
|
||||||
var notifyDebug = this.genConfig.logBindingUpdate ? `this.logBindingUpdate(${newValue});` : "";
|
var notifyDebug = this.genConfig.logBindingUpdate ? `this.logBindingUpdate(${newValue});` : "";
|
||||||
|
|
||||||
var br = r.bindingRecord;
|
var br = r.bindingRecord;
|
||||||
@ -417,14 +418,12 @@ export class ChangeDetectorJITGenerator {
|
|||||||
var directiveProperty =
|
var directiveProperty =
|
||||||
`${this._names.getDirectiveName(br.directiveRecord.directiveIndex)}.${br.target.name}`;
|
`${this._names.getDirectiveName(br.directiveRecord.directiveIndex)}.${br.target.name}`;
|
||||||
return `
|
return `
|
||||||
${this._genThrowOnChangeCheck(oldValue, newValue)}
|
|
||||||
${directiveProperty} = ${newValue};
|
${directiveProperty} = ${newValue};
|
||||||
${notifyDebug}
|
${notifyDebug}
|
||||||
${IS_CHANGED_LOCAL} = true;
|
${IS_CHANGED_LOCAL} = true;
|
||||||
`;
|
`;
|
||||||
} else {
|
} else {
|
||||||
return `
|
return `
|
||||||
${this._genThrowOnChangeCheck(oldValue, newValue)}
|
|
||||||
this.notifyDispatcher(${newValue});
|
this.notifyDispatcher(${newValue});
|
||||||
${notifyDebug}
|
${notifyDebug}
|
||||||
`;
|
`;
|
||||||
@ -435,7 +434,7 @@ export class ChangeDetectorJITGenerator {
|
|||||||
_genThrowOnChangeCheck(oldValue: string, newValue: string): string {
|
_genThrowOnChangeCheck(oldValue: string, newValue: string): string {
|
||||||
if (assertionsEnabled()) {
|
if (assertionsEnabled()) {
|
||||||
return `
|
return `
|
||||||
if(throwOnChange) {
|
if (throwOnChange && !${this.changeDetectionUtilVarName}.devModeEqual(${oldValue}, ${newValue})) {
|
||||||
this.throwOnChangeError(${oldValue}, ${newValue});
|
this.throwOnChangeError(${oldValue}, ${newValue});
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
@ -4,10 +4,17 @@ import {
|
|||||||
isBlank,
|
isBlank,
|
||||||
Type,
|
Type,
|
||||||
StringWrapper,
|
StringWrapper,
|
||||||
looseIdentical
|
looseIdentical,
|
||||||
|
isPrimitive
|
||||||
} from 'angular2/src/facade/lang';
|
} from 'angular2/src/facade/lang';
|
||||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
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 {ProtoRecord} from './proto_record';
|
||||||
import {ChangeDetectionStrategy, isDefaultChangeDetectionStrategy} from './constants';
|
import {ChangeDetectionStrategy, isDefaultChangeDetectionStrategy} from './constants';
|
||||||
import {implementsOnDestroy} from './pipe_lifecycle_reflector';
|
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 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;
|
break;
|
||||||
|
|
||||||
case RecordType.Chain:
|
case RecordType.Chain:
|
||||||
rhs = 'null';
|
rhs = `${getLocalName(protoRec.args[protoRec.args.length - 1])}`;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -153,6 +153,7 @@ export class CodegenLogicUtil {
|
|||||||
|
|
||||||
genHydrateDirectives(directiveRecords: DirectiveRecord[]): string {
|
genHydrateDirectives(directiveRecords: DirectiveRecord[]): string {
|
||||||
var res = [];
|
var res = [];
|
||||||
|
var outputCount = 0;
|
||||||
for (var i = 0; i < directiveRecords.length; ++i) {
|
for (var i = 0; i < directiveRecords.length; ++i) {
|
||||||
var r = directiveRecords[i];
|
var r = directiveRecords[i];
|
||||||
var dirVarName = this._names.getDirectiveName(r.directiveIndex);
|
var dirVarName = this._names.getDirectiveName(r.directiveIndex);
|
||||||
@ -160,14 +161,24 @@ export class CodegenLogicUtil {
|
|||||||
if (isPresent(r.outputs)) {
|
if (isPresent(r.outputs)) {
|
||||||
r.outputs.forEach(output => {
|
r.outputs.forEach(output => {
|
||||||
var eventHandlerExpr = this._genEventHandler(r.directiveIndex.elementIndex, output[1]);
|
var eventHandlerExpr = this._genEventHandler(r.directiveIndex.elementIndex, output[1]);
|
||||||
|
var statementStart =
|
||||||
|
`this.outputSubscriptions[${outputCount++}] = ${dirVarName}.${output[0]}`;
|
||||||
if (IS_DART) {
|
if (IS_DART) {
|
||||||
res.push(`${dirVarName}.${output[0]}.listen(${eventHandlerExpr});`);
|
res.push(`${statementStart}.listen(${eventHandlerExpr});`);
|
||||||
} else {
|
} 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");
|
return res.join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
import {CONST} from 'angular2/src/facade/lang';
|
import {CONST} from 'angular2/src/facade/lang';
|
||||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||||
import {
|
import {isListLikeIterable, iterateListLike, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
isListLikeIterable,
|
|
||||||
iterateListLike,
|
|
||||||
ListWrapper,
|
|
||||||
MapWrapper
|
|
||||||
} from 'angular2/src/facade/collection';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
isBlank,
|
isBlank,
|
||||||
@ -17,17 +12,21 @@ import {
|
|||||||
} from 'angular2/src/facade/lang';
|
} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
import {ChangeDetectorRef} from '../change_detector_ref';
|
||||||
import {IterableDiffer, IterableDifferFactory} from '../differs/iterable_differs';
|
import {IterableDiffer, IterableDifferFactory, TrackByFn} from '../differs/iterable_differs';
|
||||||
|
|
||||||
@CONST()
|
@CONST()
|
||||||
export class DefaultIterableDifferFactory implements IterableDifferFactory {
|
export class DefaultIterableDifferFactory implements IterableDifferFactory {
|
||||||
supports(obj: Object): boolean { return isListLikeIterable(obj); }
|
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 {
|
export class DefaultIterableDiffer implements IterableDiffer {
|
||||||
private _collection = null;
|
|
||||||
private _length: number = null;
|
private _length: number = null;
|
||||||
|
private _collection = null;
|
||||||
// Keeps track of the used records at any point in time (during & across `_check()` calls)
|
// Keeps track of the used records at any point in time (during & across `_check()` calls)
|
||||||
private _linkedRecords: _DuplicateMap = null;
|
private _linkedRecords: _DuplicateMap = null;
|
||||||
// Keeps track of the removed records at any point in time during `_check()` calls.
|
// 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 _movesTail: CollectionChangeRecord = null;
|
||||||
private _removalsHead: CollectionChangeRecord = null;
|
private _removalsHead: CollectionChangeRecord = null;
|
||||||
private _removalsTail: 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; }
|
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 {
|
diff(collection: any): DefaultIterableDiffer {
|
||||||
if (isBlank(collection)) collection = [];
|
if (isBlank(collection)) collection = [];
|
||||||
if (!isListLikeIterable(collection)) {
|
if (!isListLikeIterable(collection)) {
|
||||||
@ -104,31 +117,40 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
|||||||
var mayBeDirty: boolean = false;
|
var mayBeDirty: boolean = false;
|
||||||
var index: number;
|
var index: number;
|
||||||
var item;
|
var item;
|
||||||
|
var itemTrackBy;
|
||||||
if (isArray(collection)) {
|
if (isArray(collection)) {
|
||||||
var list = collection;
|
var list = collection;
|
||||||
this._length = collection.length;
|
this._length = collection.length;
|
||||||
|
|
||||||
for (index = 0; index < this._length; index++) {
|
for (index = 0; index < this._length; index++) {
|
||||||
item = list[index];
|
item = list[index];
|
||||||
if (record === null || !looseIdentical(record.item, item)) {
|
itemTrackBy = this._trackByFn(index, item);
|
||||||
record = this._mismatch(record, item, index);
|
if (record === null || !looseIdentical(record.trackById, itemTrackBy)) {
|
||||||
|
record = this._mismatch(record, item, itemTrackBy, index);
|
||||||
mayBeDirty = true;
|
mayBeDirty = true;
|
||||||
} else if (mayBeDirty) {
|
} else {
|
||||||
|
if (mayBeDirty) {
|
||||||
// TODO(misko): can we limit this to duplicates only?
|
// TODO(misko): can we limit this to duplicates only?
|
||||||
record = this._verifyReinsertion(record, item, index);
|
record = this._verifyReinsertion(record, item, itemTrackBy, index);
|
||||||
}
|
}
|
||||||
|
if (!looseIdentical(record.item, item)) this._addIdentityChange(record, item);
|
||||||
|
}
|
||||||
|
|
||||||
record = record._next;
|
record = record._next;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
index = 0;
|
index = 0;
|
||||||
iterateListLike(collection, (item) => {
|
iterateListLike(collection, (item) => {
|
||||||
if (record === null || !looseIdentical(record.item, item)) {
|
itemTrackBy = this._trackByFn(index, item);
|
||||||
record = this._mismatch(record, item, index);
|
if (record === null || !looseIdentical(record.trackById, itemTrackBy)) {
|
||||||
|
record = this._mismatch(record, item, itemTrackBy, index);
|
||||||
mayBeDirty = true;
|
mayBeDirty = true;
|
||||||
} else if (mayBeDirty) {
|
} else {
|
||||||
|
if (mayBeDirty) {
|
||||||
// TODO(misko): can we limit this to duplicates only?
|
// TODO(misko): can we limit this to duplicates only?
|
||||||
record = this._verifyReinsertion(record, item, index);
|
record = this._verifyReinsertion(record, item, itemTrackBy, index);
|
||||||
|
}
|
||||||
|
if (!looseIdentical(record.item, item)) this._addIdentityChange(record, item);
|
||||||
}
|
}
|
||||||
record = record._next;
|
record = record._next;
|
||||||
index++;
|
index++;
|
||||||
@ -141,9 +163,12 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
|||||||
return this.isDirty;
|
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 {
|
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._movesHead = this._movesTail = null;
|
||||||
this._removalsHead = this._removalsTail = null;
|
this._removalsHead = this._removalsTail = null;
|
||||||
|
this._identityChangesHead = this._identityChangesTail = null;
|
||||||
|
|
||||||
// todo(vicb) when assert gets supported
|
// todo(vicb) when assert gets supported
|
||||||
// assert(!this.isDirty);
|
// assert(!this.isDirty);
|
||||||
@ -190,7 +216,8 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
|||||||
*
|
*
|
||||||
* @internal
|
* @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.
|
// The previous record after which we will append the current one.
|
||||||
var previousRecord: CollectionChangeRecord;
|
var previousRecord: CollectionChangeRecord;
|
||||||
|
|
||||||
@ -203,19 +230,26 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to see if we have seen the item before.
|
// 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) {
|
if (record !== null) {
|
||||||
// We have seen this before, we need to move it forward in the collection.
|
// 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);
|
this._moveAfter(record, previousRecord, index);
|
||||||
} else {
|
} else {
|
||||||
// Never seen it, check evicted list.
|
// 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) {
|
if (record !== null) {
|
||||||
// It is an item which we have evicted earlier: reinsert it back into the list.
|
// 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);
|
this._reinsertAfter(record, previousRecord, index);
|
||||||
} else {
|
} else {
|
||||||
// It is a new item: add it.
|
// 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;
|
return record;
|
||||||
@ -248,9 +282,10 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
|||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
_verifyReinsertion(record: CollectionChangeRecord, item, index: number): CollectionChangeRecord {
|
_verifyReinsertion(record: CollectionChangeRecord, item: any, itemTrackBy: any,
|
||||||
|
index: number): CollectionChangeRecord {
|
||||||
var reinsertRecord: CollectionChangeRecord =
|
var reinsertRecord: CollectionChangeRecord =
|
||||||
this._unlinkedRecords === null ? null : this._unlinkedRecords.get(item);
|
this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy);
|
||||||
if (reinsertRecord !== null) {
|
if (reinsertRecord !== null) {
|
||||||
record = this._reinsertAfter(reinsertRecord, record._prev, index);
|
record = this._reinsertAfter(reinsertRecord, record._prev, index);
|
||||||
} else if (record.currentIndex != index) {
|
} else if (record.currentIndex != index) {
|
||||||
@ -456,36 +491,41 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
|||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(): string {
|
/** @internal */
|
||||||
var record: CollectionChangeRecord;
|
_addIdentityChange(record: CollectionChangeRecord, item: any) {
|
||||||
|
record.item = item;
|
||||||
var list = [];
|
if (this._identityChangesTail === null) {
|
||||||
for (record = this._itHead; record !== null; record = record._next) {
|
this._identityChangesTail = this._identityChangesHead = record;
|
||||||
list.push(record);
|
} else {
|
||||||
|
this._identityChangesTail = this._identityChangesTail._nextIdentityChange = record;
|
||||||
}
|
}
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
toString(): string {
|
||||||
|
var list = [];
|
||||||
|
this.forEachItem((record) => list.push(record));
|
||||||
|
|
||||||
var previous = [];
|
var previous = [];
|
||||||
for (record = this._previousItHead; record !== null; record = record._nextPrevious) {
|
this.forEachPreviousItem((record) => previous.push(record));
|
||||||
previous.push(record);
|
|
||||||
}
|
|
||||||
|
|
||||||
var additions = [];
|
var additions = [];
|
||||||
for (record = this._additionsHead; record !== null; record = record._nextAdded) {
|
this.forEachAddedItem((record) => additions.push(record));
|
||||||
additions.push(record);
|
|
||||||
}
|
|
||||||
var moves = [];
|
var moves = [];
|
||||||
for (record = this._movesHead; record !== null; record = record._nextMoved) {
|
this.forEachMovedItem((record) => moves.push(record));
|
||||||
moves.push(record);
|
|
||||||
}
|
|
||||||
|
|
||||||
var removals = [];
|
var removals = [];
|
||||||
for (record = this._removalsHead; record !== null; record = record._nextRemoved) {
|
this.forEachRemovedItem((record) => removals.push(record));
|
||||||
removals.push(record);
|
|
||||||
}
|
var identityChanges = [];
|
||||||
|
this.forEachIdentityChange((record) => identityChanges.push(record));
|
||||||
|
|
||||||
return "collection: " + list.join(', ') + "\n" + "previous: " + previous.join(', ') + "\n" +
|
return "collection: " + list.join(', ') + "\n" + "previous: " + previous.join(', ') + "\n" +
|
||||||
"additions: " + additions.join(', ') + "\n" + "moves: " + moves.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;
|
_nextAdded: CollectionChangeRecord = null;
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_nextMoved: CollectionChangeRecord = null;
|
_nextMoved: CollectionChangeRecord = null;
|
||||||
|
/** @internal */
|
||||||
|
_nextIdentityChange: CollectionChangeRecord = null;
|
||||||
|
|
||||||
constructor(public item: any) {}
|
|
||||||
|
constructor(public item: any, public trackById: any) {}
|
||||||
|
|
||||||
toString(): string {
|
toString(): string {
|
||||||
return this.previousIndex === this.currentIndex ?
|
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
|
// CollectionChangeRecord.currentIndex >= afterIndex
|
||||||
get(item: any, afterIndex: number): CollectionChangeRecord {
|
get(trackById: any, afterIndex: number): CollectionChangeRecord {
|
||||||
var record: CollectionChangeRecord;
|
var record: CollectionChangeRecord;
|
||||||
for (record = this._head; record !== null; record = record._nextDup) {
|
for (record = this._head; record !== null; record = record._nextDup) {
|
||||||
if ((afterIndex === null || afterIndex < record.currentIndex) &&
|
if ((afterIndex === null || afterIndex < record.currentIndex) &&
|
||||||
looseIdentical(record.item, item)) {
|
looseIdentical(record.trackById, trackById)) {
|
||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -599,7 +642,7 @@ class _DuplicateMap {
|
|||||||
|
|
||||||
put(record: CollectionChangeRecord) {
|
put(record: CollectionChangeRecord) {
|
||||||
// todo(vicb) handle corner cases
|
// todo(vicb) handle corner cases
|
||||||
var key = getMapKey(record.item);
|
var key = getMapKey(record.trackById);
|
||||||
|
|
||||||
var duplicates = this.map.get(key);
|
var duplicates = this.map.get(key);
|
||||||
if (!isPresent(duplicates)) {
|
if (!isPresent(duplicates)) {
|
||||||
@ -616,11 +659,11 @@ class _DuplicateMap {
|
|||||||
* Use case: `[a, b, c, a, a]` if we are at index `3` which is the second `a` then asking if we
|
* 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.
|
* have any more `a`s needs to return the last `a` not the first or second.
|
||||||
*/
|
*/
|
||||||
get(value: any, afterIndex: number = null): CollectionChangeRecord {
|
get(trackById: any, afterIndex: number = null): CollectionChangeRecord {
|
||||||
var key = getMapKey(value);
|
var key = getMapKey(trackById);
|
||||||
|
|
||||||
var recordList = this.map.get(key);
|
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.
|
* The list of duplicates also is removed from the map if it gets empty.
|
||||||
*/
|
*/
|
||||||
remove(record: CollectionChangeRecord): CollectionChangeRecord {
|
remove(record: CollectionChangeRecord): CollectionChangeRecord {
|
||||||
var key = getMapKey(record.item);
|
var key = getMapKey(record.trackById);
|
||||||
// todo(vicb)
|
// todo(vicb)
|
||||||
// assert(this.map.containsKey(key));
|
// assert(this.map.containsKey(key));
|
||||||
var recordList: _DuplicateItemRecordList = this.map.get(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.
|
* respond to changes in an iterable by effecting equivalent changes in the DOM.
|
||||||
*/
|
*/
|
||||||
export interface IterableDiffer {
|
export interface IterableDiffer {
|
||||||
diff(object: Object): any;
|
diff(object: any): any;
|
||||||
onDestroy();
|
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}.
|
* Provides a factory for {@link IterableDiffer}.
|
||||||
*/
|
*/
|
||||||
export interface IterableDifferFactory {
|
export interface IterableDifferFactory {
|
||||||
supports(objects: Object): boolean;
|
supports(objects: any): boolean;
|
||||||
create(cdRef: ChangeDetectorRef): IterableDiffer;
|
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));
|
var factory = this.factories.find(f => f.supports(iterable));
|
||||||
if (isPresent(factory)) {
|
if (isPresent(factory)) {
|
||||||
return 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.
|
* A differ that tracks changes made to an object over time.
|
||||||
*/
|
*/
|
||||||
export interface KeyValueDiffer {
|
export interface KeyValueDiffer {
|
||||||
diff(object: Object);
|
diff(object: any);
|
||||||
onDestroy();
|
onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ export interface KeyValueDiffer {
|
|||||||
* Provides a factory for {@link KeyValueDiffer}.
|
* Provides a factory for {@link KeyValueDiffer}.
|
||||||
*/
|
*/
|
||||||
export interface KeyValueDifferFactory {
|
export interface KeyValueDifferFactory {
|
||||||
supports(objects: Object): boolean;
|
supports(objects: any): boolean;
|
||||||
create(cdRef: ChangeDetectorRef): KeyValueDiffer;
|
create(cdRef: ChangeDetectorRef): KeyValueDiffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,6 +114,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
|
|||||||
super.observeDirective(this._getDirectiveFor(index), i);
|
super.observeDirective(this._getDirectiveFor(index), i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.outputSubscriptions = [];
|
||||||
for (var i = 0; i < this._directiveRecords.length; ++i) {
|
for (var i = 0; i < this._directiveRecords.length; ++i) {
|
||||||
var r = this._directiveRecords[i];
|
var r = this._directiveRecords[i];
|
||||||
if (isPresent(r.outputs)) {
|
if (isPresent(r.outputs)) {
|
||||||
@ -122,7 +123,8 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
|
|||||||
<any>this._createEventHandler(r.directiveIndex.elementIndex, output[1]);
|
<any>this._createEventHandler(r.directiveIndex.elementIndex, output[1]);
|
||||||
var directive = this._getDirectiveFor(r.directiveIndex);
|
var directive = this._getDirectiveFor(r.directiveIndex);
|
||||||
var getter = reflector.getter(output[0]);
|
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()) {
|
if (proto.shouldBeChecked()) {
|
||||||
var prevValue = this._readSelf(proto, values);
|
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) {
|
if (proto.lastInBinding) {
|
||||||
var change = ChangeDetectionUtil.simpleChange(prevValue, currValue);
|
var change = ChangeDetectionUtil.simpleChange(prevValue, currValue);
|
||||||
if (throwOnChange) this.throwOnChangeError(prevValue, currValue);
|
if (throwOnChange) this.throwOnChangeError(prevValue, currValue);
|
||||||
@ -403,7 +408,10 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
|
|||||||
|
|
||||||
if (proto.shouldBeChecked()) {
|
if (proto.shouldBeChecked()) {
|
||||||
var prevValue = this._readSelf(proto, values);
|
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);
|
currValue = ChangeDetectionUtil.unwrapValue(currValue);
|
||||||
|
|
||||||
if (proto.lastInBinding) {
|
if (proto.lastInBinding) {
|
||||||
|
@ -91,7 +91,7 @@ export class ChangeDetectionError extends WrappedException {
|
|||||||
* This is an internal Angular error.
|
* This is an internal Angular error.
|
||||||
*/
|
*/
|
||||||
export class DehydratedException extends BaseException {
|
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 {
|
scanCharacter(start: number, code: number): Token {
|
||||||
assert(this.peek == code);
|
|
||||||
this.advance();
|
this.advance();
|
||||||
return newCharacterToken(start, code);
|
return newCharacterToken(start, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
scanOperator(start: number, str: string): Token {
|
scanOperator(start: number, str: string): Token {
|
||||||
assert(this.peek == StringWrapper.charCodeAt(str, 0));
|
|
||||||
assert(SetWrapper.has(OPERATORS, str));
|
|
||||||
this.advance();
|
this.advance();
|
||||||
return newOperatorToken(start, str);
|
return newOperatorToken(start, str);
|
||||||
}
|
}
|
||||||
@ -274,7 +271,6 @@ class _Scanner {
|
|||||||
*/
|
*/
|
||||||
scanComplexOperator(start: number, one: string, twoCode: number, two: string, threeCode?: number,
|
scanComplexOperator(start: number, one: string, twoCode: number, two: string, threeCode?: number,
|
||||||
three?: string): Token {
|
three?: string): Token {
|
||||||
assert(this.peek == StringWrapper.charCodeAt(one, 0));
|
|
||||||
this.advance();
|
this.advance();
|
||||||
var str: string = one;
|
var str: string = one;
|
||||||
if (this.peek == twoCode) {
|
if (this.peek == twoCode) {
|
||||||
@ -285,12 +281,10 @@ class _Scanner {
|
|||||||
this.advance();
|
this.advance();
|
||||||
str += three;
|
str += three;
|
||||||
}
|
}
|
||||||
assert(SetWrapper.has(OPERATORS, str));
|
|
||||||
return newOperatorToken(start, str);
|
return newOperatorToken(start, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
scanIdentifier(): Token {
|
scanIdentifier(): Token {
|
||||||
assert(isIdentifierStart(this.peek));
|
|
||||||
var start: number = this.index;
|
var start: number = this.index;
|
||||||
this.advance();
|
this.advance();
|
||||||
while (isIdentifierPart(this.peek)) this.advance();
|
while (isIdentifierPart(this.peek)) this.advance();
|
||||||
@ -303,7 +297,6 @@ class _Scanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scanNumber(start: number): Token {
|
scanNumber(start: number): Token {
|
||||||
assert(isDigit(this.peek));
|
|
||||||
var simple: boolean = (this.index === start);
|
var simple: boolean = (this.index === start);
|
||||||
this.advance(); // Skip initial digit.
|
this.advance(); // Skip initial digit.
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -329,7 +322,6 @@ class _Scanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scanString(): Token {
|
scanString(): Token {
|
||||||
assert(this.peek == $SQ || this.peek == $DQ);
|
|
||||||
var start: number = this.index;
|
var start: number = this.index;
|
||||||
var quote: number = this.peek;
|
var quote: number = this.peek;
|
||||||
this.advance(); // Skip initial quote.
|
this.advance(); // Skip initial quote.
|
||||||
|
@ -49,7 +49,7 @@ import {
|
|||||||
|
|
||||||
var _implicitReceiver = new ImplicitReceiver();
|
var _implicitReceiver = new ImplicitReceiver();
|
||||||
// TODO(tbosch): Cannot make this const/final right now because of the transpiler...
|
// 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 {
|
class ParseException extends BaseException {
|
||||||
constructor(message: string, input: string, errLocation: string, ctxLocation?: any) {
|
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
|
OutOfBoundsError
|
||||||
} from './exceptions';
|
} from './exceptions';
|
||||||
import {FunctionWrapper, Type, isPresent, isBlank, CONST_EXPR} from 'angular2/src/facade/lang';
|
import {FunctionWrapper, Type, isPresent, isBlank, CONST_EXPR} from 'angular2/src/facade/lang';
|
||||||
|
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||||
import {Key} from './key';
|
import {Key} from './key';
|
||||||
import {SelfMetadata, HostMetadata, SkipSelfMetadata} from './metadata';
|
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 == 0) return this.provider0;
|
||||||
if (index == 1) return this.provider1;
|
if (index == 1) return this.provider1;
|
||||||
if (index == 2) return this.provider2;
|
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) {
|
if (index < 0 || index >= this.providers.length) {
|
||||||
throw new OutOfBoundsError(index);
|
throw new OutOfBoundsError(index);
|
||||||
}
|
}
|
||||||
@ -210,7 +211,9 @@ export class ProtoInjector {
|
|||||||
new ProtoInjectorInlineStrategy(this, bwv);
|
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,
|
obj = factory(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, d16,
|
||||||
d17, d18, d19);
|
d17, d18, d19);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
throw new BaseException(
|
||||||
|
`Cannot instantiate '${provider.key.displayName}' because it has more than 20 dependencies`);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new InstantiationError(this, e, e.stack, provider.key);
|
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 t = new OpaqueToken("value");
|
||||||
*
|
*
|
||||||
* var injector = Injector.resolveAndCreate([
|
* var injector = Injector.resolveAndCreate([
|
||||||
* provide(t, {useValue: "providedValue"})
|
* provide(t, {useValue: "bindingValue"})
|
||||||
* ]);
|
* ]);
|
||||||
*
|
*
|
||||||
* expect(injector.get(t)).toEqual("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 {Type, isPresent, isBlank, stringify} from 'angular2/src/facade/lang';
|
||||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||||
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DirectiveMetadata,
|
DirectiveMetadata,
|
||||||
ComponentMetadata,
|
ComponentMetadata,
|
||||||
@ -38,7 +39,7 @@ export class DirectiveResolver {
|
|||||||
var metadata = typeMetadata.find(_isDirectiveMetadata);
|
var metadata = typeMetadata.find(_isDirectiveMetadata);
|
||||||
if (isPresent(metadata)) {
|
if (isPresent(metadata)) {
|
||||||
var propertyMetadata = reflector.propMetadata(type);
|
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,
|
private _mergeWithPropertyMetadata(dm: DirectiveMetadata,
|
||||||
propertyMetadata: {[key: string]: any[]}): DirectiveMetadata {
|
propertyMetadata: {[key: string]: any[]},
|
||||||
|
directiveType: Type): DirectiveMetadata {
|
||||||
var inputs = [];
|
var inputs = [];
|
||||||
var outputs = [];
|
var outputs = [];
|
||||||
var host: {[key: string]: string} = {};
|
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[],
|
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 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 mergedHost = isPresent(dm.host) ? StringMapWrapper.merge(dm.host, host) : host;
|
||||||
var mergedQueries =
|
var mergedQueries =
|
||||||
isPresent(dm.queries) ? StringMapWrapper.merge(dm.queries, queries) : queries;
|
isPresent(dm.queries) ? StringMapWrapper.merge(dm.queries, queries) : queries;
|
||||||
|
@ -463,9 +463,13 @@ export class AppElement implements DependencyProvider, ElementRef, AfterViewChec
|
|||||||
var inj: AppElement = this;
|
var inj: AppElement = this;
|
||||||
while (isPresent(inj)) {
|
while (isPresent(inj)) {
|
||||||
inj._setQueriesAsDirty();
|
inj._setQueriesAsDirty();
|
||||||
|
if (isBlank(inj.parent) && inj.parentView.proto.type === ViewType.EMBEDDED) {
|
||||||
|
inj = inj.parentView.containerAppElement;
|
||||||
|
} else {
|
||||||
inj = inj.parent;
|
inj = inj.parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private _setQueriesAsDirty(): void {
|
private _setQueriesAsDirty(): void {
|
||||||
if (isPresent(this._queryStrategy)) {
|
if (isPresent(this._queryStrategy)) {
|
||||||
|
@ -25,7 +25,7 @@ export abstract class TemplateRef {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
// TODO(i): rename to anchor or location
|
// TODO(i): rename to anchor or location
|
||||||
elementRef: ElementRef;
|
get elementRef(): ElementRef { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TemplateRef_ extends TemplateRef {
|
export class TemplateRef_ extends TemplateRef {
|
||||||
|
@ -27,7 +27,7 @@ import {
|
|||||||
CONST_EXPR
|
CONST_EXPR
|
||||||
} from 'angular2/src/facade/lang';
|
} from 'angular2/src/facade/lang';
|
||||||
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
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 {ViewRef_, HostViewFactoryRef} from './view_ref';
|
||||||
import {ProtoPipes} from 'angular2/src/core/pipes/pipes';
|
import {ProtoPipes} from 'angular2/src/core/pipes/pipes';
|
||||||
import {camelCaseToDashCase} from 'angular2/src/core/render/util';
|
import {camelCaseToDashCase} from 'angular2/src/core/render/util';
|
||||||
@ -119,6 +119,12 @@ export class AppView implements ChangeDispatcher {
|
|||||||
(templateName, _) => { localsMap.set(templateName, null); });
|
(templateName, _) => { localsMap.set(templateName, null); });
|
||||||
for (var i = 0; i < appElements.length; i++) {
|
for (var i = 0; i < appElements.length; i++) {
|
||||||
var appEl = appElements[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) => {
|
StringMapWrapper.forEach(appEl.proto.directiveVariableBindings, (directiveIndex, name) => {
|
||||||
if (isBlank(directiveIndex)) {
|
if (isBlank(directiveIndex)) {
|
||||||
localsMap.set(name, appEl.nativeElement);
|
localsMap.set(name, appEl.nativeElement);
|
||||||
@ -126,6 +132,9 @@ export class AppView implements ChangeDispatcher {
|
|||||||
localsMap.set(name, appEl.getDirectiveAtIndex(directiveIndex));
|
localsMap.set(name, appEl.getDirectiveAtIndex(directiveIndex));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.renderer.setElementDebugInfo(
|
||||||
|
appEl.nativeElement, new RenderDebugInfo(appEl.getInjector(), appEl.getComponent(),
|
||||||
|
providerTokens, localsMap));
|
||||||
}
|
}
|
||||||
var parentLocals = null;
|
var parentLocals = null;
|
||||||
if (this.proto.type !== ViewType.COMPONENT) {
|
if (this.proto.type !== ViewType.COMPONENT) {
|
||||||
@ -250,7 +259,7 @@ export class AppView implements ChangeDispatcher {
|
|||||||
return this.appElements[directive.elementIndex].getDirectiveAtIndex(directive.directiveIndex);
|
return this.appElements[directive.elementIndex].getDirectiveAtIndex(directive.directiveIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
getDetectorFor(directive: DirectiveIndex): any {
|
getDetectorFor(directive: DirectiveIndex): ChangeDetector {
|
||||||
var componentView = this.appElements[directive.elementIndex].componentView;
|
var componentView = this.appElements[directive.elementIndex].componentView;
|
||||||
return isPresent(componentView) ? componentView.changeDetector : null;
|
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
|
// TODO(rado): profile and decide whether bounds checks should be added
|
||||||
// to the methods below.
|
// to the methods below.
|
||||||
createEmbeddedView(templateRef: TemplateRef_, index: number = -1): EmbeddedViewRef {
|
createEmbeddedView(templateRef: TemplateRef, index: number = -1): EmbeddedViewRef {
|
||||||
if (index == -1) index = this.length;
|
if (index == -1) index = this.length;
|
||||||
var vm = this._element.parentView.viewManager;
|
var vm = this._element.parentView.viewManager;
|
||||||
return vm.createEmbeddedViewInContainer(this._element.ref, index, templateRef);
|
return vm.createEmbeddedViewInContainer(this._element.ref, index, templateRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
createHostView(hostViewFactoryRef: HostViewFactoryRef_, index: number = -1,
|
createHostView(hostViewFactoryRef: HostViewFactoryRef, index: number = -1,
|
||||||
dynamicallyCreatedProviders: ResolvedProvider[] = null,
|
dynamicallyCreatedProviders: ResolvedProvider[] = null,
|
||||||
projectableNodes: any[][] = null): HostViewRef {
|
projectableNodes: any[][] = null): HostViewRef {
|
||||||
if (index == -1) index = this.length;
|
if (index == -1) index = this.length;
|
||||||
@ -149,14 +149,14 @@ export class ViewContainerRef_ extends ViewContainerRef {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(i): refactor insert+remove into move
|
// 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;
|
if (index == -1) index = this.length;
|
||||||
var vm = this._element.parentView.viewManager;
|
var vm = this._element.parentView.viewManager;
|
||||||
return vm.attachViewInContainer(this._element.ref, index, viewRef);
|
return vm.attachViewInContainer(this._element.ref, index, viewRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
indexOf(viewRef: ViewRef_): number {
|
indexOf(viewRef: ViewRef): number {
|
||||||
return ListWrapper.indexOf(this._element.nestedViews, viewRef.internalView);
|
return ListWrapper.indexOf(this._element.nestedViews, (<ViewRef_>viewRef).internalView);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(i): rename to destroy
|
// 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_,
|
HostViewFactoryRef_,
|
||||||
EmbeddedViewRef,
|
EmbeddedViewRef,
|
||||||
HostViewRef,
|
HostViewRef,
|
||||||
|
ViewRef,
|
||||||
ViewRef_
|
ViewRef_
|
||||||
} from './view_ref';
|
} from './view_ref';
|
||||||
import {ViewContainerRef} from './view_container_ref';
|
import {ViewContainerRef} from './view_container_ref';
|
||||||
import {TemplateRef, TemplateRef_} from './template_ref';
|
import {TemplateRef, TemplateRef_} from './template_ref';
|
||||||
import {AppViewListener} from './view_listener';
|
|
||||||
import {RootRenderer, RenderComponentType} from 'angular2/src/core/render/api';
|
import {RootRenderer, RenderComponentType} from 'angular2/src/core/render/api';
|
||||||
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
|
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
|
||||||
import {APP_ID} from 'angular2/src/core/application_tokens';
|
import {APP_ID} from 'angular2/src/core/application_tokens';
|
||||||
@ -184,25 +184,22 @@ export abstract class AppViewManager {
|
|||||||
export class AppViewManager_ extends AppViewManager {
|
export class AppViewManager_ extends AppViewManager {
|
||||||
private _nextCompTypeId: number = 0;
|
private _nextCompTypeId: number = 0;
|
||||||
|
|
||||||
constructor(private _renderer: RootRenderer, private _viewListener: AppViewListener,
|
constructor(private _renderer: RootRenderer, @Inject(APP_ID) private _appId: string) { super(); }
|
||||||
@Inject(APP_ID) private _appId: string) {
|
|
||||||
super();
|
getViewContainer(location: ElementRef): ViewContainerRef {
|
||||||
|
return (<ElementRef_>location).internalElement.getViewContainerRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
getViewContainer(location: ElementRef_): ViewContainerRef {
|
getHostElement(hostViewRef: ViewRef): ElementRef {
|
||||||
return location.internalElement.getViewContainerRef();
|
var hostView = (<ViewRef_>hostViewRef).internalView;
|
||||||
}
|
|
||||||
|
|
||||||
getHostElement(hostViewRef: ViewRef_): ElementRef {
|
|
||||||
var hostView = hostViewRef.internalView;
|
|
||||||
if (hostView.proto.type !== ViewType.HOST) {
|
if (hostView.proto.type !== ViewType.HOST) {
|
||||||
throw new BaseException('This operation is only allowed on host views');
|
throw new BaseException('This operation is only allowed on host views');
|
||||||
}
|
}
|
||||||
return hostView.appElements[0].ref;
|
return hostView.appElements[0].ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
getNamedElementInComponentView(hostLocation: ElementRef_, variableName: string): ElementRef {
|
getNamedElementInComponentView(hostLocation: ElementRef, variableName: string): ElementRef {
|
||||||
var appEl = hostLocation.internalElement;
|
var appEl = (<ElementRef_>hostLocation).internalElement;
|
||||||
var componentView = appEl.componentView;
|
var componentView = appEl.componentView;
|
||||||
if (isBlank(componentView)) {
|
if (isBlank(componentView)) {
|
||||||
throw new BaseException(`There is no component directive at element ${hostLocation}`);
|
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}`);
|
throw new BaseException(`Could not find variable ${variableName}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getComponent(hostLocation: ElementRef_): any {
|
getComponent(hostLocation: ElementRef): any {
|
||||||
return hostLocation.internalElement.getComponent();
|
return (<ElementRef_>hostLocation).internalElement.getComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_createRootHostViewScope: WtfScopeFn = wtfCreateScope('AppViewManager#createRootHostView()');
|
_createRootHostViewScope: WtfScopeFn = wtfCreateScope('AppViewManager#createRootHostView()');
|
||||||
|
|
||||||
createRootHostView(hostViewFactoryRef: HostViewFactoryRef_, overrideSelector: string,
|
createRootHostView(hostViewFactoryRef: HostViewFactoryRef, overrideSelector: string,
|
||||||
injector: Injector, projectableNodes: any[][] = null): HostViewRef {
|
injector: Injector, projectableNodes: any[][] = null): HostViewRef {
|
||||||
var s = this._createRootHostViewScope();
|
var s = this._createRootHostViewScope();
|
||||||
var hostViewFactory = hostViewFactoryRef.internalHostViewFactory;
|
var hostViewFactory = (<HostViewFactoryRef_>hostViewFactoryRef).internalHostViewFactory;
|
||||||
var selector = isPresent(overrideSelector) ? overrideSelector : hostViewFactory.selector;
|
var selector = isPresent(overrideSelector) ? overrideSelector : hostViewFactory.selector;
|
||||||
var view = hostViewFactory.viewFactory(this._renderer, this, null, projectableNodes, selector,
|
var view = hostViewFactory.viewFactory(this._renderer, this, null, projectableNodes, selector,
|
||||||
null, injector);
|
null, injector);
|
||||||
@ -236,9 +233,9 @@ export class AppViewManager_ extends AppViewManager {
|
|||||||
/** @internal */
|
/** @internal */
|
||||||
_destroyRootHostViewScope: WtfScopeFn = wtfCreateScope('AppViewManager#destroyRootHostView()');
|
_destroyRootHostViewScope: WtfScopeFn = wtfCreateScope('AppViewManager#destroyRootHostView()');
|
||||||
|
|
||||||
destroyRootHostView(hostViewRef: ViewRef_) {
|
destroyRootHostView(hostViewRef: ViewRef) {
|
||||||
var s = this._destroyRootHostViewScope();
|
var s = this._destroyRootHostViewScope();
|
||||||
var hostView = hostViewRef.internalView;
|
var hostView = (<ViewRef_>hostViewRef).internalView;
|
||||||
hostView.renderer.detachView(flattenNestedViewRenderNodes(hostView.rootNodesOrAppElements));
|
hostView.renderer.detachView(flattenNestedViewRenderNodes(hostView.rootNodesOrAppElements));
|
||||||
hostView.destroy();
|
hostView.destroy();
|
||||||
wtfLeave(s);
|
wtfLeave(s);
|
||||||
@ -248,14 +245,14 @@ export class AppViewManager_ extends AppViewManager {
|
|||||||
_createEmbeddedViewInContainerScope: WtfScopeFn =
|
_createEmbeddedViewInContainerScope: WtfScopeFn =
|
||||||
wtfCreateScope('AppViewManager#createEmbeddedViewInContainer()');
|
wtfCreateScope('AppViewManager#createEmbeddedViewInContainer()');
|
||||||
|
|
||||||
createEmbeddedViewInContainer(viewContainerLocation: ElementRef_, index: number,
|
createEmbeddedViewInContainer(viewContainerLocation: ElementRef, index: number,
|
||||||
templateRef: TemplateRef_): EmbeddedViewRef {
|
templateRef: TemplateRef): EmbeddedViewRef {
|
||||||
var s = this._createEmbeddedViewInContainerScope();
|
var s = this._createEmbeddedViewInContainerScope();
|
||||||
var contextEl = templateRef.elementRef.internalElement;
|
var contextEl = (<TemplateRef_>templateRef).elementRef.internalElement;
|
||||||
var view: AppView =
|
var view: AppView =
|
||||||
contextEl.embeddedViewFactory(contextEl.parentView.renderer, this, contextEl,
|
contextEl.embeddedViewFactory(contextEl.parentView.renderer, this, contextEl,
|
||||||
contextEl.parentView.projectableNodes, null, null, null);
|
contextEl.parentView.projectableNodes, null, null, null);
|
||||||
this._attachViewToContainer(view, viewContainerLocation.internalElement, index);
|
this._attachViewToContainer(view, (<ElementRef_>viewContainerLocation).internalElement, index);
|
||||||
return wtfLeave(s, view.ref);
|
return wtfLeave(s, view.ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,27 +260,29 @@ export class AppViewManager_ extends AppViewManager {
|
|||||||
_createHostViewInContainerScope: WtfScopeFn =
|
_createHostViewInContainerScope: WtfScopeFn =
|
||||||
wtfCreateScope('AppViewManager#createHostViewInContainer()');
|
wtfCreateScope('AppViewManager#createHostViewInContainer()');
|
||||||
|
|
||||||
createHostViewInContainer(viewContainerLocation: ElementRef_, index: number,
|
createHostViewInContainer(viewContainerLocation: ElementRef, index: number,
|
||||||
hostViewFactoryRef: HostViewFactoryRef_,
|
hostViewFactoryRef: HostViewFactoryRef,
|
||||||
dynamicallyCreatedProviders: ResolvedProvider[],
|
dynamicallyCreatedProviders: ResolvedProvider[],
|
||||||
projectableNodes: any[][]): HostViewRef {
|
projectableNodes: any[][]): HostViewRef {
|
||||||
var s = this._createHostViewInContainerScope();
|
var s = this._createHostViewInContainerScope();
|
||||||
// TODO(tbosch): This should be specifiable via an additional argument!
|
// TODO(tbosch): This should be specifiable via an additional argument!
|
||||||
var contextEl = viewContainerLocation.internalElement;
|
var viewContainerLocation_ = <ElementRef_>viewContainerLocation;
|
||||||
var hostViewFactory = hostViewFactoryRef.internalHostViewFactory;
|
var contextEl = viewContainerLocation_.internalElement;
|
||||||
|
var hostViewFactory = (<HostViewFactoryRef_>hostViewFactoryRef).internalHostViewFactory;
|
||||||
var view = hostViewFactory.viewFactory(
|
var view = hostViewFactory.viewFactory(
|
||||||
contextEl.parentView.renderer, contextEl.parentView.viewManager, contextEl,
|
contextEl.parentView.renderer, contextEl.parentView.viewManager, contextEl,
|
||||||
projectableNodes, null, dynamicallyCreatedProviders, null);
|
projectableNodes, null, dynamicallyCreatedProviders, null);
|
||||||
this._attachViewToContainer(view, viewContainerLocation.internalElement, index);
|
this._attachViewToContainer(view, viewContainerLocation_.internalElement, index);
|
||||||
return wtfLeave(s, view.ref);
|
return wtfLeave(s, view.ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_destroyViewInContainerScope = wtfCreateScope('AppViewMananger#destroyViewInContainer()');
|
_destroyViewInContainerScope = wtfCreateScope('AppViewMananger#destroyViewInContainer()');
|
||||||
|
|
||||||
destroyViewInContainer(viewContainerLocation: ElementRef_, index: number) {
|
destroyViewInContainer(viewContainerLocation: ElementRef, index: number) {
|
||||||
var s = this._destroyViewInContainerScope();
|
var s = this._destroyViewInContainerScope();
|
||||||
var view = this._detachViewInContainer(viewContainerLocation.internalElement, index);
|
var view =
|
||||||
|
this._detachViewInContainer((<ElementRef_>viewContainerLocation).internalElement, index);
|
||||||
view.destroy();
|
view.destroy();
|
||||||
wtfLeave(s);
|
wtfLeave(s);
|
||||||
}
|
}
|
||||||
@ -292,28 +291,31 @@ export class AppViewManager_ extends AppViewManager {
|
|||||||
_attachViewInContainerScope = wtfCreateScope('AppViewMananger#attachViewInContainer()');
|
_attachViewInContainerScope = wtfCreateScope('AppViewMananger#attachViewInContainer()');
|
||||||
|
|
||||||
// TODO(i): refactor detachViewInContainer+attachViewInContainer to moveViewInContainer
|
// TODO(i): refactor detachViewInContainer+attachViewInContainer to moveViewInContainer
|
||||||
attachViewInContainer(viewContainerLocation: ElementRef_, index: number,
|
attachViewInContainer(viewContainerLocation: ElementRef, index: number,
|
||||||
viewRef: ViewRef_): EmbeddedViewRef {
|
viewRef: ViewRef): EmbeddedViewRef {
|
||||||
|
var viewRef_ = <ViewRef_>viewRef;
|
||||||
var s = this._attachViewInContainerScope();
|
var s = this._attachViewInContainerScope();
|
||||||
this._attachViewToContainer(viewRef.internalView, viewContainerLocation.internalElement, index);
|
this._attachViewToContainer(viewRef_.internalView,
|
||||||
return wtfLeave(s, viewRef);
|
(<ElementRef_>viewContainerLocation).internalElement, index);
|
||||||
|
return wtfLeave(s, viewRef_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_detachViewInContainerScope = wtfCreateScope('AppViewMananger#detachViewInContainer()');
|
_detachViewInContainerScope = wtfCreateScope('AppViewMananger#detachViewInContainer()');
|
||||||
|
|
||||||
// TODO(i): refactor detachViewInContainer+attachViewInContainer to moveViewInContainer
|
// TODO(i): refactor detachViewInContainer+attachViewInContainer to moveViewInContainer
|
||||||
detachViewInContainer(viewContainerLocation: ElementRef_, index: number): EmbeddedViewRef {
|
detachViewInContainer(viewContainerLocation: ElementRef, index: number): EmbeddedViewRef {
|
||||||
var s = this._detachViewInContainerScope();
|
var s = this._detachViewInContainerScope();
|
||||||
var view = this._detachViewInContainer(viewContainerLocation.internalElement, index);
|
var view =
|
||||||
|
this._detachViewInContainer((<ElementRef_>viewContainerLocation).internalElement, index);
|
||||||
return wtfLeave(s, view.ref);
|
return wtfLeave(s, view.ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
onViewCreated(view: AppView) { this._viewListener.onViewCreated(view); }
|
onViewCreated(view: AppView) {}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
onViewDestroyed(view: AppView) { this._viewListener.onViewDestroyed(view); }
|
onViewDestroyed(view: AppView) {}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
createRenderComponentType(encapsulation: ViewEncapsulation,
|
createRenderComponentType(encapsulation: ViewEncapsulation,
|
||||||
|
@ -1166,7 +1166,7 @@ export var ViewChild: ViewChildFactory = makePropDecorator(ViewChildMetadata);
|
|||||||
* shown: boolean;
|
* shown: boolean;
|
||||||
*
|
*
|
||||||
* constructor(private @Query(Item) items:QueryList<Item>) {
|
* 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({
|
* @Component({
|
||||||
* selector: 'app',
|
* selector: 'app',
|
||||||
* template: `
|
* template: `
|
||||||
* <interval-dir (every-second)="everySecond()" (every-five-seconds)="everyFiveSeconds()">
|
* <interval-dir (everySecond)="everySecond()" (everyFiveSeconds)="everyFiveSeconds()">
|
||||||
* </interval-dir>
|
* </interval-dir>
|
||||||
* `,
|
* `,
|
||||||
* directives: [IntervalDir]
|
* directives: [IntervalDir]
|
||||||
|
@ -254,7 +254,7 @@ export class ContentChildMetadata extends QueryMetadata {
|
|||||||
* shown: boolean;
|
* shown: boolean;
|
||||||
*
|
*
|
||||||
* constructor(private @Query(Item) items:QueryList<Item>) {
|
* 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({
|
* @Component({
|
||||||
* selector: 'app',
|
* selector: 'app',
|
||||||
* template: `
|
* template: `
|
||||||
* <interval-dir (every-second)="everySecond()" (every-five-seconds)="everyFiveSeconds()">
|
* <interval-dir (everySecond)="everySecond()" (everyFiveSeconds)="everyFiveSeconds()">
|
||||||
* </interval-dir>
|
* </interval-dir>
|
||||||
* `,
|
* `,
|
||||||
* directives: [IntervalDir]
|
* directives: [IntervalDir]
|
||||||
@ -1035,7 +1035,7 @@ export class InputMetadata {
|
|||||||
* @Component({
|
* @Component({
|
||||||
* selector: 'app',
|
* selector: 'app',
|
||||||
* template: `
|
* template: `
|
||||||
* <interval-dir (every-second)="everySecond()" (every-five-seconds)="everyFiveSeconds()">
|
* <interval-dir (everySecond)="everySecond()" (everyFiveSeconds)="everyFiveSeconds()">
|
||||||
* </interval-dir>
|
* </interval-dir>
|
||||||
* `,
|
* `,
|
||||||
* directives: [IntervalDir]
|
* directives: [IntervalDir]
|
||||||
@ -1071,8 +1071,8 @@ export class OutputMetadata {
|
|||||||
* @Directive({selector: '[ngModel]'})
|
* @Directive({selector: '[ngModel]'})
|
||||||
* class NgModelStatus {
|
* class NgModelStatus {
|
||||||
* constructor(public control:NgModel) {}
|
* constructor(public control:NgModel) {}
|
||||||
* @HostBinding('[class.valid]') get valid { return this.control.valid; }
|
* @HostBinding('class.valid') get valid { return this.control.valid; }
|
||||||
* @HostBinding('[class.invalid]') get invalid { return this.control.invalid; }
|
* @HostBinding('class.invalid') get invalid { return this.control.invalid; }
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* @Component({
|
* @Component({
|
||||||
|
@ -23,7 +23,7 @@ class NoReflectionCapabilities implements PlatformReflectionCapabilities {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List parameters(dynamic type) {
|
List<List> parameters(dynamic type) {
|
||||||
throw "Cannot find reflection information on ${stringify(type)}";
|
throw "Cannot find reflection information on ${stringify(type)}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ class NoReflectionCapabilities implements PlatformReflectionCapabilities {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map propMetadata(dynamic type) {
|
Map<String, List> propMetadata(dynamic type) {
|
||||||
throw "Cannot find reflection information on ${stringify(type)}";
|
throw "Cannot find reflection information on ${stringify(type)}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_zipTypesAndAnnotaions(paramTypes, paramAnnotations): any[][] {
|
_zipTypesAndAnnotations(paramTypes, paramAnnotations): any[][] {
|
||||||
var result;
|
var result;
|
||||||
|
|
||||||
if (typeof paramTypes === 'undefined') {
|
if (typeof paramTypes === 'undefined') {
|
||||||
@ -119,7 +119,7 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
|
|||||||
var paramAnnotations = this._reflect.getMetadata('parameters', typeOrFunc);
|
var paramAnnotations = this._reflect.getMetadata('parameters', typeOrFunc);
|
||||||
var paramTypes = this._reflect.getMetadata('design:paramtypes', typeOrFunc);
|
var paramTypes = this._reflect.getMetadata('design:paramtypes', typeOrFunc);
|
||||||
if (isPresent(paramTypes) || isPresent(paramAnnotations)) {
|
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`
|
// The array has to be filled with `undefined` because holes would be skipped by `some`
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
library reflection.types;
|
library reflection.types;
|
||||||
|
|
||||||
typedef SetterFn(Object obj, value);
|
typedef SetterFn(obj, value);
|
||||||
typedef GetterFn(Object obj);
|
typedef GetterFn(obj);
|
||||||
typedef MethodFn(Object obj, List args);
|
typedef MethodFn(obj, List args);
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
import {ViewEncapsulation} from 'angular2/src/core/metadata/view';
|
import {ViewEncapsulation} from 'angular2/src/core/metadata/view';
|
||||||
|
import {Injector} from 'angular2/src/core/di/injector';
|
||||||
|
|
||||||
export class RenderComponentType {
|
export class RenderComponentType {
|
||||||
constructor(public id: string, public encapsulation: ViewEncapsulation,
|
constructor(public id: string, public encapsulation: ViewEncapsulation,
|
||||||
public styles: Array<string | any[]>) {}
|
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 interface ParentRenderer { renderComponent(componentType: RenderComponentType): Renderer; }
|
||||||
|
|
||||||
export abstract class Renderer implements ParentRenderer {
|
export abstract class Renderer implements ParentRenderer {
|
||||||
@ -28,7 +34,7 @@ export abstract class Renderer implements ParentRenderer {
|
|||||||
|
|
||||||
abstract destroyView(hostElement: any, viewAllNodes: any[]);
|
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;
|
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 setBindingDebugInfo(renderElement: any, propertyName: string, propertyValue: string);
|
||||||
|
|
||||||
|
abstract setElementDebugInfo(renderElement: any, info: RenderDebugInfo);
|
||||||
|
|
||||||
abstract setElementClass(renderElement: any, className: string, isAdd: boolean);
|
abstract setElementClass(renderElement: any, className: string, isAdd: boolean);
|
||||||
|
|
||||||
abstract setElementStyle(renderElement: any, styleName: string, styleValue: string);
|
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