Compare commits

..

78 Commits

Author SHA1 Message Date
4945e73588 docs(changelog): update change log to beta.2 2016-01-28 11:34:11 -08:00
8a00a863ac chore(release): bump version to beta.2 2016-01-28 11:27:47 -08:00
db87baeb98 fix(ddc): router, compiler, web worker fixes for DDC
Also enable DDC checks across all non-web worker playground apps. We are
now down to 2 DDC errors across all of them. The remaining two need to be
fixed in package:analyzer, not in angular.

BREAKING CHANGE:

- there's a chance of breakage as router's Instruction constructor
  signature changed.

Closes #6693
2016-01-27 02:30:20 +00:00
c4c43f5a77 docs(contributing.md): add docs for "ci" commit type/scope 2016-01-26 14:55:42 -08:00
0ae77753f3 fix(core): always remove DOM listeners and stream subscriptions
This is needed to prevent memory leaks. The DOM
listeners don’t need to be removed for simple examples,
but a big internal app shows memory leaks because of them.

BREAKING CHANGE:
- `Renderer.listen` now has to return a function that
  removes the event listener.
2016-01-26 07:37:31 -08:00
5f0baaac73 fix(dart/transform): Ensure template codegen is completed sync
Previously, template codegen was done asynchronously, which could result
in reflector state being overwritten and leading to compile errors.

Update the codegen to run synchronously to ensure this does not happen.

Closes #6603
2016-01-26 04:18:11 +00:00
b5b6ece65a chore(ddc): reduce DDC warning cap 260->180 as we fixed a bunch
Closes #6625
2016-01-26 03:58:22 +00:00
4282297c24 fix(ddc): type fixes necessary to bring DDC severe count to 0 2016-01-26 03:58:22 +00:00
9c96b8affc chore: track size of a "Hello world" app built with SystemJS
Closes #6621
2016-01-26 02:54:03 +00:00
132829e5e2 chore(core): deactivate the tests that use Dart isolates
These are broken with Dart 1.13.2 stable, and will soon be obsolete (see #6270).
2016-01-25 17:20:06 -08:00
4a414420e9 fix(bundles): testing bundle should include browser platform
Closes #6626
2016-01-22 06:12:58 +00:00
fb6335ab60 build(gulp): fail hard w/ legacy node version and provide clear upgrade instructions
Closes #6213
2016-01-22 03:25:34 +00:00
89bd008445 docs(DEVELOPER.md): update framework developer instructions 2016-01-22 03:25:34 +00:00
caafb41eb5 build(node): upgrade to node 5.4.1 2016-01-22 03:25:34 +00:00
31b81a7439 build(npm): update to karma-browserstack-launcher@0.1.9 2016-01-22 03:25:34 +00:00
f7b1973358 build(npm): bump Angular's version number in shrinkwrap files to 2.0.0-beta.1 2016-01-22 03:25:34 +00:00
32f01da49a build(npm): update to karma@0.13.17
Mark says that karma-runner/karma#1768 is resolved in 0.13.17
2016-01-22 03:25:34 +00:00
59684c97b0 build(npm): update to minimatch@3.0.0 2016-01-22 03:25:34 +00:00
a32a0a3a97 build(npm): update to semver@5.1.0 2016-01-22 03:25:33 +00:00
96f5b0929d build(npm): lock karma at 0.13.15 due to karma-runner/karma#1768 2016-01-22 03:25:33 +00:00
8e6cf7fca8 build(npm): update to yargs@3.31.0 2016-01-22 03:25:33 +00:00
fdbe8741c9 build(npm): update to proxy-middleware@0.15.0 2016-01-22 03:25:33 +00:00
775fb2c340 build(npm): remove googleapis
it was previously used by benchpress (see d02c0accbb) but that's no longer the case.

I also removed a bunch of extranous dependencies that should never have been part of node_modules (npm bug?)
2016-01-22 03:25:33 +00:00
b60f594798 build(npm): update to gulp-connect@2.3.1 2016-01-22 03:25:33 +00:00
cc49790bdb build(npm): update gulp-connect's dependencies 2016-01-22 03:25:33 +00:00
a4bc19c530 build(npm): lock broccoli-slow-trees to the 1.x.x range 2016-01-22 03:25:33 +00:00
f7985dbdb7 build(npm): update to lodash@3.10.1 2016-01-22 03:25:33 +00:00
0bdcb5c1e0 build(npm): remove del devDependency - use fs-extra instead 2016-01-22 03:25:33 +00:00
a0d25db4a5 build(npm): add tools/npm/reshrinkwrap script and update docs 2016-01-22 03:25:33 +00:00
625474c4e2 build(npm): update to mock-fs@3.6.0 2016-01-22 03:25:33 +00:00
1cd2a6328a build(npm): update to fs-extra@0.26.3 2016-01-22 03:25:33 +00:00
d6bafe4fe3 build(npm): update to minimist@1.2.0 2016-01-22 03:25:33 +00:00
6a2ef15355 build(npm): update to jasmine@2.4.1 2016-01-22 03:25:33 +00:00
a8ca560503 build(npm): upgrade to broccoli@0.16.9 2016-01-22 03:25:33 +00:00
ad361808ec build(npm): upgrade to broccoli-funnel@1.0.1 2016-01-22 03:25:33 +00:00
c47639f2b1 build(npm): upgrade to protractor@3.0.0 2016-01-22 03:25:33 +00:00
ba90a85f7b build(npm): downgrade to karma@0.13.15 due to RangeError bug
Ref https://github.com/karma-runner/karma/issues/1768
2016-01-22 03:25:33 +00:00
d3b569557f build(npm): upgrade to karma-sauce-launcher@0.3.0 2016-01-22 03:25:33 +00:00
c9090ffa31 build(npm): revert clang-format upgrade
there are too many reformatting changes require that would add noise to the upgrade commit
2016-01-22 03:25:33 +00:00
341bf39d23 build(npm): update all npm dependencies + reshrinkwrap 2016-01-22 03:25:32 +00:00
3778ac26aa build(tools): npm/copy-npm-shrinkwrap should gracefully handle situation when shrinkwrap file is missing
This situation occurs during mas update of all dependencies, so we should not throw errors when this happens.
2016-01-22 03:25:32 +00:00
6cfc6f5bb2 build(npm): upgrade to npm v3
Closes #3193
2016-01-22 03:25:32 +00:00
47a3b4d56b feat(dart/transform): Promote missing Directive warning to error
Closes #6519

Closes #6568
2016-01-22 00:46:56 +00:00
c72ed991ad fix(testing): remove test zone for now and rely on returned promises
Adds tests for public Dart and TS frameworks to make sure that
components with templateUrl can be created by the TestComponentBuilder.

Closes #6359

Closes #6601
2016-01-22 00:28:48 +00:00
78bfdf78ea feat(dart/transform): DirectiveProcessor: do not process generated files
Prevent `DirectiveProcessor` from processing files which were generated
by the Angular2 Dart transformer.

Closes #6517
2016-01-22 00:21:27 +00:00
a24ee6add4 fix(HtmlLexer): fix for unicode chars
fixes #6036
Closes #6061
2016-01-21 23:45:41 +00:00
df3074fdfe feat(core/application_ref): Allow asyncronous app initializers.
closes #5929.

Closes #6063
2016-01-21 01:45:24 +00:00
f7424d5aeb chore: track size of a "Hello world" app built with WebPack
Closes #6434
2016-01-21 01:28:35 +00:00
a593ffa6f3 fix(transformer): record HostBinding annotations applied to getters
Closes #6283
2016-01-21 01:02:56 +00:00
761c6d0df7 fix(perf): faster looseIdentical implementation
Remove String type check in looseIdentical in JS-mode. It is not necessary as dart2js already compiles `identical` to `===` which compares string contents. Inline call sites.

This improves change detection of plain fields by 40%. On a large internal app the improvement is 5%.

Closes #6364
2016-01-21 01:01:36 +00:00
3e65d1458e fix(Dart): make some playground samples run with Dart Dev Compiler
Resolve all invalid field override errors, workaround current
reflection limitations in Dart Dev Compiler. todo, hello_world and
key_events samples now work with Dart Dev Compiler.

BREAKING CHANGE: remove TemplateRef.elementRef setter

Closes #6441
2016-01-21 00:41:42 +00:00
a4b5cb8376 build(node): split test and src compilation units 2016-01-19 21:15:16 -08:00
c785a1e474 fix(ddc): use dynamic types in reflection typedefs
Closes #6437
2016-01-19 21:49:11 +00:00
3adc472f06 chore(build): fix race condition for the !bundles.js.docs task 2016-01-19 11:40:30 -08:00
e7081b8b7c chore: don't track size of non-bundle files 2016-01-19 11:32:40 -08:00
9b3a548f6f docs(template_parser.ts): typo 2016-01-19 10:58:04 -08:00
90b3502bb8 ci(circle config): add a circle CI config
This only runs the JS build (no tests) as an easy place to start.

Green build on my branch: https://circleci.com/gh/alexeagle/angular/5

Note, we are just experimenting with Circle at this point...

Closes #6520
2016-01-16 00:17:15 +00:00
e19b31db29 refactor(test): Remove unnecessary noSuchMethod
Remove trivial implementations in many spy objects which just calls the
parent's `noSuchMethod`.

Closes #6410

Closes #6491
2016-01-15 22:53:09 +00:00
bd015f14e8 build(dartanalyzer): Ignore TODOs during build
The newest version of the analyzer emits hints when it encounters TODOs
in code, which is breaking the Dart dev version of our build.

Ignore TODOs for the purpose of build health.

See #6410
2016-01-15 22:53:09 +00:00
ca7ba12fc6 chore(travis): update name of sync branch to be ignored
Closes #6518
2016-01-15 22:26:40 +00:00
ae05ec69c4 Update overview.md
Closes #6478
2016-01-15 17:44:30 +00:00
92dc3b91d8 doc(*): change package.json license field to MIT
Align the package.json license with the LICENSE file from the repo
Closes #6432
2016-01-15 17:42:43 +00:00
8bd697b316 docs(DEVELOPER): fix saucelabs gulp task name
Task is test.unit.js.sauce, not test.unit.js.saucelabs.

Closes #6435
2016-01-15 17:23:14 +00:00
eda4c3eb4c fix(template_compiler): Fix erroneous cycle detection
Before, the check for cycles was wrong and lead to false positives.

Fixes #6404

Closes #6474
2016-01-14 23:08:30 +00:00
4d0c2ed1f6 test(dart/transform): Update dependencies & fix Dart tests
Widen version dependencies for `package:angular`, `package:code_transformers`,
and `package:observe`.

`package:guinness` uses `package:unittest` while
the newest versions of `package:code_transformers` use `package:test`.
This causes our end-to-end Dart transformer tests (which use testing
code in `package:code_transformers`) to be skipped.

To fix this:
- Move e2e tests to run in a separate file
- Run `gulp test.server.dart` tests serially

Closes #5922

Closes #5935
2016-01-14 00:29:03 +00:00
eda6a5d52a refactor(WebWorker): Rename WORKER_RENDER_APP to WORKER_RENDER_APPLICATION
BREAKING CHANGE

WORKER_RENDER_APP is now deprecated. Use WORKER_RENDER_APPLICATION instead
WORKER_RENDER_APP_COMMON has been replaced by WORKER_RENDER_APPLICATION_COMMON

closes #6184

Closes #6378
2016-01-14 00:07:13 +00:00
c1c54ed0f2 refactor(dart/transform): Avoid using package:code_transformers
Replace uses of `package:code_transformers`, which is only used to
convert from uri to `AssetId`, with calls to the utility methods in
`src/transform/common/url_resolver.dart`.

Closes #5931
2016-01-13 22:24:42 +00:00
6b73d09ba1 chore(build): make experimental Dart build useful
Previously we grepped all hand-written Dart code and ran analyzer in strong mode against it.

Now we run it against transformed playground apps, which:

1. does not analyze unnecessary code (we primarily care about stuff that runs in the browser)
2. analyzes generated code, which does run in the browser and which we failed to analyze in the previous version of the build

Closes #6436
2016-01-13 21:09:55 +00:00
ac85cbb28a fix(web_workers): support @AngularEntrypoint in web workers
And enable transformers on all playground apps

Closes #6013
2016-01-13 17:55:01 +00:00
b0cebdba6b feat(test): allow tests to specify the platform and application providers used
With providers split into bundles, the test injector is now able to
use providers for a given bundle. Suggested provider lists for tests are
available in `angular2/platform/testing/<platform>`.

Change the providers for a test suite using `setBaseTestProviders`. This
should be done once at the start of the test suite, before any test cases
run.

BREAKING CHANGE: Tests are now required to use `setBaseTestProviders`
to set up. Assuming your tests are run on a browser, setup would change
as follows.

Before:

```js
// Somewhere in test setup
import {BrowserDomAdapter} from 'angular2/src/platform/browser/browser_adapter';
BrowserDomAdapter.makeCurrent
```

After:

```js
// Somewhere in the test setup
import {setBaseTestProviders} from 'angular2/testing';
import {
  TEST_BROWSER_PLATFORM_PROVIDERS,
  TEST_BROWSER_APPLICATION_PROVIDERS
} from 'angular2/platform/testing/browser';

setBaseTestProviders(TEST_BROWSER_PLATFORM_PROVIDERS,
                     TEST_BROWSER_APPLICATION_PROVIDERS);
```

Closes #5351, Closes #5585

Closes #5975
2016-01-13 02:11:06 +00:00
933a9112da fix(ChangeDetection): chain expressions evaluate to the last expression (codegen)
fixes #4782
Closes #5892
2016-01-12 17:10:42 +00:00
8c37b7e8f2 fix(directive): throw if output the same event more than once
Close: #4798
2016-01-11 16:48:57 -08:00
c8e909f8c9 docs(cheatsheet): fix pipe name in an example
Closes #6399
2016-01-12 00:12:00 +00:00
69ae3634c7 feat(testability): Expose function frameworkStabilizers
Closes #5485
2016-01-11 23:10:51 +00:00
95248f46a1 build(npm): update to ts2dart@0.7.19
Closes #6254
2016-01-09 01:44:01 +00:00
b3c7df1783 docs(cheatsheet): fix bootstrap ts namespace
Fix https://github.com/angular/angular.io/issues/615
Closes #6159
2016-01-09 01:01:17 +00:00
c56679e8e1 Update change from Apache to MIT license 2016-01-08 13:41:58 -08:00
041c599511 docs(changelog): update change log to beta.1 2016-01-08 12:12:38 -08:00
177 changed files with 15438 additions and 35389 deletions

2
.nvmrc
View File

@ -1 +1 @@
4.2.1 5.4.1

View File

@ -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:
@ -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:

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

215
LICENSE
View File

@ -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.

6
circle.yml Normal file
View File

@ -0,0 +1,6 @@
machine:
node:
version: 5.4.1
test:
override:
- npm run build

View File

@ -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) => {
@ -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/**'])
@ -638,7 +652,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 +672,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',
@ -906,24 +1017,20 @@ 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([
'modules_dart/transform/**/*',
return gulp.src([ '!modules_dart/transform/**/*.proto',
'modules_dart/transform/**/*', '!modules_dart/transform/pubspec.yaml',
'!modules_dart/transform/**/*.proto', '!modules_dart/transform/**/packages{,/**}',
'!modules_dart/transform/pubspec.yaml', ])
'!modules_dart/transform/**/packages{,/**}', .pipe(gulp.dest(path.join(CONFIG.dest.dart, 'angular2')));
]) });
.pipe(gulp.dest(path.join(CONFIG.dest.dart, 'angular2')));
});
// Builds all Dart packages, but does not compile them // Builds all Dart packages, but does not compile them
gulp.task('build/packages.dart', function(done) { gulp.task('build/packages.dart', function(done) {
@ -1127,8 +1234,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 +1383,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',

View File

@ -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;

View File

@ -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;

View File

@ -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);
@ -89,4 +89,4 @@ Depending on if you are using Angular bundles or not you can either use RxJS bun
## ES6 shims (optional) ## ES6 shims (optional)
Users of pre-ES6 browsers might need to add an ES6 shim (e.g. [es6-shim](https://github.com/paulmillr/es6-shim)) Users of pre-ES6 browsers might need to add an ES6 shim (e.g. [es6-shim](https://github.com/paulmillr/es6-shim))

View File

@ -2,7 +2,7 @@
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}

View File

@ -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:

View File

@ -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

View File

@ -6,8 +6,6 @@
/// <reference path="../typings/zone/zone.d.ts"/> /// <reference path="../typings/zone/zone.d.ts"/>
/// <reference path="../typings/hammerjs/hammerjs.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 // TODO: ideally the node.d.ts reference should be scoped only for files that need and not to all
// the code including client code // the code including client code
@ -30,6 +28,7 @@ interface BrowserNodeGlobal {
zone: Zone; zone: Zone;
getAngularTestability: Function; getAngularTestability: Function;
getAllAngularTestabilities: Function; getAllAngularTestabilities: Function;
frameworkStabilizers: Array<Function>;
setTimeout: Function; setTimeout: Function;
clearTimeout: Function; clearTimeout: Function;
setInterval: Function; setInterval: Function;

View 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]);

View 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
]);

View File

@ -0,0 +1 @@
// Intentionally blank, the Parse5Adapater bindings for JavaScript don't apply.

View 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}),
]);

View File

@ -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,7 @@ 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';
import 'package:angular2/src/platform/worker_render_common.dart';
const WORKER_RENDER_APP = WORKER_RENDER_APPLICATION_COMMON;

View File

@ -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,9 @@ 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;

View File

@ -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:

View File

@ -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); }

View File

@ -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";
} }

View File

@ -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[] {

View File

@ -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));

View File

@ -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++;

View File

@ -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;

View File

@ -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];

View File

@ -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();
zone.run(() => { if (bindingFn === null) {
PromiseWrapper.then(bindingFn(zone), (providers: Array<Type | Provider | any[]>) => { completer.resolve(this._initApp(zone, additionalProviders));
if (isPresent(additionalProviders)) { } else {
providers = ListWrapper.concat(providers, additionalProviders); zone.run(() => {
} PromiseWrapper.then(bindingFn(zone), (providers: Array<Type | Provider | any[]>) => {
completer.resolve(this._initApp(zone, providers)); if (isPresent(additionalProviders)) {
providers = ListWrapper.concat(providers, additionalProviders);
}
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,8 +270,12 @@ 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);
return app; if (promise !== null) {
return PromiseWrapper.then(promise, (_) => app);
} else {
return app;
}
} }
dispose(): void { dispose(): void {
@ -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;
}
} }
/** /**
@ -485,5 +513,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; }
} }

View File

@ -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();
} }
try { try {
var locals = new Map<string, any>(); var locals = new Map<string, any>();
@ -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)) {

View File

@ -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");
} }

View File

@ -22,7 +22,7 @@ import {IterableDiffer, IterableDifferFactory} 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): DefaultIterableDiffer { return new DefaultIterableDiffer(); }
} }
export class DefaultIterableDiffer implements IterableDiffer { export class DefaultIterableDiffer implements IterableDiffer {

View File

@ -9,7 +9,7 @@ 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();
} }
@ -17,7 +17,7 @@ export interface IterableDiffer {
* 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): IterableDiffer;
} }
@ -74,7 +74,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;

View File

@ -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;
} }

View File

@ -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));
}); });
} }
} }

View File

@ -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() { super('Attempt to use a dehydrated detector.'); }
} }
/** /**

View File

@ -143,7 +143,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 +181,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 +210,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);
}
} }

View File

@ -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;

View File

@ -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 {

View File

@ -250,7 +250,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;
} }

View File

@ -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

View File

@ -17,6 +17,7 @@ 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';
@ -189,20 +190,20 @@ export class AppViewManager_ extends AppViewManager {
super(); super();
} }
getViewContainer(location: ElementRef_): ViewContainerRef { getViewContainer(location: ElementRef): ViewContainerRef {
return location.internalElement.getViewContainerRef(); return (<ElementRef_>location).internalElement.getViewContainerRef();
} }
getHostElement(hostViewRef: ViewRef_): ElementRef { getHostElement(hostViewRef: ViewRef): ElementRef {
var hostView = hostViewRef.internalView; var hostView = (<ViewRef_>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 +217,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 +237,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 +249,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 +264,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,20 +295,23 @@ 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);
} }

View File

@ -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)}";
} }

View File

@ -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);

View File

@ -28,7 +28,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;

View File

@ -15,6 +15,13 @@ import {PromiseWrapper, ObservableWrapper} from 'angular2/src/facade/async';
export class Testability { export class Testability {
/** @internal */ /** @internal */
_pendingCount: number = 0; _pendingCount: number = 0;
/**
* Whether any work was done since the last 'whenStable' callback. This is
* useful to detect if this could have potentially destabilized another
* component while it is stabilizing.
* @internal
*/
_didWork: boolean = false;
/** @internal */ /** @internal */
_callbacks: Function[] = []; _callbacks: Function[] = [];
/** @internal */ /** @internal */
@ -23,8 +30,10 @@ export class Testability {
/** @internal */ /** @internal */
_watchAngularEvents(_ngZone: NgZone): void { _watchAngularEvents(_ngZone: NgZone): void {
ObservableWrapper.subscribe(_ngZone.onTurnStart, ObservableWrapper.subscribe(_ngZone.onTurnStart, (_) => {
(_) => { this._isAngularEventPending = true; }); this._didWork = true;
this._isAngularEventPending = true;
});
_ngZone.runOutsideAngular(() => { _ngZone.runOutsideAngular(() => {
ObservableWrapper.subscribe(_ngZone.onEventDone, (_) => { ObservableWrapper.subscribe(_ngZone.onEventDone, (_) => {
@ -38,6 +47,7 @@ export class Testability {
increasePendingRequestCount(): number { increasePendingRequestCount(): number {
this._pendingCount += 1; this._pendingCount += 1;
this._didWork = true;
return this._pendingCount; return this._pendingCount;
} }
@ -55,14 +65,16 @@ export class Testability {
/** @internal */ /** @internal */
_runCallbacksIfReady(): void { _runCallbacksIfReady(): void {
if (!this.isStable()) { if (!this.isStable()) {
this._didWork = true;
return; // Not ready return; // Not ready
} }
// Schedules the call backs in a new frame so that it is always async. // Schedules the call backs in a new frame so that it is always async.
PromiseWrapper.resolve(null).then((_) => { PromiseWrapper.resolve(null).then((_) => {
while (this._callbacks.length !== 0) { while (this._callbacks.length !== 0) {
(this._callbacks.pop())(); (this._callbacks.pop())(this._didWork);
} }
this._didWork = false;
}); });
} }

View File

@ -73,16 +73,16 @@ class ObservableWrapper {
} }
class EventEmitter<T> extends Stream<T> { class EventEmitter<T> extends Stream<T> {
StreamController<dynamic> _controller; StreamController<T> _controller;
/// Creates an instance of [EventEmitter], which depending on [isAsync], /// Creates an instance of [EventEmitter], which depending on [isAsync],
/// delivers events synchronously or asynchronously. /// delivers events synchronously or asynchronously.
EventEmitter([bool isAsync = true]) { EventEmitter([bool isAsync = true]) {
_controller = new StreamController.broadcast(sync: !isAsync); _controller = new StreamController<T>.broadcast(sync: !isAsync);
} }
StreamSubscription listen(void onData(dynamic line), StreamSubscription<T> listen(void onData(T event),
{void onError(Error error), void onDone(), bool cancelOnError}) { {Function onError, void onDone(), bool cancelOnError}) {
return _controller.stream.listen(onData, return _controller.stream.listen(onData,
onError: onError, onDone: onDone, cancelOnError: cancelOnError); onError: onError, onDone: onDone, cancelOnError: cancelOnError);
} }
@ -106,14 +106,14 @@ class EventEmitter<T> extends Stream<T> {
//todo(robwormald): maybe fix in ts2dart? //todo(robwormald): maybe fix in ts2dart?
class Subject<T> extends Stream<T> { class Subject<T> extends Stream<T> {
StreamController<dynamic> _controller; StreamController<T> _controller;
Subject([bool isAsync = true]) { Subject([bool isAsync = true]) {
_controller = new StreamController.broadcast(sync: !isAsync); _controller = new StreamController<T>.broadcast(sync: !isAsync);
} }
StreamSubscription listen(void onData(dynamic line), StreamSubscription<T> listen(void onData(T data),
{void onError(Error error), void onDone(), bool cancelOnError}) { {Function onError, void onDone(), bool cancelOnError}) {
return _controller.stream.listen(onData, return _controller.stream.listen(onData,
onError: onError, onDone: onDone, cancelOnError: cancelOnError); onError: onError, onDone: onDone, cancelOnError: cancelOnError);
} }

View File

@ -4,9 +4,11 @@ import 'exception_handler.dart';
export 'exception_handler.dart'; export 'exception_handler.dart';
class BaseException extends Error { class BaseException extends Error {
final String message; final String _message;
BaseException([this.message]); BaseException([this._message]);
String get message => _message;
String toString() { String toString() {
return this.message; return this.message;
@ -14,16 +16,16 @@ class BaseException extends Error {
} }
class WrappedException extends Error { class WrappedException extends Error {
final dynamic context; final dynamic _context;
final String wrapperMessage; final String _wrapperMessage;
final originalException; final originalException;
final originalStack; final originalStack;
WrappedException( WrappedException(
[this.wrapperMessage, [this._wrapperMessage,
this.originalException, this.originalException,
this.originalStack, this.originalStack,
this.context]); this._context]);
get message { get message {
return ExceptionHandler.exceptionToString(this); return ExceptionHandler.exceptionToString(this);
@ -32,6 +34,10 @@ class WrappedException extends Error {
String toString() { String toString() {
return this.message; return this.message;
} }
dynamic get context => _context;
String get wrapperMessage => _wrapperMessage;
} }
Error makeTypeError([String message = ""]) { Error makeTypeError([String message = ""]) {

View File

@ -235,10 +235,26 @@ class FunctionWrapper {
const _NAN_KEY = const Object(); const _NAN_KEY = const Object();
// Dart can have identical(str1, str2) == false while str1 == str2. Moreover, // Dart VM implements `identical` as true reference identity. JavaScript does
// after compiling with dart2js identical(str1, str2) might return true. // not have this. The closest we have in JS is `===`. However, for strings JS
// (see dartbug.com/22496 for details). // would actually compare the contents rather than references. `dart2js`
bool looseIdentical(a, b) => // compiles `identical` to `===` and therefore there is a discrepancy between
// Dart VM and `dart2js`. The implementation of `looseIdentical` attempts to
// bridge the gap between the two while retaining good performance
// characteristics. In JS we use simple `identical`, which compiles to `===`,
// and in Dart VM we emulate the semantics of `===` by special-casing strings.
// Note that the VM check is a compile-time constant. This allows `dart2js` to
// evaluate the conditional during compilation and inline the entire function.
//
// See: dartbug.com/22496, dartbug.com/25270
const _IS_DART_VM = !identical(1.0, 1); // a hack
bool looseIdentical(a, b) => _IS_DART_VM
? _looseIdentical(a, b)
: identical(a, b);
// This function is intentionally separated from `looseIdentical` to keep the
// number of AST nodes low enough for `dart2js` to inline the code.
bool _looseIdentical(a, b) =>
a is String && b is String ? a == b : identical(a, b); a is String && b is String ? a == b : identical(a, b);
// Dart compare map keys by equality and we can have NaN != NaN // Dart compare map keys by equality and we can have NaN != NaN
@ -334,4 +350,4 @@ var global = null;
dynamic evalExpression(String sourceUrl, String expr, String declarations, Map<String, String> vars) { dynamic evalExpression(String sourceUrl, String expr, String declarations, Map<String, String> vars) {
throw "Dart does not support evaluating expression during runtime!"; throw "Dart does not support evaluating expression during runtime!";
} }

View File

@ -90,7 +90,7 @@ class PublicTestability implements _JsObjectProxyable {
'findBindings': (bindingString, [exactMatch, allowNonElementNodes]) => 'findBindings': (bindingString, [exactMatch, allowNonElementNodes]) =>
findBindings(bindingString, exactMatch, allowNonElementNodes), findBindings(bindingString, exactMatch, allowNonElementNodes),
'isStable': () => isStable(), 'isStable': () => isStable(),
'whenStable': (callback) => whenStable(() => callback.apply([])) 'whenStable': (callback) => whenStable((didWork) => callback.apply([didWork]))
})..['_dart_'] = this; })..['_dart_'] = this;
} }
} }
@ -116,16 +116,38 @@ class BrowserGetTestability implements GetTestability {
} }
throw 'Could not find testability for element.'; throw 'Could not find testability for element.';
}); });
js.context['getAllAngularTestabilities'] = _jsify(() { var getAllAngularTestabilities = () {
var registry = js.context['ngTestabilityRegistries']; var registry = js.context['ngTestabilityRegistries'];
var result = []; var result = [];
for (int i = 0; i < registry.length; i++) { for (int i = 0; i < registry.length; i++) {
var testabilities = var testabilities =
registry[i].callMethod('getAllAngularTestabilities'); registry[i].callMethod('getAllAngularTestabilities');
if (testabilities != null) result.addAll(testabilities); if (testabilities != null) result.addAll(testabilities);
} }
return _jsify(result); return _jsify(result);
};
js.context['getAllAngularTestabilities'] =
_jsify(getAllAngularTestabilities);
var whenAllStable = _jsify((callback) {
var testabilities = getAllAngularTestabilities();
var count = testabilities.length;
var didWork = false;
var decrement = _jsify((bool didWork_) {
didWork = didWork || didWork_;
count--;
if (count == 0) {
callback.apply([didWork]);
}
});
testabilities.forEach((testability) {
testability.callMethod('whenStable', [decrement]);
});
}); });
if (js.context['frameworkStabilizers'] == null) {
js.context['frameworkStabilizers'] = new js.JsArray();
}
js.context['frameworkStabilizers'].add(whenAllStable);
} }
jsRegistry.add(this._createRegistry(registry)); jsRegistry.add(this._createRegistry(registry));
} }
@ -163,4 +185,4 @@ class BrowserGetTestability implements GetTestability {
}); });
return object; return object;
} }
} }

View File

@ -48,6 +48,25 @@ export class BrowserGetTestability implements GetTestability {
var testabilities = registry.getAllTestabilities(); var testabilities = registry.getAllTestabilities();
return testabilities.map((testability) => { return new PublicTestability(testability); }); return testabilities.map((testability) => { return new PublicTestability(testability); });
}; };
var whenAllStable = (callback) => {
var testabilities = global.getAllAngularTestabilities();
var count = testabilities.length;
var didWork = false;
var decrement = function(didWork_) {
didWork = didWork || didWork_;
count--;
if (count == 0) {
callback(didWork);
}
};
testabilities.forEach(function(testability) { testability.whenStable(decrement); });
};
if (!global.frameworkStabilizers) {
global.frameworkStabilizers = ListWrapper.createGrowableSize(0);
}
global.frameworkStabilizers.push(whenAllStable);
} }
findTestabilityInTree(registry: TestabilityRegistry, elem: any, findTestabilityInTree(registry: TestabilityRegistry, elem: any,

View File

@ -23,13 +23,17 @@ export abstract class DomAdapter {
abstract logGroup(error); abstract logGroup(error);
abstract logGroupEnd(); abstract logGroupEnd();
/** @deprecated */
abstract getXHR(): Type; abstract getXHR(): Type;
/** /**
* Maps attribute names to their corresponding property names for cases * Maps attribute names to their corresponding property names for cases
* where attribute name doesn't match property name. * where attribute name doesn't match property name.
*/ */
attrToPropMap: {[key: string]: string}; get attrToPropMap(): {[key: string]: string} { return this._attrToPropMap; };
set attrToPropMap(value: {[key: string]: string}) { this._attrToPropMap = value; };
/** @internal */
_attrToPropMap: {[key: string]: string};
abstract parse(templateHtml: string); abstract parse(templateHtml: string);
abstract query(selector: string): any; abstract query(selector: string): any;

View File

@ -155,9 +155,9 @@ export class DomRenderer implements Renderer {
} }
} }
listen(renderElement: any, name: string, callback: Function) { listen(renderElement: any, name: string, callback: Function): Function {
this._rootRenderer.eventManager.addEventListener(renderElement, name, return this._rootRenderer.eventManager.addEventListener(renderElement, name,
decoratePreventDefault(callback)); decoratePreventDefault(callback));
} }
listenGlobal(target: string, name: string, callback: Function): Function { listenGlobal(target: string, name: string, callback: Function): Function {

View File

@ -4,16 +4,15 @@ import {EventManagerPlugin, EventManager} from './event_manager';
@Injectable() @Injectable()
export class DomEventsPlugin extends EventManagerPlugin { export class DomEventsPlugin extends EventManagerPlugin {
manager: EventManager;
// This plugin should come last in the list of plugins, because it accepts all // This plugin should come last in the list of plugins, because it accepts all
// events. // events.
supports(eventName: string): boolean { return true; } supports(eventName: string): boolean { return true; }
addEventListener(element: HTMLElement, eventName: string, handler: Function) { addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
var zone = this.manager.getZone(); var zone = this.manager.getZone();
var outsideHandler = (event) => zone.run(() => handler(event)); var outsideHandler = (event) => zone.run(() => handler(event));
this.manager.getZone().runOutsideAngular(() => { DOM.on(element, eventName, outsideHandler); }); return this.manager.getZone().runOutsideAngular(
() => DOM.onAndCancel(element, eventName, outsideHandler));
} }
addGlobalEventListener(target: string, eventName: string, handler: Function): Function { addGlobalEventListener(target: string, eventName: string, handler: Function): Function {
@ -21,6 +20,6 @@ export class DomEventsPlugin extends EventManagerPlugin {
var zone = this.manager.getZone(); var zone = this.manager.getZone();
var outsideHandler = (event) => zone.run(() => handler(event)); var outsideHandler = (event) => zone.run(() => handler(event));
return this.manager.getZone().runOutsideAngular( return this.manager.getZone().runOutsideAngular(
() => { return DOM.onAndCancel(element, eventName, outsideHandler); }); () => DOM.onAndCancel(element, eventName, outsideHandler));
} }
} }

View File

@ -16,9 +16,9 @@ export class EventManager {
this._plugins = ListWrapper.reversed(plugins); this._plugins = ListWrapper.reversed(plugins);
} }
addEventListener(element: HTMLElement, eventName: string, handler: Function) { addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
var plugin = this._findPluginFor(eventName); var plugin = this._findPluginFor(eventName);
plugin.addEventListener(element, eventName, handler); return plugin.addEventListener(element, eventName, handler);
} }
addGlobalEventListener(target: string, eventName: string, handler: Function): Function { addGlobalEventListener(target: string, eventName: string, handler: Function): Function {
@ -47,7 +47,7 @@ export class EventManagerPlugin {
// That is equivalent to having supporting $event.target // That is equivalent to having supporting $event.target
supports(eventName: string): boolean { return false; } supports(eventName: string): boolean { return false; }
addEventListener(element: HTMLElement, eventName: string, handler: Function) { addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
throw "not implemented"; throw "not implemented";
} }

View File

@ -15,17 +15,18 @@ export class HammerGesturesPlugin extends HammerGesturesPluginCommon {
return true; return true;
} }
addEventListener(element: HTMLElement, eventName: string, handler: Function) { addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
var zone = this.manager.getZone(); var zone = this.manager.getZone();
eventName = eventName.toLowerCase(); eventName = eventName.toLowerCase();
zone.runOutsideAngular(function() { return zone.runOutsideAngular(function() {
// Creating the manager bind events, must be done outside of angular // Creating the manager bind events, must be done outside of angular
var mc = new Hammer(element); var mc = new Hammer(element);
mc.get('pinch').set({enable: true}); mc.get('pinch').set({enable: true});
mc.get('rotate').set({enable: true}); mc.get('rotate').set({enable: true});
var handler = function(eventObj) { zone.run(function() { handler(eventObj); }); };
mc.on(eventName, function(eventObj) { zone.run(function() { handler(eventObj); }); }); mc.on(eventName, handler);
return () => { mc.off(eventName, handler); };
}); });
} }
} }

View File

@ -27,14 +27,15 @@ export class KeyEventsPlugin extends EventManagerPlugin {
return isPresent(KeyEventsPlugin.parseEventName(eventName)); return isPresent(KeyEventsPlugin.parseEventName(eventName));
} }
addEventListener(element: HTMLElement, eventName: string, handler: (Event: any) => any) { addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
var parsedEvent = KeyEventsPlugin.parseEventName(eventName); var parsedEvent = KeyEventsPlugin.parseEventName(eventName);
var outsideHandler = KeyEventsPlugin.eventCallback( var outsideHandler = KeyEventsPlugin.eventCallback(
element, StringMapWrapper.get(parsedEvent, 'fullKey'), handler, this.manager.getZone()); element, StringMapWrapper.get(parsedEvent, 'fullKey'), handler, this.manager.getZone());
this.manager.getZone().runOutsideAngular(() => { return this.manager.getZone().runOutsideAngular(() => {
DOM.on(element, StringMapWrapper.get(parsedEvent, 'domEventName'), outsideHandler); return DOM.onAndCancel(element, StringMapWrapper.get(parsedEvent, 'domEventName'),
outsideHandler);
}); });
} }
@ -90,8 +91,8 @@ export class KeyEventsPlugin extends EventManagerPlugin {
return fullKey; return fullKey;
} }
static eventCallback(element: HTMLElement, fullKey: any, handler: (e: Event) => any, static eventCallback(element: HTMLElement, fullKey: any, handler: Function,
zone: NgZone): (event: KeyboardEvent) => void { zone: NgZone): Function {
return (event) => { return (event) => {
if (StringWrapper.equals(KeyEventsPlugin.getEventFullKey(event), fullKey)) { if (StringWrapper.equals(KeyEventsPlugin.getEventFullKey(event), fullKey)) {
zone.run(() => handler(event)); zone.run(() => handler(event));

View File

@ -10,6 +10,7 @@ import {
import {WORKER_APP_APPLICATION_COMMON} from './worker_app_common'; import {WORKER_APP_APPLICATION_COMMON} from './worker_app_common';
import {APP_INITIALIZER} from 'angular2/core'; import {APP_INITIALIZER} from 'angular2/core';
import {MessageBus} from 'angular2/src/web_workers/shared/message_bus'; import {MessageBus} from 'angular2/src/web_workers/shared/message_bus';
import {COMPILER_PROVIDERS} from 'angular2/src/compiler/compiler';
// TODO(jteplitz602) remove this and compile with lib.webworker.d.ts (#3492) // TODO(jteplitz602) remove this and compile with lib.webworker.d.ts (#3492)
let _postMessage = { let _postMessage = {
@ -20,6 +21,7 @@ let _postMessage = {
export const WORKER_APP_APPLICATION: Array<any /*Type | Provider | any[]*/> = [ export const WORKER_APP_APPLICATION: Array<any /*Type | Provider | any[]*/> = [
WORKER_APP_APPLICATION_COMMON, WORKER_APP_APPLICATION_COMMON,
COMPILER_PROVIDERS,
new Provider(MessageBus, {useFactory: createMessageBus, deps: [NgZone]}), new Provider(MessageBus, {useFactory: createMessageBus, deps: [NgZone]}),
new Provider(APP_INITIALIZER, {useValue: setupWebWorker, multi: true}) new Provider(APP_INITIALIZER, {useValue: setupWebWorker, multi: true})
]; ];

View File

@ -19,7 +19,6 @@ import {
ServiceMessageBrokerFactory, ServiceMessageBrokerFactory,
ServiceMessageBrokerFactory_ ServiceMessageBrokerFactory_
} from 'angular2/src/web_workers/shared/service_message_broker'; } from 'angular2/src/web_workers/shared/service_message_broker';
import {COMPILER_PROVIDERS} from 'angular2/src/compiler/compiler';
import {Serializer} from "angular2/src/web_workers/shared/serializer"; import {Serializer} from "angular2/src/web_workers/shared/serializer";
import {ON_WEB_WORKER} from "angular2/src/web_workers/shared/api"; import {ON_WEB_WORKER} from "angular2/src/web_workers/shared/api";
import {Provider} from 'angular2/src/core/di'; import {Provider} from 'angular2/src/core/di';
@ -37,7 +36,6 @@ export const WORKER_APP_PLATFORM: Array<any /*Type | Provider | any[]*/> =
export const WORKER_APP_APPLICATION_COMMON: Array<any /*Type | Provider | any[]*/> = CONST_EXPR([ export const WORKER_APP_APPLICATION_COMMON: Array<any /*Type | Provider | any[]*/> = CONST_EXPR([
APPLICATION_COMMON_PROVIDERS, APPLICATION_COMMON_PROVIDERS,
COMPILER_PROVIDERS,
FORM_PROVIDERS, FORM_PROVIDERS,
Serializer, Serializer,
new Provider(PLATFORM_PIPES, {useValue: COMMON_PIPES, multi: true}), new Provider(PLATFORM_PIPES, {useValue: COMMON_PIPES, multi: true}),

View File

@ -2,7 +2,7 @@ library angular2.src.platform.worker_render;
import 'package:angular2/src/platform/worker_render_common.dart' import 'package:angular2/src/platform/worker_render_common.dart'
show show
WORKER_RENDER_APP_COMMON, WORKER_RENDER_APPLICATION_COMMON,
WORKER_RENDER_MESSAGING_PROVIDERS, WORKER_RENDER_MESSAGING_PROVIDERS,
WORKER_SCRIPT, WORKER_SCRIPT,
initializeGenericWorkerRenderer; initializeGenericWorkerRenderer;
@ -14,14 +14,14 @@ import 'package:angular2/src/core/zone/ng_zone.dart';
import 'dart:isolate'; import 'dart:isolate';
import 'dart:async'; import 'dart:async';
const WORKER_RENDER_APP = WORKER_RENDER_APP_COMMON; const WORKER_RENDER_APP = WORKER_RENDER_APPLICATION_COMMON;
initIsolate(String scriptUri) { initIsolate(String scriptUri) {
return (NgZone zone) async { return (NgZone zone) async {
var instance = await spawnIsolate(Uri.parse(scriptUri)); var instance = await spawnIsolate(Uri.parse(scriptUri));
return [ return [
WORKER_RENDER_APP_COMMON, WORKER_RENDER_APPLICATION_COMMON,
new Provider(WebWorkerInstance, useValue: instance), new Provider(WebWorkerInstance, useValue: instance),
new Provider(APP_INITIALIZER, new Provider(APP_INITIALIZER,
useFactory: (injector) => () => initializeGenericWorkerRenderer(injector), useFactory: (injector) => () => initializeGenericWorkerRenderer(injector),

View File

@ -9,7 +9,7 @@ import {Injector, Injectable, Provider} from 'angular2/src/core/di';
import {MessageBasedRenderer} from 'angular2/src/web_workers/ui/renderer'; import {MessageBasedRenderer} from 'angular2/src/web_workers/ui/renderer';
import {MessageBasedXHRImpl} from 'angular2/src/web_workers/ui/xhr_impl'; import {MessageBasedXHRImpl} from 'angular2/src/web_workers/ui/xhr_impl';
import { import {
WORKER_RENDER_APP_COMMON, WORKER_RENDER_APPLICATION_COMMON,
WORKER_RENDER_MESSAGING_PROVIDERS, WORKER_RENDER_MESSAGING_PROVIDERS,
WORKER_SCRIPT, WORKER_SCRIPT,
initializeGenericWorkerRenderer initializeGenericWorkerRenderer
@ -36,8 +36,8 @@ export class WebWorkerInstance {
/** /**
* An array of providers that should be passed into `application()` when initializing a new Worker. * An array of providers that should be passed into `application()` when initializing a new Worker.
*/ */
export const WORKER_RENDER_APP: Array<any /*Type | Provider | any[]*/> = CONST_EXPR([ export const WORKER_RENDER_APPLICATION: Array<any /*Type | Provider | any[]*/> = CONST_EXPR([
WORKER_RENDER_APP_COMMON, WORKER_RENDER_APPLICATION_COMMON,
WebWorkerInstance, WebWorkerInstance,
new Provider(APP_INITIALIZER, new Provider(APP_INITIALIZER,
{ {

View File

@ -59,7 +59,7 @@ export const WORKER_RENDER_PLATFORM: Array<any /*Type | Provider | any[]*/> = CO
new Provider(PLATFORM_INITIALIZER, {useValue: initWebWorkerRenderPlatform, multi: true}) new Provider(PLATFORM_INITIALIZER, {useValue: initWebWorkerRenderPlatform, multi: true})
]); ]);
export const WORKER_RENDER_APP_COMMON: Array<any /*Type | Provider | any[]*/> = CONST_EXPR([ export const WORKER_RENDER_APPLICATION_COMMON: Array<any /*Type | Provider | any[]*/> = CONST_EXPR([
APPLICATION_COMMON_PROVIDERS, APPLICATION_COMMON_PROVIDERS,
WORKER_RENDER_MESSAGING_PROVIDERS, WORKER_RENDER_MESSAGING_PROVIDERS,
new Provider(ExceptionHandler, {useFactory: _exceptionHandler, deps: []}), new Provider(ExceptionHandler, {useFactory: _exceptionHandler, deps: []}),

View File

@ -107,9 +107,8 @@ export var BLANK_ROUTE_DATA = new RouteData();
* ``` * ```
*/ */
export abstract class Instruction { export abstract class Instruction {
public component: ComponentInstruction; constructor(public component: ComponentInstruction, public child: Instruction,
public child: Instruction; public auxInstruction: {[key: string]: Instruction}) {}
public auxInstruction: {[key: string]: Instruction} = {};
get urlPath(): string { return isPresent(this.component) ? this.component.urlPath : ''; } get urlPath(): string { return isPresent(this.component) ? this.component.urlPath : ''; }
@ -210,9 +209,9 @@ export abstract class Instruction {
* a resolved instruction has an outlet instruction for itself, but maybe not for... * a resolved instruction has an outlet instruction for itself, but maybe not for...
*/ */
export class ResolvedInstruction extends Instruction { export class ResolvedInstruction extends Instruction {
constructor(public component: ComponentInstruction, public child: Instruction, constructor(component: ComponentInstruction, child: Instruction,
public auxInstruction: {[key: string]: Instruction}) { auxInstruction: {[key: string]: Instruction}) {
super(); super(component, child, auxInstruction);
} }
resolveComponent(): Promise<ComponentInstruction> { resolveComponent(): Promise<ComponentInstruction> {
@ -225,7 +224,9 @@ export class ResolvedInstruction extends Instruction {
* Represents a resolved default route * Represents a resolved default route
*/ */
export class DefaultInstruction extends Instruction { export class DefaultInstruction extends Instruction {
constructor(public component: ComponentInstruction, public child: DefaultInstruction) { super(); } constructor(component: ComponentInstruction, child: DefaultInstruction) {
super(component, child, {});
}
resolveComponent(): Promise<ComponentInstruction> { resolveComponent(): Promise<ComponentInstruction> {
return PromiseWrapper.resolve(this.component); return PromiseWrapper.resolve(this.component);
@ -244,7 +245,7 @@ export class DefaultInstruction extends Instruction {
export class UnresolvedInstruction extends Instruction { export class UnresolvedInstruction extends Instruction {
constructor(private _resolver: () => Promise<Instruction>, private _urlPath: string = '', constructor(private _resolver: () => Promise<Instruction>, private _urlPath: string = '',
private _urlParams: string[] = CONST_EXPR([])) { private _urlParams: string[] = CONST_EXPR([])) {
super(); super(null, null, {});
} }
get urlPath(): string { get urlPath(): string {

View File

@ -202,12 +202,12 @@ export class Router {
return this._settleInstruction(instruction) return this._settleInstruction(instruction)
.then((_) => this._routerCanReuse(instruction)) .then((_) => this._routerCanReuse(instruction))
.then((_) => this._canActivate(instruction)) .then((_) => this._canActivate(instruction))
.then((result) => { .then((result: boolean) => {
if (!result) { if (!result) {
return false; return false;
} }
return this._routerCanDeactivate(instruction) return this._routerCanDeactivate(instruction)
.then((result) => { .then((result: boolean) => {
if (result) { if (result) {
return this.commit(instruction, _skipLocationChange) return this.commit(instruction, _skipLocationChange)
.then((_) => { .then((_) => {

View File

@ -1,130 +1,7 @@
import { import {Injector, Provider, PLATFORM_INITIALIZER} from 'angular2/core';
APP_ID,
APPLICATION_COMMON_PROVIDERS,
AppViewManager,
DirectiveResolver,
DynamicComponentLoader,
Injector,
NgZone,
Renderer,
Provider,
ViewResolver,
provide
} from 'angular2/core';
import {AnimationBuilder} from 'angular2/src/animate/animation_builder';
import {MockAnimationBuilder} from 'angular2/src/mock/animation_builder_mock';
import {ResolvedMetadataCache} from 'angular2/src/core/linker/resolved_metadata_cache';
import {Reflector, reflector} from 'angular2/src/core/reflection/reflection';
import {
IterableDiffers,
defaultIterableDiffers,
KeyValueDiffers,
defaultKeyValueDiffers,
ChangeDetectorGenConfig
} from 'angular2/src/core/change_detection/change_detection';
import {BaseException, ExceptionHandler} from 'angular2/src/facade/exceptions'; import {BaseException, ExceptionHandler} from 'angular2/src/facade/exceptions';
import {PipeResolver} from 'angular2/src/core/linker/pipe_resolver';
import {XHR} from 'angular2/src/compiler/xhr';
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
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 './test_component_builder';
import {
EventManager,
EVENT_MANAGER_PLUGINS,
ELEMENT_PROBE_PROVIDERS
} from 'angular2/platform/common_dom';
import {ListWrapper} from 'angular2/src/facade/collection'; import {ListWrapper} from 'angular2/src/facade/collection';
import {FunctionWrapper, Type} from 'angular2/src/facade/lang'; import {FunctionWrapper, isPresent, Type} from 'angular2/src/facade/lang';
import {RootRenderer} from 'angular2/src/core/render/api';
import {DOCUMENT} from 'angular2/src/platform/dom/dom_tokens';
import {DomRootRenderer, DomRootRenderer_} from 'angular2/src/platform/dom/dom_renderer';
import {DomSharedStylesHost} from 'angular2/src/platform/dom/shared_styles_host';
import {SharedStylesHost} from 'angular2/src/platform/dom/shared_styles_host';
import {DomEventsPlugin} from 'angular2/src/platform/dom/events/dom_events';
import {Serializer} from "angular2/src/web_workers/shared/serializer";
import {Log} from './utils';
import {COMPILER_PROVIDERS} from 'angular2/src/compiler/compiler';
import {DynamicComponentLoader_} from "angular2/src/core/linker/dynamic_component_loader";
import {AppViewManager_} from "angular2/src/core/linker/view_manager";
/**
* Returns the root injector providers.
*
* This must be kept in sync with the _rootBindings in application.js
*
* @returns {any[]}
*/
function _getRootProviders() {
return [provide(Reflector, {useValue: reflector})];
}
/**
* Returns the application injector providers.
*
* This must be kept in sync with _injectorBindings() in application.js
*
* @returns {any[]}
*/
function _getAppBindings() {
var appDoc;
// The document is only available in browser environment
try {
appDoc = DOM.defaultDoc();
} catch (e) {
appDoc = null;
}
return [
APPLICATION_COMMON_PROVIDERS,
provide(ChangeDetectorGenConfig, {useValue: new ChangeDetectorGenConfig(true, false, false)}),
provide(DOCUMENT, {useValue: appDoc}),
provide(DomRootRenderer, {useClass: DomRootRenderer_}),
provide(RootRenderer, {useExisting: DomRootRenderer}),
provide(APP_ID, {useValue: 'a'}),
DomSharedStylesHost,
provide(SharedStylesHost, {useExisting: DomSharedStylesHost}),
provide(AppViewManager, {useClass: AppViewManager_}),
Serializer,
ELEMENT_PROBE_PROVIDERS,
ResolvedMetadataCache,
provide(DirectiveResolver, {useClass: MockDirectiveResolver}),
provide(ViewResolver, {useClass: MockViewResolver}),
provide(IterableDiffers, {useValue: defaultIterableDiffers}),
provide(KeyValueDiffers, {useValue: defaultKeyValueDiffers}),
Log,
provide(DynamicComponentLoader, {useClass: DynamicComponentLoader_}),
PipeResolver,
provide(ExceptionHandler, {useValue: new ExceptionHandler(DOM)}),
provide(LocationStrategy, {useClass: MockLocationStrategy}),
provide(XHR, {useClass: DOM.getXHR()}),
TestComponentBuilder,
provide(NgZone, {useClass: MockNgZone}),
provide(AnimationBuilder, {useClass: MockAnimationBuilder}),
EventManager,
new Provider(EVENT_MANAGER_PLUGINS, {useClass: DomEventsPlugin, multi: true})
];
}
function _runtimeCompilerBindings() {
return [
provide(XHR, {useClass: DOM.getXHR()}),
COMPILER_PROVIDERS,
];
}
export class TestInjector { export class TestInjector {
private _instantiated: boolean = false; private _instantiated: boolean = false;
@ -139,6 +16,10 @@ export class TestInjector {
this._instantiated = false; this._instantiated = false;
} }
platformProviders: Array<Type | Provider | any[]> = [];
applicationProviders: Array<Type | Provider | any[]> = [];
addProviders(providers: Array<Type | Provider | any[]>) { addProviders(providers: Array<Type | Provider | any[]>) {
if (this._instantiated) { if (this._instantiated) {
throw new BaseException('Cannot add providers after test injector is instantiated'); throw new BaseException('Cannot add providers after test injector is instantiated');
@ -147,9 +28,9 @@ export class TestInjector {
} }
createInjector() { createInjector() {
var rootInjector = Injector.resolveAndCreate(_getRootProviders()); var rootInjector = Injector.resolveAndCreate(this.platformProviders);
this._injector = rootInjector.resolveAndCreateChild(ListWrapper.concat( this._injector = rootInjector.resolveAndCreateChild(
ListWrapper.concat(_getAppBindings(), _runtimeCompilerBindings()), this._providers)); ListWrapper.concat(this.applicationProviders, this._providers));
this._instantiated = true; this._instantiated = true;
return this._injector; return this._injector;
} }
@ -172,19 +53,40 @@ export function getTestInjector() {
} }
/** /**
* @deprecated Use TestInjector#createInjector() instead. * Set the providers that the test injector should use. These should be providers
* common to every test in the suite.
*
* This may only be called once, to set up the common providers for the current test
* suite on teh current platform. If you absolutely need to change the providers,
* first use `resetBaseTestProviders`.
*
* Test Providers for individual platforms are available from
* 'angular2/platform/testing/<platform_name>'.
*/ */
export function createTestInjector(providers: Array<Type | Provider | any[]>): Injector { export function setBaseTestProviders(platformProviders: Array<Type | Provider | any[]>,
var rootInjector = Injector.resolveAndCreate(_getRootProviders()); applicationProviders: Array<Type | Provider | any[]>) {
return rootInjector.resolveAndCreateChild(ListWrapper.concat(_getAppBindings(), providers)); var testInjector = getTestInjector();
if (testInjector.platformProviders.length > 0 || testInjector.applicationProviders.length > 0) {
throw new BaseException('Cannot set base providers because it has already been called');
}
testInjector.platformProviders = platformProviders;
testInjector.applicationProviders = applicationProviders;
var injector = testInjector.createInjector();
let inits: Function[] = injector.getOptional(PLATFORM_INITIALIZER);
if (isPresent(inits)) {
inits.forEach(init => init());
}
testInjector.reset();
} }
/** /**
* @deprecated Use TestInjector#createInjector() instead. * Reset the providers for the test injector.
*/ */
export function createTestInjectorWithRuntimeCompiler( export function resetBaseTestProviders() {
providers: Array<Type | Provider | any[]>): Injector { var testInjector = getTestInjector();
return createTestInjector(ListWrapper.concat(_runtimeCompilerBindings(), providers)); testInjector.platformProviders = [];
testInjector.applicationProviders = [];
testInjector.reset();
} }
/** /**

View File

@ -126,77 +126,23 @@ function _isPromiseLike(input): boolean {
return input && !!(input.then); return input && !!(input.then);
} }
function runInTestZone(fnToExecute, finishCallback, failCallback): any {
var pendingMicrotasks = 0;
var pendingTimeouts = [];
var ngTestZone = (<Zone>global.zone)
.fork({
onError: function(e) { failCallback(e); },
'$run': function(parentRun) {
return function() {
try {
return parentRun.apply(this, arguments);
} finally {
if (pendingMicrotasks == 0 && pendingTimeouts.length == 0) {
finishCallback();
}
}
};
},
'$scheduleMicrotask': function(parentScheduleMicrotask) {
return function(fn) {
pendingMicrotasks++;
var microtask = function() {
try {
fn();
} finally {
pendingMicrotasks--;
}
};
parentScheduleMicrotask.call(this, microtask);
};
},
'$setTimeout': function(parentSetTimeout) {
return function(fn: Function, delay: number, ...args) {
var id;
var cb = function() {
fn();
ListWrapper.remove(pendingTimeouts, id);
};
id = parentSetTimeout(cb, delay, args);
pendingTimeouts.push(id);
return id;
};
},
'$clearTimeout': function(parentClearTimeout) {
return function(id: number) {
parentClearTimeout(id);
ListWrapper.remove(pendingTimeouts, id);
};
},
});
return ngTestZone.run(fnToExecute);
}
function _it(jsmFn: Function, name: string, testFn: FunctionWithParamTokens | AnyTestFn, function _it(jsmFn: Function, name: string, testFn: FunctionWithParamTokens | AnyTestFn,
testTimeOut: number): void { testTimeOut: number): void {
var timeOut = testTimeOut; var timeOut = testTimeOut;
if (testFn instanceof FunctionWithParamTokens) { if (testFn instanceof FunctionWithParamTokens) {
jsmFn(name, (done) => { jsmFn(name, (done) => {
var finishCallback = () => { var returnedTestValue;
// Wait one more event loop to make sure we catch unreturned promises and try {
// promise rejections. returnedTestValue = testInjector.execute(testFn);
setTimeout(done, 0); } catch (err) {
}; done.fail(err);
var returnedTestValue = return;
runInTestZone(() => testInjector.execute(testFn), finishCallback, done.fail); }
if (testFn.isAsync) { if (testFn.isAsync) {
if (_isPromiseLike(returnedTestValue)) { if (_isPromiseLike(returnedTestValue)) {
(<Promise<any>>returnedTestValue).then(null, (err) => { done.fail(err); }); (<Promise<any>>returnedTestValue).then(() => { done(); }, (err) => { done.fail(err); });
} else { } else {
done.fail('Error: injectAsync was expected to return a promise, but the ' + done.fail('Error: injectAsync was expected to return a promise, but the ' +
' returned value was: ' + returnedTestValue); ' returned value was: ' + returnedTestValue);
@ -206,6 +152,7 @@ function _it(jsmFn: Function, name: string, testFn: FunctionWithParamTokens | An
done.fail('Error: inject returned a value. Did you mean to use injectAsync? Returned ' + done.fail('Error: inject returned a value. Did you mean to use injectAsync? Returned ' +
'value was: ' + returnedTestValue); 'value was: ' + returnedTestValue);
} }
done();
} }
}, timeOut); }, timeOut);
} else { } else {
@ -232,17 +179,17 @@ export function beforeEach(fn: FunctionWithParamTokens | AnyTestFn): void {
// The test case uses inject(). ie `beforeEach(inject([ClassA], (a) => { ... // The test case uses inject(). ie `beforeEach(inject([ClassA], (a) => { ...
// }));` // }));`
jsmBeforeEach((done) => { jsmBeforeEach((done) => {
var finishCallback = () => {
// Wait one more event loop to make sure we catch unreturned promises and
// promise rejections.
setTimeout(done, 0);
};
var returnedTestValue = var returnedTestValue;
runInTestZone(() => testInjector.execute(fn), finishCallback, done.fail); try {
returnedTestValue = testInjector.execute(fn);
} catch (err) {
done.fail(err);
return;
}
if (fn.isAsync) { if (fn.isAsync) {
if (_isPromiseLike(returnedTestValue)) { if (_isPromiseLike(returnedTestValue)) {
(<Promise<any>>returnedTestValue).then(null, (err) => { done.fail(err); }); (<Promise<any>>returnedTestValue).then(() => { done(); }, (err) => { done.fail(err); });
} else { } else {
done.fail('Error: injectAsync was expected to return a promise, but the ' + done.fail('Error: injectAsync was expected to return a promise, but the ' +
' returned value was: ' + returnedTestValue); ' returned value was: ' + returnedTestValue);
@ -252,6 +199,7 @@ export function beforeEach(fn: FunctionWithParamTokens | AnyTestFn): void {
done.fail('Error: inject returned a value. Did you mean to use injectAsync? Returned ' + done.fail('Error: inject returned a value. Did you mean to use injectAsync? Returned ' +
'value was: ' + returnedTestValue); 'value was: ' + returnedTestValue);
} }
done();
} }
}); });
} else { } else {

View File

@ -21,10 +21,13 @@ export class Log {
result(): string { return this._result.join("; "); } result(): string { return this._result.join("; "); }
} }
export var browserDetection: BrowserDetection = null;
export class BrowserDetection { export class BrowserDetection {
private _ua: string; private _ua: string;
static setup() { browserDetection = new BrowserDetection(null); }
constructor(ua: string) { constructor(ua: string) {
if (isPresent(ua)) { if (isPresent(ua)) {
this._ua = ua; this._ua = ua;
@ -61,7 +64,6 @@ export class BrowserDetection {
return this._ua.indexOf('Chrome/4') > -1 && this._ua.indexOf('Edge') == -1; return this._ua.indexOf('Chrome/4') > -1 && this._ua.indexOf('Edge') == -1;
} }
} }
export var browserDetection: BrowserDetection = new BrowserDetection(null);
export function dispatchEvent(element, eventType): void { export function dispatchEvent(element, eventType): void {
DOM.dispatchEvent(element, DOM.createEvent(eventType)); DOM.dispatchEvent(element, DOM.createEvent(eventType));

View File

@ -9,29 +9,32 @@ import 'package:angular2/src/facade/lang.dart';
import 'package:angular2/src/facade/exceptions.dart'; import 'package:angular2/src/facade/exceptions.dart';
class GenericMessageBus implements MessageBus { class GenericMessageBus implements MessageBus {
MessageBusSink sink; final MessageBusSink _sink;
MessageBusSource source; final MessageBusSource _source;
MessageBusSink get sink => _sink;
MessageBusSource get source => _source;
GenericMessageBus(MessageBusSink sink, MessageBusSource source) GenericMessageBus(MessageBusSink sink, MessageBusSource source)
: sink = sink, : _sink = sink,
source = source; _source = source;
void attachToZone(NgZone zone) { void attachToZone(NgZone zone) {
sink.attachToZone(zone); _sink.attachToZone(zone);
source.attachToZone(zone); _source.attachToZone(zone);
} }
void initChannel(String channel, [bool runInZone = true]) { void initChannel(String channel, [bool runInZone = true]) {
sink.initChannel(channel, runInZone); _sink.initChannel(channel, runInZone);
source.initChannel(channel, runInZone); _source.initChannel(channel, runInZone);
} }
EventEmitter from(String channel) { EventEmitter from(String channel) {
return source.from(channel); return _source.from(channel);
} }
EventEmitter to(String channel) { EventEmitter to(String channel) {
return sink.to(channel); return _sink.to(channel);
} }
} }

View File

@ -66,12 +66,12 @@ export class MessageBasedRenderer {
bind(this._invokeElementMethod, this)); bind(this._invokeElementMethod, this));
broker.registerMethod("setText", [RenderStoreObject, RenderStoreObject, PRIMITIVE], broker.registerMethod("setText", [RenderStoreObject, RenderStoreObject, PRIMITIVE],
bind(this._setText, this)); bind(this._setText, this));
broker.registerMethod("listen", [RenderStoreObject, RenderStoreObject, PRIMITIVE], broker.registerMethod("listen", [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
bind(this._listen, this)); bind(this._listen, this));
broker.registerMethod("listenGlobal", [RenderStoreObject, PRIMITIVE, PRIMITIVE, PRIMITIVE], broker.registerMethod("listenGlobal", [RenderStoreObject, PRIMITIVE, PRIMITIVE, PRIMITIVE],
bind(this._listenGlobal, this)); bind(this._listenGlobal, this));
broker.registerMethod("listenGlobalDone", [RenderStoreObject, RenderStoreObject], broker.registerMethod("listenDone", [RenderStoreObject, RenderStoreObject],
bind(this._listenGlobalDone, this)); bind(this._listenDone, this));
} }
private _renderComponent(renderComponentType: RenderComponentType, rendererId: number) { private _renderComponent(renderComponentType: RenderComponentType, rendererId: number) {
@ -155,9 +155,11 @@ export class MessageBasedRenderer {
renderer.setText(renderNode, text); renderer.setText(renderNode, text);
} }
private _listen(renderer: Renderer, renderElement: any, eventName: string) { private _listen(renderer: Renderer, renderElement: any, eventName: string, unlistenId: number) {
renderer.listen(renderElement, eventName, (event) => this._eventDispatcher.dispatchRenderEvent( var unregisterCallback = renderer.listen(renderElement, eventName,
renderElement, null, eventName, event)); (event) => this._eventDispatcher.dispatchRenderEvent(
renderElement, null, eventName, event));
this._renderStore.store(unregisterCallback, unlistenId);
} }
private _listenGlobal(renderer: Renderer, eventTarget: string, eventName: string, private _listenGlobal(renderer: Renderer, eventTarget: string, eventName: string,
@ -168,5 +170,5 @@ export class MessageBasedRenderer {
this._renderStore.store(unregisterCallback, unlistenId); this._renderStore.store(unregisterCallback, unlistenId);
} }
private _listenGlobalDone(renderer: Renderer, unlistenCallback: Function) { unlistenCallback(); } private _listenDone(renderer: Renderer, unlistenCallback: Function) { unlistenCallback(); }
} }

View File

@ -215,10 +215,18 @@ export class WebWorkerRenderer implements Renderer, RenderStoreObject {
[new FnArg(renderNode, RenderStoreObject), new FnArg(text, null)]); [new FnArg(renderNode, RenderStoreObject), new FnArg(text, null)]);
} }
listen(renderElement: WebWorkerRenderNode, name: string, callback: Function) { listen(renderElement: WebWorkerRenderNode, name: string, callback: Function): Function {
renderElement.events.listen(name, callback); renderElement.events.listen(name, callback);
this._runOnService('listen', var unlistenCallbackId = this._rootRenderer.allocateId();
[new FnArg(renderElement, RenderStoreObject), new FnArg(name, null)]); this._runOnService('listen', [
new FnArg(renderElement, RenderStoreObject),
new FnArg(name, null),
new FnArg(unlistenCallbackId, null)
]);
return () => {
renderElement.events.unlisten(name, callback);
this._runOnService('listenDone', [new FnArg(unlistenCallbackId, null)]);
};
} }
listenGlobal(target: string, name: string, callback: Function): Function { listenGlobal(target: string, name: string, callback: Function): Function {
@ -229,7 +237,7 @@ export class WebWorkerRenderer implements Renderer, RenderStoreObject {
[new FnArg(target, null), new FnArg(name, null), new FnArg(unlistenCallbackId, null)]); [new FnArg(target, null), new FnArg(name, null), new FnArg(unlistenCallbackId, null)]);
return () => { return () => {
this._rootRenderer.globalEvents.unlisten(eventNameWithTarget(target, name), callback); this._rootRenderer.globalEvents.unlisten(eventNameWithTarget(target, name), callback);
this._runOnService('listenGlobalDone', [new FnArg(unlistenCallbackId, null)]); this._runOnService('listenDone', [new FnArg(unlistenCallbackId, null)]);
}; };
} }
} }

View File

@ -6,9 +6,7 @@ import 'package:angular2/core.dart' show ChangeDetectorRef;
import 'package:angular2/common.dart' show ObservableListDiffFactory; import 'package:angular2/common.dart' show ObservableListDiffFactory;
@proxy @proxy
class SpyChangeDetectorRef extends SpyObject implements ChangeDetectorRef { class SpyChangeDetectorRef extends SpyObject implements ChangeDetectorRef {}
noSuchMethod(m) => super.noSuchMethod(m);
}
main() { main() {
describe('ObservableListDiff', () { describe('ObservableListDiff', () {

View File

@ -5,16 +5,10 @@ import 'package:angular2/src/core/change_detection/change_detection.dart';
import 'package:angular2/testing_internal.dart'; import 'package:angular2/testing_internal.dart';
@proxy @proxy
class SpyNgControl extends SpyObject implements NgControl { class SpyNgControl extends SpyObject implements NgControl {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyValueAccessor extends SpyObject implements ControlValueAccessor { class SpyValueAccessor extends SpyObject implements ControlValueAccessor {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyChangeDetectorRef extends SpyObject implements ChangeDetectorRef { class SpyChangeDetectorRef extends SpyObject implements ChangeDetectorRef {}
noSuchMethod(m) => super.noSuchMethod(m);
}

View File

@ -14,7 +14,7 @@ import {
} from 'angular2/testing_internal'; } from 'angular2/testing_internal';
import {provide} from 'angular2/src/core/di'; import {provide} from 'angular2/src/core/di';
import {CONST_EXPR, stringify} from 'angular2/src/facade/lang'; import {CONST_EXPR, stringify, IS_DART} from 'angular2/src/facade/lang';
import {MapWrapper} from 'angular2/src/facade/collection'; import {MapWrapper} from 'angular2/src/facade/collection';
import {Promise} from 'angular2/src/facade/async'; import {Promise} from 'angular2/src/facade/async';
@ -55,6 +55,11 @@ var THIS_MODULE_URL = `package:${THIS_MODULE_ID}${MODULE_SUFFIX}`;
var THIS_MODULE_REF = moduleRef(THIS_MODULE_URL); var THIS_MODULE_REF = moduleRef(THIS_MODULE_URL);
export function main() { export function main() {
// Dart's isolate support is broken, and these tests will be obsolote soon with
// https://github.com/angular/angular/issues/6270
if (IS_DART) {
return;
}
describe('ChangeDetectorCompiler', () => { describe('ChangeDetectorCompiler', () => {
beforeEachProviders(() => [ beforeEachProviders(() => [
TEST_PROVIDERS, TEST_PROVIDERS,

View File

@ -22,6 +22,11 @@ export var TEST_VALUE = 23;
const THIS_MODULE_URL = `package:angular2/test/compiler/eval_module_spec${IS_DART?'.dart':'.js'}`; const THIS_MODULE_URL = `package:angular2/test/compiler/eval_module_spec${IS_DART?'.dart':'.js'}`;
export function main() { export function main() {
// Dart's isolate support is broken, and these tests will be obsolote soon with
// https://github.com/angular/angular/issues/6270
if (IS_DART) {
return;
}
describe('evalModule', () => { describe('evalModule', () => {
it('should call the "run" function and allow to use imports', it('should call the "run" function and allow to use imports',
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {

View File

@ -114,9 +114,9 @@ export function main() {
}); });
}); });
describe('cdata', () => { describe('CDATA', () => {
it('should parse cdata', () => { it('should parse CDATA', () => {
expect(tokenizeAndHumanizeParts('<![cdata[t\ne\rs\r\nt]]>')) expect(tokenizeAndHumanizeParts('<![CDATA[t\ne\rs\r\nt]]>'))
.toEqual([ .toEqual([
[HtmlTokenType.CDATA_START], [HtmlTokenType.CDATA_START],
[HtmlTokenType.RAW_TEXT, 't\ne\ns\nt'], [HtmlTokenType.RAW_TEXT, 't\ne\ns\nt'],
@ -126,22 +126,22 @@ export function main() {
}); });
it('should store the locations', () => { it('should store the locations', () => {
expect(tokenizeAndHumanizeSourceSpans('<![cdata[t\ne\rs\r\nt]]>')) expect(tokenizeAndHumanizeSourceSpans('<![CDATA[t\ne\rs\r\nt]]>'))
.toEqual([ .toEqual([
[HtmlTokenType.CDATA_START, '<![cdata['], [HtmlTokenType.CDATA_START, '<![CDATA['],
[HtmlTokenType.RAW_TEXT, 't\ne\rs\r\nt'], [HtmlTokenType.RAW_TEXT, 't\ne\rs\r\nt'],
[HtmlTokenType.CDATA_END, ']]>'], [HtmlTokenType.CDATA_END, ']]>'],
[HtmlTokenType.EOF, ''] [HtmlTokenType.EOF, '']
]); ]);
}); });
it('should report <![ without cdata[', () => { it('should report <![ without CDATA[', () => {
expect(tokenizeAndHumanizeErrors('<![a')) expect(tokenizeAndHumanizeErrors('<![a'))
.toEqual([[HtmlTokenType.CDATA_START, 'Unexpected character "a"', '0:3']]); .toEqual([[HtmlTokenType.CDATA_START, 'Unexpected character "a"', '0:3']]);
}); });
it('should report missing end cdata', () => { it('should report missing end cdata', () => {
expect(tokenizeAndHumanizeErrors('<![cdata[')) expect(tokenizeAndHumanizeErrors('<![CDATA['))
.toEqual([[HtmlTokenType.RAW_TEXT, 'Unexpected character "EOF"', '0:9']]); .toEqual([[HtmlTokenType.RAW_TEXT, 'Unexpected character "EOF"', '0:9']]);
}); });
}); });
@ -367,8 +367,8 @@ export function main() {
}); });
it('should parse hexadecimal entities', () => { it('should parse hexadecimal entities', () => {
expect(tokenizeAndHumanizeParts('&#x41;')) expect(tokenizeAndHumanizeParts('&#x41;&#X41;'))
.toEqual([[HtmlTokenType.TEXT, 'A'], [HtmlTokenType.EOF]]); .toEqual([[HtmlTokenType.TEXT, 'AA'], [HtmlTokenType.EOF]]);
}); });
it('should parse decimal entities', () => { it('should parse decimal entities', () => {
@ -473,7 +473,7 @@ export function main() {
}); });
it('should not detect entities', () => { it('should not detect entities', () => {
expect(tokenizeAndHumanizeParts(`<script>&amp;</script>`)) expect(tokenizeAndHumanizeParts(`<script>&amp;</SCRIPT>`))
.toEqual([ .toEqual([
[HtmlTokenType.TAG_OPEN_START, null, 'script'], [HtmlTokenType.TAG_OPEN_START, null, 'script'],
[HtmlTokenType.TAG_OPEN_END], [HtmlTokenType.TAG_OPEN_END],
@ -587,6 +587,19 @@ export function main() {
}); });
}); });
describe('unicode characters', () => {
it('should support unicode characters', () => {
expect(tokenizeAndHumanizeSourceSpans(`<p>İ</p>`))
.toEqual([
[HtmlTokenType.TAG_OPEN_START, '<p'],
[HtmlTokenType.TAG_OPEN_END, '>'],
[HtmlTokenType.TEXT, 'İ'],
[HtmlTokenType.TAG_CLOSE, '</p>'],
[HtmlTokenType.EOF, '']
]);
});
});
}); });
} }

View File

@ -83,19 +83,19 @@ export function main() {
it('should return the directive metadatas', it('should return the directive metadatas',
inject([RuntimeMetadataResolver], (resolver: RuntimeMetadataResolver) => { inject([RuntimeMetadataResolver], (resolver: RuntimeMetadataResolver) => {
expect(resolver.getViewDirectivesMetadata(ComponentWithEverything)) expect(resolver.getViewDirectivesMetadata(ComponentWithEverything))
.toEqual([resolver.getDirectiveMetadata(SomeDirective)]); .toContain(resolver.getDirectiveMetadata(SomeDirective));
})); }));
describe("platform directives", () => { describe("platform directives", () => {
beforeEachProviders(() => [provide(PLATFORM_DIRECTIVES, {useValue: [ADirective]})]); beforeEachProviders(
() => [provide(PLATFORM_DIRECTIVES, {useValue: [ADirective], multi: true})]);
it('should include platform directives when available', it('should include platform directives when available',
inject([RuntimeMetadataResolver], (resolver: RuntimeMetadataResolver) => { inject([RuntimeMetadataResolver], (resolver: RuntimeMetadataResolver) => {
expect(resolver.getViewDirectivesMetadata(ComponentWithEverything)) expect(resolver.getViewDirectivesMetadata(ComponentWithEverything))
.toEqual([ .toContain(resolver.getDirectiveMetadata(ADirective));
resolver.getDirectiveMetadata(ADirective), expect(resolver.getViewDirectivesMetadata(ComponentWithEverything))
resolver.getDirectiveMetadata(SomeDirective) .toContain(resolver.getDirectiveMetadata(SomeDirective));
]);
})); }));
}); });
}); });

View File

@ -5,11 +5,7 @@ import 'package:angular2/testing_internal.dart';
import 'package:angular2/src/compiler/template_compiler.dart'; import 'package:angular2/src/compiler/template_compiler.dart';
@proxy @proxy
class SpyXHR extends SpyObject implements XHR { class SpyXHR extends SpyObject implements XHR {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyTemplateCompiler extends SpyObject implements TemplateCompiler { class SpyTemplateCompiler extends SpyObject implements TemplateCompiler {}
noSuchMethod(m) => super.noSuchMethod(m);
}

View File

@ -17,7 +17,14 @@ import {SpyXHR} from './spies';
import {XHR} from 'angular2/src/compiler/xhr'; import {XHR} from 'angular2/src/compiler/xhr';
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions'; import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
import {CONST_EXPR, isPresent, isBlank, StringWrapper, isArray} from 'angular2/src/facade/lang'; import {
CONST_EXPR,
isPresent,
isBlank,
StringWrapper,
isArray,
IS_DART
} from 'angular2/src/facade/lang';
import {PromiseWrapper, Promise} from 'angular2/src/facade/async'; import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
import {evalModule} from './eval_module'; import {evalModule} from './eval_module';
import {StyleCompiler} from 'angular2/src/compiler/style_compiler'; import {StyleCompiler} from 'angular2/src/compiler/style_compiler';
@ -40,6 +47,11 @@ var IMPORT_ABS_STYLESHEET_URL_WITH_IMPORT =
`package:angular2/test/compiler/style_compiler_transitive_import.css`; `package:angular2/test/compiler/style_compiler_transitive_import.css`;
export function main() { export function main() {
// Dart's isolate support is broken, and these tests will be obsolote soon with
// https://github.com/angular/angular/issues/6270
if (IS_DART) {
return;
}
describe('StyleCompiler', () => { describe('StyleCompiler', () => {
var xhr: SpyXHR; var xhr: SpyXHR;

View File

@ -14,7 +14,7 @@ import {
} from 'angular2/testing_internal'; } from 'angular2/testing_internal';
import {Promise, PromiseWrapper} from 'angular2/src/facade/async'; import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
import {Type, isPresent, isBlank, stringify, isString} from 'angular2/src/facade/lang'; import {Type, isPresent, isBlank, stringify, isString, IS_DART} from 'angular2/src/facade/lang';
import { import {
MapWrapper, MapWrapper,
SetWrapper, SetWrapper,
@ -58,6 +58,11 @@ var REFLECTION_CAPS_MODULE_REF =
moduleRef(`package:angular2/src/core/reflection/reflection_capabilities${MODULE_SUFFIX}`); moduleRef(`package:angular2/src/core/reflection/reflection_capabilities${MODULE_SUFFIX}`);
export function main() { export function main() {
// Dart's isolate support is broken, and these tests will be obsolote soon with
// https://github.com/angular/angular/issues/6270
if (IS_DART) {
return;
}
describe('TemplateCompiler', () => { describe('TemplateCompiler', () => {
var compiler: TemplateCompiler; var compiler: TemplateCompiler;
var runtimeMetadataResolver: RuntimeMetadataResolver; var runtimeMetadataResolver: RuntimeMetadataResolver;
@ -105,6 +110,22 @@ export function main() {
}); });
})); }));
it('should compile components at various nesting levels',
inject([AsyncTestCompleter], (async) => {
compile([CompWith2NestedComps, Comp1, Comp2])
.then((humanizedView) => {
expect(humanizedView['elements']).toEqual(['<comp-with-2nested>']);
expect(humanizedView['componentViews'][0]['elements'])
.toEqual(['<comp1>', '<comp2>']);
expect(humanizedView['componentViews'][0]['componentViews'][0]['elements'])
.toEqual(['<a>', '<comp2>']);
expect(humanizedView['componentViews'][0]['componentViews'][1]['elements'])
.toEqual(['<b>']);
async.done();
});
}));
it('should compile recursive components', inject([AsyncTestCompleter], (async) => { it('should compile recursive components', inject([AsyncTestCompleter], (async) => {
compile([TreeComp]) compile([TreeComp])
.then((humanizedView) => { .then((humanizedView) => {
@ -365,6 +386,29 @@ export class NonComponent {
} }
@Component({selector: 'comp2', moduleId: THIS_MODULE_ID})
@View({template: '<b></b>', encapsulation: ViewEncapsulation.None})
export class Comp2 {
}
@Component({selector: 'comp1', moduleId: THIS_MODULE_ID})
@View({
template: '<a></a>, <comp2></comp2>',
encapsulation: ViewEncapsulation.None,
directives: [Comp2]
})
export class Comp1 {
}
@Component({selector: 'comp-with-2nested', moduleId: THIS_MODULE_ID})
@View({
template: '<comp1></comp1>, <comp2></comp2>',
encapsulation: ViewEncapsulation.None,
directives: [Comp1, Comp2]
})
export class CompWith2NestedComps {
}
function testableTemplateModule(sourceModule: SourceModule, function testableTemplateModule(sourceModule: SourceModule,
normComp: CompileDirectiveMetadata): SourceModule { normComp: CompileDirectiveMetadata): SourceModule {
var testableSource = ` var testableSource = `

View File

@ -11,13 +11,14 @@ import {
AsyncTestCompleter, AsyncTestCompleter,
fakeAsync, fakeAsync,
tick, tick,
inject inject,
SpyObject
} from 'angular2/testing_internal'; } from 'angular2/testing_internal';
import {SpyChangeDetector} from './spies'; import {SpyChangeDetector} from './spies';
import {ApplicationRef_, PlatformRef_} from "angular2/src/core/application_ref"; import {ApplicationRef_, ApplicationRef, PlatformRef_} from "angular2/src/core/application_ref";
import {Injector, Provider} from "angular2/core"; import {Injector, Provider, APP_INITIALIZER} from "angular2/core";
import {ChangeDetectorRef_} from "angular2/src/core/change_detection/change_detector_ref"; import {ChangeDetectorRef_} from "angular2/src/core/change_detection/change_detector_ref";
import {PromiseWrapper} from "angular2/src/facade/async"; import {PromiseWrapper, PromiseCompleter, TimerWrapper} from "angular2/src/facade/async";
import {ListWrapper} from "angular2/src/facade/collection"; import {ListWrapper} from "angular2/src/facade/collection";
export function main() { export function main() {
@ -33,7 +34,14 @@ export function main() {
describe("PlatformRef", () => { describe("PlatformRef", () => {
describe("asyncApplication", () => { describe("asyncApplication", () => {
it("should merge synchronous and asynchronous providers", function expectProviders(injector: Injector, providers: Array<any>): void {
for (let i = 0; i < providers.length; i++) {
let provider = providers[i];
expect(injector.get(provider.token)).toBe(provider.useValue);
}
}
it("should merge syncronous and asyncronous providers",
inject([AsyncTestCompleter, Injector], (async, injector) => { inject([AsyncTestCompleter, Injector], (async, injector) => {
let ref = new PlatformRef_(injector, null); let ref = new PlatformRef_(injector, null);
let ASYNC_PROVIDERS = [new Provider(Foo, {useValue: new Foo()})]; let ASYNC_PROVIDERS = [new Provider(Foo, {useValue: new Foo()})];
@ -41,13 +49,98 @@ export function main() {
ref.asyncApplication((zone) => PromiseWrapper.resolve(ASYNC_PROVIDERS), SYNC_PROVIDERS) ref.asyncApplication((zone) => PromiseWrapper.resolve(ASYNC_PROVIDERS), SYNC_PROVIDERS)
.then((appRef) => { .then((appRef) => {
var providers = ListWrapper.concat(ASYNC_PROVIDERS, SYNC_PROVIDERS); var providers = ListWrapper.concat(ASYNC_PROVIDERS, SYNC_PROVIDERS);
for (var i = 0; i < providers.length; i++) { expectProviders(appRef.injector, providers);
var provider = providers[i];
expect(appRef.injector.get(provider.token)).toBe(provider.useValue);
}
async.done(); async.done();
}); });
})); }));
it("should allow function to be null",
inject([AsyncTestCompleter, Injector], (async, injector) => {
let ref = new PlatformRef_(injector, null);
let SYNC_PROVIDERS = [new Provider(Bar, {useValue: new Bar()})];
ref.asyncApplication(null, SYNC_PROVIDERS)
.then((appRef) => {
expectProviders(appRef.injector, SYNC_PROVIDERS);
async.done();
});
}));
function mockAsyncAppInitializer(completer, providers: Array<any> = null,
injector?: Injector) {
return () => {
if (providers != null) {
expectProviders(injector, providers);
}
TimerWrapper.setTimeout(() => completer.resolve(true), 1);
return completer.promise;
};
}
function createSpyPromiseCompleter(): SpyObject {
let completer = PromiseWrapper.completer();
let completerSpy = <any>new SpyObject();
// Note that in TypeScript we need to provide a value for the promise attribute
// whereas in dart we need to override the promise getter
completerSpy.promise = completer.promise;
completerSpy.spy("get:promise").andReturn(completer.promise);
completerSpy.spy("resolve").andCallFake(completer.resolve);
completerSpy.spy("reject").andCallFake(completer.reject);
return completerSpy;
}
it("should wait for asyncronous app initializers",
inject([AsyncTestCompleter, Injector], (async, injector) => {
let ref = new PlatformRef_(injector, null);
let completer = createSpyPromiseCompleter();
let SYNC_PROVIDERS = [
new Provider(Bar, {useValue: new Bar()}),
new Provider(APP_INITIALIZER,
{useValue: mockAsyncAppInitializer(completer), multi: true})
];
ref.asyncApplication(null, SYNC_PROVIDERS)
.then((appRef) => {
expectProviders(appRef.injector,
SYNC_PROVIDERS.slice(0, SYNC_PROVIDERS.length - 1));
expect(completer.spy("resolve")).toHaveBeenCalled();
async.done();
});
}));
it("should wait for async providers and then async app initializers",
inject([AsyncTestCompleter, Injector], (async, injector) => {
let ref = new PlatformRef_(injector, null);
let ASYNC_PROVIDERS = [new Provider(Foo, {useValue: new Foo()})];
let completer = createSpyPromiseCompleter();
let SYNC_PROVIDERS = [
new Provider(Bar, {useValue: new Bar()}),
new Provider(APP_INITIALIZER,
{
useFactory: (injector) => mockAsyncAppInitializer(
completer, ASYNC_PROVIDERS, injector),
multi: true,
deps: [Injector]
})
];
ref.asyncApplication((zone) => PromiseWrapper.resolve(ASYNC_PROVIDERS), SYNC_PROVIDERS)
.then((appRef) => {
expectProviders(appRef.injector,
SYNC_PROVIDERS.slice(0, SYNC_PROVIDERS.length - 1));
expect(completer.spy("resolve")).toHaveBeenCalled();
async.done();
});
}));
});
describe("application", () => {
it("should throw if an APP_INITIIALIZER returns a promise", inject([Injector], (injector) => {
let ref = new PlatformRef_(injector, null);
let appInitializer = new Provider(
APP_INITIALIZER, {useValue: () => PromiseWrapper.resolve([]), multi: true});
expect(() => ref.application([appInitializer]))
.toThrowError(
"Cannot use asyncronous app initializers with application. Use asyncApplication instead.");
}));
}); });
}); });
} }

View File

@ -438,6 +438,7 @@ var _availableEventDefinitions = [
'(event)="a[0]=\$event"', '(event)="a[0]=\$event"',
// '(event)="\$event=1"', // '(event)="\$event=1"',
'(event)="a=a+1; a=a+1;"', '(event)="a=a+1; a=a+1;"',
'(event)="true; false"',
'(event)="false"', '(event)="false"',
'(event)="true"', '(event)="true"',
'(event)="true ? a = a + 1 : a = a + 1"', '(event)="true ? a = a + 1 : a = a + 1"',

View File

@ -1267,7 +1267,7 @@ export function main() {
val.changeDetector.dehydrate(); val.changeDetector.dehydrate();
expect(() => {val.changeDetector.detectChanges()}) expect(() => {val.changeDetector.detectChanges()})
.toThrowErrorWith("Attempt to detect changes on a dehydrated detector"); .toThrowErrorWith("Attempt to use a dehydrated detector");
expect(val.dispatcher.log).toEqual(['propName=Bob']); expect(val.dispatcher.log).toEqual(['propName=Bob']);
}); });
}); });
@ -1358,6 +1358,10 @@ export function main() {
val = _createChangeDetector('(event)="true"', d, null); val = _createChangeDetector('(event)="true"', d, null);
res = val.changeDetector.handleEvent("event", 0, event); res = val.changeDetector.handleEvent("event", 0, event);
expect(res).toBe(true); expect(res).toBe(true);
val = _createChangeDetector('(event)="true; false"', d, null);
res = val.changeDetector.handleEvent("event", 0, event);
expect(res).toBe(false);
}); });
it('should support short-circuiting', () => { it('should support short-circuiting', () => {

View File

@ -39,6 +39,12 @@ class SomeDirectiveWithOutputs {
c; c;
} }
@Directive({selector: 'someDirective', outputs: ['a']})
class SomeDirectiveWithDuplicateOutputs {
@Output() a;
}
@Directive({selector: 'someDirective', properties: ['a']}) @Directive({selector: 'someDirective', properties: ['a']})
class SomeDirectiveWithProperties { class SomeDirectiveWithProperties {
} }
@ -153,6 +159,12 @@ export function main() {
var directiveMetadata = resolver.resolve(SomeDirectiveWithGetterOutputs); var directiveMetadata = resolver.resolve(SomeDirectiveWithGetterOutputs);
expect(directiveMetadata.outputs).toEqual(['a: renamed']); expect(directiveMetadata.outputs).toEqual(['a: renamed']);
}); });
it('should throw if duplicate outputs', () => {
expect(() => { resolver.resolve(SomeDirectiveWithDuplicateOutputs); })
.toThrowError(
`Output event 'a' defined multiple times in 'SomeDirectiveWithDuplicateOutputs'`);
});
}); });
describe('host', () => { describe('host', () => {

View File

@ -877,13 +877,22 @@ function declareTests() {
var listener = tc.inject(DirectiveListeningEvent); var listener = tc.inject(DirectiveListeningEvent);
expect(listener.msg).toEqual(''); expect(listener.msg).toEqual('');
var eventCount = 0;
ObservableWrapper.subscribe(emitter.event, (_) => { ObservableWrapper.subscribe(emitter.event, (_) => {
expect(listener.msg).toEqual('fired !'); eventCount++;
async.done(); if (eventCount === 1) {
expect(listener.msg).toEqual('fired !');
fixture.destroy();
emitter.fireEvent('fired again !');
} else {
expect(listener.msg).toEqual('fired !');
async.done();
}
}); });
emitter.fireEvent('fired !'); emitter.fireEvent('fired !');
}); });
})); }));
@ -961,6 +970,11 @@ function declareTests() {
.toEqual( .toEqual(
['domEvent', 'body_domEvent', 'document_domEvent', 'window_domEvent']); ['domEvent', 'body_domEvent', 'document_domEvent', 'window_domEvent']);
fixture.destroy();
listener.eventTypes = [];
dispatchEvent(tc.nativeElement, 'domEvent');
expect(listener.eventTypes).toEqual([]);
async.done(); async.done();
}); });
})); }));

View File

@ -13,77 +13,47 @@ import 'package:angular2/src/platform/dom/dom_adapter.dart';
import 'package:angular2/testing_internal.dart'; import 'package:angular2/testing_internal.dart';
@proxy @proxy
class SpyDependencyProvider extends SpyObject implements DependencyProvider { class SpyDependencyProvider extends SpyObject implements DependencyProvider {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyChangeDetector extends SpyObject implements ChangeDetector { class SpyChangeDetector extends SpyObject implements ChangeDetector {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyChangeDispatcher extends SpyObject implements ChangeDispatcher { class SpyChangeDispatcher extends SpyObject implements ChangeDispatcher {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyIterableDifferFactory extends SpyObject class SpyIterableDifferFactory extends SpyObject
implements IterableDifferFactory { implements IterableDifferFactory {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyInjector extends SpyObject implements Injector { class SpyInjector extends SpyObject implements Injector {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyDirectiveResolver extends SpyObject implements DirectiveResolver { class SpyDirectiveResolver extends SpyObject implements DirectiveResolver {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyView extends SpyObject implements AppView { class SpyView extends SpyObject implements AppView {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyProtoView extends SpyObject implements AppProtoView { class SpyProtoView extends SpyObject implements AppProtoView {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyHostViewFactory extends SpyObject implements HostViewFactory { class SpyHostViewFactory extends SpyObject implements HostViewFactory {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyElementRef extends SpyObject implements ElementRef { class SpyElementRef extends SpyObject implements ElementRef {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyAppViewManager extends SpyObject implements AppViewManager_ { class SpyAppViewManager extends SpyObject implements AppViewManager_ {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyRenderer extends SpyObject implements Renderer { class SpyRenderer extends SpyObject implements Renderer {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyRootRenderer extends SpyObject implements RootRenderer { class SpyRootRenderer extends SpyObject implements RootRenderer {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyAppViewListener extends SpyObject implements AppViewListener { class SpyAppViewListener extends SpyObject implements AppViewListener {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyDomAdapter extends SpyObject implements DomAdapter { class SpyDomAdapter extends SpyObject implements DomAdapter {}
noSuchMethod(m) => super.noSuchMethod(m);
}

View File

@ -43,12 +43,13 @@ class MockNgZone extends NgZone {
export function main() { export function main() {
describe('Testability', () => { describe('Testability', () => {
var testability, execute, ngZone; var testability, execute, execute2, ngZone;
beforeEach(() => { beforeEach(() => {
ngZone = new MockNgZone(); ngZone = new MockNgZone();
testability = new Testability(ngZone); testability = new Testability(ngZone);
execute = new SpyObject().spy('execute'); execute = new SpyObject().spy('execute');
execute2 = new SpyObject().spy('execute');
}); });
describe('Pending count logic', () => { describe('Pending count logic', () => {
@ -109,6 +110,35 @@ export function main() {
expect(execute).not.toHaveBeenCalled(); expect(execute).not.toHaveBeenCalled();
}); });
it('should fire whenstable callbacks with didWork if pending count is 0',
inject([AsyncTestCompleter], (async) => {
testability.whenStable(execute);
microTask(() => {
expect(execute).toHaveBeenCalledWith(false);
async.done();
});
}));
it('should fire whenstable callbacks with didWork when pending drops to 0',
inject([AsyncTestCompleter], (async) => {
testability.increasePendingRequestCount();
testability.whenStable(execute);
microTask(() => {
testability.decreasePendingRequestCount();
microTask(() => {
expect(execute).toHaveBeenCalledWith(true);
testability.whenStable(execute2);
microTask(() => {
expect(execute2).toHaveBeenCalledWith(false);
async.done();
});
});
});
}));
}); });
describe('NgZone callback logic', () => { describe('NgZone callback logic', () => {
@ -208,6 +238,43 @@ export function main() {
}); });
}); });
})); }));
it('should fire whenstable callback with didWork if event is already finished',
inject([AsyncTestCompleter], (async) => {
ngZone.start();
ngZone.finish();
testability.whenStable(execute);
microTask(() => {
expect(execute).toHaveBeenCalledWith(true);
testability.whenStable(execute2);
microTask(() => {
expect(execute2).toHaveBeenCalledWith(false);
async.done();
});
});
}));
it('should fire whenstable callback with didwork when event finishes',
inject([AsyncTestCompleter], (async) => {
ngZone.start();
testability.whenStable(execute);
microTask(() => {
ngZone.finish();
microTask(() => {
expect(execute).toHaveBeenCalledWith(true);
testability.whenStable(execute2);
microTask(() => {
expect(execute2).toHaveBeenCalledWith(false);
async.done();
});
});
});
}));
}); });
}); });
} }

View File

@ -8,7 +8,6 @@ import 'dart:js';
@proxy @proxy
class SpyApplicationRef extends SpyObject implements ApplicationRef { class SpyApplicationRef extends SpyObject implements ApplicationRef {
tick() {} tick() {}
noSuchMethod(m) => super.noSuchMethod(m);
} }
@proxy @proxy
@ -16,11 +15,9 @@ class SpyComponentRef extends SpyObject implements ComponentRef_ {
Injector injector; Injector injector;
SpyComponentRef() { SpyComponentRef() {
this.injector = this.injector = Injector
Injector.resolveAndCreate([bind(ApplicationRef).toClass(SpyApplicationRef)]); .resolveAndCreate([bind(ApplicationRef).toClass(SpyApplicationRef)]);
} }
noSuchMethod(m) => super.noSuchMethod(m);
} }
void callNgProfilerTimeChangeDetection([config]) { void callNgProfilerTimeChangeDetection([config]) {

View File

@ -1224,7 +1224,6 @@ var NG_CORE = [
'SimpleChange.isFirstChange()', 'SimpleChange.isFirstChange()',
'TemplateRef', 'TemplateRef',
'TemplateRef.elementRef', 'TemplateRef.elementRef',
'TemplateRef.elementRef=',
/* /*
Abstract method Abstract method
'TemplateRef.hasLocal()', 'TemplateRef.hasLocal()',

View File

@ -4,21 +4,14 @@ import 'package:angular2/router.dart';
import 'package:angular2/testing_internal.dart'; import 'package:angular2/testing_internal.dart';
@proxy @proxy
class SpyLocation extends SpyObject implements Location { class SpyLocation extends SpyObject implements Location {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyRouter extends SpyObject implements Router { class SpyRouter extends SpyObject implements Router {}
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy @proxy
class SpyRouterOutlet extends SpyObject implements RouterOutlet { class SpyRouterOutlet extends SpyObject implements RouterOutlet {}
noSuchMethod(m) => super.noSuchMethod(m);
}
class SpyPlatformLocation extends SpyObject implements PlatformLocation { class SpyPlatformLocation extends SpyObject implements PlatformLocation {
String pathname; String pathname;
noSuchMethod(m) => super.noSuchMethod(m);
} }

View File

@ -0,0 +1 @@
<span>from external template</span>

View File

@ -24,7 +24,6 @@ class TestObj {
class SpyTestObj extends SpyObject { class SpyTestObj extends SpyObject {
constructor() { super(TestObj); } constructor() { super(TestObj); }
noSuchMethod(m) { return super.noSuchMethod(m) }
} }

View File

@ -94,6 +94,15 @@ class TestViewProvidersComp {
constructor(private fancyService: FancyService) {} constructor(private fancyService: FancyService) {}
} }
@Component({selector: 'external-template-comp'})
@View({templateUrl: '/base/modules/angular2/test/testing/static_assets/test.html'})
class ExternalTemplateComp {
}
@Component({selector: 'bad-template-comp'})
@View({templateUrl: 'non-existant.html'})
class BadTemplateUrl {
}
export function main() { export function main() {
describe('angular2 jasmine matchers', () => { describe('angular2 jasmine matchers', () => {
@ -273,11 +282,12 @@ export function main() {
restoreJasmineIt(); restoreJasmineIt();
}); });
it('should fail when an asynchronous error is thrown', (done) => { // TODO(juliemr): reenable this test when we are using a test zone and can capture this error.
xit('should fail when an asynchronous error is thrown', (done) => {
var itPromise = patchJasmineIt(); var itPromise = patchJasmineIt();
it('throws an async error', it('throws an async error',
inject([], () => { setTimeout(() => { throw new Error('bar'); }, 0); })); injectAsync([], () => { setTimeout(() => { throw new Error('bar'); }, 0); }));
itPromise.then(() => { done.fail('Expected test to fail, but it did not'); }, (err) => { itPromise.then(() => { done.fail('Expected test to fail, but it did not'); }, (err) => {
expect(err.message).toEqual('bar'); expect(err.message).toEqual('bar');
@ -304,6 +314,19 @@ export function main() {
restoreJasmineIt(); restoreJasmineIt();
}); });
it('should fail when an XHR fails', (done) => {
var itPromise = patchJasmineIt();
it('should fail with an error from a promise',
injectAsync([TestComponentBuilder], (tcb) => { return tcb.createAsync(BadTemplateUrl); }));
itPromise.then(() => { done.fail('Expected test to fail, but it did not'); }, (err) => {
expect(err).toEqual('Failed to load non-existant.html');
done();
});
restoreJasmineIt();
});
describe('using beforeEachProviders', () => { describe('using beforeEachProviders', () => {
beforeEachProviders(() => [bind(FancyService).toValue(new FancyService())]); beforeEachProviders(() => [bind(FancyService).toValue(new FancyService())]);
@ -428,5 +451,16 @@ export function main() {
.toHaveText('injected value: mocked out value'); .toHaveText('injected value: mocked out value');
}); });
})); }));
it('should allow an external templateUrl',
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb.createAsync(ExternalTemplateComp)
.then((componentFixture) => {
componentFixture.detectChanges();
expect(componentFixture.debugElement.nativeElement)
.toHaveText('from external template\n');
});
}));
}); });
} }

View File

@ -16,7 +16,6 @@ import {getComponentInfo, parseFields} from 'angular2/src/upgrade/metadata';
import {DOM} from 'angular2/src/platform/dom/dom_adapter'; import {DOM} from 'angular2/src/platform/dom/dom_adapter';
export function main() { export function main() {
if (!DOM.supportsDOMEvents()) return;
describe('upgrade metadata', () => { describe('upgrade metadata', () => {
it('should extract component selector', () => { it('should extract component selector', () => {
expect(getComponentInfo(ElementNameComponent).selector).toEqual('elementNameDashed'); expect(getComponentInfo(ElementNameComponent).selector).toEqual('elementNameDashed');

View File

@ -17,7 +17,6 @@ import {UpgradeAdapter} from 'angular2/upgrade';
import * as angular from 'angular2/src/upgrade/angular_js'; import * as angular from 'angular2/src/upgrade/angular_js';
export function main() { export function main() {
if (!DOM.supportsDOMEvents()) return;
describe('adapter: ng1 to ng2', () => { describe('adapter: ng1 to ng2', () => {
it('should have angular 1 loaded', () => expect(angular.version.major).toBe(1)); it('should have angular 1 loaded', () => expect(angular.version.major).toBe(1));

View File

@ -5,15 +5,17 @@ import "dart:async";
import "package:angular2/testing_internal.dart" import "package:angular2/testing_internal.dart"
show show
AsyncTestCompleter, AsyncTestCompleter,
inject, SpyObject,
describe,
it,
iit,
expect,
beforeEach, beforeEach,
beforeEachProviders, beforeEachProviders,
SpyObject, describe,
proxy; expect,
iit,
inject,
it,
proxy,
testSetup;
import 'package:angular2/src/platform/server/html_adapter.dart';
import "package:angular2/src/web_workers/debug_tools/multi_client_server_message_bus.dart"; import "package:angular2/src/web_workers/debug_tools/multi_client_server_message_bus.dart";
import "package:angular2/src/web_workers/shared/messaging_api.dart"; import "package:angular2/src/web_workers/shared/messaging_api.dart";
import "./message_bus_common.dart"; import "./message_bus_common.dart";
@ -22,6 +24,9 @@ import "dart:convert" show JSON;
import 'dart:math'; import 'dart:math';
main() { main() {
Html5LibDomAdapter.makeCurrent();
testSetup();
List<String> messageHistory = new List<String>(); List<String> messageHistory = new List<String>();
List<int> resultMarkers = new List<int>(); List<int> resultMarkers = new List<int>();
describe("MultiClientServerMessageBusSink", () { describe("MultiClientServerMessageBusSink", () {

View File

@ -5,20 +5,25 @@ import "dart:async";
import "package:angular2/testing_internal.dart" import "package:angular2/testing_internal.dart"
show show
AsyncTestCompleter, AsyncTestCompleter,
inject, SpyObject,
describe,
it,
expect,
beforeEach, beforeEach,
beforeEachProviders, beforeEachProviders,
SpyObject, describe,
proxy; expect,
inject,
it,
proxy,
testSetup;
import 'package:angular2/src/platform/server/html_adapter.dart';
import "package:angular2/src/web_workers/debug_tools/single_client_server_message_bus.dart"; import "package:angular2/src/web_workers/debug_tools/single_client_server_message_bus.dart";
import "./message_bus_common.dart"; import "./message_bus_common.dart";
import "./spy_web_socket.dart"; import "./spy_web_socket.dart";
import "dart:convert" show JSON; import "dart:convert" show JSON;
main() { main() {
Html5LibDomAdapter.makeCurrent();
testSetup();
var MESSAGE = const {'test': 10}; var MESSAGE = const {'test': 10};
const CHANNEL = "TEST_CHANNEL"; const CHANNEL = "TEST_CHANNEL";
describe("SingleClientServerMessageBusSink", () { describe("SingleClientServerMessageBusSink", () {

View File

@ -60,15 +60,9 @@ main() {
@proxy @proxy
class SpyMessageEvent extends SpyObject implements MessageEvent { class SpyMessageEvent extends SpyObject implements MessageEvent {
SpyMessageEvent() : super(SpyMessageEvent); SpyMessageEvent() : super(SpyMessageEvent);
noSuchMethod(m) {
return super.noSuchMethod(m);
}
} }
@proxy @proxy
class SpyWebSocket extends SpyObject implements WebSocket { class SpyWebSocket extends SpyObject implements WebSocket {
SpyWebSocket() : super(SpyWebSocket); SpyWebSocket() : super(SpyWebSocket);
noSuchMethod(m) {
return super.noSuchMethod(m);
}
} }

View File

@ -3,11 +3,13 @@ import {
inject, inject,
describe, describe,
it, it,
iit,
expect, expect,
beforeEach, beforeEach,
beforeEachProviders, beforeEachProviders,
SpyObject, SpyObject,
proxy proxy,
browserDetection
} from 'angular2/testing_internal'; } from 'angular2/testing_internal';
import {createPairedMessageBuses} from '../shared/web_worker_test_util'; import {createPairedMessageBuses} from '../shared/web_worker_test_util';
import {Serializer, PRIMITIVE} from 'angular2/src/web_workers/shared/serializer'; import {Serializer, PRIMITIVE} from 'angular2/src/web_workers/shared/serializer';
@ -28,7 +30,7 @@ export function main() {
const RESULT = 20; const RESULT = 20;
const ID = "methodId"; const ID = "methodId";
beforeEachProviders(() => [provide(ON_WEB_WORKER, {useValue: true}), RenderStore]); beforeEachProviders(() => [Serializer, provide(ON_WEB_WORKER, {useValue: true}), RenderStore]);
describe("UIMessageBroker", () => { describe("UIMessageBroker", () => {
var messageBuses; var messageBuses;
@ -49,19 +51,23 @@ export function main() {
{'method': TEST_METHOD, 'args': [PASSED_ARG_1, PASSED_ARG_2]}); {'method': TEST_METHOD, 'args': [PASSED_ARG_1, PASSED_ARG_2]});
})); }));
it("should return promises to the worker", inject([Serializer], (serializer) => { // TODO(pkozlowski): this fails only in Edge with
var broker = new ServiceMessageBroker_(messageBuses.ui, serializer, CHANNEL); // "No provider for RenderStore! (Serializer -> RenderStore)"
broker.registerMethod(TEST_METHOD, [PRIMITIVE], (arg1) => { if (!browserDetection.isEdge) {
expect(arg1).toEqual(PASSED_ARG_1); it("should return promises to the worker", inject([Serializer], (serializer) => {
return PromiseWrapper.wrap(() => { return RESULT; }); var broker = new ServiceMessageBroker_(messageBuses.ui, serializer, CHANNEL);
}); broker.registerMethod(TEST_METHOD, [PRIMITIVE], (arg1) => {
ObservableWrapper.callEmit(messageBuses.worker.to(CHANNEL), expect(arg1).toEqual(PASSED_ARG_1);
{'method': TEST_METHOD, 'id': ID, 'args': [PASSED_ARG_1]}); return PromiseWrapper.wrap(() => { return RESULT; });
ObservableWrapper.subscribe(messageBuses.worker.from(CHANNEL), (data: any) => { });
expect(data.type).toEqual("result"); ObservableWrapper.callEmit(messageBuses.worker.to(CHANNEL),
expect(data.id).toEqual(ID); {'method': TEST_METHOD, 'id': ID, 'args': [PASSED_ARG_1]});
expect(data.value).toEqual(RESULT); ObservableWrapper.subscribe(messageBuses.worker.from(CHANNEL), (data: any) => {
}); expect(data.type).toEqual("result");
})); expect(data.id).toEqual(ID);
expect(data.value).toEqual(RESULT);
});
}));
}
}); });
} }

View File

@ -44,7 +44,10 @@ import {
ServiceMessageBrokerFactory_ ServiceMessageBrokerFactory_
} from 'angular2/src/web_workers/shared/service_message_broker'; } from 'angular2/src/web_workers/shared/service_message_broker';
import {ChangeDetectorGenConfig} from 'angular2/src/core/change_detection/change_detection'; import {ChangeDetectorGenConfig} from 'angular2/src/core/change_detection/change_detection';
import {
TEST_BROWSER_PLATFORM_PROVIDERS,
TEST_BROWSER_APPLICATION_PROVIDERS
} from 'angular2/platform/testing/browser';
export function main() { export function main() {
function createWebWorkerBrokerFactory( function createWebWorkerBrokerFactory(
@ -83,13 +86,16 @@ export function main() {
beforeEachProviders(() => { beforeEachProviders(() => {
uiRenderStore = new RenderStore(); uiRenderStore = new RenderStore();
var testInjector = new TestInjector(); var testUiInjector = new TestInjector();
testInjector.addProviders([ testUiInjector.platformProviders = TEST_BROWSER_PLATFORM_PROVIDERS;
testUiInjector.applicationProviders = TEST_BROWSER_APPLICATION_PROVIDERS;
testUiInjector.addProviders([
Serializer,
provide(RenderStore, {useValue: uiRenderStore}), provide(RenderStore, {useValue: uiRenderStore}),
provide(DomRootRenderer, {useClass: DomRootRenderer_}), provide(DomRootRenderer, {useClass: DomRootRenderer_}),
provide(RootRenderer, {useExisting: DomRootRenderer}) provide(RootRenderer, {useExisting: DomRootRenderer})
]); ]);
uiInjector = testInjector.createInjector(); uiInjector = testUiInjector.createInjector();
var uiSerializer = uiInjector.get(Serializer); var uiSerializer = uiInjector.get(Serializer);
var domRootRenderer = uiInjector.get(DomRootRenderer); var domRootRenderer = uiInjector.get(DomRootRenderer);
workerRenderStore = new RenderStore(); workerRenderStore = new RenderStore();

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