Compare commits

...

1775 Commits

Author SHA1 Message Date
80fe41a88e release: cut v2.4.9 2017-03-01 23:11:26 -08:00
af652a7c8b docs: add release notes for 2.4.9 2017-03-01 23:11:08 -08:00
de36f8a3b9 revert: fix(router): do not finish bootstrap until all the routes are resolved (#14327)
This reverts commit 541de26f7e because it introduced a regression.

Closes #14681, #14588
2017-02-27 14:37:33 -08:00
b658fa9ea0 fix(http): Make ResponseOptionsArgs an interface
closes #13708
2017-02-20 17:34:30 -08:00
2a123463ac fix(router): improve robustness (#14602)
sync a 4.x change from https://github.com/angular/angular/pull/14155
2017-02-20 16:59:28 -08:00
4f93ac8762 release: cut v2.4.8 2017-02-18 13:55:23 -08:00
37ec5b9c1a docs: add changelog for 2.4.8 2017-02-18 13:54:34 -08:00
612950bdb2 test: pin down @types/* dependencies in typings test (#14569)
This is needed because the latest versions are no longer compatible with typescript 1.8 which results in build errors:
https://travis-ci.org/angular/angular/jobs/202752040#L3863
2017-02-17 14:35:56 -08:00
3804ad1d23 revert: build: first pass of de-duplicating tsconfig.json content (#14369)
This reverts commit 1c112ae66e.

First failed build (one commit after the change being reverted): https://travis-ci.org/angular/angular/jobs/202414385#L2511
2017-02-17 12:15:49 -08:00
1b1f228525 revert: build: update jasmine to 2.4 (#14362)
This reverts commit d6a8b0b686.

Jasmine 2.4 requires new typings, which require typescript 2.

See CI failure https://travis-ci.org/angular/angular/jobs/202412220#L3859
2017-02-17 11:57:17 -08:00
19e9094275 docs(router): fix broken link (#14431)
Closes #14430
2017-02-16 15:13:43 -08:00
8ff3ab0e6d docs(router): fix guards API docs (#14528) 2017-02-16 15:13:30 -08:00
9e8d740a96 ci: fix getLatestLabel (#14535) 2017-02-16 15:12:32 -08:00
3a3a100b27 build: update .pullapprove (#14506)
* build: update .pullapprove

Add tbosch/vicb/chuckjaz to more projects.

* Update .pullapprove.yml
2017-02-16 15:02:42 -08:00
f0575e014c fix(compiler): REVERT allow absolute style urls (#14365)
This reverts commit 6b9aa2ca3d.
2017-02-16 14:51:01 -08:00
ea7737ee11 fix(forms): getRawValue should correctly work with nested FormGroups/Arrays (#12964)
Closed #12963

PR Close #12964
2017-02-16 14:50:49 -08:00
fadaf1e01a fix(platform-browser): should only add styles with native encapsulation in shadow DOM (#14313)
Closes #7887

PR Close #14313
2017-02-16 14:50:11 -08:00
c716532ff2 test(forms): test undefined as argument to forms (#13720)
PR Close #13720
2017-02-16 13:49:33 -08:00
1c112ae66e build: first pass of de-duplicating tsconfig.json content (#14369)
PR Close #14369
2017-02-16 13:47:10 -08:00
193a0ae4a0 fix(compiler): allow absolute style urls (#14365)
Closes #4974

PR Close #14365
2017-02-16 13:46:42 -08:00
9ceb5d1afe fix(http): REVERT: remove dots from jsonp callback name (#13219)
This reverts commit 9e5617e41e.
2017-02-16 13:45:48 -08:00
d6a8b0b686 build: update jasmine to 2.4 (#14362)
PR Close #14362
2017-02-16 13:44:47 -08:00
3e216dd4ad ci: find latest tag when deeper than the git clone depth (#14231)
Since we have a shallow clone of the repository, it might be the case that the
latest tag (which we need for publishing the build artifacts) might not be in
the current history.

This commit incrementally deepens the clone until it finds a tag (or reaches a
max depth).

PR Close #14231
2017-02-16 13:43:15 -08:00
7b0aba4655 ci: bump node version to 6.9.5 and npm to 3.10.7
this is required by @angular/cli
2017-02-16 13:42:25 -08:00
7c87c52c38 fix(upgrade): pass correct values to ngOnChanges for interpolation bindings (#14400)
Previously, the `previousValue` and `currentValue` arguments passed to the
`SimpleChange` constructor were swapped for interpolation bindings.

This commit also refactors the code, so that interpolation bindings and property
bindings share the same implementation, and fixes some broken tests (that hide
failures by allowing the `$exceptionHandler` to swallow thrown exceptions).

This is the same as #14301, but for the 2.4.x branch.
2017-02-10 12:53:26 -08:00
541de26f7e fix(router): do not finish bootstrap until all the routes are resolved (#14327)
Fixes #12162
2017-02-09 11:59:08 -08:00
74cb575219 fix(upgrade): correctly project content on downgraded components with structural directives (#14274)
Previously, downgraded component adapters were compiling and projecting the
contents of the template element instead of the link-element. This didn't make
any difference is most cases (as the elements are the same), but broke with
structural directives (e.g. `ngRepeat`), which compile the orginal (template)
element once and then create and link clones of it.

This commit fixes it by always compiling and projecting the contents of the
correct (link) element.

Fixes #14260
2017-02-09 10:07:11 -08:00
e90661aaee docs(changelog): add changelog for 2.4.7 2017-02-08 20:28:11 -08:00
73034c75bd chore(release): cut the 2.4.7 release 2017-02-08 20:26:10 -08:00
059085b943 docs(compiler): incorrect method reference (#14314)
PR Close #14314
2017-02-08 20:23:36 -08:00
8ab89153e0 docs(core): fix typo (#14299)
Replace `than` with `then`.

PR Close #14299
2017-02-08 20:23:36 -08:00
NFM
82923d8314 docs(router): fix typos (#14213)
PR Close #14213
2017-02-08 20:23:36 -08:00
6921b3d21d docs(zone): fix whitespace around backtick code
If there is no leading empty line then the markdown renderers get confused.
2017-02-08 20:23:36 -08:00
c0ef8b25a6 ci: add petebacondarwin to the angular.io pullapprove group (#14268)
PR Close #14268
2017-02-08 20:08:20 -08:00
e845f3b226 ci: add 'public-api' pullapprove group (#14268) 2017-02-08 20:08:20 -08:00
9779f397b7 test(compiler): add integration like tests to compiler unit tests (#14157)
Closes PR #14157

PR Close #14157
2017-02-08 20:08:20 -08:00
5bb47db887 fix(upgrade): allow non-element selectors for downgraded components (#14291)
This affects the dynamic version of `upgrade` and makes it more consistent with
the static version, while removing an artificial limitation.

(This commit backports the fix from 9aafdc7 to 2.4.x.)
2017-02-07 10:02:11 -08:00
343ee8a3a2 docs(changelog): add changelog for 2.4.6 2017-02-02 20:04:17 -08:00
223b5eb367 chore(release): cut the 2.4.6 release 2017-02-02 19:18:08 -08:00
7e639aac15 fix: ngModel should use rxjs/symbol/observable to detect observable (#14236)
PR closes #14236
2017-02-02 19:18:08 -08:00
83dafd3054 ci: increase git fetch depth to 150 2017-02-02 19:18:08 -08:00
e641636624 fix(common): DatePipe parses input string if it's not a valid date in browser (#13895)
Closes #12334
Closes #13874

PR Close #13895
2017-02-02 19:18:08 -08:00
c409860a9f refactor(common): remove isDate from facade (#13895) 2017-02-02 19:18:07 -08:00
0101aa31d6 ci: fix .pullapprove.yaml'sfile conditions (#14214)
According to [the docs](http://docs.pullapprove.com/groups/conditions/), the correct keywords are `include`/`exclude`, without the trailing `s`.
2017-02-02 19:18:07 -08:00
a5b4af0fdd fix(language-service): do not crash when Angular cannot be located (#14123)
Fixes #14122

PR Close #14123
2017-02-02 19:18:07 -08:00
d9420311ca docs(forms): fix FormArray description (#14094)
Closes #14075

PR Close #14094
2017-02-02 18:50:40 -08:00
774e1db87c fix(forms): Verify functions passed into async validators returns Observable or Promise (#14053) 2017-02-02 18:50:40 -08:00
109f0d16ef fix(common): introduce isObservable method (#14067)
Closes #8848

PR Close #14067
2017-02-02 18:50:40 -08:00
71567d1eee fix(common): add PopStateEvent interface (#13400)
Closes #13378

PR Close #13400
2017-02-02 18:50:40 -08:00
bb71acc172 build: fix red travis: fetch more github history (#14193) 2017-02-02 16:02:55 -08:00
e98d6f0912 ci: fix compiler-cli paths (#14177) 2017-02-02 16:02:55 -08:00
1dbebb184f ci: fix pullapprove groups and conditions (#14167)
- restrict root to be just root
- add fallback users to all groups
- fix indentation
- change order of users so that primary reviewers are first, follow by alpha-sorted secondaries, followed by fallback reviewers
2017-02-02 16:02:55 -08:00
8882b86b54 fix(common) add interface PipeTransform to Async pipe (#14049)
PR Close #14049
2017-02-02 16:02:54 -08:00
0965636735 fix(router): fix CanActivateChild guard provided in a lazy loaded module (#13989)
Closes #12275

PR Close #13989
2017-02-02 16:02:54 -08:00
4d2901d480 fix(router): fix navigation from the root component ngOnInit hook (#13932)
Closes #13795

PR Close #13932
2017-02-02 16:02:54 -08:00
a047124e1a fix(router): fix CanActivate redirect to the root on initial load (#13929)
Closes #13530

PR Close #13929
2017-02-02 16:02:54 -08:00
09e2d20e22 fix(forms): select shows blank line when nothing is selected in IE/Edge (#13903)
Closes #10010

PR Close #13903
2017-02-02 16:02:54 -08:00
e3bdf82c0d docs(developer): add description of npm-run to run locally installed npm scripts (#13765)
PR Close #13765
2017-02-02 16:02:54 -08:00
0614289608 fix(platform-browser): remove style nodes on destroy (#13744)
Closes #11746

PR Close #13744
2017-02-02 16:02:53 -08:00
7c344a4e49 refactor(platform-browser): polishing (#13744) 2017-02-02 16:02:53 -08:00
250dbc4bc8 fix(core): add bootstrapped modules into platform modules list (#13740)
Closes #12015

PR Close #13740
2017-02-02 16:02:53 -08:00
70bbdf55da fix(testing): async/fakeAsync/inject/withModule helpers should pass through context to callback functions (#13718)
Make sure that context (`this`) that is passed to functions generated by test helpers is passed through to the callback functions. Enables usage of Jasmine's variable sharing system to prevent accidental memory leaks during test runs.
2017-02-02 16:02:53 -08:00
41b8d95fa7 fix(core): ViewContainerRef.indexOf doesn't throw error when empty (#13220)
PR Close #13220
2017-02-02 16:02:53 -08:00
1eece5046d fix(http): remove dots from jsonp callback name (#13219)
PR Close #13219
2017-02-02 16:02:52 -08:00
1ef3eeecbd docs: update COMITTER.md with info about pullapprove.com 2017-02-02 16:02:52 -08:00
94500e0fad ci: configure pullapprove to cover the whole repository 2017-02-02 16:02:52 -08:00
gc
dd53606f69 docs(public_api): change description (#13583)
* doc(public_api): change description

Benchpress has been moved to angular/angular in modules/@angular/benchpress

* docs(public_api): change description

Here means 'other projects',like angular-cli, Angular Material. And as we know, benchpress project has been moved to angular/angular in modules/@angular/benchpress. It should not be 'other projects'.
2017-02-02 16:02:52 -08:00
6c8b5dda87 style(docs): update copyright years (#13736) 2017-02-02 16:02:52 -08:00
458ccc1aff refactor(core): simplify ReflectiveInjector by removing code for Dart implementation (#14126)
ReflectiveInjector previously used two strategies for resolving dependencies. These
were to support the Dart implementation, but are no longer needed. A result of this
PR is there is no longer a 20 dependency limit and the generated code is smaller.

PR Close #14126
2017-02-02 16:01:04 -08:00
07cfd8c432 docs: remove obsolete bundles/overview.md file (#14132) 2017-02-02 16:01:03 -08:00
23bd0fbfc1 docs(http): vanilla links do not need link tags (#14097) 2017-02-02 16:32:23 -06:00
3d1e536143 docs(router): remove invalid jsdoc tags (#14097)
The `@selector` tags are not valid.
Dgeni should be able to extract this information
from the directive annotation metadata.
2017-02-02 16:31:49 -06:00
c827097610 ci: add pullapprove config for angular.io 2017-02-02 16:31:49 -06:00
8d4aa82c04 fix(i18n): parse ICU messages while normalizing templates (#14153)
Fixes:
- Inject the i18n specific HtmlParser into the directive normalizer,
- Parse ICU messages while normalizing templates,
- Normalize (visit) the content of ICU messages.

🎄🎁🎅
2017-01-31 21:00:32 -08:00
14e97516cb refactor(abstract): Use abstract keyword where possible to decrease file size. (#14112)
PR Close: #14112
2017-01-27 12:52:12 -08:00
bc47a8cc74 refactor(compiler): add ability to get the context around a ParseLocation (#14113) 2017-01-27 12:55:54 -06:00
32cc6759ef fix(common): DatePipe doesn't throw for NaN (#14117)
Fixes #14103

PR Close #14117
2017-01-27 12:55:28 -06:00
d5f1419afe refactor(size): Use abstract keyword where possible to decrease file size. (#14112) 2017-01-27 12:55:20 -06:00
117fa79c7c fix(upgrade): detect async downgrade component changes (#14039)
This commit effectively reverts 7e0f02f but for `upgrade/static`
as it was an invalid fix for #6385, that created a more significant
bug, which was that changes were not always being detected.

Angular 1 digests should be run inside the ngZone to ensure
that async changes are detected.

We don't know how to fix #6385 without breaking change detection
at this stage. That issue is triggered by async operations, such as
`setTimeout`, being triggered inside scope watcher functions.

One could argue that watcher functions should be pure and not do
work such as triggering async operations. It is possible that the
original use case could be supported by moving the debounce
logic into the watch listener function, which is only called if the
watched value actually changes.

See #13812

PR Close #14039
2017-01-27 12:53:48 -06:00
777ba46837 refactor(compiler): improve error messages in aot compiler (#14017)
Previously aot compiler prints stack traces when it fails to resolve.
New behavior: aot compiler outputs the error message.
Example: https://gist.github.com/bowenni/a7fe81d916e8cd4a06b0e133436f40fb

PR Close #14017
2017-01-27 12:53:43 -06:00
f3d55068a8 fix(compiler): allow empty translations for attributes (#14085)
fixes #13897
2017-01-27 12:53:13 -06:00
7ed39ebaaf docs(changelog): add changelog for 2.4.5 2017-01-25 13:48:29 -08:00
091f0a5aaa chore(release): cut the 2.4.5 release 2017-01-25 13:48:21 -08:00
315606e02c style(compiler): run format 2017-01-25 13:21:04 -08:00
5ea373d184 docs(core): add docs for AnimationStyles and AnimationKeyframe (#14107) 2017-01-25 11:51:02 -08:00
6e36bb7b20 docs(compiler): add comment to warn about regexp changes (#14106)
ref #14082
2017-01-25 11:50:55 -08:00
3b2fb23805 fix(upgrade/static): ensure upgraded injector is initialized early enough (#14065)
This change ensures that the upgraded AngularJS injector is initialized
before the application run blocks are executed.

Closes #13811
2017-01-25 11:49:59 -08:00
bd2eecb4de fix(compiler): fix regexp to support firefox 31 (#14082)
fixes #14029
closes #13900
2017-01-25 11:44:09 -08:00
3d351a4f5f fixup: remove message.id check from this branch 2017-01-25 11:43:16 -08:00
5492fada21 fix(compiler): [i18n] XMB/XTB placeholder names can contain only A-Z, 0-9, _n
There are restrictions on the character set that can be used for xmb and xtb
placeholder names.

However because changing the placeholder names would change the message IDs it
is not possible to add those restrictions to the names used internally. Then we
have to map internal name to public names when generating an xmb file and back
when translating using an xtb file.

Note for implementors of `Serializer`:
- When writing a file, the implementor should take care of converting the
internal names to public names while visiting the message nodes - this is
required because the original nodes are needed to compute the message ID.
- When reading a file, the implementor does not need to take care of the mapping
back to internal names as this is handled in the `I18nToHtmlVisitor` used by the
`TranslationBundle`.

fixes b/34339636
2017-01-25 10:35:03 -08:00
fd4f9acbcf fix(core): export animation classes required for Renderer impl (#14002)
Closes #14001
2017-01-25 10:32:16 -08:00
48528a86e1 docs(common): fix a typo on the DatePipe API docs (#14060) 2017-01-25 10:32:08 -08:00
80364def27 ci: bump node and npm versions in circle.yaml to match travis 2017-01-25 10:31:50 -08:00
1803beb4d5 Fixed documentation reference to canActivate in canDeactivate (#14018)
Simple update to code sample which references canActivate: ['canDeactivateTeam'].
2017-01-25 10:31:42 -08:00
3bcba8a570 chore(docs): add missing comments (#14003)
This is a load-bearing change to avoid duplicate licenses in closure-compiled bundles.
See https://github.com/angular/tsickle/issues/332
2017-01-25 10:30:46 -08:00
84542d8ae7 docs(changelog): add changelog for 2.4.4 2017-01-18 18:35:54 -06:00
17cb3ec565 chore(release): cut the 2.4.4 release 2017-01-18 18:32:57 -06:00
015878afe6 fix(http): don't create a blob out of ArrayBuffer when type is application/octet-stream (#13992)
Closes #13973
2017-01-18 18:28:37 -06:00
2af58622c1 fix(router): enable loadChildren with function in aot (#13909)
Closes #11075
2017-01-18 18:28:02 -06:00
7ffd10541d refactor(core): remove an unused import in application_ref (#13901) 2017-01-18 18:27:52 -06:00
481b099d82 docs(CHANGELOG): added reference to closed issue in CHANGELOG for informational purposes (#13985) 2017-01-18 18:27:25 -06:00
49c4b0fa92 fix(router): routerLinkActive should not throw when not initialized (#13273)
Fixes #13270

PR Close #13273
2017-01-18 18:27:14 -06:00
b8b6b1d27a refactor(router): clean up RouterLinkActive (#13273)
PR Close #13273
2017-01-18 18:27:03 -06:00
892b5ba950 chore(tsc-wrapped): update tsickle to latest (#13471) 2017-01-18 18:26:37 -06:00
bd15110c7d feat(security): allow calc and gradient functions. (#13943)
PR Close #13943

Also includes support for # color notation in function arguments (common
in gradient functions).
2017-01-18 18:25:45 -06:00
2250082fd7 fix(upgrade): detect async downgrade component changes (#13812)
This commit effectively reverts 7e0f02f96e
as it was an invalid fix for #6385, that created a more significant
bug, which was that changes were not always being detected.

Angular 1 digests should be run inside the ngZone to ensure
that async changes are detected.

We don't know how to fix #6385 without breaking change detection
at this stage. That issue is triggered by async operations, such as
`setTimeout`, being triggered inside scope watcher functions.

One could argue that watcher functions should be pure and not do
work such as triggering async operations. It is possible that the
original use case could be supported by moving the debounce
logic into the watch listener function, which is only called if the
watched value actually changes.

Closes #10660, #12318, #12034

PR Close #13812
2017-01-18 18:21:29 -06:00
87316c52db test(upgrade): reorganise test layout (#13812) 2017-01-18 18:21:24 -06:00
606b76d9bb chore(compiler-cli): Move calculateEmitPath into CompilerHost (#13904)
This is so that it can be overriden in an environment specific CompilerHost(like within Google) to customize the output paths.

PR Close #13904
2017-01-18 18:21:09 -06:00
3d0b1b8184 fix(common): support numeric value as discrete cases for NgPlural (#13876)
PR Close #13876
2017-01-18 18:20:56 -06:00
261fd16780 fix(animations): fix internal jscompiler issue and AOT quoting (#13798)
CL #143630929
PR Close #13798
2017-01-18 18:20:47 -06:00
104cc42f6d docs(http): Spelling Fix #13867 2017-01-18 18:20:30 -06:00
a7d28044c5 docs(changelog): add changelog for 2.4.3 2017-01-11 13:38:23 -08:00
055bea2969 chore(release): cut v2.4.3 2017-01-11 13:38:16 -08:00
dad0d21b89 chore(owners): configure pullapprove.com 2017-01-11 11:35:31 -08:00
313683f6f3 fix(compiler-cli): avoid handling functions in loadChildren as lazy load routes paths
The change avoids the compiler CLI internal API from mismatching the following case as lazy loading

```
import { NonLazyLoadedModule } from './non-lazy-loaded/non-lazy-loaded.module';

export function getNonLazyLoadedModule() { return NonLazyLoadedModule; }

export const routes = [
{ path: '/some-path', loadChildren: getNonLazyLoadedModule }
];
```

The output of the check is later passed to `RouteDef.fromString()`, so, it makes sense to be only a string.

Fixes angular/angular-cli#3204
2017-01-11 11:35:23 -08:00
338be6d6a5 refactor(common): remove some facade usages 2017-01-11 11:34:03 -08:00
4b56f79328 refactor(test): <template>/<ng-container>/*-directives
- remove outer `<div>` in tests,
- use `<ng-container>` instead of `<template>` where possible,
- use *... instead of template (tag or attr) where possible.

Fixes #13816
2017-01-11 11:33:30 -08:00
d7f2a3c71b fix(i18n): translate attributes inside elements marked for translation 2017-01-10 17:15:42 -08:00
1c929ae244 docs(NgPlural): fix API docs
Fixes #13786
2017-01-10 16:51:52 -08:00
83d0ff6d13 refactor(Compiler): misc cleanup 2017-01-10 16:50:20 -08:00
d43e5dd44d chore(benchmarks): change var to let 2017-01-09 16:08:33 -08:00
61ba223c1a fix(router): throw an error when navigate to null/undefined path
Closes #10560
Fixes #13384
2017-01-09 18:55:31 -05:00
6164eb25f3 fix(compiler-cli): add support for more than 2 levels of nested lazy routes
This change adds Compiler CLI support for any level of nesting for lazy routes.

For example `{app-root}/lazy-loaded-module-1/lazy-loaded-module-2/lazy-loaded-module-3`

Where `lazy-loaded-module-3` is lazy loaded from `lazy-loaded-module-2`,
and `lazy-loaded-module-2` is lazy loaded from module `lazy-loaded-module-1`,
and `lazy-loaded-module-1` is lazy loaded from `AppModule`

Fixes angular/angular-cli#3663
2017-01-09 18:06:26 -05:00
5e9d3dba3a fix(compiler): avoid evaluating arguments to unknown decorators
Fixes #13605
2017-01-09 18:06:11 -05:00
16922655ca fix(Router): fix checking for object intersection 2017-01-09 18:06:03 -05:00
7dc12b93fe fix(Compiler): fix template binding parsing (*directive="-...")
fixes #13800
2017-01-09 16:50:14 -05:00
1c82b58185 fix(router): RouterLink mirrors input target as attribute
Closes #13837
2017-01-09 16:50:06 -05:00
d6c414c08f fix: correctly show error when karma fails to load 2017-01-09 16:49:01 -05:00
d25d1730c7 chore(tsc-wrapped): bump version number to 0.5.1 2017-01-06 12:46:07 -08:00
03b35d2e8f docs(changelog): add release notes for 2.4.2 2017-01-06 12:40:35 -08:00
722543739e chore(release): cut the 2.4.2 release 2017-01-06 12:37:50 -08:00
56b4296a09 fix(language-service): support TypeScript 2.1 (#13655)
@angular/language-service now supports using TypeScript 2.1 as the
the TypeScript host. TypeScript 2.1 is now also partially supported
in `ngc` but is not recommended as Tsickle does not yet support 2.1.
2017-01-06 11:00:12 -08:00
f1cde4339b fix(core): animations no longer silently exits if the element is not apart of the DOM (#13763) 2017-01-06 11:00:12 -08:00
b245b920a6 fix(core): animations should blend in all previously transitioned styles into next animation if interrupted (#13148) 2017-01-06 11:00:12 -08:00
f47a71689c refactor: remove unused imports 2017-01-06 11:00:11 -08:00
6be55cc214 fix(Common): allow null/undefined values for NgForTrackBy
Reverts a breaking change introduced in 2.4.1 by #13420
fixes #13641
2017-01-06 11:00:11 -08:00
504199cf5a docs(common): add an example how to bind multiple classes based on a single parameter (#13779)
Closes #13778
2017-01-06 11:00:11 -08:00
17c5fa9293 fix(forms): Validators.required properly validate arrays (#13362)
Closes #12274
2017-01-06 11:00:11 -08:00
5f49c3ed23 fix(common): do not override locale provided on bootstrap (#13654)
Closes #13607
2017-01-06 11:00:11 -08:00
ebba63057f docs(developer): add linting section and correct command to verify API changes 2017-01-06 11:00:11 -08:00
5058461af7 feat(benchmarks): add detectChanges test for ng2 tree benchmark 2017-01-06 11:00:11 -08:00
21f5f05893 fix(core): Remove reference to "Angular 2" in dev mode warning (#13751) 2017-01-06 11:00:11 -08:00
f2ee81fa7a Typo (#13698) 2017-01-06 11:00:11 -08:00
ae1029da35 docs(Http): fix and extend samples for testing/MockBackend (#13689)
Fix samples for MockBackend and MockBackend.connections that were outdated. Also extend central sample for MockBackend to ease getting started.
2017-01-06 11:00:10 -08:00
230e33f3f1 fix(compiler): don’t throw when using ANALYZE_FOR_ENTRY_COMPONENTS with user classes (#13679)
Fixed #13565
2017-01-05 21:21:33 -08:00
ec0ca01224 docs(Core): fix API docs for ContentChild and ViewChildren (#13656)
Move the documentations of the ContentChild and ViewChildren decorators
so that they appear correctly on angular.io.

Closes #13625
2017-01-05 21:21:22 -08:00
1cd73c7a79 fix(compiler): query <template> elements before their children. (#13677)
Fixes #13118
Closes #13167
2017-01-05 21:20:56 -08:00
9f6a647908 fix(router): update route snapshot before emit new values (#13558)
Closes #12912
2017-01-05 21:20:45 -08:00
29ffdfdffe fix(Compiler): allow "." in attribute selectors (#13653)
fixes #13645
2017-01-05 21:14:54 -08:00
5754ecc3e1 fix(router): fix lazy loaded module with wildcard route (#13649)
Closes #12955
2017-01-05 21:14:42 -08:00
dab15c79dd chore(tslint): update tslint to 4.x (#13603) 2017-01-05 21:14:28 -08:00
21942a88f0 fix(upgrade): fix/improve support for lifecycle hooks (#13020)
With the exception of `$onChanges()`, all lifecycle hooks in ng1 are called on
the controller, regardless if it is the binding destination or not (i.e.
regardless of the value of `bindToController`).

This change makes `upgrade` mimic that behavior when calling lifecycle hooks.

Additionally, calling the `$onInit()` hook has been moved before calling the
linking functions, which also mimics the ng1 behavior.
2017-01-05 21:14:14 -08:00
018865ee6b fix(router): routerLink support of null/undefined (#13380)
Closes #6971
2017-01-05 21:11:56 -08:00
f7234378b6 fix(common): add link to trackBy docs (#13634) 2017-01-05 21:11:34 -08:00
5f47583c94 fixed minor typo (#13626) 2017-01-05 21:06:13 -08:00
0e7f9f0bff fix(testing): improve misleading error message when don't call compileComponents (#13543)
Closes #11301
2017-01-05 21:05:39 -08:00
28a92b2bcd docs(changelog): add changelog for 2.4.1 2016-12-21 14:26:13 -08:00
48be539824 chore(release): cut the 2.4.1 release 2016-12-21 14:22:42 -08:00
d788c679b6 fix(animations): always recover from a failed animation step (#13604) 2016-12-21 14:17:45 -08:00
a38f14b39c fix(router): should reset location if a navigation by location is successful (#13545)
Closes #13491
2016-12-21 14:17:25 -08:00
6a5e46cedd fix(animations): always quote string map key values in AOT code (#13602) 2016-12-21 09:49:03 -08:00
6316e5df71 fix(compiler): ignore @import in comments (#13368)
* refactor(compiler): clean up style url resolver
* fix(compiler): ignore @import in css comments

Closes #12196
2016-12-21 09:49:03 -08:00
90fca7c879 Include bower instructions in DEVELOPER.md (#13591) 2016-12-21 09:49:03 -08:00
d871ae2dc6 refactor(platform-browser): resolver merge conflict for tslint (#13601) 2016-12-21 09:49:03 -08:00
44e84d87f9 fix(common): throw an error if trackBy is not a function (#13420)
* fix(common): throw an error if trackBy is not a function

Closes #13388

* refactor(platform-browser): disable no-console rule in DomAdapter
2016-12-21 09:49:03 -08:00
b9e979e0a5 fix(core): improve error message when component factory cannot be found (#13541)
Closes #12678
2016-12-21 09:49:03 -08:00
cb2aa41782 build: fix publish-build-artifacts branch detection (#13599) 2016-12-21 09:49:03 -08:00
189a7e3750 build: publish build artifacts to branches (#13529)
Fix #13126
2016-12-21 09:49:03 -08:00
6efdf84d3e docs(changelog): add changelog for 2.4.0 2016-12-19 17:42:17 -08:00
e61bfc8b24 chore(release): cut the 2.4.0 release 2016-12-19 17:19:25 -08:00
070f9d0644 refactor: formatting fixes 2016-12-19 17:18:33 -08:00
8d5da1e57a feat: update to rxjs@5.0.1 and unpin the rxjs peerDeps via ^5.0.1 (#13572)
Now that rxjs is stable and the rxjs team follows semver, we can update and unpin the dependency safely.

From now on the Angular application/library developers are in charge of controlling the rxjs version as long as it's newer than 5.0.1.

closes #13561
closes #13478
closes #13572
2016-12-19 17:09:41 -08:00
b6406191c7 build(npm): update angular version in shrinkwrap files 2016-12-19 17:09:41 -08:00
124face441 refactor(compiler-cli): support extracting the mesage bundle without writing a file (#13580) 2016-12-19 17:09:41 -08:00
de4ace77fe feat(compiler-cli): private i18n API for the CLI (#13536)
Also change the Extractor API to align with the Codegen API (internal APIs)
2016-12-19 17:09:41 -08:00
debb0c9798 fix(compiler-cli): produce metadata for .d.ts files without metadata (#13526)
Fixes #13307
Fixes #13473
Fixes #13521
2016-12-19 17:09:40 -08:00
9b87bb6d7f fix(compiler): do not lex }} when interpolation is disabled (#13531)
* doc(compiler): fix the ICU expander API docs

* test(compiler): add lexer and parser specs

* fix(compiler): do not lex `}}` when interpolation is disabled

fix #13525
2016-12-19 17:09:40 -08:00
71e88a8c3c refactor(core): fix typo (#13515)
Closes #13512
2016-12-19 17:09:40 -08:00
c26c24c544 fix(upgrade): fix registerForNg1Tests (#13522)
Fix an issue in `registerForNg1Tests`, where it passes a `null` as
`ng1Injector` to `_bootstrapDone`. This causes a "TypeError: Cannot
read property 'get' of null" to be thrown from `_bootstrapDone`.
2016-12-19 17:09:40 -08:00
3f178410c3 fix(i18n): add a default example to xmb placeholders (#13507)
Otherwise the TC would not be able to load the message
2016-12-19 17:09:40 -08:00
b36f4bc00d fix(animations): allow players to be destroyed before initialized (#13346)
Closes #13293
Closes #13346
2016-12-19 17:09:40 -08:00
355c537883 refactor(compiler): format update (#13506) 2016-12-19 17:09:39 -08:00
f277303ca3 refactor(compiler): don't print stack trace on template parse errors (#13390) 2016-12-19 17:09:39 -08:00
50afbe094f fix(build): use bash string comparison operator (#13502) 2016-12-19 17:09:39 -08:00
15ea758d01 feature(DEVELOPER.md): add easy way to publish personal snapshot builds (#13469) 2016-12-19 17:09:39 -08:00
1f0f429f2a refactor(compiler): store metadata of top level symbols also in summaries (#13289)
This allows a build using summaries to not need .metadata.json files at all
any more.

Part of #12787
2016-12-19 17:09:39 -08:00
dbb364e23a docs(changelog): minor updates to 2.3.1 changelog 2016-12-14 21:57:56 -08:00
540b1197a6 fix(form): fix merge errors 2016-12-14 18:22:03 -08:00
d30cc8461b docs(changelog): add changelog for 2.3.1 2016-12-14 18:14:34 -08:00
f27954e62c build: bump angular to 2.3.1 & tsc-wrapped to 0.5.0 2016-12-14 18:11:35 -08:00
69b52eb2b3 fix(compiler): fix merge error in compiler_host 2016-12-14 18:08:54 -08:00
b9b557cdb0 fix(compiler): update to metadata version 3 (#13464)
This change retracts support for metadata version 2.

The collector used to produce version 2 metadata was incomplete
and can cause the AOT compiler to fail to resolve symbols or
produce other spurious errors.

All libraries compiled and published with 2.3.0 ngc will need
to be recompiled and updated with this change.
2016-12-14 18:08:48 -08:00
a72a002a8d refactor: format & lint 2016-12-14 18:08:43 -08:00
a0437f8c9d chore(animations/aot): always export NoOpAnimationDriver (#13480) 2016-12-14 18:08:36 -08:00
1c279b3264 fix(compiler): fix simplify a reference without a name
closes #13470
2016-12-14 18:08:32 -08:00
cd03c77364 fix(tsc-wrapped): generate metadata for exports without module specifier
fixes #13327
2016-12-14 18:08:29 -08:00
f6ef7d6e5a fix(compiler): propagate exports when upgrading metadata to v2 2016-12-14 18:08:25 -08:00
6aeaca3fb4 fix(compiler): resolver should merge host bindings and listeners (#13474)
fixes #13327
2016-12-14 18:07:41 -08:00
af62050729 docs(upgrade): fix UpgradeAdapter examples
closes #12675
2016-12-14 18:02:26 -08:00
cb69656b56 docs(upgrade/upgrade_adapter): fix up references to AngularJS and Angular 2 2016-12-14 18:02:14 -08:00
2fc0560988 feat(upgrade): enable Angular 1 unit testing of upgrade module
- New method `UpgradeAdapter.registerForNg1Tests(modules)` declares the
  Angular 1 upgrade module and provides it to the `angular.mock.module()`
  helper.
  This prevents the need to bootstrap the entire hybrid for every test.

Closes #5462, #12675
2016-12-14 18:02:05 -08:00
86c50983d7 fix(upgrade): fix downgrade content projection and injector inheritance
- Full support for content projection in downgraded Angular 2
  components. In particular, this enables multi-slot projection and
  other features on <ng-content>.
- Correctly wire up hierarchical injectors for downgraded Angular 2
  components: downgraded components inherit the injector of the first
  other downgraded Angular 2 component they find up the DOM tree.

Closes #6629, #7727, #8729, #9643, #9649, #12675
2016-12-14 17:56:20 -08:00
21976446e0 refactor(upgrade/upgrade_adapter): use Deferred helper
Making Angular 1's `$compile` asynchronous by chaining injector promises
in linking functions can cause flickering views in applications.
2016-12-14 17:56:16 -08:00
998ce9ad7e refactor(upgrade/util): remove unused stringify() method 2016-12-14 17:56:11 -08:00
111523677c refactor(compiler/template_parser): export createElementCssSelector
This is needed in `ngUpgrade`.
2016-12-14 17:56:06 -08:00
2d74a224d0 refactor(upgrade): add missing Angular 1 type info 2016-12-14 17:55:56 -08:00
4d6ac9d414 fix(core): detectChanges() doesn't work on detached instance
Closes #13426
Closes #13472
2016-12-14 17:55:38 -08:00
6557bc34f6 fix(animations): throw errors and normalize offset beyond the range of [0,1]
Closes #13348
Closes #13440
2016-12-14 17:55:34 -08:00
e2622add07 perf(animations): always run the animation queue outside of zones
Related #12732
Closes #13440
2016-12-14 17:55:27 -08:00
ecfad467a1 fix(compiler): emit quoted object literal keys if the source is quoted
feat(tsc-wrapped): recored when to quote a object literal key

Collecting quoted literals is off by default as it introduces
a breaking change in the .metadata.json file. A follow-up commit
will address this.

Fixes #13249
Closes #13356
2016-12-14 17:55:22 -08:00
5918133784 Revert "fix(compiler): xmb <ph> tags should not self close (#13413)"
This reverts commit 4b3d135193.
closes #13463
2016-12-14 17:55:18 -08:00
700bce9ec1 Revert "test(i18n): fix a typo in the reference xmb (#13441)"
This reverts commit a8d237581d.
2016-12-14 17:55:14 -08:00
a64a35a8c1 refactor(facade): don't expect super() to return a new Error object in BaseError (#12600)
Related to #12575
2016-12-14 17:55:10 -08:00
b3dcff0cc1 fix(forms): ensure select[multiple] retains selections
If you bound an array to select[multiple] via ngModel and subsequently
changed the options to select from, the UI would drop any selections
made since by the user. This was due to
SelectMultipleControlValueAccessor not keeping a reference to the new
model arrays it generated when users interacted with the select control.
Update code to keep the reference.

Closes #12527
Closes #12654
2016-12-14 17:55:02 -08:00
124267c87a fix(forms): introduce checkbox required validator
Closes #11459
Closes #13364
2016-12-14 17:52:53 -08:00
547bfa92ef fix (forms): clear selected options when model is not an array (#12519)
When an invalid model value (eg empty string) was preset ngModel on
select[multiple] would throw an error, which is inconsistent with how it
works on other user input elements. Setting the model value to null or
undefined would also have no effect on what was already selected in the
UI. Fix this by clearing selected options when model set to null,
undefined or a type other than Array.

Closes #11926
2016-12-14 17:52:02 -08:00
d40bbf4d5c fix(core): properly destroy embedded Views attatched to ApplicationRef (#13459)
Fixes #13062
2016-12-14 17:51:56 -08:00
94b7031fe9 refactor: format & lint 2016-12-14 17:51:48 -08:00
df0bf1dd74 chore(internal API): introduce an internal API for ngtools. (#13415) 2016-12-14 17:51:40 -08:00
c8a9b70890 fix(compiler): generated CSS files suffixed with ngstyle. (#13353)
Mirrors factories which ends in `ngfactory`.

Closes #13141.
2016-12-14 17:50:29 -08:00
efa2d80df8 fix(compiler): make sure provider values with name property don’t break.
Fixes #13394
Closes #13445
2016-12-14 17:50:22 -08:00
a58e5efd09 test(i18n): fix a typo in the reference xmb (#13441) 2016-12-14 17:50:12 -08:00
86cf0ef892 refactor: remove intl from facades (#13404)
The existing intl.ts file is not a facade but
rather a set of utils used by i18n-related pipes only.
As such moving it back to common module so those utils
are not used accidently from other places.
2016-12-14 17:50:02 -08:00
5c568fab86 test(upgrade): fix failing test in browsers which do not support RAF
closes #13399
2016-12-14 17:49:52 -08:00
566104504c ci(browser providers): update browsers in SL and BS (#13431) 2016-12-14 17:49:37 -08:00
307d305b2d fix(compiler): narrow the span reported for invalid pipes
fixes #13326
closes #13411
2016-12-14 17:49:05 -08:00
0a7364feea fix(language-service): correctly type undefined
fixes #13412
closes #13414
2016-12-14 17:40:58 -08:00
4544b1d7a6 fix(compiler): xmb <ph> tags should not self close (#13413) 2016-12-14 17:39:51 -08:00
9e0e6b59d1 docs(core): update OnDestroy description (#13369)
Closes #11228
2016-12-14 17:39:45 -08:00
14dd2b367a fix(language-service): treat string unions as strings (#13406)
Fixes #13403
2016-12-14 17:39:36 -08:00
91eb8914dd build: update the package list of the symlinks scripts for Windows (#13408) 2016-12-14 17:39:30 -08:00
77823d721f refactor: format and lint code 2016-12-14 17:38:31 -08:00
2afe2d107f docs(Location): updating Location docs and adding example
closes #11500
2016-12-14 17:38:22 -08:00
17f40fb75f chore: Add @types/systemjs 2016-12-14 17:37:43 -08:00
98936fdf16 chore: convert hash_location_strategy example to a tested spec 2016-12-14 17:37:33 -08:00
7383e4a801 fix(forms): fix Validators.min/maxLength with FormArray (#13095)
Fixes #13089
2016-12-14 17:37:18 -08:00
65c9b5b6aa fix(http): create a copy of headers when merge options (#13365)
Closes #11980
2016-12-14 17:36:48 -08:00
5fab8710cb fix(dom_adapter): remove logError from logGroup (#12925) 2016-12-14 17:35:12 -08:00
f106a18b96 fix(http): check response body text against undefined (#13017) 2016-12-14 17:35:05 -08:00
8db184d349 fix(compiler): support dotted property binding
fixes angular/flex-layout#34
2016-12-14 17:31:08 -08:00
c18eb298eb test(Selector): add a test for dotted attribute names 2016-12-14 17:31:00 -08:00
3f4aa59cfa refactor(Compiler): cleanup 2016-12-14 17:30:50 -08:00
79728b4c41 fix(compiler): fix PR 13322 (#13331) 2016-12-14 17:30:40 -08:00
413167ab1b style: clang-format the code 2016-12-14 17:26:52 -08:00
203cc7e1f1 fix: Better instructions on running examples and their tests 2016-12-14 17:23:11 -08:00
b0cd514709 fix: Better error when directive not listed in NgModule.declarations 2016-12-14 17:22:58 -08:00
392c9ac214 fix(selector): SelectorMatcher match elements with :not selector (#12977) 2016-12-14 17:21:34 -08:00
a26e054857 fix(animations): always cleanup players after they have finished internally (#13334)
Closes #13333
Closes #13334
2016-12-14 17:21:23 -08:00
c0b001a6af refactor(router): misc refactoring (#13330) 2016-12-14 17:21:09 -08:00
c8c1f22f9c refactor(router): simplify regexp
closes #11373
closes #13329
2016-12-14 17:20:47 -08:00
e4d5a5f003 fix(router): add support for query params with mulitple values
closes #11373
2016-12-14 17:20:22 -08:00
03d9de33a1 Revert "fix(compiler): fix transpiled ES5 code (#13322)"
This reverts commit 4398056146.
2016-12-14 17:20:14 -08:00
a8a80cf523 doc: update triage owners for language service and router (#13325) 2016-12-14 17:19:50 -08:00
6c1d7908d5 fix(compiler): fix transpiled ES5 code (#13322)
fixes #13301

The inner class would transpile to a nested function declaration which is not
allowed in ES5.

See http://eslint.org/docs/rules/no-inner-declarations
2016-12-14 17:18:12 -08:00
9aab6d24eb build(tslint): enable no-inner-declarations (#13316) 2016-12-14 17:18:02 -08:00
5ee8155e4e fix(router): Use T type in Resolve interface (#13242) 2016-12-14 17:17:45 -08:00
21de0f239d docs(changelog): fix a typo (#13298) 2016-12-14 17:16:49 -08:00
13b41bd631 chore(release): update version of tsc-wrapped to 0.4.2 2016-12-07 13:54:22 -08:00
f3524af68f docs(changelog): add changelog for 2.3.0 2016-12-07 11:21:13 -08:00
0a56f4ea82 chore(release): cut the 2.3.0 release 2016-12-07 10:58:29 -08:00
cf52284ac3 docs(changelog): fix typo AplicationRef => ApplicationRef (#13284)
docs(changelog): fix typo AplicationRef => ApplicationRef
2016-12-07 10:06:40 -08:00
4a09c81724 fix(language-service): do not throw for invalid metadata (#13261)
Fixes #13255
2016-12-06 17:11:09 -08:00
16efb13dd1 fix: display framework version on bootstrapped component (#13252) 2016-12-06 16:21:07 -08:00
986abbe0b2 fix(http): set the default Accept header (#12989)
Fixes #6354
2016-12-06 16:20:43 -08:00
25c2141991 fix(language-service): remove incompletely used parameter from createLanguageServiceFromTypescript() (#13278)
Fixes #13277
2016-12-06 16:19:39 -08:00
2893c2c0a2 fix(router): validate nested routes (#13224)
Fixes #12827
2016-12-06 10:41:01 -08:00
393c1007a8 fix(tsc-wrapped): have UserError display the actual error 2016-12-06 10:40:38 -08:00
66b6fc010d refactor(common): unify export structure 2016-12-06 10:40:38 -08:00
f31c9470fa fix(compiler): short-circut expressions with an index (#13263)
Fixes #13254
2016-12-06 10:40:15 -08:00
4bd8f58552 FIX typo (#13267) 2016-12-06 10:40:01 -08:00
93556a5720 fix(language-service): avoid throwing for invalid class declarations (#13257)
Fixes #13253
2016-12-06 09:56:30 -08:00
5614c4ff0f fix(compiler): serialize any StaticSymbol correctly, not matter in which context. 2016-12-05 14:20:01 -08:00
c3065aac7a refactor(compiler): replace isStaticSymbol with instanceof StaticSymbol 2016-12-05 14:20:01 -08:00
c767df0e4e fix(router): throw a better error message when angular 1 is not bootstraped 2016-12-05 10:57:24 -08:00
25e5b2fdf0 fix(router): make setUpLocationChangeListener idempotent 2016-12-05 10:57:24 -08:00
307c4693dc refactor(router): code cleanup 2016-12-05 10:54:10 -08:00
349ad75de3 fix(router): fix replaceUrl on RouterLink directives 2016-12-05 10:54:10 -08:00
f562cbf86c fix(router): fix skipLocationChanges on RouterLink directives
fixes #13156
2016-12-05 10:54:10 -08:00
804943c9b1 refactor(router): cleanup RouterLink 2016-12-05 10:54:10 -08:00
dea59165de docs(developer): add anchor to source code formatting (#13199)
In CONTRIBUTING.md#rules has reference to DEVELOPER.md#clang-format
but anchor to #clang-format is not present
2016-12-05 10:27:20 -08:00
a1322873c8 fix(facade): cache original format string (#12764) 2016-12-05 10:26:59 -08:00
b8c839bd51 docs(cheatsheet): correct HostBinding decorator example (#13206) 2016-12-05 10:25:40 -08:00
d2e5198b93 docs(contributing): fix styleguide link and typos (#13198) 2016-12-05 10:25:20 -08:00
6cf7a1bf84 refactor(build): fix build location of compiler-cli esm module (#13212) 2016-12-02 15:19:52 -08:00
d46b8deeea fix(router): runs guards every time when unsuccessfully navigating to the same url over and over again (#13209) 2016-12-02 15:19:00 -08:00
bbb7a39414 fix(router): allow specifying a matcher wihtout specifying a path
fixes #12972
2016-12-02 15:03:59 -08:00
d7d8fab211 refactor(router): cleanup config 2016-12-02 15:03:59 -08:00
51b06924bd docs(core): correct HostListener typo (#13203) 2016-12-02 14:45:47 -08:00
aa4bd14b3f docs(changelog): add instructions for people that depend on the cache operator (#13191) 2016-12-02 14:43:05 -08:00
3ff6554cbc fix(language-service): update to use CompilerHost from compiler-cli (#13189) 2016-12-02 14:34:16 -08:00
dfd8140084 Fix format 2016-12-02 14:31:55 -08:00
6ea3ab7e14 Fix exit code. Give a specific type. Add test cases. 2016-12-02 14:31:55 -08:00
9761db5ac2 refactor(compiler): change ngc error handling
Do not print stack trace for user errors
Print stack trace for compiler internal errors
2016-12-02 14:31:55 -08:00
75d1617b63 fix(compiler): include the summaries of reexported modules / directives / pipes (#13196)
Only if these are not part of the sources.
2016-12-02 10:08:46 -08:00
614a35d539 feat(compiler): read and write .ngsummary.json files
When compiling libraries, this feature extracts the minimal information
from the directives/pipes/modules of the library into `.ngsummary.json` files,
so that applications that use this library only need to be recompiled
if one of the summary files change, but not on every change
of the libraries (e.g. one of the templates).

Only works if individual codegen for libraries is enabled,
see the `generateCodeForLibraries: false` option.

Closes #12787
2016-12-01 14:49:52 -08:00
9ab401f4d3 refactor(compiler): simplify NgModuleSymmaryMetadata
- merge `NgModuleInjectorSummary` and `NgModuleDirectiveSummary`
- remove `directiveLoaders` from the summary
2016-12-01 14:49:52 -08:00
82c81cd0d2 fix(common): make sure the plural category exists (#13169)
fixes #12379
2016-12-01 13:26:24 -08:00
12959f444c refactor(router):remove unused parameter pathIndex (#13180) 2016-12-01 13:25:53 -08:00
25a6da244c refactor(compiler-cli): refactor compiler host parameters (#13147) 2016-12-01 13:24:51 -08:00
5908b66ae9 docs(changelog): move 2.2.2 to its place in the chronological order 2016-12-01 10:21:23 -08:00
480ef20eb1 docs(changelog): add changelog for 2.2.2 2016-12-01 09:59:23 -08:00
c066281bad docs(changelog): add changelog for 2.3.0-rc.0 2016-11-30 15:42:56 -08:00
1b9493f725 chore(release): cut the 2.3.0-rc.0 release 2016-11-30 15:42:56 -08:00
ae26504e84 fix(core): update peer dep on zone.js to ^0.7.2 2016-11-30 15:42:56 -08:00
d420080b3b docs(changelog): add changelog for 2.2.4 2016-11-30 15:19:09 -08:00
2975d8933c fix(language-service): harden against partial normalization of directives 2016-11-30 14:55:56 -08:00
43c0e9a6bb fix(compiler): fix performance regression caused by 5b0f9e2
Fixes #13146
2016-11-30 14:55:56 -08:00
f275f36081 fix(version): take all of version string after patch version 2016-11-30 14:25:11 -08:00
e628b66cca feat(build): record angular version in the dom (#13164) 2016-11-30 13:52:08 -08:00
3e73bea3e7 refactor(compiler): convert metadata classes used in summaries into interfaces (#13123)
Part of #12787
2016-11-30 10:52:51 -08:00
42cf06fa12 feat(router): add support for custom route reuse strategies 2016-11-29 23:21:41 -08:00
c4bbafc291 feat: upgrade zone.js to v0.7.1 2016-11-29 17:24:00 -08:00
2d6a003dba feat: update RxJS peer dependency to 5.0.0-rc.4
Closes #13125

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

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

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

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

## Example

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

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

  ngOnInit() {}
}

class ChildDirective extends ParentDirective {}
```

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

The only real change is removal of sourceRoot property.

Fixes #13040
2016-11-23 15:48:24 -08:00
4cbf8ccf05 Keep console.log that are not called during compilation. 2016-11-23 15:47:02 -08:00
a6c4490fce Check if console.error is defined 2016-11-23 15:47:02 -08:00
2c02d34c05 refactor(lint): Don't allow console.log
Enable tslint check for `console.log` as a follow-up to
https://github.com/angular/angular/issues/13018
2016-11-23 15:47:01 -08:00
6c2d931744 chore: make test.sh work again
Previously, `test.sh` relied on calling `build.sh` first
2016-11-23 14:23:05 -08:00
86ffa884b7 fix(build): update versions of umd bundles (#13038)
Fixes #13037
2016-11-22 13:39:41 -08:00
3e548de99d Revert "fix(router): guards restor an incorrect url when used with skipLocationChange"
This reverts commit ad20d7d260.
2016-11-22 13:31:33 -08:00
909268036b test(upgrade): remove setTimeout from lifecycle hook tests (#13027)
* test(upgrade): remove unnecessary NO_ERRORS_SCHEMA

* test(upgrade): remove `setTimeout` from lifecycle hook tests

Closes #13019
2016-11-22 09:21:03 -08:00
519a324454 feat(language-service): add services to support editors (#12987) 2016-11-22 09:10:23 -08:00
ef96763fa4 fix(animations): blend in all previously transitioned styles into next animation if interrupted (#13014)
Closes #13013
Closes #13014
2016-11-21 15:46:59 -08:00
7dcca307d9 fix(closure): quote date pattern aliases (#13012)
Quota the pattern aliases to prevent closure renaming. These are quoted in DatePipe and also need to be quoted here.
2016-11-21 11:45:48 -08:00
491d5a22a9 refactor(compiler): allow control of StaticSymbol lifetime (#12986) 2016-11-18 16:58:14 -08:00
44572f114f refactor(ngUpgrade): Small cleanup with Testability API and resumeBootstrap (#12926)
* With non-static ngUpgrade apps, callbacks to `whenStable` were being invoked with the wrong
  context
* With non-static ngUpgrade apps, `resumeBootstrap` was being run outside the NgZone
* Remove redundent `whenStableContext` variable

Neither of the first two problems were actually causing bugs (as far as I know), but they *might*
have caused problems in the future.

Inspired by https://github.com/angular/angular/pull/12910, but for non-static apps.
2016-11-18 14:30:47 -08:00
1ef4696cb7 fix(upgrade): call ng1 lifecycle hooks (#12875) 2016-11-18 13:46:49 -08:00
07a986d330 fix(changelog): replace beta.1 with beta.0 (#12961) 2016-11-18 12:37:26 -08:00
59d2b4c831 refactor(compiler): further minor fixes 2016-11-18 10:04:14 -08:00
2a5bd2f345 refactor(compiler): Reintroduce ReflectorHost and move Extractor into @angular/compiler 2016-11-18 10:04:14 -08:00
3c06a5dc25 refactor(comiler): various cleanups 2016-11-18 10:04:14 -08:00
adeea5d86a refactor(compiler): renames
- `NgHost` to `CompilerHost`
- `AotCompilerHost.resolveFileToImport` to `AotCompilerHost.fileNameToModuleName`
- `AotCompilerHoset.resolveImportToFile` to `AotCompilerHost.moduleNameToFileName`
2016-11-18 10:04:14 -08:00
dddbb1c1cb refactor(tsc-wrapped): collect all exported functions and classes and bump metadata version from 1 to 2
This is needed to resolve symbols without `.d.ts` files.
This bumps the version of the metadata from 1 to 2.
This adds logic into `ng_host.ts` to automatically upgrade
version 1 to version 2 metadata by adding the exported symbols
from the `.d.ts` file.
2016-11-18 10:04:14 -08:00
bccf0e69dc fix(compiler): fix versions of @angular/tsc-wrapped 2016-11-18 10:04:14 -08:00
b15039d228 refactor(compiler): move symbol extraction to AotCompiler 2016-11-18 10:04:14 -08:00
2235048432 refactor(compiler): add createAotCompiler factory
Also adds 2 more methods to the `AotCompilerHost`:
- `loadResource`
- `resolveFileToImport`
2016-11-18 10:04:14 -08:00
484119e59f refactor(compiler): remove asset: urls
These urls were just relicts from Dart.
2016-11-18 10:04:14 -08:00
24099bdbd2 refactor(compiler): move findDeclaration into the StaticReflector
Previously, this was part of the `AotCompilerHost`.
The `AotCompilerHost` is now also greatly simplified.
2016-11-18 10:04:14 -08:00
912ca44979 refactor(compiler): move static_reflector into @angular/compiler and rename files
- `src/runtime_compiler.ts` -> `src/jit/compiler.ts`
- `src/compiler.ts` -> `src/jit/compiler_factory.ts`
- `src/offline_compiler` -> `src/aot/compiler.ts`

Part of #12867
2016-11-18 10:04:14 -08:00
664a6273e1 feature(tsc-wrapped): add option for closure compiler JSDoc annotations 2016-11-18 09:37:40 -08:00
c1a62e2154 feat(tools): allow disabling annotation lowering 2016-11-18 09:37:40 -08:00
aac37bedc0 chore(build): update package.json versions during build (#12957) 2016-11-18 09:24:57 -08:00
a3884db87c fix(ci): pin version of npm on CircleCI (#12954) 2016-11-17 17:27:51 -08:00
fc5ac1ebc4 fix(benchmarks): use sanitized style values (#12943) 2016-11-17 15:18:10 -08:00
ad20d7d260 fix(router): guards restor an incorrect url when used with skipLocationChange
Closes #12825
2016-11-17 14:10:59 -08:00
602522beb2 fix(router): support redirects to named outlets
Closes #12740, #9921
2016-11-17 14:10:59 -08:00
4e047302f2 chore(release): cut the 2.3.0-beta.0 realse and add change log 2016-11-17 11:59:03 -08:00
419a812f04 chore(release): cut angular 2.2.1 2016-11-17 11:51:25 -08:00
f340e1a414 fix(tools): fix error when running test.sh (#12927) 2016-11-16 13:35:31 -08:00
481c9b3258 refactor(compiler): allows synchronous retrieving of metadata (#12908)
Allows non-normalized metadata to be retrieved synchronously.

Related to #7482
2016-11-16 10:22:11 -08:00
8b2dfb2eca fix(core): support ngTemplateOutlet in production mode (#12921)
Fixes #12911
2016-11-16 10:00:18 -08:00
824ea8406c docs(upgrade/static): improve API docs with examples
Closes #12717
2016-11-16 09:18:17 -08:00
1f96a93f59 chore(public_api): remove Angular 1 types from upgrade/static API 2016-11-16 09:18:10 -08:00
009d545787 chore(examples): add upgrade/static example 2016-11-16 09:18:10 -08:00
53c25210a6 chore(examples): support upgrade/static examples 2016-11-16 09:18:10 -08:00
927aa69726 fix(router): add a banner file for the router (#12919) 2016-11-16 09:17:19 -08:00
ce89039036 fix(platform_browser): fix disableDebugTools() (#12918) 2016-11-16 09:16:40 -08:00
42198cd7d5 fix(ngUpgrade): make AoT ngUpgrade work with the testability API and resumeBootstrap() (#12910) 2016-11-16 01:04:56 -08:00
d6ba092a27 build(build.sh): echo before building examples 2016-11-15 20:59:37 -08:00
773b31de8f fix(router): should not create a route state if navigation is canceled (#12868)
Closes #12776
2016-11-15 19:00:20 -08:00
f79b320fc4 refactor(forms): remove facade (#12558) 2016-11-15 18:48:34 -08:00
6a212fd561 fix(router): removes a peer dependency from router to upgrade 2016-11-15 18:37:08 -08:00
be010a292a fix(animations): only pass in same typed players as previous players into web-animations (#12907)
Closes #12907
2016-11-15 17:47:21 -08:00
7c36e7f956 chore(router): remove @angular/upgrade peer dep (#12896) 2016-11-15 14:00:11 -08:00
13ba2f90b9 refactor(http): remove all facade methods from http module (#12870) 2016-11-15 09:19:14 -08:00
75277cd94b fix(tsickle): support ctorParams in function closure (#12876)
See https://github.com/angular/tsickle/issues/261 for context.
2016-11-15 09:19:00 -08:00
46d150266b feat(router_link): add skipLocationChange and replaceUrl inputs (#12850) 2016-11-14 18:30:13 -08:00
1b5384ee54 feat(core): expose ViewRef as ChangeDetectorRef
closes #12722

This is helpful when manually dirty checking embedded views.
2016-11-14 17:01:41 -08:00
9f7d32a326 feat(core): add attachView / detachView to ApplicationRef
This feature is useful to allow components / embedded views
to be dirty checked if they are not placed in any `ViewContainer`.

Closes #9293
2016-11-14 17:01:35 -08:00
9de76ebfa5 fix(animations): retain styling when transition destinations are changed (#12208)
Closes #9661
Closes #12208
2016-11-14 16:59:06 -08:00
46023e4792 fix(select): allow for null values in HTML select options bound with ngValue
closes #12829
2016-11-14 16:47:14 -08:00
b55aaf094f fix: allow for null values in HTML select options bound with ngValue
This corrects the case of <option [ngValue]="null"> binding a string like "{0: null}" to the model instead of an actual null object.

Closes #10349
2016-11-14 16:47:09 -08:00
d90b622fa4 fix: allow for null values in HTML select options bound with ngValue
This corrects the case of <option [ngValue]="null"> binding a string like "{0: null}" to the model instead of an actual null object.

Closes #10349
2016-11-14 16:47:09 -08:00
79e2bb9291 refactor(core): remove dead code (#12871) 2016-11-14 16:44:25 -08:00
efbbefd353 fix(platform-browser): enable AOT
closes #12783
2016-11-14 12:57:11 -08:00
c2fae72bc6 feat(router): register router with ngprobe 2016-11-14 12:57:05 -08:00
7908679c4b fix(compiler): assert xliff messages have translations
fixes #12815
closes #12604
2016-11-14 12:55:56 -08:00
9ed9ff40b3 test(compiler): improve xliff tests 2016-11-14 12:55:48 -08:00
2f14415836 fix(compiler): updates hash algo for xmb/xtb files 2016-11-14 12:55:48 -08:00
76e4911e8b fix(core): fix placeholders handling in i18n.
Prior to this commit, translations were built in the serializers. This
could not work as a single translation can be used for different source
messages having different placeholder content.

Serializers do not try to replace the placeholders any more.
Placeholders are replaced by the translation bundle and the source
message is given as parameter so that the content of the placeholders is
taken into account.

Also XMB ids are now independent of the expression which is replaced by
a placeholder in the extracted file.
fixes #12512
2016-11-14 12:55:48 -08:00
ed5e98d0df fix(core): misc i18n fixes 2016-11-14 12:55:48 -08:00
146af1fed9 refactor(core): simplify i18n serializers code 2016-11-14 12:55:48 -08:00
c60ba7a72f refactor(core): remove ListWrapper from i18n 2016-11-14 12:55:48 -08:00
05beffe0d0 test(core): fix a typo in the i18n integration spec 2016-11-14 12:55:48 -08:00
08c038ebd9 fix(core): xmb serializer uses decimal messaged IDs
fixes #12511
2016-11-14 12:55:48 -08:00
582550a90d feat(core): implements a decimal fingerprint for i18n 2016-11-14 12:55:48 -08:00
1d53a870dd fix(http): return request url if it cannot be retrieved from response
closes #12837
2016-11-14 12:54:43 -08:00
a0c58a6b5c fix(http): correctly handle response body for 204 status code
closes #12830
fixes #12393
2016-11-14 12:36:22 -08:00
d3eff6c483 refactor(xhr_backend): remove facade 2016-11-14 12:36:16 -08:00
2524d510bc chore(release): cut the 2.2.0 upgrade-firebooster release 2016-11-14 11:26:03 -08:00
8f5dd1f11e chore(lint): enforce no var keyword rule 2016-11-12 16:40:17 -08:00
77ee27c59e refactor(): use const and let instead of var 2016-11-12 16:40:17 -08:00
73593d4bf3 perf(platform-browser): cache plugin resolution in the EventManager
closes #12824
2016-11-11 17:19:47 -08:00
a965d11cce fix(compiler): generate safe access strictNullChecks compatible code (#12800)
fixes #12795
2016-11-11 17:12:17 -08:00
52be848f94 fix(router): incorrect injector is used when instantiating components loaded lazily (#12817) 2016-11-11 17:12:00 -08:00
69dfcf7385 docs(forms): add inline docs why ngModel runs a 2nd change detection run (#12821)
Related to #11895
2016-11-11 15:24:11 -08:00
785b7b640e fix(router): Route.isActive also compares query params (#12321) 2016-11-11 13:23:47 -08:00
e5a753e111 fix(router): router should not swallow "unhandled" errors
closes #12802
2016-11-11 13:22:19 -08:00
768cddbe62 fix(events): provide the ability to register global hammer.js events
closes #12797
2016-11-11 11:15:49 -08:00
92f244aa26 refactor(events): remove facade and clean up 2016-11-11 11:15:43 -08:00
2a4bf9a0df fix(router): avoid router initialization for non root components
closes #12338
closes #12814
2016-11-11 11:15:17 -08:00
45ddd6ba78 cleanup(forms): remove facade (#12804) 2016-11-11 10:47:34 -08:00
7886561997 fix(router): check if windows.console exists before using it (#12348) 2016-11-11 10:46:53 -08:00
752edca81b test(core): ngOnDestroy called before output events are detached (#9946)
closes #6984
closes #5436
2016-11-11 10:27:32 -08:00
1bd858fb43 build(examples): upgrade to protractor 4.0.9 (#12803)
closes #12798
2016-11-10 18:13:11 -08:00
fcb4e66493 refactor(compiler): introduce summaries for metadata (#12799)
This does not yet introduce loading / serialization of summaries.

Part of #12787
2016-11-10 16:27:53 -08:00
ef881475e9 fix(forms): check if registerOnValidatorChange exists on validator before trying to invoke it (#12801)
closes #12593
2016-11-10 16:20:59 -08:00
458ca7112a build(publish): remove unneeded add-license-to-rx (#12734) 2016-11-10 15:56:14 -08:00
2aba8b0ff2 fix(common): no TZ Offset added by DatePipe for dates without time (#12380) 2016-11-10 14:57:04 -08:00
77dc1ab675 fix(router): throw an error when encounter undefined route (#12389) 2016-11-10 14:55:10 -08:00
3052fb234f fix(router): ignore null or undefined query parameters (#12333) 2016-11-10 14:41:19 -08:00
79383ce150 refactor(compiler): never create CompileDirectiveMetadata with not loaded resources (#12788)
Part of #12787
2016-11-10 14:07:30 -08:00
c3c0e2e2a2 refactor(compiler): add span to TemplateBinding (#12792)
fix(compiler): corrected error location for implicit templates expressions
2016-11-10 13:15:09 -08:00
44a142fc02 chore(playground): use base64-js from npm
closes #12471
2016-11-10 12:08:04 -08:00
3d9d839c6c refactor(playground): make playground great again 2016-11-10 12:07:51 -08:00
69f87ca075 fix(tools): harden colletor against invalid asts (#12793) 2016-11-10 11:58:55 -08:00
f224ca1461 ci(BrowserStack): increase timeout to avoid failures (#12786)
relates to #12578
2016-11-10 11:58:06 -08:00
19e869e7c9 fix(animations): ensure animations work with web-workers (#12656) 2016-11-10 11:53:50 -08:00
7cab30f85d refactor(compiler-cli): add position data to static reflector errors (#12782) 2016-11-09 16:29:22 -08:00
73407351e7 feat(router): add support for custom url matchers
Closes #12442
Closes #12772
2016-11-09 16:24:58 -08:00
2c110931f8 fix(router): do not require the creation of empty-path routes when no url left
Closes #12133
2016-11-09 16:24:49 -08:00
2ced2a8a5a refactor(compiler): misc updates (#12773) 2016-11-09 16:23:41 -08:00
634b3bb88b feat(core): map 'for' attribute to 'htmlFor' property (#10546)
This improves ergonomics a bit by allowing people to write:
`<label [for]="ctxProp"></label>`.
This is similar to the existing class -> className mapping.

Closes #7516
2016-11-09 15:21:27 -08:00
4595a61aeb refactor(compiler-cli): refactor imports in codegen to enable rollup (#12781) 2016-11-09 15:17:24 -08:00
f80a157b65 fix(animations): ensure web-animations are caught within the Angular zone
Closes #11881
Closes #11712
Closes #12355
Closes #11881
Closes #12546
Closes #12707
Closes #12774
2016-11-09 15:16:34 -08:00
6e35d13fbc feat(router): add a provider making angular1/angular2 integration easier (#12769) 2016-11-09 13:33:33 -08:00
fe35bc34f6 fix(animations): allow animations to be destroyed manually (#12719)
Closes #12456
Closes #12719
2016-11-08 16:21:28 -08:00
ad3bf6c54f fix(core): apply host attributes to root elements (#12761)
Fixes #12744
2016-11-08 15:46:55 -08:00
a0e9fde653 fix(animations): always normalize style properties and values during compilation (#12755)
Closes #11582
Closes #12481
Closes #12755
2016-11-08 15:45:30 -08:00
3dc61779f0 fix(DatePipe): handle empty string (#12374) 2016-11-08 15:45:12 -08:00
09092ac3c2 fix(forms): getRawValue returns any instead of Object (#12599) 2016-11-08 15:44:36 -08:00
778e6ad3b4 refactor: cleanup ICU message syntax 2016-11-08 15:44:18 -08:00
55dc0e4a5f fix(compiler): use the other case by default in ICU messages 2016-11-08 15:44:18 -08:00
4708b248d5 fix(common): I18nSelectPipe selects other case on default 2016-11-08 15:44:18 -08:00
7694f974af refactor: remove some facades (#12731) 2016-11-08 15:43:24 -08:00
acbf1d859c fix(core): fix pseudo-selector shimming (#12754)
fixes #12730
fixes #12354
2016-11-07 13:56:04 -08:00
f3793b5953 fix(NgClass): throw a descriptive error when CSS class is not a string (#12662)
Fixes #12586
2016-11-07 12:23:31 -08:00
22c021c57f fix(compiler): support more than 9 interpolations (#12710)
Fixes #10253
2016-11-07 12:23:03 -08:00
d8f23f4b7f fix(common): NgSwitch - don’t create the default case if another case matches (#12726)
This also simplifies the implementation of `NgSwitch`.

Closes #11297
Closes #9420
2016-11-07 12:22:36 -08:00
32fcec9fcb chore(npm): remove dependency on minimatch 2016-11-07 10:32:00 -08:00
78039b41d6 chore(build): remove unused build/util 2016-11-07 10:32:00 -08:00
89fd54e8e3 docs(url_tree):fix typo(UrlSegment path property's comment part -> path) (#12728) 2016-11-07 10:27:47 -08:00
77cbf7f2bb fix(closure): suppress two more closure compiler checks in codegen (#12698) 2016-11-04 15:18:05 -07:00
383f23b578 fix(animations): always trigger animations after the change detection check (#12713)
This patch ensures that animations are run outside of change detection
thus allowing for start and done callbacks to modify application data
without causing a cycle loop.

Closes #12713
2016-11-04 15:15:27 -07:00
2a3f4d7b17 refactor: kill MapWrapper 2016-11-04 13:27:38 -07:00
ec92f4b198 refactor: remove keys() and values() from MapWrapper 2016-11-04 13:27:38 -07:00
121e5080aa fix(http): preserve header case when copying headers (#12697) 2016-11-04 13:26:38 -07:00
fe1d0e29c5 feat(UpgradeComponent): add support for require
This commit also adds/improves/fixes some `UpgradeComponent` tests.
2016-11-04 11:16:28 -07:00
469010ea8e feat(UpgradeComponent): add/improve support for lifecycle hooks
Add support for the `$postDigest()` and `$onDestroy()` lifecycle hooks.
Better align the behavior of the `$onChanges()` and `$onInit()` lifecycle hooks
with Angular 1.x:

- Call `$onInit()` before pre-linking.
- Always instantiate the controller before calling `$onChanges()`.
2016-11-04 11:16:28 -07:00
f0cdb428f5 fix(compiler): don't convert undefined to null literals (#11503)
Fixes #11493
2016-11-04 10:55:21 -07:00
051d74802a fix(core): ensure that component views that have no bindings recurse into nested components / view containers. 2016-11-04 10:50:27 -07:00
f2bbef3e33 fix(core): allow to query content of templates that are stamped out at a different place
Previously, if a `TemplateRef` was created in a `ViewContainerRef`
at a different place, the content was not query able at all.

With this change, the content of the template can be queried
as if it was stamped out at the declaration place of the template.

E.g. in the following example, the `QueryList<ChildCmp>` will
be filled once the button is clicked.

```
@Component({
  selector: ‘my-comp’,
  template: ‘<button #vc (click)=“createView()”></button>’
})
class MyComp {
  @ContentChildren(ChildCmp)
  children: QueryList<ChildCmp>;

  @ContentChildren(TemplateRef)
  template: TemplateRef;

  @ViewChild(‘vc’, {read: ViewContainerRef})
  vc: ViewContainerRef;

  createView() {
    this.vc.createEmbeddedView(this.template);
  }
}

@Component({
  template: `
<my-comp>
  <template><child-cmp></child-cmp></template>
</my-comp>
`
})
class App {}
```

Closes #12283
Closes #12094
2016-11-04 10:50:27 -07:00
80d36b8db4 docs(CONTRIBUTING.md): fix stackoverflow broken link url (#12705) 2016-11-04 10:21:11 -07:00
e3687706c7 refactor(compiler): minor cleanup 2016-11-03 16:29:51 -07:00
648ce5981b perf(core): don’t use DomAdapter nor zone for regular events 2016-11-03 16:29:51 -07:00
9c23884da4 perf(compiler): introduce direct rendering
This allows to attach / detach embedded views and projected nodes
in a faster way.
2016-11-03 16:29:51 -07:00
d708a8859c perf(platform-browser): don’t use DomAdapter any more
But use the DOM apis directly.
This also creates a separate `ServerRenderer` implementation
for `platform-server` as it previously reused the `BrowserRenderer`.
2016-11-03 16:29:51 -07:00
9ddf9b3d3d fix(router): advance a route only after its children have been deactivated (#12676)
Closes #11715
2016-11-03 16:26:10 -07:00
69f006cd89 docs(change_detection): fix typo(ChangeDetectorStatus enum comment CheckedOnce -> CheckOnce) (#12683) 2016-11-03 11:23:20 -07:00
4aaae3eada docs(common): fix a typo in ngStyle API docs 2016-11-03 10:27:05 -07:00
2e78b76fcf fix(router): resolve guard observables on the first emit (#10412) 2016-11-02 21:56:04 -07:00
b2cf379d1c fix(enableDebugTools): create AngularTools by merging into context.ng (#12003)
When using `enableDebugTools` the tools are merged into `context.ng` to prevent `ng.probe` and `ng.coreTokens` from being clobbered.

Fixes #12002
2016-11-02 21:55:49 -07:00
e25baa08b3 fix(router): correctly export concatMap operator in es5 (#12430) 2016-11-02 21:55:02 -07:00
7103754178 fix(closure): suppress closure compiler suspiciousCode check in codegen (#12666) 2016-11-02 21:11:30 -07:00
1a069e8372 refactor(compiler): cleanups 2016-11-02 20:58:48 -07:00
0fc11a43f1 perf(core): use array.push / array.pop instead of splice if possible 2016-11-02 20:58:48 -07:00
0e3d655220 refactor(compiler): remove view factories, use view classes directly 2016-11-02 20:58:48 -07:00
7c5cc9bc41 refactor(compiler): initialize RenderComponentType eagerly
This moves the usage of `APP_ID` into the `DomRenderer`.
2016-11-02 20:58:48 -07:00
5f1dddc5d0 refactor(compiler): cleanups 2016-11-02 17:06:27 -07:00
20a4f9923f refactor(compiler): remove view.parentInjector 2016-11-02 17:06:27 -07:00
e7c00be19d refactor(compiler): rename AppElement into ViewContainer 2016-11-02 17:06:27 -07:00
74ede9aa9b refactor(core): don’t store view factory in TemplateRef
Instead, generate `createEmbeddedView`.
2016-11-02 17:06:27 -07:00
d1035da85c refactor(compiler): don’t use AppElements for creating component views 2016-11-02 17:06:27 -07:00
13533d2a30 refactor(compiler): remove AppElement.initComponent 2016-11-02 17:06:27 -07:00
953cb50fa5 chore(release): cut v2.2.0-rc.0 2016-11-03 00:28:29 +01:00
3fffcf6645 chore: update changelog 2016-11-02 12:34:21 -07:00
d509ee078b fix(router): reset URL to the stable state when a navigation gets canceled
Closes #10321
2016-11-02 12:25:23 -07:00
8e221b826f fix(router): routerLink should not prevent default on non-link elements 2016-11-02 12:25:23 -07:00
830a780cb3 fix(router): CanDeactivate receives a wrong component
Closes #12592
2016-11-02 12:25:23 -07:00
6fda97287e fix(compiler): support multiple components in a view container 2016-11-01 14:21:40 -07:00
234c5599f1 refactor(compiler): remove unused constructor query support 2016-11-01 11:29:15 -07:00
f6710fefeb refactor(compiler): make view.disposable array null if empty 2016-11-01 11:29:15 -07:00
bda1909ede refactor(compiler): remove view.rootNodes and view.projectableNodes
They are replaced by generated visitor functions `view.visitRootNodes` / `view.visitProjectableNodes`.
2016-11-01 11:29:15 -07:00
b3e3cd3add refactor(compiler): inline view.contentChildren 2016-11-01 11:29:14 -07:00
e5fdf4c70a refactor(compiler): inline view.viewChildren in generated code 2016-11-01 11:29:14 -07:00
97471d74b6 refactor(compiler): remove unused subscriptions in view 2016-11-01 11:29:14 -07:00
1de04b23b1 fix(router): call data observers when the path changes 2016-11-01 11:28:43 -07:00
a178bc6c83 fix(compiler): dedupe NgModule declarations, …
This is important so that we don’t generate things multiple times.
2016-10-31 14:43:50 -07:00
642c1db9ef fix(compiler): Don’t throw on empty property bindings
Closes #12583
2016-10-31 14:43:50 -07:00
579deeb9c5 style(platform-browser): clean up hammer gestures 2016-10-31 14:43:05 -07:00
bad58824a0 refactor(playground): update gestures playground to use latest hammer.js 2016-10-31 14:43:04 -07:00
5494169fb4 style: make internal members accessibility explicit 2016-10-31 14:25:53 -07:00
5a3d7a62a2 style: merge imports from the same modules 2016-10-31 14:25:53 -07:00
a382d6dd20 style: add missing semicolons 2016-10-31 14:25:53 -07:00
52bf188b8f style: add missing copyright headers 2016-10-31 14:25:53 -07:00
6f412bb449 chore(lint): extend linting to all modules and tools 2016-10-31 14:24:27 -07:00
e9fd8645ed fix(core): improve error when multiple components match the same element
Closes #7067
2016-10-31 11:28:03 -07:00
a0aecac0e5 chore(lint): replace enforce-copyright-header rule with the native equivalent 2016-10-31 11:27:35 -07:00
938ed1c76d chore(lint): deduplicate tslint dependency 2016-10-31 11:27:34 -07:00
eb8288f76c chore(package): remove unused lodash and sorted-object 2016-10-31 11:26:59 -07:00
0936ceeab4 chore(npm): clean up clean-shrinkwrap script 2016-10-31 11:26:59 -07:00
e0ad413a8e style(tests): clean up testing_public_spec (#11452) 2016-10-31 11:26:38 -07:00
3045d02b9a docs(pipes): minor fix and improvements 2016-10-31 12:39:21 +01:00
e86573bac8 chore(lint): replace gulp check-task with tslint no-jasmine-focus rule
fixes #11800
2016-10-28 15:53:15 -07:00
0a94845435 chore(lint): replace duplicate-module-import rule with no-duplicate-imports 2016-10-28 15:53:15 -07:00
262bd23b84 chore(lint): add vrsource tslint rules dependency 2016-10-28 15:53:15 -07:00
7b8dae19af refactor(facade): cleanup Intl facade 2016-10-28 15:52:52 -07:00
7c16ef942e feat(core): add the find method to QueryList 2016-10-28 15:34:47 -07:00
a318b57257 refactor(core): removed extraneous interface from QueryList test 2016-10-28 15:34:47 -07:00
fe47e6b783 fix(router): rerun resolvers when url changes
Closes #12603
2016-10-28 15:17:00 -07:00
091c390032 fix(router): run navigations serialy
Closes #11754
2016-10-28 14:56:08 -07:00
e391cacdf9 fix(compiler): don’t double bind functions
This fixes a performance regressions introduced by 178fb79b5c.

Also makes properties in the directive wrapper private
so that closure compiler can minify them better.
2016-10-28 11:17:12 -07:00
32feb8a532 refactor(compiler): generate host listeners in DirectiveWrappers
Part of #11683
2016-10-27 16:09:01 -07:00
a664aba2c9 build: ensure necessary symlinks created on windows
Bash scripts create and tear down symlinks on Windows. These use the
packages.txt file as input to identify the symlink locations. The
scripts ignored the last line in packages.txt if it didn't end with a
newline. Also, one location was missing. Resolve both issues.

Closes #12422
2016-10-27 12:13:39 -07:00
d520fae70e refactor(upgrade): spec cleanup 2016-10-27 12:12:55 -07:00
fa93fd672e fix(upgrade): silent bootstrap failures
fixes #12062
2016-10-27 12:12:54 -07:00
f4be2f907d docs(changelog): fix changelog title 2016-10-27 20:38:56 +02:00
2ea27a76d3 docs(changelog): update changelog with changes in v2.1.2 2016-10-27 20:30:48 +02:00
ec0acf9a1b chore(release): cut the 2.2.0-beta.0 release 2016-10-27 18:28:07 +02:00
a26dd28bdb refactor(upgrade): re-export the new static upgrade APIs on new entry
Add upgrade-static.umd.js bundles
This allows depending on it without getting a transitive dependency on compiler.

BREAKING CHANGE:

Four newly added APIs in 2.2.0-beta:
downgradeComponent, downgradeInjectable, UpgradeComponent, and UpgradeModule
are no longer exported by @angular/upgrade.
Import these from @angular/upgrade/static instead.
2016-10-26 15:14:22 -07:00
7742ec00e7 fix: remove double exports of template_ast 2016-10-26 15:14:00 -07:00
2b5c983c13 docs(reset): change semi-colon to colon in code example
The first code example for the reset function was invalid as it has a semi-colon instead of a colon for the last property in the json object.  Change the semi-colon to a colon.

Closes https://github.com/angular/angular/issues/12531
2016-10-26 14:56:57 -07:00
ef153649b3 fix(compiler-cli): fix types 2016-10-26 14:56:27 -07:00
d321b0ebf5 fix(selectors): use Maps instead of objects 2016-10-26 14:55:59 -07:00
b4265e0685 fix(xsrf): overwrite already set xsrf header 2016-10-26 14:55:24 -07:00
178fb79b5c refactor(compiler): move host properties into DirectiveWrapper
Part of #11683
2016-10-26 14:32:24 -07:00
5a7a58b1e0 refactor(compiler): make arguments in InlineArray optional. 2016-10-26 14:32:24 -07:00
f66ac821a2 refactor(compiler): extract createCheckBindingStmt into compiler_util
Part of #11683
2016-10-26 14:32:24 -07:00
fe299f4dfc refactor(compiler): minor cleanups 2016-10-26 14:32:24 -07:00
4cac650675 refactor(compiler): extract expression evaluation and writing to renderer from view_compiler
This is needed to that `DirectiveWrapper`s can also use them later on.

Part of #11683
2016-10-26 14:32:24 -07:00
cb7643ccea refactor(compiler): introduce ClassBuilder.
Part of #11683
2016-10-26 14:32:23 -07:00
faa3478514 refactor(compiler): set element attributes via one call
This makes the cost of using directives that have host attributes
smaller.

Part of #11683
2016-10-26 14:32:23 -07:00
bc3f4bc816 refactor(compiler): extract BindingParser
Needed so that we can parse directive host bindings independent of templates.

Part of #11683
2016-10-26 14:32:23 -07:00
c9f58cf78c feat(router): export routerLinkActive w/ isActive property 2016-10-26 14:08:22 -07:00
6ccbfd41dd fix(router): preserve resolve data
Closes #12306
2016-10-26 13:53:00 -07:00
7d2554baa1 tests(router): add a test showing how to handle resovle errors 2016-10-26 13:52:59 -07:00
52a853e257 fix(router): change router not to deactivate aux routes when navigating from a componentless routes 2016-10-26 13:52:59 -07:00
8f2fa0f766 fix(router): disallow component routes with named outlets
Closes #11208, #11082
2016-10-26 13:52:59 -07:00
fc60fa790c fix(router): add a test to make sure canDeactivate guards are called for aux routes
Closes #11345
2016-10-26 13:52:58 -07:00
b74185369f fix(router): canDeactivate guards are not triggered for componentless routes
Closes #12375
2016-10-26 13:52:58 -07:00
7221632228 fix(CompilerCli): assert that all pipes and directives are declared by a module 2016-10-25 18:17:18 -07:00
02f1222a8d docs(common): minor corrections/improvements for NgClass (#12327) 2016-10-25 00:12:09 +02:00
c27ce7318f doc(compiler-cli): align example with style guide (#12414)
See The Angular Style Guide, [Section 2.2 - Separate File Names with Dots and Dashes](https://angular.io/docs/ts/latest/guide/style-guide.html#!#02-02)
2016-10-25 00:10:03 +02:00
a838aba756 fix(compiler): walk third party modules (#12453)
fixes #11889
fixes #12428
2016-10-24 22:28:23 +02:00
bfc97ff2cd refactor(i18n): extract Extractor from extract_i18n (#12417)
I put an extractor into your extract so you can extract while you
extract.

This allows integrators to call Extractor as a library. Also refactors
Extractor a bit so that callers need fewer arguments or arguments that
are at the right semantic level.

The refactoring causes no function change.
2016-10-21 15:17:57 -07:00
57051f01ce refactor: remove most facades (#12399) 2016-10-21 15:14:44 -07:00
e319cfefc3 docs(changelog): fix minor typo (#12429) 2016-10-21 14:27:07 -07:00
444014ad96 docs(changelog): add 2.1.1 changelog 2016-10-20 15:49:59 -07:00
867494a060 fix(compiler): don't access view local variables nor pipes in host expressions (#12396)
Fixes #12004
Closes #12071
2016-10-20 15:24:58 -07:00
69ad99dca6 chore(release): cut the 2.2.0-beta.0 release and add changelog 2016-10-20 14:36:46 -07:00
da5fc696bb fix(router): do not update primary route if only secondary outlet is given (#11797) 2016-10-20 10:59:08 -07:00
b44b6ef8f5 fix(router): module loader should start compiling modules when stubbedModules are set (#11742) 2016-10-20 10:58:53 -07:00
0f21a5823b cleanup(router): add a test verifying than NavigationEnd is not emitted after NavigationCancel 2016-10-20 10:56:12 -07:00
5ae6915600 fix(router): fix lazy loading triggered by redirects from wildcard routes
Closes #12183
2016-10-20 10:56:12 -07:00
8b9ab44eee feat(router): add support for ng1/ng2 migration (#12160) 2016-10-20 10:44:44 -07:00
b0a03fcab3 refactor(compiler): introduce directive wrappers to generate less code
- for now only wraps the `@Input` properties and calls
  to `ngOnInit`, `ngDoCheck` and `ngOnChanges` of directives.
- also groups eval sources by NgModule.

Part of #11683
2016-10-20 10:41:43 -07:00
c951822c35 refactor(compiler): don’t use the OfflineCompiler in extract_i18n 2016-10-20 10:41:43 -07:00
acda82c1ed refactor(compiler): remove private exports
All of `@angular/compiler` is private, so we can export
everything we need directly.
2016-10-20 10:41:43 -07:00
a8815d6b08 chore(ci): re-enable browserstack tests in ci 2016-10-20 10:01:51 -07:00
d6791ff0e0 feat(ngUpgrade): add support for AoT compiled upgrade applications
This commit introduces a new API to the ngUpgrade module, which is compatible
with AoT compilation. Primarily, it removes the dependency on reflection
over the Angular 2 metadata by introducing an API where this information
is explicitly defined, in the source code, in a way that is not lost through
AoT compilation.

This commit is a collaboration between @mhevery (who provided the original
design of the API); @gkalpak & @petebacondarwin (who implemented the
API and migrated the specs from the original ngUpgrade tests) and @alexeagle
(who provided input and review).

This commit is an starting point, there is still work to be done:

* add more documentation
* validate the API via internal projects
* align the ngUpgrade compilation of A1 directives closer to the real A1
  compiler
* add more unit tests
* consider support for async `templateUrl` A1 upgraded components

Closes #12239
2016-10-19 15:27:49 -07:00
a2d35641e3 chore(tslint.json): semicolon rule expects an array 2016-10-19 22:38:14 +01:00
76dd026447 refactor: remove some facades (#12335) 2016-10-19 13:42:39 -07:00
0ecd9b2df0 chore(ci): make browserstack tests optional until they are fixed 2016-10-19 10:41:00 -07:00
0e9503b500 feat(forms) range values need to be numbers instead of strings (#11792) 2016-10-19 10:12:13 -07:00
f77ab6a2d2 feat(datePipe): support narrow forms for month and weekdays (#12297)
Closes #12294
2016-10-19 10:05:13 -07:00
97bc97153b feat(forms): add ng-pending CSS class during async validation (#11243)
Closes #10336
2016-10-19 09:56:31 -07:00
445e5922ec feat(forms): make 'parent' a public property of 'AbstractControl' (#11855) 2016-10-19 09:55:50 -07:00
b9fc090143 feat(forms): Added emitEvent to AbstractControl methods (#11949)
* feat(forms): Added emitEvent to AbstractControl methods

* style(forms): unified named parameter
2016-10-19 09:54:54 -07:00
592f40aa9c feat(forms): add hasError and getError to AbstractControlDirective (#11985)
Allows cleaner expressions in template-driven forms.

Before:

    <label>Username</label><input name="username" ngModel required #username="ngModel">
    <div *ngIf="username.dirty && username.control.hasError('required')">Username is required</div>

After:

    <label>Username</label><input name="username" ngModel required #username="ngModel">
    <div *ngIf="username.dirty && username.hasError('required')">Username is required</div>

Fixes #7255
2016-10-19 09:49:02 -07:00
24facdea2d feat(benchmark): add large form benchmark
This benchmark tracks the generated file size for large forms
as well as the time to create and destroy many form fields.
2016-10-19 09:39:16 -07:00
aa2d3372a5 fix(benchmarks): fix method name in targetable spec 2016-10-19 09:39:16 -07:00
bf60418fdc feat(forms): Validator.pattern accepts a RegExp (#12323) 2016-10-19 09:37:54 -07:00
cca4a5c519 fix(compiler): don't redeclare a var in the same scope (#12386)
This is not allowed by Closure Compiler.
2016-10-18 20:28:30 -07:00
6e5f8b59b3 fix(animations): generate aot code for animation trigger output events (#12291)
Closes #11707
Closes #12291
2016-10-18 17:16:51 -07:00
8409b65153 fix(http): make normalizeMethodName optimizer-compatible. (#12370)
`normalizeMethodName` reflectively accessed the RequestMethod enum. With a smart
optimizer, properties from the enum could be removed or renamed, and so user
code just passing in e.g. 'PATCH' might not work. This change fixes the code to
be more explicit and avoids the optimizer issue.
2016-10-18 11:21:54 -07:00
38e2203b24 refactor(core): delete unused reflector code 2016-10-17 23:17:34 -07:00
bd1dcb5f11 fix(core): fix decorator defalut values 2016-10-17 23:17:34 -07:00
3993279527 fix(core): fix property decorators
fixes #12224
2016-10-17 23:17:34 -07:00
bf1e2613b2 refactor(core): cleanup decorators 2016-10-17 23:17:34 -07:00
f7db0668d1 refactor(core): simplify & cleanup reflection 2016-10-17 23:17:34 -07:00
27d76776b8 fix(router): correctly export filter operator in es5 (#12286) 2016-10-17 23:06:19 -07:00
8603d9c269 refactor(http): use Http.request for all http shorthand methods (#12319) 2016-10-17 23:04:25 -07:00
d55f747858 docs(router): attribute notation for string paths (#12205)
Either bind an expression or use the attribute notation.
The mixed way `[routerLink]="/path"` won't work.
Prefer the attribute notation for string-only paths
2016-10-17 22:53:55 -07:00
52de0fa558 docs(CONTRIBUTING.md): fix typo (reproductions --> reproduction) (#12230) 2016-10-17 22:52:44 -07:00
d61ecf0663 docs(NgSwitch): fix mismatched tags in example (#12270) 2016-10-17 22:51:56 -07:00
5a9c5f28b8 docs(CHANGELOG.md): remove incorrect link (#12259) 2016-10-17 22:51:44 -07:00
15fc5dd7ee test(forms): added missing selfOnly tests (#12317) 2016-10-17 22:51:13 -07:00
a5419608e0 docs(ngIf): minor improvements 2016-10-17 22:50:12 -07:00
5f95bf1dd2 refactor(common): remove redundant type 2016-10-17 22:50:12 -07:00
33c8948fd3 refactor(animations): ensure animation data-structures are created only when used
Closes #12250
2016-10-14 15:43:41 -07:00
606e51881a perf(benchmarks): update ng2-switch to match ng2
- use the ~same template layout (text nodes),
- use trackBy

both benchmark now show about the same perfs.
2016-10-12 17:11:46 -07:00
fdf4309b50 perf(common): optimize NgSwitch default case
relates to #11297
2016-10-12 17:11:46 -07:00
af996ef0c4 docs(changelog): fix typo in code name, ouch! 2016-10-12 14:05:48 -07:00
68d2dfdd2a docs(changelog): tweak the change log and group all the 2.1 changes together 2016-10-12 13:54:21 -07:00
07bd4b0630 chore: bump version number and generate CHANGELOG (#12247) 2016-10-12 13:19:31 -07:00
df1718d624 fix(compiler): allow WS as <ng-content> content (#12225) 2016-10-12 07:58:06 -07:00
17e3410d98 Form submit event (#11989)
* feat(forms): ngSubmit event exposes $event from original submit event as local variable

Modify NgForm directive and FormGroup directive to expose the original submit event as $event in the ngSubmit event. Modify docs to reflect changes.

This resolves #10920.

* refactor: code cleanup
2016-10-11 15:49:36 -07:00
5effc330ed feat(upgrade): compilerOptions in bootstrap (#10575) 2016-10-11 15:48:08 -07:00
3df00828d7 docs(router): fix CanActivateChild API docs (#12128)
fixes #12127
2016-10-11 15:47:57 -07:00
8c477b2f45 fix(compiler-cli): don't clone static symbols when simplifying annotation metadata (#12158) 2016-10-11 15:47:44 -07:00
7787771aba refactor(core): cleanup decorators.ts (#12161) 2016-10-11 15:47:20 -07:00
7275e1beb3 refactor(compiler): add optional visit() to TemplateAstVisitor (#12209) 2016-10-11 15:46:11 -07:00
12ba62e5e2 refactor(compiler): expose template parser phases (#12210) 2016-10-11 15:45:27 -07:00
e6e007e2f1 refactor(core): cleanup SpyObject (#12221) 2016-10-11 15:44:48 -07:00
91dd138fa5 docs(animations): document :enter and :leave transition aliases (#12222) 2016-10-11 15:44:38 -07:00
d972d82354 refactor: simplify isPresent(x) ? x : y to x || y (#12166)
Closes #12166
2016-10-10 09:20:58 -07:00
bdcf46f82e refactor(compiler): improve types, misc 2016-10-10 09:20:58 -07:00
79e1c7b807 refactor(upgrade): unify spec code (#12190)
- replace all variable declarations using 'var' by 'const' or 'let'
- replace es5 function declaration by arrow function where applicable
2016-10-10 09:18:33 -07:00
d22eeb70b8 fix(forms): allow optional fields with pattern and minlength validators (#12147) 2016-10-10 09:17:45 -07:00
aa92512ac6 fix(compiler): properly shim :host:before and :host(:before) (#12171)
fixes #12165
2016-10-10 09:15:15 -07:00
f782b08f58 docs: Minor typo fix (#12151) 2016-10-10 09:14:35 -07:00
4202936bbf refactor(compiler): add optional visit() to html AST Visitor (#12135) 2016-10-10 09:13:50 -07:00
e1faca6386 refactor(compiler): template element ast has endSourceSpan (#12138) 2016-10-10 09:12:05 -07:00
f5b0e22d35 docs(public_api): fix missing backtick 2016-10-07 17:23:08 -07:00
00693d70a2 docs: add PUBLIC_API.md 2016-10-07 14:29:16 -07:00
bcef5efffe fix(platform-browser-dynamic): mark platformBrowserDynamic as stable API (#12154)
Everyone building Angular apps need to use this api to bootstrap or AoT compile, so it can't be experimental.
2016-10-07 13:54:06 -07:00
13ecc140e8 fix(compiler): validate @HostBinding name (#12139)
relates to #7500
2016-10-07 13:53:53 -07:00
709a6dea06 refactor(compiler): attribute ast records span of the value (#12132) 2016-10-07 13:53:29 -07:00
16cfb88c00 refactor(compiler): refactor analyzeModules() out of OfflineCompiler (#12137) 2016-10-07 13:52:53 -07:00
efee6f5199 docs(saved-replies): order the replies as shown in github (#12153)
github sorts the replies by reply name.
2016-10-07 13:52:18 -07:00
2aa8aae76d docs(saved-replies): add document with saved replies for our issue tracker 2016-10-07 09:21:20 -07:00
afb4bd9ef6 refactor(NgZone): merge NgZoneImpl and NgZone (#12104) 2016-10-06 15:23:37 -07:00
d641c36a45 fix(compiler): interpolation expressions report the correct offset (#12125) 2016-10-06 15:22:10 -07:00
f4566f8128 fix(http): fix Headers initialization from Headers and Object (#12106) 2016-10-06 15:21:27 -07:00
a67c06708d fix(http): Headers.append should append to the list 2016-10-06 15:21:03 -07:00
d9d57d71dd refactor(http): move one Headers test inside the main describe 2016-10-06 15:21:03 -07:00
e06303a987 fix(router): improve error message (#12102) 2016-10-06 15:19:22 -07:00
40b92ddf21 fix(router): wildcards routes should support lazy loading
Closes #12024
2016-10-06 15:19:09 -07:00
1681e4f57f fix(router): parent resolve should complete before merging resolved data
Closes #12032
2016-10-06 15:19:09 -07:00
71b7654660 fix(compiler-cli): remove peerDependency on @angular/platform-server (#12122)
There is no runtime dependency from the compiler-cli on @angular/platform-server - it was most likely added to package.json by mistake.
2016-10-06 15:16:41 -07:00
eaaec6979c fix(compiler-cli): remove unused parse5 dependency from package.json
This was added in error or is an obsolete dependency. We don't need parse5 for the compiler-cli's runtime.
2016-10-06 15:16:22 -07:00
c587c63591 docs(changelog): fix mentions, backticks and a misplaced line ending (#12109)
* docs(changelog): fix mentions and backticks

`@page` and `@document` were both incorrectly linking to GitHub repositories.
`:enter` and `:leave` in the *Features* section were missing backticks.

* Fix misplaced line ending.
2016-10-06 15:12:41 -07:00
f50c1da4e2 fix(forms): properly validate blank strings with minlength (#12091) 2016-10-06 15:12:09 -07:00
0254ce1f6c refactor(core): simplify Reflector code, add types (#12099) 2016-10-06 15:11:16 -07:00
c9b765f5c0 refactor(compiler): module collector is reusable (#12095) 2016-10-06 15:10:44 -07:00
8c975ed156 refactor(facade): inline StringWrapper (#12051) 2016-10-06 15:10:27 -07:00
bb35fcb562 docs(contributing): remove references to Angular 2
It's just Angular.
2016-10-06 15:07:46 -07:00
57230b70a9 docs(contributing): update the "Submitting an Issue" section 2016-10-06 15:06:37 -07:00
43dc60ce4f docs(contributing): update "got a question or a problem" section
Inspired by: https://github.com/ng-bootstrap/ng-bootstrap#getting-help
2016-10-06 13:58:14 -07:00
230b3b73d8 chore(benchpress): fix the license (#12090)
It's not Apache MIT 2.0, that's a mishmash of Apache 2.0 and MIT
2016-10-06 10:24:01 -07:00
0b7dc2f9ff docs(RouterTestingModule) change modules to imports in example (#12118) 2016-10-06 10:22:39 -07:00
de1f44f51f fix(benchmarks): allow ng2_switch benchmark to be used with AoT. (#12124) 2016-10-06 10:22:08 -07:00
f1cfddf6d6 refactor(benchmarks): add index_aot to support AoT bootstrap. (#12105)
Note: This only make sure it can compile the AoT version, but does not yet use it in e2e tests.
2016-10-06 08:37:37 -07:00
ef621a2f00 docs(changelog): tweak changelog 2016-10-06 06:43:17 -07:00
df9761951b docs(changelog): added changelog for 2.1.0-rc.0 2016-10-05 16:48:22 -07:00
f786c560f1 doc(triage): add info about user pain, frequency and severity labels 2016-10-05 15:58:45 -07:00
c5557de3e7 doc(triage): correct existing incorrect info 2016-10-05 15:58:45 -07:00
ec3a5b54de docs(readme): remove incorrect download count badge
npm doesn't currently support download counts for scoped packages, so there is no replacement right now.
2016-10-05 11:37:28 -07:00
cf269d9ff4 refactor: add license header to JS files & format files (#12081) 2016-10-04 20:39:20 -07:00
5fa5ffb82a refactor(benchmarks): refactor to support AOT bootstrap in G3 (#12075) 2016-10-04 16:27:45 -07:00
4a57dcfd8d fix(forms): properly validate empty strings with patterns (#11450) 2016-10-04 16:14:23 -07:00
43923ffcf5 docs(traige): update triaging doc 2016-10-04 16:13:32 -07:00
50c37d45dc refactor: simplify arrow functions (#12057) 2016-10-04 15:57:37 -07:00
a63359689f fix(ShadowCss): fix attribute selectors in :host and :host-context (#12056)
Fix a regression introduced in #11917 while fixing #6249
2016-10-04 15:40:31 -07:00
43d3a84df3 Revert "refactor: add license header to JS files & format files (#12035)"
This reverts commit 8310c91823.
2016-10-04 14:06:41 -07:00
8310c91823 refactor: add license header to JS files & format files (#12035) 2016-10-04 13:15:49 -07:00
b64b5ece65 refactor(facade): Remove most of StringMapWrapper facade. (#12022)
This change mostly automated by
12012b07a2
with some manual fixes.
2016-10-03 16:46:05 -07:00
ed9c2b6281 fix(Header): preserve case of the first init, set() or append() (#12023)
fixes #11624
2016-10-03 15:27:56 -07:00
1cf5f5fa38 docs(NgModule): Fixed docs for NgModule.entryComponents (#12006)
* docs(NgModule): Corrected the wording of the documentation of `entryComponents`, fixed some minor grammar issues

* docs(NgModule): Remove redundant ComponentFactory mentions

* docs(NgModule): Restore ComponentFactory/ComponentResolver links
2016-10-03 10:19:03 -07:00
a32078f85e docs(DEVELOPER.md): fix typos on "Tests" section (#12029) 2016-10-02 14:19:47 -07:00
decd129a4d refactor(facade): remove DateWrapper (#12027) 2016-10-02 14:12:14 -07:00
c3c9ecb302 text(offline compiler): fix expected output 2016-09-30 17:59:43 -07:00
af520947aa test(AstSerializer): fix serializing void tags 2016-09-30 17:59:43 -07:00
040bf57966 fix(xlif): fix <x> ctype names
fixes #12000
see http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#ctype
2016-09-30 17:59:43 -07:00
65a60b7456 style(I18N): Carriage returns in serialized files 2016-09-30 17:59:43 -07:00
756ef09d12 docs(gh): try to improve the issue template (#11891) 2016-09-30 16:40:56 -07:00
9316f95467 fix(ShadowCss): support @page and @document CSS rules (#11878)
fixes #11860
2016-09-30 16:26:24 -07:00
83d94b7504 fix(ShadowCss): support quoted attribute values
fixes #6085
2016-09-30 14:37:41 -07:00
a121136fae refactor(ShadowCss): add missing types 2016-09-30 14:37:41 -07:00
a6bb84e02b fix(ShadowCss): fix :host(tag) and :host-context(tag)
fixes #11972
2016-09-30 14:37:41 -07:00
3898dc488e fix(BrowserAdapter): correctly removes styles on IE
fixes #7916
2016-09-30 11:18:17 -07:00
ca3f9926f9 refactor(BrowserAdapter): cleanup 2016-09-30 11:18:17 -07:00
1c012a035f refactor(CssSelector): misc cleanup 2016-09-30 11:06:24 -07:00
38c5304b7f docs(CssSelector): [name*=value] is not supported
fixes #6042
2016-09-30 11:06:24 -07:00
9a049be67f feat(Parse5): update to the latest version 2.2.1
fixes #6237
2016-09-30 10:46:49 -07:00
2045c9e8ee docs: update docs for ng2_ftl benchmark 2016-09-30 10:42:21 -07:00
6c4ec05a4a fix(ShadowCss): support [attr="value with space"]
fixes #6249
2016-09-30 10:27:35 -07:00
f7bfda31ff refactor(ShadowCss): cleanup 2016-09-30 10:27:35 -07:00
a92b573309 test(DirectiveResolver): test that a prop can have both @Input and @HostBinding 2016-09-30 10:08:52 -07:00
4fd13d71c8 refactor(DirectiveResolver): cleanup 2016-09-30 10:08:52 -07:00
bf7b82b658 fix(UrlSearchParams): change a behavior when a param value is null or undefined (#11990) 2016-09-30 09:57:26 -07:00
c143fee849 refactor(routerLinkActive): optimised routerLinkActive active check code (#11968)
Modify routerLinkActive to optimise performance by removing unnecessary iteration. By replacing Array.reduce with Array.some, the loop will break when it finds an active link. Useful if used on the parent of a large group of routerLinks. Furthermore, if a RouterLink is active it will not check the RouterLinkWithHrefs.
2016-09-30 09:42:54 -07:00
0286956107 refactor(facade): Inline isBlank called with object-type argument (#11992) 2016-09-30 09:26:53 -07:00
e884f4854d feat(animations): provide aliases for :enter and :leave transitions (#11991) 2016-09-30 09:15:56 -07:00
df1822fc2a benchmarks: add ng2_ftl and ng2_switch_ftl benchmarks (#11963)
These benchmarks take the output of AoT
and manually tweaks it to explore possible
future changes to the compiler to produce
this output directly.
2016-09-30 09:09:31 -07:00
42b4b6d21b fix(upgrade): bind optional properties when upgrading from ng1 (#11411)
Previously, optional properties of a directive/component would be wrongly mapped and thus ignored.

Closes #10181
2016-09-29 09:45:28 -07:00
36bc2ff269 docs(forms): Added FormControl initialization information (#11948) 2016-09-28 13:59:08 -07:00
1564042fe8 fix(ngc): allow ReflectorHost passed as argument to CodeGenerator#create (#11951) 2016-09-27 17:12:57 -07:00
41c8c30973 chore(lint): remove unused imports (#11923)
This was done automatically by tslint, which can now fix issues it finds.
The fixer is still pending in PR https://github.com/palantir/tslint/pull/1568
Also I have a local bugfix for https://github.com/palantir/tslint/issues/1569
which causes too many imports to be deleted.
2016-09-27 17:12:25 -07:00
61129fa12d fix(compiler): move detection of unsafe properties for binding to ElementSchemaRegistry (#11378) 2016-09-27 17:10:02 -07:00
3a5b4882bc fix(compiler): Do not embed templateUrl in view factories in non-debug mode. (#11818)
Fixes #11117.
2016-09-27 17:09:44 -07:00
425c1e6042 refactor: remove dead code 2016-09-27 16:13:09 -07:00
58605cf350 refactor(facade): remove useless facades 2016-09-27 16:13:09 -07:00
34b31dea7c docs(upgrade): rename undeclared Ng2 to Ng2Component (#11950) 2016-09-27 16:11:41 -07:00
a241ab7c07 (docs): removing addProvider from UpgradeAdapter (#11934)
The `addProvider` function in the `UpgradeAdapter` was deprecated in this [commit](d21331e902 (diff-77163e956a7842149f583846c1c01651)) and has been removed in final. Given this, the documentation for downgrading ng2 providers for use in ng1 is invalid.
2016-09-27 10:10:45 -07:00
745e10e6d2 docs(router_config): add missing quote (#11925) 2016-09-27 10:10:12 -07:00
33340dbbd1 docs: remove outdated docs (#11875) 2016-09-24 08:23:28 +09:00
52812c08e2 chore(CHANGELOG): fix wrong issue link (#11871) 2016-09-24 07:13:24 +09:00
52f5ae1961 chore(compiler): followup fix for PR#11846 (#11870)
Original PR set [] to any, but any[], is a tighter type and still
works for SNC enabled consumers of the emit.
2016-09-24 07:13:05 +09:00
9be895b6da docs(ExceptionHandler): fix API docs (#11772)
fixes #11769
2016-09-24 07:05:43 +09:00
9f1c82537e ci(travis): increase node's heap size to prevent OOM on travis (#11869) 2016-09-24 06:04:29 +09:00
5ab5cc77bb Fix(http): invalidStateError if response body without content (#11786)
Fix(http): invalidStateError if response body without content
If the responseType has been specified and other than 'text', responseText throw an InvalidStateError exception

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

Unit Test to prevent invalidStateError
2016-09-24 05:44:01 +09:00
f1b6c6efa1 refactor(animations): ensure animation input/outputs are managed within the template parser (#11782)
Closes #11782
Closes #11601
Related #11707
2016-09-24 05:37:04 +09:00
45ad13560b docs(changelog): remove info about an internal change 2016-09-23 12:02:56 -07:00
2045268cec chore(release): v2.1.0-beta.0 2016-09-23 11:41:35 -07:00
fb1076b44a docs(changelog): release notes for 2.1.0-beta.0 2016-09-23 11:37:28 -07:00
6fc46526ae fix(upgrade): allow attribute selectors for components in ng2 which are not part of upgrade (#11808)
fixes #11280
2016-09-24 02:47:16 +09:00
3ef5ede6d6 chore(compiler): emit ([] as any[]) instead of purely []. (#11846)
In SNC mode `[]` has type of never[], so we cast it to any[] to
typecheck correctly see
https://github.com/Microsoft/TypeScript/issues/10479.

This is temporary workaround, until we fully
migrate the framework to TS 2.0 and strictNullChecks.
2016-09-24 02:21:59 +09:00
136621ebc9 docs(Component): API docs for .encapsulation and .interpolation 2016-09-22 11:01:16 -07:00
f23b22a0f4 refactor: misc cleanup 2016-09-22 11:01:16 -07:00
0ca971c5bd refactor(common): cleanup (#11668) 2016-09-22 10:34:00 -07:00
3a6fcee0e6 docs(core): mark TestBed as stable api and add preliminary docs (#11767)
TestBed was accidentaly ommited from the 'stable' api list during the API sweep before final. We do consider it to be stable.
2016-09-22 10:32:17 -07:00
8972137c29 docs(contributing): remove preview references (#11795) 2016-09-22 10:31:56 -07:00
cc6481077f ci(BrowserStack): add Safari 10 (#11796) 2016-09-22 10:31:38 -07:00
c041b93418 refactor(TemplateParser): clearer error message for on* binding (#11802)
fixes #11756
2016-09-22 10:31:18 -07:00
bc33765913 chore(ISSUE_TEMPLATE): update Angular version field (#11821) 2016-09-22 10:29:12 -07:00
31dce72b7b fix(router): update the router not to reset router state when updating root component (#11799) 2016-09-21 11:37:43 -07:00
212f8dbde7 fix(forms): disable all radios with disable() 2016-09-20 15:00:12 -07:00
44da4984f9 fix(forms): support unbound disabled in ngModel (#11736) 2016-09-20 14:55:47 -07:00
d95344430c chore(zone.js): update to 0.6.25 (#11725) 2016-09-20 14:55:07 -07:00
131626fc61 fix(compiler): Safe property access expressions work in event bindings (#11724) 2016-09-20 14:54:53 -07:00
676bb0fa7d feat(router): update dts files 2016-09-20 14:53:52 -07:00
5a849829c4 feat(router): add router preloader to optimistically preload routes 2016-09-20 14:53:52 -07:00
671f73448c refactor: misc cleanup (#11654) 2016-09-19 17:15:57 -07:00
51d73d3e4e fix(forms): make setDisabledState optional for reactive form directives (#11731)
Closes #11719
2016-09-19 16:26:33 -07:00
bf81b06a28 docs(forms): add select control examples (#11728) 2016-09-19 16:25:33 -07:00
0621f07a2c refactor: misc cleanup 2016-09-19 16:24:31 -07:00
1225ecfb14 chore(node): allow current node version
node current is 6.6.0
see https://github.com/nodejs/LTS#lts_schedule
2016-09-19 16:24:31 -07:00
5509453e72 refactor(common): pipe code cleanup 2016-09-19 16:19:28 -07:00
70488ed382 fix(OfflineCompiler): support older TS versions (#11734) 2016-09-19 15:36:25 -07:00
03aedbe54b fix(OfflineCompiler): Do not provide I18N values when they're not specified
fixes #11643
2016-09-19 10:44:33 -07:00
8395aab25d refactor(OfflineCompiler): cleanup 2016-09-19 10:44:33 -07:00
0dc15eb64a fix(ContentChild): query descendants by default
fixes #1645
2016-09-19 10:42:46 -07:00
cba885a1fb refactor: code cleanup 2016-09-19 10:42:46 -07:00
fa4723a208 docs(forms): add radio button examples (#11676) 2016-09-19 10:41:20 -07:00
5bf08b886f build(npm): update fsevents to 1.0.14 (#11686)
fixes #11685
2016-09-18 16:04:46 -07:00
89802316b9 docs(injector): API docs - remove lone code-block backticks (#11653)
The triple backticks in the markdown of the API entry are unbalanced.
2016-09-18 16:04:04 -07:00
2300c23332 fix(docs): Fixed wording for NgModule schemas (#11620) 2016-09-18 16:03:43 -07:00
fa39965a37 build(gulp): fail on ddescribe / iit left in tests
Closes #10524
2016-09-18 16:01:50 -07:00
115f0fa842 refactor(gulpfile): cleanup, add comments 2016-09-18 16:01:50 -07:00
734b8b8c13 fix(compiler): [attribute~=value] selector (#11696)
Change the seperator regular expression to ignore tildes which are followed by an equal sign.

Closes #9644
2016-09-18 15:58:19 -07:00
54b41f57be docs(Host): fix the API example (#11684)
fixes #11681
2016-09-18 15:56:13 -07:00
df4254ae89 refactor(facade): move isPromise to core private (#10573) 2016-09-18 15:55:08 -07:00
14ee75924b fix(common): fix ngOnChanges signature of NgTemplateOutlet directive 2016-09-15 11:00:30 -07:00
bd4045b6e7 fix(MetadataResolver): throw Component.moduleId is not a string
fixes #11590
2016-09-15 10:57:37 -07:00
255099aa61 refactor(MetadataResolver): cleanup 2016-09-15 10:57:37 -07:00
1c24096650 refactor(benchpress): add more types 2016-09-15 10:17:10 -07:00
32aeb1052d refactor(benchpress): normalize phase b into B and e into E
This simplifies the perflog metrics and prevents future errors.
2016-09-15 10:17:10 -07:00
838d4bbf6c fix(benchpress): support measuring scriptTime and other metrics of page reload.
E.g. for benchmarks that measure page start time
2016-09-15 10:17:10 -07:00
c4114c2f66 finished refactoring 2016-09-15 10:17:10 -07:00
37b8691c8c refactor(benchpress): remove chrome < v44 support 2016-09-15 10:17:10 -07:00
93054d4e3d refactor(benchpress): remove facades from chrome_driver_extension 2016-09-15 10:17:10 -07:00
cfc12c6539 docs(api): changes to correct jade errors in API doc gen (#11619) 2016-09-15 09:09:00 -07:00
c0bdd89b5d docs(readme): update the note about RC 2016-09-14 19:37:19 -07:00
d5515473bf docs: update README.md for npm packages 2016-09-14 17:14:02 -07:00
ffe5c49c3e chore(release): v2.0.0 proprioception-reinforcement 2016-09-14 16:49:10 -07:00
ae1dd5bfd0 docs(changelog): add changelog for bug fixes that landed between rc.7 and 2.0.0 2016-09-14 16:45:16 -07:00
cb657c4b55 docs: update descriptions in package.jsons 2016-09-14 16:44:39 -07:00
42f60ca303 docs(core): update dts file 2016-09-14 15:27:33 -07:00
e33037a2f1 docs(core): docs for Directive and Component 2016-09-14 15:27:33 -07:00
9cee8bcc83 docs(common): add directives docs
Closes #11581
2016-09-14 15:24:01 -07:00
003294d5df docs(core): fix examples 2016-09-14 14:53:30 -07:00
785292f44f chore(core): reexport query metadata decorators 2016-09-14 14:53:30 -07:00
15c2912527 chore(core): update public api file 2016-09-14 14:53:30 -07:00
096ae7c404 docs(core): updates query decorator docs 2016-09-14 14:53:30 -07:00
5972fdc817 docs(core): extract how to examples 2016-09-14 14:53:30 -07:00
2c42a50fc3 docs(pipes): updated pipe documentation 2016-09-14 14:32:09 -07:00
caa1cd2470 docs(pipes): move pipe examples to the common folder 2016-09-14 14:26:00 -07:00
5fad37df69 Revert "chore(core): update public api file"
This reverts commit 727c2b38a4.

Revert "docs(core): updates query decorator docs"

This reverts commit b6287ccc51.

Revert "docs(core): extract how to examples"

This reverts commit 69e8ace884.
2016-09-14 13:34:25 -07:00
727c2b38a4 chore(core): update public api file 2016-09-14 13:22:09 -07:00
b6287ccc51 docs(core): updates query decorator docs 2016-09-14 13:22:09 -07:00
69e8ace884 docs(core): extract how to examples 2016-09-14 13:22:09 -07:00
85d9db6bc4 fix(platform-browser): provide Title service as part of the module (#11605)
Fixes #11600
2016-09-14 13:21:23 -07:00
0a2132ef10 docs(di): update docs on di 2016-09-14 11:57:31 -07:00
d299ce4bcf docs(lifecycle): update docs for lifecycle hooks 2016-09-14 11:51:03 -07:00
0b9425bbb4 fix(examples): make them work with noImplicitAny and declarations:true 2016-09-14 11:29:31 -07:00
1a035a0dc7 build(examples): include in main tsconfig.json
Also rename `examples/tsconfig.json` into `examples/tsconfig-build.json`
so that it does not shadow the main `tsconfig.json` in editors

Also adds `noImplicitAny` and `declarations`
`examples/tsconfig.json`.
2016-09-14 11:29:31 -07:00
84b4338ab5 build(example): fix tsconfig (#11593) 2016-09-14 07:40:58 -07:00
b847257b16 refactor(ShadowCss): remove a comment that trigger an issue with webpack (#11587)
fixes #11584
2016-09-13 21:59:11 -07:00
c65d139081 build: remove JS suffix from the license banner 2016-09-13 21:48:58 -07:00
57f0269491 build(examples): fail build.sh if errors are found 2016-09-13 21:48:58 -07:00
4e6c41b3a1 build(examples): work around protractor typings issues and fix existing type errors
This works around the typings issues until we have a build of protractor with typings that don't
polute global types via ambient type definitions
2016-09-13 21:48:58 -07:00
7105021c41 docs(forms): add docs for FormArray 2016-09-13 14:00:52 -07:00
f7313db0be docs(forms): add docs for FormGroup 2016-09-13 14:00:52 -07:00
1d2e70e3a4 docs(forms): add docs for FormControl 2016-09-13 14:00:52 -07:00
21516c32e6 docs(forms): add docs for AbstractControl 2016-09-13 14:00:52 -07:00
00a24b63da build(npm): roll back jasmine 2.5 upgrade due to console reporter issues (#11573)
2.5.1 no longer prints dots in the './test.sh node' mode
2016-09-13 13:32:58 -07:00
e71558ba89 docs(forms): update docs for FormBuilder (#11548) 2016-09-13 13:23:31 -07:00
7ac47acc1c docs(core): updates docs for query metadata 2016-09-13 11:28:12 -07:00
60e49a7e4b docs(core): add an example of using ViewChildren 2016-09-13 11:28:12 -07:00
c71e35cbf5 docs(core): add an example of using ViewChild 2016-09-13 11:28:12 -07:00
1348c65b0c docs(core): add an example of using ContentChildren 2016-09-13 11:28:12 -07:00
ff03d87cdd docs(core): add an example of using ContentChild 2016-09-13 11:28:12 -07:00
a2bf334e6e chore(benchpress): update package.json and add publish script 2016-09-13 10:49:16 -07:00
f8690caa98 chore: refactor build script to allow to build individual packages 2016-09-13 10:49:16 -07:00
aa713d1dd9 docs(readme): fixed visual of browserstack link (#11552)
Instead of using a variable for the link of browserstack it was using the direct https link.
That caused to show the text and the link (incorrect markdown).
Moved the https link to the bottom with the other link assignments. It will now only show the blue text with the link to the browserstack.
2016-09-13 10:06:02 -07:00
a2519c6164 fix(upgrade): correct the main entry path in package.json 2016-09-13 10:03:45 -07:00
fa994810d5 chore(release): v2.0.0-rc.7 2016-09-12 23:25:28 -07:00
c54580a4af docs(changelog): add release notes for 2.0.0-rc.7 2016-09-12 23:25:05 -07:00
730415e048 build: temporarily disable building and testing of documentation examples
This is due to protractor typings issue that breaks the compilation.
2016-09-12 23:06:38 -07:00
42a287fabf fix(core): make name in Pipe non optional 2016-09-12 22:47:54 -07:00
42d442dcd5 refactor(core): add a name to all decorators and other fixes 2016-09-12 22:47:54 -07:00
cc2873a94d chore: update typings
Note that the typings don’t reflect the shape of the metadata
due to a bug in the public-api-guard
2016-09-12 22:47:54 -07:00
63e15ffaec refactor(core): remove …Metadata for all decorators and use the decorator directly.
BREAKING CHANGE:
- all `…Metadata` classes have been removed. Use the corresponding decorator
  as constructor or for `instanceof` checks instead.
- Example:
  * Before: `new ComponentMetadata(…)`
  * After: `new Component(…)`
- Note: `new Component(…)` worked before as well.
2016-09-12 22:47:54 -07:00
1b15170c89 refactor(core): simplify decorators
Every decorator now is made of the following:
- a function that can be used
as a decorator or as a constructor. This function
also can be used for `instanceof` checks.
- a type for this function (callable and newable)
- a type that describes the shape of the data
  that the user needs to pass to the decorator
  as well as the instance of the metadata

The docs for decorators live at the followig places
so that IDEs can discover them correctly:
- General description of the decorator is placed on the
  `...Decorator` interface on the callable function
  definition
- Property descriptions are placed on the interface
  that describes the metadata produces by the decorator
2016-09-12 22:47:54 -07:00
26d1423ae9 docs(forms): update docs for NgForm (#11547) 2016-09-12 17:01:04 -07:00
61aad7925f fix(forms): fix resetting radios (#11546)
Closes #11516
2016-09-12 15:15:58 -07:00
79055f727b fix(forms): support dots in control names in contains (#11542)
Closes #11535
2016-09-12 15:15:50 -07:00
220d8377fe build(npm): update to jasmine@2.5.1
Closes #11390
2016-09-12 12:54:52 -07:00
cc7780adf7 build(npm): update to rxjs@5.0.0-beta.12
Fixes #11300
2016-09-12 12:05:00 -07:00
051a6ebe12 feat(zone): upgrade to zone.js@0.6.21 2016-09-12 11:48:24 -07:00
c9513b713a docs(forms): add example apps for ngModelGroup (#11525) 2016-09-12 11:45:48 -07:00
66e38b6754 docs(forms): add example apps for ngModel (#11524) 2016-09-12 11:27:29 -07:00
7b82877ee5 fix(Localization): BCP47 uses hyphens as separator (#11514)
https://tools.ietf.org/html/bcp47
2016-09-12 11:27:15 -07:00
c9ad5e46d6 docs(forms): add example app for formArrayName (#11512) 2016-09-12 11:26:43 -07:00
2cdd051109 docs(forms): update example for formGroupName (#11510) 2016-09-12 11:26:18 -07:00
57cb82052b docs(forms): add example app for formControlDirective (#11508) 2016-09-12 11:24:09 -07:00
dd8204a655 docs(forms): update example for formGroupDirective 2016-09-12 11:22:51 -07:00
cdda4082de docs(forms): add example app for formControlName 2016-09-12 11:22:51 -07:00
0614c8c99d chore(router): update publicapi 2016-09-12 10:02:48 -07:00
a343a8e1c2 docs(router): fix typos 2016-09-12 09:47:44 -07:00
a41c1bbdf4 docs(router): update docs of the router lifecycle interfaces 2016-09-10 16:55:14 -07:00
f2c6157e74 docs(router): update docs of RouteModule and RouterTestingModule 2016-09-10 16:55:13 -07:00
32564ece27 docs(router): update RouterState docs 2016-09-10 16:55:13 -07:00
3eee62fa71 docs(router): update router configuration docs 2016-09-10 16:55:13 -07:00
617475005f docs(router): update docs of the Router service 2016-09-10 16:55:13 -07:00
0822066175 docs(router): update docs for router directives 2016-09-10 16:55:13 -07:00
82f30e09f0 refactor(common): cleanup directive tests 2016-09-09 14:30:18 -07:00
c649a5c5ab refactor(common): cleanup directives 2016-09-09 14:30:18 -07:00
53f0c2206d fix(forms): rename validator change fn due to conflict (#11492)
Closes #11479
2016-09-09 14:09:11 -07:00
0bce3907b8 fix(tests): add missing import (#11490) 2016-09-09 14:08:47 -07:00
2170379251 refactor(common): cleanup, strip deprecated doc (#11469) 2016-09-09 12:05:06 -07:00
5a4e46db20 refactor(tests): simplify code (#11485) 2016-09-09 12:04:38 -07:00
f5d44a42c9 refactor(NgClass): cleanup, readability (#11467) 2016-09-09 12:03:51 -07:00
673de004d2 fix(forms): clear errors on disable (#11463)
Closes #11287
2016-09-09 12:00:38 -07:00
f386cb4ba9 Fix benchpress for newest protractor and selenium (#11451)
* chore: update protractor and selenium-webdriver packages

As `karma-jasmine` has a peer dependency on `jasmine-core@2.3`, but `jasmine` and `protractor` are using `jasmine-core@2.4` we need to add `jasmine-core@2.3` explicitly. Previously, the peer dependency was
satisfied by accident because npm deduped the dependency
for `jasmine-core@2.3` as top level dependency.

Note that the shrink-wrap files changes quite a bit because
of the deduping mechanism of npm.

* fix(benchpress): make it work with latest protractor and seleniuv-webdriver

* fix(e2e_tests): make them work with latest protractor
2016-09-09 10:37:47 -07:00
71e9cae1d0 chore(github): update issue template to hide comments (#11473)
Wrap additional descriptions in comments so that they are hidden in created issues (only visible during editing)
2016-09-09 09:36:53 -07:00
df6762a170 docs(TestBed): Fix to current packageing (#11472) 2016-09-09 09:36:38 -07:00
d296298282 fix(build): prevent package tsconfigs from shadowing main tsconfig (#11454) 2016-09-08 15:01:22 -07:00
077e0be1e7 fix(CssSelector): fix getMatchingElementTemplate() for void tags
fixes #11407
2016-09-08 13:55:41 -07:00
a52d076912 refactor(CssSelector): misc 2016-09-08 13:55:41 -07:00
dae7cfc454 chore(github): update pull request template fix link (#11449)
Fix the link to the contribution guildelines -  commit message guidlines
2016-09-08 13:54:30 -07:00
436af15d63 refactor: remove parseFloat from facades (#11446) 2016-09-08 13:54:10 -07:00
7b24028437 fix(forms): fix disabled support for empty form containers (#11427)
Closes #11386
2016-09-08 12:21:48 -07:00
6a2bbffe10 fix(animations): allow group() to be used as entry point for an animation trigger (#11419)
Closes #11312
Closes #11419
2016-09-08 12:20:07 -07:00
f78e184822 docs(FactoryProvider): add missing backtick (#11444) 2016-09-08 09:18:37 -07:00
78ad9adc1a fix(ShadowCss): fix perf regression (#11420)
fixes #11371
2016-09-07 16:48:10 -07:00
9e2ec7a1aa fix(ngc): use the compilerHost to detect file existence (#11418) 2016-09-07 16:24:52 -07:00
643afa4b15 docs(cheatsheet): fix typo NgModule definition (#11377)
`.Class` and not `.class` in js approach for NgModule definition.
2016-09-07 16:05:05 -07:00
ed2ebeb52a fix(build): test example directories with unit and e2e tests (#11296) 2016-09-07 16:04:33 -07:00
567900e550 chore(github): update issue template (#11415) 2016-09-07 14:10:47 -07:00
cc958c74ad docs(router): Fix typo of segment name and odd quote (#11409) 2016-09-07 14:10:19 -07:00
62af613741 chore: update triage and labels process (#11403) 2016-09-07 14:10:01 -07:00
3ff816afa6 style(CompileMetadataResolver): better error message (#11401) 2016-09-07 14:09:25 -07:00
dd03bf12e1 docs: misc fixes.
docs(common_module): Fix macro format
docs(number_pipe): Add missing period sign
docs(date_pipe): Fix suffix consistency
docs(date_pipe): Fix missing quote
docs(number_pipe): Fix incorrect article

Looks like the word "Polyfill" does not start with a vowel pronunciation.

docs(location_strategy): Fix code format

Add missing \`\`\` at start.

docs(i18n_plural_pipe): Fix code format
docs(location): Add missing period sign
refactor(ngSwitch): fix typo on parameter
docs(di): Add missing quote
docs(compiler): Fix typo
docs(compiler): Add missing period sign
docs(directives): Fix description for styles parameter
docs(location_strategy): Add code language

Revert for misunderstanding.
2016-09-06 15:45:37 -07:00
645108f25b test: cleanup playground/src/bootstrap.ts file 2016-09-06 15:35:10 -07:00
882efd125e build: remove obsolete presubmit.sh script 2016-09-06 15:35:10 -07:00
d91e92c2f5 build(test.sh): clear dist directory when the script starts
This is to prevent stale files causing the tests to fail when we run them locally after checking out a new revision.
2016-09-06 15:35:10 -07:00
8858ebc4ab ci: update SauceLabs badge when running CI on master (#11352) 2016-09-06 12:07:48 -07:00
df4c0a3d1f refactor(benchmarks): align tree benchmark with largetable benchmark
- add ng2_switch benchmark to track `ngFor` over `ngSwitch`
- measure create only, createDestroy and update
- simplify the created dom
- always add a style binding
2016-09-06 12:07:12 -07:00
b4363bc8af feat(benchmarks): add targetable benchmarks back 2016-09-06 12:07:12 -07:00
d26a827494 fix(lazy-loading): fix an issue with webpack and lazy loader. (#11387)
The issue was introduced in PR#11049.
2016-09-06 12:06:18 -07:00
ea95c391c1 fix(compiler): error when NgModule.bootstrap contains undefined or null 2016-09-06 11:44:56 -07:00
aa9b617c9d fix(compiler): correctly type event handler proxy functions 2016-09-06 11:44:56 -07:00
7192fec841 refactor(EventManager): remove ListWrapper (#11363) 2016-09-06 11:23:00 -07:00
ee88c3c976 fix typo (#11265)
meesage => message
2016-09-06 10:26:51 -07:00
1ff0add29e docs(CHANGELOG): fix provider syntax (#11258)
fixes #11256
2016-09-06 10:26:20 -07:00
5ee0f09b92 build: update the symlinks scripts for Windows to new packaging (#11192) 2016-09-06 10:25:59 -07:00
70b0ab457b style(dom_renderer): use const (#11229) 2016-09-06 10:25:16 -07:00
c25d1f7ecc test: reactivate the remaining disabled tests in Edge (#11188)
Fixes #4756
2016-09-06 10:24:48 -07:00
a45769a0a2 test(offline_compiler_test.sh): lock down npm dependencies 2016-09-02 15:58:46 -07:00
109dc99d32 build(npm): remove obsolete npm dependencies
I also removed an obsolete bundling script which depended on systemjs-builder that I removed.
2016-09-02 15:58:46 -07:00
2371d22d49 chore: remove obsolete dart related files 2016-09-02 15:58:46 -07:00
6f4b6edfea chore(git): cleanup .gitignore
all obsolete paths have been removed
2016-09-02 15:58:46 -07:00
8c09933803 fix(forms): support rebinding nested controls (#11210) 2016-09-02 15:57:35 -07:00
d309f7799c fix(DomSchema): add missing elements
fixes #11219
2016-09-02 15:35:36 -07:00
93deff6c33 refactor(DomSchema): improve readability by making the schema more explicit using interface names 2016-09-02 15:35:36 -07:00
c31535982c fix(ngc): prepend a rootDir when assuming a file exists (#11291)
Otherwise we'll later try to resolve the file under one of the rootDirs and won't find it.
2016-09-02 14:52:14 -07:00
f5101782d9 docs(router): Fixed examples for router.navigate (#11263) 2016-09-02 13:42:51 -07:00
5e5ae3cde6 fix(ngc): propagate errors to main (#11214) 2016-09-01 16:54:37 -07:00
53cf71430f build(publish): shallow fetch to improve perfs (depth=1) 2016-09-01 16:53:51 -07:00
04d02b55d1 build(publish): replace version placeholders in .min.js files 2016-09-01 16:53:51 -07:00
043493cb62 fix(forms): disabled controls should never be invalid (#11257)
Closes #11253
2016-09-01 16:51:42 -07:00
2581c0851a feat(benchmarks): add incremental-dom version of deep tree benchmark 2016-09-01 14:13:33 -07:00
27d72e87c3 feat(benchmarks): add baseline for deep tree that only used createElement 2016-09-01 14:13:33 -07:00
eef4c22e87 feat(benchmarks): add static tree benchmark 2016-09-01 14:13:33 -07:00
4287f1716d chore: add incremental-dom as dev dependency 2016-09-01 14:13:33 -07:00
ebc8e808a9 feat(router): register NgModuleFactory objects. (#11211)
When lazily loading code, users need to be able to get hold of the
NgModuleFactory. For SystemJS environments, the SystemJS registry serves
this purpose. However other environments, such as modules compiled with
Closure compiler, do not expose exports object or a path based registry.

For these environments, `@NgModule` objects can include an identifier, and
the loading code can then pass `loadModule(id).then(() =>
getNgModule(id))` to the router.
2016-09-01 13:46:08 -07:00
c9e5b599e4 fix(animations): ensure parent animations are triggered before children (#11201) 2016-09-01 13:24:26 -07:00
e42a057048 docs(cheatsheet): complete the copy edit (#11215)
…and general cleanup of the cheatsheet.
2016-09-01 12:06:42 -07:00
0bb94df1da docs(core): docs fixes (#11212) 2016-09-01 11:45:59 -07:00
50e171c09b docs(CHANGELOG): add missing animation feature for RC6 (#11216) 2016-09-01 11:40:36 -07:00
96697029c9 docs(changelog): small fixes 2016-08-31 22:26:31 -07:00
7c3b1367bc docs(changelog): add notes about required SystemJS and Karma config changes 2016-08-31 22:23:54 -07:00
18be339ee9 chore: upgrade chrome to v53 (#11213) 2016-08-31 16:59:17 -07:00
ddda62b1f2 docs(router): add changelog for 3.0.0-rc.2 2016-08-31 16:55:18 -07:00
0ddae9b727 chore(release): bump Angular version to 2.0.0-rc.6 in package.json 2016-08-31 16:49:14 -07:00
625b105d3a docs(changelog): add changelog for 2.0.0-rc.6 2016-08-31 16:49:14 -07:00
f9eb1f33f4 fix(platform-webworker): remove trailing comma in package.json 2016-08-31 16:49:14 -07:00
046c1a8a25 fix(compiler-cli): update package.json to tsc-wrapped@0.3.0 2016-08-31 16:49:14 -07:00
08e48c8f73 fix(router): correct peerDependencies info in package.json 2016-08-31 16:49:14 -07:00
1b5e2b5129 test: add Intl polyfill and run Intl tests in all browsers (#10471) 2016-08-31 15:55:13 -07:00
562c8263dc fix(animations): ensure animation callbacks are fired for embedded views 2016-08-31 15:46:23 -07:00
99c0a7fae2 fix(tsc-wrapped): correct the tsickle dependency in package.json 2016-08-31 15:10:09 -07:00
f4f6f4b4d8 fix(core): don't require reflect-metadata shim when in AOT mode 2016-08-31 15:10:09 -07:00
cc89ef6c8c fix(core): report errors for missing di tokens correctly (#11209) 2016-08-31 14:47:56 -07:00
6ea5b05e7c refactor(benchmarks): make setup nicer
- simplify and correct systemjs config
- remove deep imports into Ng2 packages to work with bundles
- have separate Ng2 and Polymer bootstrap files
2016-08-31 11:24:22 -07:00
f7b5478e9f feat(benchmarks): add polymer_leaves benchmark 2016-08-31 08:24:11 -07:00
873233e825 feat(benchpress): also report the statistics in the generated file 2016-08-31 08:24:11 -07:00
942104d9ac fix(benchpress): support chrome 52
Without this fix, the `scriptTime` was always 0.
2016-08-31 08:24:10 -07:00
6dceaf209d fix(benchmarks): recreate setup for running benchmarks 2016-08-31 08:24:10 -07:00
2ab07d9418 chore: cleanup stale protractor files 2016-08-31 08:24:10 -07:00
1ef122988e fix(benchpress): make code compile and unit tests green again 2016-08-31 08:24:10 -07:00
db280fc67e chore: move benchpress to @angular/benchpress 2016-08-31 08:24:09 -07:00
ef0f29c372 fix: merge artifact 2016-08-30 21:37:28 -07:00
1818056912 fix(TemplateParser): disallow event-property binding even with the NO_ERRORS_SCHEMA
closes #11026
2016-08-30 21:32:24 -07:00
1df69cb4d2 fix(DomSchemaRegistry): detect invalid elements 2016-08-30 21:32:03 -07:00
2b20db6c5a chore: update to typescript@2.0.2 - the currect 2.0 rc 2016-08-30 21:07:45 -07:00
174c016104 fix(bundles): correct RxJS mapping in rollup config for umd/es5 bundles 2016-08-30 21:07:45 -07:00
71ae2c4525 refactor(webworkers): move webworkers to separate @angular/platform-webworker and @angular/platform-webworker-dynamic packages
BREAKING CHANGE: web worker platform is now exported via separate packages.

Please use @angular/platform-webworker and @angular/platform-webworker-dynamic
2016-08-30 21:07:45 -07:00
0f68351979 fix(Router): fix type (#11181) 2016-08-30 21:06:38 -07:00
c74a438f0c docs(router): fix up the exampesd 2016-08-30 20:37:35 -07:00
c350ba29f6 fix(router): do not use rx/add/operator 2016-08-30 20:37:35 -07:00
6e40ef0f6d refactor: remove requestAnimationFrame from polyfills and platforms (#10528) 2016-08-30 19:58:22 -07:00
24e046fd6a ci(publish): fix multiples umd files (#11179) 2016-08-30 19:58:07 -07:00
979657989b fix(packages): use ES modules for primary build (#11120) 2016-08-30 18:07:40 -07:00
8cb1046ce9 docs(cheatsheet): copy edit bootstrapping.md (#11149)
Also remove Dart-specific code, since the Dart cheatsheet is produced
from dart-lang/angular2.
2016-08-30 08:32:51 -07:00
d53a898f46 edit dependency-injection.md (#11156)
No copy edits to this one, but I removed Dart-specific code, since the
Dart cheatsheet is produced from dart-lang/angular2.

Part of a group of cheatsheet PRs (see #11149).

cc @Foxandxss & @IgorMinar
2016-08-29 18:13:35 -07:00
f9f80003c8 docs(cheatsheet): copy edit class-decorators.md (#11154)
No copy edits to this one, but I removed Dart-specific code, since the
Dart cheatsheet is produced
from dart-lang/angular2.
2016-08-29 18:13:10 -07:00
d59ee3caaa docs(cheatsheet): copy edit component-configuration.md (#11155)
Also remove Dart-specific code, since the Dart cheatsheet is produced
from dart-lang/angular2.

Part of a group of cheatsheet PRs (see #11149).

cc @Foxandxss & @IgorMinar
2016-08-29 18:12:51 -07:00
b8ea71afb6 docs(cheatsheet): copy edit built-in-directives.md (#11153)
Also remove Dart-specific code, since the Dart cheatsheet is produced
from dart-lang/angular2.
2016-08-29 18:12:42 -07:00
e2241a2f92 fix(router): support guards navigating synchronously (#11150) 2016-08-29 17:51:38 -07:00
e8a1566065 fix(forms): support radio buttons with same name but diff parent (#11152)
Closes #10065
2016-08-29 17:49:42 -07:00
d2ad871279 fix(forms): update validity when validator dir changes
closes #11116
2016-08-29 13:12:46 -07:00
0b665c0ece feat(validations): add support to bind validation attributes
This change enables to bind the validations attributes `required`,
`minlength`, `maxlength` and `pattern`.

Closes: #10505, #7393
2016-08-29 13:12:20 -07:00
875e66409c fix(closure): prevent closure renaming of testability interface (#11146) 2016-08-29 13:08:28 -07:00
d7de5c4f8e refactor(compiler): replace CompileIdentifierMap with regular Map
closes #11145

Also rename `CompileIdentifierMetadata.runtime` into `CompileIdentifierMetadata.reference`.

Also remove `CompileIdentifierMetadata.equalsTo` as
now it is enough to just check the `reference` fields for equality.
2016-08-29 12:45:27 -07:00
51877ef4ed fix(compiler): no longer uses assetCacheKey for token identity.
Fixes #10545, Fixes #10538
2016-08-29 12:45:02 -07:00
c377e80670 chore: format benchmarks
closes #11112
2016-08-29 12:43:25 -07:00
61002733bc refactor(benchmarks): make tree benchmark work again 2016-08-29 12:42:57 -07:00
5ff14de1f3 chore: force lf EOL for ts files (#11143) 2016-08-29 12:41:58 -07:00
38069aba35 fix(compiler): make ShadowCSS shim work on Android browser (#11139)
Fixes #11123
2016-08-29 08:18:55 -07:00
7dee1ee4cf test(core): update ErrorHandler tests to handle browsers without stack (#11141)
Fixes #11114
2016-08-29 08:17:45 -07:00
af63378fa0 fix(ShadowCss): properly shim selectors after :host and :host-context (#10997)
fixes #5390

Before the change:

    // original CSS
    :host .foo .bar {...}
    .foo .bar {...}

    // translated to 
    [_nghost-shh-2] .foo .bar {...}
    .foo[_ngcontent-shh-2] .bar[_ngcontent-shh-2] {...}

Note that `.foo` and `.bar` where not scoped and would then apply to nested components.

With this change those selectors are scoped (as they are without  `:host`).

You can explicitly apply the style to inner component by using `>>>` or `/deep/`: `:host >>> .foo`
2016-08-26 16:11:57 -07:00
abad6673e6 fix(ngc): don't quote properties in literal maps (#11110)
Closure compiler treats quoted properties specially, and doesn't rename them.

Fixes #11050
2016-08-26 15:54:34 -07:00
75553200c0 fix(http): encode correct value for %3D (#9790) 2016-08-26 15:47:29 -07:00
6c77d7182a fix(compiler-cli): make ngc to work on Windows (#10919)
Fixes #10792
2016-08-26 15:41:50 -07:00
4a44832114 fix(UrlParser) stop setting default value 'true' (matrix params) (#10946)
This was already fixed recently for query params in #10399.
2016-08-26 15:41:32 -07:00
27539c8b80 refactor(example): refactor forward_ref example into a spec and unignore example specs (#11088) 2016-08-26 15:40:46 -07:00
e220a80093 feat(codegen): Add an error message when the locale is not provided (#11104) 2016-08-26 15:38:48 -07:00
3dd85cb7f1 test(tools): make the test suite to pass on Windows (#10926) 2016-08-26 15:36:04 -07:00
511fe3d9f8 chore(contributing): remove documentation note (#11108) 2016-08-26 15:35:33 -07:00
9ce8ef76bf fix(ErrorHandler): make rethrowError internal so that the interface can be implemented (#11109) 2016-08-26 14:43:42 -07:00
7c07bfff97 fix(errors): [2/2] Rename Exception to Error; remove from public API
BREAKING CHANGE:

Exceptions are no longer part of the public API. We don't expect that anyone should be referring to the Exception types.

ExceptionHandler.call(exception: any, stackTrace?: any, reason?: string): void;
change to:
ErrorHandler.handleError(error: any): void;
2016-08-26 10:37:17 -07:00
86ba072758 fix(errors): [1/2] Rename Exception to Error; remove from public API 2016-08-26 10:37:17 -07:00
fc1e45db92 fix(Router): merge artifacts
closes #11063
closes #11102
2016-08-26 10:32:35 -07:00
a2deafc50f fix(router): add an option to disable initial navigation 2016-08-26 10:32:35 -07:00
2fc5c57b31 feat(router): add support for custom error handlers 2016-08-26 10:32:35 -07:00
93f323cfa2 refactor(router): make RouterLink and RouterLinkWithHref create url in a similar way 2016-08-26 10:32:35 -07:00
bb9dfbc578 fix(router): use encodeUri/decodeUri to encode fragment 2016-08-26 10:32:35 -07:00
0bb516fae2 fix(router): fix the order of guards, so canActivateChild runs before canActivate 2016-08-26 10:32:35 -07:00
2ffecc0e14 fix(router): update the location before activating components 2016-08-26 10:32:35 -07:00
b9647b7347 fix(i18n): change default locale from en_US to en-US (#11103) 2016-08-26 10:30:10 -07:00
f25c97671a fix(compiler): handle invalid host bindings and events (#11101) 2016-08-26 10:29:53 -07:00
0a053a4cd5 fix(i18n): Currency/Date/Number pipe use injected locale (#11093) 2016-08-26 09:16:01 -07:00
4d7d2a2daa refactor: remove various leftover unused or deprecated code (#11091) 2016-08-26 09:12:27 -07:00
0cf5ece7f8 build: workaround to run presubmit.sh on Windows (#11096) 2016-08-26 09:12:10 -07:00
66df335998 chore(dependencies): switch from es6-shim to core-js (#10884) 2016-08-25 17:28:36 -07:00
fc2fe00d16 fix(compiler): allow tsc-wrapped to be compile with TypeScript 2.0 (#11086) 2016-08-25 17:28:20 -07:00
811962b2bb refactor: rename SanitizationService to Sanitizer and DomSanitizationService to DomSanitizer (#11085)
BREAKING CHANGE: Previously inconsistently named APIs SanitizationService and DomSanitizationService were renamed to Sanitizer and DomSanitizer
2016-08-25 15:41:19 -07:00
b867764b0d refactor(template): remove supporter deprecated var / # (#11084)
BREAKING CHANGES:

- `#` and `var` are not supported any more in expressions, use `let`,
- `var-<name>` could not be used any more on templates, use `let-<name>`,
- `var-<name>` could not be used any more to create a reference, use `ref-<name>`.
2016-08-25 15:21:33 -07:00
ce08982f78 fix(forms): fix conflicting getter name (#11081) 2016-08-25 14:56:31 -07:00
cbe0976426 test: improve perfs by removing unneeded TestBed.compileComponents() calls (#11083) 2016-08-25 14:56:14 -07:00
515ff61fcb fix(forms): fully support rebinding form group directive (#11051) 2016-08-25 14:37:57 -07:00
d7c82f5c0f test: fix memory leak when running test campaign (#11072) 2016-08-25 14:37:46 -07:00
566d4361e2 refactor: remove obsolete analyzeAppProvidersForDeprecatedConfiguration
closes #11028
2016-08-25 13:29:43 -07:00
ea2e5521e8 refactor: replace any[] with Provider[] where possible 2016-08-25 13:29:03 -07:00
eb7d8c702c fix(core): FactoryProvider's deps property should be optional 2016-08-25 13:29:03 -07:00
5d294624fa docs(core): update stability markers for core apis 2016-08-25 13:29:03 -07:00
3aaf064d11 refactor(router): remove ROUTER_DIRECTIVES which were replaced by RouterModule 2016-08-25 13:29:03 -07:00
f38a700e35 docs(upgrade): mark upgrade apis as stable 2016-08-25 13:29:03 -07:00
501b83441d refactor(forms): remove FORM_PROVIDERS, FORM_DIRECTIVES, REACTIVE_FORM_PROVIDERS, REACTIVE_DIRECTIVES
All of these have been replaced by FormsModule and ReactiveFormsModule.
2016-08-25 13:29:03 -07:00
c03e25a7b7 docs(common): mark platform-browser and platform-browser-dynamic apis stable 2016-08-25 13:29:03 -07:00
1f5a5895e5 refactor(common): rename UrlChangeEvent and UrlChangeListener to LocationChangeEvent and LocationChangeListener
These apis are not expected to be used anyone, hence I'm not documenting this change as a breaking.
2016-08-25 13:29:03 -07:00
8a2324f86a docs(common): mark all common apis except for i18n as stable 2016-08-25 13:29:03 -07:00
6335b31702 refactor(common): remove COMMON_DIRECTIVES, COMMON_PIPES, CORE_DIRECTIVES that were replace with CommonModule 2016-08-25 13:29:03 -07:00
6ef7a76e39 doc(form): updating example to avoid "TypeError: Converting circular structure to JSON" (#10184) 2016-08-25 11:14:40 -07:00
cc79dcac7f docs(cheatsheet): update javascript sections (#11070) 2016-08-25 11:12:23 -07:00
dc6f72e963 fix(closure): replace property accesses (#11078)
Accessing a property on the window object must be done with square brackets.
Otherwise closure compiler may collide the symbol's alias between the property
and variable mappings.
Also, accessing the 'provide' property must be done with dot syntax, so that
it can be renamed along with the code that declares such a property.
2016-08-25 11:12:06 -07:00
2b313e4979 feat(forms): add support for disabled controls (#10994) 2016-08-24 16:58:43 -07:00
4f8f8cfc66 feat(animations): make sure animation callback reports the totalTime (#11022)
Closes #11022
2016-08-24 16:55:00 -07:00
8b782818f5 feat(linker): Allow configurable module prefixes and suffixes. (#11049) 2016-08-24 16:54:42 -07:00
bd510ccdbb fix(core): assigns an overriden name to constructor named constructor (#11043)
Fixes #10545
2016-08-24 10:21:13 -07:00
f1ce7607a6 fix(router): canLoad should cancel a navigation instead of failing it (#11001) 2016-08-24 10:20:44 -07:00
7dfcaac730 fix(http): restructure exports so that we don't leak private factory functions (#11016)
Ref #10615
2016-08-23 16:34:57 -07:00
c7a874dd2f feature(ngc): allow codegen to skip over .d.ts inputs (#11021) 2016-08-23 16:26:35 -07:00
aa5c8ca61f fix(compiler): throw descriptive error meesage for invalid NgModule providers (#10947)
Fixes #10714
2016-08-23 16:18:41 -07:00
5c93a8800a fix(core): Share private types through an exported interface. (#11009)
Instead of using declare namespace to share the types. This allows the generated code to be compiled with closure with full optimizations.
2016-08-23 16:18:11 -07:00
05bbb8efcf fix(platform-browser): remove export for private symbol _WORKER_UI_PLATFORM_PROVIDERS. (#11018) 2016-08-23 16:16:40 -07:00
14a30f3ca0 fix(compiler): Correctly handles references to static methods (#11013)
Fixes: #10975
2016-08-23 11:58:12 -07:00
5ddecb18a7 feat(router): throw a helpful error when misusing forRoot() from a lazy module. (#10996) 2016-08-23 11:57:58 -07:00
c02325dd06 docs(DatePipe): add AM/PM designator in description #10998 2016-08-23 11:57:41 -07:00
4a740f23a4 refactor(core): remove deprecated @Component.directives and @Component.pipes
BREAKING CHANGE: previously deprecated @Component.directives and @Component.pipes support was removed.

All the components and pipes now must be declarated via an NgModule. NgModule is the basic
compilation block passed into the Angular compiler via Compiler#compileModuleSync or #compileModuleAsync.

Because of this change, the Compiler#compileComponentAsync and #compileComponentSync were removed as well -
any code doing compilation should compile module instead using the apis mentioned above.

Lastly, since modules are the basic compilation unit, the ngUpgrade module was modified to always require
an NgModule to be passed into the UpgradeAdapter's constructor - previously this was optional.
2016-08-23 09:59:00 -07:00
a782232ca3 refactor(core): fix typo in private property name 2016-08-23 09:59:00 -07:00
a29f9f3ab8 refactor(core/testing): remove deprecated TestComponentBuilder
BREAKING CHANGE: deprecated TestComponentBuilder was removed, please use TestBed instead
2016-08-23 09:59:00 -07:00
3c2b2ff332 test: fix existing tests by removing usage of obsolete stuff like component level directives, AsyncCompleter and TestComponentBuilder 2016-08-23 09:59:00 -07:00
939d318242 refactor(platform-browser-dynamic): Removed TestComponentBuilder from ResourceLoaderCache specs (#10890) 2016-08-23 09:22:33 -07:00
39a2c39cef feat(compiler): Added "strictMetadataEmit" option to ngc (#10951)
ngc can now validate metadata before emitting to verify it doesn't
contain an error symbol that will result in a runtime error if
it is used by the StaticReflector.

To enable this add the section,

  "angularCompilerOptions": {
    "strictMetadataEmit": true
  }

to the top level of the tsconfig.json file passed to ngc.

Enabled metadata validation for packages that are intended to be
used statically.
2016-08-22 17:37:48 -07:00
45e8e73670 refactor(animations): deport TCB away from animation-land forever (#10892)
* feat(animations): support animation trigger template callbacks

* refactor(animations): deport TCB away from animation-land forever
2016-08-22 17:18:25 -07:00
ca41b4f5ff feature(core): update RxJS to 5.0.0-beta.11 (#10648) 2016-08-22 17:17:23 -07:00
3c561475c8 refactor(animations): add an onStart handler for AnimationPlayer (#10360) 2016-08-22 16:39:52 -07:00
23a27776e2 chore: upgrade zone.js to v0.6.17 (#10989) 2016-08-22 16:24:21 -07:00
01111b04ff fix(ngc): codegen allows --strictNullChecks (#10991) 2016-08-22 15:30:18 -07:00
8560e1e4bf fix(ngc): comment out a private keyword in codegen. (#10949)
Workaround for b/30775898
2016-08-22 14:28:09 -07:00
e0fbca9fb0 feat(ngc): support pathmapping using a separate reflector (#10985)
Until we have comprehensive E2E tests, it's too risky to change the
reflector_host Misko wrote before final. But google3 uses path mapping
and needs all imports to be  and all paths to be canonicalized to
the longest rootDir.

This change introduces a subclass of ReflectorHost with overrides for methods
that differ. After final (or when we have good tests), we'll refactor
them back into one class.
2016-08-22 11:48:33 -07:00
a7b76826a0 fix(compiler): Only emit metadata for exported enums (#10957)
Closes: #10955
2016-08-22 10:26:22 -07:00
ece7985b8a chore(formatting): fix formatting for component fixture spec (#10986) 2016-08-22 10:20:21 -07:00
9883e19e2e fix(tests): remove fit in component_fixture_spec (#10961) 2016-08-19 17:12:58 -07:00
c631cfc2fd feat(core): add NO_ERRORS_SCHEMA that allows any properties to be set on any element (#10956)
Often it is useful to test a component without rendering certain directives/components
in its template because these directives require some complicated setup.

You can do that by using NO_ERRORS_SCHEMA.

TestBed.configureTestingModule({
  schemas: [NO_ERRORS_SCHEMA]
});

This would disable all schema checks in your tests.
2016-08-19 16:05:34 -07:00
53c99cfc95 feat(router): add syntax sugar for confuguring RouterTestingModule (#10906) 2016-08-19 16:01:59 -07:00
c56f3f2246 fix(compiler): do not autoinclude components declared as entry points (#10898) 2016-08-19 15:59:50 -07:00
cc0e3d2296 docs(router): Added additional router documentation including cheatsheet updates (#10802) 2016-08-19 15:48:09 -07:00
917d43e108 refactor(tests): add ComponentFixture tests (#10910)
Remove old TestComponentBuilder tests, and keep relevant
ComponentFixture tests as component_fixture_spec.
2016-08-19 15:46:40 -07:00
bb7d55244d fix(zones): bump zone version to 0.6.15 (#10953)
This fixes issues with microtasks being called too early
in certain tests.
2016-08-19 14:35:26 -07:00
8a5eb08672 fix(fakeAsync): have fakeAsync use Proxy zone. (#10797)
Closes #10503

It is possible for code in `beforeEach` to capture and fork a zone
(for example creating `NgZone` in `beforeEach`). Subsequently the code
in `it` may chose to do `fakeAsync`. The issue is that because the
code in `it` can use `NgZone` from the `beforeEach`. it effectively can
escape the `fakeAsync` zone. A solution is to run all of the test in
`ProxyZone` which allows a test to dynamically replace the rules at any
time. This allows the `beforeEach` to fork a zone, and then `it` to
retroactively became `fakeAsync` zone.
2016-08-19 12:10:53 -07:00
477e425f57 fix(http): inline HTTP_PROVIDERS and JSONP_PROVIDERS until the metadata collector can do it automatically. (#10928) 2016-08-18 15:01:07 -07:00
654ff6115a fix(http): deep copy for constructor using existing Headers (#10679)
When creating a new Headers object using an existing Headers object
the existing Headers map is copied by reference. Therefore adding a
new Header value to the new Headers object also added this value to
the existing Headers object which is not in accordance with the
spec.
This commit alters the constructor to create a deep copy of existing
Headers maps and therefore unlink existing Headers from new Headers.

Closes #6845

BREAKING CHANGE: 

any code which relies on the fact that a newly
created Headers object is referencing an existing Headers map is
now broken, but that should normally not be the case since this
behavior is not documented and not in accordance with the spec.
2016-08-18 15:00:44 -07:00
628d06c17c feat(core): Throw a descriptive error when BrowserModule is installed a second time (via lazy loading). (#10899)
Such a configuration is unsupported and causes all kinds of problems.
2016-08-18 13:34:28 -07:00
91980382e8 fix(pipes): remove bidi control chars (#10870)
Fix inconsistent results in Edge vs. other browsers.

Closes #10080.
2016-08-18 13:31:33 -07:00
2f41b5c8a0 refactor(core): Removed test deprecated references from runtime_compiler (#10927)
Removed reference to TestComponentBuilder from runtime_compiler_spec.ts
2016-08-18 11:20:02 -07:00
cd8cbd3762 fix(ngc): don't codegen foo.d.ngfactory.ts from foo.d.ts (#10833) 2016-08-18 10:11:06 -07:00
292ccf882a test(forms): update reactive form integration tests to use TestBed (#10908) 2016-08-17 17:10:56 -07:00
a0e13b9797 refactor(core): remove deprecated functions ReflectiveInjector.fromResolvedBindings and ResolvedReflectiveBinding (#10819) 2016-08-17 16:53:09 -07:00
a5c0349d88 refactor(core): Removed linker test references to TestComponentBuilder (#10903)
Removed references to TestComponentBuilder from:
  query_integration_spec.ts
  regression_integration_spec.ts
  security_integration_spec.ts
  view_injector_integration_spec.ts
2016-08-17 16:52:39 -07:00
c48021ab97 refactor(compiler): move test/test_bindings to testing/test_bindings (#10081)
`test_bindings` is used in core test cases too, but `test` should be
private to the package, so it should live in `testing`.
2016-08-17 16:37:31 -07:00
beb79e75bf refactor(various): remove a few lingering but unused deprecated apis (#10896)
Removes deprecated APPLICATION_COMMON_PROVIDERS, as well as some
internal apis that were deprecated.
2016-08-17 16:36:10 -07:00
0b62b6f783 refactor(debug): switch tests from TCB to use TestBed (#10756) 2016-08-17 16:27:54 -07:00
895c542a20 refactor(directiveLifecycle): switch test from TCB to use TestBed (#10768) 2016-08-17 16:17:07 -07:00
c4fd862e15 fix(metadata): throw better errors when components are passed to imports or modules are passed to declarations. (#10888)
Closes #10823
2016-08-17 15:57:02 -07:00
6f18bd18bb refactor(core): Removed linker test reference to TestComponentBuilder (#10867)
Removed TestComponentBuilder references from ng_container_integration_spect.ts
2016-08-17 15:45:29 -07:00
00e157dc3b refactor(router): update stability labels (#10902) 2016-08-17 15:35:30 -07:00
4be863c223 Remove TCB (#10900)
* refactor(webworker): change tests not to use TestComponentBuilder

* refactor(core): change tests not to use TestComponentBuilder
2016-08-17 15:05:22 -07:00
3009be8d6e docs(security): mark the various DomAdapters as unsafe. (#10868)
Part of #8511.
2016-08-17 13:42:18 -07:00
4829fbb95c refactor(core): Remove linker test references to TestComponentBuilder (#10869)
Removed TestComponentBuilder references from projection_integration_spec.ts
2016-08-17 11:19:38 -07:00
40e160c22c fix(platform-browser-dynamic): Rename CACHED_TEMPLATE_PROVIDER to RESOURCE_CACHE_PROVIDER (#10866)
* fix(platform-browser-dynamic): Rename CACHED_TEMPLATE_PROVIDER to RESOURCE_CACHE_PROVIDER

Closes #9741

BREAKING CHANGE:

`CACHED_TEMPLATE_PROVIDER` is now renamed to `RESOURCE_CACHE_PROVIDER`

Before:

```js
import {CACHED_TEMPLATE_PROVIDER} from '@angular/platform-browser-dynamic';
```

After:

```js
import {RESOURCE_CACHE_PROVIDER} from '@angular/platform-browser-dynamic';
```

* Rename XHR -> ResourceLoader
2016-08-17 09:24:44 -07:00
951ecb4d90 feat(core): update public api 2016-08-17 08:06:32 -07:00
9318033294 refactor(router): update router spec not to use TestComponentBuilder 2016-08-17 08:06:32 -07:00
4648b3e5de feat(testing): add TestBed.get 2016-08-17 08:06:32 -07:00
740e80492d refactor(core): update entry_components_integration_spec not to use TestComponentBuilder 2016-08-17 08:06:32 -07:00
cc22b051e3 refactor(core): update change_detection_integration_spec not to use TestComponentBuilder 2016-08-17 08:06:32 -07:00
75405ae0f5 refactor(core): update forward_ref_integration_spec not to use TestComponentBuilder 2016-08-17 08:06:32 -07:00
f12d51992d fix(animations): report errors for missing host-level referenced animations (#10650)
Closes #10650
2016-08-17 08:00:49 -07:00
6fd5bc075d chore(forms): update forms labels (#10873) 2016-08-17 07:44:39 -07:00
675e582ffd refactor(http): Removed deprecated HTTP_PROVIDERS and JSONP_PROVIDERS (#10864)
BREAKING CHANGE: previously deprecated HTTP_PROVIDERS and JSONP_PROVIDERS were removed; see deprecation notice for migration instructions.
2016-08-17 07:43:31 -07:00
0a22e8eefd refactor(core): Removing linker test references to TestComponentBuilder (#10865)
Removed references to TestComponentBuilder from integration_spec.ts
2016-08-17 07:15:35 -07:00
44a4814766 Update package.json (#10609)
Update compiler-cli dependencies to increment tsc-wrapped to 0.2.2. It appears this was missed in the rc5 release.
2016-08-16 19:40:25 -07:00
3c23238129 docs(ngFor): add documentation for ngForTrackBy (#10780)
* docs(ngFor): add documentation for ngForTrackBy

* wo/ prefix
2016-08-16 19:39:22 -07:00
916ed55d82 chore(docs): remove sentences for dart (#10781) 2016-08-16 19:38:49 -07:00
2451eb9ded docs(router): Explanation in code should be comment (#10790) 2016-08-16 19:38:23 -07:00
ed639784d4 docs(router): Fix mismatching of code and comment (#10791) 2016-08-16 19:37:53 -07:00
b77a3794b8 docs(changelog): added missing closing parenthesis (#10783) 2016-08-16 19:37:24 -07:00
73a9ee4a05 Remove component resolver (#10858)
* refactor(core): remove deprecated ComponentResolver

BREAKING CHANGE: deprecated ComponentResolver was removed

Please follow deprecation instruction and migrate your code to use ComponentFactoryResolver.

* refactor(common): remove deprecated NgSwitchWhen directive

BREAKING CHANGE: previously deprecated NgSwitchWhen directive was removed, use NgSwitchCase instead
2016-08-16 16:48:32 -07:00
9adf80385b fix(animations): remove deprecated trigger APIs (#10825)
BREAKING CHANGE: Animations defined using an at-symbol prefix that are
not property bound are now invalid.

```html
<!-- this is now invalid -->
<div @flip="flipState"></div>

<!-- change that to -->
<div [@flip]="flipState"></div>
```

BREAKING CHANGE: Animations that are not bound using the at-symbol
prefix using `animate-` must now be preixed using `bind-animate-`.

```html
<!-- this is now invalid -->
<div animate-flip="flipState"></div>

<!-- is valid now -->
<div bind-animate-flip="flipState"></div>
```

Closes #10825
2016-08-16 14:09:21 -07:00
a86c554a8e refactor(core/testing): remove deprecated ViewMetadata (#10837)
Note that this doesn't actually remove all uses, but makes them
private.
2016-08-16 13:59:06 -07:00
62078eee45 chore(tsconfig): emit decorator metadata so that tsc watch works with demos (#10863) 2016-08-16 13:53:04 -07:00
24e280a21a refactor(router): remove deprecated apis (#10658) 2016-08-16 13:40:28 -07:00
f7ff6c5a12 refactor(core): remove deprecated 'bootstrap' (#10831) 2016-08-16 11:15:01 -07:00
f6a7d6504c feat(i18n): xliff integration 2016-08-15 22:28:38 -07:00
96bf42261b fix(XmlHelper): declaration 2016-08-15 22:21:40 -07:00
72bb38f83b feat(i18n): xliff 2016-08-15 22:21:40 -07:00
4c9900dc3a refactor(testing): remove deprecated testing functions (#10832)
Remove TestComponentBuilder, addProviders, and withProviders. These
were deprecated in rc5 - see the changelog for update information.

Note - this does not actually remove the functions, but makes them
internal only. They will be removed from the codebase entirely
at a later time.
2016-08-15 21:40:37 -07:00
6b26102931 feat(router): extend support for lazy loading children (#10705) 2016-08-15 21:11:09 -07:00
bec5c5fdad refactor(Provider): remove deprecated provider/bind API (#10652)
Closes #9751

BREAKING CHANGE:

These forms of providers are no longer accepted:
  bind(MyClass).toFactory(...)
  new Provider(MyClass, toFactory: ...)

We now only accept:
  {provider: MyClass, toFactory: ...}
2016-08-15 19:37:42 -07:00
04c11bb749 test(forms): update template-driven form tests to use testbed (#10830) 2016-08-15 16:37:59 -07:00
3f5331be9d refactor(chore): remove deprecated NgZoneError (#10822)
BREAKING CHANGE: previously deprecated NgZoneError has been removed
2016-08-15 16:10:30 -07:00
48751cceae refactor(core): Removed deprecated Query and ViewQuery (#10820)
BREAKING CHANGE: previously deprecated Query and ViewQuery  were removed; see deprecation notice for migration instructions.
2016-08-15 16:07:55 -07:00
4a9745ef78 refactor(core): Remove deprecated DynamicComponentLoader (#10759)
BREAKING CHANGE: previously deprecated DynamicComponentLoader was removed; see deprecation notice for migration instructions.
2016-08-15 16:07:19 -07:00
acc0fe6cf9 refactor(TestBed): remove deprecated TestBed.reset 2016-08-15 14:07:54 -07:00
b238414984 refactor(core): remove previously deprecated SystemJsComponentResolver and SystemJsCmpFactoryResolver
BREAKING CHANGE: previously deprecated SystemJsComponentResolver and SystemJsCmpFactoryResolver have been removed.

Please follow deprecation instructions to migrate your code.
2016-08-15 14:07:54 -07:00
231ed69507 refactor(common): Remove uses of deprecated TestComponentBuilder. (#10754)
* ng_class_spec

* Working through ng_for_spec.

* Finishing up ng_for_spec.

* Finish the rest of the specs.

* Convert pipes tests.
2016-08-15 13:52:57 -07:00
60b10134df cleanup(platform): removed webworker and server deprecated apis (#10745) 2016-08-15 13:44:01 -07:00
73c0a9daaf fix(router): make routerLinkActiveOptions public (#10758) 2016-08-15 00:39:59 -07:00
398bbb6aa9 refactor(core): replace some for statements with map/reduce 2016-08-14 10:10:07 -07:00
05d1312306 refactor(core): Replace all var with const and let 2016-08-14 10:10:07 -07:00
bc6d1c87a6 fix(core): don't strip sourceMappingURL (#9664)
fix #9664
2016-08-14 10:10:07 -07:00
712c7d5c3b fix(datePipe): allow float for date pipe input (#10687) 2016-08-14 10:05:21 -07:00
e9479b30e8 refactor(OutputAst): BuiltinMethod.bind renamed to Bind (#10739) 2016-08-14 10:04:37 -07:00
7f6685e451 test(forms): refactor form model tests to three files (#10774) 2016-08-13 17:26:08 -07:00
ce4eae65a7 feat(i18n): provide LOCALE_ID and NgLocalization 2016-08-13 06:18:25 -07:00
4df48b202c fix(i18n): update NgLocalLocalization (#10771)
ref https://github.com/papandreou/node-cldr/issues/31
2016-08-13 05:43:36 -07:00
33ced7088f refactor(common): remove deprecated ReplacePipe (#10772)
BREAKING CHANGE: previously deprecated ReplacePipe was removed
2016-08-12 21:50:57 -07:00
3329977ec9 refactor(core): remove deprecated coreBootstrap and coreLoadAndBootstrap
BREAKING CHANGE: previously deprecated coreBootstrap and coreLoadAndBootstrap have been removed.

Please follow deprecation instructions to migrate your code.
2016-08-12 18:07:58 -07:00
f84c3fdc5f refactor(ApplicationRef): remove all previously deprecated ApplicationRef apis
BREAKING CHANGE: All previously deprecated ApplicationRef apis have been removed.

Please follow the deprecation instructions to migrate your code.
2016-08-12 17:59:30 -07:00
44e1b23813 refactor(PlatformRef): remove deprecated PlatformRef#registerDisposeListener, #disposed, #dispose()
BREAKING CHANGE: previously deprecated PlatformRef#registerDisposeListener, #disposed, #dispose() - follow deprecation instructions to upgrade
2016-08-12 17:59:30 -07:00
12b0a3d0e5 refactor(NgUpgrade): remove deprecated addProvider
BREAKING CHANGE: previously deprecated UpgradeAdapter#addProvider was removed, see deprecation notice for migration instructions.
2016-08-12 17:59:30 -07:00
d2825077b1 fix(core): Removed depricated disposePlatform
BREAKING CHANGE: previously deprecated disposePlatform was removed; see deprecation notice for migration instructions.
2016-08-12 17:52:13 -07:00
156a52e390 refactor(core): Removed deprecated properties and events from metadata (#10753)
BREAKING CHANGE: previously deprecated DirectiveMetadataType#properties and DirectiveMetadataType#events were removed; see deprecation notice for migration instructions.
2016-08-12 17:44:44 -07:00
bb7221f922 refactor(facade): Removed unnecessary override and deprecation. (#10761) 2016-08-12 17:41:12 -07:00
2eb4ee8393 refactor(core): Removed depricated lockRunMode (#10763)
BREAKING CHANGE: previously deprecated lockRunMode was removed; see deprecation notice for migration instructions.
2016-08-12 17:40:22 -07:00
87fe47737a fix(testing): override metadata subclasses properly (#10767)
This fixes an issue where `TestBed.overrideComponent(MyComp, {})`
would remove some properties including `providers` from the component.

This was due to the override not properly dealing with getter fields
on subclasses.
2016-08-12 17:39:33 -07:00
9317056138 fix(ngc): Revert "fix(ngc): add an option to produce TS1.9-pathMapping imports (#10602)" (#10765)
This reverts commit beadf6167a.
2016-08-12 17:38:29 -07:00
a235ae16ed refactor(core): Removed deprecated DebugNode.inject() (#10751)
BREAKING CHANGE: previously deprecated DebugNode#inject was removed, see deprecation notice for migration instructions.
2016-08-12 15:57:23 -07:00
79afcf0766 fix(forms): remove deprecated form provider functions (#10741)
BREAKING CHANGE:

The deprecated `provideForms()` and `disableDeprecatedForms()` functions have been removed. Please import the `FormsModule` or the `ReactiveFormsModule` from @angular/forms instead.
2016-08-12 15:32:47 -07:00
161a4dd15f feat(i18n): Add NgLocaleLocalization which returns plural cases given a locale (#10744) 2016-08-12 14:46:06 -07:00
6580d67875 feat(i18n): pass translation config directly into ngc (#10622) 2016-08-12 14:45:36 -07:00
04c6b2fe85 fix(router): location changes and redirects break the back button (#10742) 2016-08-12 14:30:51 -07:00
203b2ba637 fix(http): expose jsonpFactory for AoT compilation (#10730) 2016-08-12 11:30:12 -07:00
5b99b8c18a test: add Blob and FormData polyfills for testing in IE9 (#10563) 2016-08-12 10:35:19 -07:00
6a011f4e8e test(security): work around an escaping bug in IE9 (#10493) 2016-08-12 10:34:55 -07:00
f0c1f9ef39 docs(GH): you never know... (#10740) 2016-08-12 10:33:39 -07:00
97f35714f7 feat(forms): add NgForm method that resets submit state (#10715) 2016-08-11 23:27:33 -07:00
00e5b7d30a refactor(SharedStylesHost): remove SetWrapper facade (#10598) 2016-08-11 23:26:57 -07:00
39c0f9ebb3 fix(ExtractorMerger): returns errors together with nodes (as a ParseTreeResult) 2016-08-11 23:24:22 -07:00
e60c765280 refactor: remove unused imports 2016-08-11 23:24:22 -07:00
91dd672aa4 style(xmb): add a space after ICU message cases 2016-08-11 23:24:22 -07:00
a5d2aadecb ci(travis): enable fast finish mode for optional modes. (#10588)
* Travis CI runs the optional tasks in "waiting" mode, which means that the whole build is only ready once the optional tasks are also ready.
   e.g https://travis-ci.org/angular/angular/builds/150844963 - This build lost about 48 minutes just from an optional mode.

* The Travis Fast Finish mode will mark the build as finished, once all "required" tasks have finished.
   https://blog.travis-ci.com/2013-11-27-fast-finishing-builds/
2016-08-11 23:03:28 -07:00
cc6749c158 fix(router): lazy loading keeps refetching modules (#10707) 2016-08-11 22:59:53 -07:00
f48142e679 feat(core): make ngprobe tokens pluggable 2016-08-11 22:56:10 -07:00
947f9c3f56 feat(router): make router.config public 2016-08-11 22:56:10 -07:00
7cd4741fcb fix(http): return empty string if no body is present (#10668) 2016-08-11 21:40:18 -07:00
2d520ae7e7 fix(compiler): Generate temporary variables for guarded expressions (#10657)
Fixes: #10639
2016-08-11 21:20:54 -07:00
5d59c6e80f docs(forms): fix reactive forms api examples (#10701) 2016-08-11 21:20:39 -07:00
50345b8c36 feat(i18n): add an HtmlParser decorator (#10645)
* fix(i18n): merge retains attributes w/o value

* feat(i18n): allow attributes on ng-container (i.e. i18n)

* feat(i18n): add an HtmlParser decorator

* style: clang format
2016-08-11 21:00:35 -07:00
7606c96c80 fix(forms): remove deprecated forms APIs (#10624)
BREAKING CHANGE:

The deprecated forms APIs in @angular/common have been removed. Please update to the new forms API in @angular/forms. See angular.io for more information.
2016-08-11 20:40:46 -07:00
3466232f8b fix(build): Remove duplicate System declarations (#10713)
Add it to a common .d.ts. Prevents closure from complaining of duplicate declarations when compiled using tsickle to generate externs.
2016-08-11 19:37:01 -07:00
6e842fc5bf feat(ngc): allow ngc implementations to provide XHR (#10708) 2016-08-11 15:04:00 -07:00
50c795280f fix: use a global System.import() instead of using a property of the global facade (#10696) 2016-08-11 14:17:44 -07:00
51b22cf14f chore: Fix typos in changelog for rc5 (#10688) 2016-08-11 09:02:12 -07:00
2291929a15 feat(forms): add control status classes to form groups (#10667) 2016-08-11 09:01:09 -07:00
7fac4efede chore(facades): missed a couple places in #10620 (#10661)
This lets us skip src/facade/exception* when compiling modules other than core
2016-08-11 08:39:13 -07:00
b96869afd2 refactor(Type): merge Type and ConcreType<?> into Type<?> (#10616)
Closes #9729

BREAKING CHANGE:

`Type` is now `Type<T>` which means that in most cases you have to
use `Type<any>` in place of `Type`.

We don't expect that any user applications use the `Type` type.
2016-08-10 18:21:28 -07:00
6f4ee6101c chore(imports): don't import ExceptionHandler from facade (#10620)
This lets us skip src/facade/exception* when compiling modules other than core.
It prevents having many conflicting declarations
2016-08-10 15:55:18 -07:00
6db27153ef Router Fixes (#10579)
* fix(router): copy over data during data resolution
* fix(router): components instantiated in lazy-loaded modules should use location's injector
2016-08-10 15:53:57 -07:00
9a11ec2624 fix(metadata): treat empty array of metadata like absent file (#10610) 2016-08-10 11:52:56 -07:00
aff1bc9f2d refactor(tests): move public test APIs to TestBed (#10621)
Completely remove deprecated TestComponentBuilder and friends.
2016-08-10 11:51:40 -07:00
43512aa5eb fix(i18n): ICU placeholders are replaced by their translations (#10586)
They were replaced by the original message.
2016-08-09 21:05:04 -07:00
c7f3aa71fb fix(router): support relative param-only navigation (#10613) 2016-08-09 17:03:17 -07:00
f9da3c98d6 chore: remove deprecated router 2/2 2016-08-09 15:24:14 -07:00
a20a420be6 chore: remove deprecated router 1/2 2016-08-09 15:24:14 -07:00
beadf6167a fix(ngc): add an option to produce TS1.9-pathMapping imports (#10602)
This fixes a regression in #10486
2016-08-09 14:58:19 -07:00
c8da7e995f test(router): Android browser does not support element.click() 2016-08-09 13:25:20 -07:00
8be6b12c2b test(router): use Object.isFrozen instead of relying on an exception 2016-08-09 13:25:20 -07:00
4728f29f67 test(router): increase Karma timers and add polyfills for old browsers 2016-08-09 13:25:20 -07:00
2a942e49ac chore(changelog): update convetional-changelog (#10594)
conventional-changelog-angular@1.3.0 makes breaking changes message detection more forgiving
2016-08-09 11:53:23 -07:00
e3aa19049f chore(router): update changelog 2016-08-09 11:02:04 -07:00
ef1eadadcd chore(router): bump up version number 2016-08-09 11:01:17 -07:00
f444c11d21 docs(changelog): add the ngModel is now fully async note 2016-08-09 10:54:54 -07:00
d75502eeee refactor(testing): remove deprecated test setup functions (#10600)
Remove test setup functions which were deprecated in rc5. See the
changelog for rc5 for how to update. In brief, instead of
`setBaseTestProviders`, use `TestBed.initTestEnvironment`.
2016-08-09 10:46:28 -07:00
ebcd14f8e9 docs(changelog): update change log to rc.5
Closes #10599
2016-08-09 10:34:07 -07:00
b65f66feff feat(i18n): switch to sha1 for message fingerprinting 2016-08-09 09:52:11 -07:00
dd68ae3ef1 feat(ExtractorMerger): ignore implicit tags in translatable sections 2016-08-09 09:52:11 -07:00
1b04d70626 feat(ExtractorMerger): allow nested implicit tags 2016-08-09 09:52:11 -07:00
01bca41168 fix: allow users to pass in absolute paths to ngc (#10572) 2016-08-09 09:36:37 -07:00
94e1ab33ce chore(release): update package.jsons 2016-08-09 09:33:17 -07:00
0b08dd8674 chore(animations): make sure host-prop animation deprecation is correctly emitted
Closes #10581
2016-08-08 23:39:22 -07:00
b2b47177cd add brandon suggestions 2016-08-09 03:30:25 +02:00
f08257ff4a docs(cheatsheet): update for rc5 2016-08-09 03:06:01 +02:00
d1f4222c83 docs(cheatsheet): add NgModules docs to the cheatsheet 2016-08-08 17:18:50 -07:00
d21331e902 fix(ngUpgrade): to work with @NgModule
We changed the bootstrap order:
1. create NgZone
2. bootstrap ng1 inside NgZone and upgrade ng1 components to ng2 components.
3. bootstrap ng2 with NgZone

Note: Previous footgun behavior was: bootstrap ng2 first to extract NgZone, so that ng1 bootstrap can happen in NgZone. This meant that if ng2 bootstrap eagerly compiled a component which contained ng1 components, then we did not have complete metadata.
2016-08-08 12:50:08 -07:00
37f138e83d test(ngUpgrade): convert the upgrade example to use NgModules
The example worked even before this change - verifying that the fallback/legacy mode works as well.
2016-08-08 12:20:22 -07:00
5dab0bad3c test(NgUpgrade): add support for loading plaground/upgrade example without bundles 2016-08-08 12:20:22 -07:00
85e70a4cde style(ngUpgrade): small cleanup 2016-08-08 12:20:21 -07:00
6b564ecda5 feat(ngUpgrade): add support for NgModules
BREAKING CHANGE: UpgradeAdapter.addProvider are now deprecated in favor of passing in an NgModule into the adapter's constructor

Before:

```
let upgradeAdapter = new UpgradeAdapter();
upgradeAdapter.addProviders([myProvidersArray);
```

After:

```
@NgModule({
  providers: myProvidersArray
})
class MyModule {}

let upgradeAdapter = new UpgradeAdapter(MyModule);
```
2016-08-08 12:17:35 -07:00
d4cceff0ef chore: remove module aware bootstrap API (#10543)
This API was introduced post RC4, but needs to be removed
before RC5 as we have decided against it.
2016-08-08 09:36:09 -07:00
a415613457 fix(router): update dts files 2016-08-08 09:15:59 -07:00
1a41bd1ca4 feature(router): add route.root returning the root of router state 2016-08-08 09:15:59 -07:00
5a99393355 fix(router): route.parent should work for secondary children 2016-08-08 09:15:59 -07:00
afcb3c0035 fix(router): support outlets in non-absolute positions 2016-08-08 09:15:59 -07:00
d2d36c61f3 fix(router): fix matrix params check to handle 'special' objects 2016-08-08 09:15:59 -07:00
0bd97ecda2 feat(http): add options method to Http (#10540)
Add options method to the Http object, which could be useful when using self-describing RESTful APIs.

This closes #10500, closes #7918
2016-08-08 09:15:13 -07:00
46bbcefb36 fix(linker): prevent pollution of empty embeddedView context (#10548)
Fixes #10045
2016-08-08 09:11:35 -07:00
74b57dfa7d refactor(i18n): remove circular dep 2016-08-05 13:39:54 -07:00
8c9c0986e9 refatcor(digestMessage): takes a i18n.Message 2016-08-05 13:39:54 -07:00
4028fcaa51 refactor(i18n): Drop html.Message and create i18n.Message right away 2016-08-05 13:39:54 -07:00
7a8ef1eae5 feat(i18n): merge translations 2016-08-05 13:39:54 -07:00
e811a5d97f refactor(i18n): misc updates 2016-08-05 13:39:54 -07:00
df44e3e425 fix(i18n extractor): array manipulation 2016-08-05 13:39:54 -07:00
cdb1a237e5 refactor(compiler): html_parser -> ml_parser 2016-08-05 13:39:54 -07:00
fcafdff10b feat(forms): allow both patching and strict setting of values (#10537) 2016-08-05 13:35:17 -07:00
c586656d43 fix(router): fix type definition 2016-08-05 13:12:21 -07:00
3a307c2794 fix(router): absolute redirects should work with lazy loading 2016-08-05 13:12:21 -07:00
4f17dbc721 fix(router): add segmentPath to the link DSL 2016-08-05 13:12:21 -07:00
99989f5d3f chore(facade): remove most facade/async functions 2016-08-05 12:26:28 -07:00
6baf3baedd chore(playground): clang-format 2016-08-05 12:26:28 -07:00
0d1f3c3b07 fix: support trailing slash in basePath (#10533) 2016-08-05 11:11:24 -07:00
83e2d3d1cb refactor(RegExpWrapper): remove the facade (#10512) 2016-08-05 09:50:49 -07:00
b4613ab2d2 fix(ExpressionParser): undefined is undefined (was null) 2016-08-05 09:45:13 -07:00
0ca05eee45 feat(ExpressionParser): add support for this 2016-08-05 09:45:13 -07:00
26c9e1dc70 refactor(NgFor spec): code cleanup 2016-08-05 09:45:13 -07:00
797cb5ae7b refactor(NgStyleSpec): simplify NgStyle tests (#10519) 2016-08-05 09:28:08 -07:00
63b82cd730 feat(router): Allow navigation without updating the URL (#9608) 2016-08-04 11:46:09 -07:00
2b704f0586 fix(linker/compiler): rename const to avoid duplicate declaration (#10457)
Currently in the `linker/compiler.ts` file, the **same identifier** is used in **two declarations**:
```typescript
export type CompilerOptions = { … }
…
export const CompilerOptions = new OpaqueToken('compilerOptions');
```
This breaks the API doc generation. I’m surprised that this was not flagged by the tsc.

The duplicate declaration was introduced in 46b212706b.
2016-08-04 11:31:58 -07:00
ce5ba80792 refactor(NgTemplateOutlet): simplify implementation (#10492) 2016-08-04 11:28:36 -07:00
8b18ef4ba2 feat(NgStyle): add support for the style.unit notation (#10496)
Closes #10326
2016-08-04 11:00:43 -07:00
cd18de7a21 refactor(compiler): use Object.keys instead of Object.getOwnPropertyNames (#10498) 2016-08-04 10:35:41 -07:00
fd19671c07 chore(benchpress): clang-format and lint 2016-08-04 10:08:37 -07:00
3fcd6fd93f chore(benchpress): make benchpress compile
Also adds compiling benchpress to the build scripts to verify that.
2016-08-04 10:08:37 -07:00
c8d53d71a3 fix(ngc): gather metadata for OpaqueToken
Fixes #10482
2016-08-04 10:05:25 -07:00
790362e243 fix: put all ngc files into a single directory (#10486)
Prior to this change `ngc` would place generated files which refer
to components in the node_modules into the node_module. This is an
issue. Now all of the files are forced into a single directory
as specified in `tsconfig.json` by the `genDir` option.

see: https://docs.google.com/document/d/1OgP1RIpZ-lWUc4113J3w13HTDcW-1-0o7TuGz0tGx0g
2016-08-03 21:34:03 -07:00
2eda7a5293 fix(router): provideRouter should use provideRoutes (#10488) 2016-08-03 19:35:12 -07:00
9925aa89dc fix(compiler): Report references to non-exported symbols.
Includes fixes to places now reported as errors.

Part of #8310
2016-08-03 15:42:38 -07:00
6195a45ae2 fix(forms): export AbstractFormGroupDirective
Because
- `Form` is **exported** -- see line 30/31 of
`modules/@angular/forms/src/forms.ts`: i.e., <br>`export {Form} from
'./directives/form_interface'`; and
- Methods of `Form`, which are public, have an
`AbstractFormGroupDirective` parameter;
e.g.,<br>`Form.getFormGroup(dir: AbstractFormGroupDirective):
FormGroup`.

Then it makes sense for `AbstractFormGroupDirective` to be
public/exported too. In any case, if it isn't exported then the **API
docs for `Form` don't get generated properly.**
2016-08-03 15:33:29 -07:00
422d380b3e feat(router): add queryParams and fragment to every activated route 2016-08-03 15:30:03 -07:00
550ab31bd0 feat(router): add parent, children, firstChild to ActivatedRoute 2016-08-03 15:30:03 -07:00
5fceb21549 refactor(router): remove dead code 2016-08-03 15:30:03 -07:00
29caa37943 feat(router): support sibling modules providing routes 2016-08-02 13:31:15 -07:00
8efbcc996a fix(compiler): allow to use pipes inside of *ngIf (#10452)
Fixes #9746
2016-08-02 12:19:34 -07:00
91c64d2b8d fix: missing export for validators 2016-08-02 12:12:15 -07:00
82e7ecd611 fix(compiler): StaticReflect now resolves re-exported symbols (#10453)
Fixes: #10451
2016-08-02 11:45:14 -07:00
3d53b33391 chore: update public api and integrate minor review comments 2016-08-02 11:23:26 -07:00
34624b2db2 refactor(core): deprecate old methods on ApplicationRef
BREAKING CHANGE:
- `ApplicationRef.run` is deprecated. Use `NgZone.run` directly
- `ApplicationRef.injector` is deprecated. Inject an `Injector` or
  use `NgModuleRef.injector` instead
- `ApplicationRef.zone` is deprecated. Inject `NgZone` instead.
2016-08-02 11:23:26 -07:00
1ab5eb0844 refactor(core): don’t use zone.run in ApplicationRef.bootstrap.
`ApplicationRef.bootstrap` is supposed to be run inside of `ngDoBootstrap` method
of the module that is bootstrapped, and that method already runs inside of the
zone.
2016-08-02 11:23:26 -07:00
630028350a refactor(core): Introduce AppInitStatus
This class allows any provider to know and wait for the initialization of the
application. This functionality previously was tied to `ApplicationRef`.

BREAKING CHANGE:
- `ApplicationRef.waitForAsyncInitializers` is deprecated. Use 
  `AppInitStatus.donePromise` / `AppInitStatus.done` instead.
2016-08-02 11:23:26 -07:00
7e4fd7d7da refactor(core): introduce @NgModule.bootstrap and ngDoBootstrap method
If a `@NgModule` has a `bootstrap` property, `PlatformRef.bootstrapModule` /
`PlatformRef.bootstrapModuleFactory` will automatically bootstrap the components
listed in there.
If such a property does not exist, `PlatformRef.bootstrapModule` /
`PlatformRef.bootstrapModuleFactory` will try to call the method `ngDoBootstrap(appRef: ApplicationRef)` on the module class.
Otherwise an error is reported.
2016-08-02 11:23:26 -07:00
af2e80e068 refactor(core): introduce APP_BOOTSTRAP_LISTENER multi provider
Using the `registerBootstrapListener` easily lead to race condition
and needed dependencies on `ApplicationRef`.

BREAKING CHANGE:
- `ApplicationRef.registerBootstrapListener` is deprecated. Provide a multi
  provider for the new token `APP_BOOTSTRAP_LISTENER` instead.
2016-08-02 11:23:26 -07:00
8e6091de6c refactor(core): use ngOnDestroy in providers
Note about the addition of `beforeEach(fakeAsync(inject(…))))` in some tests:
`ApplicationRef` is now using `ngOnDestroy` and there is eager,
including all of its dependencies which contain `NgZone`.
The additional `fakeAsync` in `beforeEach` ensures that `NgZone`
uses the fake async zone as parent, and not the root zone.

BREAKING CHANGE (via deprecations):
- `ApplicationRef.dispose` is deprecated. Destroy the module that was
   created during bootstrap instead by calling `NgModuleRef.destroy`.
- `AplicationRef.registerDisposeListener` is deprecated.
   Use the `ngOnDestroy` lifecycle hook for providers or
   `NgModuleRef.onDestroy` instead.
- `disposePlatform` is deprecated. Use `destroyPlatform` instead.
- `PlatformRef.dipose()` is deprecated. Use `PlatformRef.destroy()`
   instead.
- `PlatformRef.registerDisposeListener` is deprecated. Use
  `PlatformRef.onDestroy` instead.
- `PlaformRef.diposed` is deprecated. Use `PlatformRef.destroyed`
  instead.
2016-08-02 11:23:26 -07:00
ecdaded25f feat(core): introduce NgModuleRef.destroy and call ngOnDestroy on all providers 2016-08-02 11:23:26 -07:00
c161ed415d feat(core): support ngOnDestroy on providers of a directive.
Such providers also become eager as they will be instantiated
anyways on destruction.
2016-08-02 11:23:26 -07:00
ff3b71f7b3 refactor(core): collect lifecycle hooks for all injectable classes 2016-08-02 11:23:26 -07:00
16cc9b46aa fix(fake_async): share zone between beforeEach and it
This is needed for the case if a `beforeEach` instantiates
`NgZone`and the `it` uses
`TestComponentBuilder.createFakeAsync`.

Otherwise the `NgZone` will use the root zone as parent,
and `TestComponentBuilder.createFakeAsync` will always return
undefined as `tick` does not forward promises created
under the zone of `NgZone`.
2016-08-02 11:23:26 -07:00
3ce11ed58c docs(pipes): update I18nSelectPipe API documentation (#10449) 2016-08-02 10:59:07 -07:00
7db75fa361 test: reactivate some of the disabled tests in Edge (#10450) 2016-08-02 10:58:03 -07:00
d6d4568830 fix(forms): allow arrays as parents (#10440)
Closes #10432
2016-08-02 09:40:42 -07:00
a55d796c4b fix: Better error message in case of unknown property binding 2016-08-02 09:28:04 -07:00
73f02c7861 fix: throw useful error on missing platform module. 2016-08-02 09:28:04 -07:00
8c8754e573 chore: add browserNoRouter test running mode 2016-08-02 09:28:04 -07:00
c977a906b3 docs(cheatsheet): add moduleId (#10095) 2016-08-02 07:34:04 -07:00
e0eea6c2f4 feat(forms): add invalid prop to abstract controls (#10439) 2016-08-01 18:41:25 -07:00
3e377f520e fix(router): make an outlet to unregister itself when it is removed from the dom 2016-08-01 16:56:38 -07:00
8dc82a0080 fix(router): fix offline compilation by exporting provideLocationStrategy 2016-08-01 16:23:28 -07:00
4624a35845 docs(router): fixes api docs 2016-08-01 16:23:28 -07:00
8d4499959a feat(forms): add get method for easy access to child controls (#10428) 2016-08-01 14:22:50 -07:00
2dfc9c653b refactor: dart 2016-08-01 11:34:51 -07:00
106db0aba8 refactor: IS_DART === false 2016-08-01 11:34:51 -07:00
28c4852cd6 refactor: remove ts2dart annotations 2016-08-01 11:34:51 -07:00
13c8211065 fix: String.split(str, n) stops after n separator (#10408) 2016-08-01 11:33:35 -07:00
e73d0511cf fix(TemplateParser): report empty expression (#10391)
fixes #3754
2016-08-01 11:24:49 -07:00
e18626b7a2 fix(core): ensure ngFor only inserts/moves/removes elements when necessary (#10287)
Closes #9960
Closes #7239
Closes #9672
Closes #9454
Closes #10287
2016-08-01 11:09:52 -07:00
4df7b1cfbc chore: fixes some issues that happen with closure compiler. (#10392) 2016-08-01 09:47:49 -07:00
f9573ece41 ci(browser providers): update browsers in SL and BS (#10425) 2016-08-01 08:00:12 -07:00
93ade740e2 fix(router): configure DI correctly when using the old provideRouter function 2016-08-01 02:35:41 -07:00
a46437c57d refactor(core): fix bootstrapModule regarding zones and initializers (#10383)
This makes `bootstrapModuleFactory` wait for promises
returned by `APP_INITIALIZER`s, also making `bootstrapModuleFactory` async.
I.e. now `bootstrapModule` and `bootstrapModuleFactory` behave in the
same way.

This ensures that all code from module instantiation, to creating
`ApplicationRef`s as well as calling `APP_INITIALIZERS` is run
in the Angular zone.

This also moves the invocation of the initializers from the `ApplicationRef`
constructor into the `bootstrapModuleFactory` call, allowing initializers
to get a hold of `ApplicationRef` (see #9101).

Fixes #9101
Fixes #10363
Fixes #10205
2016-08-01 02:12:59 -07:00
633c7d1ebe refactor(core): cleanup unused NgZone factory
This factory was only used when using `coreBootstrap` / `coreLoadAndBoostrap`
which is not supported any more.
2016-08-01 02:12:59 -07:00
251953218c fix(http): URLSearchParams.clone propagate the QueryEncoder (#9900) 2016-07-30 19:01:20 -07:00
0d6cc17252 fix(UrlParser): stop setting default value 'true' (#10399) 2016-07-30 14:34:03 -07:00
c8989c900f chore(github): remove reference to Dart in the issue template (#10388) 2016-07-30 00:22:04 -07:00
6134320f16 refactor(http): rewrite for readable & efficient. 2016-07-29 21:30:28 -07:00
7f647822bd fix(http): headers should be case-insensitive.
fixes #9452

spec at https://tools.ietf.org/html/rfc2616
2016-07-29 21:30:15 -07:00
e34a04d2ad feat(xmb/xtb): support dtd 2016-07-29 14:18:34 -07:00
44093905e2 refactor(test): refine types 2016-07-29 13:53:13 -07:00
3e2900f74b refactor(i18n): move code around 2016-07-29 13:40:58 -07:00
11fd2eccec refactor: fix merge glitches 2016-07-29 13:40:58 -07:00
0eee1d5de3 feat(i18n): xtb serializer 2016-07-29 13:40:58 -07:00
1b77604ee2 refactor(compiler): re-arrange files 2016-07-29 13:40:58 -07:00
cc5cfe87c3 feat(i18n): xmb serializer 2016-07-29 13:40:58 -07:00
48f230a951 feat(I18nAst): introduce an intermediate AST 2016-07-29 13:40:58 -07:00
2be50bdbb0 refactor(i18n): message extractor
fixes #8802
2016-07-29 13:40:58 -07:00
f7258ea52a test(HtmlAst): add a serializer 2016-07-29 13:40:58 -07:00
28e8b2faab feat(ICU): extract ICU messages 2016-07-29 13:40:58 -07:00
3c3e9ddb10 feat(router): add a validation to make sure pathMatch is set correctly 2016-07-29 12:27:43 -07:00
5162fb6d52 feat(router): add isActive to router 2016-07-29 12:27:43 -07:00
2fdb39e60a feat(router): activateroute should expose its route config 2016-07-29 12:27:43 -07:00
43c71ae103 fix(platform-browser): IEMobile is badly detected when testing (#10382) 2016-07-29 10:05:12 -07:00
f0bd528d77 test(http): fix Blob creation for Android <= 4.3
Closes #10377
2016-07-29 18:20:09 +02:00
50a024b42f test(http): add Typed Array polyfill for IE9 2016-07-29 18:19:54 +02:00
b48f7bcb8d fix(forms): normalize written value in NumberValueAccessor
Closes #10379
2016-07-29 18:18:30 +02:00
763ca60f5b feat(compiler): Support default parameters in static reflector (#10370)
Closes: #10369
2016-07-29 09:10:45 -07:00
0eca7abdd8 chore: update public api
Closes #10355
2016-07-29 04:47:50 -07:00
d0a95e35af refactor(testing): introduce new testing api to support ng modules
BREAKING CHANGE:
- deprecations:
  * `withProviders`, use `TestBed.withModule` instead
  * `addProviders`, use `TestBed.configureTestingModule` instead
  * `TestComponentBuilder`, use `TestBed.configureTestModule` / `TestBed.override...` / `TestBed.createComponent` instead.

Closes #10354
2016-07-29 04:47:18 -07:00
acc6c8d0b7 feat(compiler): introduce MockDirectiveResolver.setDirective 2016-07-29 04:47:18 -07:00
3dbc66c1ac refactor(core): introduce interfaces for constructor arguments of decorators
For @Directive, @Component, @Pipe, @NgModule
2016-07-29 04:47:18 -07:00
4ad6bcce54 feat(compiler): add MockPipeResolver 2016-07-29 04:47:17 -07:00
0988cc82b0 refactor(core): remove ViewResolver and ViewResolverMock
The methods on `ViewResolverMock` have been merged into `DirectiveResolver`.

BREAKING CHANGE:
- ES5 users can no longer use the `View(…)` function to provide `ViewMetadata`.
  This mirrors the removal of the `@View` decorator a while ago.
2016-07-29 04:47:17 -07:00
20b03bad11 feat(compiler): Added support for conditional expressions. (#10366)
Expression evaluated by the static reflector can now supports
conditional expressions.

Closes: #10365
2016-07-28 17:32:29 -07:00
81d27daf0d fix(router): update dts files 2016-07-28 15:03:19 -07:00
bb8b82b3f5 fix(router): relax type defintion of Route to improve dev ergonomics 2016-07-28 15:03:19 -07:00
915a6666f8 fix(core): fix offline detection in ng_module_factory_loader 2016-07-28 15:03:19 -07:00
72da547d6a fix(router): updates router module to be offline-compilation friendly 2016-07-28 15:03:19 -07:00
7c76a75452 fix(forms): update dirty before emitting value change (#10362)
Closes #5328
2016-07-28 14:25:33 -07:00
a32c4ad2f0 fix(compiler): auto declare entryComponents recursively
Closes #10348
2016-07-28 12:03:34 -07:00
fb3608aa5d fix(compiler): report better error messages for host bindings
Closes #10346
2016-07-28 11:21:50 -07:00
0a46f37444 fix(metadata): fix typechecking with typescript@next 2016-07-28 11:17:53 -07:00
9b39e499ac fix(core): support components without a selector (#10331)
Components without a selector now get the selector `ng-component`.
Directives without a selector will throw an error message.

Closes #3464
Closes #10216
2016-07-28 10:39:10 -07:00
a67cc8229d chore: move injector to being non-internal but private (#10339)
* chore: move injector to being non-internal but private

* Add the new non-internal method to the public API.
2016-07-28 10:38:29 -07:00
b58e9ea775 feat(compiler): Added support for references to static fields. (#10334)
Closes: #10332
2016-07-27 19:26:59 -07:00
422effdd18 refactor(http): use ngModules for http (#10329) 2016-07-27 13:09:05 -07:00
3b690b68a6 fix(testing): Fix error message in test bed
The API name in the error message was wrong
2016-07-27 12:03:27 -07:00
43349dd373 fix(forms): improve ngModel error messages (#10314) 2016-07-27 10:59:40 -07:00
e44e8668ea fix(core): only warn and auto declare undeclared entryComponents.
This is needed to support existing applications.
After final these warnings will become errors.

Closes #10316
2016-07-27 10:56:12 -07:00
69e72c0786 chore: remove browserDynamicTestingPlatform as it is deprecated and was not part of rc.4
Closes #10319
2016-07-27 10:52:47 -07:00
553344739c fix(core): allow module providers to overwrite providers from ModuleWithProviders
Fixes #10313
Closes #10317
2016-07-27 10:51:58 -07:00
367f0fd142 fix(static_reflector): report methods with decorators in propMetadata as well
This was the behavior of our regular reflector as well, although the
method name does not imply this.

Fixes #10308
Closes #10318
2016-07-27 10:50:58 -07:00
58d9e7fc5a feat(facade): add support for all thenables (#10278)
All objects that have a then function will be considered Promises
2016-07-27 10:37:48 -07:00
9d9e9c6ff1 refactor(router): take advantage of the new way of configuring modules 2016-07-27 10:24:29 -07:00
ba88db5141 fix(ngClass): do not deconstruct classes on element removal (#10303)
Prior to this fix [ngClass] would remove all dynamic classes
when destroyed. It's essential that classes are persisted such
that remove-based animations will still be stylistically correct.
This patch fixes this issue.

Closes #10008
Closes #10303
2016-07-26 15:20:27 -07:00
62e7c0f464 feat(router): implement canLoad 2016-07-26 14:39:02 -07:00
fc83bbbe98 fix(compiler): treat custom elements as unknown elements by default
Closes #10300
2016-07-26 12:31:22 -07:00
482c019199 feat(security): only warn when actually sanitizing HTML. (#10272)
Previously, Angular would warn users when simply re-encoding text
outside of the ASCII range. While harmless, the log spam was annoying.

With this change, Angular specifically tracks whether anything was
stripped during sanitization, and only reports a warning if so.

Fixes #10206.
2016-07-26 11:39:09 -07:00
b449467940 feat(compiler): Allow calls to simple static methods (#10289)
Closes: #10266
2016-07-26 10:18:35 -07:00
0aba42ae5b fix(forms): throw error if wrong control container for reactive forms (#10286) 2016-07-26 10:08:46 -07:00
0d1bf8148b fix(animations): ensure animation detection doesn't rely on the body node
Closes #10230
Closes #10191
Closes #10273
2016-07-26 09:33:50 -07:00
b42411ba1f chore: update public api
- `precompile` -> `entryComponents`
- introduce `ModuleWithProviders`
- introduce `@NgModule.schema`
- update to bootstrap

Closes #10268
2016-07-26 07:45:40 -07:00
5a21f168d6 refactor(core): change bootstrap of modules and names of platforms
BREAKING CHANGES:
- `browserPlatform`/`browserDynamicPlatform`/... have been deprecated and renamed into `platformBrowser`/`platformBrowserDynamic`/....
- `bootstrapModule` and `bootstrapModuleFactory` have been moved to be members of `PlaformRef`.
  E.g. `platformBrowserDynamic().bootstrapModule(MyModule)`.
2016-07-26 07:28:55 -07:00
00b726f695 refactor(core): introduce NgModule.schemas
This allows Angular to error on unknown properties,
allowing applications that don’t use custom elements
to get better error reporting.

Part of #10043

BREAKING CHANGE:
- By default, Angular will error during parsing
  on unknown properties,
  even if they are on elements with a `-` in their name
  (aka custom elements). If you application is using
  custom elements, fill the new parameter `@NgModule.schemas`
  with the value `[CUSTOM_ELEMENTS_SCHEMA]`.

  E.g. for bootstrap:
  ```
  bootstrap(MyComponent, {schemas: [CUSTOM_ELEMENTS_SCHEMA]});
  ```
2016-07-26 07:04:36 -07:00
f02da4e91a feat(core): introduce ModuleWithProviders.
Modules can now provider helper functions that allow
to import a module together with an array of providers.

Part of #10043
2016-07-26 07:04:36 -07:00
d6b65db9a7 fix(static_reflector): resolve values of functions in the function context 2016-07-26 07:04:36 -07:00
6f4e49ed53 refactor(core): rename precompile into entryComponents.
Part of #10043

BREAKING CHANGE:
- `@Component.precompile` was renamed to `@Component.entryComponents`
  (old property still works but is deprecated)
- `ANALYZE_FOR_PRECOMPILE` was renamed to `ANALYZE_FOR_ENTRY_COMPONENTS` (no deprecations)
2016-07-26 07:04:36 -07:00
46b212706b refactor(core): change module semantics
This contains major changes to the compiler, bootstrap of the platforms
and test environment initialization.

Main part of #10043
Closes #10164

BREAKING CHANGE:
- Semantics and name of `@AppModule` (now `@NgModule`) changed quite a bit.
  This is actually not breaking as `@AppModules` were not part of rc.4.
  We will have detailed docs on `@NgModule` separately.
- `coreLoadAndBootstrap` and `coreBootstrap` can't be used any more (without migration support).
  Use `bootstrapModule` / `bootstrapModuleFactory` instead.
- All Components listed in routes have to be part of the `declarations` of an NgModule.
  Either directly on the bootstrap module / lazy loaded module, or in an NgModule imported by them.
2016-07-26 07:04:10 -07:00
ca16fc29a6 build: fix and document the symlinks scripts for Windows
Closes #10213
2016-07-26 09:52:11 +02:00
9edea0b139 fix(ng upgrade): do not compile ng2 components until after ng1 bootstrap (#10084)
Closes #9407 and angular/protractor#2944
2016-07-25 21:14:35 -07:00
d15a1d64e1 fix(router): make router provides work with cli and offline compilation 2016-07-25 18:04:22 -07:00
c87847974a chore(forms): separate out tests for reactive forms (#10283) 2016-07-25 15:57:51 -07:00
6f68330fa5 feat(router): rename UrlPathWithParams into UrlSegment
BREAKING CHANGE:

UrlPathWithParams => UrlSegment
UrlSegment => UrlSegmentGroup
2016-07-25 12:15:07 -07:00
2b63330a36 fix(router): handle when both primary and secondary are empty-path and primary has a child 2016-07-22 18:51:35 -07:00
06e4ca4bb3 fix(router): advance query params and fragment after advanced routes 2016-07-22 18:51:35 -07:00
43437c175a fix(router): handle url fragments when no url segments present 2016-07-22 18:51:35 -07:00
8d90a5a4cf fix(router): router link active should take all descendants into account 2016-07-22 18:51:35 -07:00
93a4ca652a refactor(router): renames PRIMARY_OUTLET into primary 2016-07-22 18:51:35 -07:00
41178367d1 feat(HtmlLexer): better hint on unclosed ICU message errors
fixes #10227
2016-07-22 17:27:15 -07:00
54f2edbb90 refactor(Lexer): code cleanup 2016-07-22 16:50:54 -07:00
b652a7fc9f chore: remove obsolete files (#10240) 2016-07-22 16:18:31 -07:00
e34eb4520f fix(testing): ComponentFixture - Avoid extra scheduleMicrotask (#10223)
Don't schedule microtask to check for pending macrotasks when no one is waiting for a whenStable().
2016-07-22 16:07:11 -07:00
190bcc89c1 refactor(EventEmitter): optional emits (#10058)
the Subject#next is optional
2016-07-22 10:19:57 -07:00
64fc4648b7 fix(testing): correctly import NgMatchers (#10077)
Some test cases incorrectly rely on the side effect of other test cases
importing `NgMatchers`. This commit fixes this by making `expect` in
`core/testing_internal` properly typed.
2016-07-22 09:20:51 -07:00
bdb59129d0 feat(http): add content-type override support for http request (#10211) 2016-07-22 08:37:32 -07:00
d455942389 fix(CurrencyPipe): use default Intl formatting options when none provided
fixes #10189
2016-07-22 08:21:31 -07:00
cdb3678fe3 chore(tools): remove unused files 2016-07-22 08:20:46 -07:00
e73ac1e992 chore(Dart): remove obsolete files, update the docs 2016-07-22 08:20:46 -07:00
51f3d22e4f feat(security): trust resource URLs as URLs. (#10220)
Resource URLs are strictly "more" trustworthy than plain URLs, so trusting them maintains the same level of security while avoiding to break people when we downgrade a resource URL context to a plain URL context.
2016-07-21 17:44:59 -07:00
00aa7a76b6 chore(tests): enable lint, make it green. (#10224) 2016-07-21 17:12:00 -07:00
27b87ef535 fix(router): throw when cannot parse a url 2016-07-21 16:14:55 -07:00
44709e0dca fix(router): handle urls with only secondary top-level segments 2016-07-21 16:14:44 -07:00
31a7709ece test: execute router tests on ./test.sh browser (#10053) 2016-07-21 16:12:40 -07:00
a441b5b8fe feat(security): categorize <track src> as a regular URL.
After security review, it turns out we were too paranoid about <track src>. Its content is not actually active or dangerous.

Fixes #10089.
2016-07-21 13:53:35 -07:00
76b8a49bfb feat(http): add support for blob as a response type (#10190) 2016-07-21 13:44:38 -07:00
db54a84d14 fix(router): routerLinkActive should only set classes after the router has successfully navigated 2016-07-20 17:51:21 -07:00
eb6ff65af7 refactor(router): makes an error message clearer 2016-07-20 14:47:51 -07:00
23ee29b6a2 fix(router): navigation should not preserve query params and fragment by default
BREAKING CHANGE

Previously both imperative (router.navigate) and declarative (routerLink) navigations
would preserve the current query params and fragment. This behavior turned out to
be confusing. This commit changes it.

Now, neither is preserved by default. To preserve them, you need to do the following:

router.naviage("newUrl", {preserveQueryParams: true, preserveFragment: true})

<a routerLink="newUrl" preserveQueryParams preserveFragment></a>
2016-07-20 14:30:04 -07:00
73a69895d8 cleanup(router): removes unnecessary files from tsconfig 2016-07-20 11:44:07 -07:00
2799e7a3ca refactor(router): rename RouterTestModule into RouterTestingModule 2016-07-20 11:39:31 -07:00
b43f95435b fix(testing): add an explicit doAsyncPrecompilation step (#10015)
This removes the magic from the `inject` test helper that would inspect
the current zone and would only work with our `async` test helper.
Now, `inject` is always synchronous, and if you are using a module
that requires async precompilation, you're required to call
`doAsyncPrecompilation` in your tests.

This is part of the breaking changes introduced with the swap
to each test having an AppModule.

Closes #9975
Closes #9593

BREAKING CHANGE:

`TestInjector` is now renamed to `TestBed`

Before:

```js
import {TestInjector, getTestInjector} from '@angular/core/testing';
```

After:

```js
import {TestBed, getTestBed} from '@angular/core/testing';
```
2016-07-20 10:51:21 -07:00
450f61d384 docs(router): fix provider token (#10177) 2016-07-20 07:27:09 -07:00
f3dd91e1d7 feat(NumberPipe): add string support (#10163)
fixes #10159
2016-07-19 11:27:06 -07:00
979946c062 fix(testing): Add platform directives to the shim that keeps setBaseTestProviders running (#10154)
Due to daa9da4047,
tests using the setBaseTestProviders stopped working with ambient directives such as
`ngIf`. Add them back in to keep the shim working.
2016-07-19 08:59:14 -07:00
51e661eb74 fix(router): export navigation extras 2016-07-18 17:42:04 -07:00
921a17960c fix(router): lazy loaded components should use loaded injector 2016-07-18 17:42:04 -07:00
7a4f6621ed fix(router): handle lastPathIndex of empty-path routes 2016-07-18 17:42:04 -07:00
83bc5c97ef fix(http): convert objects passed to requests into a string (#10124)
This remove a breaking change introduced with commit #e7a8e2757b06d572f614f53b648d2fd75df370d2 where json objects passed to  requests were not converted into string.

BREAKING CHANGE:

The behavior in this commit is the same as before PR 7260 : the objects sent with the request are converted to a string, therefore there is no need for the user to take care of the serialization.

Fixes #10073
2016-07-18 14:20:03 -07:00
3f08efa35d fix(KeyValueDiffer): check for changes
fixes #9115
2016-07-18 11:30:07 -07:00
0914dc35e8 refactor(Differ): cleanup 2016-07-18 11:30:07 -07:00
b6746cce9c refactor(decorators): cleanup 2016-07-18 10:38:59 -07:00
8cd97c2054 refactor(NgFor): cleanup 2016-07-18 10:38:59 -07:00
32d8cde9c6 docs(NgSwitch): fix typo ngSwitch to NgSwitch (#10143) 2016-07-18 10:24:55 -07:00
1803ed2512 fix(router): fix rollup config to properly set up rxjs 2016-07-15 16:27:54 -07:00
f08060b0b0 fix(router): back button does not work in IE11 and Safari 2016-07-15 14:59:59 -07:00
b77a4a40a4 fix(router): expose initalNavigation and dispose so they can be used with webworkers 2016-07-14 17:29:01 -07:00
e1109d52e1 docs(router): update the docs of LocationPathStrategy 2016-07-14 15:00:50 -07:00
0668ba50e8 fix(router): freeze params and queryParams to prevent common source of bugs 2016-07-14 13:33:05 -07:00
44ff005ce3 doc(developer): updates (#10075) 2016-07-14 08:51:05 -07:00
aa88438b54 feat(Router): add extra validation for when route was passed as Array (#9942) 2016-07-14 08:28:31 -07:00
85be729c70 fix(router): lazily-loaded modules should use loaded injectors instead of the root one 2016-07-13 18:25:30 -07:00
a5dc5705a3 feat(router): guards and data resolvers can now return promises 2016-07-13 18:25:30 -07:00
9e3d13f61f feat(router): add support for canActivateChild 2016-07-13 18:25:30 -07:00
961c9d48ae fix(compiler): Query expression lambdas should have dynamic type
Fixes: #9875
2016-07-13 15:41:30 -07:00
9229bbbc80 Revert "fix(compiler): Generates function expressions as returning any (#9980)"
This reverts commit eb5763c23f.
2016-07-13 15:41:30 -07:00
34feecf60e fix(forms): improve no value accessor error message (#10051) 2016-07-13 14:13:02 -07:00
4c762a6be3 chore(lint): enable lint check for duplicate vars 2016-07-13 12:33:39 -07:00
0426325ef7 fix(router): merge SystemJsAppModuleFactoryLoader and SystemJsAllModuleLoader 2016-07-13 11:16:46 -07:00
0b54e3cf0a fix(router): do not fire events on 'duplicate' location events 2016-07-13 11:16:46 -07:00
5cf58971f1 fix(router): update current state and url before activating components 2016-07-13 11:16:46 -07:00
6518ff88b2 fix(compiler): No longer writes 0 length files outside of genDir (#10023)
Fixes: #9984
2016-07-13 11:15:23 -07:00
42b0c1d8a2 refactor: misc cleanup (#10046) 2016-07-13 11:01:32 -07:00
4a965052f9 fix(platform-browser): remove testing_e2e target (#10029)
The testing_e2e util does not belong in platform-browser and was never
intended to be a public API. Move it out of that whole tree.

BREAKING CHANGE:

The following API was never intended to be public and is removed:

```js
import {verifyNoBrowserErrors} from '@angular/platform-browser/testing_e2e';
```

Consider using Protractor's console plugin: https://github.com/angular/protractor-console-plugin
2016-07-13 10:10:02 -07:00
5725c5925c docs(ExceptionHandler): Update code example in comment block to correct syntax error. (#10032) 2016-07-13 07:28:08 -07:00
a46291b67c docs(router) Added @Injectable decorators to Router API examples (#10033) 2016-07-13 07:27:32 -07:00
4ac76ca281 docs(router): fix syntax in code example of comment block (#10026) 2016-07-13 07:26:26 -07:00
e7a8e2757b refactor(http): share 'body' logic between Request and Response 2016-07-12 18:01:06 -07:00
1266460386 feat(http): add support for ArrayBuffer
Add the buffer option to store response in ArrayBuffer
Improve the interface to get back response independently of the buffer type
2016-07-12 18:01:06 -07:00
0ccb6e0dfc refactor: code cleanup 2016-07-12 16:57:39 -07:00
3050ae155c feat(ICU): enable ICU extraction even when when in is not used
BREAKING CHANGES:

"{" is used a a delimiter for ICU messages then it could not be used in text nodes.
"{" should be escaped as "{{ '{' }}"

Before:

    <span>some { valid } text</span>

After:

    <span>some { invalid } text<span> <!-- throw parse error -->
    <span>some {{ '{' }} valid } text</span>
2016-07-12 16:57:39 -07:00
402fd934d0 refactor: code cleanup 2016-07-12 15:26:03 -07:00
6c86e8d80a test(HtmlLexer): Add test for "{" and "{{" escaping 2016-07-12 15:26:03 -07:00
60e6f91a53 refactor(HmtlLexer): cleanup 2016-07-12 15:26:03 -07:00
e676fded21 refactor(Lexer): add types
relates to #9100
2016-07-12 15:26:03 -07:00
25e070dd65 fix(HtmlParser): correctly propagate the interpolation config across layers 2016-07-12 15:26:03 -07:00
da8eb9f8b8 feat(forms): add ability to reset forms (#9974)
Closes #4914
Closes #4933
2016-07-12 15:02:25 -07:00
806a25413c feat(animations): allow animation integration support into host params
Closes #9044
Closes #9933
2016-07-12 14:55:36 -07:00
5af1e891cd fix(animations): throw errors when duplicate component trigger names are registered 2016-07-12 14:55:31 -07:00
79eda30f0f refactor(animations): collect parser / lookup errors in the same place 2016-07-12 14:55:27 -07:00
6d02d2f107 fix(SyncAsyncResult): fix default async value (#10013) 2016-07-12 13:55:06 -07:00
ded518d47f feat(router): update routerLink DSL to handle aux routes 2016-07-12 11:44:55 -07:00
27436270fd fix(Compiler): Catch exceptions in the logging of binding update
fixes #9994
2016-07-12 11:21:32 -07:00
b4ea0b1601 test(datePipe): remove hardcoded timezone (#10007)
Closes #9964
2016-07-12 11:13:26 -07:00
7b31178546 fix(platform-browser-dynamic): Add @Injectable() annotation to XHRImpl.
Otherwise Closure compiled code will complain that the class is missing the annootation.
2016-07-11 23:27:35 -07:00
2ff83324af fix(core): Don't use ES6 spread operator when undefined is allowed.
Workaround a closure bug where it doesn't produce the right code ES6 operator when the array value can be undefined.
2016-07-11 23:14:25 -07:00
4ef86891a3 fix(compiler): Ignore references to declared modules and unneeded types (#9776)
Fixes: #9670
2016-07-11 17:26:35 -07:00
eb5763c23f fix(compiler): Generates function expressions as returning any (#9980)
Function expressions are used in an expression context so untyped
function expressions should have any as the result type.

Fixes: #9877
2016-07-11 17:19:38 -07:00
d1a3e3aff1 fix(DirectiveResolver): throw on duplicate Input & Output names 2016-07-11 16:38:06 -07:00
93d0a01d3d refactor: code cleanup 2016-07-11 16:22:23 -07:00
9af2d8b810 fix(testing): remove deprecated testing APIs (#9923)
See https://github.com/angular/angular/blob/master/CHANGELOG.md for
prior deprecation and how to update.
2016-07-11 16:04:32 -07:00
94dc632a6d fix(NgStyle): remove duplicate input declaration (#9978)
fixes #9977
2016-07-11 15:09:04 -07:00
29231877e6 fix(testing): reintroduce and deprecate setBaseTestProviders (#9905)
This change reverts the removal of setBaseTestProviders that was
introduced in 8d746e3f67.

Instead, setBaseTestProviders and the providers provided from
`@angular/platform-browser-dynamic/testing` and `@angular/server/testing`
will still work for the next release, but are deprecated.

See 8d746e3f67 for how to upgrade.
2016-07-11 14:01:11 -07:00
e68252a79b fix(forms): re-enable form provider functions for easier migration (#9972) 2016-07-11 13:23:38 -07:00
4ec2a30942 fix(compiler): Fixed ?. operator to short-circut execution (#9965)
Fixes: #9850
2016-07-11 12:58:56 -07:00
e6b24437a9 fix(compiler): Collector collects enum values. (#9967)
Fixes: #9928
2016-07-11 11:50:33 -07:00
a05f7b2d76 refactor(animations): move MockAnimationPlayer back into core (#9966)
Closes #9966
2016-07-11 10:55:47 -07:00
61e18434d3 refactor(router): not use reserved words as variable (#9941) 2016-07-11 10:53:29 -07:00
57473e72ec refactor: code cleanup (#9931) 2016-07-09 10:12:39 -07:00
c3bdd504d0 fix(animations): ensure all child elements are rendered before running animations
Closes #9402
Closes #9775
Closes #9887
2016-07-08 18:18:46 -07:00
daa9da4047 refactor(core): deprecate coreBootstrap, PLATFORM_PIPES/DIRECTIVES providers and ComponentResolver
BREAKING CHANGE (deprecations)

- Instead of `coreBootstrap`, create an `@AppModule` and use `bootstrapModule`.
- Instead of `coreLoadAndBootstarp`, create an `@AppModule` and use `bootstrapModuleFactory`.
- Instead of `bootstrapWorkerApp`, create an `@AppModule` that includes the `WorkerAppModule` and use `bootstrapModule` with the `workerAppPlatform()`.
- Instead of `bootstrapWorkerUi`, create an @AppModule that includes the `WorkerUiModule` and use `bootstrapModule` with the `workerUiPlatform()` instead.
- Instead of `serverBootstrap`, create an @AppModule and use `bootstrapModule` with the `serverDynamicPlatform()` instead.
- Instead of `PLATFORM_PIPES` and `PLATFORM_DIRECTIVES`, provide platform directives/pipes via an `@AppModule`.
- Instead of `ComponentResolver`:
  - use `ComponentFactoryResolver` together with `@AppModule.precompile`/`@Component.precompile` or `ANALYZE_FOR_PRECOMPILE` provider for dynamic component creation.
  - use `AppModuleFactoryLoader` for lazy loading.
- Instead of `SystemJsComponentResolver`, create an `@AppModule` and use `SystemJsAppModuleLoader`.
- Instead of `SystemJsCmpFactoryResolver`, create an `@AppModule` and use `SystemJsAppModuleFactoryLoader`

Closes #9726
2016-07-08 15:31:50 -07:00
245b0910ed feat(router): add activate and deactivate events to RouterOutlet 2016-07-08 15:01:52 -07:00
a77db44129 feat(router): empty-path routes should inherit matrix params 2016-07-08 14:48:59 -07:00
34b3c534e7 fix(router): disallow root segments with matrix params 2016-07-08 14:47:55 -07:00
fa47890032 refactor(core): clean up platform bootstrap and initTestEnvironment
- Introduces `CompilerFactory` which can be part of a `PlatformRef`.
- Introduces `WorkerAppModule`, `WorkerUiModule`, `ServerModule`
- Introduces `serverDynamicPlatform` for applications using runtime compilation
  on the server.
- Changes browser bootstrap for runtime and offline compilation (see below for an example).
  * introduces `bootstrapModule` and `bootstrapModuleFactory` in `@angular/core`
  * introduces new `browserDynamicPlatform` in `@angular/platform-browser-dynamic
- Changes `initTestEnvironment` (which used to be `setBaseTestProviders`) to not take a compiler factory any more (see below for an example).

BREAKING CHANGE:

## Migration from `setBaseTestProviders` to `initTestEnvironment`:

- For the browser platform:
  BEFORE:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
      TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS} from ‘@angular/platform-browser-dynamic/testing’;

  setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
      TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);
  ```

  AFTER:
  ```
  import {initTestEnvironment} from ‘@angular/core/testing’;
  import {browserDynamicTestPlatform,
      BrowserDynamicTestModule} from ‘@angular/platform-browser-dynamic/testing’;

  initTestEnvironment(
      BrowserDynamicTestModule,
      browserDynamicTestPlatform());

  ```
- For the server platform:
  BEFORE:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {TEST_SERVER_PLATFORM_PROVIDERS,
      TEST_SERVER_APPLICATION_PROVIDERS} from ‘@angular/platform-server/testing/server’;

  setBaseTestProviders(TEST_SERVER_PLATFORM_PROVIDERS,
      TEST_SERVER_APPLICATION_PROVIDERS);
  ```

  AFTER:
  ```
  import {initTestEnvironment} from ‘@angular/core/testing’;
  import {serverTestPlatform,
      ServerTestModule} from ‘@angular/platform-browser-dynamic/testing’;

  initTestEnvironment(
      ServerTestModule,
      serverTestPlatform());

  ```

## Bootstrap changes
```
@AppModule({
  modules: [BrowserModule],
  precompile: [MainComponent],
  providers: […], // additional providers
  directives: […], // additional platform directives
  pipes: […] // additional platform pipes
})
class MyModule {
  constructor(appRef: ApplicationRef) {
    appRef.bootstrap(MainComponent);
  }
}

// offline compile
import {browserPlatform} from ‘@angular/platform-browser’;
import {bootstrapModuleFactory} from ‘@angular/core’;

bootstrapModuleFactory(MyModuleNgFactory, browserPlatform());

// runtime compile long form
import {browserDynamicPlatform} from ‘@angular/platform-browser-dynamic’;
import {bootstrapModule} from ‘@angular/core’;

bootstrapModule(MyModule, browserDynamicPlatform());
```

Closes #9922
Part of #9726
2016-07-08 13:41:38 -07:00
d84a43c828 fix(TemplateParser): add support for data-template attribute
fixes #9904
2016-07-08 13:07:01 -07:00
9a1babb30c refactor(TemplateParser): cleanup 2016-07-08 13:07:01 -07:00
30a332ee36 feat(forms): updateValue() for form groups and form arrays (#9901)
Closes #9553
2016-07-08 13:04:25 -07:00
426b002897 docs(developer): update building and testing instructions (#9903)
fixes #9683
2016-07-08 12:00:27 -07:00
2de8364de2 feat(ExpressionChangedAfterItHasBeenCheckedException): more meaningful error message
fixes #9882
2016-07-08 10:34:22 -07:00
eacc9e6541 refactor: misc cleanup 2016-07-08 10:34:22 -07:00
749dec7dfb doc(api): fix invalid doc links (#9873)
Errors were reported during API doc generation.
2016-07-07 23:02:35 -07:00
96a9e66616 feat(router): add the ANALYZE_FOR_PRECOMPILE provider to make dev ergonomics better 2016-07-07 18:07:10 -07:00
46e105f3ab fix(router): encode/decode params and path segments 2016-07-07 17:33:42 -07:00
f7a0e9ecb6 fix(router): fix RouterLinKActive to work with RouterLink 2016-07-07 17:33:42 -07:00
93025d1bc6 fix(forms): export form directive arrays for offline compile (#9893) 2016-07-07 17:29:20 -07:00
98d49d4ce3 refactor(core): make lockRunMode a noop and deprecate it.
BREAKING CHANGE:
- `lockRunMode` is deprecated and no more needed.

Closes #9878
2016-07-07 16:16:55 -07:00
1426f680f5 refactor(core): add a deprecation message for using PLATFORM_DIRECTIVES / PLATFORM_PIPES / CompilerConfig / XHR as regular providers in bootstrap.
We still support this via a hack, but should remove this soon.

This also fixes tests for module directives / pipes
as they used directives / pipes that were
already present in the underlying platform.
2016-07-07 16:16:55 -07:00
c7fc51a185 chore(public api): run build.sh before generating the api doc (#9889) 2016-07-07 15:39:53 -07:00
b7e69bc1a1 fix(NgPlural): expression inside cases (#9883)
fixes #9868
2016-07-07 14:47:06 -07:00
72544ba551 feat(router): add RouterTestModule 2016-07-07 14:28:01 -07:00
c43dd5a655 refactor(router): renamed RouterAppModule into RouterModule 2016-07-07 14:28:01 -07:00
7f4954bed6 fix(animations): change trigger binding syntax to function as a property binding []
Animation triggers can now be set via template bindings `[]`

BREAKING CHANGE:

animation trigger expressions within the template that are assigned as
an element attribute (e.g. `@prop`) are deprecated. Please use the
Angular2 property binding syntax (e.g. `[@prop]`) when assigning
properties.

```ts
// this is now deprecated
<div @trigger="expression"></div>

// do this instead
<div [@trigger]="expression"></div>
```
2016-07-07 14:13:06 -07:00
f1fc1dc669 revert: fix(animations): ensure all child elements are rendered before running animations
This reverts commit cbe85a0893.
2016-07-07 14:12:17 -07:00
cbe85a0893 fix(animations): ensure all child elements are rendered before running animations
Closes #9402
Closes #9775
2016-07-07 14:10:04 -07:00
7073cf74fe feat(core): allow to add precompiled tokens via a provider
Introduces the new `ANALYZE_FOR_PRECOMPILE` token. This token can be used to
create a virtual provider that will populate the `precompile` fields of
components and app modules based on its
`useValue`. All components that are referenced in the `useValue`
value (either directly or in a nested array or map) will be added
to the `precompile` property.

closes #9874
related to #9726
2016-07-07 12:16:48 -07:00
9d265b6f61 feat(forms): add modules for forms and deprecatedForms (#9859)
Closes #9732

BREAKING CHANGE:

We have removed the deprecated form directives from the built-in platform directive list, so apps are not required to package forms with their app. This also makes forms friendly to offline compilation.

Instead, we have exposed three modules:

OLD API:
- `DeprecatedFormsModule`

NEW API:
- `FormsModule`
- `ReactiveFormsModule`

If you provide one of these modules, the default forms directives and providers from that module will be available to you app-wide.  Note: You can provide both the `FormsModule` and the `ReactiveFormsModule` together if you like, but they are fully-functional separately.

**Before:**
```ts
import {disableDeprecatedForms, provideForms} from @angular/forms;

bootstrap(App, [
   disableDeprecatedForms(),
   provideForms()
]);
```

**After:**

```ts
import {DeprecatedFormsModule} from @angular/common;

bootstrap(App, {modules: [DeprecatedFormsModule] });
```

-OR-

```ts
import {FormsModule} from @angular/forms;

bootstrap(App, {modules: [FormsModule] });
```

-OR-

```ts
import {ReactiveFormsModule} from @angular/forms;

bootstrap(App, {modules: [ReactiveFormsModule] });
```

You can also choose not to provide any forms module and run your app without forms.

Or you can choose not to provide any forms module *and* provide form directives at will.  This will allow you to use the deprecatedForms API for some components and not others.

```
import {FORM_DIRECTIVES, FORM_PROVIDERS} from @angular/forms;

@Component({
   selector: some-comp,
   directives: [FORM_DIRECTIVES],
   providers: [FORM_PROVIDERS]
})
class SomeComp
```
2016-07-07 11:32:51 -07:00
776a83f9da doc(i18nPluralPipe): update API doc example (#9862) 2016-07-07 08:48:37 -07:00
f29457f3f0 fix(datePipe): short timezone not displayed, closes #9812 (#9816) 2016-07-07 08:47:30 -07:00
a005d1595e chore(compiler-cli): correct homepage URL in package.json (#9869) 2016-07-07 08:43:53 -07:00
8d746e3f67 feat(testing): add implicit test module
Every test now has an implicit module. It can be configured via `configureModule` (from @angular/core/testing)
to add providers, directives, pipes, ...

The compiler now has to be configured separately via `configureCompiler` (from @angular/core/testing)
to add providers or define whether to use jit.

BREAKING CHANGE:
- Application providers can no longer inject compiler internals (i.e. everything
  from `@angular/compiler). Inject `Compiler` instead. This reflects the
  changes to `bootstrap` for module support (3f55aa609f).
- Compiler providers can no longer be added via `addProviders` / `withProviders`.
  Use the new method `configureCompiler` instead.
- Platform directives / pipes need to be provided via
  `configureModule` and can no longer be provided via the
  `PLATFORM_PIPES` / `PLATFORM_DIRECTIVES` tokens.
- `setBaseTestProviders()` was renamed into `initTestEnvironment` and 
  now takes a `PlatformRef` and a factory for a
  `Compiler`.
- E.g. for the browser platform:
  
  BEFORE:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
      TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS} from ‘@angular/platform-browser-dynamic/testing’;
  
  setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
      TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);   
  ```

  AFTER:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {browserTestCompiler, browserDynamicTestPlatform,
      BrowserDynamicTestModule} from ‘@angular/platform-browser-dynamic/testing’;
  
  initTestEnvironment(
      browserTestCompiler,
      browserDynamicTestPlatform(),
      BrowserDynamicTestModule);

  ```
- E.g. for the server platform:
  
  BEFORE:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {TEST_SERVER_PLATFORM_PROVIDERS,
      TEST_SERVER_APPLICATION_PROVIDERS} from ‘@angular/platform-server/testing/server’;
  
  setBaseTestProviders(TEST_SERVER_PLATFORM_PROVIDERS,
      TEST_SERVER_APPLICATION_PROVIDERS);   
  ```

  AFTER:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {serverTestCompiler, serverTestPlatform,
      ServerTestModule} from ‘@angular/platform-browser-dynamic/testing’;
  
  initTestEnvironment(
      serverTestCompiler,
      serverTestPlatform(),
      ServerTestModule);

  ```

Related to #9726
Closes #9846
2016-07-06 18:04:19 -07:00
37e6da6dfb refactor(router): clean up naming 2016-07-06 16:19:52 -07:00
8aa2a0c1b2 feat(router): add RouterAppModule 2016-07-06 16:00:40 -07:00
6bfd514caf fix(router): remove a circular dep 2016-07-06 14:38:05 -07:00
ad3f18c0dd chore(build): update build script to increase node's heap size 2016-07-06 14:38:05 -07:00
39d04b4a15 chore(public_api): update public api 2016-07-06 14:38:05 -07:00
6fbe56dbf2 feat(router): update the example app to use lazily-loaded modules 2016-07-06 14:38:05 -07:00
8ebb8e44c8 feat(router): add support for lazily loaded modules 2016-07-06 14:38:05 -07:00
6fcf962fb5 feat(core): add AddModuleFactoryLoader 2016-07-06 14:38:05 -07:00
2708ce6a17 docs(api): fix links (#9852) 2016-07-06 14:34:27 -07:00
30bec78da3 fix(compiler): Missing metadata files should result in undefined (#9704)
RelectorHost threw an exception when metadata was requested for a
.d.ts file that didn't have a .metadata.json file.  Changed it to
return undefined.

Fixes #9678
2016-07-06 14:26:31 -07:00
9a04fcd061 feat(compiler): Expression span information and error correction (#9772)
Added error correction so the parser always returns an AST
Added span information to the expression parser
Refactored the test to account for the difference in error reporting
Added tests for error corretion
Modified tests to validate the span information
2016-07-06 14:06:47 -07:00
ae62f082fd docs(api): fix broken example urls (#9828) 2016-07-06 13:57:38 -07:00
9cc3b2ca9e fix(animations): ensure a null easing value is never used with web-animations
Closes #9780
Closes #9752
2016-07-06 11:25:54 -07:00
3fe1cb0253 refactor(core): ensure CSS parser uses ParseSourceSpan to track ast locations
This commit also fixes up any remaining TODO comments.

Closes #9778
2016-07-06 11:22:45 -07:00
0ed7773223 build(gulp): Fix paths for public-api tasks on Windows (#9794) 2016-07-05 20:52:35 -07:00
3f55aa609f feat(browser): use AppModules for bootstrap in the browser
This introduces the `BrowserModule` to be used for long form
bootstrap and offline compile bootstrap:

```
@AppModule({
  modules: [BrowserModule],
  precompile: [MainComponent],
  providers: […], // additional providers
  directives: […], // additional platform directives
  pipes: […] // additional platform pipes
})
class MyModule {
  constructor(appRef: ApplicationRef) {
    appRef.bootstrap(MainComponent);
  }
}

// offline compile
import {bootstrapModuleFactory} from ‘@angular/platform-browser’;
bootstrapModuleFactory(MyModuleNgFactory);

// runtime compile long form
import {bootstrapModule} from ‘@angular/platform-browser-dynamic’;
bootstrapModule(MyModule);
```

The short form, `bootstrap(...)`, can now creates a module on the fly,
given `directives`, `pipes, `providers`, `precompile` and `modules`
properties.

Related changes:
- make `SanitizationService`, `SecurityContext` public in `@angular/core` so that the offline compiler can resolve the token
- move `AnimationDriver` to `platform-browser` and make it
  public so that the offline compiler can resolve the token

BREAKING CHANGES:
- short form bootstrap does no longer allow
  to inject compiler internals (i.e. everything 
  from `@angular/compiler). Inject `Compiler` instead.
  To provide custom providers for the compiler,
  create a custom compiler via `browserCompiler({providers: [...]})`
  and pass that into the `bootstrap` method.
2016-07-02 20:35:09 -07:00
74b45dfbf8 Revert "refactor(core): ensure CSS parser uses ParseSourceSpan to track ast locations"
This reverts commit 5c9f871b21.
2016-07-01 21:21:56 -07:00
5c9f871b21 refactor(core): ensure CSS parser uses ParseSourceSpan to track ast locations
This commit also fixes up any remaining TODO comments.

Closes #9285
2016-07-01 17:18:14 -07:00
77dc6ef411 fix(forms): mark control containers as touched when child controls are touched (#9735) 2016-07-01 15:36:04 -07:00
5eca6e4e40 bug(datePipe): passing "hh" to the datepipe (#9774)
closes #9759
2016-07-01 15:34:57 -07:00
0c65d5cf2b fix(router): handle router outlets in ngIf 2016-06-30 22:14:42 -07:00
f65ebec3ed fix(router): update links when query params change 2016-06-30 22:14:42 -07:00
81bf3f66ca docs(router): rename global redirects into absolute redirects 2016-06-30 22:14:42 -07:00
3cbded6694 fix(forms): use change event for select multiple (#9713) 2016-06-30 20:24:39 -07:00
137fff9632 fix(router): remove private and internal annotations (#9753) 2016-06-30 19:39:13 -07:00
695c08b9dd test(forms): add test for multi-select and custom accessors (#9624) 2016-06-30 18:04:00 -07:00
119794249b doc(changelog): cleans up markdown for breaking changes (#9739) 2016-06-30 17:31:39 -07:00
afb72164e4 fix(docs): typo in comments (#9743)
correct a typo in comments
2016-06-30 15:18:41 -07:00
9fee5630fd chore: fix package on changelog (#9736) 2016-06-30 15:17:00 -07:00
01de58d650 chore(router): bump up version number 2016-06-30 14:58:59 -07:00
dabf214f17 fix(router): remove private and internal annotations (#9745) 2016-06-30 14:47:55 -07:00
fb2539e1d5 fix(router): remove the precompile warning 2016-06-30 14:33:04 -07:00
ad9f02a73e chore: enable cyclic dependency check
Closes #9742
2016-06-30 14:28:22 -07:00
2d73583253 chore(compiler): fix cyclic dependency 2016-06-30 14:28:22 -07:00
73f017bad9 fix(typescript): make router compile with typescript@next
fixes #9731
2016-06-30 11:51:52 -07:00
055282f156 chore(router): bump up version number 2016-06-30 11:45:31 -07:00
fe7de53b89 chore(router): update router change log 2016-06-30 11:45:31 -07:00
17e4cfc748 feat(core): introduce @AppModule
Main part for #9726
Closes #9730
2016-06-30 11:34:40 -07:00
1608d91728 docs(changelog): change log and package.json to rc4
Closes #9727
2016-06-30 10:16:32 -07:00
a3b90411aa fix(router): fix RouterLinkActive to handle the case when the link has extra paths 2016-06-30 09:26:57 -07:00
5781b96490 fix(router): redirect should not add unnecessary brackets 2016-06-30 09:26:57 -07:00
f208ee0d57 fix(router): reexport router directives 2016-06-30 09:26:57 -07:00
8aa388de6c doc(directive): fixes incorrect example code (#9635) 2016-06-29 22:16:43 -07:00
51d4c9dcbd fix(compiler): make code easier to type check
These changes are needed for the G3 sync as we use a different version/settings of Typescript than on Github.

closes #9701
2016-06-29 10:43:58 -07:00
e81dea695c fix(compiler): report not existing files as errors
Closes #9690
2016-06-29 07:35:34 -07:00
3fec27961e fix: support *directive on <template> (#9691)
fixes #7315
2016-06-28 21:53:41 -07:00
3784696b9e fix(router): make the contstructor of the router service public 2016-06-28 18:39:37 -07:00
8c45aebc18 fix(router): make router links work on non-a tags 2016-06-28 18:39:37 -07:00
810c722413 docs(security): point users to docs when sanitization fails. (#9680) 2016-06-28 18:13:46 -07:00
e2116c53f3 fix(upgrade): add peerDependency on platform-browser-dynamic (#9674)
Closes #9623
2016-06-28 17:27:28 -07:00
296a447e3c docs(router): add api docs 2016-06-28 14:49:29 -07:00
0961bd1eff feat(forms): use formControlName on radio buttons when name is absent (#9681) 2016-06-28 15:21:53 -06:00
9340e1b065 docs(security): security api doc update and fix stability marker for Type 2016-06-28 14:01:48 -07:00
ae4fa56ee9 fix(public API): update golden files
broken by #9606
2016-06-28 12:21:50 -07:00
2d9d7f1310 fix(security): allow empty CSS values. (#9675) 2016-06-28 11:45:02 -07:00
5ee84fe0f6 refactor: add types (#9606)
relates to #9100
2016-06-28 11:35:59 -07:00
1620426393 fix(http): don't encode values that are allowed in query (#9651)
This implements a new class, QueryEncoder, that provides
methods for encoding keys and values of query parameter.
The encoder encodes with encodeURIComponent, and then
decodes a whitelist of allowed characters back to their
unencoded form.

BREAKING CHANGE:

The changes to Http's URLSearchParams serialization now 
prevent encoding of these characters inside query parameters
which were previously converted to percent-encoded values:

@ : $ , ; + ; ? /

The default encoding behavior can be overridden by extending
QueryEncoder, as documented in the URLSearchParams service.

Fixes #9348
2016-06-28 11:31:35 -07:00
bf598d6b8b feat(compiler): support sync runtime compile
Adds new abstraction `Compiler` with methods
`compileComponentAsync` and `compileComponentSync`.
This is in preparation of deprecating `ComponentResolver`.

`compileComponentSync` is able to compile components
synchronously given all components either have an inline
template or they have been compiled before.

Also changes `TestComponentBuilder.createSync` to
take a `Type` and use the new `compileComponentSync` method.

Also supports overriding the component metadata even if
the component has already been compiled.

Also fixes #7084 in a better way.

BREAKING CHANGE:
`TestComponentBuilder.createSync` now takes a component type
and throws if not all templates are either inlined
are compiled before via `createAsync`.

Closes #9594
2016-06-28 10:26:16 -07:00
24eb8389d2 fix: public api surface fixes + stability markers
- ts-api-guardian will now error if a new public symbol is added with a stability marker (`@stable`, `@experimental`, `@deprecated`)
- DomEventsPlugin and KeyEventsPlugin were removed from public api surface - these classes is an implementation detail
- deprecated BROWSER_PROVIDERS was removed completely
- `@angular/compiler` was removed from the ts-api-guardian check since this package shouldn't contain anything that users need to directly import
- the rest of the api surface was conservatively marked as stable or experimental

BREAKING CHANGES: DomEventsPlugin and KeyEventsPlugin previously exported from core are no longer public - these classes are implementation detail.

Previously deprecated BROWSER_PROVIDERS was completely removed from platform-browser.

Closes #9236
Closes #9235
Ref #9234
2016-06-28 07:39:40 -07:00
fcfddbf79c feat(router): add pathMatch property to replace terminal 2016-06-27 20:21:30 -07:00
dc64e90ab9 feat(router): use componentFactoryResolver 2016-06-27 20:21:30 -07:00
e12b1277df feat(core): split ChangeDetectorStrategy into ChangeDetectionStrategy and ChangeDetectorStatus 2016-06-27 20:19:20 -07:00
797914e948 fix(forms): emit statusChange when child controls have async validator (#9652) 2016-06-27 21:01:24 -06:00
e0b0a594bb fix(animations): ensure void => * animations are triggered when an expression is omitted
Closes #9327
Closes #9381
2016-06-27 18:55:10 -07:00
ed0ade6f34 fix(forms): make radio button selection logic more flexible (#9646)
Closes #9558
2016-06-27 15:29:33 -06:00
5cc7b41f39 Revert "fix(Compiler): relax childIsRecursive check (#8705)"
This fix prevented waiting for child components even if the cycle was only introduced via the `directives` array, i.e. without actually having a cycle. This easily causes issues for applications that have one shared list of directives for all components.

This reverts commit 3d5bb23184.

Closes #9647
2016-06-27 14:27:03 -07:00
f2f1ec0117 feat(router): implement data and resolve 2016-06-27 14:25:56 -07:00
e913d9954d chore(typings): restrict Angular to es5+collections+promise 2016-06-27 13:58:59 -07:00
d20488752b fix(router): top-levels do not work in ngIf 2016-06-27 13:34:54 -07:00
855f3afb28 fix(router): canceled navigations should return a promise that is resolved with false 2016-06-27 13:34:54 -07:00
3f44377f2f fix(router): handle empty path with query params 2016-06-27 13:34:54 -07:00
90295e3252 fix(router): preserve fragment on initial load 2016-06-27 13:34:54 -07:00
a620f95891 build(npm): upgrade ts-api-guardian to v0.1.4
Closes #9642
2016-06-27 12:27:59 -07:00
db66509e66 test(security): tests for HTML5 elements, srcset.
Part of #9572.
2016-06-27 12:19:03 -07:00
6605eb30e9 feat(security): allow more HTML5 elements and attributes in sanitizers
Allow more elements and attributes from the HTML5 spec which were stripped by the htmlSanitizer.

fixes #9438

feat(security): allow audio data URLs in urlSanitizer

test(security) : add test for valid audio data URL

feat(security): allow and sanitize srcset attributes

test(security): test for srcset sanitization
2016-06-27 12:19:03 -07:00
3644eef860 feat(DomRenderer): Adding support for document fragments in SVG foreign objects (#9458) 2016-06-27 08:26:45 -07:00
fb2509675d doc(changelog): add backticks around html elements so they actually render (#9637) 2016-06-27 08:21:34 -07:00
eef9512ce6 fix(forms): async validator-directives process Observables correctly (#8186)
Closes #/8022
2016-06-26 16:52:50 -06:00
9f00a1b902 fix(forms): add select multiple accessor as built-in accessor 2016-06-26 16:24:27 -06:00
c369bc747d docs: update cheatsheet import lines (#9614) 2016-06-26 07:31:35 -07:00
c03e1f2f59 feat(forms): add support for formArrayName
Closes #9251
2016-06-25 13:30:53 -07:00
17dcbf66b9 feat(forms): expose ValidatorFn and AsyncValidatorFn
Closes #8834
2016-06-24 18:24:11 -07:00
40b907a657 refactor(testing): remove wrapping of Jasmine functions (#9564)
Instead, the async function now determines whether it should return a promise
or instead call a done function parameter. Importing Jasmine functions
from `@angular/core/testing` is no longer necessary and is now deprecated.

Additionally, beforeEachProviders is also deprecated, as it is specific
to the testing framework. Instead, use the new addProviders method directly.

Before:
```js
import {beforeEachProviders, it, describe, inject} from 'angular2/testing/core';

describe('my code', () => {
  beforeEachProviders(() => [MyService]);

  it('does stuff', inject([MyService], (service) => {
    // actual test
  });
});
```

After:
```js
import {addProviders, inject} from 'angular2/testing/core';

describe('my code', () => {
  beforeEach(() => {
    addProviders([MyService]);
  });

  it('does stuff', inject([MyService], (service) => {
    // actual test
  });
});
```
2016-06-24 17:48:35 -07:00
a33195dcf3 fix(core/testing compiler/testing): move TestComponentBuilder to core/testing (#9590)
TestComponentBuilder now lives in core/testing. compiler/testing contains a private
OverridingTestComponentBuilder implementation which handles the private behavior
we need to override templates. This is part of the effort to simplify the testing
imports and hide compiler APIs.

Closes #9585

BREAKING CHANGE:

`TestComponentBuilder` is now imported from `@angular/core/testing`. Imports
from `@angular/compiler/testing` are deprecated.

Before:

```
import {TestComponentBuilder, TestComponentRenderer, ComponentFixtureAutoDetect} from '@angular/compiler/testing';
```

After:
```
import {TestComponentBuilder, TestComponentRenderer, ComponentFixtureAutoDetect} from '@angular/core/testing';
```
2016-06-24 17:35:01 -07:00
c693c03f1d test(node): enable source maps in test.sh node (#9589) 2016-06-24 16:52:41 -07:00
de127109f9 feat(forms): make valueChanges and statusChanges available on abstract control directives 2016-06-24 14:37:19 -07:00
83208983b3 chore(router): bump up version number 2016-06-24 13:07:42 -07:00
327d04c9c6 chore(router): clang-format 2016-06-24 12:44:32 -07:00
54edce2bab fix(router): wildcard don't get notified on url changes 2016-06-24 12:44:32 -07:00
1a145ac500 fix(router): default exact to false in routerLinkActiveOptions 2016-06-24 12:44:32 -07:00
9f978cf49d test(router): add a test checking that you can use a slash in query params 2016-06-24 12:44:32 -07:00
41b781107b fix(router): doen't throw on canDeactive when route hasn't advanced 2016-06-24 12:44:32 -07:00
dcf75126bf fix(common/testing): remove internal MockLocationStrategy from common/testing (#9562)
BREAKING CHANGE:

MockLocationStrategy was intended to be internal only and is now removed
from the `@angular/common/testing` public api.

Use `SpyLocation` from `@angular/common/testing` for location testing.
2016-06-24 12:41:57 -07:00
1143b0389a fix(core/testing): move ComponentFixture to core (#9386)
BREAKING CHANGE:

`ComponentFixture` will be moving out of `@angular/compiler/testing` to `@angular/core/testing` in
this release. For now, it is deprecated from `@angular/compiler/testing`.
2016-06-24 12:41:49 -07:00
97a2119596 fix(forms): ngModel should emit valueChanges and statusChanges asynchronously 2016-06-24 12:37:46 -07:00
fbd2dd9ca2 fix(router): handle path:'' redirects and matches 2016-06-24 11:39:41 -07:00
f463e09b9f fix(ngc): work with typescript@next
This is required due to breaking change in TS, see
https://github.com/Microsoft/TypeScript/pull/8841#issuecomment-227300348
2016-06-24 10:27:31 -07:00
42a5b6cbda chore(testing): upgrade ts-api-guardian to 0.1.3 2016-06-23 18:19:32 -07:00
0ad1215a92 build(changelog): remove old changelog script and add gulp task 2016-06-23 17:35:57 -07:00
7733c97df3 build(npm): update conventional-changelog dependency
Fixes #5672
2016-06-23 17:35:57 -07:00
8a9e9c7bd3 fix(core/testing): clean up the core testing public API (#9466)
Previously, we were exporting internal mocks and helpers. Move these
to core/testing/testing_internal or remove them if they were
never used.

Remove deprecated items - injectAsync, clearPendingTimers.

BREAKING CHANGE:

Remove the following APIs from `@angular/core/testing`, which have been deprecated or were
never intended to be publicly exported:

```
injectAsync
clearPendingTimers
Log
MockAppliacationHref
MockNgZone
clearPendingTimers
getTypeOf
instantiateType
```

Instead of `injectAsync`, use `async(inject())`.

`clearPendingTimers` is no longer required.
2016-06-23 17:10:22 -07:00
3d8eb8cbca fix(platform-browser/testing): clean up public api for platform-browser/testing (#9519)
Mostly, removing things that were never intended to be exported publicy.

BREAKING CHANGE:

The following are no longer publicly exported APIs. They were intended as internal
utilities and you should use your own util:

```
browserDetection,
dispatchEvent,
el,
normalizeCSS,
stringifyElement,
expect (and custom matchers for Jasmine)
```
2016-06-23 16:42:25 -07:00
894747c34c fix(platform-browser/testing-e2e): clean up unused exports from e2e testing helpers (#9387) 2016-06-23 16:14:31 -07:00
8d5a312585 chore(api): clean up compiler/testing api (#9520)
Do not export MockXHR, which is a private helper.
2016-06-23 15:52:18 -07:00
8eb81b3741 ci: add updated ts-api-guardian check 2016-06-23 14:26:40 -07:00
22d8f73bc9 test: add public api golden files
Includes a few style fixes on "* as foo" imports.
2016-06-23 14:26:40 -07:00
249a6bdd98 test: upgrade ts-api-guardian to v0.1.2 2016-06-23 14:26:40 -07:00
3ad81b1beb test(security): simplify integration test. 2016-06-23 13:57:51 -07:00
5ab0534164 test(security): Ensure xlink:href is not bindable.
The DOM schema does not allow binding any properties to dangerous SVG
attributes/properties. This change adds a smoke test to verify that
behaviour, by testing that `xlink:href` (a sample dangerous property)
is not bindable.

Fixes #9510.
2016-06-23 13:57:51 -07:00
5150344213 fix(common): add license header to localization.ts 2016-06-23 13:27:43 -07:00
98cef76931 fix(security): no warning when sanitizing escaped html (#9392) (#9413) 2016-06-23 13:06:19 -07:00
6c5b653593 feat(core): add @Component.precompile and ComponentFactoryResolver
Part to #9467
Closes #9543
2016-06-23 12:10:04 -07:00
9ed8f2d26e fix(compiler): don't inject viewProviders into content child elements
E.g. in the following scenario,
`some-directive` should not be able to inject
any view provider that `my-comp-with-view-providers`
declares.

```
<my-comp-with-view-providers>
  <div some-directive></div>
</my-comp-with-view-providers>
```
2016-06-23 12:10:04 -07:00
33a2f86b28 chore: remove stale tsconfig.json
This tsconfig.json prevents fast round trip cycles in VsCode
as it relies on the package-dist folders to be filled.
2016-06-23 12:10:04 -07:00
fed1672a43 refactor(i18n): I18nPipe uses NgLocalization (#9313)
and some refactoring
2016-06-23 11:44:05 -07:00
54dbed4f48 fix(typings): don't test compiler-cli typings on TS 1.8 2016-06-23 10:57:03 -07:00
df759b8d4b fix(core): improve error message for broken bindings
Fixes #6820

Closes #9536
2016-06-23 19:28:56 +02:00
6edf0474cc feat(forms): add support for standalone ngModel dirs inside forms
Closes #9230
2016-06-23 10:16:47 -07:00
826f89f862 fix(ngc): correct dependencies for compiler-cli
Update compiler-cli dependencies to include minimist and also increment tsc-wrapped to 0.2.0.  There is signature mismatch between tsc-wrapped (v0.1.0) collector.js#getMetadata and compiler-cli reflector_host.js#getMetadataFor that caused an error anytime ngc was executed. The error received was as follows.

`TypeError: Cannot read property 'getSymbolsInScope' of undefined`

After forcing NPM to install @angular/tsc-wrapped@latest the error was resolved.

Fixes #9540
2016-06-23 10:16:04 -07:00
c43aec2182 fix(animations): make sure the easing value is passed into the web-animations player
Closes #9517
Closes #9523
2016-06-23 10:14:18 -07:00
ae75e3640a chore(lint): Added license headers to most TypeScript files
Relates to #9380
2016-06-23 09:47:54 -07:00
a5f2cc73f6 chore(lint): Add lint check for license headers
Added a tslint check to make sure all source files begin with a license
header (at the very beginning or after a `#!`).

Relates to #9380
2016-06-23 09:46:32 -07:00
e1e5c40ef7 fix(testing): remove the toThrowErrorWith matcher (jasmine has toThrowError)
BREAKING CHANGE:

Before:

    expect(...).toThrowErrorWith(msg);

After:

    expect(...).toThrowError(msg);
2016-06-23 08:58:52 -07:00
6420f75320 fix(testing): remove the toMatchPattern matcher (jasmine has toMatch)
BREAKING CHANGE:

Before:

    expect(...).toMatchPattern(pattern);

After:

    expect(...).toMatch(pattern);
2016-06-23 08:58:28 -07:00
5face35ae5 refactor: misc cleanup 2016-06-23 08:56:10 -07:00
398060d5ff fix(NgSwitch): display deprecation message only once 2016-06-23 08:56:10 -07:00
638fd744aa feat(forms): support updating of validators on exiting controls (#9516)
lint

fix

async

d

test

test
2016-06-23 08:18:07 -07:00
098b461b69 fix(core): report duplicate template bindings in templates
Fixes #7315

BREAKING CHANGES:

Previously multiple template bindings on one element
(ex. `<div *ngIf='..' *ngFor='...'>`) were allowed but most of the time
were leading to undesired result. It is possible that a small number
of applications will see template parse errors that shuld be fixed by
nesting elements or using `<template>` tags explicitly.

Closes #9462
2016-06-23 15:59:07 +02:00
9decc3d823 build: fix some issues on Windows platforms
Closes #9450
2016-06-23 10:46:01 +02:00
a5f2e205ef fix(http): add search param escaping for keys (#9166) 2016-06-22 18:23:15 -07:00
8899b83927 chore(typescript): Enabled noFallthroughCasesInSwitch
Turned on the noFallthroughCasesInSwitch flag in tsconfig and fixed
a few cases where there were fallthroughs.
2016-06-22 16:08:55 -07:00
f6a410a4a8 feat(QueryList): implement some() (#9464)
closes #9443
2016-06-22 13:13:31 -07:00
3d5bb23184 fix(Compiler): relax childIsRecursive check (#8705)
Fix how the compiler checks for recursive components by also considering
component descendants. Previously, it only checked if the current
component was evaluated previously. This failed in certain cases of
mutually recursive components, causing `createAsync` in tests to not
resolve.

closes [7084](https://github.com/angular/angular/issues/7084)
2016-06-22 07:02:11 -07:00
ef37d2ae0b example(router): add an example app for the new router 2016-06-21 23:19:26 -07:00
2eb234bc63 chore(router): enable bundling 2016-06-21 23:19:26 -07:00
758ee95880 fix(router): fix tsconfig to use es2015 modules 2016-06-21 23:19:26 -07:00
40e1112a8e chore(router): test karma config to rerun tests on change 2016-06-21 23:19:26 -07:00
397f5e2390 refactor(HtmlLexer): simplify the code 2016-06-21 18:03:22 -07:00
1a212259af refactor: cleanup lexers & parsers 2016-06-21 18:03:22 -07:00
f114dd300b fix(core): properly report missing providers and viewProviders (#9411)
Fixes #8237
2016-06-21 17:27:27 -07:00
5954a26bce docs: add latest changelog updates (#9415) 2016-06-21 17:16:22 -07:00
bdbbe5aa20 chore(release): 2.0.0-rc.3 2016-06-21 16:34:48 -07:00
15911367a2 refactor(router): removes a circualr dep 2016-06-21 12:17:30 -07:00
8dd3f59c81 chore(router): changes the router setup to align with other modules 2016-06-21 12:17:30 -07:00
c9d28492b7 chore(router): remove lint and format tasks from router 2016-06-21 12:17:30 -07:00
d1f93072a8 chore(router): clang-format 2016-06-21 12:17:30 -07:00
92d8bf9619 feat(router): add support for componentless routes 2016-06-21 12:17:30 -07:00
bd2281e32d fix(resolve): change resolve not to resolve root activate route 2016-06-21 12:17:30 -07:00
0c50bc6449 fix(router): url serializer should handle segments without primary children 2016-06-21 12:17:30 -07:00
f164715678 chore(README): fix a typo 2016-06-21 12:17:30 -07:00
2aa615b4ae chore(router): bump up version 2016-06-21 12:17:30 -07:00
42c89b1b9b docs(router): add a README to include a link to the guide 2016-06-21 12:17:30 -07:00
f6b75f56ad fix(router): typo in starts with slash validation error 2016-06-21 12:17:30 -07:00
280540e4a2 fix(router): change serialize not to require parenthesis in query string to be encoded 2016-06-21 12:17:30 -07:00
fea216db12 fix(router): fixes a type issue in a test 2016-06-21 12:17:30 -07:00
b260eb06f6 fix(router): change postinstall hook to devsetup to not require having 'typings' installed 2016-06-21 12:17:30 -07:00
1c937a10f9 chore(router): add changelog 2016-06-21 12:17:30 -07:00
ca23b4c55f feat(router): add route config validation 2016-06-21 12:17:30 -07:00
7e12208ca6 feat(router): do not support paths starting with / 2016-06-21 12:17:30 -07:00
2773281338 feat(router): drop index property
Use path: '/' instead of 'index: true'
2016-06-21 12:17:30 -07:00
f8e8d22e4e fix(router): stringify positional parameters when using routerLink 2016-06-21 12:17:30 -07:00
cf4a9236b9 chore(router): bump up version number 2016-06-21 12:17:30 -07:00
4450e7b246 cleanup(router): enable noImplicitAny and noImplicntReturns 2016-06-21 12:17:30 -07:00
cdbf67ee05 test(router): add a test checking that guards work for child routes 2016-06-21 12:17:30 -07:00
9a67f38728 fix(router): port fixes done on angular current router to the new one
The bugs were fixed on current angular router in the following commits:
angular/angular@b2a7fd05cb
angular/angular@fa2ce8100b
angular/angular@595bcdd1ac

Closes #12
2016-06-21 12:17:30 -07:00
25560ed048 feat(router): implement RouterLinkActive 2016-06-21 12:17:30 -07:00
2aa19fd078 feat(router): support navigating by url tree 2016-06-21 12:17:30 -07:00
cca9a58ded chore(router): bump up version number 2016-06-21 12:17:30 -07:00
d6a25325c7 chore(package): unpin version 2016-06-21 12:17:30 -07:00
a717da2d3e chore(router): bump up version number 2016-06-21 12:17:30 -07:00
b3e801ed9e feat(router): make it work with TypeScript 1.8 2016-06-21 12:17:30 -07:00
3683fb6886 refactor(router): minor refactoring 2016-06-21 12:17:30 -07:00
3bd0ce291e feat(router): mark the index property as deprecated
Use {path: '', component: A} instead of {index: true, component: A}

}#
2016-06-21 12:17:30 -07:00
523fc5536c fix(router): fix Params type to allow passing any value types when calling router.navigate 2016-06-21 12:17:30 -07:00
f5efccfb44 test(router): test update location when route does not change 2016-06-21 12:17:30 -07:00
b6ec22de6b test(router): test empty url with global redirect 2016-06-21 12:17:30 -07:00
15f27b5455 fix(providers): make providers static analysis friendly 2016-06-21 12:17:30 -07:00
127401598b feat(router): implement terminal 2016-06-21 12:17:30 -07:00
503b07f698 docs(router): add a README 2016-06-21 12:17:30 -07:00
f0a6329005 fix(router): fixes a typo 2016-06-21 12:17:30 -07:00
2982892acc cleanup(router): clang-format 2016-06-21 12:17:30 -07:00
9de56481f1 feat(router): add enableTracing option 2016-06-21 12:17:30 -07:00
777eb2f159 feat(router): emit an event when routes are recognized 2016-06-21 12:17:30 -07:00
05eebe0fed feat(router): provide meaningful toString impls 2016-06-21 12:17:30 -07:00
fdfbbd5bac chore(router): bump up version number 2016-06-21 12:17:30 -07:00
1f3f8ef6c8 fix(router): fix nested deactivation 2016-06-21 12:17:30 -07:00
820eeb49d1 chore(router): bump up version number 2016-06-21 12:17:30 -07:00
2d4be1c9eb fix(router): init is not triggered in certain scenarios 2016-06-21 12:17:30 -07:00
2fef30f619 fix(router): make stringify handle nulls 2016-06-21 12:17:30 -07:00
10113b63b5 chore(router): bump up version number 2016-06-21 12:17:30 -07:00
545caab433 fix(router): use bootstrap listener to trigger initial navigation 2016-06-21 12:17:30 -07:00
3f90659cc1 fix(router): supports index routes with path 2016-06-21 12:17:30 -07:00
131914ac94 fix(router): fix lazy loading issues 2016-06-21 12:17:30 -07:00
29a7c4538c Revert "fix(provider): fix a circular dependency & remove common providers"
This reverts commit 6375fdd4f2928d5ddeccaf11a8589a7668bc9049.
2016-06-21 12:17:30 -07:00
f195bb608c chore(router): update config before publishing to npm 2016-06-21 12:17:30 -07:00
66caabca0c feat(router): implement redirectTo 2016-06-21 12:17:30 -07:00
25c6a3715d fix(provider): fix a circular dependency & remove common providers 2016-06-21 12:17:30 -07:00
97cf0e40d5 fix(guards): Cancel in-flight guards if one returns false 2016-06-21 12:17:30 -07:00
6988a550ea cleanup(router): fix tslint errors 2016-06-21 12:17:30 -07:00
8a1cdc2dd5 chore: install typings with npm i 2016-06-21 12:17:30 -07:00
dadd5ddded chore: add lint and clang-format 2016-06-21 12:17:30 -07:00
56f8c95ee9 tests(router): add tests verifying that updating secondary segments using router link works 2016-06-21 12:17:30 -07:00
ed50e17e5b refactor(router): rename queryParameters into queryParams 2016-06-21 12:17:30 -07:00
33b518ad21 feat(router): update RouterLink to support query params and fragment 2016-06-21 12:17:30 -07:00
b0e7c14545 fix(router): add an app initializer to trigger initial navigation
Closes #10
2016-06-21 12:17:30 -07:00
5742d4720a fix(router): fix router to handle guards that return observable
Closes #19
2016-06-21 12:17:30 -07:00
9b356d9b86 fix(router): traverse route config in depth-first order
Closes #17
2016-06-21 12:17:30 -07:00
793ac3f6b4 Configure router with provided routes
Closes #9
2016-06-21 12:17:30 -07:00
9b094e42a3 chore(router): update the npm dist 2016-06-21 12:17:30 -07:00
6ce7a5a1ea docs(router): add docs 2016-06-21 12:17:30 -07:00
88920bfee1 feat(router): add support for basic events 2016-06-21 12:17:30 -07:00
2717bcc3af feat(router): implement cancelation 2016-06-21 12:17:30 -07:00
5d386dc426 chore(router): update build dir 2016-06-21 12:17:30 -07:00
f34af4f249 feat(router): add support for using classes as guard 2016-06-21 12:17:30 -07:00
f04b6978fb cleanup(router): add @internal to constructors where needed 2016-06-21 12:17:30 -07:00
ab958598d7 feat(router): implement CandDeactivate 2016-06-21 12:17:30 -07:00
1914847e72 cleanup(router): make strictNullChecks happy 2016-06-21 12:17:30 -07:00
d95f0fd83d fix(router): fix index routes 2016-06-21 12:17:30 -07:00
243612e36d refactor(router): rename candidate into snapshot 2016-06-21 12:17:30 -07:00
c5cca8e098 feat(router): add support for CanActivate guard 2016-06-21 12:17:30 -07:00
99f7404d8b refactor(router): remove rootNode function 2016-06-21 12:17:30 -07:00
9ff6b0828f feat(router): make activation sync 2016-06-21 12:17:30 -07:00
6f052d1daf feat(router): add a function to resolve components 2016-06-21 12:17:30 -07:00
63c194b71f feat(router): change recognize to return a router state candidate 2016-06-21 12:17:30 -07:00
46911117f1 feat(router): implement a function create router state out of a candidate 2016-06-21 12:17:30 -07:00
2de1030413 feat(router): add RouterStateCandidate 2016-06-21 12:17:30 -07:00
1f6ade894e cleanup(router): fix a typo 2016-06-21 12:17:30 -07:00
8407cfeac7 fix(router): fix router to take root component type instead of instance 2016-06-21 12:17:30 -07:00
91d64a2855 feat(router): export provideRouter via index 2016-06-21 12:17:30 -07:00
40a06af79b feat(router): add provideRouter to configure the router when bootstrapping an app 2016-06-21 12:17:30 -07:00
8aef86f4a0 feat(router): export all public api tokens via index 2016-06-21 12:17:30 -07:00
5bdc6ecec8 chore: adds the build dir to use with 'npm install' 2016-06-21 12:17:30 -07:00
c179b5033b feat(router): implement relative navigation 2016-06-21 12:17:30 -07:00
86f47273bc feat(router): changes router config not to use names 2016-06-21 12:17:30 -07:00
2e1bd46bb1 feat(router): add createUrlTree 2016-06-21 12:17:30 -07:00
a9e773b47b feat(router): serialize outlet names into the url 2016-06-21 12:17:30 -07:00
10d38cbb72 chore(router): change karma reporter 2016-06-21 12:17:30 -07:00
a5371bfb8a cleanup: cleanup tsconfig files 2016-06-21 12:17:30 -07:00
4b2740f270 refactor: move index.ts into src 2016-06-21 12:17:30 -07:00
5b371736b2 feat: add RouterLink 2016-06-21 12:17:30 -07:00
c9b4bcf689 refactor: move all utility functions into the utils dir 2016-06-21 12:17:30 -07:00
013f9a2bbc feat: add tree.siblings 2016-06-21 12:17:30 -07:00
5bf1c93ead docs: adds missing api docs 2016-06-21 12:17:30 -07:00
4f6ec01932 feat: implement a simple version of the router service 2016-06-21 12:17:30 -07:00
0f79e504c9 test: set up karma to support fakeAsync 2016-06-21 12:17:30 -07:00
1a4e911b8b cleanup: fix type errors when compiling with strictNullChecks enabled 2016-06-21 12:17:30 -07:00
1f98519380 feat: implement RouterOutletMap 2016-06-21 12:17:30 -07:00
aad7010952 feat: add RouterOutlet 2016-06-21 12:17:30 -07:00
1be9ea681b fix: fix source maps 2016-06-21 12:17:30 -07:00
f259a2204b feat: implement recognizer 2016-06-21 12:17:30 -07:00
4b1db0e61c feat: implement default url serializer 2016-06-21 12:17:30 -07:00
aee764d14d chore: update TS to enable non-nullable types 2016-06-21 12:17:30 -07:00
47585498af chore: updates typings to head 2016-06-21 12:17:30 -07:00
37c5320e33 feat: implement Tree 2016-06-21 12:17:30 -07:00
01111a1122 cleanup: removes a fake test 2016-06-21 12:17:30 -07:00
0b2bb1b6f5 chore(typings): use typings instead of tsd 2016-06-21 12:17:30 -07:00
f57df3cf8a chore: set up test and build infrastructure 2016-06-21 12:17:30 -07:00
c9c81e1fbc fix(XmbSerializer): add meaning attribute, escape attribute values 2016-06-21 11:52:11 -07:00
e38e04c1c2 refactor(MessageExtractor): pass the interpolationConfig around 2016-06-21 11:52:11 -07:00
99587ea4ed refactor(i18n): misc 2016-06-21 11:52:11 -07:00
58b18d7fe7 fix(partition): fix partition when <!-- i18n --> is the only child 2016-06-21 11:52:11 -07:00
04a50f5832 feat(MessageExtractor): do not expand ICU messages before extraction 2016-06-21 11:52:11 -07:00
e157a065b0 fix(compiler): codegen view query generic types 2016-06-21 11:51:54 -07:00
41ef4b3d4a chore(npm): add repository metadata 2016-06-21 11:21:04 -07:00
262650ab39 docs(test_injector): Fix documentation typo (#9403)
- Change 'teh' for 'the'
2016-06-21 11:19:08 -07:00
8c076d5a73 fix(upgrade): fix bundling issue and fix e2e test
the previous demo app was broken and is missing an e2e test.

I fixed the app, but was not able to get protractor to properly test
this app. Julie and I are looking into that. For now I manually verified
that the app works and that the original issue was fixed.

Closes #9244
2016-06-21 11:12:42 -07:00
c5c456120c refactor: delete containsRegexp() (there is escapeRegExp() in the lang facade)
BREAKING CHANGES:

`containsRegexp` is no more exported from `@angular/core/testing`. It should not have been part of the public API in the first place.
2016-06-21 09:15:21 -07:00
fdf6bc18dd fix(compiler): properly report unresolved dependencies
Fixes #9332

Closes #9341
2016-06-21 16:36:57 +02:00
297f0fd2c3 fix(core/testing): show full error
test(platform-browser): update fail capture

test(platform-browser-dynamic): update fail capture
2016-06-20 19:36:37 -07:00
86405345b7 doc: fix enableDebugTools import path (#9377) 2016-06-20 16:45:35 -07:00
12c49042ab fix(HTTP/XhrBackend): correctly set the status code on errors (#9355)
fixes #9329
fixes angular/http#54
2016-06-20 15:02:14 -07:00
ba46ca683b fix(animations): ensure starting styles are applied when a delay is present
Closes #9326
Closes #9328
2016-06-20 11:16:39 -07:00
ca42b49fa2 refactor: misc cleanup (#9369) 2016-06-20 10:55:29 -07:00
1b28cf71f5 feat(compiler): make interpolation symbols configurable (@Component config) (#9367)
closes #9158
2016-06-20 09:52:41 -07:00
6fd52dfb38 build(npm): update ts-api-guardian to v0.0.4 (#9366) 2016-06-20 09:32:27 -07:00
af2f5c3d7d cleanup(router): removes router 2016-06-20 08:47:54 -07:00
65be81baf8 doc(CheatSheet): update ngSwitch syntax in the cheatsheet (#9361) 2016-06-20 08:05:50 -07:00
7a3689f175 chore: formating 2016-06-19 22:27:29 +02:00
8675b8dc48 fix: cleanup public api of platform-server
BREAKING CHANGE: Parse5Adapter is no longer exported as public API, use serverBootstrap()

Parse5Adapter is an implementation detail not a public API

Closes #9237

Closes #9205
2016-06-19 09:03:01 -07:00
279e816ea7 chore: Remove unnecessary calls to Parse5DomAdapter
This reverts commit 80deac5cde.
2016-06-19 08:42:00 -07:00
2d60ff14ae bug(datePipe): date format pipe's 2-digit interpretation of minutes and seconds (#9338)
Closes #9333
2016-06-18 09:03:58 -07:00
dee1b774f2 docs(changelog): add note about forthcoming deprecation of Parse5DomAdapter (#9314) 2016-06-17 17:34:14 -07:00
c0f2a22a08 fix(perf): support prod mode again
After splitting the facades into multiple modules,
enabling prod mode for code had no effect for the compiler.

Also in a change between RC1 and RC2 we created the `CompilerConfig`
via a provider with `useValue` and not via a `useFactory`, which reads
the prod mode too early.

Closes #9318
Closes #8508
Closes #9318
2016-06-17 15:59:27 -07:00
5c8d3154d7 feat(datePipe): numeric string support 2016-06-17 15:58:06 -07:00
40f8a45b95 test(DatePipe): fixes 2016-06-17 15:48:26 -07:00
76a418760e fix(BrowserUtil): fix supportsIntlApi() 2016-06-17 15:34:12 -07:00
49bf3f5b3a fix(NumberPipe): fix broken RegExp
introduced in 7498050421 (#9308)
2016-06-17 15:33:25 -07:00
773c34900f fix(change_detection): ChangeDetectorRef reattach should restore original mode
After using ChangeDetectorRef detach, it should keep the ChangeDetector mode so that it is restored after calling reattach.

closes #7078
closes #7080
2016-06-17 15:00:41 -07:00
791153c93c fix(compiler): StaticReflector ignores unregistered decorators. (#9266)
Also modified static reflector to allow writing tests in using
the .ts and using the MetadataCollector.

Also made MetadataCollector be able to use SourceFiles that have
not been bound (that is, don't have the parent property set).

Fixes #9182
Fixes #9265
2016-06-17 13:11:00 -07:00
721f53f0d6 feat(I18N Expander): do not add extra <ul> & <li> around ICU messages (#9283)
fixes #9072
2016-06-17 11:38:24 -07:00
7498050421 refactor: misc (#9308) 2016-06-17 10:57:50 -07:00
5e3ccbcea9 refactor: add types (#9288) 2016-06-17 10:57:32 -07:00
8879aa1df4 feat(security): fail more detectably when using a safe value in an interpolation.
If a user ends up with a safe value in an interpolation context, that's probably
a bug. Returning `"SafeValue must use [property]= binding"` will make it easier
to detect and correct the situation. Detecting the situation and throwing an
error for it could cause performance issues, so we're not doing this at this
point (but might revisit later).

Part of #8511 and #9253.
2016-06-17 10:00:30 -07:00
44e0ad4987 refactor(forms): remove the facade local copy (#9276) 2016-06-17 08:53:17 -07:00
c449f325ba docs: remove and identify reverts in changelog 2016-06-17 08:45:40 -07:00
5fe60759f9 feat(QueryList): support index in callbacks
Closes #9278
2016-06-17 08:09:42 -07:00
6c389ed32f ci(local dev): fix test.sh 2016-06-16 15:46:08 -07:00
45549cda61 refactor(core): get rid of the bitwise operator facade helpers 2016-06-16 14:31:55 -07:00
a13052fc73 refactor(core): rename css_parser and css_lexer files
Closes #9273
2016-06-16 14:31:48 -07:00
4e7bb03e81 refactor(core): rename AST to Ast for all CSS parser code 2016-06-16 14:31:41 -07:00
935c39a7e2 feat(core): ensure CSS parser tracks start/end values and understands complex pseudo selectors 2016-06-16 14:31:34 -07:00
e0c1c13004 chore(.github): improve github issue and PR templates
the current templates accidentaly introduce tasks list which is confusing to both people
submitting the issue as well as triaging it.
2016-06-16 14:29:05 -07:00
c08ca22dba refactor(HtmlParser): clang format 2016-06-16 13:54:00 -07:00
a3f6e19881 docs: add missing breaking changes (#9267) 2016-06-16 13:49:29 -07:00
37b617dccf chore(tsickle): add @Annotation annotations
This lets users continue using runtime-sideeffect Decorators if they choose,
only down-leveling the marked ones to Annotations.

Also remove the "skipTemplateCodegen" option, which is no longer needed
since Angular compiles with tsc-wrapped rather than ngc. The former doesn't
include any codegen.
2016-06-16 12:29:46 -07:00
c60ef45bc8 fix(HtmlParser): add missing ; 2016-06-16 10:23:02 -07:00
2b1ac63e3a npm: bump the version number in package.json
this version string is currently not authoritative source see #9264 and #9233
2016-06-16 09:57:44 -07:00
6686bc62f6 feat(benchpress): add custom user metric to benchpress
This is a continuation of #7440 (@jeffbcross).

Closes #9229
2016-06-16 07:30:53 -07:00
1eaa193c51 feat(compiler-cli): add a debug option to control the output
fixes #9208
2016-06-15 18:13:57 -07:00
b620f4f456 feat(DomElementSchemaRegistry): add support for <ng-content> and <ng-container> 2016-06-15 18:13:57 -07:00
e484c62a8d fix(HtmlParser): do not add required parents to template root elements
fixes #5967
2016-06-15 18:13:57 -07:00
9ba400d7d5 fix(HtmlParser): consider <ng-container> when adding required parents 2016-06-15 18:13:57 -07:00
9cbd8f7afc test(ng-container): test nesting ng-containers 2016-06-15 18:13:57 -07:00
8e6e90e703 fix(forms): ngModel should export as ngModel 2016-06-15 17:46:45 -07:00
26676c4833 docs(webworker): add/correct experimental markers to web worker apis 2016-06-15 17:12:40 -07:00
39e0b4903c feat(radio): support radio button sharing a control 2016-06-15 15:27:34 -07:00
54c577cfe0 chore: update cheatsheet for new provider syntax (#9227) 2016-06-15 15:11:39 -07:00
27024915e4 docs: removed iframe from changelog (#9223) 2016-06-15 13:17:45 -07:00
80f3e7591e chore(docs): Update changelog for release (#9217) 2016-06-15 12:49:39 -07:00
2309 changed files with 136439 additions and 128347 deletions

6
.gitattributes vendored
View File

@ -1,5 +1,9 @@
# Auto detect text files and perform LF normalization
* text=auto
# JS files must always use LF for tools to work
# JS and TS files must always use LF for tools to work
*.js eol=lf
*.ts eol=lf
# Must keep Windows line ending to be parsed correctly
scripts/windows/packages.txt eol=crlf

View File

@ -1,31 +1,39 @@
* **I'm submitting a ...**
- [ ] bug report
- [ ] feature request
- [ ] support request => Please do not submit support request here, see note at the top of this template.
<!--
IF YOU DON'T FILL OUT THE FOLLOWING INFORMATION WE MIGHT CLOSE YOUR ISSUE WITHOUT INVESTIGATING
-->
**I'm submitting a ...** (check one with "x")
```
[ ] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
```
**Current behavior**
<!-- Describe how the bug manifests. -->
**Expected behavior**
<!-- Describe what the behavior would be without the bug. -->
**Expected/desired behavior**
* **If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem** via
**Minimal reproduction of the problem with instructions**
<!--
If the current behavior is a bug or you can illustrate your feature request better with an example,
please provide the *STEPS TO REPRODUCE* and if possible a *MINIMAL DEMO* of the problem via
https://plnkr.co or similar (you can use this template as a starting point: http://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5).
-->
**What is the motivation / use case for changing the behavior?**
<!-- Describe the motivation or the concrete use case -->
**Please tell us about your environment:**
<!-- Operating system, IDE, package manager, HTTP server, ... -->
* **What is the expected behavior?**
* **Angular version:** 2.0.X
<!-- Check whether this is still an issue in the most recent Angular version -->
* **What is the motivation / use case for changing the behavior?**
* **Please tell us about your environment:**
* **Angular version:** 2.0.0-beta.X
* **Browser:** [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]
<!-- All browsers where this could be reproduced -->
* **Browser:** [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]
* **Language:** [all | TypeScript X.X | ES6/7 | ES5 | Dart]
* **Language:** [all | TypeScript X.X | ES6/7 | ES5]
* **Node (for AoT issues):** `node --version` =

View File

@ -1,17 +1,19 @@
**Please check if the PR fulfills these requirements**
- [ ] The commit message follows our guidelines: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit-message-format
- [ ] The commit message follows our guidelines: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
- [ ] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)
**What kind of change does this PR introduce?** (Bug fix, feature, docs update, ...)
- [ ] Bugfix
- [ ] Feature
- [ ] Code style update (formatting, local variables)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] CI related changes
- [ ] Other... Please describe:
**What kind of change does this PR introduce?** (check one with "x")
```
[ ] Bugfix
[ ] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Other... Please describe:
```
**What is the current behavior?** (You can also link to an open issue here)
@ -21,9 +23,11 @@
**Does this PR introduce a breaking change?**
- [ ] Yes
- [ ] No
**Does this PR introduce a breaking change?** (check one with "x")
```
[ ] Yes
[ ] No
```
If this PR contains a breaking change, please describe the impact and migration path for existing applications: ...

22
.gitignore vendored
View File

@ -1,26 +1,9 @@
.DS_STORE
# Dont commit the following directories created by pub.
packages
pubspec.lock
.pub
.packages
/dist/
.buildlog
node_modules
bower_components
# Or broccoli working directory
tmp
# Or the files created by dart2js.
*.dart.js
*.dart.precompiled.js
*.js_
*.js.deps
*.js.map
# Include when developing application packages.
pubspec.lock
.c9
@ -37,13 +20,8 @@ modules/.vscode
# Ignore npm debug log
npm-debug.log
/docs/bower_components/
# build-analytics
.build-analytics
# built dart payload tests
/modules_dart/payload/**/build
# rollup-test output
/modules/rollup-test/dist/

2
.nvmrc
View File

@ -1 +1 @@
5.4.1
6.9.5

248
.pullapprove.yml Normal file
View File

@ -0,0 +1,248 @@
# Configuration for pullapprove.com
#
# Approval access and primary role is determined by info in the project ownership spreadsheet:
# https://docs.google.com/spreadsheets/d/1-HIlzfbPYGsPr9KuYMe6bLfc4LXzPjpoALqtYRYTZB0/edit?pli=1#gid=0&vpid=A5
#
# === GitHub username to Full name map ===
#
# alexeagle - Alex Eagle
# alxhub - Alex Rickabaugh
# chuckjaz - Chuck Jazdzewski
# gkalpak - George Kalpakas
# IgorMinar - Igor Minar
# kara - Kara Erickson
# matsko - Matias Niemelä
# mhevery - Misko Hevery
# petebacondarwin - Pete Bacon Darwin
# pkozlowski-opensource - Pawel Kozlowski
# robwormald - Rob Wormald
# tbosch - Tobias Bosch
# vicb - Victor Berchet
# vikerman - Vikram Subramanian
version: 2
group_defaults:
required: 1
reset_on_reopened:
enabled: true
approve_by_comment:
enabled: false
groups:
root:
conditions:
files:
include:
- "*"
exclude:
- "angular.io/*"
- "integration/*"
- "modules/*"
- "tools/*"
users:
- IgorMinar
- mhevery
public-api:
conditions:
files:
include:
- "tools/public_api_guard/*"
users:
- IgorMinar
- mhevery
build-and-ci:
conditions:
files:
include:
- "*.yml"
- "*.json"
- "*.lock"
- "tools/*"
exclude:
- "tools/@angular/tsc-wrapped/*"
- "tools/public_api_guard/*"
users:
- IgorMinar #primary
- mhevery
integration:
conditions:
files:
- "integration/*"
users:
- alexeagle
- mhevery
- tbosch
- vicb
- IgorMinar #fallback
core:
conditions:
files:
- "modules/@angular/core/*"
users:
- tbosch #primary
- mhevery
- vicb
- IgorMinar #fallback
compiler/animations:
conditions:
files:
- "modules/@angular/compiler/src/animation/*"
users:
- matsko #primary
- tbosch
- IgorMinar #fallback
- mhevery #fallback
compiler/i18n:
conditions:
files:
- "modules/@angular/compiler/src/i18n/*"
users:
- vicb #primary
- tbosch
- IgorMinar #fallback
- mhevery #fallback
compiler:
conditions:
files:
- "modules/@angular/compiler/*"
users:
- tbosch #primary
- vicb
- chuckjaz
- mhevery
- IgorMinar #fallback
compiler-cli:
conditions:
files:
- "tools/@angular/tsc-wrapped/*"
- "modules/@angular/compiler-cli/*"
users:
- alexeagle
- chuckjaz
- tbosch
- IgorMinar #fallback
- mhevery #fallback
common:
conditions:
files:
- "modules/@angular/common/*"
users:
- pkozlowski-opensource #primary
- vicb
- IgorMinar #fallback
- mhevery #fallback
forms:
conditions:
files:
- "modules/@angular/forms/*"
users:
- kara #primary
# needs secondary
- IgorMinar #fallback
- mhevery #fallback
http:
conditions:
files:
- "modules/@angular/http/*"
users:
- vikerman #primary
- alxhub
- IgorMinar #fallback
- mhevery #fallback
language-service:
conditions:
files:
- "modules/@angular/language-service/*"
users:
- chuckjaz #primary
# needs secondary
- IgorMinar #fallback
- mhevery #fallback
router:
conditions:
files:
- "modules/@angular/router/*"
users:
- vicb #primary
# needs secondary
- IgorMinar #fallback
- mhevery #fallback
upgrade:
conditions:
files:
- "modules/@angular/upgrade/*"
users:
- petebacondarwin #primary
- gkalpak
- IgorMinar #fallback
- mhevery #fallback
platform-browser:
conditions:
files:
- "modules/@angular/platform-browser/*"
users:
- tbosch #primary
- vicb #secondary
- IgorMinar #fallback
- mhevery #fallback
platform-server:
conditions:
files:
- "modules/@angular/platform-server/*"
users:
- vikerman #primary
- alxhub
- vicb
- tbosch
- IgorMinar #fallback
- mhevery #fallback
platform-webworker:
conditions:
files:
- "modules/@angular/platform-webworker/*"
users:
- vicb #primary
- tbosch #secondary
- IgorMinar #fallback
- mhevery #fallback
benchpress:
conditions:
files:
- "modules/@angular/benchpress/*"
users:
- tbosch #primary
# needs secondary
- IgorMinar #fallback
- mhevery #fallback
angular.io:
conditions:
files:
- "angular.io/*"
users:
- IgorMinar
- robwormald
- petebacondarwin
- mhevery #fallback

View File

@ -1,7 +1,7 @@
language: node_js
sudo: false
node_js:
- '5.4.1'
- '6.9.5'
addons:
# firefox: "38.0"
@ -20,20 +20,9 @@ cache:
directories:
- ./node_modules
- ./.chrome/chromium
# - $HOME/.pub-cache
#before_cache:
# # Undo the pollution of the typescript_next build before the cache is primed for future use
# - if [[ "$MODE" == "typescript_next" ]]; then npm install typescript; fi
env:
global:
# - KARMA_JS_BROWSERS=ChromeNoSandbox
# - E2E_BROWSERS=ChromeOnTravis
# - LOGS_DIR=/tmp/angular-build/logs
# - ARCH=linux-x64
# GITHUB_TOKEN_ANGULAR
# This is needed for the e2e Travis matrix task to publish packages to github for continuous packages delivery.
- secure: "fq/U7VDMWO8O8SnAQkdbkoSe2X92PVqg4d044HmRYVmcf6YbO48+xeGJ8yOk0pCBwl3ISO4Q2ot0x546kxfiYBuHkZetlngZxZCtQiFT9kyId8ZKcYdXaIW9OVdw3Gh3tQyUwDucfkVhqcs52D6NZjyE2aWZ4/d1V4kWRO/LMgo="
@ -47,150 +36,16 @@ env:
- CI_MODE=browserstack_optional
matrix:
fast_finish: true
allow_failures:
- env: "CI_MODE=saucelabs_optional"
- env: "CI_MODE=browserstack_optional"
install:
- ./scripts/ci-lite/install.sh
before_script:
script:
- ./scripts/ci-lite/build.sh && ./scripts/ci-lite/test.sh
after_script:
- ./scripts/ci-lite/cleanup.sh
#branches:
# except:
# - g3_v2_0
#
#cache:
# directories:
# - $HOME/.pub-cache
# - $HOME/.chrome/chromium
#
#before_cache:
# # Undo the pollution of the typescript_next build before the cache is primed for future use
# - if [[ "$MODE" == "typescript_next" ]]; then npm install typescript; fi
#
#env:
# global:
# # Use newer verison of GCC to that is required to compile native npm modules for Node v4+ on Ubuntu Precise
# # more info: https://docs.travis-ci.com/user/languages/javascript-with-nodejs#Node.js-v4-(or-io.js-v3)-compiler-requirements
# - CXX=g++-4.8
# - KARMA_DART_BROWSERS=DartiumWithWebPlatform
# # No sandbox mode is needed for Chromium in Travis, it crashes otherwise: https://sites.google.com/a/chromium.org/chromedriver/help/chrome-doesn-t-start
# - KARMA_JS_BROWSERS=ChromeNoSandbox
# - E2E_BROWSERS=ChromeOnTravis
# - LOGS_DIR=/tmp/angular-build/logs
# - SAUCE_USERNAME=angular-ci
# - SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
# - BROWSER_STACK_USERNAME=angularteam1
# - BROWSER_STACK_ACCESS_KEY=BWCd4SynLzdDcv8xtzsB
# - ARCH=linux-x64
# - DART_DEV_VERSION=latest
# - DART_STABLE_VERSION=latest
# - DART_CHANNEL=stable
# - DART_VERSION=$DART_STABLE_VERSION
# # Token for tsd to increase github rate limit
# # See https://github.com/DefinitelyTyped/tsd#tsdrc
# # This does not use http://docs.travis-ci.com/user/environment-variables/#Secure-Variables
# # because those are not visible for pull requests, and those should also be reliable.
# # This SSO token belongs to github account angular-github-ratelimit-token which has no access
# # (password is in Valentine)
# - TSDRC='{"token":"ef474500309daea53d5991b3079159a29520a40b"}'
# # GITHUB_TOKEN_ANGULAR
# - secure: "fq/U7VDMWO8O8SnAQkdbkoSe2X92PVqg4d044HmRYVmcf6YbO48+xeGJ8yOk0pCBwl3ISO4Q2ot0x546kxfiYBuHkZetlngZxZCtQiFT9kyId8ZKcYdXaIW9OVdw3Gh3tQyUwDucfkVhqcs52D6NZjyE2aWZ4/d1V4kWRO/LMgo="
# matrix:
# # Order: a slower build first, so that we don't occupy an idle travis worker waiting for others to complete.
# - MODE=dart
# - MODE=dart DART_CHANNEL=dev
# - MODE=saucelabs_required
# - MODE=browserstack_required
# - MODE=saucelabs_optional
# - MODE=browserstack_optional
# - MODE=dart_ddc
# - MODE=js
# - MODE=router
# - MODE=build_only
# - MODE=typescript_next
# - MODE=lint
#
#matrix:
# allow_failures:
# - env: "MODE=saucelabs_optional"
# - env: "MODE=browserstack_optional"
#
#addons:
# firefox: "38.0"
# apt:
# sources:
# - ubuntu-toolchain-r-test
# packages:
# - g++-4.8
#
#before_install:
# - node tools/analytics/build-analytics start ci job
# - node tools/analytics/build-analytics start ci before_install
# - echo ${TSDRC} > .tsdrc
# - export CHROME_BIN=$HOME/.chrome/chromium/chrome-linux/chrome
# - export DISPLAY=:99.0
# - export GIT_SHA=$(git rev-parse HEAD)
# - ./scripts/ci/init_android.sh
# - sh -e /etc/init.d/xvfb start
# # Use a separate SauseLabs account for upstream/master builds in order for Sauce to create a badge representing the status of just upstream/master
# - '[ "${TRAVIS_PULL_REQUEST}" = "false" ] && [ "${TRAVIS_BRANCH}" = "master" ] && SAUCE_USERNAME="angular2-ci" && SAUCE_ACCESS_KEY="693ebc16208a-0b5b-1614-8d66-a2662f4e" || true'
# - node tools/analytics/build-analytics success ci before_install
#
#install:
# - node tools/analytics/build-analytics start ci install
# # Install version of npm that we are locked against
# - npm install -g npm@3.5.3
# # Install version of Chromium that we are locked against
# - ./scripts/ci/install_chromium.sh
# # Install version of Dart based on the matrix build variables
# - ./scripts/ci/install_dart.sh ${DART_CHANNEL} ${DART_VERSION} ${ARCH}
# # Print the size of caches to ease debugging
# - du -sh ./node_modules || true
# # Install npm dependecies
# # check-node-modules will exit(1) if we don't need to install
# # we need to manually kick off the postinstall script if check-node-modules exit(0)s
# - node tools/npm/check-node-modules --purge && npm install || npm run postinstall
# - node tools/analytics/build-analytics success ci install
#
#before_script:
# - node tools/analytics/build-analytics start ci before_script
# - mkdir -p $LOGS_DIR
# - ./scripts/ci/presubmit-queue-setup.sh
# - node tools/analytics/build-analytics success ci before_script
#
#script:
# - node tools/analytics/build-analytics start ci script
# - ./scripts/ci/build_and_test.sh ${MODE}
# - node tools/analytics/build-analytics success ci script
#
#after_script:
# - node tools/analytics/build-analytics start ci after_script
# - ./scripts/ci/print-logs.sh
# - ./scripts/ci/after-script.sh
# - ./scripts/publish/publish-build-artifacts.sh
# - node tools/analytics/build-analytics success ci after_script
# - tools/analytics/build-analytics $TRAVIS_TEST_RESULT ci job
#
#notifications:
# webhooks:
# urls:
# - https://webhooks.gitter.im/e/1ef62e23078036f9cee4
# # trigger Buildtime Trend Service to parse Travis CI log
# - https://buildtimetrend.herokuapp.com/travis
# - http://104.197.9.155:8484/hubot/travis/activity
# on_success: always # options: [always|never|change] default: always
# on_failure: always # options: [always|never|change] default: always
# on_start: never # default: never
# slack:
# secure: EP4MzZ8JMyNQJ4S3cd5LEPWSMjC7ZRdzt3veelDiOeorJ6GwZfCDHncR+4BahDzQAuqyE/yNpZqaLbwRWloDi15qIUsm09vgl/1IyNky1Sqc6lEknhzIXpWSalo4/T9ZP8w870EoDvM/UO+LCV99R3wS8Nm9o99eLoWVb2HIUu0=

File diff suppressed because it is too large Load Diff

View File

@ -6,29 +6,16 @@ for details about how we maintain a linear commit history, and the rules for com
As a contributor, just read the instructions in [CONTRIBUTING.md](CONTRIBUTING.md) and send a pull request.
Someone with committer access will do the rest.
## The `PR: merge` label and `presubmit-*` branches
# Change approvals
We have automated the process for merging pull requests into master. Our goal is to minimize the disruption for
Angular committers and also prevent breakages on master.
Change approvals in our monorepo are managed via [pullapprove.com](https://about.pullapprove.com/) and are configured via the `.pullapprove.yaml` file.
When a PR has `pr_state: LGTM` and is ready to merge, you should add the `pr_action: merge` label.
Currently (late 2015), we need to ensure that each PR will cleanly merge into the Google-internal version control,
so the caretaker reviews the changes manually.
After this review, the caretaker adds `zomg_admin: do_merge` which is restricted to admins only.
A robot running as [mary-poppins](https://github.com/mary-poppins)
is notified that the label was added by an authorized person,
and will create a new branch in the angular project, using the convention `presubmit-{username}-pr-{number}`.
# Merging
(Note: if the automation fails, committers can instead push the commits to a branch following this naming scheme.)
Once a change has all the approvals either the last approver or the PR author (if PR author has the project collaborator status) should mark the PR with "PR: merge" label.
This signals to the caretaker that the PR should be merged.
When a Travis build succeeds for a presubmit branch named following the convention,
Travis will re-base the commits, merge to master, and close the PR automatically.
# Who is the Caretaker?
Finally, after merge `mary-poppins` removes the presubmit branch.
## Administration
The list of users who can trigger a merge by adding the `zomg_admin: do_merge` label is stored in our appengine app datastore.
Edit the contents of the [CoreTeamMember Table](
https://console.developers.google.com/project/angular2-automation/datastore/query?queryType=KindQuery&namespace=&kind=CoreTeamMember)
See [this explanation](https://twitter.com/IgorMinar/status/799365744806854656).

View File

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

View File

@ -1,19 +1,13 @@
# Building and Testing Angular 2 for JS and Dart
# Building and Testing Angular
This document describes how to set up your development environment to build and test Angular, both
JS and Dart versions. It also explains the basic mechanics of using `git`, `node`, and `npm`.
This document describes how to set up your development environment to build and test Angular.
It also explains the basic mechanics of using `git`, `node`, and `npm`.
* [Prerequisite Software](#prerequisite-software)
* [Getting the Sources](#getting-the-sources)
* [Environment Variable Setup](#environment-variable-setup)
* [Installing NPM Modules and Dart Packages](#installing-npm-modules-and-dart-packages)
* [Build commands](#build-commands)
* [Installing NPM Modules](#installing-npm-modules)
* [Building](#building)
* [Running Tests Locally](#running-tests-locally)
* [Code Style](#code-style)
* [Project Information](#project-information)
* [CI using Travis](#ci-using-travis)
* [Transforming Dart code](#transforming-dart-code)
* [Debugging](#debugging)
See the [contribution guidelines](https://github.com/angular/angular/blob/master/CONTRIBUTING.md)
if you'd like to contribute to Angular.
@ -32,15 +26,6 @@ following products on your development machine:
(version `>=3.5.3 <4.0`), which comes with Node. Depending on your system, you can install Node either from
source or as a pre-packaged bundle.
* *Optional*: [Dart](https://www.dartlang.org) (version `>=1.13.2 <2.0.0`), specifically the Dart SDK and
Dartium (a version of [Chromium](http://www.chromium.org) with native support for Dart through
the Dart VM). Visit Dart's [Downloads page](https://www.dartlang.org/downloads) page for
instructions. You can also download both **stable** and **dev** channel versions from the
[download archive](https://www.dartlang.org/downloads/archive/). In that case, on Windows, Dart
must be added 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`).
* [Java Development Kit](http://www.oracle.com/technetwork/es/java/javase/downloads/index.html) which is used
to execute the selenium standalone server for e2e testing.
@ -65,44 +50,9 @@ cd angular
# Add the main Angular repository as an upstream remote to your repository:
git remote add upstream https://github.com/angular/angular.git
```
## Installing NPM Modules
## Environment Variable Setup
Define the environment variables listed below. These are mainly needed for the testing. The
notation shown here is for [`bash`](http://www.gnu.org/software/bash); adapt as appropriate for
your favorite shell.
Examples given below of possible values for initializing the environment variables assume **Mac OS
X** and that you have installed the Dart Editor in the directory named by
`DART_EDITOR_DIR=/Applications/dart`. This is only for illustrative purposes.
```shell
# DARTIUM_BIN: path to a Dartium browser executable; used by Karma to run Dart tests
export DARTIUM_BIN="$DART_EDITOR_DIR/chromium/Chromium.app/Contents/MacOS/Chromium"
```
Add the Dart SDK `bin` directory to your path and/or define `DART_SDK` (this is also detailed
[here](https://www.dartlang.org/tools/pub/installing.html)):
```shell
# DART_SDK: path to a Dart SDK directory
export DART_SDK="$DART_EDITOR_DIR/dart-sdk"
# Update PATH to include the Dart SDK bin directory
PATH+=":$DART_SDK/bin"
```
And specify where the pubs dependencies are downloaded. By default, this directory is located under .pub_cache
in your home directory (on Mac and Linux), or in AppData\Roaming\Pub\Cache (on Windows).
```shell
# PUB_CACHE: location of pub dependencies
export PUB_CACHE="/Users/<user>/.pub-cache"
```
## Installing NPM Modules and Dart Packages
Next, install the JavaScript modules and Dart packages needed to build and test Angular:
Next, install the JavaScript modules needed to build and test Angular:
```shell
# Install Angular project dependencies (package.json)
@ -121,246 +71,114 @@ particular `gulp` and `protractor` commands. If you prefer, you can drop this pa
Since global installs can become stale, and required versions can vary by project, we avoid their
use in these instructions.
*Option 2*: defining a bash alias like `alias nbin='PATH=$(npm bin):$PATH'` as detailed in this
*Option 2*: globally installing the package `npm-run` by running `npm install -g npm-run`
(you might need to prefix this command with `sudo`). You will then be able to run locally installed
package scripts by invoking: e.g., `npm-run gulp build`
(see [npm-run project page](https://github.com/timoxley/npm-run) for more details).
*Option 3*: defining a bash alias like `alias nbin='PATH=$(npm bin):$PATH'` as detailed in this
[Stackoverflow answer](http://stackoverflow.com/questions/9679932/how-to-use-package-installed-locally-in-node-modules/15157360#15157360) and used like this: e.g., `nbin gulp build`.
## Build commands
## Installing Bower Modules
To build Angular and prepare tests, run:
Now run `bower` to install additional dependencies:
```shell
$(npm bin)/gulp build
# Install other Angular project dependencies (bower.json)
bower install
```
Notes:
* Results are put in the `dist` folder.
* This will also run `pub get` for the subfolders in `modules` and run `dartanalyzer` for
every file that matches `<module>/src/<module>.dart`, e.g. `di/src/di.dart`.
## Windows only
You can selectively build either the JS or Dart versions as follows:
In order to create the right symlinks, run **as administrator**:
```shell
./scripts/windows/create-symlinks.sh
```
* `$(npm bin)/gulp build.js`
* `$(npm bin)/gulp build.dart`
Before submitting a PR, do not forget to remove them:
```shell
./scripts/windows/remove-symlinks.sh
```
To clean out the `dist` folder, run:
## Building
To build Angular run:
```shell
$(npm bin)/gulp clean
./build.sh
```
* Results are put in the dist folder.
## Running Tests Locally
### Full test suite
* `npm test`: full test suite for both JS and Dart versions of Angular. These are the same tests
that run on Travis.
You can selectively run either the JS or Dart versions as follows:
* `$(npm bin)/gulp test.all.js`
* `$(npm bin)/gulp test.all.dart`
### Unit tests
You can run just the unit tests as follows:
* `$(npm bin)/gulp test.unit.js`: JS tests in a browser; runs in **watch mode** (i.e.
watches the test files for changes and re-runs tests when files are updated).
* `$(npm bin)/gulp test.unit.cjs`: JS tests in NodeJS; runs in **watch mode**.
* `$(npm bin)/gulp test.unit.dart`: Dart tests in Dartium; runs in **watch mode**.
If you prefer running tests in "single-run" mode rather than watch mode use:
* `$(npm bin)/gulp test.unit.js/ci`
* `$(npm bin)/gulp test.unit.cjs/ci`
* `$(npm bin)/gulp test.unit.dart/ci`
The task updates the dist folder with transpiled code whenever a source or test file changes, and
Karma is run against the new output.
**Note**: If you want to only run a single test you can alter the test you wish to run by changing
`it` to `iit` or `describe` to `ddescribe`. This will only run that individual test and make it
much easier to debug. `xit` and `xdescribe` can also be useful to exclude a test and a group of
tests respectively.
**Note**: **watch mode** needs symlinks to work, so if you're using Windows, ensure you have the
rights to built them in your operating system. On Windows, only administrators can create symbolic links by default, but you may change the policy. (see [here](https://technet.microsoft.com/library/cc766301.aspx?f=255&MSPPError=-2147217396).)
### Unit tests with Sauce Labs or Browser Stack
First, in a terminal, create a tunnel with [Sauce Connect](https://docs.saucelabs.com/reference/sauce-connect/) or [Browser Stack Local](https://www.browserstack.com/local-testing#command-line), and valid credentials.
Then, in another terminal:
- Define the credentials as environment variables, e.g.:
```
export SAUCE_USERNAME='my_user'; export SAUCE_ACCESS_KEY='my_key';
export BROWSER_STACK_USERNAME='my_user'; export BROWSER_STACK_ACCESS_KEY='my_key';
```
- Then run `gulp test.unit.js.(sauce|browserstack) --browsers=option1,option2,..,optionN`
The options are any mix of browsers and aliases which are defined in the [browser-providers.conf.js](https://github.com/angular/angular/blob/master/browser-providers.conf.js) file.
They are case insensitive, and the `SL_` or `BS_` prefix must not be added for browsers.
Some examples of commands:
```
gulp test.unit.js.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.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
1. `$(npm bin)/gulp build.js.cjs` (builds benchpress and tests into `dist/js/cjs` folder).
2. `$(npm bin)/gulp serve.js.prod serve.dart` (runs a local webserver).
3. `$(npm bin)/protractor protractor-js.conf.js`: JS e2e tests.
4. `$(npm bin)/protractor protractor-dart2js.conf.js`: dart2js e2e tests.
Angular specific command line options when running protractor:
- `$(npm bin)/protractor protractor-{js|dart2js}-conf.js --ng-help`
### Performance tests
1. `$(npm bin)/gulp build.js.cjs` (builds benchpress and tests into `dist/js/cjs` folder)
2. `$(npm bin)/gulp serve.js.prod serve.dart` (runs a local webserver)
3. `$(npm bin)/protractor protractor-js.conf.js --benchmark`: JS performance tests
4. `$(npm bin)/protractor protractor-dart2js.conf.js --benchmark`: dart2js performance tests
Angular specific command line options when running protractor (e.g. force gc, ...):
`$(npm bin)/protractor protractor-{js|dart2js}-conf.js --ng-help`
## Code Style
### Formatting with <a name="clang-format">clang-format</a>
We use [clang-format](http://clang.llvm.org/docs/ClangFormat.html) to automatically enforce code
style for our TypeScript code. This allows us to focus our code reviews more on the content, and
less on style nit-picking. It also lets us encode our style guide in the `.clang-format` file in the
repository, allowing many tools and editors to share our settings.
To check the formatting of your code, run
gulp lint
Note that the continuous build on CircleCI will fail the build if files aren't formatted according
to the style guide.
Your life will be easier if you include the formatter in your standard workflow. Otherwise, you'll
likely forget to check the formatting, and waste time waiting for a build on Travis that fails due
to some whitespace difference.
* Use `gulp format` to format everything.
* Use `gulp lint` to check if your code is `clang-format` clean. This also gives
you a command line to format your code.
* `clang-format` also includes a git hook, run `git clang-format` to format all files you
touched.
* You can run this as a **git pre-commit hook** to automatically format your delta regions when you
commit a change. In the angular repo, run
```
$ echo -e '#!/bin/sh\nexec git clang-format --style file' > .git/hooks/pre-commit
$ chmod u+x !$
```
**NOTE**: To use ```git clang-format``` use have to make sure that ```git-clang-format``` is in your
```PATH```. The easiest way is probably to just ```npm install -g clang-format``` as it comes with
```git-clang-format```.
* **WebStorm** can run clang-format on the current file.
1. Under Preferences, open Tools > External Tools.
1. Plus icon to Create Tool
1. Fill in the form:
- Name: clang-format
- Description: Format
- Synchronize files after execution: checked
- Open console: not checked
- Show in: Editor menu
- Program: `$ProjectFileDir$/node_modules/.bin/clang-format`
- Parameters: `-i -style=file $FilePath$`
- Working directory: `$ProjectFileDir$`
* `clang-format` integrations are also available for many popular editors (`vim`, `emacs`,
`Sublime Text`, etc.).
### Linting
We use [tslint](https://github.com/palantir/tslint) for linting. See linting rules in [gulpfile](gulpfile.js). To lint, run
To run tests:
```shell
$ ./test.sh node # Run all angular tests on node
$ ./test.sh browser # Run all angular tests in browser
$ ./test.sh browserNoRouter # Optionally run all angular tests without router in browser
$ ./test.sh tools # Run angular tooling (not framework) tests
```
You should execute the 3 test suites before submitting a PR to github.
All the tests are executed on our Continuous Integration infrastructure and a PR could only be merged once the tests pass.
- CircleCI fails if your code is not formatted properly,
- Travis CI fails if any of the test suites described above fails.
## Update the public API tests
If you happen to modify the public API of Angular, API golden files must be updated using:
``` shell
$ gulp public-api:update
```
Note: The command `gulp public-api:enforce` fails when the API doesn't match the golden files. Make sure to rebuild
the project before trying to verify after an API change.
## <a name="clang-format"></a> Formatting your source code
Angular uses [clang-format](http://clang.llvm.org/docs/ClangFormat.html) to format the source code. If the source code
is not properly formatted, the CI will fail and the PR can not be merged.
You can automatically format your code by running:
``` shell
$ gulp format
```
## Linting/verifying your source code
You can check that your code is properly formatted and adheres to coding style by running:
``` shell
$ gulp lint
```
## Generating the API documentation
## Publishing your own personal snapshot build
The following gulp task will generate the API docs in the `dist/angular.io/partials/api/angular2`:
You may find that your un-merged change needs some validation from external participants.
Rather than requiring them to pull your Pull Request and build Angular locally, you can
publish the `*-builds` snapshots just like our Travis build does.
```shell
$(npm bin)/gulp docs/angular.io
First time, you need to create the github repositories:
``` shell
$ export TOKEN=[get one from https://github.com/settings/tokens]
$ CREATE_REPOS=1 ./scripts/publish/publish-build-artifacts.sh [github username]
```
You can serve the generated documentation to check how it would render on [angular.io](https://angular.io/):
- check out the [angular.io repo](https://github.com/angular/angular.io) locally,
- install dependencies as described in the [angular.io README](https://github.com/angular/angular.io/blob/master/README.md),
- copy the generated documentation from your local angular repo at `angular/dist/angular.io/partials/api/angular2` to your local angular.io repo at `angular.io/public/docs/js/latest/api`,
- run `harp compile` at the root of the angular.io repo to check the generated documentation for errors,
- run `harp server` and open a browser at `http://localhost:9000/docs/js/latest/api/` to check the rendered documentation.
For subsequent snapshots, just run
## Project Information
``` shell
$ ./scripts/publish/publish-build-artifacts.sh [github username]
```
### Folder structure
* `modules/*`: modules that will be loaded in the browser
* `tools/*`: tools that are needed to build Angular
* `dist/*`: build files are placed here.
### File suffixes
* `*.ts`: TypeScript files that get transpiled to Dart and EcmaScript 5/6
* `*.dart`: Dart files that don't get transpiled
## CI using Travis
For instructions on setting up Continuous Integration using Travis, see the instructions given
[here](https://github.com/angular/angular.dart/blob/master/travis.md).
## Transforming Dart code
See the [wiki](//github.com/angular/angular/wiki/Angular-2-Dart-Transformer).
## Debugging
### Debug the transpiler
If you need to debug the transpiler:
- add a `debugger;` statement in the transpiler code,
- from the root folder, execute `node debug $(npm bin)/gulp build` to enter the node
debugger
- press "c" to execute the program until you reach the `debugger;` statement,
- you can then type "repl" to enter the REPL and inspect variables in the context.
See the [Node.js manual](http://nodejs.org/api/debugger.html) for more information.
Notes:
- You can also execute `node $(npm bin)/karma start karma-dart.conf.js` depending on which
code you want to debug (the former will process the "modules" folder while the later processes
the transpiler specs).
- You can also add `debugger;` statements in the specs (JavaScript). The execution will halt when
the developer tools are opened in the browser running Karma.
### Debug the tests
If you need to debug the tests:
- add a `debugger;` statement to the test you want to debug (or the source code),
- execute karma `$(npm bin)/gulp test.js`,
- press the top right "DEBUG" button,
- open the DevTools and press F5,
- the execution halts at the `debugger;` statement
**Note (WebStorm users)**:
1. Create a Karma run config from WebStorm.
2. Then in the "Run" menu, press "Debug 'karma-js.conf.js'", and WebStorm will stop in the generated
code on the `debugger;` statement.
3. You can then step into the code and add watches.
The `debugger;` statement is needed because WebStorm will stop in a transpiled file. Breakpoints in
the original source files are not supported at the moment.
The script will publish the build snapshot to a branch with the same name as your current branch,
and create it if it doesn't exist.

View File

@ -1,6 +1,6 @@
The MIT License
Copyright (c) 2014-2016 Google, Inc. http://angular.io
Copyright (c) 2014-2017 Google, Inc. http://angular.io
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -4,17 +4,18 @@
[![Issue Stats](http://issuestats.com/github/angular/angular/badge/pr?style=flat)](http://issuestats.com/github/angular/angular)
[![Issue Stats](http://issuestats.com/github/angular/angular/badge/issue?style=flat)](http://issuestats.com/github/angular/angular)
[![npm version](https://badge.fury.io/js/%40angular%2Fcore.svg)](https://badge.fury.io/js/%40angular%2Fcore)
[![Downloads](http://img.shields.io/npm/dm/angular2.svg)](https://npmjs.org/package/angular2)
[![Sauce Test Status](https://saucelabs.com/browser-matrix/angular2-ci.svg)](https://saucelabs.com/u/angular2-ci)
[![Sauce Test Status](https://saucelabs.com/browser-matrix/angular2-ci.svg)](https://saucelabs.com/u/angular2-ci)
*Safari (7+), iOS (7+), Edge (14) and IE mobile (11) are tested on [BrowserStack][browserstack].*
Angular
=========
Angular is a development platform for building mobile and desktop web applications. This is the
repository for [Angular 2][ng2], both the JavaScript (JS) and [Dart][dart] versions.
repository for [Angular 2][ng2] Typescript/JavaScript (JS).
Angular2 for [Dart][dart] can be found at [dart-lang/angular2][ng2dart].
Angular 2 is currently in **Release Candidate**.
## Quickstart
@ -26,11 +27,11 @@ Angular 2 is currently in **Release Candidate**.
Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our
guidelines for [contributing][contributing] and then check out one of our issues in the [hotlist: community-help](https://github.com/angular/angular/labels/hotlist%3A%20community-help).
[browserstack]: https://www.browserstack.com/
[contributing]: http://github.com/angular/angular/blob/master/CONTRIBUTING.md
[dart]: http://www.dartlang.org
[dartium]: http://www.dartlang.org/tools/dartium
[quickstart]: https://angular.io/docs/ts/latest/quickstart.html
[ng2]: http://angular.io
[ngDart]: http://angulardart.org
[ngJS]: http://angularjs.org
[ng2dart]: https://github.com/dart-lang/angular2

62
SAVED_REPLIES.md Normal file
View File

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

140
TOOLS.md
View File

@ -1,4 +1,140 @@
# Developer Tools for Angular 2
- [JavaScript](TOOLS_JS.md)
- [Dart](TOOLS_DART.md)
Here you will find a collection of tools and tips for keeping your application
perform well and contain fewer bugs.
## Angular debug tools in the dev console
Angular provides a set of debug tools that are accessible from any browser's
developer console. In Chrome the dev console can be accessed by pressing
Ctrl + Shift + j.
### Enabling debug tools
By default the debug tools are disabled. You can enable debug tools as follows:
```typescript
import {enableDebugTools} from '@angular/platform-browser';
bootstrap(Application).then((appRef) => {
enableDebugTools(appRef);
});
```
### Using debug tools
In the browser open the developer console (Ctrl + Shift + j in Chrome). The
top level object is called `ng` and contains more specific tools inside it.
Example:
```javascript
ng.profiler.timeChangeDetection();
```
## Performance
### Change detection profiler
If your application is janky (it misses frames) or is slow according to other
metrics it is important to find the root cause of the issue. Change detection
is a phase in Angular's lifecycle that detects changes in values that are
bound to UI, and if it finds a change it performs the corresponding UI update.
However, sometimes it is hard to tell if the slowness is due to the act of
computing the changes being slow, or due to the act of applying those changes
to the UI. For your application to be performant it is important that the
process of computing changes is very fast. For best results it should be under
3 milliseconds in order to leave room for the application logic, the UI updates
and browser's rendering pipeline to fit withing the 16 millisecond frame
(assuming the 60 FPS target frame rate).
Change detection profiler repeatedly performs change detection without invoking
any user actions, such as clicking buttons or entering text in input fields. It
then computes the average amount of time it took to perform a single cycle of
change detection in milliseconds and prints it to the console. This number
depends on the current state of the UI. You will likely see different numbers
as you go from one screen in your application to another.
#### Running the profiler
Enable debug tools (see above), then in the dev console enter the following:
```javascript
ng.profiler.timeChangeDetection();
```
The results will be printed to the console.
#### Recording CPU profile
Pass `{record: true}` an argument:
```javascript
ng.profiler.timeChangeDetection({record: true});
```
Then open the "Profiles" tab. You will see the recorded profile titled
"Change Detection". In Chrome, if you record the profile repeatedly, all the
profiles will be nested under "Change Detection".
#### Interpreting the numbers
In a properly-designed application repeated attempts to detect changes without
any user actions should result in no changes to be applied on the UI. It is
also desirable to have the cost of a user action be proportional to the amount
of UI changes required. For example, popping up a menu with 5 items should be
vastly faster than rendering a table of 500 rows and 10 columns. Therefore,
change detection with no UI updates should be as fast as possible. Ideally the
number printed by the profiler should be well below the length of a single
animation frame (16ms). A good rule of thumb is to keep it under 3ms.
#### Investigating slow change detection
So you found a screen in your application on which the profiler reports a very
high number (i.e. >3ms). This is where a recorded CPU profile can help. Enable
recording while profiling:
```javascript
ng.profiler.timeChangeDetection({record: true});
```
Then look for hot spots using
[Chrome CPU profiler](https://developer.chrome.com/devtools/docs/cpu-profiling).
#### Reducing change detection cost
There are many reasons for slow change detection. To gain intuition about
possible causes it would help to understand how change detection works. Such a
discussion is outside the scope of this document (TODO link to docs), but here
are some key concepts in brief.
By default Angular uses "dirty checking" mechanism for finding model changes.
This mechanism involves evaluating every bound expression that's active on the
UI. These usually include text interpolation via `{{expression}}` and property
bindings via `[prop]="expression"`. If any of the evaluated expressions are
costly to compute they could contribute to slow change detection. A good way to
speed things up is to use plain class fields in your expressions and avoid any
kinds of computation. Example:
```typescript
@Component({
template: '<button [enabled]="isEnabled">{{title}}</button>'
})
class FancyButton {
// GOOD: no computation, just return the value
isEnabled: boolean;
// BAD: computes the final value upon request
_title: String;
get title(): String { return this._title.trim().toUpperCase(); }
}
```
Most cases like these could be solved by precomputing the value and storing the
final value in a field.
Angular also supports a second type of change detection - the "push" model. In
this model Angular does not poll your component for changes. Instead, the
component "tells" Angular when it changes and only then does Angular perform
the update. This model is suitable in situations when your data model uses
observable or immutable objects (also a discussion for another time).

View File

@ -1,376 +0,0 @@
# Developer Tools for Dart
Use these tools and techniques to increase your app's performance
and reliability.
* [Angular debugging tools](#angular-debugging-tools)
* [Code size](#code-size)
* [Performance](#performance)
## Angular debugging tools
Starting with alpha.38, Angular provides a set of debugging tools
that are accessible from any browser's developer console.
In Chrome, you can get to the dev console by pressing
Ctrl + Shift + J (on Mac: Cmd + Opt + J).
### Enabling the debugging tools
By default the debugging tools are disabled.
Enable the debugging tools as follows:
```dart
import 'package:angular2/platform/browser.dart';
main() async {
var appRef = await bootstrap(Application);
enableDebugTools(appRef);
}
```
<!-- Change function name to enableDebuggingTools? -->
### Using the debugging tools
In the browser, open the dev console. The top-level object is called `ng` and
contains more specific tools inside it.
For example, to run the change detection profiler on your app:
```javascript
// In the dev console:
ng.profiler.timeChangeDetection();
```
The [Change detection profiler](#change-detection-profiler) section
has more details.
<!-- Point to API docs when they're published, if they're useful.
They should be under
http://www.dartdocs.org/documentation/angular2/latest
and/or
https://angular.io/docs/js/latest/api/. -->
## Code size
Code must be downloaded, parsed, and executed. Too much code can lead to
slow application start-up time, especially on slow networks and low-end devices.
The tools and techniques in this section can help you to identify
unnecessarily large code and to reduce code size.
### Finding contributors to code size
Options for investigating code size include the `--dump-info` dart2js option,
ng2soyc, `reflector.trackUsage()`, and code coverage information
from the Dart VM.
#### Use --dump-info
The `--dump-info` option of `dart2js` outputs information about what happened
during compilation. You can specify `--dump-info` in `pubspec.yaml`:
```yaml
transformers:
...
- $dart2js:
commandLineOptions:
- --dump-info
```
The [Dump Info Visualizer](https://github.com/dart-lang/dump-info-visualizer)
can help you analyze the output.
For more information, see the
[dart2js_info API reference](http://dart-lang.github.io/dart2js_info/doc/api/).
#### Use ng2soyc.dart
[ng2soyc](https://github.com/angular/ng2soyc.dart) is a utility for analyzing
code size contributors in Angular 2 applications. It groups code size by
library and, assuming your library names follow
[standard naming conventions](https://www.dartlang.org/articles/style-guide/#do-prefix-library-names-with-the-package-name-and-a-dot-separated-path)
(package.library.sublibrary...), gives the code size breakdown at
each level. To reduce noise in the output of very large apps, ng2soyc provides
an option to hide libraries that are too small, so you can focus on the biggest
contributors.
#### Find unused reflection data
Your app might have types that are annotated with `@Component` or `@Injectable`
but never used.
To find these unused types, use `reflector.trackUsage()` and then,
after exercising your app, `reflector.listUnusedKeys()`.
For example:
```
import 'package:angular2/src/core/reflection/reflection.dart';
...
main() async {
reflector.trackUsage();
await bootstrap(AppComponent);
print('Unused keys: ${reflector.listUnusedKeys()}');
}
```
When you run that code (in Dartium or another browser),
you'll see a list of types that Angular _can_ inject but hasn't needed to.
Consider removing those types or their `@Component`/`@Injectable` annotation
to decrease your app's code size.
Three conditions must be true for `listUnusedKeys()` to return helpful data:
1. The angular2 transformer must run on the app.
2. If you're running a JavaScript version of the app,
the app must not be minified, so that the names are readable.
3. You must exercise your app in as many ways as possible
before calling `listUnusedKeys()`.
Otherwise, you might get false positives:
keys that haven't been used only because you didn't exercise
the relevant feature of the app.
To run the angular2 transformer, first specify it in `pubspec.yaml`:
```
name: hello_world
...
transformers:
- angular2:
entry_points: web/main.dart
```
Then use pub to run the transformer. If you use `pub serve`,
it provides both Dart and unminified (by default) JavaScript versions.
If you want to serve actual files, then use `pub build` in debug mode
to generate Dart and unminified JavaScript files:
`pub build --mode=debug`.
The `reflector.trackUsage()` method makes Angular track the reflection
information used by the app. Reflection information (`ReflectionInfo`) is a data
structure that stores information that Angular uses for locating DI factories
and for generating change detectors and other code related to a
given type.
#### Use code coverage to find dead code
When running in Dartium (or in the Dart VM, in general) you can request code
coverage information from the VM. You can either use
[observatory](https://www.dartlang.org/tools/observatory/) or download
the coverage file and use your own tools to inspect it. Lines of code that are
not covered are top candidates for dead code.
Keep in mind, however, that uncovered code is not sufficient evidence of dead
code, only necessary evidence. It is perfectly possible that you simply didn't
exercise your application in a way that triggers the execution of uncovered
code. A common example is error handling code. Just because your testing never
encountered an error does not mean the error won't happen in production. You
therefore don't have to rush and remove all the `catch` blocks.
### Reducing code size
To reduce code size, you can disable reflection,
enable minification, and manually remove dead code.
You can also try less safe options such as
telling dart2js to trust type annotations.
#### Disable reflection
`dart:mirrors` allows discovering program metadata at runtime. However, this
means that `dart2js` needs to retain that metadata and thus increase the size
of resulting JS output. In practice, however, it is possible to extract most
metadata necessary for your metaprogramming tasks statically using a
transformer and `package:analyzer`, and act on it before compiling to JS.
#### Enable minification
Minification shortens all your `longMethodNames` into 2- or 3-letter long
symbols. `dart2js` ensures that this kind of renaming is done safely, without
breaking the functionality of your programs. You can enable it in `pubspec.yaml`
under `$dart2js` transformer:
```yaml
transformers:
...
- $dart2js:
minify: true
```
#### Manually remove dead code
`dart2js` comes with dead code elimination out-of-the-box. However, it may not
always be able to tell if a piece of code could be used. Consider the following
example:
```dart
/// This function decides which serialization format to use
void setupSerializers() {
if (server.doYouSupportProtocolBuffers()) {
useProtobufSerializers();
} else {
useJsonSerializers();
}
}
```
In this example the application asks the server what kind of serialization
format it uses and dynamically chooses one or the other. `dart2js` can't
tell whether the server responds with yes or no, so it must retain both
kinds of serializers. However, if you know that your server supports
protocol buffers, you can remove that `if` block entirely and default to
protocol buffers.
Code coverage (see above) is a good way to find dead code in your app.
#### Unsafe options
Dart also provides more aggressive optimization options. However, you have to
be careful when using them and as of today the benefits aren't that clear. If
your type annotations are inaccurate you may end up with non-Darty runtime
behavior, including the classic "undefined is not a function" tautology, as
well as the "keep on truckin'" behavior, e.g. `null + 1 == 1` and
`{} + [] == 0`.
`--trust-type-annotations` tells `dart2js` to trust that your type annotations
are correct. So if you have a function `foo(Bar bar)` the compiler can omit the
check that `bar` is truly `Bar` when calling methods on it.
`--trust-primitives` tells `dart2js` that primitive types, such as numbers and
booleans are never `null` when performing arithmetic, and that your program
does not run into range error when operating on lists, letting the compiler
remove some of the error checking code.
Specify these options in `pubspec.yaml`.
Example:
```yaml
transformers:
...
- $dart2js:
commandLineOptions:
- --trust-type-annotations
- --trust-primitives
```
## Performance
### Change detection profiler
If your application is janky (it misses frames) or is slow according to other
metrics, you need to find out why. This tool helps by measuring the average
speed of _change detection_, a phase in Angular's
lifecycle that detects changes in values that are bound to the UI.
Janky UI updates can result from slowness either in _computing_ the changes or
in _applying_ those changes to the UI.
For your app to be performant, the process of _computing_ changes must be very
fast—preferably **under 3 milliseconds**.
Fast change computation leaves room for
the application logic, UI updates, and browser rendering pipeline
to fit within a 16 ms frame (assuming a target frame rate of 60 FPS).
The change detection profiler repeatedly performs change detection
without invoking any user actions, such as clicking buttons or entering
text in input fields. It then computes the average amount of time
(in milliseconds) to perform a single cycle of change detection and
prints that to the console. This number depends on the current state of the UI. You are likely to see different numbers
as you go from one screen in your application to another.
#### Running the profiler
Before running the profiler, enable the debugging tools
and put the app into the state you want to measure:
1. If you haven't already done so,
[enable the debugging tools](#enabling-the-debugging-tools).
2. Navigate the app to a screen whose performance you want to profile.
3. Make sure the screen is in a state that you want to measure.
For example, you might want to profile the screen several times,
with different amounts and kinds of data.
To run the profiler, enter the following in the dev console:
```javascript
ng.profiler.timeChangeDetection();
```
The results are visible in the console.
#### Recording CPU profiles
To record a profile, pass `{record: true}` to `timeChangeDetection()`:
```javascript
ng.profiler.timeChangeDetection({record: true});
```
Then open the **Profiles** tab. The recorded profile has the title
**Change Detection**. In Chrome, if you record the profile repeatedly, all the
profiles are nested under Change Detection.
#### Interpreting the numbers
In a properly designed application, repeated attempts to detect changes without
any user actions result in no changes to the UI. It is
also desirable to have the cost of a user action be proportional to the amount
of UI changes required. For example, popping up a menu with 5 items should be
vastly faster than rendering a table of 500 rows and 10 columns. Therefore,
change detection with no UI updates should be as fast as possible.
#### Investigating slow change detection
So you found a screen in your application on which the profiler reports a very
high number (i.e. >3ms). This is where a recorded CPU profile can help. Enable
recording while profiling:
```javascript
ng.profiler.timeChangeDetection({record: true});
```
Then look for hot spots using
[Chrome CPU profiler](https://developer.chrome.com/devtools/docs/cpu-profiling).
#### Reducing change detection cost
There are many reasons for slow change detection. To gain intuition about
possible causes it helps to understand how change detection works. Such a
discussion is outside the scope of this document,
but here are some key concepts.
<!-- TODO: link to change detection docs -->
By default, Angular uses a _dirty checking_ mechanism to find model changes.
This mechanism involves evaluating every bound expression that's active on the
UI. These usually include text interpolation via `{{expression}}` and property
bindings via `[prop]="expression"`. If any of the evaluated expressions are
costly to compute, they might contribute to slow change detection. A good way to
speed things up is to use plain class fields in your expressions and avoid any
kind of computation. For example:
```dart
@View(
template: '<button [enabled]="isEnabled">{{title}}</button>'
)
class FancyButton {
// GOOD: no computation, just returns the value
bool isEnabled;
// BAD: computes the final value upon request
String _title;
String get title => _title.trim().toUpperCase();
}
```
Most cases like these can be solved by precomputing the value and storing the
final value in a field.
Angular also supports a second type of change detection: the _push_ model. In
this model, Angular does not poll your component for changes. Instead, the
component tells Angular when it changes, and only then does Angular perform
the update. This model is suitable in situations when your data model uses
observable or immutable objects.
<!-- TODO: link to discussion of push model -->

View File

@ -1,140 +0,0 @@
# Developer Tools for JavaScript
Here you will find a collection of tools and tips for keeping your application
perform well and contain fewer bugs.
## Angular debug tools in the dev console
Angular provides a set of debug tools that are accessible from any browser's
developer console. In Chrome the dev console can be accessed by pressing
Ctrl + Shift + j.
### Enabling debug tools
By default the debug tools are disabled. You can enable debug tools as follows:
```typescript
import {enableDebugTools} from 'angular2/platform/browser';
bootstrap(Application).then((appRef) => {
enableDebugTools(appRef);
});
```
### Using debug tools
In the browser open the developer console (Ctrl + Shift + j in Chrome). The
top level object is called `ng` and contains more specific tools inside it.
Example:
```javascript
ng.profiler.timeChangeDetection();
```
## Performance
### Change detection profiler
If your application is janky (it misses frames) or is slow according to other
metrics it is important to find the root cause of the issue. Change detection
is a phase in Angular's lifecycle that detects changes in values that are
bound to UI, and if it finds a change it performs the corresponding UI update.
However, sometimes it is hard to tell if the slowness is due to the act of
computing the changes being slow, or due to the act of applying those changes
to the UI. For your application to be performant it is important that the
process of computing changes is very fast. For best results it should be under
3 milliseconds in order to leave room for the application logic, the UI updates
and browser's rendering pipeline to fit withing the 16 millisecond frame
(assuming the 60 FPS target frame rate).
Change detection profiler repeatedly performs change detection without invoking
any user actions, such as clicking buttons or entering text in input fields. It
then computes the average amount of time it took to perform a single cycle of
change detection in milliseconds and prints it to the console. This number
depends on the current state of the UI. You will likely see different numbers
as you go from one screen in your application to another.
#### Running the profiler
Enable debug tools (see above), then in the dev console enter the following:
```javascript
ng.profiler.timeChangeDetection();
```
The results will be printed to the console.
#### Recording CPU profile
Pass `{record: true}` an argument:
```javascript
ng.profiler.timeChangeDetection({record: true});
```
Then open the "Profiles" tab. You will see the recorded profile titled
"Change Detection". In Chrome, if you record the profile repeatedly, all the
profiles will be nested under "Change Detection".
#### Interpreting the numbers
In a properly-designed application repeated attempts to detect changes without
any user actions should result in no changes to be applied on the UI. It is
also desirable to have the cost of a user action be proportional to the amount
of UI changes required. For example, popping up a menu with 5 items should be
vastly faster than rendering a table of 500 rows and 10 columns. Therefore,
change detection with no UI updates should be as fast as possible. Ideally the
number printed by the profiler should be well below the length of a single
animation frame (16ms). A good rule of thumb is to keep it under 3ms.
#### Investigating slow change detection
So you found a screen in your application on which the profiler reports a very
high number (i.e. >3ms). This is where a recorded CPU profile can help. Enable
recording while profiling:
```javascript
ng.profiler.timeChangeDetection({record: true});
```
Then look for hot spots using
[Chrome CPU profiler](https://developer.chrome.com/devtools/docs/cpu-profiling).
#### Reducing change detection cost
There are many reasons for slow change detection. To gain intuition about
possible causes it would help to understand how change detection works. Such a
discussion is outside the scope of this document (TODO link to docs), but here
are some key concepts in brief.
By default Angular uses "dirty checking" mechanism for finding model changes.
This mechanism involves evaluating every bound expression that's active on the
UI. These usually include text interpolation via `{{expression}}` and property
bindings via `[prop]="expression"`. If any of the evaluated expressions are
costly to compute they could contribute to slow change detection. A good way to
speed things up is to use plain class fields in your expressions and avoid any
kinds of computation. Example:
```typescript
@Component({
template: '<button [enabled]="isEnabled">{{title}}</button>'
})
class FancyButton {
// GOOD: no computation, just return the value
isEnabled: boolean;
// BAD: computes the final value upon request
_title: String;
get title(): String { return this._title.trim().toUpperCase(); }
}
```
Most cases like these could be solved by precomputing the value and storing the
final value in a field.
Angular also supports a second type of change detection - the "push" model. In
this model Angular does not poll your component for changes. Instead, the
component "tells" Angular when it changes and only then does Angular perform
the update. This model is suitable in situations when your data model uses
observable or immutable objects (also a discussion for another time).

View File

@ -1,31 +1,105 @@
# Triage Process and Github Labels for Angular 2
This document describes how the Angular team uses labels and milestones to triage issues on github.
This document describes how the Angular team uses labels and milestones
to triage issues on github. The basic idea of the process is that
caretaker only assigns a component and type (bug, feature) label. The
owner of the component than is in full control of how the issues should
be triaged further.
# Issues and PRs
## Triaged vs Untriaged Issues
Once this process is implemented and in use, we will revisit it to see
if further labeling is needed.
Every triaged issue must have four attributes assigned to it:
## Components
* `priority` -- P0 through P4. P0 issues are "drop everything and do this now". P4 are nice to have.
* `component` -- Which area of Angular knowledge this relates to.
* `effort` -- Rough assessment of how much work this issue is. E.g. `effort: easy` means
"probably a few hours of work".
* `type` -- Whether this issue is a bug, feature, or other kind of task.
A caretaker should be able to determine which component the issue
belongs to. The components have a clear piece of source code associated
with it.
Untriaged issues are any issues in the queue that don't yet have these four attributes.
* `comp: animations`: `@matsko`
* `comp: benchpress`: `@tbosch`
* `comp: build & ci`: `@IgorMinar` -- All build and CI scripts
* `comp: common`: `@mhevery` -- This includes core components / pipes.
* `comp: core & compiler`: `@tbosch` -- Because core and compiler are very
intertwined, we will be treating them as one.
* `comp: forms`: `@kara`
* `comp: http`: `@jeffbcross`
* `comp: i18n`: `@vicb`
* `comp: language service`: `@chuckjaz`
* `comp: metadata-extractor`: `@chuckjaz`
* `comp: router`: `@vicb`
* `comp: testing`: `@juliemr`
* `comp: upgrade`: `@mhevery`
* `comp: web-worker`: `@vicb`
* `comp: zones`: `@mhevery`
You can view a report of untriaged issues here, in our
[Angular Triage Dashboard](http://mhevery.github.io/github_issues/).
There are few components which are cross-cutting. They don't have
a clear location in the source tree. We will treat them as a component
even thought no specific source tree is associated with them.
* `comp: docs`: `@naomiblack`
* `comp: packaging`: `@IgorMinar`
* `comp: performance`: `@tbosch`
* `comp: security`: `@IgorMinar`
## Type
What kind of problem is this?
* `type: RFC / discussion / question`
* `type: bug`
* `type: chore`
* `type: feature`
* `type: performance`
* `type: refactor`
## Caretaker Triage Process
It is the caretaker's responsibility to assign `comp: *` to each new
issue as they come in. The reason why we limit the responsibility of the
caretaker to this one label is that it is likely that without domain
knowledge the caretaker could mislabel issues or lack knowledge of
duplicate issues.
## Component's owner Triage Process
At this point we are leaving each component owner to determine their own
process for their component.
It will be up to the component owner to determine the order in which the
issues within the component will be resolved.
Several owners have adopted the issue categorization based on
[user pain](http://www.lostgarden.com/2008/05/improving-bug-triage-with-user-pain.html)
used by Angular 1. In this system every issue is assigned frequency and
severity based on which the total user pain score is calculated.
Following is the definition of various frequency and severity levels:
1. `freq(score): *` How often does this issue come up? How many developers does this affect?
* low (1) - obscure issue affecting a handful of developers
* moderate (2) - impacts auxiliary usage patterns, only small number of applications are affected
* high (3) - impacts primary usage patterns, affecting most Angular apps
* critical (4) - impacts all Angular apps
1. `severity(score): *` - How bad is the issue?
* inconvenience (1) - causes ugly/boilerplate code in apps
* confusing (2) - unexpected or inconsistent behavior; hard-to-debug
* broken expected use (3) - it's hard or impossible for a developer using Angular to accomplish something that Angular should be able to do
* memory leak (4)
* regression (5) - functionality that used to work no longer works in a new release due to an unintentional change
* security issue (6)
These criteria are then used to calculate a "user pain" score as follows:
`pain = severity × frequency`
Issues should also have a clear action to complete that can be addressed or resolved within the
scope of Angular 2. We'll close issues that don't meet these criteria.
### Assigning Issues to Milestones
Any issue that is being worked on must have:
* An `assignee`: The person doing the work.
* An `Assignee`: The person doing the work.
* A `Milestone`: When we expect to complete this work.
We aim to only have at most three milestones open at a time:
@ -37,7 +111,10 @@ We aim to only have at most three milestones open at a time:
The [backlog](https://github.com/angular/angular/issues?q=is%3Aopen+is%3Aissue+no%3Amilestone)
consists of all issues that have been triaged but do not have an assignee or milestone.
## Triaged vs Untriaged PRs
## Triaged vs Untrained PRs
PRs should also be label with a `comp: *` so that it is clear which
primary area the PR effects.
Because of the cumulative pain associated with rebasing PRs, we triage PRs daily, and
closing or reviewing PRs is a top priority ahead of other ongoing work.
@ -63,90 +140,6 @@ uncontroversial change.
PRs do not need to be assigned to milestones, unless a milestone release should be held for that
PR to land.
Victor (`vsavkin`) and Tobias (`tbosch`) are owners of the PR queue. Here is a list of [current
untriaged PRs](https://github.com/angular/angular/pulls?utf8=%E2%9C%93&q=is%3Aopen+no%3Amilestone+is%3Apr+-label%3A%22pr_action%3A+cleanup%22+-label%3A%22pr_action%3A+merge%22+-label%3A%22pr_action%3A+review%22+-label%3A%22pr_action%3A+discuss%22+-label%3A%22pr_state%3A+blocked%22+-label%3A%22pr_state%3A+WIP%22+).
# Prioritization of Work
What should you be working on?
1. Any PRs that are assigned to you that don't have `pr_state: WIP` or `pr_state: blocked`
1. Any issues that are assigned to you in the lowest-numbered Milestone
1. Any issues that are assigned to you in any Milestone
If there are no issues assigned to you in any Milestone, pick an issue, self-assign it, and add
it to the most appropriate Milestone based on effort.
Here are some suggestions for what to work on next:
* Filter for issues in a component that you are knowledgeable about, and pick something that has a
high priority.
* Filter for any small effort task that has the special `cust: GT` or `cust:Ionic` tags,
and priority > P3.
* Add a new task that's really important, add `component`, `priority`, `effort`, `type` and
assign it to yourself and the most appropriate milestone.
# Labels Used in Triage
## Priority
How urgent is this issue? We use priority to determine what should be worked on in each new
milestone.
* `P0: critical` -- drop everything to work on this
* `P1: urgent` -- resolve quickly in the current milestone. people are blocked
* `P2: required` -- needed for development but not urgent yet. workaround exists, or e.g. new API
* `P3: important` -- must complete before Angular 2 is ready for release
* `P4: nice to have` -- a good idea, but maybe not until after release
## Effort
Rough, non-binding estimate of how much work this issue represents. Please change this assessment
for anything you're working on to better reflect reality.
* `effort: easy` -- straightforward issue that can be resolved in a few hours, e.g. < 1 day of work.
* `effort: medium` -- issue that will be a few days of work. Can be completed within a single
milestone.
* `effort: tough` -- issue that will likely take more than 1 milestone to complete.
<!-- We don't like these label names as
they're not absolute (what is one developer-hour, really?) but decided it wasn't worth arguing
over terms. -->
## Component
Which area of Angular knowledge is this issue most closely related to? Helpful when deciding what
to work on next.
* `comp: benchpress` -- benchmarks and performance testing &rarr; *tbosch*, *crossj*
* `comp: build/dev-productivity` -- build process, e.g. CLI and related tasks &rarr; *iminar*, *caitp*
* `comp: build/pipeline` -- build pipeline, e.g. ts2dart &rarr; *mprobst*, *alexeagle*
* `comp: core` -- general core Angular issues, not related to a sub-category (see below) &rarr;
*mhevery*
* `comp: core/animations` -- animations framework &rarr; *matsko*
* `comp: core/change_detection` -- change detection &rarr; *vsavkin*
* `comp: core/di` -- dependency injection &rarr; *vicb*, *rkirov*
* `comp: core/directives` -- directives
* `comp: core/forms` -- forms &rarr; *vsavkin*
* `comp: core/pipes` -- pipes
* `comp: core/view` -- runtime processing of the `View`s
* `comp: core/view/compiler` -- static analysis of the templates which generate `ProtoView`s.
* `comp: core/testbed` -- e2e tests and support for them
* `comp: core/webworker` -- core web worker infrastructure
* `comp: dart-transformer` -- Dart transforms &rarr; *kegluneq*, *jakemac*
* `comp: data-access` -- &rarr; *jeffbcross*
* `comp: docs` -- API docs and doc generation &rarr; *naomiblack*, *petebacondarwin*
* `comp: material-components` -- Angular Material components built in Angular 2 &rarr; *jelbourn*
* `comp: router` -- Component Router &rarr; *btford*, *igorminar*, *matsko*
* `comp: wrenchjs`
## Type
What kind of problem is this?
* `type RFC / discussion / question`
* `type bug`
* `type chore`
* `type feature`
* `type performance`
* `type refactor`
## Special Labels
@ -160,9 +153,6 @@ More active discussion is needed before the issue can be worked on further. Typi
Managed by googlebot. Indicates whether a PR has a CLA on file for its author(s). Only issues with
`cla:yes` should be merged into master.
### cust
This is an issue causing user pain for early adopter customers `cust: GT` or `cust: Ionic`.
### WORKS_AS_INTENDED
Only used on closed issues, to indicate to the reporter why we closed it.

View File

@ -1,6 +1,6 @@
{
"name": "angular2",
"dependencies": {
"polymer": "Polymer/polymer"
"polymer": "Polymer/polymer#^1.6.0"
}
}

View File

@ -1,220 +1,102 @@
// Unique place to configure the browsers which are used in the different CI jobs in Sauce Labs (SL) and BrowserStack (BS).
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
// Unique place to configure the browsers which are used in the different CI jobs in Sauce Labs (SL)
// and BrowserStack (BS).
// If the target is set to null, then the browser is not run anywhere during CI.
// If a category becomes empty (e.g. BS and required), then the corresponding job must be commented out in Travis configuration.
// If a category becomes empty (e.g. BS and required), then the corresponding job must be commented
// out in Travis configuration.
var CIconfiguration = {
'Chrome': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
'Firefox': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
'Chrome': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
'Firefox': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
// FirefoxBeta and ChromeBeta should be target:'BS' or target:'SL', and required:true
// Currently deactivated due to https://github.com/angular/angular/issues/7560
'ChromeBeta': { unitTest: {target: null, required: true}, e2e: {target: null, required: false}},
'FirefoxBeta': { unitTest: {target: null, required: false}, e2e: {target: null, required: false}},
'ChromeDev': { unitTest: {target: null, required: true}, e2e: {target: null, required: true}},
'FirefoxDev': { unitTest: {target: null, required: true}, e2e: {target: null, required: true}},
'IE9': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
'IE10': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
'IE11': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
'Edge': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
'Android4.1': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
'Android4.2': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
'Android4.3': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
'Android4.4': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
'Android5': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
'Safari7': { unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
'Safari8': { unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
'Safari9': { unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
'iOS7': { unitTest: {target: 'BS', required: true}, e2e: {target: null, required: true}},
'iOS8': { unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
'iOS9': { unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
'WindowsPhone': { unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}}
'ChromeBeta': {unitTest: {target: null, required: true}, e2e: {target: null, required: false}},
'FirefoxBeta': {unitTest: {target: null, required: false}, e2e: {target: null, required: false}},
'ChromeDev': {unitTest: {target: null, required: true}, e2e: {target: null, required: true}},
'FirefoxDev': {unitTest: {target: null, required: true}, e2e: {target: null, required: true}},
'IE9': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
'IE10': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
'IE11': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
'Edge': {unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
'Android4.1': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
'Android4.2': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
'Android4.3': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
'Android4.4': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
'Android5': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
'Safari7': {unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
'Safari8': {unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
'Safari9': {unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
'Safari10': {unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
'iOS7': {unitTest: {target: 'BS', required: true}, e2e: {target: null, required: true}},
'iOS8': {unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
'iOS9': {unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
'iOS10': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
'WindowsPhone': {unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}}
};
var customLaunchers = {
'DartiumWithWebPlatform': {
base: 'Dartium',
flags: ['--enable-experimental-web-platform-features'] },
'ChromeNoSandbox': {
base: 'Chrome',
flags: ['--no-sandbox'] },
'SL_CHROME': {
base: 'SauceLabs',
browserName: 'chrome',
version: '50'
},
'SL_CHROMEBETA': {
base: 'SauceLabs',
browserName: 'chrome',
version: 'beta'
},
'SL_CHROMEDEV': {
base: 'SauceLabs',
browserName: 'chrome',
version: 'dev'
},
'SL_FIREFOX': {
base: 'SauceLabs',
browserName: 'firefox',
version: '45'
},
'SL_FIREFOXBETA': {
base: 'SauceLabs',
browserName: 'firefox',
version: 'beta'
},
'SL_FIREFOXDEV': {
base: 'SauceLabs',
browserName: 'firefox',
version: 'dev'
},
'SL_SAFARI7': {
base: 'SauceLabs',
browserName: 'safari',
platform: 'OS X 10.9',
version: '7'
},
'SL_SAFARI8': {
base: 'SauceLabs',
browserName: 'safari',
platform: 'OS X 10.10',
version: '8'
},
'SL_SAFARI9': {
base: 'SauceLabs',
browserName: 'safari',
platform: 'OS X 10.11',
version: '9.0'
},
'SL_IOS7': {
base: 'SauceLabs',
browserName: 'iphone',
platform: 'OS X 10.10',
version: '7.1'
},
'SL_IOS8': {
base: 'SauceLabs',
browserName: 'iphone',
platform: 'OS X 10.10',
version: '8.4'
},
'SL_IOS9': {
base: 'SauceLabs',
browserName: 'iphone',
platform: 'OS X 10.10',
version: '9.1'
},
'SL_IE9': {
base: 'SauceLabs',
browserName: 'internet explorer',
platform: 'Windows 2008',
version: '9'
},
'DartiumWithWebPlatform':
{base: 'Dartium', flags: ['--enable-experimental-web-platform-features']},
'ChromeNoSandbox': {base: 'Chrome', flags: ['--no-sandbox']},
'SL_CHROME': {base: 'SauceLabs', browserName: 'chrome', version: '54'},
'SL_CHROMEBETA': {base: 'SauceLabs', browserName: 'chrome', version: 'beta'},
'SL_CHROMEDEV': {base: 'SauceLabs', browserName: 'chrome', version: 'dev'},
'SL_FIREFOX': {base: 'SauceLabs', browserName: 'firefox', version: '50'},
'SL_FIREFOXBETA': {base: 'SauceLabs', browserName: 'firefox', version: 'beta'},
'SL_FIREFOXDEV': {base: 'SauceLabs', browserName: 'firefox', version: 'dev'},
'SL_SAFARI7': {base: 'SauceLabs', browserName: 'safari', platform: 'OS X 10.9', version: '7.0'},
'SL_SAFARI8': {base: 'SauceLabs', browserName: 'safari', platform: 'OS X 10.10', version: '8.0'},
'SL_SAFARI9': {base: 'SauceLabs', browserName: 'safari', platform: 'OS X 10.11', version: '9.0'},
'SL_SAFARI10':
{base: 'SauceLabs', browserName: 'safari', platform: 'OS X 10.12', version: '10.0'},
'SL_IOS7': {base: 'SauceLabs', browserName: 'iphone', platform: 'OS X 10.10', version: '7.1'},
'SL_IOS8': {base: 'SauceLabs', browserName: 'iphone', platform: 'OS X 10.10', version: '8.4'},
'SL_IOS9': {base: 'SauceLabs', browserName: 'iphone', platform: 'OS X 10.10', version: '9.3'},
'SL_IOS10': {base: 'SauceLabs', browserName: 'iphone', platform: 'OS X 10.10', version: '10.0'},
'SL_IE9':
{base: 'SauceLabs', browserName: 'internet explorer', platform: 'Windows 2008', version: '9'},
'SL_IE10': {
base: 'SauceLabs',
browserName: 'internet explorer',
platform: 'Windows 2012',
version: '10'
},
'SL_IE11': {
base: 'SauceLabs',
browserName: 'internet explorer',
platform: 'Windows 8.1',
version: '11'
},
'SL_IE11':
{base: 'SauceLabs', browserName: 'internet explorer', platform: 'Windows 8.1', version: '11'},
'SL_EDGE': {
base: 'SauceLabs',
browserName: 'MicrosoftEdge',
platform: 'Windows 10',
version: '13.10586'
},
'SL_ANDROID4.1': {
base: 'SauceLabs',
browserName: 'android',
platform: 'Linux',
version: '4.1'
},
'SL_ANDROID4.2': {
base: 'SauceLabs',
browserName: 'android',
platform: 'Linux',
version: '4.2'
},
'SL_ANDROID4.3': {
base: 'SauceLabs',
browserName: 'android',
platform: 'Linux',
version: '4.3'
},
'SL_ANDROID4.4': {
base: 'SauceLabs',
browserName: 'android',
platform: 'Linux',
version: '4.4'
},
'SL_ANDROID5': {
base: 'SauceLabs',
browserName: 'android',
platform: 'Linux',
version: '5.1'
},
'SL_ANDROID4.1': {base: 'SauceLabs', browserName: 'android', platform: 'Linux', version: '4.1'},
'SL_ANDROID4.2': {base: 'SauceLabs', browserName: 'android', platform: 'Linux', version: '4.2'},
'SL_ANDROID4.3': {base: 'SauceLabs', browserName: 'android', platform: 'Linux', version: '4.3'},
'SL_ANDROID4.4': {base: 'SauceLabs', browserName: 'android', platform: 'Linux', version: '4.4'},
'SL_ANDROID5': {base: 'SauceLabs', browserName: 'android', platform: 'Linux', version: '5.1'},
'BS_CHROME': {
base: 'BrowserStack',
browser: 'chrome',
os: 'OS X',
os_version: 'Yosemite'
},
'BS_FIREFOX': {
base: 'BrowserStack',
browser: 'firefox',
os: 'Windows',
os_version: '10'
},
'BS_SAFARI7': {
base: 'BrowserStack',
browser: 'safari',
os: 'OS X',
os_version: 'Mavericks'
},
'BS_SAFARI8': {
base: 'BrowserStack',
browser: 'safari',
os: 'OS X',
os_version: 'Yosemite'
},
'BS_SAFARI9': {
base: 'BrowserStack',
browser: 'safari',
os: 'OS X',
os_version: 'El Capitan'
},
'BS_IOS7': {
base: 'BrowserStack',
device: 'iPhone 5S',
os: 'ios',
os_version: '7.0'
},
'BS_IOS8': {
base: 'BrowserStack',
device: 'iPhone 6',
os: 'ios',
os_version: '8.3'
},
'BS_IOS9': {
base: 'BrowserStack',
device: 'iPhone 6S',
os: 'ios',
os_version: '9.0'
},
'BS_IE9': {
base: 'BrowserStack',
browser: 'ie',
browser_version: '9.0',
os: 'Windows',
os_version: '7'
},
'BS_CHROME': {base: 'BrowserStack', browser: 'chrome', os: 'OS X', os_version: 'Yosemite'},
'BS_FIREFOX': {base: 'BrowserStack', browser: 'firefox', os: 'Windows', os_version: '10'},
'BS_SAFARI7': {base: 'BrowserStack', browser: 'safari', os: 'OS X', os_version: 'Mavericks'},
'BS_SAFARI8': {base: 'BrowserStack', browser: 'safari', os: 'OS X', os_version: 'Yosemite'},
'BS_SAFARI9': {base: 'BrowserStack', browser: 'safari', os: 'OS X', os_version: 'El Capitan'},
'BS_SAFARI10': {base: 'BrowserStack', browser: 'safari', os: 'OS X', os_version: 'Sierra'},
'BS_IOS7': {base: 'BrowserStack', device: 'iPhone 5S', os: 'ios', os_version: '7.0'},
'BS_IOS8': {base: 'BrowserStack', device: 'iPhone 6', os: 'ios', os_version: '8.3'},
'BS_IOS9': {base: 'BrowserStack', device: 'iPhone 6S', os: 'ios', os_version: '9.1'},
'BS_IOS10': {base: 'BrowserStack', device: 'iPhone SE', os: 'ios', os_version: '10.0'},
'BS_IE9':
{base: 'BrowserStack', browser: 'ie', browser_version: '9.0', os: 'Windows', os_version: '7'},
'BS_IE10': {
base: 'BrowserStack',
browser: 'ie',
browser_version: '10.0',
browser_version: '10.1',
os: 'Windows',
os_version: '8'
},
@ -225,58 +107,35 @@ var customLaunchers = {
os: 'Windows',
os_version: '10'
},
'BS_EDGE': {
base: 'BrowserStack',
browser: 'edge',
os: 'Windows',
os_version: '10'
},
'BS_WINDOWSPHONE' : {
base: 'BrowserStack',
device: 'Nokia Lumia 930',
os: 'winphone',
os_version: '8.1'
},
'BS_ANDROID5': {
base: 'BrowserStack',
device: 'Google Nexus 5',
os: 'android',
os_version: '5.0'
},
'BS_ANDROID4.4': {
base: 'BrowserStack',
device: 'HTC One M8',
os: 'android',
os_version: '4.4'
},
'BS_ANDROID4.3': {
base: 'BrowserStack',
device: 'Samsung Galaxy S4',
os: 'android',
os_version: '4.3'
},
'BS_ANDROID4.2': {
base: 'BrowserStack',
device: 'Google Nexus 4',
os: 'android',
os_version: '4.2'
},
'BS_ANDROID4.1': {
base: 'BrowserStack',
device: 'Google Nexus 7',
os: 'android',
os_version: '4.1'
}
'BS_EDGE': {base: 'BrowserStack', browser: 'edge', os: 'Windows', os_version: '10'},
'BS_WINDOWSPHONE':
{base: 'BrowserStack', device: 'Nokia Lumia 930', os: 'winphone', os_version: '8.1'},
'BS_ANDROID5': {base: 'BrowserStack', device: 'Google Nexus 5', os: 'android', os_version: '5.0'},
'BS_ANDROID4.4': {base: 'BrowserStack', device: 'HTC One M8', os: 'android', os_version: '4.4'},
'BS_ANDROID4.3':
{base: 'BrowserStack', device: 'Samsung Galaxy S4', os: 'android', os_version: '4.3'},
'BS_ANDROID4.2':
{base: 'BrowserStack', device: 'Google Nexus 4', os: 'android', os_version: '4.2'},
'BS_ANDROID4.1':
{base: 'BrowserStack', device: 'Google Nexus 7', os: 'android', os_version: '4.1'}
};
var sauceAliases = {
'ALL': Object.keys(customLaunchers).filter(function(item) {return customLaunchers[item].base == 'SauceLabs';}),
'DESKTOP': ['SL_CHROME', 'SL_FIREFOX', 'SL_IE9', 'SL_IE10', 'SL_IE11', 'SL_EDGE', 'SL_SAFARI7', 'SL_SAFARI8', 'SL_SAFARI9'],
'MOBILE': ['SL_ANDROID4.1', 'SL_ANDROID4.2', 'SL_ANDROID4.3', 'SL_ANDROID4.4', 'SL_ANDROID5', 'SL_IOS7', 'SL_IOS8', 'SL_IOS9'],
'ALL': Object.keys(customLaunchers).filter(function(item) {
return customLaunchers[item].base == 'SauceLabs';
}),
'DESKTOP': [
'SL_CHROME', 'SL_FIREFOX', 'SL_IE9', 'SL_IE10', 'SL_IE11', 'SL_EDGE', 'SL_SAFARI7',
'SL_SAFARI8', 'SL_SAFARI9', 'SL_SAFARI10'
],
'MOBILE': [
'SL_ANDROID4.1', 'SL_ANDROID4.2', 'SL_ANDROID4.3', 'SL_ANDROID4.4', 'SL_ANDROID5', 'SL_IOS7',
'SL_IOS8', 'SL_IOS9', 'SL_IOS10'
],
'ANDROID': ['SL_ANDROID4.1', 'SL_ANDROID4.2', 'SL_ANDROID4.3', 'SL_ANDROID4.4', 'SL_ANDROID5'],
'IE': ['SL_IE9', 'SL_IE10', 'SL_IE11'],
'IOS': ['SL_IOS7', 'SL_IOS8', 'SL_IOS9'],
'SAFARI': ['SL_SAFARI7', 'SL_SAFARI8', 'SL_SAFARI9'],
'IOS': ['SL_IOS7', 'SL_IOS8', 'SL_IOS9', 'SL_IOS10'],
'SAFARI': ['SL_SAFARI7', 'SL_SAFARI8', 'SL_SAFARI9', 'SL_SAFARI10'],
'BETA': ['SL_CHROMEBETA', 'SL_FIREFOXBETA'],
'DEV': ['SL_CHROMEDEV', 'SL_FIREFOXDEV'],
'CI_REQUIRED': buildConfiguration('unitTest', 'SL', true),
@ -284,13 +143,20 @@ var sauceAliases = {
};
var browserstackAliases = {
'ALL': Object.keys(customLaunchers).filter(function(item) {return customLaunchers[item].base == 'BrowserStack';}),
'DESKTOP': ['BS_CHROME', 'BS_FIREFOX', 'BS_IE9', 'BS_IE10', 'BS_IE11', 'BS_EDGE', 'BS_SAFARI7', 'BS_SAFARI8', 'BS_SAFARI9'],
'MOBILE': ['BS_ANDROID4.3', 'BS_ANDROID4.4', 'BS_IOS7', 'BS_IOS8', 'BS_IOS9', 'BS_WINDOWSPHONE'],
'ALL': Object.keys(customLaunchers).filter(function(item) {
return customLaunchers[item].base == 'BrowserStack';
}),
'DESKTOP': [
'BS_CHROME', 'BS_FIREFOX', 'BS_IE9', 'BS_IE10', 'BS_IE11', 'BS_EDGE', 'BS_SAFARI7',
'BS_SAFARI8', 'BS_SAFARI9', 'BS_SAFARI10'
],
'MOBILE': [
'BS_ANDROID4.3', 'BS_ANDROID4.4', 'BS_IOS7', 'BS_IOS8', 'BS_IOS9', 'BS_IOS10', 'BS_WINDOWSPHONE'
],
'ANDROID': ['BS_ANDROID4.3', 'BS_ANDROID4.4'],
'IE': ['BS_IE9', 'BS_IE10', 'BS_IE11'],
'IOS': ['BS_IOS7', 'BS_IOS8', 'BS_IOS9'],
'SAFARI': ['BS_SAFARI7', 'BS_SAFARI8', 'BS_SAFARI9'],
'IOS': ['BS_IOS7', 'BS_IOS8', 'BS_IOS9', 'BS_IOS10'],
'SAFARI': ['BS_SAFARI7', 'BS_SAFARI8', 'BS_SAFARI9', 'BS_SAFARI10'],
'CI_REQUIRED': buildConfiguration('unitTest', 'BS', true),
'CI_OPTIONAL': buildConfiguration('unitTest', 'BS', false)
};
@ -303,11 +169,9 @@ module.exports = {
function buildConfiguration(type, target, required) {
return Object.keys(CIconfiguration)
.filter((item) => {
var conf = CIconfiguration[item][type];
return conf.required === required && conf.target === target;
})
.map((item) => {
return target + '_' + item.toUpperCase();
});
.filter((item) => {
var conf = CIconfiguration[item][type];
return conf.required === required && conf.target === target;
})
.map((item) => target + '_' + item.toUpperCase());
}

273
build.sh
View File

@ -4,115 +4,234 @@ set -e -o pipefail
cd `dirname $0`
PACKAGES=(core
compiler
common
forms
platform-browser
platform-browser-dynamic
platform-server
platform-webworker
platform-webworker-dynamic
http
upgrade
router
compiler-cli
language-service
benchpress)
BUILD_ALL=true
BUNDLE=true
VERSION_PREFIX=$(node -p "require('./package.json').version")
VERSION_SUFFIX="-$(git log --oneline -1 | awk '{print $1}')"
ROUTER_VERSION_PREFIX=$(node -p "require('./package.json').version.replace(/^2/, '3')")
REMOVE_BENCHPRESS=false
for ARG in "$@"; do
case "$ARG" in
--packages=*)
PACKAGES_STR=${ARG#--packages=}
PACKAGES=( ${PACKAGES_STR//,/ } )
BUILD_ALL=false
;;
--bundle=*)
BUNDLE=( "${ARG#--bundle=}" )
;;
--publish)
VERSION_SUFFIX=""
REMOVE_BENCHPRESS=true
;;
*)
echo "Unknown option $ARG."
exit 1
;;
esac
done
VERSION="${VERSION_PREFIX}${VERSION_SUFFIX}"
ROUTER_VERSION="${ROUTER_VERSION_PREFIX}${VERSION_SUFFIX}"
echo "====== BUILDING: Version ${VERSION} (Router ${ROUTER_VERSION})"
export NODE_PATH=${NODE_PATH}:$(pwd)/dist/all:$(pwd)/dist/tools
rm -rf ./dist/all/
mkdir -p ./dist/all/
TSC="node --max-old-space-size=3000 dist/tools/@angular/tsc-wrapped/src/main"
UGLIFYJS=`pwd`/node_modules/.bin/uglifyjs
TSCONFIG=./tools/tsconfig.json
echo "====== (all)COMPILING: \$(npm bin)/tsc -p ${TSCONFIG} ====="
echo "====== (tools)COMPILING: \$(npm bin)/tsc -p ${TSCONFIG} ====="
rm -rf ./dist/tools/
mkdir -p ./dist/tools/
$(npm bin)/tsc -p ${TSCONFIG}
cp ./tools/@angular/tsc-wrapped/package.json ./dist/tools/@angular/tsc-wrapped
echo "====== Copying files needed for e2e tests ====="
cp -r ./modules/playground ./dist/all/
cp -r ./modules/playground/favicon.ico ./dist/
#rsync -aP ./modules/playground/* ./dist/all/playground/
mkdir ./dist/all/playground/vendor
cd ./dist/all/playground/vendor
ln -s ../../../../node_modules/es6-shim/es6-shim.js .
ln -s ../../../../node_modules/zone.js/dist/zone.js .
ln -s ../../../../node_modules/zone.js/dist/long-stack-trace-zone.js .
ln -s ../../../../node_modules/systemjs/dist/system.src.js .
ln -s ../../../../node_modules/base64-js/lib/b64.js .
ln -s ../../../../node_modules/reflect-metadata/Reflect.js .
ln -s ../../../../node_modules/rxjs .
ln -s ../../../../node_modules/angular/angular.js .
cd -
if [[ ${BUILD_ALL} == true ]]; then
rm -rf ./dist/all/
mkdir -p ./dist/all/
echo "====== Copying files needed for e2e tests ====="
cp -r ./modules/playground ./dist/all/
cp -r ./modules/playground/favicon.ico ./dist/
#rsync -aP ./modules/playground/* ./dist/all/playground/
mkdir ./dist/all/playground/vendor
cd ./dist/all/playground/vendor
ln -s ../../../../node_modules/core-js/client/core.js .
ln -s ../../../../node_modules/zone.js/dist/zone.js .
ln -s ../../../../node_modules/zone.js/dist/long-stack-trace-zone.js .
ln -s ../../../../node_modules/systemjs/dist/system.src.js .
ln -s ../../../../node_modules/base64-js .
ln -s ../../../../node_modules/reflect-metadata/Reflect.js .
ln -s ../../../../node_modules/rxjs .
ln -s ../../../../node_modules/angular/angular.js .
ln -s ../../../../node_modules/hammerjs/hammer.js .
cd -
TSCONFIG=./modules/tsconfig.json
echo "====== (all)COMPILING: \$(npm bin)/tsc -p ${TSCONFIG} ====="
# compile ts code
TSC="node dist/tools/@angular/tsc-wrapped/src/main"
$TSC -p modules/tsconfig.json
echo "====== Copying files needed for benchmarks ====="
cp -r ./modules/benchmarks ./dist/all/
cp -r ./modules/benchmarks/favicon.ico ./dist/
mkdir ./dist/all/benchmarks/vendor
cd ./dist/all/benchmarks/vendor
ln -s ../../../../node_modules/core-js/client/core.js .
ln -s ../../../../node_modules/zone.js/dist/zone.js .
ln -s ../../../../node_modules/zone.js/dist/long-stack-trace-zone.js .
ln -s ../../../../node_modules/systemjs/dist/system.src.js .
ln -s ../../../../node_modules/reflect-metadata/Reflect.js .
ln -s ../../../../node_modules/rxjs .
ln -s ../../../../node_modules/angular/angular.js .
ln -s ../../../../bower_components/polymer .
ln -s ../../../../node_modules/incremental-dom/dist/incremental-dom-cjs.js
cd -
rm -rf ./dist/packages-dist
TSCONFIG=./modules/tsconfig.json
echo "====== (all)COMPILING: \$(npm bin)/tsc -p ${TSCONFIG} ====="
# compile ts code
$TSC -p modules/tsconfig.json
for PACKAGE in \
core \
compiler \
common \
forms \
platform-browser \
platform-browser-dynamic \
platform-server \
http \
router \
router-deprecated \
upgrade \
compiler-cli
rm -rf ./dist/packages-dist
fi
for PACKAGE in ${PACKAGES[@]}
do
SRCDIR=./modules/@angular/${PACKAGE}
DESTDIR=./dist/packages-dist/${PACKAGE}
UMD_ES6_PATH=${DESTDIR}/esm/${PACKAGE}.umd.js
PWD=`pwd`
SRCDIR=${PWD}/modules/@angular/${PACKAGE}
DESTDIR=${PWD}/dist/packages-dist/${PACKAGE}
UMD_ES5_PATH=${DESTDIR}/bundles/${PACKAGE}.umd.js
UMD_TESTING_ES5_PATH=${DESTDIR}/bundles/${PACKAGE}-testing.umd.js
UMD_STATIC_ES5_PATH=${DESTDIR}/bundles/${PACKAGE}-static.umd.js
UMD_UPGRADE_ES5_PATH=${DESTDIR}/bundles/${PACKAGE}-upgrade.umd.js
UMD_ES5_MIN_PATH=${DESTDIR}/bundles/${PACKAGE}.umd.min.js
UMD_STATIC_ES5_MIN_PATH=${DESTDIR}/bundles/${PACKAGE}-static.umd.min.js
UMD_UPGRADE_ES5_MIN_PATH=${DESTDIR}/bundles/${PACKAGE}-upgrade.umd.min.js
if [[ ${PACKAGE} == "router-deprecated" ]]; then
echo "====== COMPILING: \$(npm bin)/tsc -p ${SRCDIR}/tsconfig-es5.json ====="
$(npm bin)/tsc -p ${SRCDIR}/tsconfig-es5.json
else
echo "====== COMPILING: ${TSC} -p ${SRCDIR}/tsconfig-es5.json ====="
$TSC -p ${SRCDIR}/tsconfig-es5.json
if [[ ${PACKAGE} != router ]]; then
LICENSE_BANNER=${PWD}/modules/@angular/license-banner.txt
fi
if [[ ${PACKAGE} == router ]]; then
LICENSE_BANNER=${PWD}/modules/@angular/router-license-banner.txt
fi
rm -rf ${DESTDIR}
echo "====== COMPILING: ${TSC} -p ${SRCDIR}/tsconfig-build.json ====="
$TSC -p ${SRCDIR}/tsconfig-build.json
if [[ -e ${SRCDIR}/tsconfig-upgrade.json ]]; then
echo "====== COMPILING: ${TSC} -p ${SRCDIR}/tsconfig-upgrade.json ====="
$TSC -p ${SRCDIR}/tsconfig-upgrade.json
fi
cp ${SRCDIR}/package.json ${DESTDIR}/
cp ${PWD}/modules/@angular/README.md ${DESTDIR}/
if [[ -e ${SRCDIR}/tsconfig-testing.json ]]; then
echo "====== COMPILING TESTING: ${TSC} -p ${SRCDIR}/tsconfig-testing.json"
$TSC -p ${SRCDIR}/tsconfig-testing.json
fi
if [[ -e ${SRCDIR}/tsconfig-2015.json ]]; then
echo "====== COMPILING ESM: ${TSC} -p ${SRCDIR}/tsconfig-2015.json"
${TSC} -p ${SRCDIR}/tsconfig-2015.json
fi
echo "====== TSC 1.8 d.ts compat for ${DESTDIR} ====="
# safely strips 'readonly' specifier from d.ts files to make them compatible with tsc 1.8
if [[ ${TRAVIS} ]]; then
find ${DESTDIR} -type f -name '*.d.ts' -print0 | xargs -0 sed -i -e 's/\(^ *(static |private )*\)*readonly */\1/g'
find ${DESTDIR} -type f -name '*.d.ts' -print0 | xargs -0 sed -i -E 's/^( +)abstract ([[:alnum:]]+\:)/\1\2/g'
else
if [ "$(uname)" == "Darwin" ]; then
find ${DESTDIR} -type f -name '*.d.ts' -print0 | xargs -0 sed -i '' -e 's/\(^ *(static |private )*\)*readonly */\1/g'
find ${DESTDIR} -type f -name '*.d.ts' -print0 | xargs -0 sed -i '' -e 's/\/\/\/ <reference types="node" \/>//g'
find ${DESTDIR} -type f -name '*.d.ts' -print0 | xargs -0 sed -i '' -E 's/^( +)abstract ([[:alnum:]]+\:)/\1\2/g'
else
find ${DESTDIR} -type f -name '*.d.ts' -print0 | xargs -0 sed -i -e 's/\(^ *(static |private )*\)*readonly */\1/g'
find ${DESTDIR} -type f -name '*.d.ts' -print0 | xargs -0 sed -i -e 's/\/\/\/ <reference types="node" \/>//g'
find ${DESTDIR} -type f -name '*.d.ts' -print0 | xargs -0 sed -i -E 's/^( +)abstract ([[:alnum:]]+\:)/\1\2/g'
fi
if [[ ${PACKAGE} != compiler-cli ]]; then
if [[ ${PACKAGE} == benchpress ]]; then
cp ${SRCDIR}/*.md ${DESTDIR}
cp -r ${SRCDIR}/docs ${DESTDIR}
fi
if [[ ${PACKAGE} == "router-deprecated" ]]; then
echo "====== (esm)COMPILING: \$(npm bin)/tsc -p ${SRCDIR}/tsconfig-es2015.json ====="
$(npm bin)/tsc -p ${SRCDIR}/tsconfig-es2015.json
else
echo "====== (esm)COMPILING: $TSC -p ${SRCDIR}/tsconfig-es2015.json ====="
$TSC -p ${SRCDIR}/tsconfig-es2015.json
fi
if [[ ${BUNDLE} == true && ${PACKAGE} != compiler-cli && ${PACKAGE} != benchpress ]]; then
echo "====== BUNDLING: ${SRCDIR} ====="
mkdir ${DESTDIR}/bundles
(
cd ${SRCDIR}
echo "..." # here just to have grep match something and not exit with 1
echo "====== Rollup ${PACKAGE} index"
../../../node_modules/.bin/rollup -c rollup.config.js
cat ${LICENSE_BANNER} > ${UMD_ES5_PATH}.tmp
cat ${UMD_ES5_PATH} >> ${UMD_ES5_PATH}.tmp
mv ${UMD_ES5_PATH}.tmp ${UMD_ES5_PATH}
$UGLIFYJS -c --screw-ie8 --comments -o ${UMD_ES5_MIN_PATH} ${UMD_ES5_PATH}
if [[ -e rollup-testing.config.js ]]; then
echo "====== Rollup ${PACKAGE} testing"
../../../node_modules/.bin/rollup -c rollup-testing.config.js
echo "{\"main\": \"../bundles/${PACKAGE}-testing.umd.js\"}" > ${DESTDIR}/testing/package.json
cat ${LICENSE_BANNER} > ${UMD_TESTING_ES5_PATH}.tmp
cat ${UMD_TESTING_ES5_PATH} >> ${UMD_TESTING_ES5_PATH}.tmp
mv ${UMD_TESTING_ES5_PATH}.tmp ${UMD_TESTING_ES5_PATH}
fi
if [[ -e rollup-static.config.js ]]; then
echo "====== Rollup ${PACKAGE} static"
../../../node_modules/.bin/rollup -c rollup-static.config.js
# create dir because it doesn't exist yet, we should move the src code here and remove this line
mkdir ${DESTDIR}/static
echo "{\"main\": \"../bundles/${PACKAGE}-static.umd.js\"}" > ${DESTDIR}/static/package.json
cat ${LICENSE_BANNER} > ${UMD_STATIC_ES5_PATH}.tmp
cat ${UMD_STATIC_ES5_PATH} >> ${UMD_STATIC_ES5_PATH}.tmp
mv ${UMD_STATIC_ES5_PATH}.tmp ${UMD_STATIC_ES5_PATH}
$UGLIFYJS -c --screw-ie8 --comments -o ${UMD_STATIC_ES5_MIN_PATH} ${UMD_STATIC_ES5_PATH}
fi
if [[ -e rollup-upgrade.config.js ]]; then
echo "====== Rollup ${PACKAGE} upgrade"
../../../node_modules/.bin/rollup -c rollup-upgrade.config.js
# create dir because it doesn't exist yet, we should move the src code here and remove this line
mkdir ${DESTDIR}/upgrade
echo "{\"main\": \"../bundles/${PACKAGE}-upgrade.umd.js\"}" > ${DESTDIR}/upgrade/package.json
cat ${LICENSE_BANNER} > ${UMD_UPGRADE_ES5_PATH}.tmp
cat ${UMD_UPGRADE_ES5_PATH} >> ${UMD_UPGRADE_ES5_PATH}.tmp
mv ${UMD_UPGRADE_ES5_PATH}.tmp ${UMD_UPGRADE_ES5_PATH}
$UGLIFYJS -c --screw-ie8 --comments -o ${UMD_UPGRADE_ES5_MIN_PATH} ${UMD_UPGRADE_ES5_PATH}
fi
) 2>&1 | grep -v "as external dependency"
$(npm bin)/tsc \
--out ${UMD_ES5_PATH} \
--target es5 \
--lib "es6,dom" \
--allowJs \
${UMD_ES6_PATH}
rm ${UMD_ES6_PATH}
cat ./modules/@angular/license-banner.txt > ${UMD_ES5_PATH}.tmp
cat ${UMD_ES5_PATH} >> ${UMD_ES5_PATH}.tmp
mv ${UMD_ES5_PATH}.tmp ${UMD_ES5_PATH}
$(npm bin)/uglifyjs -c --screw-ie8 -o ${UMD_ES5_MIN_PATH} ${UMD_ES5_PATH}
fi
(
echo "====== VERSION: Updating version references"
cd ${DESTDIR}
echo "====== EXECUTE: perl -p -i -e \"s/0\.0\.0\-PLACEHOLDER/${VERSION}/g\" $""(grep -ril 0\.0\.0\-PLACEHOLDER .)"
perl -p -i -e "s/0\.0\.0\-PLACEHOLDER/${VERSION}/g" $(grep -ril 0\.0\.0\-PLACEHOLDER .) < /dev/null 2> /dev/null
echo "====== EXECUTE: perl -p -i -e \"s/0\.0\.0\-ROUTERPLACEHOLDER/${ROUTER_VERSION}/g\" $""(grep -ril 0\.0\.0\-ROUTERPLACEHOLDER .)"
perl -p -i -e "s/0\.0\.0\-ROUTERPLACEHOLDER/${ROUTER_VERSION}/g" $(grep -ril 0\.0\.0\-ROUTERPLACEHOLDER .) < /dev/null 2> /dev/null
)
done
echo ""
echo "====== Building examples: ./modules/@angular/examples/build.sh ====="
./modules/@angular/examples/build.sh
if [[ ${REMOVE_BENCHPRESS} == true ]]; then
echo ""
echo "==== Removing benchpress from publication"
rm -r dist/packages-dist/benchpress
fi

View File

@ -1,10 +1,10 @@
machine:
node:
version: 5.4.1
version: 6.9.5
dependencies:
pre:
- npm install -g npm
- npm install -g npm@3.10.7
test:
override:

40
docs/PUBLIC_API.md Normal file
View File

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

View File

@ -1,67 +1,234 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
'use strict';
// THIS CHECK SHOULD BE THE FIRST THING IN THIS FILE
// This is to ensure that we catch env issues before we error while requiring other dependencies.
require('./tools/check-environment')(
{requiredNpmVersion: '>=3.5.3 <4.0.0', requiredNodeVersion: '>=5.4.1 <6.0.0'});
require('./tools/check-environment')({
requiredNpmVersion: '>=3.10.7 <4.0.0',
requiredNodeVersion: '>=6.9.5 <7.0.0',
});
const gulp = require('gulp');
const path = require('path');
const os = require('os');
const srcsToFmt = ['tools/**/*.ts', 'modules/@angular/**/*.ts'];
// clang-format entry points
const srcsToFmt = [
'modules/@angular/**/*.{js,ts}',
'modules/benchmarks/**/*.{js,ts}',
'modules/e2e_util/**/*.{js,ts}',
'modules/playground/**/*.{js,ts}',
'tools/**/*.{js,ts}',
'!tools/public_api_guard/**/*.d.ts',
'./*.{js,ts}',
'!shims_for_IE.js',
];
// Check source code for formatting errors (clang-format)
gulp.task('format:enforce', () => {
const format = require('gulp-clang-format');
const clangFormat = require('clang-format');
return gulp.src(srcsToFmt).pipe(
format.checkFormat('file', clangFormat, {verbose: true, fail: true}));
format.checkFormat('file', clangFormat, {verbose: true, fail: true}));
});
// Format the source code with clang-format (see .clang-format)
gulp.task('format', () => {
const format = require('gulp-clang-format');
const clangFormat = require('clang-format');
return gulp.src(srcsToFmt, { base: '.' }).pipe(
format.format('file', clangFormat)).pipe(gulp.dest('.'));
return gulp.src(srcsToFmt, {base: '.'})
.pipe(format.format('file', clangFormat))
.pipe(gulp.dest('.'));
});
const entrypoints = [
'dist/packages-dist/core/index.d.ts',
'dist/packages-dist/core/testing/index.d.ts',
'dist/packages-dist/common/index.d.ts',
'dist/packages-dist/common/testing/index.d.ts',
// The API surface of the compiler is currently unstable - all of the important APIs are exposed
// via @angular/core, @angular/platform-browser or @angular/platform-browser-dynamic instead.
//'dist/packages-dist/compiler/index.d.ts',
//'dist/packages-dist/compiler/testing.d.ts',
'dist/packages-dist/upgrade/index.d.ts',
'dist/packages-dist/upgrade/static.d.ts',
'dist/packages-dist/platform-browser/index.d.ts',
'dist/packages-dist/platform-browser/testing/index.d.ts',
'dist/packages-dist/platform-browser-dynamic/index.d.ts',
'dist/packages-dist/platform-browser-dynamic/testing/index.d.ts',
'dist/packages-dist/platform-webworker/index.d.ts',
'dist/packages-dist/platform-webworker-dynamic/index.d.ts',
'dist/packages-dist/platform-server/index.d.ts',
'dist/packages-dist/platform-server/testing/index.d.ts',
'dist/packages-dist/http/index.d.ts',
'dist/packages-dist/http/testing/index.d.ts',
'dist/packages-dist/forms/index.d.ts',
'dist/packages-dist/router/index.d.ts',
];
const publicApiDir = path.normalize('tools/public_api_guard');
const publicApiArgs = [
'--rootDir',
'dist/packages-dist',
'--stripExportPattern',
'^__',
'--allowModuleIdentifiers',
'jasmine',
'--allowModuleIdentifiers',
'protractor',
'--allowModuleIdentifiers',
'angular',
'--onStabilityMissing',
'error',
].concat(entrypoints);
// Build angular
gulp.task('build.sh', (done) => {
const childProcess = require('child_process');
childProcess.exec(path.join(__dirname, 'build.sh'), done);
});
// Enforce that the public API matches the golden files
// Note that these two commands work on built d.ts files instead of the source
gulp.task('public-api:enforce', (done) => {
const childProcess = require('child_process');
childProcess
.spawn(
path.join(__dirname, platformScriptPath(`/node_modules/.bin/ts-api-guardian`)),
['--verifyDir', publicApiDir].concat(publicApiArgs), {stdio: 'inherit'})
.on('close', (errorCode) => {
if (errorCode !== 0) {
done(new Error(
'Public API differs from golden file. Please run `gulp public-api:update`.'));
} else {
done();
}
});
});
// Generate the public API golden files
gulp.task('public-api:update', ['build.sh'], (done) => {
const childProcess = require('child_process');
childProcess
.spawn(
path.join(__dirname, platformScriptPath(`/node_modules/.bin/ts-api-guardian`)),
['--outDir', publicApiDir].concat(publicApiArgs), {stdio: 'inherit'})
.on('close', done);
});
// Check the coding standards and programming errors
gulp.task('lint', ['format:enforce', 'tools:build'], () => {
const tslint = require('gulp-tslint');
// Built-in rules are at
// https://github.com/palantir/tslint#supported-rules
// https://palantir.github.io/tslint/rules/
const tslintConfig = require('./tslint.json');
return gulp.src(['modules/@angular/**/*.ts', '!modules/@angular/*/test/**'])
.pipe(tslint({
tslint: require('tslint').default,
configuration: tslintConfig,
rulesDirectory: 'dist/tools/tslint'
}))
.pipe(tslint.report('prose', {emitError: true}));
return gulp
.src([
// todo(vicb): add .js files when supported
// see https://github.com/palantir/tslint/pull/1515
'./modules/**/*.ts',
'./tools/**/*.ts',
'./*.ts',
// Ignore TypeScript mocks because it's not managed by us
'!./tools/@angular/tsc-wrapped/test/typescript.mocks.ts',
// Ignore generated files due to lack of copyright header
// todo(alfaproject): make generated files lintable
'!**/*.d.ts',
'!**/*.ngfactory.ts',
])
.pipe(tslint({
tslint: require('tslint').default,
configuration: tslintConfig,
formatter: 'prose',
}))
.pipe(tslint.report({emitError: true}));
});
gulp.task('tools:build', (done) => { tsc('tools/', done); });
// Check for circular dependency in the source code
gulp.task('check-cycle', (done) => {
const madge = require('madge');
const dependencyObject = madge(['dist/all/'], {
format: 'cjs',
extensions: ['.js'],
onParseFile: function(data) { data.src = data.src.replace(/\/\* circular \*\//g, '//'); }
});
const circularDependencies = dependencyObject.circular().getArray();
if (circularDependencies.length > 0) {
console.log('Found circular dependencies!');
console.log(circularDependencies);
process.exit(1);
}
done();
});
// Serve the built files
gulp.task('serve', () => {
let connect = require('gulp-connect');
let cors = require('cors');
const connect = require('gulp-connect');
const cors = require('cors');
connect.server({
root: `${__dirname}/dist`,
port: 8000,
livereload: false,
open: false,
middleware: (connect, opt) => [cors()]
middleware: (connect, opt) => [cors()],
});
});
// Serve the examples
gulp.task('serve-examples', () => {
const connect = require('gulp-connect');
const cors = require('cors');
connect.server({
root: `${__dirname}/dist/examples`,
port: 8001,
livereload: false,
open: false,
middleware: (connect, opt) => [cors()],
});
});
function tsc(projectPath, done) {
let child_process = require('child_process');
// Update the changelog with the latest changes
gulp.task('changelog', () => {
const conventionalChangelog = require('gulp-conventional-changelog');
child_process
return gulp.src('CHANGELOG.md')
.pipe(conventionalChangelog({preset: 'angular', releaseCount: 1}, {
// Conventional Changelog Context
// We have to manually set version number so it doesn't get prefixed with `v`
// See https://github.com/conventional-changelog/conventional-changelog-core/issues/10
currentTag: require('./package.json').version
}))
.pipe(gulp.dest('./'));
});
function tsc(projectPath, done) {
const childProcess = require('child_process');
childProcess
.spawn(
`${__dirname}/node_modules/.bin/tsc`, ['-p', path.join(__dirname, projectPath)],
{stdio: 'inherit'})
.on('close', (errorCode) => done(errorCode));
path.normalize(platformScriptPath(`${__dirname}/node_modules/.bin/tsc`)),
['-p', path.join(__dirname, projectPath)], {stdio: 'inherit'})
.on('close', done);
}
// returns the script path for the current platform
function platformScriptPath(path) {
return /^win/.test(os.platform()) ? `${path}.cmd` : path;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
var browserProvidersConf = require('./browser-providers.conf.js');
var internalAngularReporter = require('./tools/karma/reporter.js');
@ -13,12 +21,15 @@ module.exports = function(config) {
// Loaded through the System loader, in `test-main.js`.
{pattern: 'dist/all/@angular/**/*.js', included: false, watched: true},
'node_modules/es6-shim/es6-shim.js',
'node_modules/core-js/client/core.js',
// include Angular v1 for upgrade module testing
'node_modules/angular/angular.min.js',
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'node_modules/zone.js/dist/zone.js',
'node_modules/zone.js/dist/long-stack-trace-zone.js',
'node_modules/zone.js/dist/proxy.js',
'node_modules/zone.js/dist/sync-test.js',
'node_modules/zone.js/dist/jasmine-patch.js',
'node_modules/zone.js/dist/async-test.js',
'node_modules/zone.js/dist/fake-async-test.js',
@ -31,16 +42,30 @@ module.exports = function(config) {
'tools/build/file2modulename.js',
'test-main.js',
{pattern: 'dist/all/empty.*', included: false, watched: false},
{pattern: 'modules/@angular/platform-browser/test/static_assets/**', included: false, watched: false},
{pattern: 'modules/@angular/platform-browser/test/browser/static_assets/**', included: false, watched: false}
{
pattern: 'modules/@angular/platform-browser/test/static_assets/**',
included: false,
watched: false
},
{
pattern: 'modules/@angular/platform-browser/test/browser/static_assets/**',
included: false,
watched: false,
}
],
exclude: [
'dist/all/@angular/**/e2e_test/**',
'dist/all/@angular/examples/**',
'dist/all/@angular/**/*node_only_spec.js',
'dist/all/@angular/benchpress/**',
'dist/all/@angular/compiler-cli/**',
'dist/all/@angular/compiler/test/aot/**',
'dist/all/@angular/examples/**/e2e_test/*',
'dist/all/@angular/language-service/**',
'dist/all/@angular/router/**',
'dist/all/@angular/platform-browser/testing/e2e_util.js',
'dist/all/angular1_router.js',
'dist/all/@angular/platform-browser/testing/e2e_util.js'
'dist/examples/**/e2e_test/**',
],
customLaunchers: browserProvidersConf.customLaunchers,
@ -51,11 +76,11 @@ module.exports = function(config) {
'karma-sauce-launcher',
'karma-chrome-launcher',
'karma-sourcemap-loader',
internalAngularReporter
internalAngularReporter,
],
preprocessors: {
'**/*.js': ['sourcemap']
'**/*.js': ['sourcemap'],
},
reporters: ['internal-angular'],
@ -69,7 +94,7 @@ module.exports = function(config) {
'selenium-version': '2.53.0',
'command-timeout': 600,
'idle-timeout': 600,
'max-duration': 5400
'max-duration': 5400,
}
},
@ -77,21 +102,22 @@ module.exports = function(config) {
project: 'Angular2',
startTunnel: false,
retryLimit: 3,
timeout: 600,
pollingTimeout: 10000
timeout: 1800,
pollingTimeout: 10000,
},
browsers: ['Chrome'],
port: 9876,
captureTimeout: 60000,
browserDisconnectTimeout : 60000,
browserDisconnectTolerance : 3,
browserNoActivityTimeout : 60000,
captureTimeout: 180000,
browserDisconnectTimeout: 180000,
browserDisconnectTolerance: 3,
browserNoActivityTimeout: 300000,
});
if (process.env.TRAVIS) {
var buildId = 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')';
var buildId =
'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')';
if (process.env.CI_MODE.startsWith('saucelabs')) {
config.sauceLabs.build = buildId;
config.sauceLabs.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER;

View File

@ -1,6 +0,0 @@
Angular2
=========
The sources for this package are in the main [Angular2](https://github.com/angular/angular) repo. Please file issues and pull requests against that repo. This is the repository for the upcoming 2.0 version. If you're looking for the current official version of Angular you should go to [angular/angular.js](https://github.com/angular/angular.js)
License: Apache MIT 2.0

View File

@ -1,15 +0,0 @@
Angular2
=========
The sources for this package are in the main [Angular2](https://github.com/angular/angular) repo. Please file issues and pull requests against that repo. This is the repository for the upcoming 2.0 version. If you're looking for the current official version of Angular you should go to [angular/angular.js](https://github.com/angular/angular.js)
This package contains different sources for different users:
1. The files located in the root folder can be consumed using CommonJS.
2. The files under `/es6` are es6 compatible files that can be transpiled to
es5 using any transpiler. This contains:
* `dev/`: a development version that includes runtime type assertions
* `prod/`: a production version that does not include runtime type assertions
3. The files under `/ts` are the TypeScript source files.
License: Apache MIT 2.0

View File

@ -0,0 +1,6 @@
Angular
=======
The sources for this package are in the main [Angular](https://github.com/angular/angular) repo. Please file issues and pull requests against that repo.
License: MIT

View File

@ -3,6 +3,10 @@
Benchpress is a framework for e2e performance tests.
See [here for an example project](https://github.com/angular/benchpress-tree).
The sources for this package are in the main [Angular2](https://github.com/angular/angular) repo. Please file issues and pull requests against that repo.
License: MIT
# Why?
There are so called "micro benchmarks" that essentially use a stop watch in the browser to measure time
@ -158,7 +162,44 @@ runner.sample({
````
When looking into the DevTools Timeline, we see a marker as well:
![Marked Timeline](marked_timeline.png)
![Marked Timeline](docs/marked_timeline.png)
### Custom Metrics Without Using `console.time`
It's also possible to measure any "user metric" within the browser
by setting a numeric value on the `window` object. For example:
```js
bootstrap(App)
.then(() => {
window.timeToBootstrap = Date.now() - performance.timing.navigationStart;
});
```
A test driver for this user metric could be written as follows:
```js
describe('home page load', function() {
it('should log load time for a 2G connection', done => {
runner.sample({
execute: () => {
browser.get(`http://localhost:8080`);
},
userMetrics: {
timeToBootstrap: 'The time in milliseconds to bootstrap'
},
providers: [
{provide: RegressionSlopeValidator.METRIC, useValue: 'timeToBootstrap'}
]
}).then(done);
});
});
```
Using this strategy, benchpress will wait until the specified property name,
`timeToBootstrap` in this case, is defined as a number on the `window` object
inside the application under test.
# Smoothness Metrics
@ -171,9 +212,9 @@ Benchpress can also measure the "smoothness" of scrolling and animations. In ord
To collect these metrics, you need to execute `console.time('frameCapture')` and `console.timeEnd('frameCapture')` either in your benchmark application or in you benchmark driver via webdriver. The metrics mentioned above will only be collected between those two calls and it is recommended to wrap the time/timeEnd calls as closely as possible around the action you want to evaluate to get accurate measurements.
In addition to that, one extra binding needs to be passed to benchpress in tests that want to collect these metrics:
In addition to that, one extra provider needs to be passed to benchpress in tests that want to collect these metrics:
benchpress.sample(providers: [bp.bind(bp.Options.CAPTURE_FRAMES).toValue(true)], ... )
benchpress.sample(providers: [{provide: bp.Options.CAPTURE_FRAMES, useValue: true}], ... )
# Requests Metrics
@ -185,8 +226,8 @@ Benchpress can also record the number of requests sent and count the received "e
To collect these metrics, you need the following corresponding extra providers:
benchpress.sample(providers: [
bp.bind(bp.Options.RECEIVED_DATA).toValue(true),
bp.bind(bp.Options.REQUEST_COUNT).toValue(true)
{provide: bp.Options.RECEIVED_DATA, useValue: true},
{provide: bp.Options.REQUEST_COUNT, useValue: true}
], ... )
# Best practices
@ -219,7 +260,7 @@ To collect these metrics, you need the following corresponding extra providers:
# Detailed overview
![Overview](overview.png)
![Overview](docs/overview.png)
Definitions:

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -1,22 +1,34 @@
export {Sampler, SampleState} from './src/sampler';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
// Must be imported first, because angular2 decorators throws on load.
import 'reflect-metadata';
export {Injector, OpaqueToken, Provider, ReflectiveInjector} from '@angular/core';
export {Options} from './src/common_options';
export {MeasureValues} from './src/measure_values';
export {Metric} from './src/metric';
export {Validator} from './src/validator';
export {MultiMetric} from './src/metric/multi_metric';
export {PerflogMetric} from './src/metric/perflog_metric';
export {UserMetric} from './src/metric/user_metric';
export {Reporter} from './src/reporter';
export {WebDriverExtension, PerfLogFeatures} from './src/web_driver_extension';
export {WebDriverAdapter} from './src/web_driver_adapter';
export {SizeValidator} from './src/validator/size_validator';
export {RegressionSlopeValidator} from './src/validator/regression_slope_validator';
export {ConsoleReporter} from './src/reporter/console_reporter';
export {JsonFileReporter} from './src/reporter/json_file_reporter';
export {MultiReporter} from './src/reporter/multi_reporter';
export {Runner} from './src/runner';
export {SampleDescription} from './src/sample_description';
export {PerflogMetric} from './src/metric/perflog_metric';
export {SampleState, Sampler} from './src/sampler';
export {Validator} from './src/validator';
export {RegressionSlopeValidator} from './src/validator/regression_slope_validator';
export {SizeValidator} from './src/validator/size_validator';
export {WebDriverAdapter} from './src/web_driver_adapter';
export {PerfLogEvent, PerfLogFeatures, WebDriverExtension} from './src/web_driver_extension';
export {ChromeDriverExtension} from './src/webdriver/chrome_driver_extension';
export {FirefoxDriverExtension} from './src/webdriver/firefox_driver_extension';
export {IOsDriverExtension} from './src/webdriver/ios_driver_extension';
export {Runner} from './src/runner';
export {Options} from './src/common_options';
export {MeasureValues} from './src/measure_values';
export {MultiMetric} from './src/metric/multi_metric';
export {MultiReporter} from './src/reporter/multi_reporter';
export {bind, provide, Injector, ReflectiveInjector, OpaqueToken} from '@angular/core/src/di';
export {SeleniumWebDriverAdapter} from './src/webdriver/selenium_webdriver_adapter';

View File

@ -0,0 +1,31 @@
{
"name": "@angular/benchpress",
"version": "0.1.0",
"description": "Benchpress - a framework for e2e performance tests",
"main": "index.js",
"typings": "index.d.ts",
"dependencies": {
"@angular/core": "^2.0.0-rc.7",
"reflect-metadata": "^0.1.2",
"rxjs": "^5.0.1",
"jpm": "1.1.4",
"firefox-profile": "0.4.0",
"selenium-webdriver": "^2.53.3"
},
"repository": {
"type": "git",
"url": "https://github.com/angular/angular.git"
},
"keywords": [
"angular",
"benchmarks"
],
"contributors": [
"Tobias Bosch <tbosch@google.com> (https://angular.io/)"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/angular/angular/issues"
},
"homepage": "https://github.com/angular/angular/tree/master/modules/@angular/compiler-cli"
}

View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -ex
cd $(dirname $0)/../../..
ROOTDIR=$(pwd)
SRCDIR=${ROOTDIR}/modules/@angular/benchpress
DESTDIR=${ROOTDIR}/dist/packages-dist/benchpress
rm -fr ${DESTDIR}
echo "====== BUILDING... ====="
./build.sh --packages=core,benchpress --bundle=false
echo "====== PUBLISHING: ${DESTDIR} ====="
npm publish ${DESTDIR} --access public

View File

@ -0,0 +1,53 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from '@angular/core';
import * as fs from 'fs';
export class Options {
static SAMPLE_ID = new OpaqueToken('Options.sampleId');
static DEFAULT_DESCRIPTION = new OpaqueToken('Options.defaultDescription');
static SAMPLE_DESCRIPTION = new OpaqueToken('Options.sampleDescription');
static FORCE_GC = new OpaqueToken('Options.forceGc');
static NO_PREPARE = () => true;
static PREPARE = new OpaqueToken('Options.prepare');
static EXECUTE = new OpaqueToken('Options.execute');
static CAPABILITIES = new OpaqueToken('Options.capabilities');
static USER_AGENT = new OpaqueToken('Options.userAgent');
static MICRO_METRICS = new OpaqueToken('Options.microMetrics');
static USER_METRICS = new OpaqueToken('Options.userMetrics');
static NOW = new OpaqueToken('Options.now');
static WRITE_FILE = new OpaqueToken('Options.writeFile');
static RECEIVED_DATA = new OpaqueToken('Options.receivedData');
static REQUEST_COUNT = new OpaqueToken('Options.requestCount');
static CAPTURE_FRAMES = new OpaqueToken('Options.frameCapture');
static DEFAULT_PROVIDERS = [
{provide: Options.DEFAULT_DESCRIPTION, useValue: {}},
{provide: Options.SAMPLE_DESCRIPTION, useValue: {}},
{provide: Options.FORCE_GC, useValue: false},
{provide: Options.PREPARE, useValue: Options.NO_PREPARE},
{provide: Options.MICRO_METRICS, useValue: {}}, {provide: Options.USER_METRICS, useValue: {}},
{provide: Options.NOW, useValue: () => new Date()},
{provide: Options.RECEIVED_DATA, useValue: false},
{provide: Options.REQUEST_COUNT, useValue: false},
{provide: Options.CAPTURE_FRAMES, useValue: false},
{provide: Options.WRITE_FILE, useValue: writeFile}
];
}
function writeFile(filename: string, content: string): Promise<any> {
return new Promise(function(resolve, reject) {
fs.writeFile(filename, content, (error) => {
if (error) {
reject(error);
} else {
resolve();
}
});
});
}

View File

@ -0,0 +1,38 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
declare var exportFunction: any;
declare var unsafeWindow: any;
exportFunction(function() {
const curTime = unsafeWindow.performance.now();
(<any>self).port.emit('startProfiler', curTime);
}, unsafeWindow, {defineAs: 'startProfiler'});
exportFunction(function() {
(<any>self).port.emit('stopProfiler');
}, unsafeWindow, {defineAs: 'stopProfiler'});
exportFunction(function(cb: Function) {
(<any>self).port.once('perfProfile', cb);
(<any>self).port.emit('getProfile');
}, unsafeWindow, {defineAs: 'getProfile'});
exportFunction(function() {
(<any>self).port.emit('forceGC');
}, unsafeWindow, {defineAs: 'forceGC'});
exportFunction(function(name: string) {
const curTime = unsafeWindow.performance.now();
(<any>self).port.emit('markStart', name, curTime);
}, unsafeWindow, {defineAs: 'markStart'});
exportFunction(function(name: string) {
const curTime = unsafeWindow.performance.now();
(<any>self).port.emit('markEnd', name, curTime);
}, unsafeWindow, {defineAs: 'markEnd'});

View File

@ -0,0 +1,78 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const {Cc, Ci, Cu} = require('chrome');
const os = Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
const ParserUtil = require('./parser_util');
class Profiler {
private _profiler: any;
private _markerEvents: any[];
private _profilerStartTime: number;
constructor() { this._profiler = Cc['@mozilla.org/tools/profiler;1'].getService(Ci.nsIProfiler); }
start(entries: any, interval: any, features: any, timeStarted: any) {
this._profiler.StartProfiler(entries, interval, features, features.length);
this._profilerStartTime = timeStarted;
this._markerEvents = [];
}
stop() { this._profiler.StopProfiler(); }
getProfilePerfEvents() {
const profileData = this._profiler.getProfileData();
let perfEvents = ParserUtil.convertPerfProfileToEvents(profileData);
perfEvents = this._mergeMarkerEvents(perfEvents);
perfEvents.sort(function(event1: any, event2: any) {
return event1.ts - event2.ts;
}); // Sort by ts
return perfEvents;
}
/** @internal */
private _mergeMarkerEvents(perfEvents: any[]): any[] {
this._markerEvents.forEach(function(markerEvent) { perfEvents.push(markerEvent); });
return perfEvents;
}
addStartEvent(name: string, timeStarted: number) {
this._markerEvents.push({ph: 'B', ts: timeStarted - this._profilerStartTime, name: name});
}
addEndEvent(name: string, timeEnded: number) {
this._markerEvents.push({ph: 'E', ts: timeEnded - this._profilerStartTime, name: name});
}
}
function forceGC() {
Cu.forceGC();
os.notifyObservers(null, 'child-gc-request', null);
};
const mod = require('sdk/page-mod');
const data = require('sdk/self').data;
const profiler = new Profiler();
mod.PageMod({
include: ['*'],
contentScriptFile: data.url('installed_script.js'),
onAttach: (worker: any) => {
worker.port.on(
'startProfiler',
(timeStarted: any) => profiler.start(
/* = profiler memory */ 3000000, 0.1, ['leaf', 'js', 'stackwalk', 'gc'], timeStarted));
worker.port.on('stopProfiler', () => profiler.stop());
worker.port.on(
'getProfile', () => worker.port.emit('perfProfile', profiler.getProfilePerfEvents()));
worker.port.on('forceGC', forceGC);
worker.port.on(
'markStart', (name: string, timeStarted: any) => profiler.addStartEvent(name, timeStarted));
worker.port.on(
'markEnd', (name: string, timeEnded: any) => profiler.addEndEvent(name, timeEnded));
}
});

View File

@ -1,14 +1,22 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @param {Object} perfProfile The perf profile JSON object.
* @return {Object[]} An array of recognized events that are captured
* within the perf profile.
*/
export function convertPerfProfileToEvents(perfProfile: any): any[] {
var inProgressEvents = new Map(); // map from event name to start time
var finishedEvents = []; // Event[] finished events
var addFinishedEvent = function(eventName, startTime, endTime) {
var categorizedEventName = categorizeEvent(eventName);
var args = undefined;
const inProgressEvents = new Map(); // map from event name to start time
const finishedEvents: {[key: string]: any}[] = []; // Event[] finished events
const addFinishedEvent = function(eventName: string, startTime: number, endTime: number) {
const categorizedEventName = categorizeEvent(eventName);
let args: {[key: string]: any} = undefined;
if (categorizedEventName == 'gc') {
// TODO: We cannot measure heap size at the moment
args = {usedHeapSize: 0};
@ -23,23 +31,25 @@ export function convertPerfProfileToEvents(perfProfile: any): any[] {
}
};
var samples = perfProfile.threads[0].samples;
const samples = perfProfile.threads[0].samples;
// In perf profile, firefox samples all the frames in set time intervals. Here
// we go through all the samples and construct the start and end time for each
// event.
for (var i = 0; i < samples.length; ++i) {
var sample = samples[i];
var sampleTime = sample.time;
for (let i = 0; i < samples.length; ++i) {
const sample = samples[i];
const sampleTime = sample.time;
// Add all the frames into a set so it's easier/faster to find the set
// differences
var sampleFrames = new Set();
sample.frames.forEach(function(frame) { sampleFrames.add(frame.location); });
const sampleFrames = new Set();
sample.frames.forEach(function(frame: {[key: string]: any}) {
sampleFrames.add(frame['location']);
});
// If an event is in the inProgressEvents map, but not in the current sample,
// then it must have just finished. We add this event to the finishedEvents
// array and remove it from the inProgressEvents map.
var previousSampleTime = (i == 0 ? /* not used */ -1 : samples[i - 1].time);
const previousSampleTime = (i == 0 ? /* not used */ -1 : samples[i - 1].time);
inProgressEvents.forEach(function(startTime, eventName) {
if (!(sampleFrames.has(eventName))) {
addFinishedEvent(eventName, startTime, previousSampleTime);
@ -59,13 +69,13 @@ export function convertPerfProfileToEvents(perfProfile: any): any[] {
// If anything is still in progress, we need to included it as a finished event
// since recording ended.
var lastSampleTime = samples[samples.length - 1].time;
const lastSampleTime = samples[samples.length - 1].time;
inProgressEvents.forEach(function(startTime, eventName) {
addFinishedEvent(eventName, startTime, lastSampleTime);
});
// Remove all the unknown categories.
return finishedEvents.filter(function(event) { return event.name != 'unknown'; });
return finishedEvents.filter(function(event) { return event['name'] != 'unknown'; });
}
// TODO: this is most likely not exhaustive.

View File

@ -0,0 +1,51 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const q = require('q');
const FirefoxProfile = require('firefox-profile');
const jpm = require('jpm/lib/xpi');
const pathUtil = require('path');
const PERF_ADDON_PACKAGE_JSON_DIR = '..';
exports.getAbsolutePath = function(path: string) {
const normalizedPath = pathUtil.normalize(path);
if (pathUtil.resolve(normalizedPath) == normalizedPath) {
// Already absolute path
return normalizedPath;
} else {
return pathUtil.join(__dirname, normalizedPath);
}
};
exports.getFirefoxProfile = function(extensionPath: string) {
const deferred = q.defer();
const firefoxProfile = new FirefoxProfile();
firefoxProfile.addExtensions([extensionPath], () => {
firefoxProfile.encoded((encodedProfile: any) => {
const multiCapabilities = [{browserName: 'firefox', firefox_profile: encodedProfile}];
deferred.resolve(multiCapabilities);
});
});
return deferred.promise;
};
exports.getFirefoxProfileWithExtension = function() {
const absPackageJsonDir = pathUtil.join(__dirname, PERF_ADDON_PACKAGE_JSON_DIR);
const packageJson = require(pathUtil.join(absPackageJsonDir, 'package.json'));
const savedCwd = process.cwd();
process.chdir(absPackageJsonDir);
return jpm(packageJson).then((xpiPath: string) => {
process.chdir(savedCwd);
return exports.getFirefoxProfile(xpiPath);
});
};

View File

@ -0,0 +1,20 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
export class MeasureValues {
constructor(
public runIndex: number, public timeStamp: Date, public values: {[key: string]: any}) {}
toJson() {
return {
'timeStamp': this.timeStamp.toJSON(),
'runIndex': this.runIndex,
'values': this.values,
};
}
}

View File

@ -1,28 +1,31 @@
import {BaseException, WrappedException} from '@angular/facade';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* A metric is measures values
*/
export abstract class Metric {
static bindTo(delegateToken): any[] {
return [{provide: Metric, useFactory: (delegate) => delegate, deps: [delegateToken]}];
}
/**
* Starts measuring
*/
beginMeasure(): Promise<any> { throw new BaseException('NYI'); }
beginMeasure(): Promise<any> { throw new Error('NYI'); }
/**
* Ends measuring and reports the data
* since the begin call.
* @param restart: Whether to restart right after this.
*/
endMeasure(restart: boolean): Promise<{[key: string]: any}> { throw new BaseException('NYI'); }
endMeasure(restart: boolean): Promise<{[key: string]: any}> { throw new Error('NYI'); }
/**
* Describes the metrics provided by this metric implementation.
* (e.g. units, ...)
*/
describe(): {[key: string]: any} { throw new BaseException('NYI'); }
describe(): {[key: string]: string} { throw new Error('NYI'); }
}

View File

@ -0,0 +1,63 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, OpaqueToken} from '@angular/core';
import {Metric} from '../metric';
export class MultiMetric extends Metric {
static provideWith(childTokens: any[]): any[] {
return [
{
provide: _CHILDREN,
useFactory: (injector: Injector) => childTokens.map(token => injector.get(token)),
deps: [Injector]
},
{
provide: MultiMetric,
useFactory: (children: Metric[]) => new MultiMetric(children),
deps: [_CHILDREN]
}
];
}
constructor(private _metrics: Metric[]) { super(); }
/**
* Starts measuring
*/
beginMeasure(): Promise<any> {
return Promise.all(this._metrics.map(metric => metric.beginMeasure()));
}
/**
* Ends measuring and reports the data
* since the begin call.
* @param restart: Whether to restart right after this.
*/
endMeasure(restart: boolean): Promise<{[key: string]: any}> {
return Promise.all(this._metrics.map(metric => metric.endMeasure(restart)))
.then(values => mergeStringMaps(<any>values));
}
/**
* Describes the metrics provided by this metric implementation.
* (e.g. units, ...)
*/
describe(): {[key: string]: any} {
return mergeStringMaps(this._metrics.map((metric) => metric.describe()));
}
}
function mergeStringMaps(maps: {[key: string]: string}[]): {[key: string]: string} {
const result: {[key: string]: string} = {};
maps.forEach(map => { Object.keys(map).forEach(prop => { result[prop] = map[prop]; }); });
return result;
}
const _CHILDREN = new OpaqueToken('MultiMetric.children');

View File

@ -0,0 +1,371 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable, OpaqueToken} from '@angular/core';
import {Options} from '../common_options';
import {Metric} from '../metric';
import {PerfLogEvent, PerfLogFeatures, WebDriverExtension} from '../web_driver_extension';
/**
* A metric that reads out the performance log
*/
@Injectable()
export class PerflogMetric extends Metric {
static SET_TIMEOUT = new OpaqueToken('PerflogMetric.setTimeout');
static PROVIDERS = [
PerflogMetric, {
provide: PerflogMetric.SET_TIMEOUT,
useValue: (fn: Function, millis: number) => <any>setTimeout(fn, millis)
}
];
private _remainingEvents: PerfLogEvent[];
private _measureCount: number;
private _perfLogFeatures: PerfLogFeatures;
/**
* @param driverExtension
* @param setTimeout
* @param microMetrics Name and description of metrics provided via console.time / console.timeEnd
**/
constructor(
private _driverExtension: WebDriverExtension,
@Inject(PerflogMetric.SET_TIMEOUT) private _setTimeout: Function,
@Inject(Options.MICRO_METRICS) private _microMetrics: {[key: string]: string},
@Inject(Options.FORCE_GC) private _forceGc: boolean,
@Inject(Options.CAPTURE_FRAMES) private _captureFrames: boolean,
@Inject(Options.RECEIVED_DATA) private _receivedData: boolean,
@Inject(Options.REQUEST_COUNT) private _requestCount: boolean) {
super();
this._remainingEvents = [];
this._measureCount = 0;
this._perfLogFeatures = _driverExtension.perfLogFeatures();
if (!this._perfLogFeatures.userTiming) {
// User timing is needed for navigationStart.
this._receivedData = false;
this._requestCount = false;
}
}
describe(): {[key: string]: string} {
const res: {[key: string]: any} = {
'scriptTime': 'script execution time in ms, including gc and render',
'pureScriptTime': 'script execution time in ms, without gc nor render'
};
if (this._perfLogFeatures.render) {
res['renderTime'] = 'render time in ms';
}
if (this._perfLogFeatures.gc) {
res['gcTime'] = 'gc time in ms';
res['gcAmount'] = 'gc amount in kbytes';
res['majorGcTime'] = 'time of major gcs in ms';
if (this._forceGc) {
res['forcedGcTime'] = 'forced gc time in ms';
res['forcedGcAmount'] = 'forced gc amount in kbytes';
}
}
if (this._receivedData) {
res['receivedData'] = 'encoded bytes received since navigationStart';
}
if (this._requestCount) {
res['requestCount'] = 'count of requests sent since navigationStart';
}
if (this._captureFrames) {
if (!this._perfLogFeatures.frameCapture) {
const warningMsg = 'WARNING: Metric requested, but not supported by driver';
// using dot syntax for metric name to keep them grouped together in console reporter
res['frameTime.mean'] = warningMsg;
res['frameTime.worst'] = warningMsg;
res['frameTime.best'] = warningMsg;
res['frameTime.smooth'] = warningMsg;
} else {
res['frameTime.mean'] = 'mean frame time in ms (target: 16.6ms for 60fps)';
res['frameTime.worst'] = 'worst frame time in ms';
res['frameTime.best'] = 'best frame time in ms';
res['frameTime.smooth'] = 'percentage of frames that hit 60fps';
}
}
for (const name in this._microMetrics) {
res[name] = this._microMetrics[name];
}
return res;
}
beginMeasure(): Promise<any> {
let resultPromise = Promise.resolve(null);
if (this._forceGc) {
resultPromise = resultPromise.then((_) => this._driverExtension.gc());
}
return resultPromise.then((_) => this._beginMeasure());
}
endMeasure(restart: boolean): Promise<{[key: string]: number}> {
if (this._forceGc) {
return this._endPlainMeasureAndMeasureForceGc(restart);
} else {
return this._endMeasure(restart);
}
}
/** @internal */
private _endPlainMeasureAndMeasureForceGc(restartMeasure: boolean) {
return this._endMeasure(true).then((measureValues) => {
// disable frame capture for measurements during forced gc
const originalFrameCaptureValue = this._captureFrames;
this._captureFrames = false;
return this._driverExtension.gc()
.then((_) => this._endMeasure(restartMeasure))
.then((forceGcMeasureValues) => {
this._captureFrames = originalFrameCaptureValue;
measureValues['forcedGcTime'] = forceGcMeasureValues['gcTime'];
measureValues['forcedGcAmount'] = forceGcMeasureValues['gcAmount'];
return measureValues;
});
});
}
private _beginMeasure(): Promise<any> {
return this._driverExtension.timeBegin(this._markName(this._measureCount++));
}
private _endMeasure(restart: boolean): Promise<{[key: string]: number}> {
const markName = this._markName(this._measureCount - 1);
const nextMarkName = restart ? this._markName(this._measureCount++) : null;
return this._driverExtension.timeEnd(markName, nextMarkName)
.then((_) => this._readUntilEndMark(markName));
}
private _readUntilEndMark(
markName: string, loopCount: number = 0, startEvent: PerfLogEvent = null) {
if (loopCount > _MAX_RETRY_COUNT) {
throw new Error(`Tried too often to get the ending mark: ${loopCount}`);
}
return this._driverExtension.readPerfLog().then((events) => {
this._addEvents(events);
const result = this._aggregateEvents(this._remainingEvents, markName);
if (result) {
this._remainingEvents = events;
return result;
}
let resolve: (result: any) => void;
const promise = new Promise(res => { resolve = res; });
this._setTimeout(() => resolve(this._readUntilEndMark(markName, loopCount + 1)), 100);
return promise;
});
}
private _addEvents(events: PerfLogEvent[]) {
let needSort = false;
events.forEach(event => {
if (event['ph'] === 'X') {
needSort = true;
const startEvent: PerfLogEvent = {};
const endEvent: PerfLogEvent = {};
for (const prop in event) {
startEvent[prop] = event[prop];
endEvent[prop] = event[prop];
}
startEvent['ph'] = 'B';
endEvent['ph'] = 'E';
endEvent['ts'] = startEvent['ts'] + startEvent['dur'];
this._remainingEvents.push(startEvent);
this._remainingEvents.push(endEvent);
} else {
this._remainingEvents.push(event);
}
});
if (needSort) {
// Need to sort because of the ph==='X' events
this._remainingEvents.sort((a, b) => {
const diff = a['ts'] - b['ts'];
return diff > 0 ? 1 : diff < 0 ? -1 : 0;
});
}
}
private _aggregateEvents(events: PerfLogEvent[], markName: string): {[key: string]: number} {
const result: {[key: string]: number} = {'scriptTime': 0, 'pureScriptTime': 0};
if (this._perfLogFeatures.gc) {
result['gcTime'] = 0;
result['majorGcTime'] = 0;
result['gcAmount'] = 0;
}
if (this._perfLogFeatures.render) {
result['renderTime'] = 0;
}
if (this._captureFrames) {
result['frameTime.mean'] = 0;
result['frameTime.best'] = 0;
result['frameTime.worst'] = 0;
result['frameTime.smooth'] = 0;
}
for (const name in this._microMetrics) {
result[name] = 0;
}
if (this._receivedData) {
result['receivedData'] = 0;
}
if (this._requestCount) {
result['requestCount'] = 0;
}
let markStartEvent: PerfLogEvent = null;
let markEndEvent: PerfLogEvent = null;
events.forEach((event) => {
const ph = event['ph'];
const name = event['name'];
if (ph === 'B' && name === markName) {
markStartEvent = event;
} else if (ph === 'I' && name === 'navigationStart') {
// if a benchmark measures reload of a page, use the last
// navigationStart as begin event
markStartEvent = event;
} else if (ph === 'E' && name === markName) {
markEndEvent = event;
}
});
if (!markStartEvent || !markEndEvent) {
// not all events have been received, no further processing for now
return null;
}
let gcTimeInScript = 0;
let renderTimeInScript = 0;
const frameTimestamps: number[] = [];
const frameTimes: number[] = [];
let frameCaptureStartEvent: PerfLogEvent = null;
let frameCaptureEndEvent: PerfLogEvent = null;
const intervalStarts: {[key: string]: PerfLogEvent} = {};
const intervalStartCount: {[key: string]: number} = {};
let inMeasureRange = false;
events.forEach((event) => {
const ph = event['ph'];
let name = event['name'];
let microIterations = 1;
const microIterationsMatch = name.match(_MICRO_ITERATIONS_REGEX);
if (microIterationsMatch) {
name = microIterationsMatch[1];
microIterations = parseInt(microIterationsMatch[2], 10);
}
if (event === markStartEvent) {
inMeasureRange = true;
} else if (event === markEndEvent) {
inMeasureRange = false;
}
if (!inMeasureRange || event['pid'] !== markStartEvent['pid']) {
return;
}
if (this._requestCount && name === 'sendRequest') {
result['requestCount'] += 1;
} else if (this._receivedData && name === 'receivedData' && ph === 'I') {
result['receivedData'] += event['args']['encodedDataLength'];
}
if (ph === 'B' && name === _MARK_NAME_FRAME_CAPUTRE) {
if (frameCaptureStartEvent) {
throw new Error('can capture frames only once per benchmark run');
}
if (!this._captureFrames) {
throw new Error(
'found start event for frame capture, but frame capture was not requested in benchpress');
}
frameCaptureStartEvent = event;
} else if (ph === 'E' && name === _MARK_NAME_FRAME_CAPUTRE) {
if (!frameCaptureStartEvent) {
throw new Error('missing start event for frame capture');
}
frameCaptureEndEvent = event;
}
if (ph === 'I' && frameCaptureStartEvent && !frameCaptureEndEvent && name === 'frame') {
frameTimestamps.push(event['ts']);
if (frameTimestamps.length >= 2) {
frameTimes.push(
frameTimestamps[frameTimestamps.length - 1] -
frameTimestamps[frameTimestamps.length - 2]);
}
}
if (ph === 'B') {
if (!intervalStarts[name]) {
intervalStartCount[name] = 1;
intervalStarts[name] = event;
} else {
intervalStartCount[name]++;
}
} else if ((ph === 'E') && intervalStarts[name]) {
intervalStartCount[name]--;
if (intervalStartCount[name] === 0) {
const startEvent = intervalStarts[name];
const duration = (event['ts'] - startEvent['ts']);
intervalStarts[name] = null;
if (name === 'gc') {
result['gcTime'] += duration;
const amount =
(startEvent['args']['usedHeapSize'] - event['args']['usedHeapSize']) / 1000;
result['gcAmount'] += amount;
const majorGc = event['args']['majorGc'];
if (majorGc && majorGc) {
result['majorGcTime'] += duration;
}
if (intervalStarts['script']) {
gcTimeInScript += duration;
}
} else if (name === 'render') {
result['renderTime'] += duration;
if (intervalStarts['script']) {
renderTimeInScript += duration;
}
} else if (name === 'script') {
result['scriptTime'] += duration;
} else if (this._microMetrics[name]) {
(<any>result)[name] += duration / microIterations;
}
}
}
});
if (frameCaptureStartEvent && !frameCaptureEndEvent) {
throw new Error('missing end event for frame capture');
}
if (this._captureFrames && !frameCaptureStartEvent) {
throw new Error('frame capture requested in benchpress, but no start event was found');
}
if (frameTimes.length > 0) {
this._addFrameMetrics(result, frameTimes);
}
result['pureScriptTime'] = result['scriptTime'] - gcTimeInScript - renderTimeInScript;
return result;
}
private _addFrameMetrics(result: {[key: string]: number}, frameTimes: any[]) {
result['frameTime.mean'] = frameTimes.reduce((a, b) => a + b, 0) / frameTimes.length;
const firstFrame = frameTimes[0];
result['frameTime.worst'] = frameTimes.reduce((a, b) => a > b ? a : b, firstFrame);
result['frameTime.best'] = frameTimes.reduce((a, b) => a < b ? a : b, firstFrame);
result['frameTime.smooth'] =
frameTimes.filter(t => t < _FRAME_TIME_SMOOTH_THRESHOLD).length / frameTimes.length;
}
private _markName(index: number) { return `${_MARK_NAME_PREFIX}${index}`; }
}
const _MICRO_ITERATIONS_REGEX = /(.+)\*(\d+)$/;
const _MAX_RETRY_COUNT = 20;
const _MARK_NAME_PREFIX = 'benchpress';
const _MARK_NAME_FRAME_CAPUTRE = 'frameCapture';
// using 17ms as a somewhat looser threshold, instead of 16.6666ms
const _FRAME_TIME_SMOOTH_THRESHOLD = 17;

View File

@ -0,0 +1,69 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable} from '@angular/core';
import {Options} from '../common_options';
import {Metric} from '../metric';
import {WebDriverAdapter} from '../web_driver_adapter';
@Injectable()
export class UserMetric extends Metric {
static PROVIDERS = [UserMetric];
constructor(
@Inject(Options.USER_METRICS) private _userMetrics: {[key: string]: string},
private _wdAdapter: WebDriverAdapter) {
super();
}
/**
* Starts measuring
*/
beginMeasure(): Promise<any> { return Promise.resolve(true); }
/**
* Ends measuring.
*/
endMeasure(restart: boolean): Promise<{[key: string]: any}> {
let resolve: (result: any) => void;
let reject: (error: any) => void;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
const adapter = this._wdAdapter;
const names = Object.keys(this._userMetrics);
function getAndClearValues() {
Promise.all(names.map(name => adapter.executeScript(`return window.${name}`)))
.then((values: any[]) => {
if (values.every(v => typeof v === 'number')) {
Promise.all(names.map(name => adapter.executeScript(`delete window.${name}`)))
.then((_: any[]) => {
const map: {[k: string]: any} = {};
for (let i = 0, n = names.length; i < n; i++) {
map[names[i]] = values[i];
}
resolve(map);
}, reject);
} else {
<any>setTimeout(getAndClearValues, 100);
}
}, reject);
}
getAndClearValues();
return promise;
}
/**
* Describes the metrics provided by this metric implementation.
* (e.g. units, ...)
*/
describe(): {[key: string]: any} { return this._userMetrics; }
}

View File

@ -1,17 +1,20 @@
import {BaseException, WrappedException} from '@angular/facade';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {MeasureValues} from './measure_values';
/**
* A reporter reports measure values and the valid sample.
*/
export abstract class Reporter {
static bindTo(delegateToken): any[] {
return [{provide: Reporter, useFactory: (delegate) => delegate, deps: [delegateToken]}];
}
reportMeasureValues(values: MeasureValues): Promise<any> { throw new BaseException('NYI'); }
reportMeasureValues(values: MeasureValues): Promise<any> { throw new Error('NYI'); }
reportSample(completeSample: MeasureValues[], validSample: MeasureValues[]): Promise<any> {
throw new BaseException('NYI');
throw new Error('NYI');
}
}

View File

@ -0,0 +1,83 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable, OpaqueToken} from '@angular/core';
import {print} from '../facade/lang';
import {MeasureValues} from '../measure_values';
import {Reporter} from '../reporter';
import {SampleDescription} from '../sample_description';
import {formatNum, formatStats, sortedProps} from './util';
/**
* A reporter for the console
*/
@Injectable()
export class ConsoleReporter extends Reporter {
static PRINT = new OpaqueToken('ConsoleReporter.print');
static COLUMN_WIDTH = new OpaqueToken('ConsoleReporter.columnWidth');
static PROVIDERS = [
ConsoleReporter, {provide: ConsoleReporter.COLUMN_WIDTH, useValue: 18},
{provide: ConsoleReporter.PRINT, useValue: print}
];
private static _lpad(value: string, columnWidth: number, fill = ' ') {
let result = '';
for (let i = 0; i < columnWidth - value.length; i++) {
result += fill;
}
return result + value;
}
private _metricNames: string[];
constructor(
@Inject(ConsoleReporter.COLUMN_WIDTH) private _columnWidth: number,
sampleDescription: SampleDescription,
@Inject(ConsoleReporter.PRINT) private _print: Function) {
super();
this._metricNames = sortedProps(sampleDescription.metrics);
this._printDescription(sampleDescription);
}
private _printDescription(sampleDescription: SampleDescription) {
this._print(`BENCHMARK ${sampleDescription.id}`);
this._print('Description:');
const props = sortedProps(sampleDescription.description);
props.forEach((prop) => { this._print(`- ${prop}: ${sampleDescription.description[prop]}`); });
this._print('Metrics:');
this._metricNames.forEach((metricName) => {
this._print(`- ${metricName}: ${sampleDescription.metrics[metricName]}`);
});
this._print('');
this._printStringRow(this._metricNames);
this._printStringRow(this._metricNames.map((_) => ''), '-');
}
reportMeasureValues(measureValues: MeasureValues): Promise<any> {
const formattedValues = this._metricNames.map(metricName => {
const value = measureValues.values[metricName];
return formatNum(value);
});
this._printStringRow(formattedValues);
return Promise.resolve(null);
}
reportSample(completeSample: MeasureValues[], validSamples: MeasureValues[]): Promise<any> {
this._printStringRow(this._metricNames.map((_) => ''), '=');
this._printStringRow(
this._metricNames.map(metricName => formatStats(validSamples, metricName)));
return Promise.resolve(null);
}
private _printStringRow(parts: any[], fill = ' ') {
this._print(
parts.map(part => ConsoleReporter._lpad(part, this._columnWidth, fill)).join(' | '));
}
}

View File

@ -0,0 +1,52 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable, OpaqueToken} from '@angular/core';
import {Options} from '../common_options';
import {MeasureValues} from '../measure_values';
import {Reporter} from '../reporter';
import {SampleDescription} from '../sample_description';
import {formatStats, sortedProps} from './util';
/**
* A reporter that writes results into a json file.
*/
@Injectable()
export class JsonFileReporter extends Reporter {
static PATH = new OpaqueToken('JsonFileReporter.path');
static PROVIDERS = [JsonFileReporter, {provide: JsonFileReporter.PATH, useValue: '.'}];
constructor(
private _description: SampleDescription, @Inject(JsonFileReporter.PATH) private _path: string,
@Inject(Options.WRITE_FILE) private _writeFile: Function,
@Inject(Options.NOW) private _now: Function) {
super();
}
reportMeasureValues(measureValues: MeasureValues): Promise<any> { return Promise.resolve(null); }
reportSample(completeSample: MeasureValues[], validSample: MeasureValues[]): Promise<any> {
const stats: {[key: string]: string} = {};
sortedProps(this._description.metrics).forEach((metricName) => {
stats[metricName] = formatStats(validSample, metricName);
});
const content = JSON.stringify(
{
'description': this._description,
'stats': stats,
'completeSample': completeSample,
'validSample': validSample,
},
null, 2);
const filePath = `${this._path}/${this._description.id}_${this._now().getTime()}.json`;
return this._writeFile(filePath, content);
}
}

View File

@ -0,0 +1,42 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, OpaqueToken} from '@angular/core';
import {MeasureValues} from '../measure_values';
import {Reporter} from '../reporter';
export class MultiReporter extends Reporter {
static provideWith(childTokens: any[]): any[] {
return [
{
provide: _CHILDREN,
useFactory: (injector: Injector) => childTokens.map(token => injector.get(token)),
deps: [Injector],
},
{
provide: MultiReporter,
useFactory: (children: Reporter[]) => new MultiReporter(children),
deps: [_CHILDREN]
}
];
}
constructor(private _reporters: Reporter[]) { super(); }
reportMeasureValues(values: MeasureValues): Promise<any[]> {
return Promise.all(this._reporters.map(reporter => reporter.reportMeasureValues(values)));
}
reportSample(completeSample: MeasureValues[], validSample: MeasureValues[]): Promise<any[]> {
return Promise.all(
this._reporters.map(reporter => reporter.reportSample(completeSample, validSample)));
}
}
const _CHILDREN = new OpaqueToken('MultiReporter.children');

View File

@ -0,0 +1,28 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {MeasureValues} from '../measure_values';
import {Statistic} from '../statistic';
export function formatNum(n: number) {
return n.toFixed(2);
}
export function sortedProps(obj: {[key: string]: any}) {
return Object.keys(obj).sort();
}
export function formatStats(validSamples: MeasureValues[], metricName: string): string {
const samples = validSamples.map(measureValues => measureValues.values[metricName]);
const mean = Statistic.calculateMean(samples);
const cv = Statistic.calculateCoefficientOfVariation(samples, mean);
const formattedMean = formatNum(mean);
// Note: Don't use the unicode character for +- as it might cause
// hickups for consoles...
return isNaN(cv) ? formattedMean : `${formattedMean}+-${Math.floor(cv)}%`;
}

View File

@ -1,45 +1,52 @@
import {ReflectiveInjector} from '@angular/core';
import {isPresent, isBlank} from '@angular/facade';
import {PromiseWrapper} from '@angular/facade';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Sampler, SampleState} from './sampler';
import {Provider, ReflectiveInjector} from '@angular/core';
import {Options} from './common_options';
import {isPresent} from './facade/lang';
import {Metric} from './metric';
import {MultiMetric} from './metric/multi_metric';
import {PerflogMetric} from './metric/perflog_metric';
import {UserMetric} from './metric/user_metric';
import {Reporter} from './reporter';
import {ConsoleReporter} from './reporter/console_reporter';
import {MultiReporter} from './reporter/multi_reporter';
import {SampleDescription} from './sample_description';
import {SampleState, Sampler} from './sampler';
import {Validator} from './validator';
import {RegressionSlopeValidator} from './validator/regression_slope_validator';
import {SizeValidator} from './validator/size_validator';
import {Validator} from './validator';
import {PerflogMetric} from './metric/perflog_metric';
import {MultiMetric} from './metric/multi_metric';
import {WebDriverAdapter} from './web_driver_adapter';
import {WebDriverExtension} from './web_driver_extension';
import {ChromeDriverExtension} from './webdriver/chrome_driver_extension';
import {FirefoxDriverExtension} from './webdriver/firefox_driver_extension';
import {IOsDriverExtension} from './webdriver/ios_driver_extension';
import {WebDriverExtension} from './web_driver_extension';
import {SampleDescription} from './sample_description';
import {WebDriverAdapter} from './web_driver_adapter';
import {Reporter} from './reporter';
import {Metric} from './metric';
import {Options} from './common_options';
/**
* The Runner is the main entry point for executing a sample run.
* It provides defaults, creates the injector and calls the sampler.
*/
export class Runner {
private _defaultProviders: any[];
constructor(defaultProviders: any[] = null) {
if (isBlank(defaultProviders)) {
defaultProviders = [];
}
this._defaultProviders = defaultProviders;
}
constructor(private _defaultProviders: Provider[] = []) {}
sample({id, execute, prepare, microMetrics, providers}:
{id: string, execute?: any, prepare?: any, microMetrics?: any, providers?: any}):
Promise<SampleState> {
var sampleProviders = [
_DEFAULT_PROVIDERS,
this._defaultProviders,
{provide: Options.SAMPLE_ID, useValue: id},
sample({id, execute, prepare, microMetrics, providers, userMetrics}: {
id: string,
execute?: Function,
prepare?: Function,
microMetrics?: {[key: string]: string},
providers?: Provider[],
userMetrics?: {[key: string]: string}
}): Promise<SampleState> {
const sampleProviders: Provider[] = [
_DEFAULT_PROVIDERS, this._defaultProviders, {provide: Options.SAMPLE_ID, useValue: id},
{provide: Options.EXECUTE, useValue: execute}
];
if (isPresent(prepare)) {
@ -48,38 +55,40 @@ export class Runner {
if (isPresent(microMetrics)) {
sampleProviders.push({provide: Options.MICRO_METRICS, useValue: microMetrics});
}
if (isPresent(userMetrics)) {
sampleProviders.push({provide: Options.USER_METRICS, useValue: userMetrics});
}
if (isPresent(providers)) {
sampleProviders.push(providers);
}
var inj = ReflectiveInjector.resolveAndCreate(sampleProviders);
var adapter = inj.get(WebDriverAdapter);
const inj = ReflectiveInjector.resolveAndCreate(sampleProviders);
const adapter: WebDriverAdapter = inj.get(WebDriverAdapter);
return PromiseWrapper
return Promise
.all([adapter.capabilities(), adapter.executeScript('return window.navigator.userAgent;')])
.then((args) => {
var capabilities = args[0];
var userAgent = args[1];
const capabilities = args[0];
const userAgent = args[1];
// This might still create instances twice. We are creating a new injector with all the
// providers.
// Only WebDriverAdapter is reused.
// TODO vsavkin consider changing it when toAsyncFactory is added back or when child
// injectors are handled better.
var injector = ReflectiveInjector.resolveAndCreate([
sampleProviders,
{provide: Options.CAPABILITIES, useValue: capabilities},
const injector = ReflectiveInjector.resolveAndCreate([
sampleProviders, {provide: Options.CAPABILITIES, useValue: capabilities},
{provide: Options.USER_AGENT, useValue: userAgent},
{provide: WebDriverAdapter, useValue: adapter}
]);
var sampler = injector.get(Sampler);
const sampler = injector.get(Sampler);
return sampler.sample();
});
}
}
var _DEFAULT_PROVIDERS = [
const _DEFAULT_PROVIDERS = [
Options.DEFAULT_PROVIDERS,
Sampler.PROVIDERS,
ConsoleReporter.PROVIDERS,
@ -89,12 +98,13 @@ var _DEFAULT_PROVIDERS = [
FirefoxDriverExtension.PROVIDERS,
IOsDriverExtension.PROVIDERS,
PerflogMetric.PROVIDERS,
UserMetric.PROVIDERS,
SampleDescription.PROVIDERS,
MultiReporter.createBindings([ConsoleReporter]),
MultiMetric.createBindings([PerflogMetric]),
Reporter.bindTo(MultiReporter),
Validator.bindTo(RegressionSlopeValidator),
WebDriverExtension.bindTo([ChromeDriverExtension, FirefoxDriverExtension, IOsDriverExtension]),
Metric.bindTo(MultiMetric),
MultiReporter.provideWith([ConsoleReporter]),
MultiMetric.provideWith([PerflogMetric, UserMetric]),
{provide: Reporter, useExisting: MultiReporter},
{provide: Validator, useExisting: RegressionSlopeValidator},
WebDriverExtension.provideFirstSupported(
[ChromeDriverExtension, FirefoxDriverExtension, IOsDriverExtension]),
{provide: Metric, useExisting: MultiMetric},
];

View File

@ -0,0 +1,49 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from '@angular/core';
import {Options} from './common_options';
import {Metric} from './metric';
import {Validator} from './validator';
/**
* SampleDescription merges all available descriptions about a sample
*/
export class SampleDescription {
static PROVIDERS = [{
provide: SampleDescription,
useFactory:
(metric: Metric, id: string, forceGc: boolean, userAgent: string, validator: Validator,
defaultDesc: {[key: string]: string}, userDesc: {[key: string]: string}) =>
new SampleDescription(
id,
[
{'forceGc': forceGc, 'userAgent': userAgent}, validator.describe(), defaultDesc,
userDesc
],
metric.describe()),
deps: [
Metric, Options.SAMPLE_ID, Options.FORCE_GC, Options.USER_AGENT, Validator,
Options.DEFAULT_DESCRIPTION, Options.SAMPLE_DESCRIPTION
]
}];
description: {[key: string]: any};
constructor(
public id: string, descriptions: Array<{[key: string]: any}>,
public metrics: {[key: string]: any}) {
this.description = {};
descriptions.forEach(description => {
Object.keys(description).forEach(prop => { this.description[prop] = description[prop]; });
});
}
toJson() { return {'id': this.id, 'description': this.description, 'metrics': this.metrics}; }
}

View File

@ -0,0 +1,81 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable} from '@angular/core';
import {Options} from './common_options';
import {isPresent} from './facade/lang';
import {MeasureValues} from './measure_values';
import {Metric} from './metric';
import {Reporter} from './reporter';
import {Validator} from './validator';
import {WebDriverAdapter} from './web_driver_adapter';
/**
* The Sampler owns the sample loop:
* 1. calls the prepare/execute callbacks,
* 2. gets data from the metric
* 3. asks the validator for a valid sample
* 4. reports the new data to the reporter
* 5. loop until there is a valid sample
*/
@Injectable()
export class Sampler {
static PROVIDERS = [Sampler];
constructor(
private _driver: WebDriverAdapter, private _metric: Metric, private _reporter: Reporter,
private _validator: Validator, @Inject(Options.PREPARE) private _prepare: Function,
@Inject(Options.EXECUTE) private _execute: Function,
@Inject(Options.NOW) private _now: Function) {}
sample(): Promise<SampleState> {
const loop = (lastState: SampleState): Promise<SampleState> => {
return this._iterate(lastState).then((newState) => {
if (isPresent(newState.validSample)) {
return newState;
} else {
return loop(newState);
}
});
};
return loop(new SampleState([], null));
}
private _iterate(lastState: SampleState): Promise<SampleState> {
let resultPromise: Promise<SampleState>;
if (this._prepare !== Options.NO_PREPARE) {
resultPromise = this._driver.waitFor(this._prepare);
} else {
resultPromise = Promise.resolve(null);
}
if (this._prepare !== Options.NO_PREPARE || lastState.completeSample.length === 0) {
resultPromise = resultPromise.then((_) => this._metric.beginMeasure());
}
return resultPromise.then((_) => this._driver.waitFor(this._execute))
.then((_) => this._metric.endMeasure(this._prepare === Options.NO_PREPARE))
.then((measureValues) => this._report(lastState, measureValues));
}
private _report(state: SampleState, metricValues: {[key: string]: any}): Promise<SampleState> {
const measureValues = new MeasureValues(state.completeSample.length, this._now(), metricValues);
const completeSample = state.completeSample.concat([measureValues]);
const validSample = this._validator.validate(completeSample);
let resultPromise = this._reporter.reportMeasureValues(measureValues);
if (isPresent(validSample)) {
resultPromise =
resultPromise.then((_) => this._reporter.reportSample(completeSample, validSample));
}
return resultPromise.then((_) => new SampleState(completeSample, validSample));
}
}
export class SampleState {
constructor(public completeSample: MeasureValues[], public validSample: MeasureValues[]) {}
}

View File

@ -1,19 +1,25 @@
import {Math} from '@angular/facade';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
export class Statistic {
static calculateCoefficientOfVariation(sample, mean) {
static calculateCoefficientOfVariation(sample: number[], mean: number) {
return Statistic.calculateStandardDeviation(sample, mean) / mean * 100;
}
static calculateMean(samples: number[]) {
var total = 0;
let total = 0;
// TODO: use reduce
samples.forEach(x => total += x);
return total / samples.length;
}
static calculateStandardDeviation(samples: number[], mean) {
var deviation = 0;
static calculateStandardDeviation(samples: number[], mean: number) {
let deviation = 0;
// TODO: use reduce
samples.forEach(x => deviation += Math.pow(x - mean, 2));
deviation = deviation / (samples.length);
@ -21,12 +27,12 @@ export class Statistic {
return deviation;
}
static calculateRegressionSlope(xValues: number[], xMean: number, yValues: number[],
yMean: number) {
static calculateRegressionSlope(
xValues: number[], xMean: number, yValues: number[], yMean: number) {
// See http://en.wikipedia.org/wiki/Simple_linear_regression
var dividendSum = 0;
var divisorSum = 0;
for (var i = 0; i < xValues.length; i++) {
let dividendSum = 0;
let divisorSum = 0;
for (let i = 0; i < xValues.length; i++) {
dividendSum += (xValues[i] - xMean) * (yValues[i] - yMean);
divisorSum += Math.pow(xValues[i] - xMean, 2);
}

View File

@ -1,4 +1,10 @@
import {BaseException, WrappedException} from '@angular/facade';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {MeasureValues} from './measure_values';
@ -8,18 +14,14 @@ import {MeasureValues} from './measure_values';
* in the correct way.
*/
export abstract class Validator {
static bindTo(delegateToken): any[] {
return [{provide: Validator, useFactory: (delegate) => delegate, deps: [delegateToken]}];
}
/**
* Calculates a valid sample out of the complete sample
*/
validate(completeSample: MeasureValues[]): MeasureValues[] { throw new BaseException('NYI'); }
validate(completeSample: MeasureValues[]): MeasureValues[] { throw new Error('NYI'); }
/**
* Returns a Map that describes the properties of the validator
* (e.g. sample size, ...)
*/
describe(): {[key: string]: any} { throw new BaseException('NYI'); }
describe(): {[key: string]: any} { throw new Error('NYI'); }
}

View File

@ -0,0 +1,57 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable, OpaqueToken} from '@angular/core';
import {MeasureValues} from '../measure_values';
import {Statistic} from '../statistic';
import {Validator} from '../validator';
/**
* A validator that checks the regression slope of a specific metric.
* Waits for the regression slope to be >=0.
*/
@Injectable()
export class RegressionSlopeValidator extends Validator {
static SAMPLE_SIZE = new OpaqueToken('RegressionSlopeValidator.sampleSize');
static METRIC = new OpaqueToken('RegressionSlopeValidator.metric');
static PROVIDERS = [
RegressionSlopeValidator, {provide: RegressionSlopeValidator.SAMPLE_SIZE, useValue: 10},
{provide: RegressionSlopeValidator.METRIC, useValue: 'scriptTime'}
];
constructor(
@Inject(RegressionSlopeValidator.SAMPLE_SIZE) private _sampleSize: number,
@Inject(RegressionSlopeValidator.METRIC) private _metric: string) {
super();
}
describe(): {[key: string]: any} {
return {'sampleSize': this._sampleSize, 'regressionSlopeMetric': this._metric};
}
validate(completeSample: MeasureValues[]): MeasureValues[] {
if (completeSample.length >= this._sampleSize) {
const latestSample =
completeSample.slice(completeSample.length - this._sampleSize, completeSample.length);
const xValues: number[] = [];
const yValues: number[] = [];
for (let i = 0; i < latestSample.length; i++) {
// For now, we only use the array index as x value.
// TODO(tbosch): think about whether we should use time here instead
xValues.push(i);
yValues.push(latestSample[i].values[this._metric]);
}
const regressionSlope = Statistic.calculateRegressionSlope(
xValues, Statistic.calculateMean(xValues), yValues, Statistic.calculateMean(yValues));
return regressionSlope >= 0 ? latestSample : null;
} else {
return null;
}
}
}

View File

@ -0,0 +1,33 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable, OpaqueToken} from '@angular/core';
import {MeasureValues} from '../measure_values';
import {Validator} from '../validator';
/**
* A validator that waits for the sample to have a certain size.
*/
@Injectable()
export class SizeValidator extends Validator {
static SAMPLE_SIZE = new OpaqueToken('SizeValidator.sampleSize');
static PROVIDERS = [SizeValidator, {provide: SizeValidator.SAMPLE_SIZE, useValue: 10}];
constructor(@Inject(SizeValidator.SAMPLE_SIZE) private _sampleSize: number) { super(); }
describe(): {[key: string]: any} { return {'sampleSize': this._sampleSize}; }
validate(completeSample: MeasureValues[]): MeasureValues[] {
if (completeSample.length >= this._sampleSize) {
return completeSample.slice(completeSample.length - this._sampleSize, completeSample.length);
} else {
return null;
}
}
}

View File

@ -0,0 +1,22 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* A WebDriverAdapter bridges API differences between different WebDriver clients,
* e.g. JS vs Dart Async vs Dart Sync webdriver.
* Needs one implementation for every supported WebDriver client.
*/
export abstract class WebDriverAdapter {
waitFor(callback: Function): Promise<any> { throw new Error('NYI'); }
executeScript(script: string): Promise<any> { throw new Error('NYI'); }
executeAsyncScript(script: string): Promise<any> { throw new Error('NYI'); }
capabilities(): Promise<{[key: string]: any}> { throw new Error('NYI'); }
logs(type: string): Promise<any[]> { throw new Error('NYI'); }
}

View File

@ -1,18 +1,40 @@
import {Injector, OpaqueToken} from '@angular/core/src/di';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {isBlank, isPresent} from '@angular/facade';
import {BaseException, WrappedException} from '@angular/facade';
import {Injector, OpaqueToken} from '@angular/core';
import {Options} from './common_options';
export type PerfLogEvent = {
[key: string]: any
} & {
ph?: 'X' | 'B' | 'E' | 'I',
ts?: number,
dur?: number,
name?: string,
pid?: string,
args?: {
encodedDataLength?: number,
usedHeapSize?: number,
majorGc?: boolean,
url?: string,
method?: string
}
};
/**
* A WebDriverExtension implements extended commands of the webdriver protocol
* for a given browser, independent of the WebDriverAdapter.
* Needs one implementation for every supported Browser.
*/
export abstract class WebDriverExtension {
static bindTo(childTokens: any[]): any[] {
var res = [
static provideFirstSupported(childTokens: any[]): any[] {
const res = [
{
provide: _CHILDREN,
useFactory: (injector: Injector) => childTokens.map(token => injector.get(token)),
@ -20,15 +42,15 @@ export abstract class WebDriverExtension {
},
{
provide: WebDriverExtension,
useFactory: (children:WebDriverExtension[], capabilities) => {
var delegate;
useFactory: (children: WebDriverExtension[], capabilities: {[key: string]: any}) => {
let delegate: WebDriverExtension;
children.forEach(extension => {
if (extension.supports(capabilities)) {
delegate = extension;
}
});
if (isBlank(delegate)) {
throw new BaseException('Could not find a delegate for given capabilities!');
if (!delegate) {
throw new Error('Could not find a delegate for given capabilities!');
}
return delegate;
},
@ -38,18 +60,17 @@ export abstract class WebDriverExtension {
return res;
}
gc(): Promise<any> { throw new BaseException('NYI'); }
gc(): Promise<any> { throw new Error('NYI'); }
timeBegin(name: string): Promise<any> { throw new BaseException('NYI'); }
timeBegin(name: string): Promise<any> { throw new Error('NYI'); }
timeEnd(name: string, restartName: string): Promise<any> { throw new BaseException('NYI'); }
timeEnd(name: string, restartName: string): Promise<any> { throw new Error('NYI'); }
/**
* Format:
* - cat: category of the event
* - name: event name: 'script', 'gc', 'render', ...
* - ph: phase: 'B' (begin), 'E' (end), 'b' (nestable start), 'e' (nestable end), 'X' (Complete
*event)
* - ph: phase: 'B' (begin), 'E' (end), 'X' (Complete event), 'I' (Instant event)
* - ts: timestamp in ms, e.g. 12345
* - pid: process id
* - args: arguments, e.g. {heapSize: 1234}
@ -57,9 +78,9 @@ export abstract class WebDriverExtension {
* Based on [Chrome Trace Event
*Format](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit)
**/
readPerfLog(): Promise<any[]> { throw new BaseException('NYI'); }
readPerfLog(): Promise<PerfLogEvent[]> { throw new Error('NYI'); }
perfLogFeatures(): PerfLogFeatures { throw new BaseException('NYI'); }
perfLogFeatures(): PerfLogFeatures { throw new Error('NYI'); }
supports(capabilities: {[key: string]: any}): boolean { return true; }
}
@ -80,4 +101,4 @@ export class PerfLogFeatures {
}
}
var _CHILDREN = new OpaqueToken('WebDriverExtension.children');
const _CHILDREN = new OpaqueToken('WebDriverExtension.children');

View File

@ -0,0 +1,208 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable} from '@angular/core';
import {Options} from '../common_options';
import {WebDriverAdapter} from '../web_driver_adapter';
import {PerfLogEvent, PerfLogFeatures, WebDriverExtension} from '../web_driver_extension';
/**
* Set the following 'traceCategories' to collect metrics in Chrome:
* 'v8,blink.console,disabled-by-default-devtools.timeline,devtools.timeline,blink.user_timing'
*
* In order to collect the frame rate related metrics, add 'benchmark'
* to the list above.
*/
@Injectable()
export class ChromeDriverExtension extends WebDriverExtension {
static PROVIDERS = [ChromeDriverExtension];
private _majorChromeVersion: number;
constructor(private _driver: WebDriverAdapter, @Inject(Options.USER_AGENT) userAgent: string) {
super();
this._majorChromeVersion = this._parseChromeVersion(userAgent);
}
private _parseChromeVersion(userAgent: string): number {
if (!userAgent) {
return -1;
}
let v = userAgent.split(/Chrom(e|ium)\//g)[2];
if (!v) {
return -1;
}
v = v.split('.')[0];
if (!v) {
return -1;
}
return parseInt(v, 10);
}
gc() { return this._driver.executeScript('window.gc()'); }
timeBegin(name: string): Promise<any> {
return this._driver.executeScript(`console.time('${name}');`);
}
timeEnd(name: string, restartName: string = null): Promise<any> {
let script = `console.timeEnd('${name}');`;
if (restartName) {
script += `console.time('${restartName}');`;
}
return this._driver.executeScript(script);
}
// See [Chrome Trace Event
// Format](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit)
readPerfLog(): Promise<PerfLogEvent[]> {
// TODO(tbosch): Chromedriver bug https://code.google.com/p/chromedriver/issues/detail?id=1098
// Need to execute at least one command so that the browser logs can be read out!
return this._driver.executeScript('1+1')
.then((_) => this._driver.logs('performance'))
.then((entries) => {
const events: PerfLogEvent[] = [];
entries.forEach(entry => {
const message = JSON.parse(entry['message'])['message'];
if (message['method'] === 'Tracing.dataCollected') {
events.push(message['params']);
}
if (message['method'] === 'Tracing.bufferUsage') {
throw new Error('The DevTools trace buffer filled during the test!');
}
});
return this._convertPerfRecordsToEvents(events);
});
}
private _convertPerfRecordsToEvents(
chromeEvents: Array<{[key: string]: any}>, normalizedEvents: PerfLogEvent[] = null) {
if (!normalizedEvents) {
normalizedEvents = [];
}
chromeEvents.forEach((event) => {
const categories = this._parseCategories(event['cat']);
const normalizedEvent = this._convertEvent(event, categories);
if (normalizedEvent != null) normalizedEvents.push(normalizedEvent);
});
return normalizedEvents;
}
private _convertEvent(event: {[key: string]: any}, categories: string[]) {
const name = event['name'];
const args = event['args'];
if (this._isEvent(categories, name, ['blink.console'])) {
return normalizeEvent(event, {'name': name});
} else if (this._isEvent(
categories, name, ['benchmark'],
'BenchmarkInstrumentation::ImplThreadRenderingStats')) {
// TODO(goderbauer): Instead of BenchmarkInstrumentation::ImplThreadRenderingStats the
// following events should be used (if available) for more accurate measurments:
// 1st choice: vsync_before - ground truth on Android
// 2nd choice: BenchmarkInstrumentation::DisplayRenderingStats - available on systems with
// new surfaces framework (not broadly enabled yet)
// 3rd choice: BenchmarkInstrumentation::ImplThreadRenderingStats - fallback event that is
// always available if something is rendered
const frameCount = event['args']['data']['frame_count'];
if (frameCount > 1) {
throw new Error('multi-frame render stats not supported');
}
if (frameCount == 1) {
return normalizeEvent(event, {'name': 'frame'});
}
} else if (
this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], 'Rasterize') ||
this._isEvent(
categories, name, ['disabled-by-default-devtools.timeline'], 'CompositeLayers')) {
return normalizeEvent(event, {'name': 'render'});
} else if (this._isEvent(categories, name, ['devtools.timeline', 'v8'], 'MajorGC')) {
const normArgs = {
'majorGc': true,
'usedHeapSize': args['usedHeapSizeAfter'] !== undefined ? args['usedHeapSizeAfter'] :
args['usedHeapSizeBefore']
};
return normalizeEvent(event, {'name': 'gc', 'args': normArgs});
} else if (this._isEvent(categories, name, ['devtools.timeline', 'v8'], 'MinorGC')) {
const normArgs = {
'majorGc': false,
'usedHeapSize': args['usedHeapSizeAfter'] !== undefined ? args['usedHeapSizeAfter'] :
args['usedHeapSizeBefore']
};
return normalizeEvent(event, {'name': 'gc', 'args': normArgs});
} else if (
this._isEvent(categories, name, ['devtools.timeline'], 'FunctionCall') &&
(!args || !args['data'] ||
(args['data']['scriptName'] !== 'InjectedScript' && args['data']['scriptName'] !== ''))) {
return normalizeEvent(event, {'name': 'script'});
} else if (this._isEvent(categories, name, ['devtools.timeline'], 'EvaluateScript')) {
return normalizeEvent(event, {'name': 'script'});
} else if (this._isEvent(
categories, name, ['devtools.timeline', 'blink'], 'UpdateLayoutTree')) {
return normalizeEvent(event, {'name': 'render'});
} else if (
this._isEvent(categories, name, ['devtools.timeline'], 'UpdateLayerTree') ||
this._isEvent(categories, name, ['devtools.timeline'], 'Layout') ||
this._isEvent(categories, name, ['devtools.timeline'], 'Paint')) {
return normalizeEvent(event, {'name': 'render'});
} else if (this._isEvent(categories, name, ['devtools.timeline'], 'ResourceReceivedData')) {
const normArgs = {'encodedDataLength': args['data']['encodedDataLength']};
return normalizeEvent(event, {'name': 'receivedData', 'args': normArgs});
} else if (this._isEvent(categories, name, ['devtools.timeline'], 'ResourceSendRequest')) {
const data = args['data'];
const normArgs = {'url': data['url'], 'method': data['requestMethod']};
return normalizeEvent(event, {'name': 'sendRequest', 'args': normArgs});
} else if (this._isEvent(categories, name, ['blink.user_timing'], 'navigationStart')) {
return normalizeEvent(event, {'name': 'navigationStart'});
}
return null; // nothing useful in this event
}
private _parseCategories(categories: string): string[] { return categories.split(','); }
private _isEvent(
eventCategories: string[], eventName: string, expectedCategories: string[],
expectedName: string = null): boolean {
const hasCategories = expectedCategories.reduce(
(value, cat) => value && eventCategories.indexOf(cat) !== -1, true);
return !expectedName ? hasCategories : hasCategories && eventName === expectedName;
}
perfLogFeatures(): PerfLogFeatures {
return new PerfLogFeatures({render: true, gc: true, frameCapture: true, userTiming: true});
}
supports(capabilities: {[key: string]: any}): boolean {
return this._majorChromeVersion >= 44 && capabilities['browserName'].toLowerCase() === 'chrome';
}
}
function normalizeEvent(chromeEvent: {[key: string]: any}, data: PerfLogEvent): PerfLogEvent {
let ph = chromeEvent['ph'].toUpperCase();
if (ph === 'S') {
ph = 'B';
} else if (ph === 'F') {
ph = 'E';
} else if (ph === 'R') {
// mark events from navigation timing
ph = 'I';
}
const result: {[key: string]: any} =
{'pid': chromeEvent['pid'], 'ph': ph, 'cat': 'timeline', 'ts': chromeEvent['ts'] / 1000};
if (ph === 'X') {
let dur = chromeEvent['dur'];
if (dur === undefined) {
dur = chromeEvent['tdur'];
}
result['dur'] = !dur ? 0.0 : dur / 1000;
}
for (const prop in data) {
result[prop] = data[prop];
}
return result;
}

View File

@ -1,9 +1,20 @@
import {isPresent, StringWrapper} from '@angular/facade';
import {WebDriverExtension, PerfLogFeatures} from '../web_driver_extension';
import {WebDriverAdapter} from '../web_driver_adapter';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Injectable} from '@angular/core';
import {isPresent} from '../facade/lang';
import {WebDriverAdapter} from '../web_driver_adapter';
import {PerfLogEvent, PerfLogFeatures, WebDriverExtension} from '../web_driver_extension';
@Injectable()
export class FirefoxDriverExtension extends WebDriverExtension {
static get PROVIDERS(): any[] { return _PROVIDERS; }
static PROVIDERS = [FirefoxDriverExtension];
private _profilerStarted: boolean;
@ -23,28 +34,20 @@ export class FirefoxDriverExtension extends WebDriverExtension {
}
timeEnd(name: string, restartName: string = null): Promise<any> {
var script = 'window.markEnd("' + name + '");';
let script = 'window.markEnd("' + name + '");';
if (isPresent(restartName)) {
script += 'window.markStart("' + restartName + '");';
}
return this._driver.executeScript(script);
}
readPerfLog(): Promise<any> {
readPerfLog(): Promise<PerfLogEvent> {
return this._driver.executeAsyncScript('var cb = arguments[0]; window.getProfile(cb);');
}
perfLogFeatures(): PerfLogFeatures { return new PerfLogFeatures({render: true, gc: true}); }
supports(capabilities: {[key: string]: any}): boolean {
return StringWrapper.equals(capabilities['browserName'].toLowerCase(), 'firefox');
return capabilities['browserName'].toLowerCase() === 'firefox';
}
}
var _PROVIDERS = [
{
provide: FirefoxDriverExtension,
useFactory: (driver) => new FirefoxDriverExtension(driver),
deps: [WebDriverAdapter]
}
];

View File

@ -1,25 +1,33 @@
import {Json, isPresent, isBlank, RegExpWrapper, StringWrapper} from '@angular/facade';
import {BaseException, WrappedException} from '@angular/facade';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {WebDriverExtension, PerfLogFeatures} from '../web_driver_extension';
import {Injectable} from '@angular/core';
import {isBlank, isPresent} from '../facade/lang';
import {WebDriverAdapter} from '../web_driver_adapter';
import {PerfLogEvent, PerfLogFeatures, WebDriverExtension} from '../web_driver_extension';
@Injectable()
export class IOsDriverExtension extends WebDriverExtension {
// TODO(tbosch): use static values when our transpiler supports them
static get PROVIDERS(): any[] { return _PROVIDERS; }
static PROVIDERS = [IOsDriverExtension];
constructor(private _driver: WebDriverAdapter) { super(); }
gc(): Promise<any> { throw new BaseException('Force GC is not supported on iOS'); }
gc(): Promise<any> { throw new Error('Force GC is not supported on iOS'); }
timeBegin(name: string): Promise<any> {
return this._driver.executeScript(`console.time('${name}');`);
}
timeEnd(name: string, restartName: string = null): Promise<any> {
var script = `console.timeEnd('${name}');`;
let script = `console.timeEnd('${name}');`;
if (isPresent(restartName)) {
script += `console.time('${restartName}');`
script += `console.time('${restartName}');`;
}
return this._driver.executeScript(script);
}
@ -31,10 +39,10 @@ export class IOsDriverExtension extends WebDriverExtension {
return this._driver.executeScript('1+1')
.then((_) => this._driver.logs('performance'))
.then((entries) => {
var records = [];
const records: any[] = [];
entries.forEach(entry => {
var message = Json.parse(entry['message'])['message'];
if (StringWrapper.equals(message['method'], 'Timeline.eventRecorded')) {
const message = JSON.parse(entry['message'])['message'];
if (message['method'] === 'Timeline.eventRecorded') {
records.push(message['params']['record']);
}
});
@ -42,30 +50,28 @@ export class IOsDriverExtension extends WebDriverExtension {
});
}
_convertPerfRecordsToEvents(records: any[], events: any[] = null) {
if (isBlank(events)) {
/** @internal */
private _convertPerfRecordsToEvents(records: any[], events: PerfLogEvent[] = null) {
if (!events) {
events = [];
}
records.forEach((record) => {
var endEvent = null;
var type = record['type'];
var data = record['data'];
var startTime = record['startTime'];
var endTime = record['endTime'];
let endEvent: PerfLogEvent = null;
const type = record['type'];
const data = record['data'];
const startTime = record['startTime'];
const endTime = record['endTime'];
if (StringWrapper.equals(type, 'FunctionCall') &&
(isBlank(data) || !StringWrapper.equals(data['scriptName'], 'InjectedScript'))) {
if (type === 'FunctionCall' && (data == null || data['scriptName'] !== 'InjectedScript')) {
events.push(createStartEvent('script', startTime));
endEvent = createEndEvent('script', endTime);
} else if (StringWrapper.equals(type, 'Time')) {
} else if (type === 'Time') {
events.push(createMarkStartEvent(data['message'], startTime));
} else if (StringWrapper.equals(type, 'TimeEnd')) {
} else if (type === 'TimeEnd') {
events.push(createMarkEndEvent(data['message'], startTime));
} else if (StringWrapper.equals(type, 'RecalculateStyles') ||
StringWrapper.equals(type, 'Layout') ||
StringWrapper.equals(type, 'UpdateLayerTree') ||
StringWrapper.equals(type, 'Paint') || StringWrapper.equals(type, 'Rasterize') ||
StringWrapper.equals(type, 'CompositeLayers')) {
} else if (
type === 'RecalculateStyles' || type === 'Layout' || type === 'UpdateLayerTree' ||
type === 'Paint' || type === 'Rasterize' || type === 'CompositeLayers') {
events.push(createStartEvent('render', startTime));
endEvent = createEndEvent('render', endTime);
}
@ -83,12 +89,13 @@ export class IOsDriverExtension extends WebDriverExtension {
perfLogFeatures(): PerfLogFeatures { return new PerfLogFeatures({render: true}); }
supports(capabilities: {[key: string]: any}): boolean {
return StringWrapper.equals(capabilities['browserName'].toLowerCase(), 'safari');
return capabilities['browserName'].toLowerCase() === 'safari';
}
}
function createEvent(ph, name, time, args = null) {
var result = {
function createEvent(
ph: 'X' | 'B' | 'E' | 'B' | 'E', name: string, time: number, args: any = null) {
const result: PerfLogEvent = {
'cat': 'timeline',
'name': name,
'ts': time,
@ -103,22 +110,18 @@ function createEvent(ph, name, time, args = null) {
return result;
}
function createStartEvent(name, time, args = null) {
function createStartEvent(name: string, time: number, args: any = null) {
return createEvent('B', name, time, args);
}
function createEndEvent(name, time, args = null) {
function createEndEvent(name: string, time: number, args: any = null) {
return createEvent('E', name, time, args);
}
function createMarkStartEvent(name, time) {
return createEvent('b', name, time);
function createMarkStartEvent(name: string, time: number) {
return createEvent('B', name, time);
}
function createMarkEndEvent(name, time) {
return createEvent('e', name, time);
function createMarkEndEvent(name: string, time: number) {
return createEvent('E', name, time);
}
var _PROVIDERS = [
{provide: IOsDriverExtension, useFactory: (driver) => new IOsDriverExtension(driver), deps: [WebDriverAdapter]}
];

View File

@ -0,0 +1,70 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {WebDriverAdapter} from '../web_driver_adapter';
/**
* Adapter for the selenium-webdriver.
*/
export class SeleniumWebDriverAdapter extends WebDriverAdapter {
static PROTRACTOR_PROVIDERS = [{
provide: WebDriverAdapter,
useFactory: () => new SeleniumWebDriverAdapter((<any>global).browser)
}];
constructor(private _driver: any) { super(); }
waitFor(callback: () => any): Promise<any> { return this._driver.call(callback); }
executeScript(script: string): Promise<any> { return this._driver.executeScript(script); }
executeAsyncScript(script: string): Promise<any> {
return this._driver.executeAsyncScript(script);
}
capabilities(): Promise<{[key: string]: any}> {
return this._driver.getCapabilities().then((capsObject: any) => {
const localData: {[key: string]: any} = {};
capsObject.forEach((value: any, key: string) => { localData[key] = value; });
return localData;
});
}
logs(type: string): Promise<any> {
// Needed as selenium-webdriver does not forward
// performance logs in the correct way via manage().logs
return this._driver.schedule(
new Command('getLog').setParameter('type', type),
'WebDriver.manage().logs().get(' + type + ')');
}
}
/**
* Copy of the `Command` class of webdriver as
* it is not exposed via index.js in selenium-webdriver.
*/
class Command {
private parameters_: {[key: string]: any} = {};
constructor(private name_: string) {}
getName() { return this.name_; }
setParameter(name: string, value: any) {
this.parameters_[name] = value;
return this;
}
setParameters(parameters: {[key: string]: any}) {
this.parameters_ = parameters;
return this;
}
getParameter(key: string) { return this.parameters_[key]; }
getParameters() { return this.parameters_; }
}

View File

@ -0,0 +1,21 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
require('core-js');
require('reflect-metadata');
const testHelper = require('../../src/firefox_extension/lib/test_helper.js');
exports.config = {
specs: ['spec.js', 'sample_benchmark.js'],
framework: 'jasmine2',
jasmineNodeOpts: {showColors: true, defaultTimeoutInterval: 1200000},
getMultiCapabilities: function() { return testHelper.getFirefoxProfileWithExtension(); }
};

View File

@ -0,0 +1,100 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {convertPerfProfileToEvents} from '../../src/firefox_extension/lib/parser_util';
function assertEventsEqual(actualEvents: any[], expectedEvents: any[]) {
expect(actualEvents.length == expectedEvents.length);
for (let i = 0; i < actualEvents.length; ++i) {
const actualEvent = actualEvents[i];
const expectedEvent = expectedEvents[i];
for (const key in actualEvent) {
expect(actualEvent[key]).toEqual(expectedEvent[key]);
}
}
};
export function main() {
describe('convertPerfProfileToEvents', function() {
it('should convert single instantaneous event', function() {
const profileData = {
threads: [
{samples: [{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}]}
]
};
const perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(perfEvents, [{ph: 'X', ts: 1, name: 'script'}]);
});
it('should convert single non-instantaneous event', function() {
const profileData = {
threads: [{
samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 100, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}
]
}]
};
const perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(
perfEvents, [{ph: 'B', ts: 1, name: 'script'}, {ph: 'E', ts: 100, name: 'script'}]);
});
it('should convert multiple instantaneous events', function() {
const profileData = {
threads: [{
samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'PresShell::Paint'}]}
]
}]
};
const perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(
perfEvents, [{ph: 'X', ts: 1, name: 'script'}, {ph: 'X', ts: 2, name: 'render'}]);
});
it('should convert multiple mixed events', function() {
const profileData = {
threads: [{
samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'PresShell::Paint'}]},
{time: 5, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 10, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}
]
}]
};
const perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(perfEvents, [
{ph: 'X', ts: 1, name: 'script'}, {ph: 'X', ts: 2, name: 'render'},
{ph: 'B', ts: 5, name: 'script'}, {ph: 'E', ts: 10, name: 'script'}
]);
});
it('should add args to gc events', function() {
const profileData = {threads: [{samples: [{time: 1, frames: [{location: 'forceGC'}]}]}]};
const perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(perfEvents, [{ph: 'X', ts: 1, name: 'gc', args: {usedHeapSize: 0}}]);
});
it('should skip unknown events', function() {
const profileData = {
threads: [{
samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'foo'}]}
]
}]
};
const perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(perfEvents, [{ph: 'X', ts: 1, name: 'script'}]);
});
});
};

View File

@ -1,7 +1,17 @@
var benchpress = require('../../index.js');
var runner = new benchpress.Runner([
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {$, browser} from 'protractor';
const benchpress = require('../../index.js');
const runner = new benchpress.Runner([
// use protractor as Webdriver client
benchpress.SeleniumWebDriverAdapter.PROTRACTOR_BINDINGS,
benchpress.SeleniumWebDriverAdapter.PROTRACTOR_PROVIDERS,
// use RegressionSlopeValidator to validate samples
benchpress.Validator.bindTo(benchpress.RegressionSlopeValidator),
// use 10 samples to calculate slope regression
@ -21,12 +31,12 @@ describe('deep tree baseline', function() {
* Benchpress will log the collected metrics after each sample is collected, and will stop
* sampling as soon as the calculated regression slope for last 20 samples is stable.
*/
runner.sample({
id: 'baseline',
execute: function() { $('button')
.click(); },
providers: [benchpress.bind(benchpress.Options.SAMPLE_DESCRIPTION).toValue({depth: 9})]
})
runner
.sample({
id: 'baseline',
execute: function() { $('button').click(); },
providers: [benchpress.bind(benchpress.Options.SAMPLE_DESCRIPTION).toValue({depth: 9})]
})
.then(done, done.fail);
});
});

View File

@ -0,0 +1,44 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/* tslint:disable:no-console */
import {browser} from 'protractor';
const assertEventsContainsName = function(events: any[], eventName: string) {
let found = false;
for (let i = 0; i < events.length; ++i) {
if (events[i].name == eventName) {
found = true;
break;
}
}
expect(found).toBeTruthy();
};
describe('firefox extension', function() {
const TEST_URL = 'http://localhost:8001/playground/src/hello_world/index.html';
it('should measure performance', function() {
browser.sleep(3000); // wait for extension to load
browser.driver.get(TEST_URL);
browser.executeScript('window.startProfiler()').then(function() {
console.log('started measuring perf');
});
browser.executeAsyncScript('setTimeout(arguments[0], 1000);');
browser.executeScript('window.forceGC()');
browser.executeAsyncScript('var cb = arguments[0]; window.getProfile(cb);')
.then(function(profile: any) {
assertEventsContainsName(profile, 'gc');
assertEventsContainsName(profile, 'script');
});
});
});

View File

@ -0,0 +1,69 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AsyncTestCompleter, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
import {Metric, MultiMetric, ReflectiveInjector} from '../../index';
export function main() {
function createMetric(ids: any[]) {
const m = ReflectiveInjector
.resolveAndCreate([
ids.map(id => ({provide: id, useValue: new MockMetric(id)})),
MultiMetric.provideWith(ids)
])
.get(MultiMetric);
return Promise.resolve(m);
}
describe('multi metric', () => {
it('should merge descriptions', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createMetric(['m1', 'm2']).then((m) => {
expect(m.describe()).toEqual({'m1': 'describe', 'm2': 'describe'});
async.done();
});
}));
it('should merge all beginMeasure calls',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createMetric(['m1', 'm2']).then((m) => m.beginMeasure()).then((values) => {
expect(values).toEqual(['m1_beginMeasure', 'm2_beginMeasure']);
async.done();
});
}));
[false, true].forEach((restartFlag) => {
it(`should merge all endMeasure calls for restart=${restartFlag}`,
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createMetric(['m1', 'm2']).then((m) => m.endMeasure(restartFlag)).then((values) => {
expect(values).toEqual(
{'m1': {'restart': restartFlag}, 'm2': {'restart': restartFlag}});
async.done();
});
}));
});
});
}
class MockMetric extends Metric {
constructor(private _id: string) { super(); }
beginMeasure(): Promise<string> { return Promise.resolve(`${this._id}_beginMeasure`); }
endMeasure(restart: boolean): Promise<{[key: string]: any}> {
const result: {[key: string]: any} = {};
result[this._id] = {'restart': restart};
return Promise.resolve(result);
}
describe(): {[key: string]: string} {
const result: {[key: string]: string} = {};
result[this._id] = 'describe';
return result;
}
}

View File

@ -0,0 +1,700 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Provider} from '@angular/core';
import {AsyncTestCompleter, beforeEach, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
import {Metric, Options, PerfLogEvent, PerfLogFeatures, PerflogMetric, ReflectiveInjector, WebDriverExtension} from '../../index';
import {isPresent} from '../../src/facade/lang';
import {TraceEventFactory} from '../trace_event_factory';
export function main() {
let commandLog: any[];
const eventFactory = new TraceEventFactory('timeline', 'pid0');
function createMetric(
perfLogs: PerfLogEvent[], perfLogFeatures: PerfLogFeatures,
{microMetrics, forceGc, captureFrames, receivedData, requestCount}: {
microMetrics?: {[key: string]: string},
forceGc?: boolean,
captureFrames?: boolean,
receivedData?: boolean,
requestCount?: boolean
} = {}): Metric {
commandLog = [];
if (!perfLogFeatures) {
perfLogFeatures =
new PerfLogFeatures({render: true, gc: true, frameCapture: true, userTiming: true});
}
if (!microMetrics) {
microMetrics = {};
}
const providers: Provider[] = [
Options.DEFAULT_PROVIDERS, PerflogMetric.PROVIDERS,
{provide: Options.MICRO_METRICS, useValue: microMetrics}, {
provide: PerflogMetric.SET_TIMEOUT,
useValue: (fn: Function, millis: number) => {
commandLog.push(['setTimeout', millis]);
fn();
},
},
{
provide: WebDriverExtension,
useValue: new MockDriverExtension(perfLogs, commandLog, perfLogFeatures)
}
];
if (isPresent(forceGc)) {
providers.push({provide: Options.FORCE_GC, useValue: forceGc});
}
if (isPresent(captureFrames)) {
providers.push({provide: Options.CAPTURE_FRAMES, useValue: captureFrames});
}
if (isPresent(receivedData)) {
providers.push({provide: Options.RECEIVED_DATA, useValue: receivedData});
}
if (isPresent(requestCount)) {
providers.push({provide: Options.REQUEST_COUNT, useValue: requestCount});
}
return ReflectiveInjector.resolveAndCreate(providers).get(PerflogMetric);
}
describe('perflog metric', () => {
function sortedKeys(stringMap: {[key: string]: any}) {
const res: string[] = [];
res.push(...Object.keys(stringMap));
res.sort();
return res;
}
it('should describe itself based on the perfLogFeatrues', () => {
expect(sortedKeys(createMetric([[]], new PerfLogFeatures()).describe())).toEqual([
'pureScriptTime', 'scriptTime'
]);
expect(
sortedKeys(createMetric([[]], new PerfLogFeatures({render: true, gc: false})).describe()))
.toEqual(['pureScriptTime', 'renderTime', 'scriptTime']);
expect(sortedKeys(createMetric([[]], null).describe())).toEqual([
'gcAmount', 'gcTime', 'majorGcTime', 'pureScriptTime', 'renderTime', 'scriptTime'
]);
expect(sortedKeys(createMetric([[]], new PerfLogFeatures({render: true, gc: true}), {
forceGc: true
}).describe()))
.toEqual([
'forcedGcAmount', 'forcedGcTime', 'gcAmount', 'gcTime', 'majorGcTime', 'pureScriptTime',
'renderTime', 'scriptTime'
]);
expect(sortedKeys(createMetric([[]], new PerfLogFeatures({userTiming: true}), {
receivedData: true,
requestCount: true
}).describe()))
.toEqual(['pureScriptTime', 'receivedData', 'requestCount', 'scriptTime']);
});
it('should describe itself based on micro metrics', () => {
const description =
createMetric([[]], null, {microMetrics: {'myMicroMetric': 'someDesc'}}).describe();
expect(description['myMicroMetric']).toEqual('someDesc');
});
it('should describe itself if frame capture is requested and available', () => {
const description = createMetric([[]], new PerfLogFeatures({frameCapture: true}), {
captureFrames: true
}).describe();
expect(description['frameTime.mean']).not.toContain('WARNING');
expect(description['frameTime.best']).not.toContain('WARNING');
expect(description['frameTime.worst']).not.toContain('WARNING');
expect(description['frameTime.smooth']).not.toContain('WARNING');
});
it('should describe itself if frame capture is requested and not available', () => {
const description = createMetric([[]], new PerfLogFeatures({frameCapture: false}), {
captureFrames: true
}).describe();
expect(description['frameTime.mean']).toContain('WARNING');
expect(description['frameTime.best']).toContain('WARNING');
expect(description['frameTime.worst']).toContain('WARNING');
expect(description['frameTime.smooth']).toContain('WARNING');
});
describe('beginMeasure', () => {
it('should not force gc and mark the timeline',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const metric = createMetric([[]], null);
metric.beginMeasure().then((_) => {
expect(commandLog).toEqual([['timeBegin', 'benchpress0']]);
async.done();
});
}));
it('should force gc and mark the timeline',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const metric = createMetric([[]], null, {forceGc: true});
metric.beginMeasure().then((_) => {
expect(commandLog).toEqual([['gc'], ['timeBegin', 'benchpress0']]);
async.done();
});
}));
});
describe('endMeasure', () => {
it('should mark and aggregate events in between the marks',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const events = [[
eventFactory.markStart('benchpress0', 0), eventFactory.start('script', 4),
eventFactory.end('script', 6), eventFactory.markEnd('benchpress0', 10)
]];
const metric = createMetric(events, null);
metric.beginMeasure().then((_) => metric.endMeasure(false)).then((data) => {
expect(commandLog).toEqual([
['timeBegin', 'benchpress0'], ['timeEnd', 'benchpress0', null], 'readPerfLog'
]);
expect(data['scriptTime']).toBe(2);
async.done();
});
}));
it('should mark and aggregate events since navigationStart',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const events = [[
eventFactory.markStart('benchpress0', 0), eventFactory.start('script', 4),
eventFactory.end('script', 6), eventFactory.instant('navigationStart', 7),
eventFactory.start('script', 8), eventFactory.end('script', 9),
eventFactory.markEnd('benchpress0', 10)
]];
const metric = createMetric(events, null);
metric.beginMeasure().then((_) => metric.endMeasure(false)).then((data) => {
expect(data['scriptTime']).toBe(1);
async.done();
});
}));
it('should restart timing', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const events = [
[
eventFactory.markStart('benchpress0', 0),
eventFactory.markEnd('benchpress0', 1),
eventFactory.markStart('benchpress1', 2),
],
[eventFactory.markEnd('benchpress1', 3)]
];
const metric = createMetric(events, null);
metric.beginMeasure()
.then((_) => metric.endMeasure(true))
.then((_) => metric.endMeasure(true))
.then((_) => {
expect(commandLog).toEqual([
['timeBegin', 'benchpress0'], ['timeEnd', 'benchpress0', 'benchpress1'],
'readPerfLog', ['timeEnd', 'benchpress1', 'benchpress2'], 'readPerfLog'
]);
async.done();
});
}));
it('should loop and aggregate until the end mark is present',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const events = [
[eventFactory.markStart('benchpress0', 0), eventFactory.start('script', 1)],
[eventFactory.end('script', 2)],
[
eventFactory.start('script', 3), eventFactory.end('script', 5),
eventFactory.markEnd('benchpress0', 10)
]
];
const metric = createMetric(events, null);
metric.beginMeasure().then((_) => metric.endMeasure(false)).then((data) => {
expect(commandLog).toEqual([
['timeBegin', 'benchpress0'], ['timeEnd', 'benchpress0', null], 'readPerfLog',
['setTimeout', 100], 'readPerfLog', ['setTimeout', 100], 'readPerfLog'
]);
expect(data['scriptTime']).toBe(3);
async.done();
});
}));
it('should store events after the end mark for the next call',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const events = [
[
eventFactory.markStart('benchpress0', 0), eventFactory.markEnd('benchpress0', 1),
eventFactory.markStart('benchpress1', 1), eventFactory.start('script', 1),
eventFactory.end('script', 2)
],
[
eventFactory.start('script', 3), eventFactory.end('script', 5),
eventFactory.markEnd('benchpress1', 6)
]
];
const metric = createMetric(events, null);
metric.beginMeasure()
.then((_) => metric.endMeasure(true))
.then((data) => {
expect(data['scriptTime']).toBe(0);
return metric.endMeasure(true);
})
.then((data) => {
expect(commandLog).toEqual([
['timeBegin', 'benchpress0'], ['timeEnd', 'benchpress0', 'benchpress1'],
'readPerfLog', ['timeEnd', 'benchpress1', 'benchpress2'], 'readPerfLog'
]);
expect(data['scriptTime']).toBe(3);
async.done();
});
}));
describe('with forced gc', () => {
let events: PerfLogEvent[][];
beforeEach(() => {
events = [[
eventFactory.markStart('benchpress0', 0), eventFactory.start('script', 4),
eventFactory.end('script', 6), eventFactory.markEnd('benchpress0', 10),
eventFactory.markStart('benchpress1', 11),
eventFactory.start('gc', 12, {'usedHeapSize': 2500}),
eventFactory.end('gc', 15, {'usedHeapSize': 1000}),
eventFactory.markEnd('benchpress1', 20)
]];
});
it('should measure forced gc', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const metric = createMetric(events, null, {forceGc: true});
metric.beginMeasure().then((_) => metric.endMeasure(false)).then((data) => {
expect(commandLog).toEqual([
['gc'], ['timeBegin', 'benchpress0'], ['timeEnd', 'benchpress0', 'benchpress1'],
'readPerfLog', ['gc'], ['timeEnd', 'benchpress1', null], 'readPerfLog'
]);
expect(data['forcedGcTime']).toBe(3);
expect(data['forcedGcAmount']).toBe(1.5);
async.done();
});
}));
it('should restart after the forced gc if needed',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const metric = createMetric(events, null, {forceGc: true});
metric.beginMeasure().then((_) => metric.endMeasure(true)).then((data) => {
expect(commandLog[5]).toEqual(['timeEnd', 'benchpress1', 'benchpress2']);
async.done();
});
}));
});
});
describe('aggregation', () => {
function aggregate(events: any[], {microMetrics, captureFrames, receivedData, requestCount}: {
microMetrics?: {[key: string]: string},
captureFrames?: boolean,
receivedData?: boolean,
requestCount?: boolean
} = {}) {
events.unshift(eventFactory.markStart('benchpress0', 0));
events.push(eventFactory.markEnd('benchpress0', 10));
const metric = createMetric([events], null, {
microMetrics: microMetrics,
captureFrames: captureFrames,
receivedData: receivedData,
requestCount: requestCount
});
return metric.beginMeasure().then((_) => metric.endMeasure(false));
}
describe('frame metrics', () => {
it('should calculate mean frame time',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate(
[
eventFactory.markStart('frameCapture', 0), eventFactory.instant('frame', 1),
eventFactory.instant('frame', 3), eventFactory.instant('frame', 4),
eventFactory.markEnd('frameCapture', 5)
],
{captureFrames: true})
.then((data) => {
expect(data['frameTime.mean']).toBe(((3 - 1) + (4 - 3)) / 2);
async.done();
});
}));
it('should throw if no start event',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate(
[eventFactory.instant('frame', 4), eventFactory.markEnd('frameCapture', 5)],
{captureFrames: true})
.catch((err): any => {
expect(() => {
throw err;
}).toThrowError('missing start event for frame capture');
async.done();
});
}));
it('should throw if no end event',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate(
[eventFactory.markStart('frameCapture', 3), eventFactory.instant('frame', 4)],
{captureFrames: true})
.catch((err): any => {
expect(() => { throw err; }).toThrowError('missing end event for frame capture');
async.done();
});
}));
it('should throw if trying to capture twice',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate(
[
eventFactory.markStart('frameCapture', 3),
eventFactory.markStart('frameCapture', 4)
],
{captureFrames: true})
.catch((err): any => {
expect(() => {
throw err;
}).toThrowError('can capture frames only once per benchmark run');
async.done();
});
}));
it('should throw if trying to capture when frame capture is disabled',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate([eventFactory.markStart('frameCapture', 3)]).catch((err) => {
expect(() => { throw err; })
.toThrowError(
'found start event for frame capture, but frame capture was not requested in benchpress');
async.done();
return null;
});
}));
it('should throw if frame capture is enabled, but nothing is captured',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate([], {captureFrames: true}).catch((err): any => {
expect(() => { throw err; })
.toThrowError(
'frame capture requested in benchpress, but no start event was found');
async.done();
});
}));
it('should calculate best and worst frame time',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate(
[
eventFactory.markStart('frameCapture', 0), eventFactory.instant('frame', 1),
eventFactory.instant('frame', 9), eventFactory.instant('frame', 15),
eventFactory.instant('frame', 18), eventFactory.instant('frame', 28),
eventFactory.instant('frame', 32), eventFactory.markEnd('frameCapture', 10)
],
{captureFrames: true})
.then((data) => {
expect(data['frameTime.worst']).toBe(10);
expect(data['frameTime.best']).toBe(3);
async.done();
});
}));
it('should calculate percentage of smoothness to be good',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate(
[
eventFactory.markStart('frameCapture', 0), eventFactory.instant('frame', 1),
eventFactory.instant('frame', 2), eventFactory.instant('frame', 3),
eventFactory.markEnd('frameCapture', 4)
],
{captureFrames: true})
.then((data) => {
expect(data['frameTime.smooth']).toBe(1.0);
async.done();
});
}));
it('should calculate percentage of smoothness to be bad',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate(
[
eventFactory.markStart('frameCapture', 0), eventFactory.instant('frame', 1),
eventFactory.instant('frame', 2), eventFactory.instant('frame', 22),
eventFactory.instant('frame', 23), eventFactory.instant('frame', 24),
eventFactory.markEnd('frameCapture', 4)
],
{captureFrames: true})
.then((data) => {
expect(data['frameTime.smooth']).toBe(0.75);
async.done();
});
}));
});
it('should report a single interval',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate([
eventFactory.start('script', 0), eventFactory.end('script', 5)
]).then((data) => {
expect(data['scriptTime']).toBe(5);
async.done();
});
}));
it('should sum up multiple intervals',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate([
eventFactory.start('script', 0), eventFactory.end('script', 5),
eventFactory.start('script', 10), eventFactory.end('script', 17)
]).then((data) => {
expect(data['scriptTime']).toBe(12);
async.done();
});
}));
it('should ignore not started intervals',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate([eventFactory.end('script', 10)]).then((data) => {
expect(data['scriptTime']).toBe(0);
async.done();
});
}));
it('should ignore not ended intervals',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate([eventFactory.start('script', 10)]).then((data) => {
expect(data['scriptTime']).toBe(0);
async.done();
});
}));
it('should ignore nested intervals',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate([
eventFactory.start('script', 0), eventFactory.start('script', 5),
eventFactory.end('script', 10), eventFactory.end('script', 17)
]).then((data) => {
expect(data['scriptTime']).toBe(17);
async.done();
});
}));
it('should ignore events from different processed as the start mark',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const otherProcessEventFactory = new TraceEventFactory('timeline', 'pid1');
const metric = createMetric(
[[
eventFactory.markStart('benchpress0', 0), eventFactory.start('script', 0, null),
eventFactory.end('script', 5, null),
otherProcessEventFactory.start('script', 10, null),
otherProcessEventFactory.end('script', 17, null),
eventFactory.markEnd('benchpress0', 20)
]],
null);
metric.beginMeasure().then((_) => metric.endMeasure(false)).then((data) => {
expect(data['scriptTime']).toBe(5);
async.done();
});
}));
it('should support scriptTime metric',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate([
eventFactory.start('script', 0), eventFactory.end('script', 5)
]).then((data) => {
expect(data['scriptTime']).toBe(5);
async.done();
});
}));
it('should support renderTime metric',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate([
eventFactory.start('render', 0), eventFactory.end('render', 5)
]).then((data) => {
expect(data['renderTime']).toBe(5);
async.done();
});
}));
it('should support gcTime/gcAmount metric',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate([
eventFactory.start('gc', 0, {'usedHeapSize': 2500}),
eventFactory.end('gc', 5, {'usedHeapSize': 1000})
]).then((data) => {
expect(data['gcTime']).toBe(5);
expect(data['gcAmount']).toBe(1.5);
expect(data['majorGcTime']).toBe(0);
async.done();
});
}));
it('should support majorGcTime metric',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate([
eventFactory.start('gc', 0, {'usedHeapSize': 2500}),
eventFactory.end('gc', 5, {'usedHeapSize': 1000, 'majorGc': true})
]).then((data) => {
expect(data['gcTime']).toBe(5);
expect(data['majorGcTime']).toBe(5);
async.done();
});
}));
it('should support pureScriptTime = scriptTime-gcTime-renderTime',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate([
eventFactory.start('script', 0), eventFactory.start('gc', 1, {'usedHeapSize': 1000}),
eventFactory.end('gc', 4, {'usedHeapSize': 0}), eventFactory.start('render', 4),
eventFactory.end('render', 5), eventFactory.end('script', 6)
]).then((data) => {
expect(data['scriptTime']).toBe(6);
expect(data['pureScriptTime']).toBe(2);
async.done();
});
}));
describe('receivedData', () => {
it('should report received data since last navigationStart',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate(
[
eventFactory.instant('receivedData', 0, {'encodedDataLength': 1}),
eventFactory.instant('navigationStart', 1),
eventFactory.instant('receivedData', 2, {'encodedDataLength': 2}),
eventFactory.instant('navigationStart', 3),
eventFactory.instant('receivedData', 4, {'encodedDataLength': 4}),
eventFactory.instant('receivedData', 5, {'encodedDataLength': 8})
],
{receivedData: true})
.then((data) => {
expect(data['receivedData']).toBe(12);
async.done();
});
}));
});
describe('requestCount', () => {
it('should report count of requests sent since last navigationStart',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate(
[
eventFactory.instant('sendRequest', 0),
eventFactory.instant('navigationStart', 1),
eventFactory.instant('sendRequest', 2),
eventFactory.instant('navigationStart', 3),
eventFactory.instant('sendRequest', 4), eventFactory.instant('sendRequest', 5)
],
{requestCount: true})
.then((data) => {
expect(data['requestCount']).toBe(2);
async.done();
});
}));
});
describe('microMetrics', () => {
it('should report micro metrics',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate(
[
eventFactory.markStart('mm1', 0),
eventFactory.markEnd('mm1', 5),
],
{microMetrics: {'mm1': 'micro metric 1'}})
.then((data) => {
expect(data['mm1']).toBe(5.0);
async.done();
});
}));
it('should ignore micro metrics that were not specified',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate([
eventFactory.markStart('mm1', 0),
eventFactory.markEnd('mm1', 5),
]).then((data) => {
expect(data['mm1']).toBeFalsy();
async.done();
});
}));
it('should report micro metric averages',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
aggregate(
[
eventFactory.markStart('mm1*20', 0),
eventFactory.markEnd('mm1*20', 5),
],
{microMetrics: {'mm1': 'micro metric 1'}})
.then((data) => {
expect(data['mm1']).toBe(5 / 20);
async.done();
});
}));
});
});
});
}
class MockDriverExtension extends WebDriverExtension {
constructor(
private _perfLogs: any[], private _commandLog: any[],
private _perfLogFeatures: PerfLogFeatures) {
super();
}
timeBegin(name: string): Promise<any> {
this._commandLog.push(['timeBegin', name]);
return Promise.resolve(null);
}
timeEnd(name: string, restartName: string): Promise<any> {
this._commandLog.push(['timeEnd', name, restartName]);
return Promise.resolve(null);
}
perfLogFeatures(): PerfLogFeatures { return this._perfLogFeatures; }
readPerfLog(): Promise<any> {
this._commandLog.push('readPerfLog');
if (this._perfLogs.length > 0) {
const next = this._perfLogs[0];
this._perfLogs.shift();
return Promise.resolve(next);
} else {
return Promise.resolve([]);
}
}
gc(): Promise<any> {
this._commandLog.push(['gc']);
return Promise.resolve(null);
}
}

View File

@ -0,0 +1,82 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Provider, ReflectiveInjector} from '@angular/core';
import {AsyncTestCompleter, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
import {Options, PerfLogEvent, PerfLogFeatures, UserMetric, WebDriverAdapter} from '../../index';
export function main() {
let wdAdapter: MockDriverAdapter;
function createMetric(
perfLogs: PerfLogEvent[], perfLogFeatures: PerfLogFeatures,
{userMetrics}: {userMetrics?: {[key: string]: string}} = {}): UserMetric {
if (!perfLogFeatures) {
perfLogFeatures =
new PerfLogFeatures({render: true, gc: true, frameCapture: true, userTiming: true});
}
if (!userMetrics) {
userMetrics = {};
}
wdAdapter = new MockDriverAdapter();
const providers: Provider[] = [
Options.DEFAULT_PROVIDERS, UserMetric.PROVIDERS,
{provide: Options.USER_METRICS, useValue: userMetrics},
{provide: WebDriverAdapter, useValue: wdAdapter}
];
return ReflectiveInjector.resolveAndCreate(providers).get(UserMetric);
}
describe('user metric', () => {
it('should describe itself based on userMetrics', () => {
expect(createMetric([[]], new PerfLogFeatures(), {
userMetrics: {'loadTime': 'time to load'}
}).describe())
.toEqual({'loadTime': 'time to load'});
});
describe('endMeasure', () => {
it('should stop measuring when all properties have numeric values',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const metric = createMetric(
[[]], new PerfLogFeatures(),
{userMetrics: {'loadTime': 'time to load', 'content': 'time to see content'}});
metric.beginMeasure()
.then((_) => metric.endMeasure(true))
.then((values: {[key: string]: string}) => {
expect(values['loadTime']).toBe(25);
expect(values['content']).toBe(250);
async.done();
});
wdAdapter.data['loadTime'] = 25;
// Wait before setting 2nd property.
setTimeout(() => { wdAdapter.data['content'] = 250; }, 50);
}), 600);
});
});
}
class MockDriverAdapter extends WebDriverAdapter {
data: any = {};
executeScript(script: string): any {
// Just handles `return window.propName` ignores `delete window.propName`.
if (script.indexOf('return window.') == 0) {
const metricName = script.substring('return window.'.length);
return Promise.resolve(this.data[metricName]);
} else if (script.indexOf('delete window.') == 0) {
return Promise.resolve(null);
} else {
return Promise.reject(`Unexpected syntax: ${script}`);
}
}
}

View File

@ -1,48 +1,47 @@
import {
describe,
ddescribe,
it,
iit,
xit,
expect,
beforeEach,
afterEach
} from '@angular/testing/testing_internal';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {isBlank, isPresent, Date, DateWrapper} from '@angular/facade';
import {Provider} from '@angular/core';
import {describe, expect, it} from '@angular/core/testing/testing_internal';
import {
SampleState,
Reporter,
ReflectiveInjector,
ConsoleReporter,
SampleDescription,
MeasureValues
} from 'benchpress/common';
import {ConsoleReporter, MeasureValues, ReflectiveInjector, SampleDescription} from '../../index';
import {isBlank, isPresent} from '../../src/facade/lang';
export function main() {
describe('console reporter', () => {
var reporter;
var log: string[];
let reporter: ConsoleReporter;
let log: string[];
function createReporter({columnWidth = null, sampleId = null, descriptions = null,
metrics = null}: {columnWidth?, sampleId?, descriptions?, metrics?}) {
function createReporter(
{columnWidth = null, sampleId = null, descriptions = null, metrics = null}: {
columnWidth?: number,
sampleId?: string,
descriptions?: {[key: string]: any}[],
metrics?: {[key: string]: any}
}) {
log = [];
if (isBlank(descriptions)) {
if (!descriptions) {
descriptions = [];
}
if (isBlank(sampleId)) {
if (sampleId == null) {
sampleId = 'null';
}
var bindings = [
ConsoleReporter.PROVIDERS,
{provide: SampleDescription, useValue: new SampleDescription(sampleId, descriptions, metrics)},
{provide: ConsoleReporter.PRINT, useValue: (line) => log.push(line)}
const providers: Provider[] = [
ConsoleReporter.PROVIDERS, {
provide: SampleDescription,
useValue: new SampleDescription(sampleId, descriptions, metrics)
},
{provide: ConsoleReporter.PRINT, useValue: (line: string) => log.push(line)}
];
if (isPresent(columnWidth)) {
bindings.push({provide: ConsoleReporter.COLUMN_WIDTH, useValue(columnWidth)};
providers.push({provide: ConsoleReporter.COLUMN_WIDTH, useValue: columnWidth});
}
reporter = ReflectiveInjector.resolveAndCreate(bindings).get(ConsoleReporter);
reporter = ReflectiveInjector.resolveAndCreate(providers).get(ConsoleReporter);
}
it('should print the sample id, description and table header', () => {
@ -90,6 +89,6 @@ export function main() {
});
}
function mv(runIndex, time, values) {
return new MeasureValues(runIndex, DateWrapper.fromMillis(time), values);
function mv(runIndex: number, time: number, values: {[key: string]: number}) {
return new MeasureValues(runIndex, new Date(time), values);
}

View File

@ -0,0 +1,81 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AsyncTestCompleter, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
import {JsonFileReporter, MeasureValues, Options, ReflectiveInjector, SampleDescription} from '../../index';
import {isPresent} from '../../src/facade/lang';
export function main() {
describe('file reporter', () => {
let loggedFile: any;
function createReporter({sampleId, descriptions, metrics, path}: {
sampleId: string,
descriptions: {[key: string]: any}[],
metrics: {[key: string]: string},
path: string
}) {
const providers = [
JsonFileReporter.PROVIDERS, {
provide: SampleDescription,
useValue: new SampleDescription(sampleId, descriptions, metrics)
},
{provide: JsonFileReporter.PATH, useValue: path},
{provide: Options.NOW, useValue: () => new Date(1234)}, {
provide: Options.WRITE_FILE,
useValue: (filename: string, content: string) => {
loggedFile = {'filename': filename, 'content': content};
return Promise.resolve(null);
}
}
];
return ReflectiveInjector.resolveAndCreate(providers).get(JsonFileReporter);
}
it('should write all data into a file',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createReporter({
sampleId: 'someId',
descriptions: [{'a': 2}],
path: 'somePath',
metrics: {'a': 'script time', 'b': 'render time'}
})
.reportSample(
[mv(0, 0, {'a': 3, 'b': 6})],
[mv(0, 0, {'a': 3, 'b': 6}), mv(1, 1, {'a': 5, 'b': 9})]);
const regExp = /somePath\/someId_\d+\.json/;
expect(isPresent(loggedFile['filename'].match(regExp))).toBe(true);
const parsedContent = JSON.parse(loggedFile['content']);
expect(parsedContent).toEqual({
'description': {
'id': 'someId',
'description': {'a': 2},
'metrics': {'a': 'script time', 'b': 'render time'}
},
'stats': {'a': '4.00+-25%', 'b': '7.50+-20%'},
'completeSample': [
{'timeStamp': '1970-01-01T00:00:00.000Z', 'runIndex': 0, 'values': {'a': 3, 'b': 6}}
],
'validSample': [
{'timeStamp': '1970-01-01T00:00:00.000Z', 'runIndex': 0, 'values': {'a': 3, 'b': 6}}, {
'timeStamp': '1970-01-01T00:00:00.001Z',
'runIndex': 1,
'values': {'a': 5, 'b': 9}
}
]
});
async.done();
}));
});
}
function mv(runIndex: number, time: number, values: {[key: string]: number}) {
return new MeasureValues(runIndex, new Date(time), values);
}

View File

@ -0,0 +1,68 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AsyncTestCompleter, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
import {MeasureValues, MultiReporter, ReflectiveInjector, Reporter} from '../../index';
export function main() {
function createReporters(ids: any[]) {
const r = ReflectiveInjector
.resolveAndCreate([
ids.map(id => ({provide: id, useValue: new MockReporter(id)})),
MultiReporter.provideWith(ids)
])
.get(MultiReporter);
return Promise.resolve(r);
}
describe('multi reporter', () => {
it('should reportMeasureValues to all',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const mv = new MeasureValues(0, new Date(), {});
createReporters(['m1', 'm2']).then((r) => r.reportMeasureValues(mv)).then((values) => {
expect(values).toEqual([{'id': 'm1', 'values': mv}, {'id': 'm2', 'values': mv}]);
async.done();
});
}));
it('should reportSample to call', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const completeSample =
[new MeasureValues(0, new Date(), {}), new MeasureValues(1, new Date(), {})];
const validSample = [completeSample[1]];
createReporters(['m1', 'm2'])
.then((r) => r.reportSample(completeSample, validSample))
.then((values) => {
expect(values).toEqual([
{'id': 'm1', 'completeSample': completeSample, 'validSample': validSample},
{'id': 'm2', 'completeSample': completeSample, 'validSample': validSample}
]);
async.done();
});
}));
});
}
class MockReporter extends Reporter {
constructor(private _id: string) { super(); }
reportMeasureValues(values: MeasureValues): Promise<{[key: string]: any}> {
return Promise.resolve({'id': this._id, 'values': values});
}
reportSample(completeSample: MeasureValues[], validSample: MeasureValues[]):
Promise<{[key: string]: any}> {
return Promise.resolve(
{'id': this._id, 'completeSample': completeSample, 'validSample': validSample});
}
}

View File

@ -0,0 +1,140 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AsyncTestCompleter, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
import {Injector, Metric, Options, ReflectiveInjector, Runner, SampleDescription, SampleState, Sampler, Validator, WebDriverAdapter} from '../index';
export function main() {
describe('runner', () => {
let injector: ReflectiveInjector;
let runner: Runner;
function createRunner(defaultProviders: any[] = null): Runner {
if (!defaultProviders) {
defaultProviders = [];
}
runner = new Runner([
defaultProviders, {
provide: Sampler,
useFactory: (_injector: ReflectiveInjector) => {
injector = _injector;
return new MockSampler();
},
deps: [Injector]
},
{provide: Metric, useFactory: () => new MockMetric(), deps: []},
{provide: Validator, useFactory: () => new MockValidator(), deps: []},
{provide: WebDriverAdapter, useFactory: () => new MockWebDriverAdapter(), deps: []}
]);
return runner;
}
it('should set SampleDescription.id',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createRunner()
.sample({id: 'someId'})
.then((_) => injector.get(SampleDescription))
.then((desc) => {
expect(desc.id).toBe('someId');
async.done();
});
}));
it('should merge SampleDescription.description',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createRunner([{provide: Options.DEFAULT_DESCRIPTION, useValue: {'a': 1}}])
.sample({
id: 'someId',
providers: [{provide: Options.SAMPLE_DESCRIPTION, useValue: {'b': 2}}]
})
.then((_) => injector.get(SampleDescription))
.then((desc) => {
expect(desc.description)
.toEqual(
{'forceGc': false, 'userAgent': 'someUserAgent', 'a': 1, 'b': 2, 'v': 11});
async.done();
});
}));
it('should fill SampleDescription.metrics from the Metric',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createRunner()
.sample({id: 'someId'})
.then((_) => injector.get(SampleDescription))
.then((desc) => {
expect(desc.metrics).toEqual({'m1': 'some metric'});
async.done();
});
}));
it('should provide Options.EXECUTE',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const execute = () => {};
createRunner().sample({id: 'someId', execute: execute}).then((_) => {
expect(injector.get(Options.EXECUTE)).toEqual(execute);
async.done();
});
}));
it('should provide Options.PREPARE',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const prepare = () => {};
createRunner().sample({id: 'someId', prepare: prepare}).then((_) => {
expect(injector.get(Options.PREPARE)).toEqual(prepare);
async.done();
});
}));
it('should provide Options.MICRO_METRICS',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createRunner().sample({id: 'someId', microMetrics: {'a': 'b'}}).then((_) => {
expect(injector.get(Options.MICRO_METRICS)).toEqual({'a': 'b'});
async.done();
});
}));
it('should overwrite providers per sample call',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createRunner([{provide: Options.DEFAULT_DESCRIPTION, useValue: {'a': 1}}])
.sample({
id: 'someId',
providers: [{provide: Options.DEFAULT_DESCRIPTION, useValue: {'a': 2}}]
})
.then((_) => injector.get(SampleDescription))
.then((desc) => {
expect(desc.description['a']).toBe(2);
async.done();
});
}));
});
}
class MockWebDriverAdapter extends WebDriverAdapter {
executeScript(script: string): Promise<string> { return Promise.resolve('someUserAgent'); }
capabilities(): Promise<Map<string, any>> { return null; }
}
class MockValidator extends Validator {
constructor() { super(); }
describe() { return {'v': 11}; }
}
class MockMetric extends Metric {
constructor() { super(); }
describe() { return {'m1': 'some metric'}; }
}
class MockSampler extends Sampler {
constructor() { super(null, null, null, null, null, null, null); }
sample(): Promise<SampleState> { return Promise.resolve(new SampleState([], [])); }
}

View File

@ -1,35 +1,21 @@
import {
afterEach,
AsyncTestCompleter,
beforeEach,
ddescribe,
describe,
expect,
iit,
inject,
it,
xit,
} from '@angular/testing/testing_internal';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {isBlank, isPresent, stringify, Date, DateWrapper} from '@angular/facade';
import {PromiseWrapper} from '@angular/facade';
import {AsyncTestCompleter, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
import {
Sampler,
WebDriverAdapter,
Validator,
Metric,
Reporter,
ReflectiveInjector,
Options,
MeasureValues
} from 'benchpress/common';
import {MeasureValues, Metric, Options, ReflectiveInjector, Reporter, Sampler, Validator, WebDriverAdapter} from '../index';
import {isBlank, isPresent} from '../src/facade/lang';
export function main() {
var EMPTY_EXECUTE = () => {};
const EMPTY_EXECUTE = () => {};
describe('sampler', () => {
var sampler: Sampler;
let sampler: Sampler;
function createSampler({driver, metric, reporter, validator, prepare, execute}: {
driver?: any,
@ -39,25 +25,21 @@ export function main() {
prepare?: any,
execute?: any
} = {}) {
var time = 1000;
if (isBlank(metric)) {
let time = 1000;
if (!metric) {
metric = new MockMetric([]);
}
if (isBlank(reporter)) {
if (!reporter) {
reporter = new MockReporter([]);
}
if (isBlank(driver)) {
driver = new MockDriverAdapter([]);
}
var providers = [
Options.DEFAULT_PROVIDERS,
Sampler.PROVIDERS,
{provide: Metric, useValue: metric},
{provide: Reporter, useValue: reporter},
{provide: WebDriverAdapter, useValue: driver},
{provide: Options.EXECUTE, useValue: execute},
{provide: Validator, useValue: validator},
{provide: Options.NOW, useValue: () => DateWrapper.fromMillis(time++)}
const providers = [
Options.DEFAULT_PROVIDERS, Sampler.PROVIDERS, {provide: Metric, useValue: metric},
{provide: Reporter, useValue: reporter}, {provide: WebDriverAdapter, useValue: driver},
{provide: Options.EXECUTE, useValue: execute}, {provide: Validator, useValue: validator},
{provide: Options.NOW, useValue: () => new Date(time++)}
];
if (isPresent(prepare)) {
providers.push({provide: Options.PREPARE, useValue: prepare});
@ -67,19 +49,19 @@ export function main() {
}
it('should call the prepare and execute callbacks using WebDriverAdapter.waitFor',
inject([AsyncTestCompleter], (async) => {
var log = [];
var count = 0;
var driver = new MockDriverAdapter([], (callback) => {
var result = callback();
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const log: any[] = [];
let count = 0;
const driver = new MockDriverAdapter([], (callback: Function) => {
const result = callback();
log.push(result);
return PromiseWrapper.resolve(result);
return Promise.resolve(result);
});
createSampler({
driver: driver,
validator: createCountingValidator(2),
prepare: () => { return count++; },
execute: () => { return count++; }
prepare: () => count++,
execute: () => count++,
});
sampler.sample().then((_) => {
expect(count).toBe(4);
@ -90,9 +72,9 @@ export function main() {
}));
it('should call prepare, beginMeasure, execute, endMeasure for every iteration',
inject([AsyncTestCompleter], (async) => {
var workCount = 0;
var log = [];
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
let workCount = 0;
const log: any[] = [];
createSampler({
metric: createCountingMetric(log),
validator: createCountingValidator(2),
@ -115,9 +97,9 @@ export function main() {
}));
it('should call execute, endMeasure for every iteration if there is no prepare callback',
inject([AsyncTestCompleter], (async) => {
var log = [];
var workCount = 0;
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const log: any[] = [];
let workCount = 0;
createSampler({
metric: createCountingMetric(log),
validator: createCountingValidator(2),
@ -137,17 +119,18 @@ export function main() {
}));
it('should only collect metrics for execute and ignore metrics from prepare',
inject([AsyncTestCompleter], (async) => {
var scriptTime = 0;
var iterationCount = 1;
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
let scriptTime = 0;
let iterationCount = 1;
createSampler({
validator: createCountingValidator(2),
metric: new MockMetric([],
() => {
var result = PromiseWrapper.resolve({'script': scriptTime});
scriptTime = 0;
return result;
}),
metric: new MockMetric(
[],
() => {
const result = Promise.resolve({'script': scriptTime});
scriptTime = 0;
return result;
}),
prepare: () => { scriptTime = 1 * iterationCount; },
execute: () => {
scriptTime = 10 * iterationCount;
@ -163,9 +146,9 @@ export function main() {
}));
it('should call the validator for every execution and store the valid sample',
inject([AsyncTestCompleter], (async) => {
var log = [];
var validSample = [{}];
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const log: any[] = [];
const validSample = [mv(null, null, {})];
createSampler({
metric: createCountingMetric(),
@ -189,9 +172,10 @@ export function main() {
});
}));
it('should report the metric values', inject([AsyncTestCompleter], (async) => {
var log = [];
var validSample = [{}];
it('should report the metric values',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const log: any[] = [];
const validSample = [mv(null, null, {})];
createSampler({
validator: createCountingValidator(2, validSample),
metric: createCountingMetric(),
@ -209,9 +193,7 @@ export function main() {
expect(log[0]).toEqual(['reportMeasureValues', mv(0, 1000, {'script': 0})]);
expect(log[1]).toEqual(['reportMeasureValues', mv(1, 1001, {'script': 1})]);
expect(log[2]).toEqual([
'reportSample',
[mv(0, 1000, {'script': 0}), mv(1, 1001, {'script': 1})],
validSample
'reportSample', [mv(0, 1000, {'script': 0}), mv(1, 1001, {'script': 1})], validSample
]);
async.done();
@ -221,98 +203,70 @@ export function main() {
});
}
function mv(runIndex, time, values) {
return new MeasureValues(runIndex, DateWrapper.fromMillis(time), values);
function mv(runIndex: number, time: number, values: {[key: string]: number}) {
return new MeasureValues(runIndex, new Date(time), values);
}
function createCountingValidator(count, validSample = null, log = null) {
return new MockValidator(log, (completeSample) => {
function createCountingValidator(
count: number, validSample: MeasureValues[] = null, log: any[] = []) {
return new MockValidator(log, (completeSample: MeasureValues[]) => {
count--;
if (count === 0) {
return isPresent(validSample) ? validSample : completeSample;
return validSample || completeSample;
} else {
return null;
}
});
}
function createCountingMetric(log = null) {
var scriptTime = 0;
return new MockMetric(log, () => { return {'script': scriptTime++}; });
function createCountingMetric(log: any[] = []) {
let scriptTime = 0;
return new MockMetric(log, () => ({'script': scriptTime++}));
}
class MockDriverAdapter extends WebDriverAdapter {
private _log: any[];
private _waitFor: Function;
constructor(log = null, waitFor = null) {
super();
if (isBlank(log)) {
log = [];
}
this._log = log;
this._waitFor = waitFor;
}
constructor(private _log: any[] = [], private _waitFor: Function = null) { super(); }
waitFor(callback: Function): Promise<any> {
if (isPresent(this._waitFor)) {
return this._waitFor(callback);
} else {
return PromiseWrapper.resolve(callback());
return Promise.resolve(callback());
}
}
}
class MockValidator extends Validator {
private _log: any[];
constructor(log = null, private _validate: Function = null) {
super();
if (isBlank(log)) {
log = [];
}
this._log = log;
}
constructor(private _log: any[] = [], private _validate: Function = null) { super(); }
validate(completeSample: MeasureValues[]): MeasureValues[] {
var stableSample = isPresent(this._validate) ? this._validate(completeSample) : completeSample;
const stableSample =
isPresent(this._validate) ? this._validate(completeSample) : completeSample;
this._log.push(['validate', completeSample, stableSample]);
return stableSample;
}
}
class MockMetric extends Metric {
private _log: any[];
constructor(log = null, private _endMeasure: Function = null) {
super();
if (isBlank(log)) {
log = [];
}
this._log = log;
}
constructor(private _log: any[] = [], private _endMeasure: Function = null) { super(); }
beginMeasure() {
this._log.push(['beginMeasure']);
return PromiseWrapper.resolve(null);
return Promise.resolve(null);
}
endMeasure(restart) {
var measureValues = isPresent(this._endMeasure) ? this._endMeasure() : {};
endMeasure(restart: boolean) {
const measureValues = isPresent(this._endMeasure) ? this._endMeasure() : {};
this._log.push(['endMeasure', restart, measureValues]);
return PromiseWrapper.resolve(measureValues);
return Promise.resolve(measureValues);
}
}
class MockReporter extends Reporter {
_log: any[];
constructor(log = null) {
super();
if (isBlank(log)) {
log = [];
}
this._log = log;
}
reportMeasureValues(values): Promise<any> {
constructor(private _log: any[] = []) { super(); }
reportMeasureValues(values: MeasureValues): Promise<any> {
this._log.push(['reportMeasureValues', values]);
return PromiseWrapper.resolve(null);
return Promise.resolve(null);
}
reportSample(completeSample, validSample): Promise<any> {
reportSample(completeSample: MeasureValues[], validSample: MeasureValues[]): Promise<any> {
this._log.push(['reportSample', completeSample, validSample]);
return PromiseWrapper.resolve(null);
return Promise.resolve(null);
}
}

View File

@ -1,17 +1,13 @@
import {
describe,
ddescribe,
it,
iit,
xit,
expect,
beforeEach,
afterEach
} from '@angular/testing/testing_internal';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Statistic} from 'benchpress/src/statistic';
import {NaN} from '@angular/facade';
import {describe, expect, it} from '@angular/core/testing/testing_internal';
import {Statistic} from '../src/statistic';
export function main() {
describe('statistic', () => {

View File

@ -0,0 +1,41 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {PerfLogEvent} from '../index';
import {isPresent} from '../src/facade/lang';
export class TraceEventFactory {
constructor(private _cat: string, private _pid: string) {}
create(ph: any, name: string, time: number, args: any = null) {
const res:
PerfLogEvent = {'name': name, 'cat': this._cat, 'ph': ph, 'ts': time, 'pid': this._pid};
if (isPresent(args)) {
res['args'] = args;
}
return res;
}
markStart(name: string, time: number) { return this.create('B', name, time); }
markEnd(name: string, time: number) { return this.create('E', name, time); }
start(name: string, time: number, args: any = null) { return this.create('B', name, time, args); }
end(name: string, time: number, args: any = null) { return this.create('E', name, time, args); }
instant(name: string, time: number, args: any = null) {
return this.create('I', name, time, args);
}
complete(name: string, time: number, duration: number, args: any = null) {
const res = this.create('X', name, time, args);
res['dur'] = duration;
return res;
}
}

View File

@ -0,0 +1,62 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {describe, expect, it} from '@angular/core/testing/testing_internal';
import {MeasureValues, ReflectiveInjector, RegressionSlopeValidator} from '../../index';
export function main() {
describe('regression slope validator', () => {
let validator: RegressionSlopeValidator;
function createValidator({size, metric}: {size: number, metric: string}) {
validator = ReflectiveInjector
.resolveAndCreate([
RegressionSlopeValidator.PROVIDERS,
{provide: RegressionSlopeValidator.METRIC, useValue: metric},
{provide: RegressionSlopeValidator.SAMPLE_SIZE, useValue: size}
])
.get(RegressionSlopeValidator);
}
it('should return sampleSize and metric as description', () => {
createValidator({size: 2, metric: 'script'});
expect(validator.describe()).toEqual({'sampleSize': 2, 'regressionSlopeMetric': 'script'});
});
it('should return null while the completeSample is smaller than the given size', () => {
createValidator({size: 2, metric: 'script'});
expect(validator.validate([])).toBe(null);
expect(validator.validate([mv(0, 0, {})])).toBe(null);
});
it('should return null while the regression slope is < 0', () => {
createValidator({size: 2, metric: 'script'});
expect(validator.validate([mv(0, 0, {'script': 2}), mv(1, 1, {'script': 1})])).toBe(null);
});
it('should return the last sampleSize runs when the regression slope is ==0', () => {
createValidator({size: 2, metric: 'script'});
const sample = [mv(0, 0, {'script': 1}), mv(1, 1, {'script': 1}), mv(2, 2, {'script': 1})];
expect(validator.validate(sample.slice(0, 2))).toEqual(sample.slice(0, 2));
expect(validator.validate(sample)).toEqual(sample.slice(1, 3));
});
it('should return the last sampleSize runs when the regression slope is >0', () => {
createValidator({size: 2, metric: 'script'});
const sample = [mv(0, 0, {'script': 1}), mv(1, 1, {'script': 2}), mv(2, 2, {'script': 3})];
expect(validator.validate(sample.slice(0, 2))).toEqual(sample.slice(0, 2));
expect(validator.validate(sample)).toEqual(sample.slice(1, 3));
});
});
}
function mv(runIndex: number, time: number, values: {[key: string]: number}) {
return new MeasureValues(runIndex, new Date(time), values);
}

View File

@ -0,0 +1,48 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {describe, expect, it} from '@angular/core/testing/testing_internal';
import {MeasureValues, ReflectiveInjector, SizeValidator} from '../../index';
export function main() {
describe('size validator', () => {
let validator: SizeValidator;
function createValidator(size: number) {
validator =
ReflectiveInjector
.resolveAndCreate(
[SizeValidator.PROVIDERS, {provide: SizeValidator.SAMPLE_SIZE, useValue: size}])
.get(SizeValidator);
}
it('should return sampleSize as description', () => {
createValidator(2);
expect(validator.describe()).toEqual({'sampleSize': 2});
});
it('should return null while the completeSample is smaller than the given size', () => {
createValidator(2);
expect(validator.validate([])).toBe(null);
expect(validator.validate([mv(0, 0, {})])).toBe(null);
});
it('should return the last sampleSize runs when it has at least the given size', () => {
createValidator(2);
const sample = [mv(0, 0, {'a': 1}), mv(1, 1, {'b': 2}), mv(2, 2, {'c': 3})];
expect(validator.validate(sample.slice(0, 2))).toEqual(sample.slice(0, 2));
expect(validator.validate(sample)).toEqual(sample.slice(1, 3));
});
});
}
function mv(runIndex: number, time: number, values: {[key: string]: number}) {
return new MeasureValues(runIndex, new Date(time), values);
}

View File

@ -0,0 +1,57 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AsyncTestCompleter, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
import {Options, ReflectiveInjector, WebDriverExtension} from '../index';
import {isPresent} from '../src/facade/lang';
export function main() {
function createExtension(ids: any[], caps: any) {
return new Promise<any>((res, rej) => {
try {
res(ReflectiveInjector
.resolveAndCreate([
ids.map((id) => ({provide: id, useValue: new MockExtension(id)})),
{provide: Options.CAPABILITIES, useValue: caps},
WebDriverExtension.provideFirstSupported(ids)
])
.get(WebDriverExtension));
} catch (e) {
rej(e);
}
});
}
describe('WebDriverExtension.provideFirstSupported', () => {
it('should provide the extension that matches the capabilities',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension(['m1', 'm2', 'm3'], {'browser': 'm2'}).then((m) => {
expect(m.id).toEqual('m2');
async.done();
});
}));
it('should throw if there is no match',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension(['m1'], {'browser': 'm2'}).catch((err) => {
expect(isPresent(err)).toBe(true);
async.done();
});
}));
});
}
class MockExtension extends WebDriverExtension {
constructor(public id: string) { super(); }
supports(capabilities: {[key: string]: any}): boolean {
return capabilities['browser'] === this.id;
}
}

View File

@ -0,0 +1,408 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AsyncTestCompleter, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
import {ChromeDriverExtension, Options, ReflectiveInjector, WebDriverAdapter, WebDriverExtension} from '../../index';
import {isBlank} from '../../src/facade/lang';
import {TraceEventFactory} from '../trace_event_factory';
export function main() {
describe('chrome driver extension', () => {
const CHROME45_USER_AGENT =
'"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2499.0 Safari/537.36"';
let log: any[];
let extension: ChromeDriverExtension;
const blinkEvents = new TraceEventFactory('blink.console', 'pid0');
const v8Events = new TraceEventFactory('v8', 'pid0');
const v8EventsOtherProcess = new TraceEventFactory('v8', 'pid1');
const chromeTimelineEvents =
new TraceEventFactory('disabled-by-default-devtools.timeline', 'pid0');
const chrome45TimelineEvents = new TraceEventFactory('devtools.timeline', 'pid0');
const chromeTimelineV8Events = new TraceEventFactory('devtools.timeline,v8', 'pid0');
const chromeBlinkTimelineEvents = new TraceEventFactory('blink,devtools.timeline', 'pid0');
const chromeBlinkUserTimingEvents = new TraceEventFactory('blink.user_timing', 'pid0');
const benchmarkEvents = new TraceEventFactory('benchmark', 'pid0');
const normEvents = new TraceEventFactory('timeline', 'pid0');
function createExtension(
perfRecords: any[] = null, userAgent: string = null,
messageMethod = 'Tracing.dataCollected'): WebDriverExtension {
if (!perfRecords) {
perfRecords = [];
}
if (isBlank(userAgent)) {
userAgent = CHROME45_USER_AGENT;
}
log = [];
extension = ReflectiveInjector
.resolveAndCreate([
ChromeDriverExtension.PROVIDERS, {
provide: WebDriverAdapter,
useValue: new MockDriverAdapter(log, perfRecords, messageMethod)
},
{provide: Options.USER_AGENT, useValue: userAgent}
])
.get(ChromeDriverExtension);
return extension;
}
it('should force gc via window.gc()',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension().gc().then((_) => {
expect(log).toEqual([['executeScript', 'window.gc()']]);
async.done();
});
}));
it('should mark the timeline via console.time()',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension().timeBegin('someName').then((_) => {
expect(log).toEqual([['executeScript', `console.time('someName');`]]);
async.done();
});
}));
it('should mark the timeline via console.timeEnd()',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension().timeEnd('someName', null).then((_) => {
expect(log).toEqual([['executeScript', `console.timeEnd('someName');`]]);
async.done();
});
}));
it('should mark the timeline via console.time() and console.timeEnd()',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension().timeEnd('name1', 'name2').then((_) => {
expect(log).toEqual(
[['executeScript', `console.timeEnd('name1');console.time('name2');`]]);
async.done();
});
}));
it('should normalize times to ms and forward ph and pid event properties',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([chromeTimelineV8Events.complete('FunctionCall', 1100, 5500, null)])
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.complete('script', 1.1, 5.5, null),
]);
async.done();
});
}));
it('should normalize "tdur" to "dur"',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const event: any = chromeTimelineV8Events.create('X', 'FunctionCall', 1100, null);
event['tdur'] = 5500;
createExtension([event]).readPerfLog().then((events) => {
expect(events).toEqual([
normEvents.complete('script', 1.1, 5.5, null),
]);
async.done();
});
}));
it('should report FunctionCall events as "script"',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([chromeTimelineV8Events.start('FunctionCall', 0)])
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.start('script', 0),
]);
async.done();
});
}));
it('should report EvaluateScript events as "script"',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([chromeTimelineV8Events.start('EvaluateScript', 0)])
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.start('script', 0),
]);
async.done();
});
}));
it('should report minor gc', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([
chromeTimelineV8Events.start('MinorGC', 1000, {'usedHeapSizeBefore': 1000}),
chromeTimelineV8Events.end('MinorGC', 2000, {'usedHeapSizeAfter': 0}),
])
.readPerfLog()
.then((events) => {
expect(events.length).toEqual(2);
expect(events[0]).toEqual(
normEvents.start('gc', 1.0, {'usedHeapSize': 1000, 'majorGc': false}));
expect(events[1]).toEqual(
normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': false}));
async.done();
});
}));
it('should report major gc', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension(
[
chromeTimelineV8Events.start('MajorGC', 1000, {'usedHeapSizeBefore': 1000}),
chromeTimelineV8Events.end('MajorGC', 2000, {'usedHeapSizeAfter': 0}),
], )
.readPerfLog()
.then((events) => {
expect(events.length).toEqual(2);
expect(events[0]).toEqual(
normEvents.start('gc', 1.0, {'usedHeapSize': 1000, 'majorGc': true}));
expect(events[1]).toEqual(
normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': true}));
async.done();
});
}));
['Layout', 'UpdateLayerTree', 'Paint'].forEach((recordType) => {
it(`should report ${recordType} as "render"`,
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension(
[
chrome45TimelineEvents.start(recordType, 1234),
chrome45TimelineEvents.end(recordType, 2345)
], )
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.start('render', 1.234),
normEvents.end('render', 2.345),
]);
async.done();
});
}));
});
it(`should report UpdateLayoutTree as "render"`,
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension(
[
chromeBlinkTimelineEvents.start('UpdateLayoutTree', 1234),
chromeBlinkTimelineEvents.end('UpdateLayoutTree', 2345)
], )
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.start('render', 1.234),
normEvents.end('render', 2.345),
]);
async.done();
});
}));
it('should ignore FunctionCalls from webdriver',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([chromeTimelineV8Events.start(
'FunctionCall', 0, {'data': {'scriptName': 'InjectedScript'}})])
.readPerfLog()
.then((events) => {
expect(events).toEqual([]);
async.done();
});
}));
it('should ignore FunctionCalls with empty scriptName',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension(
[chromeTimelineV8Events.start('FunctionCall', 0, {'data': {'scriptName': ''}})])
.readPerfLog()
.then((events) => {
expect(events).toEqual([]);
async.done();
});
}));
it('should report navigationStart',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([chromeBlinkUserTimingEvents.instant('navigationStart', 1234)])
.readPerfLog()
.then((events) => {
expect(events).toEqual([normEvents.instant('navigationStart', 1.234)]);
async.done();
});
}));
it('should report receivedData', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([chrome45TimelineEvents.instant(
'ResourceReceivedData', 1234, {'data': {'encodedDataLength': 987}})], )
.readPerfLog()
.then((events) => {
expect(events).toEqual(
[normEvents.instant('receivedData', 1.234, {'encodedDataLength': 987})]);
async.done();
});
}));
it('should report sendRequest', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([chrome45TimelineEvents.instant(
'ResourceSendRequest', 1234,
{'data': {'url': 'http://here', 'requestMethod': 'GET'}})], )
.readPerfLog()
.then((events) => {
expect(events).toEqual([normEvents.instant(
'sendRequest', 1.234, {'url': 'http://here', 'method': 'GET'})]);
async.done();
});
}));
describe('readPerfLog (common)', () => {
it('should execute a dummy script before reading them',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
// TODO(tbosch): This seems to be a bug in ChromeDriver:
// Sometimes it does not report the newest events of the performance log
// to the WebDriver client unless a script is executed...
createExtension([]).readPerfLog().then((_) => {
expect(log).toEqual([['executeScript', '1+1'], ['logs', 'performance']]);
async.done();
});
}));
['Rasterize', 'CompositeLayers'].forEach((recordType) => {
it(`should report ${recordType} as "render"`,
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension(
[
chromeTimelineEvents.start(recordType, 1234),
chromeTimelineEvents.end(recordType, 2345)
], )
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.start('render', 1.234),
normEvents.end('render', 2.345),
]);
async.done();
});
}));
});
describe('frame metrics', () => {
it('should report ImplThreadRenderingStats as frame event',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([benchmarkEvents.instant(
'BenchmarkInstrumentation::ImplThreadRenderingStats', 1100,
{'data': {'frame_count': 1}})])
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.instant('frame', 1.1),
]);
async.done();
});
}));
it('should not report ImplThreadRenderingStats with zero frames',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([benchmarkEvents.instant(
'BenchmarkInstrumentation::ImplThreadRenderingStats', 1100,
{'data': {'frame_count': 0}})])
.readPerfLog()
.then((events) => {
expect(events).toEqual([]);
async.done();
});
}));
it('should throw when ImplThreadRenderingStats contains more than one frame',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([benchmarkEvents.instant(
'BenchmarkInstrumentation::ImplThreadRenderingStats', 1100,
{'data': {'frame_count': 2}})])
.readPerfLog()
.catch((err): any => {
expect(() => {
throw err;
}).toThrowError('multi-frame render stats not supported');
async.done();
});
}));
});
it('should report begin timestamps',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([blinkEvents.create('S', 'someName', 1000)])
.readPerfLog()
.then((events) => {
expect(events).toEqual([normEvents.markStart('someName', 1.0)]);
async.done();
});
}));
it('should report end timestamps',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([blinkEvents.create('F', 'someName', 1000)])
.readPerfLog()
.then((events) => {
expect(events).toEqual([normEvents.markEnd('someName', 1.0)]);
async.done();
});
}));
it('should throw an error on buffer overflow',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension(
[
chromeTimelineEvents.start('FunctionCall', 1234),
],
CHROME45_USER_AGENT, 'Tracing.bufferUsage')
.readPerfLog()
.catch((err): any => {
expect(() => {
throw err;
}).toThrowError('The DevTools trace buffer filled during the test!');
async.done();
});
}));
it('should match chrome browsers', () => {
expect(createExtension().supports({'browserName': 'chrome'})).toBe(true);
expect(createExtension().supports({'browserName': 'Chrome'})).toBe(true);
});
});
});
}
class MockDriverAdapter extends WebDriverAdapter {
constructor(private _log: any[], private _events: any[], private _messageMethod: string) {
super();
}
executeScript(script: string) {
this._log.push(['executeScript', script]);
return Promise.resolve(null);
}
logs(type: string) {
this._log.push(['logs', type]);
if (type === 'performance') {
return Promise.resolve(this._events.map(
(event) => ({
'message': JSON.stringify(
{'message': {'method': this._messageMethod, 'params': event}}, null, 2)
})));
} else {
return null;
}
}
}

View File

@ -0,0 +1,195 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AsyncTestCompleter, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
import {IOsDriverExtension, ReflectiveInjector, WebDriverAdapter, WebDriverExtension} from '../../index';
import {TraceEventFactory} from '../trace_event_factory';
export function main() {
describe('ios driver extension', () => {
let log: any[];
let extension: IOsDriverExtension;
const normEvents = new TraceEventFactory('timeline', 'pid0');
function createExtension(perfRecords: any[] = null): WebDriverExtension {
if (!perfRecords) {
perfRecords = [];
}
log = [];
extension =
ReflectiveInjector
.resolveAndCreate([
IOsDriverExtension.PROVIDERS,
{provide: WebDriverAdapter, useValue: new MockDriverAdapter(log, perfRecords)}
])
.get(IOsDriverExtension);
return extension;
}
it('should throw on forcing gc', () => {
expect(() => createExtension().gc()).toThrowError('Force GC is not supported on iOS');
});
it('should mark the timeline via console.time()',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension().timeBegin('someName').then((_) => {
expect(log).toEqual([['executeScript', `console.time('someName');`]]);
async.done();
});
}));
it('should mark the timeline via console.timeEnd()',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension().timeEnd('someName', null).then((_) => {
expect(log).toEqual([['executeScript', `console.timeEnd('someName');`]]);
async.done();
});
}));
it('should mark the timeline via console.time() and console.timeEnd()',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension().timeEnd('name1', 'name2').then((_) => {
expect(log).toEqual(
[['executeScript', `console.timeEnd('name1');console.time('name2');`]]);
async.done();
});
}));
describe('readPerfLog', () => {
it('should execute a dummy script before reading them',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
// TODO(tbosch): This seems to be a bug in ChromeDriver:
// Sometimes it does not report the newest events of the performance log
// to the WebDriver client unless a script is executed...
createExtension([]).readPerfLog().then((_) => {
expect(log).toEqual([['executeScript', '1+1'], ['logs', 'performance']]);
async.done();
});
}));
it('should report FunctionCall records as "script"',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([durationRecord('FunctionCall', 1, 5)]).readPerfLog().then((events) => {
expect(events).toEqual([normEvents.start('script', 1), normEvents.end('script', 5)]);
async.done();
});
}));
it('should ignore FunctionCalls from webdriver',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([internalScriptRecord(1, 5)]).readPerfLog().then((events) => {
expect(events).toEqual([]);
async.done();
});
}));
it('should report begin time', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([timeBeginRecord('someName', 12)]).readPerfLog().then((events) => {
expect(events).toEqual([normEvents.markStart('someName', 12)]);
async.done();
});
}));
it('should report end timestamps',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([timeEndRecord('someName', 12)]).readPerfLog().then((events) => {
expect(events).toEqual([normEvents.markEnd('someName', 12)]);
async.done();
});
}));
['RecalculateStyles', 'Layout', 'UpdateLayerTree', 'Paint', 'Rasterize', 'CompositeLayers']
.forEach((recordType) => {
it(`should report ${recordType}`,
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([durationRecord(recordType, 0, 1)])
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.start('render', 0),
normEvents.end('render', 1),
]);
async.done();
});
}));
});
it('should walk children', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
createExtension([durationRecord('FunctionCall', 1, 5, [timeBeginRecord('someName', 2)])])
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.start('script', 1), normEvents.markStart('someName', 2),
normEvents.end('script', 5)
]);
async.done();
});
}));
it('should match safari browsers', () => {
expect(createExtension().supports({'browserName': 'safari'})).toBe(true);
expect(createExtension().supports({'browserName': 'Safari'})).toBe(true);
});
});
});
}
function timeBeginRecord(name: string, time: number) {
return {'type': 'Time', 'startTime': time, 'data': {'message': name}};
}
function timeEndRecord(name: string, time: number) {
return {'type': 'TimeEnd', 'startTime': time, 'data': {'message': name}};
}
function durationRecord(type: string, startTime: number, endTime: number, children: any[] = null) {
if (!children) {
children = [];
}
return {'type': type, 'startTime': startTime, 'endTime': endTime, 'children': children};
}
function internalScriptRecord(startTime: number, endTime: number) {
return {
'type': 'FunctionCall',
'startTime': startTime,
'endTime': endTime,
'data': {'scriptName': 'InjectedScript'}
};
}
class MockDriverAdapter extends WebDriverAdapter {
constructor(private _log: any[], private _perfRecords: any[]) { super(); }
executeScript(script: string) {
this._log.push(['executeScript', script]);
return Promise.resolve(null);
}
logs(type: string) {
this._log.push(['logs', type]);
if (type === 'performance') {
return Promise.resolve(this._perfRecords.map(function(record) {
return {
'message': JSON.stringify(
{'message': {'method': 'Timeline.eventRecorded', 'params': {'record': record}}}, null,
2)
};
}));
} else {
return null;
}
}
}

View File

@ -0,0 +1,26 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": ["es6", "dom"],
"noImplicitAny": true,
"sourceMap": true,
"baseUrl": ".",
"paths": {
"@angular/core": ["../../../dist/packages-dist/core"]
},
"experimentalDecorators": true,
"rootDir": ".",
"sourceRoot": ".",
"outDir": "../../../dist/packages-dist/benchpress",
"declaration": true,
"skipLibCheck": true
},
"exclude": ["integrationtest"],
"files": [
"index.ts",
"../../../node_modules/@types/node/index.d.ts",
"../../../node_modules/@types/jasmine/index.d.ts",
"../../../node_modules/zone.js/dist/zone.js.d.ts"
]
}

View File

@ -1 +0,0 @@
export 'index.dart';

View File

@ -1,5 +1,16 @@
export * from './src/pipes';
export * from './src/directives';
export * from './src/forms-deprecated';
export * from './src/common_directives';
export * from './src/location';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @module
* @description
* Entry point for all public APIs of the common package.
*/
export * from './src/common';
// This file only reexports content of the `src` folder. Keep it that way.

View File

@ -1,9 +1,9 @@
{
"name": "@angular/common",
"version": "0.0.0-PLACEHOLDER",
"description": "",
"main": "index.js",
"jsnext:main": "esm/index.js",
"description": "Angular - commonly needed directives and services",
"main": "bundles/common.umd.js",
"module": "index.js",
"typings": "index.d.ts",
"author": "angular",
"license": "MIT",

View File

@ -0,0 +1,20 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
export default {
entry: '../../../dist/packages-dist/common/testing/index.js',
dest: '../../../dist/packages-dist/common/bundles/common-testing.umd.js',
format: 'umd',
moduleName: 'ng.common.testing',
globals: {
'@angular/core': 'ng.core',
'@angular/common': 'ng.common',
'rxjs/Observable': 'Rx',
'rxjs/Subject': 'Rx'
}
};

View File

@ -1,17 +1,19 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
export default {
entry: '../../../dist/packages-dist/common/esm/index.js',
dest: '../../../dist/packages-dist/common/esm/common.umd.js',
entry: '../../../dist/packages-dist/common/index.js',
dest: '../../../dist/packages-dist/common/bundles/common.umd.js',
format: 'umd',
moduleName: 'ng.common',
globals: {
'@angular/core': 'ng.core',
'rxjs/Observable': 'Rx',
'rxjs/Subject': 'Rx',
'rxjs/observable/PromiseObservable': 'Rx', // this is wrong, but this stuff has changed in rxjs b.6 so we need to fix it when we update.
'rxjs/operator/toPromise': 'Rx.Observable.prototype',
'rxjs/Observable': 'Rx'
},
plugins: [
// nodeResolve({ jsnext: true, main: true }),
]
}
}
};

View File

@ -0,0 +1,20 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @module
* @description
* Entry point for all public APIs of the common package.
*/
export * from './location/index';
export {NgLocalization} from './localization';
export {CommonModule} from './common_module';
export {NgClass, NgFor, NgIf, NgPlural, NgPluralCase, NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault, NgTemplateOutlet} from './directives/index';
export {AsyncPipe, DatePipe, I18nPluralPipe, I18nSelectPipe, JsonPipe, LowerCasePipe, CurrencyPipe, DecimalPipe, PercentPipe, SlicePipe, UpperCasePipe} from './pipes/index';
export {VERSION} from './version';
export {Version} from '@angular/core';

View File

@ -1,52 +0,0 @@
import {Type} from '@angular/core';
import {CORE_DIRECTIVES} from './directives';
import {FORM_DIRECTIVES} from './forms-deprecated';
/**
* A collection of Angular core directives that are likely to be used in each and every Angular
* application. This includes core directives (e.g., NgIf and NgFor), and forms directives (e.g.,
* NgModel).
*
* This collection can be used to quickly enumerate all the built-in directives in the `directives`
* property of the `@Component` decorator.
*
* ### Example
*
* Instead of writing:
*
* ```typescript
* import {NgClass, NgIf, NgFor, NgSwitch, NgSwitchWhen, NgSwitchDefault, NgModel, NgForm} from
* '@angular/common';
* import {OtherDirective} from './myDirectives';
*
* @Component({
* selector: 'my-component',
* templateUrl: 'myComponent.html',
* directives: [NgClass, NgIf, NgFor, NgSwitch, NgSwitchWhen, NgSwitchDefault, NgModel, NgForm,
* OtherDirective]
* })
* export class MyComponent {
* ...
* }
* ```
* one could import all the common directives at once:
*
* ```typescript
* import {COMMON_DIRECTIVES} from '@angular/common';
* import {OtherDirective} from './myDirectives';
*
* @Component({
* selector: 'my-component',
* templateUrl: 'myComponent.html',
* directives: [COMMON_DIRECTIVES, OtherDirective]
* })
* export class MyComponent {
* ...
* }
* ```
*
* @experimental Contains forms which are experimental.
*/
export const COMMON_DIRECTIVES: Type[][] = /*@ts2dart_const*/[CORE_DIRECTIVES, FORM_DIRECTIVES];

View File

@ -0,0 +1,30 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {NgModule} from '@angular/core';
import {COMMON_DIRECTIVES} from './directives/index';
import {NgLocaleLocalization, NgLocalization} from './localization';
import {COMMON_PIPES} from './pipes/index';
// Note: This does not contain the location providers,
// as they need some platform specific implementations to work.
/**
* The module that includes all the basic Angular directives like {@link NgIf}, {@link NgFor}, ...
*
* @stable
*/
@NgModule({
declarations: [COMMON_DIRECTIVES, COMMON_PIPES],
exports: [COMMON_DIRECTIVES, COMMON_PIPES],
providers: [
{provide: NgLocalization, useClass: NgLocaleLocalization},
],
})
export class CommonModule {
}

View File

@ -1,13 +0,0 @@
/**
* @module
* @description
* Common directives shipped with Angular.
*/
export {CORE_DIRECTIVES} from './directives/core_directives';
export {NgClass} from './directives/ng_class';
export {NgFor} from './directives/ng_for';
export {NgIf} from './directives/ng_if';
export {NgLocalization, NgPlural, NgPluralCase} from './directives/ng_plural';
export {NgStyle} from './directives/ng_style';
export {NgSwitch, NgSwitchCase, NgSwitchDefault} from './directives/ng_switch';
export {NgTemplateOutlet} from './directives/ng_template_outlet';

View File

@ -1,66 +0,0 @@
import {Type} from '../facade/lang';
import {NgClass} from './ng_class';
import {NgFor} from './ng_for';
import {NgIf} from './ng_if';
import {NgPlural, NgPluralCase} from './ng_plural';
import {NgStyle} from './ng_style';
import {NgSwitch, NgSwitchCase, NgSwitchDefault} from './ng_switch';
import {NgTemplateOutlet} from './ng_template_outlet';
/**
* A collection of Angular core directives that are likely to be used in each and every Angular
* application.
*
* This collection can be used to quickly enumerate all the built-in directives in the `directives`
* property of the `@Component` annotation.
*
* ### Example ([live demo](http://plnkr.co/edit/yakGwpCdUkg0qfzX5m8g?p=preview))
*
* Instead of writing:
*
* ```typescript
* import {NgClass, NgIf, NgFor, NgSwitch, NgSwitchWhen, NgSwitchDefault} from '@angular/common';
* import {OtherDirective} from './myDirectives';
*
* @Component({
* selector: 'my-component',
* templateUrl: 'myComponent.html',
* directives: [NgClass, NgIf, NgFor, NgSwitch, NgSwitchWhen, NgSwitchDefault, OtherDirective]
* })
* export class MyComponent {
* ...
* }
* ```
* one could import all the core directives at once:
*
* ```typescript
* import {CORE_DIRECTIVES} from '@angular/common';
* import {OtherDirective} from './myDirectives';
*
* @Component({
* selector: 'my-component',
* templateUrl: 'myComponent.html',
* directives: [CORE_DIRECTIVES, OtherDirective]
* })
* export class MyComponent {
* ...
* }
* ```
*
* @stable
*/
export const CORE_DIRECTIVES: Type[] = /*@ts2dart_const*/[
NgClass,
NgFor,
NgIf,
NgTemplateOutlet,
NgStyle,
NgSwitch,
NgSwitchCase,
NgSwitchDefault,
NgPlural,
NgPluralCase,
];

View File

@ -0,0 +1,47 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Provider} from '@angular/core';
import {NgClass} from './ng_class';
import {NgFor} from './ng_for';
import {NgIf} from './ng_if';
import {NgPlural, NgPluralCase} from './ng_plural';
import {NgStyle} from './ng_style';
import {NgSwitch, NgSwitchCase, NgSwitchDefault} from './ng_switch';
import {NgTemplateOutlet} from './ng_template_outlet';
export {
NgClass,
NgFor,
NgIf,
NgPlural,
NgPluralCase,
NgStyle,
NgSwitch,
NgSwitchCase,
NgSwitchDefault,
NgTemplateOutlet
};
/**
* A collection of Angular directives that are likely to be used in each and every Angular
* application.
*/
export const COMMON_DIRECTIVES: Provider[] = [
NgClass,
NgFor,
NgIf,
NgTemplateOutlet,
NgStyle,
NgSwitch,
NgSwitchCase,
NgSwitchDefault,
NgPlural,
NgPluralCase,
];

View File

@ -1,134 +1,107 @@
import {CollectionChangeRecord, Directive, DoCheck, ElementRef, IterableDiffer, IterableDiffers, KeyValueChangeRecord, KeyValueDiffer, KeyValueDiffers, OnDestroy, Renderer} from '@angular/core';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {StringMapWrapper, isListLikeIterable} from '../facade/collection';
import {isArray, isPresent, isString} from '../facade/lang';
import {CollectionChangeRecord, Directive, DoCheck, ElementRef, Input, IterableDiffer, IterableDiffers, KeyValueChangeRecord, KeyValueDiffer, KeyValueDiffers, Renderer} from '@angular/core';
import {isListLikeIterable} from '../facade/collection';
import {stringify} from '../facade/lang';
/**
* The `NgClass` directive conditionally adds and removes CSS classes on an HTML element based on
* an expression's evaluation result.
* @ngModule CommonModule
*
* The result of an expression evaluation is interpreted differently depending on type of
* the expression evaluation result:
* - `string` - all the CSS classes listed in a string (space delimited) are added
* - `Array` - all the CSS classes (Array elements) are added
* - `Object` - each key corresponds to a CSS class name while values are interpreted as expressions
* evaluating to `Boolean`. If a given expression evaluates to `true` a corresponding CSS class
* is added - otherwise it is removed.
*
* While the `NgClass` directive can interpret expressions evaluating to `string`, `Array`
* or `Object`, the `Object`-based version is the most often used and has an advantage of keeping
* all the CSS class names in a template.
*
* ### Example ([live demo](http://plnkr.co/edit/a4YdtmWywhJ33uqfpPPn?p=preview)):
* @whatItDoes Adds and removes CSS classes on an HTML element.
*
* @howToUse
* ```
* import {Component} from '@angular/core';
* import {NgClass} from '@angular/common';
* <some-element [ngClass]="'first second'">...</some-element>
*
* @Component({
* selector: 'toggle-button',
* inputs: ['isDisabled'],
* template: `
* <div class="button" [ngClass]="{active: isOn, disabled: isDisabled}"
* (click)="toggle(!isOn)">
* Click me!
* </div>`,
* styles: [`
* .button {
* width: 120px;
* border: medium solid black;
* }
* <some-element [ngClass]="['first', 'second']">...</some-element>
*
* .active {
* background-color: red;
* }
* <some-element [ngClass]="{'first': true, 'second': true, 'third': false}">...</some-element>
*
* .disabled {
* color: gray;
* border: medium solid gray;
* }
* `],
* directives: [NgClass]
* })
* class ToggleButton {
* isOn = false;
* isDisabled = false;
* <some-element [ngClass]="stringExp|arrayExp|objExp">...</some-element>
*
* toggle(newState) {
* if (!this.isDisabled) {
* this.isOn = newState;
* }
* }
* }
* <some-element [ngClass]="{'class1 class2 class3' : true}">...</some-element>
* ```
*
* @description
*
* The CSS classes are updated as follows, depending on the type of the expression evaluation:
* - `string` - the CSS classes listed in the string (space delimited) are added,
* - `Array` - the CSS classes declared as Array elements are added,
* - `Object` - keys are CSS classes that get added when the expression given in the value
* evaluates to a truthy value, otherwise they are removed.
*
* @stable
*/
@Directive({selector: '[ngClass]', inputs: ['rawClass: ngClass', 'initialClasses: class']})
export class NgClass implements DoCheck, OnDestroy {
@Directive({selector: '[ngClass]'})
export class NgClass implements DoCheck {
private _iterableDiffer: IterableDiffer;
private _keyValueDiffer: KeyValueDiffer;
private _initialClasses: string[] = [];
private _rawClass: string[]|Set<string>;
private _rawClass: string[]|Set<string>|{[klass: string]: any};
constructor(
private _iterableDiffers: IterableDiffers, private _keyValueDiffers: KeyValueDiffers,
private _ngEl: ElementRef, private _renderer: Renderer) {}
set initialClasses(v: string) {
@Input('class')
set klass(v: string) {
this._applyInitialClasses(true);
this._initialClasses = isPresent(v) && isString(v) ? v.split(' ') : [];
this._initialClasses = typeof v === 'string' ? v.split(/\s+/) : [];
this._applyInitialClasses(false);
this._applyClasses(this._rawClass, false);
}
set rawClass(v: string|string[]|Set<string>|{[key: string]: any}) {
@Input()
set ngClass(v: string|string[]|Set<string>|{[klass: string]: any}) {
this._cleanupClasses(this._rawClass);
if (isString(v)) {
v = (<string>v).split(' ');
}
this._rawClass = <string[]|Set<string>>v;
this._iterableDiffer = null;
this._keyValueDiffer = null;
if (isPresent(v)) {
if (isListLikeIterable(v)) {
this._iterableDiffer = this._iterableDiffers.find(v).create(null);
this._rawClass = typeof v === 'string' ? v.split(/\s+/) : v;
if (this._rawClass) {
if (isListLikeIterable(this._rawClass)) {
this._iterableDiffer = this._iterableDiffers.find(this._rawClass).create(null);
} else {
this._keyValueDiffer = this._keyValueDiffers.find(v).create(null);
this._keyValueDiffer = this._keyValueDiffers.find(this._rawClass).create(null);
}
}
}
ngDoCheck(): void {
if (isPresent(this._iterableDiffer)) {
var changes = this._iterableDiffer.diff(this._rawClass);
if (isPresent(changes)) {
if (this._iterableDiffer) {
const changes = this._iterableDiffer.diff(this._rawClass);
if (changes) {
this._applyIterableChanges(changes);
}
}
if (isPresent(this._keyValueDiffer)) {
var changes = this._keyValueDiffer.diff(this._rawClass);
if (isPresent(changes)) {
} else if (this._keyValueDiffer) {
const changes = this._keyValueDiffer.diff(this._rawClass);
if (changes) {
this._applyKeyValueChanges(changes);
}
}
}
ngOnDestroy(): void { this._cleanupClasses(this._rawClass); }
private _cleanupClasses(rawClassVal: string[]|Set<string>|{[key: string]: any}): void {
private _cleanupClasses(rawClassVal: string[]|Set<string>|{[klass: string]: any}): void {
this._applyClasses(rawClassVal, true);
this._applyInitialClasses(false);
}
private _applyKeyValueChanges(changes: any): void {
changes.forEachAddedItem(
(record: KeyValueChangeRecord) => { this._toggleClass(record.key, record.currentValue); });
(record: KeyValueChangeRecord) => this._toggleClass(record.key, record.currentValue));
changes.forEachChangedItem(
(record: KeyValueChangeRecord) => { this._toggleClass(record.key, record.currentValue); });
(record: KeyValueChangeRecord) => this._toggleClass(record.key, record.currentValue));
changes.forEachRemovedItem((record: KeyValueChangeRecord) => {
if (record.previousValue) {
this._toggleClass(record.key, false);
@ -137,43 +110,41 @@ export class NgClass implements DoCheck, OnDestroy {
}
private _applyIterableChanges(changes: any): void {
changes.forEachAddedItem(
(record: CollectionChangeRecord) => { this._toggleClass(record.item, true); });
changes.forEachAddedItem((record: CollectionChangeRecord) => {
if (typeof record.item === 'string') {
this._toggleClass(record.item, true);
} else {
throw new Error(
`NgClass can only toggle CSS classes expressed as strings, got ${stringify(record.item)}`);
}
});
changes.forEachRemovedItem(
(record: CollectionChangeRecord) => { this._toggleClass(record.item, false); });
(record: CollectionChangeRecord) => this._toggleClass(record.item, false));
}
private _applyInitialClasses(isCleanup: boolean) {
this._initialClasses.forEach(className => this._toggleClass(className, !isCleanup));
this._initialClasses.forEach(klass => this._toggleClass(klass, !isCleanup));
}
private _applyClasses(
rawClassVal: string[]|Set<string>|{[key: string]: any}, isCleanup: boolean) {
if (isPresent(rawClassVal)) {
if (isArray(rawClassVal)) {
(<string[]>rawClassVal).forEach(className => this._toggleClass(className, !isCleanup));
} else if (rawClassVal instanceof Set) {
(<Set<string>>rawClassVal).forEach(className => this._toggleClass(className, !isCleanup));
if (rawClassVal) {
if (Array.isArray(rawClassVal) || rawClassVal instanceof Set) {
(<any>rawClassVal).forEach((klass: string) => this._toggleClass(klass, !isCleanup));
} else {
StringMapWrapper.forEach(
<{[k: string]: any}>rawClassVal, (expVal: any, className: string) => {
if (isPresent(expVal)) this._toggleClass(className, !isCleanup);
});
Object.keys(rawClassVal).forEach(klass => {
if (rawClassVal[klass] != null) this._toggleClass(klass, !isCleanup);
});
}
}
}
private _toggleClass(className: string, enabled: boolean): void {
className = className.trim();
if (className.length > 0) {
if (className.indexOf(' ') > -1) {
var classes = className.split(/\s+/g);
for (var i = 0, len = classes.length; i < len; i++) {
this._renderer.setElementClass(this._ngEl.nativeElement, classes[i], enabled);
}
} else {
this._renderer.setElementClass(this._ngEl.nativeElement, className, enabled);
}
private _toggleClass(klass: string, enabled: boolean): void {
klass = klass.trim();
if (klass) {
klass.split(/\s+/g).forEach(
klass => { this._renderer.setElementClass(this._ngEl.nativeElement, klass, enabled); });
}
}
}

View File

@ -1,7 +1,14 @@
import {ChangeDetectorRef, CollectionChangeRecord, DefaultIterableDiffer, Directive, DoCheck, EmbeddedViewRef, IterableDiffer, IterableDiffers, TemplateRef, TrackByFn, ViewContainerRef} from '@angular/core';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {BaseException} from '../facade/exceptions';
import {getTypeNameForDebugging, isBlank, isPresent} from '../facade/lang';
import {ChangeDetectorRef, CollectionChangeRecord, DefaultIterableDiffer, Directive, DoCheck, EmbeddedViewRef, Input, IterableDiffer, IterableDiffers, OnChanges, SimpleChanges, TemplateRef, TrackByFn, ViewContainerRef, isDevMode} from '@angular/core';
import {getTypeNameForDebugging} from '../facade/lang';
export class NgForRow {
constructor(public $implicit: any, public index: number, public count: number) {}
@ -55,11 +62,22 @@ export class NgForRow {
* elements were deleted and all new elements inserted). This is an expensive operation and should
* be avoided if possible.
*
* To customize the default tracking algorithm, `NgFor` supports `trackBy` option.
* `trackBy` takes a function which has two arguments: `index` and `item`.
* If `trackBy` is given, Angular tracks changes by the return value of the function.
*
* ### Syntax
*
* - `<li *ngFor="let item of items; let i = index">...</li>`
* - `<li template="ngFor let item of items; let i = index">...</li>`
* - `<template ngFor let-item [ngForOf]="items" let-i="index"><li>...</li></template>`
* - `<li *ngFor="let item of items; let i = index; trackBy: trackByFn">...</li>`
* - `<li template="ngFor let item of items; let i = index; trackBy: trackByFn">...</li>`
*
* With `<template>` element:
*
* ```
* <template ngFor let-item [ngForOf]="items" let-i="index" [ngForTrackBy]="trackByFn">
* <li>...</li>
* </template>
* ```
*
* ### Example
*
@ -68,77 +86,91 @@ export class NgForRow {
*
* @stable
*/
@Directive({selector: '[ngFor][ngForOf]', inputs: ['ngForTrackBy', 'ngForOf', 'ngForTemplate']})
export class NgFor implements DoCheck {
/** @internal */
_ngForOf: any;
/** @internal */
_ngForTrackBy: TrackByFn;
private _differ: IterableDiffer;
@Directive({selector: '[ngFor][ngForOf]'})
export class NgFor implements DoCheck, OnChanges {
@Input() ngForOf: any;
@Input()
set ngForTrackBy(fn: TrackByFn) {
if (isDevMode() && fn != null && typeof fn !== 'function') {
// TODO(vicb): use a log service once there is a public one available
if (<any>console && <any>console.warn) {
console.warn(
`trackBy must be a function, but received ${JSON.stringify(fn)}. ` +
`See https://angular.io/docs/ts/latest/api/common/index/NgFor-directive.html#!#change-propagation for more information.`);
}
}
this._trackByFn = fn;
}
get ngForTrackBy(): TrackByFn { return this._trackByFn; }
private _differ: IterableDiffer = null;
private _trackByFn: TrackByFn;
constructor(
private _viewContainer: ViewContainerRef, private _templateRef: TemplateRef<NgForRow>,
private _iterableDiffers: IterableDiffers, private _cdr: ChangeDetectorRef) {}
private _viewContainer: ViewContainerRef, private _template: TemplateRef<NgForRow>,
private _differs: IterableDiffers, private _cdr: ChangeDetectorRef) {}
set ngForOf(value: any) {
this._ngForOf = value;
if (isBlank(this._differ) && isPresent(value)) {
try {
this._differ = this._iterableDiffers.find(value).create(this._cdr, this._ngForTrackBy);
} catch (e) {
throw new BaseException(
`Cannot find a differ supporting object '${value}' of type '${getTypeNameForDebugging(value)}'. NgFor only supports binding to Iterables such as Arrays.`);
@Input()
set ngForTemplate(value: TemplateRef<NgForRow>) {
if (value) {
this._template = value;
}
}
ngOnChanges(changes: SimpleChanges): void {
if ('ngForOf' in changes) {
// React on ngForOf changes only once all inputs have been initialized
const value = changes['ngForOf'].currentValue;
if (!this._differ && value) {
try {
this._differ = this._differs.find(value).create(this._cdr, this.ngForTrackBy);
} catch (e) {
throw new Error(
`Cannot find a differ supporting object '${value}' of type '${getTypeNameForDebugging(value)}'. NgFor only supports binding to Iterables such as Arrays.`);
}
}
}
}
set ngForTemplate(value: TemplateRef<NgForRow>) {
if (isPresent(value)) {
this._templateRef = value;
}
}
set ngForTrackBy(value: TrackByFn) { this._ngForTrackBy = value; }
ngDoCheck() {
if (isPresent(this._differ)) {
var changes = this._differ.diff(this._ngForOf);
if (isPresent(changes)) this._applyChanges(changes);
ngDoCheck(): void {
if (this._differ) {
const changes = this._differ.diff(this.ngForOf);
if (changes) this._applyChanges(changes);
}
}
private _applyChanges(changes: DefaultIterableDiffer) {
// TODO(rado): check if change detection can produce a change record that is
// easier to consume than current.
var recordViewTuples: RecordViewTuple[] = [];
changes.forEachRemovedItem(
(removedRecord: CollectionChangeRecord) =>
recordViewTuples.push(new RecordViewTuple(removedRecord, null)));
const insertTuples: RecordViewTuple[] = [];
changes.forEachOperation(
(item: CollectionChangeRecord, adjustedPreviousIndex: number, currentIndex: number) => {
if (item.previousIndex == null) {
const view = this._viewContainer.createEmbeddedView(
this._template, new NgForRow(null, null, null), currentIndex);
const tuple = new RecordViewTuple(item, view);
insertTuples.push(tuple);
} else if (currentIndex == null) {
this._viewContainer.remove(adjustedPreviousIndex);
} else {
const view = this._viewContainer.get(adjustedPreviousIndex);
this._viewContainer.move(view, currentIndex);
const tuple = new RecordViewTuple(item, <EmbeddedViewRef<NgForRow>>view);
insertTuples.push(tuple);
}
});
changes.forEachMovedItem(
(movedRecord: CollectionChangeRecord) =>
recordViewTuples.push(new RecordViewTuple(movedRecord, null)));
var insertTuples = this._bulkRemove(recordViewTuples);
changes.forEachAddedItem(
(addedRecord: CollectionChangeRecord) =>
insertTuples.push(new RecordViewTuple(addedRecord, null)));
this._bulkInsert(insertTuples);
for (var i = 0; i < insertTuples.length; i++) {
for (let i = 0; i < insertTuples.length; i++) {
this._perViewChange(insertTuples[i].view, insertTuples[i].record);
}
for (var i = 0, ilen = this._viewContainer.length; i < ilen; i++) {
var viewRef = <EmbeddedViewRef<NgForRow>>this._viewContainer.get(i);
for (let i = 0, ilen = this._viewContainer.length; i < ilen; i++) {
const viewRef = <EmbeddedViewRef<NgForRow>>this._viewContainer.get(i);
viewRef.context.index = i;
viewRef.context.count = ilen;
}
changes.forEachIdentityChange((record: any /** TODO #9100 */) => {
var viewRef = <EmbeddedViewRef<NgForRow>>this._viewContainer.get(record.currentIndex);
changes.forEachIdentityChange((record: any) => {
const viewRef = <EmbeddedViewRef<NgForRow>>this._viewContainer.get(record.currentIndex);
viewRef.context.$implicit = record.item;
});
}
@ -146,46 +178,8 @@ export class NgFor implements DoCheck {
private _perViewChange(view: EmbeddedViewRef<NgForRow>, record: CollectionChangeRecord) {
view.context.$implicit = record.item;
}
private _bulkRemove(tuples: RecordViewTuple[]): RecordViewTuple[] {
tuples.sort(
(a: RecordViewTuple, b: RecordViewTuple) =>
a.record.previousIndex - b.record.previousIndex);
var movedTuples: RecordViewTuple[] = [];
for (var i = tuples.length - 1; i >= 0; i--) {
var tuple = tuples[i];
// separate moved views from removed views.
if (isPresent(tuple.record.currentIndex)) {
tuple.view =
<EmbeddedViewRef<NgForRow>>this._viewContainer.detach(tuple.record.previousIndex);
movedTuples.push(tuple);
} else {
this._viewContainer.remove(tuple.record.previousIndex);
}
}
return movedTuples;
}
private _bulkInsert(tuples: RecordViewTuple[]): RecordViewTuple[] {
tuples.sort((a, b) => a.record.currentIndex - b.record.currentIndex);
for (var i = 0; i < tuples.length; i++) {
var tuple = tuples[i];
if (isPresent(tuple.view)) {
this._viewContainer.insert(tuple.view, tuple.record.currentIndex);
} else {
tuple.view = this._viewContainer.createEmbeddedView(
this._templateRef, new NgForRow(null, null, null), tuple.record.currentIndex);
}
}
return tuples;
}
}
class RecordViewTuple {
view: EmbeddedViewRef<NgForRow>;
record: any;
constructor(record: any, view: EmbeddedViewRef<NgForRow>) {
this.record = record;
this.view = view;
}
constructor(public record: any, public view: EmbeddedViewRef<NgForRow>) {}
}

View File

@ -1,19 +1,24 @@
import {Directive, TemplateRef, ViewContainerRef} from '@angular/core';
import {isBlank} from '../facade/lang';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Directive, Input, TemplateRef, ViewContainerRef} from '@angular/core';
/**
* Removes or recreates a portion of the DOM tree based on an {expression}.
*
* If the expression assigned to `ngIf` evaluates to a false value then the element
* If the expression assigned to `ngIf` evaluates to a falsy value then the element
* is removed from the DOM, otherwise a clone of the element is reinserted into the DOM.
*
* ### Example ([live demo](http://plnkr.co/edit/fe0kgemFBtmQOY31b4tw?p=preview)):
*
* ```
* <div *ngIf="errorCount > 0" class="error">
* <!-- Error message displayed when the errorCount property on the current context is greater
* <!-- Error message displayed when the errorCount property in the current context is greater
* than 0. -->
* {{errorCount}} errors detected
* </div>
@ -27,19 +32,19 @@ import {isBlank} from '../facade/lang';
*
* @stable
*/
@Directive({selector: '[ngIf]', inputs: ['ngIf']})
@Directive({selector: '[ngIf]'})
export class NgIf {
private _prevCondition: boolean = null;
private _hasView = false;
constructor(private _viewContainer: ViewContainerRef, private _templateRef: TemplateRef<Object>) {
}
constructor(private _viewContainer: ViewContainerRef, private _template: TemplateRef<Object>) {}
set ngIf(newCondition: any /* boolean */) {
if (newCondition && (isBlank(this._prevCondition) || !this._prevCondition)) {
this._prevCondition = true;
this._viewContainer.createEmbeddedView(this._templateRef);
} else if (!newCondition && (isBlank(this._prevCondition) || this._prevCondition)) {
this._prevCondition = false;
@Input()
set ngIf(condition: any) {
if (condition && !this._hasView) {
this._hasView = true;
this._viewContainer.createEmbeddedView(this._template);
} else if (!condition && this._hasView) {
this._hasView = false;
this._viewContainer.clear();
}
}

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