Compare commits

...

18 Commits
2.4.2 ... 2.4.3

Author SHA1 Message Date
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
69 changed files with 504 additions and 447 deletions

32
.pullapprove.yml Normal file
View File

@ -0,0 +1,32 @@
# Configuration for pullapprove.com
# See ownership spreadsheet:
# https://docs.google.com/spreadsheets/d/1-HIlzfbPYGsPr9KuYMe6bLfc4LXzPjpoALqtYRYTZB0/edit?pli=1#gid=0&vpid=A5
version: 2
group_defaults:
required: 1
reset_on_reopened:
enabled: true
approve_by_comment:
enabled: true
approve_regex: '^(Approved|:\+1:|LGTM)'
groups:
config:
conditions:
files:
- "*.yml"
- "*.json"
teams:
- repoowners
compiler:
conditions:
files:
- "tools/@angular/tsc-wrapped/*"
- "modules/@angular/compiler/*"
- "modules/@angular/compiler-cli/*"
teams:
- compiler-owners
- repoowners

View File

@ -1,3 +1,20 @@
<a name="2.4.3"></a>
## [2.4.3](https://github.com/angular/angular/compare/2.4.2...2.4.3) (2017-01-11)
### Bug Fixes
* **compiler:** avoid evaluating arguments to unknown decorators ([5e9d3db](https://github.com/angular/angular/commit/5e9d3db)), closes [#13605](https://github.com/angular/angular/issues/13605)
* **compiler:** fix template binding parsing (`*directive="-..."`) ([7dc12b9](https://github.com/angular/angular/commit/7dc12b9)), closes [#13800](https://github.com/angular/angular/issues/13800)
* **compiler-cli:** add support for more than 2 levels of nested lazy routes ([6164eb2](https://github.com/angular/angular/commit/6164eb2)), closes [angular/angular-cli#3663](https://github.com/angular/angular-cli/issues/3663)
* **compiler-cli:** avoid handling functions in loadChildren as lazy load routes paths ([313683f](https://github.com/angular/angular/commit/313683f)), closes [angular/angular-cli#3204](https://github.com/angular/angular-cli/issues/3204)
* **i18n:** translate attributes inside elements marked for translation ([d7f2a3c](https://github.com/angular/angular/commit/d7f2a3c))
* **router:** RouterLink mirrors input `target` as attribute ([1c82b58](https://github.com/angular/angular/commit/1c82b58)), closes [#13837](https://github.com/angular/angular/issues/13837)
* **router:** throw an error when navigate to null/undefined path ([61ba223](https://github.com/angular/angular/commit/61ba223)), closes [#10560](https://github.com/angular/angular/issues/10560) [#13384](https://github.com/angular/angular/issues/13384)
* **router:** fix checking for object intersection ([1692265](https://github.com/angular/angular/commit/1692265))
<a name="2.4.2"></a>
## [2.4.2](https://github.com/angular/angular/compare/2.4.1...2.4.2) (2017-01-06)

View File

@ -9,7 +9,7 @@
import {CollectionChangeRecord, Directive, DoCheck, ElementRef, Input, IterableDiffer, IterableDiffers, KeyValueChangeRecord, KeyValueDiffer, KeyValueDiffers, Renderer} from '@angular/core';
import {isListLikeIterable} from '../facade/collection';
import {isPresent, stringify} from '../facade/lang';
import {stringify} from '../facade/lang';
/**
* @ngModule CommonModule
@ -134,7 +134,7 @@ export class NgClass implements DoCheck {
(<any>rawClassVal).forEach((klass: string) => this._toggleClass(klass, !isCleanup));
} else {
Object.keys(rawClassVal).forEach(klass => {
if (isPresent(rawClassVal[klass])) this._toggleClass(klass, !isCleanup);
if (rawClassVal[klass] != null) this._toggleClass(klass, !isCleanup);
});
}
}

View File

@ -21,10 +21,9 @@ import {SwitchView} from './ng_switch';
* @howToUse
* ```
* <some-element [ngPlural]="value">
* <ng-container *ngPluralCase="'=0'">there is nothing</ng-container>
* <ng-container *ngPluralCase="'=1'">there is one</ng-container>
* <ng-container *ngPluralCase="'few'">there are a few</ng-container>
* <ng-container *ngPluralCase="'other'">there are exactly #</ng-container>
* <template ngPluralCase="=0">there is nothing</template>
* <template ngPluralCase="=1">there is one</template>
* <template ngPluralCase="few">there are a few</template>
* </some-element>
* ```
*
@ -90,8 +89,8 @@ export class NgPlural {
* @howToUse
* ```
* <some-element [ngPlural]="value">
* <ng-container *ngPluralCase="'=0'">...</ng-container>
* <ng-container *ngPluralCase="'other'">...</ng-container>
* <template ngPluralCase="=0">...</template>
* <template ngPluralCase="other">...</template>
* </some-element>
*```
*

View File

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

View File

@ -8,7 +8,7 @@
import {Inject, LOCALE_ID, Pipe, PipeTransform, Type} from '@angular/core';
import {NumberWrapper, isBlank, isPresent} from '../facade/lang';
import {NumberWrapper} from '../facade/lang';
import {NumberFormatStyle, NumberFormatter} from './intl';
import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
@ -18,7 +18,7 @@ const _NUMBER_FORMAT_REGEXP = /^(\d+)?\.((\d+)(-(\d+))?)?$/;
function formatNumber(
pipe: Type<any>, locale: string, value: number | string, style: NumberFormatStyle,
digits: string, currency: string = null, currencyAsSymbol: boolean = false): string {
if (isBlank(value)) return null;
if (value == null) return null;
// Convert strings to numbers
value = typeof value === 'string' && NumberWrapper.isNumeric(value) ? +value : value;
@ -41,13 +41,13 @@ function formatNumber(
if (parts === null) {
throw new Error(`${digits} is not a valid digit info for number pipes`);
}
if (isPresent(parts[1])) { // min integer digits
if (parts[1] != null) { // min integer digits
minInt = NumberWrapper.parseIntAutoRadix(parts[1]);
}
if (isPresent(parts[3])) { // min fraction digits
if (parts[3] != null) { // min fraction digits
minFraction = NumberWrapper.parseIntAutoRadix(parts[3]);
}
if (isPresent(parts[5])) { // max fraction digits
if (parts[5] != null) { // max fraction digits
maxFraction = NumberWrapper.parseIntAutoRadix(parts[5]);
}
}

View File

@ -7,7 +7,6 @@
*/
import {Pipe, PipeTransform} from '@angular/core';
import {isBlank} from '../facade/lang';
import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
/**
@ -58,7 +57,7 @@ import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
@Pipe({name: 'slice', pure: false})
export class SlicePipe implements PipeTransform {
transform(value: any, start: number, end?: number): any {
if (isBlank(value)) return value;
if (value == null) return value;
if (!this.supports(value)) {
throw new InvalidPipeArgumentError(SlicePipe, value);

View File

@ -7,7 +7,7 @@
*/
import {CommonModule} from '@angular/common';
import {Component, ContentChild, TemplateRef} from '@angular/core';
import {Component} from '@angular/core';
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {By} from '@angular/platform-browser/src/dom/debug/by';
import {expect} from '@angular/platform-browser/testing/matchers';
@ -29,10 +29,7 @@ export function main() {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
TestComponent,
ComponentUsingTestComponent,
],
declarations: [TestComponent],
imports: [CommonModule],
});
});
@ -77,7 +74,7 @@ export function main() {
}));
it('should iterate over an array of objects', async(() => {
const template = '<ul><li template="ngFor let item of items">{{item["name"]}};</li></ul>';
const template = '<ul><li *ngFor="let item of items">{{item["name"]}};</li></ul>';
fixture = createTestComponent(template);
// INIT
@ -95,7 +92,7 @@ export function main() {
}));
it('should gracefully handle nulls', async(() => {
const template = '<ul><li template="ngFor let item of null">{{item}};</li></ul>';
const template = '<ul><li *ngFor="let item of null">{{item}};</li></ul>';
fixture = createTestComponent(template);
detectChangesAndExpectText('');
@ -140,12 +137,8 @@ export function main() {
}));
it('should repeat over nested arrays', async(() => {
const template = '<div>' +
'<div template="ngFor let item of items">' +
'<div template="ngFor let subitem of item">' +
'{{subitem}}-{{item.length}};' +
'</div>|' +
'</div>' +
const template = '<div *ngFor="let item of items">' +
'<div *ngFor="let subitem of item">{{subitem}}-{{item.length}};</div>|' +
'</div>';
fixture = createTestComponent(template);
@ -157,10 +150,9 @@ export function main() {
}));
it('should repeat over nested arrays with no intermediate element', async(() => {
const template = '<div><template ngFor let-item [ngForOf]="items">' +
'<div template="ngFor let subitem of item">' +
'{{subitem}}-{{item.length}};' +
'</div></template></div>';
const template = '<div *ngFor="let item of items">' +
'<div *ngFor="let subitem of item">{{subitem}}-{{item.length}};</div>' +
'</div>';
fixture = createTestComponent(template);
getComponent().items = [['a', 'b'], ['c']];
@ -170,10 +162,11 @@ export function main() {
detectChangesAndExpectText('e-1;f-2;g-2;');
}));
it('should repeat over nested ngIf that are the last node in the ngFor temlate', async(() => {
const template =
`<div><template ngFor let-item [ngForOf]="items" let-i="index"><div>{{i}}|</div>` +
`<div *ngIf="i % 2 == 0">even|</div></template></div>`;
it('should repeat over nested ngIf that are the last node in the ngFor template', async(() => {
const template = `<div *ngFor="let item of items; let i=index">` +
`<div>{{i}}|</div>` +
`<div *ngIf="i % 2 == 0">even|</div>` +
`</div>`;
fixture = createTestComponent(template);
@ -189,8 +182,7 @@ export function main() {
}));
it('should display indices correctly', async(() => {
const template =
'<div><span template="ngFor: let item of items; let i=index">{{i.toString()}}</span></div>';
const template = '<span *ngFor ="let item of items; let i=index">{{i.toString()}}</span>';
fixture = createTestComponent(template);
getComponent().items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
@ -202,7 +194,7 @@ export function main() {
it('should display first item correctly', async(() => {
const template =
'<div><span template="ngFor: let item of items; let isFirst=first">{{isFirst.toString()}}</span></div>';
'<span *ngFor="let item of items; let isFirst=first">{{isFirst.toString()}}</span>';
fixture = createTestComponent(template);
getComponent().items = [0, 1, 2];
@ -214,7 +206,7 @@ export function main() {
it('should display last item correctly', async(() => {
const template =
'<div><span template="ngFor: let item of items; let isLast=last">{{isLast.toString()}}</span></div>';
'<span *ngFor="let item of items; let isLast=last">{{isLast.toString()}}</span>';
fixture = createTestComponent(template);
getComponent().items = [0, 1, 2];
@ -226,7 +218,7 @@ export function main() {
it('should display even items correctly', async(() => {
const template =
'<div><span template="ngFor: let item of items; let isEven=even">{{isEven.toString()}}</span></div>';
'<span *ngFor="let item of items; let isEven=even">{{isEven.toString()}}</span>';
fixture = createTestComponent(template);
getComponent().items = [0, 1, 2];
@ -238,7 +230,7 @@ export function main() {
it('should display odd items correctly', async(() => {
const template =
'<div><span template="ngFor: let item of items; let isOdd=odd">{{isOdd.toString()}}</span></div>';
'<span *ngFor="let item of items; let isOdd=odd">{{isOdd.toString()}}</span>';
fixture = createTestComponent(template);
getComponent().items = [0, 1, 2, 3];
@ -249,55 +241,38 @@ export function main() {
}));
it('should allow to use a custom template', async(() => {
const tcTemplate =
'<ul><template ngFor [ngForOf]="items" [ngForTemplate]="contentTpl"></template></ul>';
TestBed.overrideComponent(TestComponent, {set: {template: tcTemplate}});
const cutTemplate =
'<test-cmp><li template="let item; let i=index">{{i}}: {{item}};</li></test-cmp>';
TestBed.overrideComponent(ComponentUsingTestComponent, {set: {template: cutTemplate}});
fixture = TestBed.createComponent(ComponentUsingTestComponent);
const testComponent = fixture.debugElement.children[0];
testComponent.componentInstance.items = ['a', 'b', 'c'];
const template =
'<ng-container *ngFor="let item of items; template: tpl"></ng-container>' +
'<template let-item let-i="index" #tpl><p>{{i}}: {{item}};</p></template>';
fixture = createTestComponent(template);
getComponent().items = ['a', 'b', 'c'];
fixture.detectChanges();
expect(testComponent.nativeElement).toHaveText('0: a;1: b;2: c;');
detectChangesAndExpectText('0: a;1: b;2: c;');
}));
it('should use a default template if a custom one is null', async(() => {
const testTemplate = `<ul><template ngFor let-item [ngForOf]="items"
[ngForTemplate]="contentTpl" let-i="index">{{i}}: {{item}};</template></ul>`;
TestBed.overrideComponent(TestComponent, {set: {template: testTemplate}});
const cutTemplate =
'<test-cmp><li template="let item; let i=index">{{i}}: {{item}};</li></test-cmp>';
TestBed.overrideComponent(ComponentUsingTestComponent, {set: {template: cutTemplate}});
fixture = TestBed.createComponent(ComponentUsingTestComponent);
const testComponent = fixture.debugElement.children[0];
testComponent.componentInstance.items = ['a', 'b', 'c'];
const template =
`<ul><ng-container *ngFor="let item of items; template: null; let i=index">{{i}}: {{item}};</ng-container></ul>`;
fixture = createTestComponent(template);
getComponent().items = ['a', 'b', 'c'];
fixture.detectChanges();
expect(testComponent.nativeElement).toHaveText('0: a;1: b;2: c;');
detectChangesAndExpectText('0: a;1: b;2: c;');
}));
it('should use a custom template when both default and a custom one are present', async(() => {
const testTemplate = `<ul><template ngFor let-item [ngForOf]="items"
[ngForTemplate]="contentTpl" let-i="index">{{i}}=> {{item}};</template></ul>`;
TestBed.overrideComponent(TestComponent, {set: {template: testTemplate}});
const cutTemplate =
'<test-cmp><li template="let item; let i=index">{{i}}: {{item}};</li></test-cmp>';
TestBed.overrideComponent(ComponentUsingTestComponent, {set: {template: cutTemplate}});
fixture = TestBed.createComponent(ComponentUsingTestComponent);
const testComponent = fixture.debugElement.children[0];
testComponent.componentInstance.items = ['a', 'b', 'c'];
const template =
'<ng-container *ngFor="let item of items; template: tpl">{{i}};</ng-container>' +
'<template let-item let-i="index" #tpl>{{i}}: {{item}};</template>';
fixture = createTestComponent(template);
getComponent().items = ['a', 'b', 'c'];
fixture.detectChanges();
expect(testComponent.nativeElement).toHaveText('0: a;1: b;2: c;');
detectChangesAndExpectText('0: a;1: b;2: c;');
}));
describe('track by', () => {
it('should console.warn if trackBy is not a function', async(() => {
// TODO(vicb): expect a warning message when we have a proper log service
const template =
`<template ngFor let-item [ngForOf]="items" [ngForTrackBy]="value"></template>`;
const template = `<p *ngFor="let item of items; trackBy: value"></p>`;
fixture = createTestComponent(template);
fixture.componentInstance.value = 0;
fixture.detectChanges();
@ -305,8 +280,7 @@ export function main() {
it('should track by identity when trackBy is to `null` or `undefined`', async(() => {
// TODO(vicb): expect no warning message when we have a proper log service
const template =
`<template ngFor let-item [ngForOf]="items" [ngForTrackBy]="value">{{ item }}</template>`;
const template = `<p *ngFor="let item of items; trackBy: value">{{ item }}</p>`;
fixture = createTestComponent(template);
fixture.componentInstance.items = ['a', 'b', 'c'];
fixture.componentInstance.value = null;
@ -317,7 +291,7 @@ export function main() {
it('should set the context to the component instance', async(() => {
const template =
`<template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackByContext.bind(this)"></template>`;
`<p *ngFor="let item of items; trackBy: trackByContext.bind(this)"></p>`;
fixture = createTestComponent(template);
thisArg = null;
@ -327,9 +301,7 @@ export function main() {
it('should not replace tracked items', async(() => {
const template =
`<template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackById" let-i="index">
<p>{{items[i]}}</p>
</template>`;
`<p *ngFor="let item of items; trackBy: trackById; let i=index">{{items[i]}}</p>`;
fixture = createTestComponent(template);
const buildItemList = () => {
@ -345,7 +317,7 @@ export function main() {
it('should update implicit local variable on view', async(() => {
const template =
`<div><template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackById">{{item['color']}}</template></div>`;
`<div *ngFor="let item of items; trackBy: trackById">{{item['color']}}</div>`;
fixture = createTestComponent(template);
getComponent().items = [{'id': 'a', 'color': 'blue'}];
@ -357,7 +329,7 @@ export function main() {
it('should move items around and keep them updated ', async(() => {
const template =
`<div><template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackById">{{item['color']}}</template></div>`;
`<div *ngFor="let item of items; trackBy: trackById">{{item['color']}}</div>`;
fixture = createTestComponent(template);
getComponent().items = [{'id': 'a', 'color': 'blue'}, {'id': 'b', 'color': 'yellow'}];
@ -368,8 +340,7 @@ export function main() {
}));
it('should handle added and removed items properly when tracking by index', async(() => {
const template =
`<div><template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackByIndex">{{item}}</template></div>`;
const template = `<div *ngFor="let item of items; trackBy: trackByIndex">{{item}}</div>`;
fixture = createTestComponent(template);
getComponent().items = ['a', 'b', 'c', 'd'];
@ -389,7 +360,6 @@ class Foo {
@Component({selector: 'test-cmp', template: ''})
class TestComponent {
@ContentChild(TemplateRef) contentTpl: TemplateRef<Object>;
value: any;
items: any[] = [1, 2];
trackById(index: number, item: any): string { return item['id']; }
@ -397,12 +367,7 @@ class TestComponent {
trackByContext(): void { thisArg = this; }
}
@Component({selector: 'outer-cmp', template: ''})
class ComponentUsingTestComponent {
items: any = [1, 2];
}
const TEMPLATE = '<div><span template="ngFor let item of items">{{item.toString()}};</span></div>';
const TEMPLATE = '<div><span *ngFor="let item of items">{{item.toString()}};</span></div>';
function createTestComponent(template: string = TEMPLATE): ComponentFixture<TestComponent> {
return TestBed.overrideComponent(TestComponent, {set: {template: template}})

View File

@ -9,6 +9,7 @@
import {CommonModule} from '@angular/common';
import {Component} from '@angular/core';
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {By} from '@angular/platform-browser/src/dom/debug/by';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {expect} from '@angular/platform-browser/testing/matchers';
@ -28,131 +29,114 @@ export function main() {
});
it('should work in a template attribute', async(() => {
const template = '<div><span template="ngIf booleanCondition">hello</span></div>';
const template = '<span *ngIf="booleanCondition">hello</span>';
fixture = createTestComponent(template);
fixture.detectChanges();
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(1);
expect(fixture.nativeElement).toHaveText('hello');
}));
it('should work in a template element', async(() => {
const template =
'<div><template [ngIf]="booleanCondition"><span>hello2</span></template></div>';
it('should work on a template element', async(() => {
const template = '<template [ngIf]="booleanCondition">hello2</template>';
fixture = createTestComponent(template);
fixture.detectChanges();
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
expect(fixture.nativeElement).toHaveText('hello2');
}));
it('should toggle node when condition changes', async(() => {
const template = '<div><span template="ngIf booleanCondition">hello</span></div>';
const template = '<span *ngIf="booleanCondition">hello</span>';
fixture = createTestComponent(template);
getComponent().booleanCondition = false;
fixture.detectChanges();
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(0);
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(0);
expect(fixture.nativeElement).toHaveText('');
getComponent().booleanCondition = true;
fixture.detectChanges();
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(1);
expect(fixture.nativeElement).toHaveText('hello');
getComponent().booleanCondition = false;
fixture.detectChanges();
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(0);
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(0);
expect(fixture.nativeElement).toHaveText('');
}));
it('should handle nested if correctly', async(() => {
const template =
'<div><template [ngIf]="booleanCondition"><span *ngIf="nestedBooleanCondition">hello</span></template></div>';
'<div *ngIf="booleanCondition"><span *ngIf="nestedBooleanCondition">hello</span></div>';
fixture = createTestComponent(template);
getComponent().booleanCondition = false;
fixture.detectChanges();
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(0);
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(0);
expect(fixture.nativeElement).toHaveText('');
getComponent().booleanCondition = true;
fixture.detectChanges();
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(1);
expect(fixture.nativeElement).toHaveText('hello');
getComponent().nestedBooleanCondition = false;
fixture.detectChanges();
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(0);
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(0);
expect(fixture.nativeElement).toHaveText('');
getComponent().nestedBooleanCondition = true;
fixture.detectChanges();
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(1);
expect(fixture.nativeElement).toHaveText('hello');
getComponent().booleanCondition = false;
fixture.detectChanges();
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(0);
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(0);
expect(fixture.nativeElement).toHaveText('');
}));
it('should update several nodes with if', async(() => {
const template = '<div>' +
'<span template="ngIf numberCondition + 1 >= 2">helloNumber</span>' +
'<span template="ngIf stringCondition == \'foo\'">helloString</span>' +
'<span template="ngIf functionCondition(stringCondition, numberCondition)">helloFunction</span>' +
'</div>';
const template = '<span *ngIf="numberCondition + 1 >= 2">helloNumber</span>' +
'<span *ngIf="stringCondition == \'foo\'">helloString</span>' +
'<span *ngIf="functionCondition(stringCondition, numberCondition)">helloFunction</span>';
fixture = createTestComponent(template);
fixture.detectChanges();
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(3);
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(3);
expect(getDOM().getText(fixture.nativeElement))
.toEqual('helloNumberhelloStringhelloFunction');
getComponent().numberCondition = 0;
fixture.detectChanges();
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(1);
expect(fixture.nativeElement).toHaveText('helloString');
getComponent().numberCondition = 1;
getComponent().stringCondition = 'bar';
fixture.detectChanges();
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(1);
expect(fixture.nativeElement).toHaveText('helloNumber');
}));
it('should not add the element twice if the condition goes from true to true (JS)',
async(() => {
const template = '<div><span template="ngIf numberCondition">hello</span></div>';
it('should not add the element twice if the condition goes from truthy to truthy', async(() => {
const template = '<span *ngIf="numberCondition">hello</span>';
fixture = createTestComponent(template);
fixture.detectChanges();
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
let els = fixture.debugElement.queryAll(By.css('span'));
expect(els.length).toEqual(1);
getDOM().addClass(els[0].nativeElement, 'marker');
expect(fixture.nativeElement).toHaveText('hello');
getComponent().numberCondition = 2;
fixture.detectChanges();
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
els = fixture.debugElement.queryAll(By.css('span'));
expect(els.length).toEqual(1);
expect(getDOM().hasClass(els[0].nativeElement, 'marker')).toBe(true);
expect(fixture.nativeElement).toHaveText('hello');
}));
it('should not recreate the element if the condition goes from true to true (JS)', async(() => {
const template = '<div><span template="ngIf numberCondition">hello</span></div>';
fixture = createTestComponent(template);
fixture.detectChanges();
getDOM().addClass(getDOM().querySelector(fixture.nativeElement, 'span'), 'foo');
getComponent().numberCondition = 2;
fixture.detectChanges();
expect(getDOM().hasClass(getDOM().querySelector(fixture.nativeElement, 'span'), 'foo'))
.toBe(true);
}));
});
}

View File

@ -33,11 +33,10 @@ export function main() {
});
it('should display the template according to the exact value', async(() => {
const template = '<div>' +
'<ul [ngPlural]="switchValue">' +
const template = '<ul [ngPlural]="switchValue">' +
'<template ngPluralCase="=0"><li>you have no messages.</li></template>' +
'<template ngPluralCase="=1"><li>you have one message.</li></template>' +
'</ul></div>';
'</ul>';
fixture = createTestComponent(template);
@ -51,10 +50,9 @@ export function main() {
// https://github.com/angular/angular/issues/9868
// https://github.com/angular/angular/issues/9882
it('should not throw when ngPluralCase contains expressions', async(() => {
const template = '<div>' +
'<ul [ngPlural]="switchValue">' +
const template = '<ul [ngPlural]="switchValue">' +
'<template ngPluralCase="=0"><li>{{ switchValue }}</li></template>' +
'</ul></div>';
'</ul>';
fixture = createTestComponent(template);
@ -64,11 +62,10 @@ export function main() {
it('should be applicable to <ng-container> elements', async(() => {
const template = '<div>' +
'<ng-container [ngPlural]="switchValue">' +
const template = '<ng-container [ngPlural]="switchValue">' +
'<template ngPluralCase="=0">you have no messages.</template>' +
'<template ngPluralCase="=1">you have one message.</template>' +
'</ng-container></div>';
'</ng-container>';
fixture = createTestComponent(template);
@ -80,11 +77,10 @@ export function main() {
}));
it('should display the template according to the category', async(() => {
const template = '<div>' +
'<ul [ngPlural]="switchValue">' +
const template = '<ul [ngPlural]="switchValue">' +
'<template ngPluralCase="few"><li>you have a few messages.</li></template>' +
'<template ngPluralCase="many"><li>you have many messages.</li></template>' +
'</ul></div>';
'</ul>';
fixture = createTestComponent(template);
@ -96,11 +92,10 @@ export function main() {
}));
it('should default to other when no matches are found', async(() => {
const template = '<div>' +
'<ul [ngPlural]="switchValue">' +
const template = '<ul [ngPlural]="switchValue">' +
'<template ngPluralCase="few"><li>you have a few messages.</li></template>' +
'<template ngPluralCase="other"><li>default message.</li></template>' +
'</ul></div>';
'</ul>';
fixture = createTestComponent(template);
@ -109,11 +104,10 @@ export function main() {
}));
it('should prioritize value matches over category matches', async(() => {
const template = '<div>' +
'<ul [ngPlural]="switchValue">' +
const template = '<ul [ngPlural]="switchValue">' +
'<template ngPluralCase="few"><li>you have a few messages.</li></template>' +
'<template ngPluralCase="=2">you have two messages.</template>' +
'</ul></div>';
'</ul>';
fixture = createTestComponent(template);

View File

@ -29,22 +29,19 @@ export function main() {
it('should add styles specified in an object literal', async(() => {
const template = `<div [ngStyle]="{'max-width': '40px'}"></div>`;
fixture = createTestComponent(template);
fixture.detectChanges();
expectNativeEl(fixture).toHaveCssStyle({'max-width': '40px'});
}));
it('should add and change styles specified in an object expression', async(() => {
const template = `<div [ngStyle]="expr"></div>`;
fixture = createTestComponent(template);
let expr: {[k: string]: string};
getComponent().expr = {'max-width': '40px'};
fixture.detectChanges();
expectNativeEl(fixture).toHaveCssStyle({'max-width': '40px'});
expr = getComponent().expr;
let expr = getComponent().expr;
expr['max-width'] = '30%';
fixture.detectChanges();
expectNativeEl(fixture).toHaveCssStyle({'max-width': '30%'});

View File

@ -33,11 +33,10 @@ export function main() {
describe('switch value changes', () => {
it('should switch amongst when values', () => {
const template = '<div>' +
'<ul [ngSwitch]="switchValue">' +
'<template ngSwitchCase="a"><li>when a</li></template>' +
'<template ngSwitchCase="b"><li>when b</li></template>' +
'</ul></div>';
const template = '<ul [ngSwitch]="switchValue">' +
'<li *ngSwitchCase="\'a\'">when a</li>' +
'<li *ngSwitchCase="\'b\'">when b</li>' +
'</ul>';
fixture = createTestComponent(template);
@ -51,11 +50,10 @@ export function main() {
});
it('should switch amongst when values with fallback to default', () => {
const template = '<div>' +
'<ul [ngSwitch]="switchValue">' +
'<li template="ngSwitchCase \'a\'">when a</li>' +
'<li template="ngSwitchDefault">when default</li>' +
'</ul></div>';
const template = '<ul [ngSwitch]="switchValue">' +
'<li *ngSwitchCase="\'a\'">when a</li>' +
'<li *ngSwitchDefault>when default</li>' +
'</ul>';
fixture = createTestComponent(template);
detectChangesAndExpectText('when default');
@ -71,15 +69,14 @@ export function main() {
});
it('should support multiple whens with the same value', () => {
const template = '<div>' +
'<ul [ngSwitch]="switchValue">' +
'<template ngSwitchCase="a"><li>when a1;</li></template>' +
'<template ngSwitchCase="b"><li>when b1;</li></template>' +
'<template ngSwitchCase="a"><li>when a2;</li></template>' +
'<template ngSwitchCase="b"><li>when b2;</li></template>' +
'<template ngSwitchDefault><li>when default1;</li></template>' +
'<template ngSwitchDefault><li>when default2;</li></template>' +
'</ul></div>';
const template = '<ul [ngSwitch]="switchValue">' +
'<li *ngSwitchCase="\'a\'">when a1;</li>' +
'<li *ngSwitchCase="\'b\'">when b1;</li>' +
'<li *ngSwitchCase="\'a\'">when a2;</li>' +
'<li *ngSwitchCase="\'b\'">when b2;</li>' +
'<li *ngSwitchDefault>when default1;</li>' +
'<li *ngSwitchDefault>when default2;</li>' +
'</ul>';
fixture = createTestComponent(template);
detectChangesAndExpectText('when default1;when default2;');
@ -94,12 +91,11 @@ export function main() {
describe('when values changes', () => {
it('should switch amongst when values', () => {
const template = '<div>' +
'<ul [ngSwitch]="switchValue">' +
'<template [ngSwitchCase]="when1"><li>when 1;</li></template>' +
'<template [ngSwitchCase]="when2"><li>when 2;</li></template>' +
'<template ngSwitchDefault><li>when default;</li></template>' +
'</ul></div>';
const template = '<ul [ngSwitch]="switchValue">' +
'<li *ngSwitchCase="when1">when 1;</li>' +
'<li *ngSwitchCase="when2">when 2;</li>' +
'<li *ngSwitchDefault>when default;</li>' +
'</ul>';
fixture = createTestComponent(template);
getComponent().when1 = 'a';
@ -148,11 +144,10 @@ export function main() {
});
it('should create the default case if there is no other case', () => {
const template = '<div>' +
'<ul [ngSwitch]="switchValue">' +
'<template ngSwitchDefault><li>when default1;</li></template>' +
'<template ngSwitchDefault><li>when default2;</li></template>' +
'</ul></div>';
const template = '<ul [ngSwitch]="switchValue">' +
'<li *ngSwitchDefault>when default1;</li>' +
'<li *ngSwitchDefault>when default2;</li>' +
'</ul>';
fixture = createTestComponent(template);
detectChangesAndExpectText('when default1;when default2;');
@ -160,15 +155,14 @@ export function main() {
});
it('should allow defaults before cases', () => {
const template = '<div>' +
'<ul [ngSwitch]="switchValue">' +
'<template ngSwitchDefault><li>when default1;</li></template>' +
'<template ngSwitchDefault><li>when default2;</li></template>' +
'<template ngSwitchCase="a"><li>when a1;</li></template>' +
'<template ngSwitchCase="b"><li>when b1;</li></template>' +
'<template ngSwitchCase="a"><li>when a2;</li></template>' +
'<template ngSwitchCase="b"><li>when b2;</li></template>' +
'</ul></div>';
const template = '<ul [ngSwitch]="switchValue">' +
'<li *ngSwitchDefault>when default1;</li>' +
'<li *ngSwitchDefault>when default2;</li>' +
'<li *ngSwitchCase="\'a\'">when a1;</li>' +
'<li *ngSwitchCase="\'b\'">when b1;</li>' +
'<li *ngSwitchCase="\'a\'">when a2;</li>' +
'<li *ngSwitchCase="\'b\'">when b2;</li>' +
'</ul>';
fixture = createTestComponent(template);
detectChangesAndExpectText('when default1;when default2;');

View File

@ -34,29 +34,22 @@ export function main() {
});
});
it('should do nothing if templateRef is null', async(() => {
const template = `<template [ngTemplateOutlet]="null"></template>`;
it('should do nothing if templateRef is `null`', async(() => {
const template = `<ng-container [ngTemplateOutlet]="null"></ng-container>`;
fixture = createTestComponent(template);
detectChangesAndExpectText('');
}));
it('should insert content specified by TemplateRef', async(() => {
const template =
`<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`;
const template = `<template #tpl>foo</template>` +
`<ng-container [ngTemplateOutlet]="tpl"></ng-container>`;
fixture = createTestComponent(template);
detectChangesAndExpectText('');
const refs = fixture.debugElement.children[0].references['refs'];
setTplRef(refs.tplRefs.first);
detectChangesAndExpectText('foo');
}));
it('should clear content if TemplateRef becomes null', async(() => {
const template =
`<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`;
it('should clear content if TemplateRef becomes `null`', async(() => {
const template = `<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs>` +
`<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`;
fixture = createTestComponent(template);
fixture.detectChanges();
const refs = fixture.debugElement.children[0].references['refs'];
@ -70,7 +63,8 @@ export function main() {
it('should swap content if TemplateRef changes', async(() => {
const template =
`<tpl-refs #refs="tplRefs"><template>foo</template><template>bar</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`;
`<tpl-refs #refs="tplRefs"><template>foo</template><template>bar</template></tpl-refs>` +
`<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`;
fixture = createTestComponent(template);
fixture.detectChanges();
@ -83,70 +77,47 @@ export function main() {
detectChangesAndExpectText('bar');
}));
it('should display template if context is null', async(() => {
const template =
`<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef" [ngOutletContext]="null"></template>`;
it('should display template if context is `null`', async(() => {
const template = `<template #tpl>foo</template>` +
`<ng-container [ngTemplateOutlet]="tpl" [ngOutletContext]="null"></ng-container>`;
fixture = createTestComponent(template);
detectChangesAndExpectText('');
const refs = fixture.debugElement.children[0].references['refs'];
setTplRef(refs.tplRefs.first);
detectChangesAndExpectText('foo');
}));
it('should reflect initial context and changes', async(() => {
const template =
`<tpl-refs #refs="tplRefs"><template let-foo="foo"><span>{{foo}}</span></template></tpl-refs><template [ngTemplateOutlet]="currentTplRef" [ngOutletContext]="context"></template>`;
const template = `<template let-foo="foo" #tpl>{{foo}}</template>` +
`<ng-container [ngTemplateOutlet]="tpl" [ngOutletContext]="context"></ng-container>`;
fixture = createTestComponent(template);
fixture.detectChanges();
const refs = fixture.debugElement.children[0].references['refs'];
setTplRef(refs.tplRefs.first);
detectChangesAndExpectText('bar');
fixture.componentInstance.context.foo = 'alter-bar';
detectChangesAndExpectText('alter-bar');
}));
it('should reflect user defined $implicit property in the context', async(() => {
const template =
`<tpl-refs #refs="tplRefs"><template let-ctx><span>{{ctx.foo}}</span></template></tpl-refs><template [ngTemplateOutlet]="currentTplRef" [ngOutletContext]="context"></template>`;
it('should reflect user defined `$implicit` property in the context', async(() => {
const template = `<template let-ctx #tpl>{{ctx.foo}}</template>` +
`<ng-container [ngTemplateOutlet]="tpl" [ngOutletContext]="context"></ng-container>`;
fixture = createTestComponent(template);
fixture.detectChanges();
const refs = fixture.debugElement.children[0].references['refs'];
setTplRef(refs.tplRefs.first);
fixture.componentInstance.context = {$implicit: fixture.componentInstance.context};
detectChangesAndExpectText('bar');
fixture.componentInstance.context = {$implicit: {foo: 'bra'}};
detectChangesAndExpectText('bra');
}));
it('should reflect context re-binding', async(() => {
const template =
`<tpl-refs #refs="tplRefs"><template let-shawshank="shawshank"><span>{{shawshank}}</span></template></tpl-refs><template [ngTemplateOutlet]="currentTplRef" [ngOutletContext]="context"></template>`;
const template = `<template let-shawshank="shawshank" #tpl>{{shawshank}}</template>` +
`<ng-container [ngTemplateOutlet]="tpl" [ngOutletContext]="context"></ng-container>`;
fixture = createTestComponent(template);
fixture.detectChanges();
const refs = fixture.debugElement.children[0].references['refs'];
setTplRef(refs.tplRefs.first);
fixture.componentInstance.context = {shawshank: 'brooks'};
detectChangesAndExpectText('brooks');
fixture.componentInstance.context = {shawshank: 'was here'};
detectChangesAndExpectText('was here');
}));
});
}
@Directive({selector: 'tpl-refs', exportAs: 'tplRefs'})
class CaptureTplRefs {
@ContentChildren(TemplateRef) tplRefs: QueryList<TemplateRef<any>>;
@ -162,4 +133,4 @@ function createTestComponent(template: string): ComponentFixture<TestComponent>
return TestBed.overrideComponent(TestComponent, {set: {template: template}})
.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]})
.createComponent(TestComponent);
}
}

View File

@ -0,0 +1,23 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Component, NgModule} from '@angular/core';
import {RouterModule} from '@angular/router';
@Component({selector: 'lazy-feature-comp', template: 'lazy feature, nested!'})
export class LazyFeatureNestedComponent {
}
@NgModule({
imports: [RouterModule.forChild([
{path: '', component: LazyFeatureNestedComponent, pathMatch: 'full'},
])],
declarations: [LazyFeatureNestedComponent]
})
export class LazyFeatureNestedModule {
}

View File

@ -16,7 +16,10 @@ export class LazyFeatureComponent {
@NgModule({
imports: [RouterModule.forChild([
{path: '', component: LazyFeatureComponent, pathMatch: 'full'},
{path: 'feature', loadChildren: './feature.module#FeatureModule'}
{path: 'feature', loadChildren: './feature.module#FeatureModule'}, {
path: 'nested-feature',
loadChildren: './lazy-feature-nested.module#LazyFeatureNestedModule'
}
])],
declarations: [LazyFeatureComponent]
})

View File

@ -191,6 +191,8 @@ function lazyRoutesTest() {
'./lazy.module#LazyModule': 'lazy.module.ts',
'./feature/feature.module#FeatureModule': 'feature/feature.module.ts',
'./feature/lazy-feature.module#LazyFeatureModule': 'feature/lazy-feature.module.ts',
'./feature.module#FeatureModule': 'feature/feature.module.ts',
'./lazy-feature-nested.module#LazyFeatureNestedModule': 'feature/lazy-feature-nested.module.ts',
'feature2/feature2.module#Feature2Module': 'feature2/feature2.module.ts',
'./default.module': 'feature2/default.module.ts',
'feature/feature.module#FeatureModule': 'feature/feature.module.ts'

View File

@ -9,7 +9,7 @@
"ng-xi18n": "./src/extract_i18n.js"
},
"dependencies": {
"@angular/tsc-wrapped": "0.5.0",
"@angular/tsc-wrapped": "0.5.1",
"reflect-metadata": "^0.1.2",
"minimist": "^1.2.0"
},

View File

@ -15,8 +15,6 @@
import {AotCompilerHost, StaticReflector, StaticSymbol} from '@angular/compiler';
import {NgModule} from '@angular/core';
// We cannot depend directly to @angular/router.
type Route = any;
const ROUTER_MODULE_PATH = '@angular/router/src/router_config_loader';
@ -63,29 +61,37 @@ export function listLazyRoutesOfModule(
const className = entryRouteDef.className;
// List loadChildren of this single module.
const staticSymbol = reflector.findDeclaration(modulePath, className, containingFile);
const appStaticSymbol = reflector.findDeclaration(modulePath, className, containingFile);
const ROUTES = reflector.findDeclaration(ROUTER_MODULE_PATH, ROUTER_ROUTES_SYMBOL_NAME);
const lazyRoutes: LazyRoute[] =
_extractLazyRoutesFromStaticModule(staticSymbol, reflector, host, ROUTES);
const routes: LazyRouteMap = {};
_extractLazyRoutesFromStaticModule(appStaticSymbol, reflector, host, ROUTES);
lazyRoutes.forEach((lazyRoute: LazyRoute) => {
const route: string = lazyRoute.routeDef.toString();
_assertRoute(routes, lazyRoute);
routes[route] = lazyRoute;
const allLazyRoutes = lazyRoutes.reduce(
function includeLazyRouteAndSubRoutes(allRoutes: LazyRouteMap, lazyRoute: LazyRoute):
LazyRouteMap {
const route: string = lazyRoute.routeDef.toString();
_assertRoute(allRoutes, lazyRoute);
allRoutes[route] = lazyRoute;
const lazyModuleSymbol = reflector.findDeclaration(
lazyRoute.absoluteFilePath, lazyRoute.routeDef.className || 'default');
const subRoutes = _extractLazyRoutesFromStaticModule(lazyModuleSymbol, reflector, host, ROUTES);
// StaticReflector does not support discovering annotations like `NgModule` on default
// exports
// Which means: if a default export NgModule was lazy-loaded, we can discover it, but,
// we cannot parse its routes to see if they have loadChildren or not.
if (!lazyRoute.routeDef.className) {
return allRoutes;
}
// Populate the map using the routes we just found.
subRoutes.forEach(subRoute => {
_assertRoute(routes, subRoute);
routes[subRoute.routeDef.toString()] = subRoute;
});
});
const lazyModuleSymbol = reflector.findDeclaration(
lazyRoute.absoluteFilePath, lazyRoute.routeDef.className || 'default');
return routes;
const subRoutes =
_extractLazyRoutesFromStaticModule(lazyModuleSymbol, reflector, host, ROUTES);
return subRoutes.reduce(includeLazyRouteAndSubRoutes, allRoutes);
},
{});
return allLazyRoutes;
}
@ -192,7 +198,7 @@ function _collectRoutes(
*/
function _collectLoadChildren(routes: Route[]): string[] {
return routes.reduce((m, r) => {
if (r.loadChildren) {
if (r.loadChildren && typeof r.loadChildren === 'string') {
return m.concat(r.loadChildren);
} else if (Array.isArray(r)) {
return m.concat(_collectLoadChildren(r));

View File

@ -6,8 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/
import {SchemaMetadata} from '@angular/core';
import {AnimationCompiler} from '../animation/animation_compiler';
import {AnimationParser} from '../animation/animation_parser';
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeMetadata, CompileProviderMetadata, CompileTypeSummary, createHostComponentMeta, identifierModuleUrl, identifierName} from '../compile_metadata';

View File

@ -10,8 +10,8 @@ import {Attribute, Component, ContentChild, ContentChildren, Directive, Host, Ho
import {ReflectorReader} from '../private_import_core';
import {StaticSymbol, StaticSymbolCache} from './static_symbol';
import {ResolvedStaticSymbol, StaticSymbolResolver} from './static_symbol_resolver';
import {StaticSymbol} from './static_symbol';
import {StaticSymbolResolver} from './static_symbol_resolver';
const ANGULAR_IMPORT_LOCATIONS = {
coreDecorators: '@angular/core/src/metadata',
@ -310,6 +310,7 @@ export class StaticReflector implements ReflectorReader {
if (value && (depth != 0 || value.__symbolic != 'error')) {
const parameters: string[] = targetFunction['parameters'];
const defaults: any[] = targetFunction.defaults;
args = args.map(arg => simplifyInContext(context, arg, depth + 1));
if (defaults && defaults.length > args.length) {
args.push(...defaults.slice(args.length).map((value: any) => simplify(value)));
}
@ -499,15 +500,15 @@ export class StaticReflector implements ReflectorReader {
return context;
}
const argExpressions: any[] = expression['arguments'] || [];
const args =
argExpressions.map(arg => simplifyInContext(context, arg, depth + 1));
let converter = self.conversionMap.get(staticSymbol);
if (converter) {
const args =
argExpressions.map(arg => simplifyInContext(context, arg, depth + 1));
return converter(context, args);
} else {
// Determine if the function is one we can simplify.
const targetFunction = resolveReferenceValue(staticSymbol);
return simplifyCall(staticSymbol, targetFunction, args);
return simplifyCall(staticSymbol, targetFunction, argExpressions);
}
}
break;
@ -651,10 +652,6 @@ class PopulatedScope extends BindingScope {
}
}
function sameSymbol(a: StaticSymbol, b: StaticSymbol): boolean {
return a === b;
}
function shouldIgnore(value: any): boolean {
return value && value.__symbolic == 'ignore';
}

View File

@ -5,7 +5,7 @@
* 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 {CompileSummaryKind, CompileTypeSummary} from '../compile_metadata';
import {Summary, SummaryResolver} from '../summary_resolver';
import {StaticSymbol, StaticSymbolCache} from './static_symbol';

View File

@ -5,16 +5,16 @@
* 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 {CompileDirectiveSummary, CompileIdentifierMetadata, CompileNgModuleSummary, CompilePipeSummary, CompileSummaryKind, CompileTypeMetadata, CompileTypeSummary, identifierModuleUrl, identifierName} from '../compile_metadata';
import {CompileNgModuleSummary, CompileSummaryKind, CompileTypeSummary} from '../compile_metadata';
import {Summary, SummaryResolver} from '../summary_resolver';
import {ValueTransformer, visitValue} from '../util';
import {GeneratedFile} from './generated_file';
import {StaticSymbol, StaticSymbolCache} from './static_symbol';
import {ResolvedStaticSymbol, StaticSymbolResolver} from './static_symbol_resolver';
const STRIP_SRC_FILE_SUFFIXES = /(\.ts|\.d\.ts|\.js|\.jsx|\.tsx)$/;
export interface AotSummarySerializerHost {
/**
* Returns the output file path of a source file.
@ -180,4 +180,4 @@ class Deserializer extends ValueTransformer {
return super.visitStringMap(map, context);
}
}
}
}

View File

@ -5,7 +5,6 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Identifiers, createIdentifier} from '../identifiers';
import {ClassBuilder} from '../output/class_builder';
import * as o from '../output/output_ast';

View File

@ -8,7 +8,7 @@
import * as cdAst from '../expression_parser/ast';
import {isBlank, isPresent} from '../facade/lang';
import {isBlank} from '../facade/lang';
import {Identifiers, createIdentifier} from '../identifiers';
import {ClassBuilder} from '../output/class_builder';
import * as o from '../output/output_ast';
@ -338,7 +338,7 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
const receiver = this.visit(ast.receiver, _Mode.Expression);
if (receiver === this._implicitReceiver) {
const varExpr = this._getLocal(ast.name);
if (isPresent(varExpr)) {
if (varExpr) {
result = varExpr.callFn(args);
}
}
@ -374,7 +374,7 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
const receiver: o.Expression = this.visit(ast.receiver, _Mode.Expression);
if (receiver === this._implicitReceiver) {
const varExpr = this._getLocal(ast.name);
if (isPresent(varExpr)) {
if (varExpr) {
throw new Error('Cannot assign to a reference or variable!');
}
}

View File

@ -8,7 +8,7 @@
import {Component, ViewEncapsulation} from '@angular/core';
import {CompileAnimationEntryMetadata, CompileDirectiveMetadata, CompileStylesheetMetadata, CompileTemplateMetadata, CompileTypeMetadata} from './compile_metadata';
import {CompileAnimationEntryMetadata, CompileDirectiveMetadata, CompileStylesheetMetadata, CompileTemplateMetadata} from './compile_metadata';
import {CompilerConfig} from './config';
import {isBlank, isPresent, stringify} from './facade/lang';
import {CompilerInjectable} from './injectable';

View File

@ -14,8 +14,6 @@ import {CompilerInjectable} from './injectable';
import {ReflectorReader, reflector} from './private_import_core';
import {splitAtColon} from './util';
/*
* Resolve a `Type` for {@link Directive}.
*

View File

@ -128,7 +128,6 @@ class DirectiveWrapperBuilder implements ClassBuilder {
new o.ClassMethod('ngOnDestroy', [], this.destroyStmts),
];
const fields: o.ClassField[] = [
new o.ClassField(EVENT_HANDLER_FIELD_NAME, o.FUNCTION_TYPE, [o.StmtModifier.Private]),
new o.ClassField(CONTEXT_FIELD_NAME, o.importType(this.dirMeta.type)),

View File

@ -7,7 +7,7 @@
*/
import * as chars from '../chars';
import {NumberWrapper, isPresent} from '../facade/lang';
import {NumberWrapper} from '../facade/lang';
import {CompilerInjectable} from '../injectable';
export enum TokenType {
@ -241,7 +241,7 @@ class _Scanner {
this.advance();
str += two;
}
if (isPresent(threeCode) && this.peek == threeCode) {
if (threeCode != null && this.peek == threeCode) {
this.advance();
str += three;
}

View File

@ -53,20 +53,22 @@ enum _VisitorMode {
* @internal
*/
class _Visitor implements html.Visitor {
private _depth: number;
// <el i18n>...</el>
private _inI18nNode: boolean;
private _depth: number;
private _inImplicitNode: boolean;
// <!--i18n-->...<!--/i18n-->
private _inI18nBlock: boolean;
private _blockMeaningAndDesc: string;
private _blockChildren: html.Node[];
private _blockStartDepth: number;
private _inI18nBlock: boolean;
// {<icu message>}
private _inIcu: boolean;
// set to void 0 when not in a section
private _msgCountAtSectionStart: number;
private _errors: I18nError[];
private _mode: _VisitorMode;
@ -208,50 +210,31 @@ class _Visitor implements html.Visitor {
this._depth++;
const wasInI18nNode = this._inI18nNode;
const wasInImplicitNode = this._inImplicitNode;
let childNodes: html.Node[];
let childNodes: html.Node[] = [];
let translatedChildNodes: html.Node[];
// Extract only top level nodes with the (implicit) "i18n" attribute if not in a block or an ICU
// message
// Extract:
// - top level nodes with the (implicit) "i18n" attribute if not already in a section
// - ICU messages
const i18nAttr = _getI18nAttr(el);
const i18nMeta = i18nAttr ? i18nAttr.value : '';
const isImplicit = this._implicitTags.some(tag => el.name === tag) && !this._inIcu &&
!this._isInTranslatableSection;
const isTopLevelImplicit = !wasInImplicitNode && isImplicit;
this._inImplicitNode = this._inImplicitNode || isImplicit;
this._inImplicitNode = wasInImplicitNode || isImplicit;
if (!this._isInTranslatableSection && !this._inIcu) {
if (i18nAttr) {
// explicit translation
if (i18nAttr || isTopLevelImplicit) {
this._inI18nNode = true;
const message = this._addMessage(el.children, i18nAttr.value);
childNodes = this._translateMessage(el, message);
} else if (isTopLevelImplicit) {
// implicit translation
this._inI18nNode = true;
const message = this._addMessage(el.children);
childNodes = this._translateMessage(el, message);
const message = this._addMessage(el.children, i18nMeta);
translatedChildNodes = this._translateMessage(el, message);
}
if (this._mode == _VisitorMode.Extract) {
const isTranslatable = i18nAttr || isTopLevelImplicit;
if (isTranslatable) {
this._openTranslatableSection(el);
}
if (isTranslatable) this._openTranslatableSection(el);
html.visitAll(this, el.children);
if (isTranslatable) {
this._closeTranslatableSection(el, el.children);
}
}
if (this._mode === _VisitorMode.Merge && !i18nAttr && !isTopLevelImplicit) {
childNodes = [];
el.children.forEach(child => {
const visited = child.visit(this, context);
if (visited && !this._isInTranslatableSection) {
// Do not add the children from translatable sections (= i18n blocks here)
// They will be added when the section is close (i.e. on `<!-- /i18n -->`)
childNodes = childNodes.concat(visited);
}
});
if (isTranslatable) this._closeTranslatableSection(el, el.children);
}
} else {
if (i18nAttr || isTopLevelImplicit) {
@ -263,19 +246,18 @@ class _Visitor implements html.Visitor {
// Descend into child nodes for extraction
html.visitAll(this, el.children);
}
}
if (this._mode == _VisitorMode.Merge) {
// Translate attributes in ICU messages
childNodes = [];
el.children.forEach(child => {
const visited = child.visit(this, context);
if (visited && !this._isInTranslatableSection) {
// Do not add the children from translatable sections (= i18n blocks here)
// They will be added when the section is close (i.e. on `<!-- /i18n -->`)
childNodes = childNodes.concat(visited);
}
});
}
if (this._mode === _VisitorMode.Merge) {
const visitNodes = translatedChildNodes || el.children;
visitNodes.forEach(child => {
const visited = child.visit(this, context);
if (visited && !this._isInTranslatableSection) {
// Do not add the children from translatable sections (= i18n blocks here)
// They will be added later in this loop when the block closes (i.e. on `<!-- /i18n -->`)
childNodes = childNodes.concat(visited);
}
});
}
this._visitAttributesOf(el);
@ -285,7 +267,6 @@ class _Visitor implements html.Visitor {
this._inImplicitNode = wasInImplicitNode;
if (this._mode === _VisitorMode.Merge) {
// There are no childNodes in translatable sections - those nodes will be replace anyway
const translatedAttrs = this._translateAttributes(el);
return new html.Element(
el.name, translatedAttrs, childNodes, el.sourceSpan, el.startSourceSpan,
@ -432,7 +413,7 @@ class _Visitor implements html.Visitor {
/**
* A translatable section could be:
* - a translatable element,
* - the content of translatable element,
* - nodes between `<!-- i18n -->` and `<!-- /i18n -->` comments
*/
private get _isInTranslatableSection(): boolean {

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ANALYZE_FOR_ENTRY_COMPONENTS, AnimationTransitionEvent, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ComponentRef, ElementRef, Injector, LOCALE_ID, NgModuleFactory, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TRANSLATIONS_FORMAT, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
import {ANALYZE_FOR_ENTRY_COMPONENTS, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ComponentRef, ElementRef, Injector, LOCALE_ID, NgModuleFactory, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TRANSLATIONS_FORMAT, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
import {StaticSymbol} from './aot/static_symbol';
import {CompileIdentifierMetadata, CompileTokenMetadata, identifierModuleUrl, identifierName} from './compile_metadata';

View File

@ -283,7 +283,7 @@ class _TreeBuilder {
const tagDef = this.getTagDefinition(el.name);
const {parent, container} = this._getParentElementSkippingContainers();
if (isPresent(parent) && tagDef.requireExtraParent(parent.name)) {
if (parent && tagDef.requireExtraParent(parent.name)) {
const newParent = new html.Element(
tagDef.parentToAdd, [], [], el.sourceSpan, el.startSourceSpan, el.endSourceSpan);
this._insertBeforeContainer(parent, container, newParent);

View File

@ -9,7 +9,7 @@
import {CompileDiDependencyMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileProviderMetadata, CompileTokenMetadata, identifierModuleUrl, identifierName, tokenName, tokenReference} from './compile_metadata';
import {createDiTokenExpression} from './compiler_util/identifier_util';
import {isPresent} from './facade/lang';
import {Identifiers, createIdentifier, createIdentifierToken, resolveIdentifier} from './identifiers';
import {Identifiers, createIdentifier, resolveIdentifier} from './identifiers';
import {CompilerInjectable} from './injectable';
import {ClassBuilder, createClassStmt} from './output/class_builder';
import * as o from './output/output_ast';

View File

@ -9,7 +9,7 @@
import {NgModule, Type} from '@angular/core';
import {ListWrapper} from './facade/collection';
import {isPresent, stringify} from './facade/lang';
import {stringify} from './facade/lang';
import {CompilerInjectable} from './injectable';
import {ReflectorReader, reflector} from './private_import_core';
@ -30,7 +30,7 @@ export class NgModuleResolver {
const ngModuleMeta: NgModule =
ListWrapper.findLast(this._reflector.annotations(type), _isNgModuleMetadata);
if (isPresent(ngModuleMeta)) {
if (ngModuleMeta) {
return ngModuleMeta;
} else {
if (throwIfNotFound) {

View File

@ -7,7 +7,6 @@
*/
import {CompileIdentifierMetadata} from '../compile_metadata';
import {ValueTransformer, visitValue} from '../util';
import * as o from './output_ast';

View File

@ -9,7 +9,7 @@
import {Pipe, Type, resolveForwardRef} from '@angular/core';
import {ListWrapper} from './facade/collection';
import {isPresent, stringify} from './facade/lang';
import {stringify} from './facade/lang';
import {CompilerInjectable} from './injectable';
import {ReflectorReader, reflector} from './private_import_core';
@ -38,9 +38,9 @@ export class PipeResolver {
*/
resolve(type: Type<any>, throwIfNotFound = true): Pipe {
const metas = this._reflector.annotations(resolveForwardRef(type));
if (isPresent(metas)) {
if (metas) {
const annotation = ListWrapper.findLast(metas, _isPipeMetadata);
if (isPresent(annotation)) {
if (annotation) {
return annotation;
}
}

View File

@ -9,7 +9,7 @@
import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompileNgModuleMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata, CompileTypeMetadata, tokenName, tokenReference} from './compile_metadata';
import {isBlank, isPresent} from './facade/lang';
import {Identifiers, createIdentifierToken, resolveIdentifier} from './identifiers';
import {Identifiers, resolveIdentifier} from './identifiers';
import {ParseError, ParseSourceSpan} from './parse_util';
import {AttrAst, DirectiveAst, ProviderAst, ProviderAstType, ReferenceAst} from './template_parser/template_ast';
@ -114,7 +114,7 @@ export class ProviderElementContext {
let queries: CompileQueryMetadata[];
while (currentEl !== null) {
queries = currentEl._contentQueries.get(tokenReference(token));
if (isPresent(queries)) {
if (queries) {
result.push(...queries.filter((query) => query.descendants || distance <= 1));
}
if (currentEl._directiveAsts.length > 0) {
@ -123,7 +123,7 @@ export class ProviderElementContext {
currentEl = currentEl._parent;
}
queries = this.viewContext.viewQueries.get(tokenReference(token));
if (isPresent(queries)) {
if (queries) {
result.push(...queries);
}
return result;
@ -143,7 +143,7 @@ export class ProviderElementContext {
return null;
}
let transformedProviderAst = this._transformedProviders.get(tokenReference(token));
if (isPresent(transformedProviderAst)) {
if (transformedProviderAst) {
return transformedProviderAst;
}
if (isPresent(this._seenProviders.get(tokenReference(token)))) {
@ -165,11 +165,11 @@ export class ProviderElementContext {
transformedUseExisting = null;
transformedUseValue = existingDiDep.value;
}
} else if (isPresent(provider.useFactory)) {
} else if (provider.useFactory) {
const deps = provider.deps || provider.useFactory.diDeps;
transformedDeps =
deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep, eager));
} else if (isPresent(provider.useClass)) {
} else if (provider.useClass) {
const deps = provider.deps || provider.useClass.diDeps;
transformedDeps =
deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep, eager));
@ -235,7 +235,7 @@ export class ProviderElementContext {
}
} else {
// check parent elements
while (!result && isPresent(currElement._parent)) {
while (!result && currElement._parent) {
const prevElement = currElement;
currElement = currElement._parent;
if (prevElement._isViewRoot) {
@ -301,7 +301,7 @@ export class NgModuleProviderAnalyzer {
return null;
}
let transformedProviderAst = this._transformedProviders.get(tokenReference(token));
if (isPresent(transformedProviderAst)) {
if (transformedProviderAst) {
return transformedProviderAst;
}
if (isPresent(this._seenProviders.get(tokenReference(token)))) {
@ -324,11 +324,11 @@ export class NgModuleProviderAnalyzer {
transformedUseExisting = null;
transformedUseValue = existingDiDep.value;
}
} else if (isPresent(provider.useFactory)) {
} else if (provider.useFactory) {
const deps = provider.deps || provider.useFactory.diDeps;
transformedDeps =
deps.map((dep) => this._getDependency(dep, eager, resolvedProvider.sourceSpan));
} else if (isPresent(provider.useClass)) {
} else if (provider.useClass) {
const deps = provider.deps || provider.useClass.diDeps;
transformedDeps =
deps.map((dep) => this._getDependency(dep, eager, resolvedProvider.sourceSpan));
@ -454,7 +454,7 @@ function _resolveProviders(
function _getViewQueries(component: CompileDirectiveMetadata): Map<any, CompileQueryMetadata[]> {
const viewQueries = new Map<any, CompileQueryMetadata[]>();
if (isPresent(component.viewQueries)) {
if (component.viewQueries) {
component.viewQueries.forEach((query) => _addQueryToTokenMap(viewQueries, query));
}
return viewQueries;
@ -464,7 +464,7 @@ function _getContentQueries(directives: CompileDirectiveSummary[]):
Map<any, CompileQueryMetadata[]> {
const contentQueries = new Map<any, CompileQueryMetadata[]>();
directives.forEach(directive => {
if (isPresent(directive.queries)) {
if (directive.queries) {
directive.queries.forEach((query) => _addQueryToTokenMap(contentQueries, query));
}
});

View File

@ -11,7 +11,6 @@ import {SecurityContext} from '@angular/core';
import {CompileDirectiveSummary, CompilePipeSummary} from '../compile_metadata';
import {ASTWithSource, BindingPipe, EmptyExpr, ParserError, RecursiveAstVisitor, TemplateBinding} from '../expression_parser/ast';
import {Parser} from '../expression_parser/parser';
import {isPresent} from '../facade/lang';
import {InterpolationConfig} from '../ml_parser/interpolation_config';
import {mergeNsAndName} from '../ml_parser/tags';
import {ParseError, ParseErrorLevel, ParseSourceSpan} from '../parse_util';
@ -111,14 +110,14 @@ export class BindingParser {
}
parseInlineTemplateBinding(
name: string, prefixToken: string, value: string, sourceSpan: ParseSourceSpan,
prefixToken: string, value: string, sourceSpan: ParseSourceSpan,
targetMatchableAttrs: string[][], targetProps: BoundProperty[], targetVars: VariableAst[]) {
const bindings = this._parseTemplateBindings(prefixToken, value, sourceSpan);
for (let i = 0; i < bindings.length; i++) {
const binding = bindings[i];
if (binding.keyIsVar) {
targetVars.push(new VariableAst(binding.key, binding.name, sourceSpan));
} else if (isPresent(binding.expression)) {
} else if (binding.expression) {
this._parsePropertyAst(
binding.key, binding.expression, sourceSpan, targetMatchableAttrs, targetProps);
} else {
@ -136,7 +135,7 @@ export class BindingParser {
const bindingsResult = this._exprParser.parseTemplateBindings(prefixToken, value, sourceInfo);
this._reportExpressionParserErrors(bindingsResult.errors, sourceSpan);
bindingsResult.templateBindings.forEach((binding) => {
if (isPresent(binding.expression)) {
if (binding.expression) {
this._checkPipes(binding.expression, sourceSpan);
}
});
@ -193,7 +192,7 @@ export class BindingParser {
name: string, value: string, sourceSpan: ParseSourceSpan, targetMatchableAttrs: string[][],
targetProps: BoundProperty[]): boolean {
const expr = this.parseInterpolation(value, sourceSpan);
if (isPresent(expr)) {
if (expr) {
this._parsePropertyAst(name, expr, sourceSpan, targetMatchableAttrs, targetProps);
return true;
}
@ -374,7 +373,7 @@ export class BindingParser {
}
private _checkPipes(ast: ASTWithSource, sourceSpan: ParseSourceSpan) {
if (isPresent(ast)) {
if (ast) {
const collector = new PipeCollector();
ast.visit(collector);
collector.pipes.forEach((ast, pipeName) => {

View File

@ -276,7 +276,7 @@ class TemplateParseVisitor implements html.Visitor {
templateBindingsSource = attr.value;
} else if (normalizedName.startsWith(TEMPLATE_ATTR_PREFIX)) {
templateBindingsSource = attr.value;
prefixToken = normalizedName.substring(TEMPLATE_ATTR_PREFIX.length);
prefixToken = normalizedName.substring(TEMPLATE_ATTR_PREFIX.length) + ':';
}
const hasTemplateBinding = isPresent(templateBindingsSource);
@ -288,7 +288,7 @@ class TemplateParseVisitor implements html.Visitor {
}
hasInlineTemplates = true;
this._bindingParser.parseInlineTemplateBinding(
attr.name, prefixToken, templateBindingsSource, attr.sourceSpan, templateMatchableAttrs,
prefixToken, templateBindingsSource, attr.sourceSpan, templateMatchableAttrs,
templateElementOrDirectiveProps, templateElementVars);
}
@ -309,9 +309,11 @@ class TemplateParseVisitor implements html.Visitor {
const elementProps: BoundElementPropertyAst[] =
this._createElementPropertyAsts(element.name, elementOrDirectiveProps, directiveAsts);
const isViewRoot = parent.isTemplateElement || hasInlineTemplates;
const providerContext = new ProviderElementContext(
this.providerViewContext, parent.providerContext, isViewRoot, directiveAsts, attrs,
references, element.sourceSpan);
const children = html.visitAll(
preparsedElement.nonBindable ? NON_BINDABLE_VISITOR : this, element.children,
ElementContext.create(

View File

@ -19,7 +19,7 @@ import {ProviderAst, ProviderAstType, ReferenceAst, TemplateAst} from '../templa
import {CompileMethod} from './compile_method';
import {CompileQuery, addQueryToTokenMap, createQueryList} from './compile_query';
import {CompileView, CompileViewRootNode} from './compile_view';
import {InjectMethodVars, ViewProperties} from './constants';
import {InjectMethodVars} from './constants';
import {ComponentFactoryDependency, DirectiveWrapperDependency} from './deps';
import {getPropertyInView, injectFromViewParentInjector} from './util';
@ -195,7 +195,7 @@ export class CompileElement extends CompileNode {
const propName =
`_${tokenName(resolvedProvider.token)}_${this.nodeIndex}_${this.instances.size}`;
const instance = createProviderProperty(
propName, resolvedProvider, providerValueExpressions, resolvedProvider.multiProvider,
propName, providerValueExpressions, resolvedProvider.multiProvider,
resolvedProvider.eager, this);
if (isDirectiveWrapper) {
this.directiveWrapperInstance.set(tokenReference(resolvedProvider.token), instance);
@ -289,7 +289,7 @@ export class CompileElement extends CompileNode {
CompileQuery {
const propName =
`_query_${tokenName(queryMeta.selectors[0])}_${this.nodeIndex}_${this._queryCount++}`;
const queryList = createQueryList(queryMeta, directiveInstance, propName, this.view);
const queryList = createQueryList(propName, this.view);
const query = new CompileQuery(queryMeta, queryList, directiveInstance, this.view);
addQueryToTokenMap(this._queries, query);
return query;
@ -369,8 +369,8 @@ function createInjectInternalCondition(
}
function createProviderProperty(
propName: string, provider: ProviderAst, providerValueExpressions: o.Expression[],
isMulti: boolean, isEager: boolean, compileElement: CompileElement): o.Expression {
propName: string, providerValueExpressions: o.Expression[], isMulti: boolean, isEager: boolean,
compileElement: CompileElement): o.Expression {
const view = compileElement.view;
let resolvedProviderValueExpr: o.Expression;
let type: o.Type;

View File

@ -6,7 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/
import {isPresent} from '../facade/lang';
import * as o from '../output/output_ast';
import {TemplateAst} from '../template_parser/template_ast';
@ -34,7 +33,7 @@ export class CompileMethod {
if (this._newState.nodeIndex !== this._currState.nodeIndex ||
this._newState.sourceAst !== this._currState.sourceAst) {
const expr = this._updateDebugContext(this._newState);
if (isPresent(expr)) {
if (expr) {
this._bodyStatements.push(expr.toStmt());
}
}
@ -43,13 +42,12 @@ export class CompileMethod {
private _updateDebugContext(newState: _DebugState): o.Expression {
this._currState = this._newState = newState;
if (this._debugEnabled) {
const sourceLocation =
isPresent(newState.sourceAst) ? newState.sourceAst.sourceSpan.start : null;
const sourceLocation = newState.sourceAst ? newState.sourceAst.sourceSpan.start : null;
return o.THIS_EXPR.callMethod('debug', [
o.literal(newState.nodeIndex),
isPresent(sourceLocation) ? o.literal(sourceLocation.line) : o.NULL_EXPR,
isPresent(sourceLocation) ? o.literal(sourceLocation.col) : o.NULL_EXPR
sourceLocation ? o.literal(sourceLocation.line) : o.NULL_EXPR,
sourceLocation ? o.literal(sourceLocation.col) : o.NULL_EXPR
]);
} else {
return null;

View File

@ -8,7 +8,6 @@
import {CompileQueryMetadata, tokenReference} from '../compile_metadata';
import {ListWrapper} from '../facade/collection';
import {isPresent} from '../facade/lang';
import {Identifiers, createIdentifier} from '../identifiers';
import * as o from '../output/output_ast';
@ -33,7 +32,7 @@ export class CompileQuery {
addValue(value: o.Expression, view: CompileView) {
let currentView = view;
const elPath: CompileElement[] = [];
while (isPresent(currentView) && currentView !== this.view) {
while (currentView && currentView !== this.view) {
const parentEl = currentView.declarationElement;
elPath.unshift(parentEl);
currentView = parentEl.view;
@ -67,7 +66,7 @@ export class CompileQuery {
generateStatements(targetStaticMethod: CompileMethod, targetDynamicMethod: CompileMethod) {
const values = createQueryValues(this._values);
const updateStmts = [this.queryList.callMethod('reset', [o.literalArr(values)]).toStmt()];
if (isPresent(this.ownerDirectiveExpression)) {
if (this.ownerDirectiveExpression) {
const valueExpr = this.meta.first ? this.queryList.prop('first') : this.queryList;
updateStmts.push(
this.ownerDirectiveExpression.prop(this.meta.propertyName).set(valueExpr).toStmt());
@ -110,9 +109,7 @@ function mapNestedViews(
]);
}
export function createQueryList(
query: CompileQueryMetadata, directiveInstance: o.Expression, propertyName: string,
compileView: CompileView): o.Expression {
export function createQueryList(propertyName: string, compileView: CompileView): o.Expression {
compileView.fields.push(new o.ClassField(
propertyName, o.importType(createIdentifier(Identifiers.QueryList), [o.DYNAMIC_TYPE])));
const expr = o.THIS_EXPR.prop(propertyName);

View File

@ -12,7 +12,6 @@ import {EventHandlerVars, NameResolver} from '../compiler_util/expression_conver
import {createPureProxy} from '../compiler_util/identifier_util';
import {CompilerConfig} from '../config';
import {isPresent} from '../facade/lang';
import {Identifiers, createIdentifier} from '../identifiers';
import * as o from '../output/output_ast';
import {ViewType} from '../private_import_core';
@ -119,7 +118,7 @@ export class CompileView implements NameResolver {
const directiveInstance = o.THIS_EXPR.prop('context');
this.component.viewQueries.forEach((queryMeta, queryIndex) => {
const propName = `_viewQuery_${tokenName(queryMeta.selectors[0])}_${queryIndex}`;
const queryList = createQueryList(queryMeta, directiveInstance, propName, this);
const queryList = createQueryList(propName, this);
const query = new CompileQuery(queryMeta, queryList, directiveInstance, this);
addQueryToTokenMap(viewQueries, query);
});

View File

@ -11,7 +11,7 @@ import {ChangeDetectionStrategy, ViewEncapsulation} from '@angular/core';
import {createEnumExpression} from '../compiler_util/identifier_util';
import {Identifiers} from '../identifiers';
import * as o from '../output/output_ast';
import {ChangeDetectorStatus, ViewType} from '../private_import_core';
import {ViewType} from '../private_import_core';
export class ViewTypeEnum {
static fromValue(value: ViewType): o.Expression {
@ -25,12 +25,6 @@ export class ViewEncapsulationEnum {
}
}
export class ChangeDetectionStrategyEnum {
static fromValue(value: ChangeDetectionStrategy): o.Expression {
return createEnumExpression(Identifiers.ChangeDetectionStrategy, value);
}
}
export class ChangeDetectorStatusEnum {
static fromValue(value: ChangeDetectorStatusEnum): o.Expression {
return createEnumExpression(Identifiers.ChangeDetectorStatus, value);

View File

@ -15,7 +15,6 @@ import {BoundEventAst, DirectiveAst} from '../template_parser/template_ast';
import {CompileElement} from './compile_element';
import {CompileMethod} from './compile_method';
import {ViewProperties} from './constants';
import {getHandleEventMethodName} from './util';
export function bindOutputs(

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {CompileQueryMetadata, CompileTokenMetadata, tokenReference} from '../compile_metadata';
import {CompileTokenMetadata, tokenReference} from '../compile_metadata';
import * as o from '../output/output_ast';
import {CompileElement} from './compile_element';
@ -17,16 +17,18 @@ import {CompileQuery} from './compile_query';
// as we create embedded views before the <template> elements themselves.
export function bindQueryValues(ce: CompileElement) {
const queriesWithReads: _QueryWithRead[] = [];
ce.getProviderTokens().forEach((token) => {
const queriesForProvider = ce.getQueriesFor(token);
queriesWithReads.push(...queriesForProvider.map(query => new _QueryWithRead(query, token)));
});
Object.keys(ce.referenceTokens).forEach(varName => {
const token = ce.referenceTokens[varName];
const varToken = {value: varName};
queriesWithReads.push(
...ce.getQueriesFor(varToken).map(query => new _QueryWithRead(query, varToken)));
});
queriesWithReads.forEach((queryWithRead) => {
let value: o.Expression;
if (queryWithRead.read.identifier) {

View File

@ -9,8 +9,6 @@
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileTokenMetadata, identifierName} from '../compile_metadata';
import {createDiTokenExpression} from '../compiler_util/identifier_util';
import {isPresent} from '../facade/lang';
import {Identifiers, createIdentifier} from '../identifiers';
import * as o from '../output/output_ast';
import {ViewType} from '../private_import_core';
@ -23,7 +21,7 @@ export function getPropertyInView(
} else {
let viewProp: o.Expression = o.THIS_EXPR;
let currView: CompileView = callingView;
while (currView !== definedView && isPresent(currView.declarationElement.view)) {
while (currView !== definedView && currView.declarationElement.view) {
currView = currView.declarationElement.view;
viewProp = viewProp.prop('parentView');
}

View File

@ -15,7 +15,6 @@ import {isPresent} from '../facade/lang';
import {Identifiers, createIdentifier, identifierToken} from '../identifiers';
import {createClassStmt} from '../output/class_builder';
import * as o from '../output/output_ast';
import {ParseSourceSpan} from '../parse_util';
import {ChangeDetectorStatus, ViewType, isDefaultChangeDetectionStrategy} from '../private_import_core';
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '../template_parser/template_ast';
@ -695,7 +694,6 @@ function generateCreateEmbeddedViewsMethod(view: CompileView): o.ClassMethod {
view.nodes.forEach((node) => {
if (node instanceof CompileElement) {
if (node.embeddedView) {
const parentNodeIndex = node.isRootElement() ? null : node.parent.nodeIndex;
stmts.push(new o.IfStmt(
nodeIndexVar.equals(o.literal(node.nodeIndex)),
[new o.ReturnStatement(node.embeddedView.classExpr.instantiate([

View File

@ -449,6 +449,40 @@ describe('StaticReflector', () => {
expect(annotations[0].providers[0].useValue.members[0]).toEqual('staticMethod');
});
// #13605
it('should not throw on unknown decorators', () => {
const data = Object.create(DEFAULT_TEST_DATA);
const file = '/tmp/src/app.component.ts';
data[file] = `
import { Component } from '@angular/core';
export const enum TypeEnum {
type
}
export function MyValidationDecorator(p1: any, p2: any): any {
return null;
}
export function ValidationFunction(a1: any): any {
return null;
}
@Component({
selector: 'my-app',
template: "<h1>Hello {{name}}</h1>",
})
export class AppComponent {
name = 'Angular';
@MyValidationDecorator( TypeEnum.type, ValidationFunction({option: 'value'}))
myClassProp: number;
}`;
init(data);
const appComponent = reflector.getStaticSymbol(file, 'AppComponent');
expect(() => reflector.propMetadata(appComponent)).not.toThrow();
});
describe('inheritance', () => {
class ClassDecorator {
constructor(public value: any) {}

View File

@ -210,5 +210,56 @@ const XMB = `
<ph name="START_TAG_DIV_1"><ex>&lt;div&gt;</ex></ph><ph name="ICU"/><ph name="CLOSE_TAG_DIV"><ex>&lt;/div&gt;</ex></ph>
</msg>
<msg id="1491627405349178954">it <ph name="START_BOLD_TEXT"><ex>&lt;b&gt;</ex></ph>should<ph name="CLOSE_BOLD_TEXT"><ex>&lt;/b&gt;</ex></ph> work</msg>
</messagebundle>
</messagebundle>`;
const HTML = `
<div>
<h1 i18n>i18n attribute on tags</h1>
<div id="i18n-1"><p i18n>nested</p></div>
<div id="i18n-2"><p i18n="different meaning|">nested</p></div>
<div id="i18n-3"><p i18n><i>with placeholders</i></p></div>
<div id="i18n-3b"><p i18n><i class="preserved-on-placeholders">with placeholders</i></p></div>
<div>
<p id="i18n-4" i18n-title title="on not translatable node"></p>
<p id="i18n-5" i18n i18n-title title="on translatable node"></p>
<p id="i18n-6" i18n-title title></p>
</div>
<!-- no ph below because the ICU node is the only child of the div, i.e. no text nodes -->
<div i18n id="i18n-7">{count, plural, =0 {zero} =1 {one} =2 {two} other {<b>many</b>}}</div>
<div i18n id="i18n-8">
{sex, select, m {male} f {female}}
</div>
<div i18n id="i18n-8b">
{sexB, select, m {male} f {female}}
</div>
<div i18n id="i18n-9">{{ "count = " + count }}</div>
<div i18n id="i18n-10">sex = {{ sex }}</div>
<div i18n id="i18n-11">{{ "custom name" //i18n(ph="CUSTOM_NAME") }}</div>
</div>
<!-- i18n -->
<h1 id="i18n-12" >Markers in html comments</h1>
<div id="i18n-13" i18n-title title="in a translatable section"></div>
<div id="i18n-14">{count, plural, =0 {zero} =1 {one} =2 {two} other {<b>many</b>}}</div>
<!-- /i18n -->
<div id="i18n-15"><ng-container i18n>it <b>should</b> work</ng-container></div>
<!-- make sure that ICU messages are not treated as text nodes -->
<div i18n="desc">{
response.getItemsList().length,
plural,
=0 {Found no results}
=1 {Found one result}
other {Found {{response.getItemsList().length}} results}
}</div>
<div i18n id="i18n-18">foo<a i18n-title title="in a translatable section">bar</a></div>
`;

View File

@ -1323,17 +1323,30 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
});
it('should work with *... and use the attribute name as property binding name', () => {
expect(humanizeTplAst(parse('<div *ngIf="test">', [ngIf]))).toEqual([
[EmbeddedTemplateAst], [DirectiveAst, ngIf],
[BoundDirectivePropertyAst, 'ngIf', 'test'], [ElementAst, 'div']
[EmbeddedTemplateAst],
[DirectiveAst, ngIf],
[BoundDirectivePropertyAst, 'ngIf', 'test'],
[ElementAst, 'div'],
]);
// https://github.com/angular/angular/issues/13800
expect(humanizeTplAst(parse('<div *ngIf="-1">', [ngIf]))).toEqual([
[EmbeddedTemplateAst],
[DirectiveAst, ngIf],
[BoundDirectivePropertyAst, 'ngIf', '0 - 1'],
[ElementAst, 'div'],
]);
});
it('should work with *... and empty value', () => {
expect(humanizeTplAst(parse('<div *ngIf>', [ngIf]))).toEqual([
[EmbeddedTemplateAst], [DirectiveAst, ngIf],
[BoundDirectivePropertyAst, 'ngIf', 'null'], [ElementAst, 'div']
[EmbeddedTemplateAst],
[DirectiveAst, ngIf],
[BoundDirectivePropertyAst, 'ngIf', 'null'],
[ElementAst, 'div'],
]);
});
});

View File

@ -13,7 +13,6 @@ import {Type} from '../type';
import {ElementRef} from './element_ref';
import {AppView} from './view';
import {ViewContainer} from './view_container';
import {ViewRef} from './view_ref';
import {ViewUtils} from './view_utils';
@ -86,11 +85,6 @@ export class ComponentRef_<C> extends ComponentRef<C> {
onDestroy(callback: Function): void { this.hostView.onDestroy(callback); }
}
/**
* @experimental
*/
const EMPTY_CONTEXT = new Object();
/**
* @stable
*/

View File

@ -8,7 +8,6 @@
import {ElementRef} from './element_ref';
import {AppView} from './view';
import {ViewContainer} from './view_container';
import {EmbeddedViewRef} from './view_ref';

View File

@ -11,7 +11,7 @@ import {ChangeDetectorRef, ChangeDetectorStatus} from '../change_detection/chang
import {Injector, THROW_IF_NOT_FOUND} from '../di/injector';
import {isPresent} from '../facade/lang';
import {WtfScopeFn, wtfCreateScope, wtfLeave} from '../profile/profile';
import {DirectRenderer, RenderComponentType, RenderDebugInfo, Renderer} from '../render/api';
import {DirectRenderer, RenderComponentType, Renderer} from '../render/api';
import {AnimationViewContext} from './animation_view_context';
import {ComponentRef} from './component_factory';

View File

@ -7,10 +7,8 @@
*/
import {Injector} from '../di/injector';
import {isPresent} from '../facade/lang';
import {ElementRef} from './element_ref';
import {QueryList} from './query_list';
import {AppView} from './view';
import {ViewContainerRef_} from './view_container_ref';
import {ViewType} from './view_type';

View File

@ -15,7 +15,6 @@ import {ViewEncapsulation} from '../metadata/view';
import {RenderComponentType, RenderDebugInfo, Renderer, RootRenderer} from '../render/api';
import {Sanitizer} from '../security';
import {VERSION} from '../version';
import {NgZone} from '../zone/ng_zone';
import {ExpressionChangedAfterItHasBeenCheckedError} from './errors';
import {AppView} from './view';
@ -23,7 +22,6 @@ import {AppView} from './view';
@Injectable()
export class ViewUtils {
sanitizer: Sanitizer;
private _nextCompTypeId: number = 0;
constructor(
private _renderer: RootRenderer, sanitizer: Sanitizer,

View File

@ -138,7 +138,7 @@ export function main() {
@Component({
selector: 'child',
template:
'(<template [ngTemplateOutlet]="templateRef" [ngOutletContext]="templateCtx"></template>)'
'(<ng-container [ngTemplateOutlet]="templateRef" [ngOutletContext]="templateCtx"></ng-container>)'
})
class Child {
@Input()

View File

@ -23,8 +23,15 @@ function declareTests({useJit}: {useJit: boolean}) {
beforeEach(() => {
TestBed.configureCompiler({useJit: useJit});
TestBed.configureTestingModule(
{declarations: [MyComp, NeedsContentChildren, NeedsViewChildren, TextDirective, Simple]});
TestBed.configureTestingModule({
declarations: [
MyComp,
NeedsContentChildren,
NeedsViewChildren,
TextDirective,
Simple,
],
});
});
it('should support the "i18n" attribute', () => {

View File

@ -421,7 +421,7 @@ export function main() {
TestBed.overrideDirective(
SimpleDirective, {set: {providers: [{provide: 'service', useValue: 'parentService'}]}});
const el = createComponent(
'<div simpleDirective><template [ngIf]="true"><div *ngIf="true" needsService></div></template></div>');
'<div simpleDirective><ng-container *ngIf="true"><div *ngIf="true" needsService></div></ng-container></div>');
expect(el.children[0].children[0].injector.get(NeedsService).service)
.toEqual('parentService');
});

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Component, ComponentRef, Injectable, Injector} from '@angular/core';
import {Component, ComponentRef, Injectable} from '@angular/core';
import {DebugDomRootRenderer} from '@angular/core/src/debug/debug_renderer';
import {RootRenderer} from '@angular/core/src/render/api';
import {TestBed} from '@angular/core/testing';
@ -152,7 +152,7 @@ export function main() {
it('should update any template comment property/attributes', () => {
TestBed.overrideComponent(
MyComp2, {set: {template: '<template [ngIf]="ctxBoolProp"></template>'}});
MyComp2, {set: {template: '<ng-container *ngIf="ctxBoolProp"></ng-container>'}});
const fixture = TestBed.createComponent(MyComp2);
(<MyComp2>fixture.componentInstance).ctxBoolProp = true;
@ -163,7 +163,7 @@ export function main() {
it('should add and remove fragments', () => {
TestBed.overrideComponent(
MyComp2, {set: {template: '<template [ngIf]="ctxBoolProp">hello</template>'}});
MyComp2, {set: {template: '<ng-container *ngIf="ctxBoolProp">hello</ng-container>'}});
const fixture = TestBed.createComponent(MyComp2);
const rootEl = getRenderElement(fixture.nativeElement);

View File

@ -71,4 +71,4 @@ Promise
return Promise.all(
allSpecFiles.map(function(moduleName) { return System.import(moduleName); }));
})
.then(__karma__.start, __karma__.error);
.then(__karma__.start, (v) => console.error(v));

View File

@ -133,7 +133,7 @@ export class RouterLink {
*/
@Directive({selector: 'a[routerLink]'})
export class RouterLinkWithHref implements OnChanges, OnDestroy {
@Input() target: string;
@HostBinding('attr.target') @Input() target: string;
@Input() queryParams: {[k: string]: any};
@Input() fragment: string;
@Input() preserveQueryParams: boolean;

View File

@ -526,6 +526,7 @@ export class Router {
*/
navigate(commands: any[], extras: NavigationExtras = {skipLocationChange: false}):
Promise<boolean> {
validateCommands(commands);
if (typeof extras.queryParams === 'object' && extras.queryParams !== null) {
extras.queryParams = this.removeEmptyProps(extras.queryParams);
}
@ -1237,3 +1238,12 @@ function getOutlet(outletMap: RouterOutletMap, route: ActivatedRoute): RouterOut
}
return outlet;
}
function validateCommands(commands: string[]): void {
for (let i = 0; i < commands.length; i++) {
const cmd = commands[i];
if (cmd == null) {
throw new Error(`The requested path contains ${cmd} segment at index ${i}`);
}
}
}

View File

@ -40,7 +40,7 @@ function equalSegmentGroups(container: UrlSegmentGroup, containee: UrlSegmentGro
function containsQueryParams(
container: {[k: string]: string}, containee: {[k: string]: string}): boolean {
return Object.keys(containee) <= Object.keys(container) &&
return Object.keys(containee).length <= Object.keys(container).length &&
Object.keys(containee).every(key => containee[key] === container[key]);
}

View File

@ -536,6 +536,17 @@ describe('Integration', () => {
expect(cmp.recordedParams).toEqual([{name: '1'}]);
})));
it('should throw an error when one of the commands is null/undefined',
fakeAsync(inject([Router], (router: Router) => {
createRoot(router, RootCmp);
router.resetConfig([{path: 'query', component: EmptyQueryParamsCmp}]);
expect(() => router.navigate([
undefined, 'query'
])).toThrowError(`The requested path contains undefined segment at index 0`);
})));
it('should push params only when they change', fakeAsync(inject([Router], (router: Router) => {
const fixture = createRoot(router, RootCmp);
@ -998,6 +1009,7 @@ describe('Integration', () => {
const native = fixture.nativeElement.querySelector('a');
expect(native.getAttribute('href')).toEqual('/team/33/simple');
expect(native.getAttribute('target')).toEqual('_self');
native.click();
advance(fixture);
@ -2646,7 +2658,8 @@ function expectEvents(events: Event[], pairs: any[]) {
}
}
@Component({selector: 'link-cmp', template: `<a routerLink="/team/33/simple">link</a>`})
@Component(
{selector: 'link-cmp', template: `<a routerLink="/team/33/simple" [target]="'_self'">link</a>`})
class StringLinkCmp {
}

View File

@ -102,8 +102,8 @@ describe('UrlTree', () => {
});
it('should return true when container contains containees queryParams', () => {
const t1 = serializer.parse('/one/two?test=1&page=5');
const t2 = serializer.parse('/one/two?test=1');
const t1 = serializer.parse('/one/two?test=1&u=5');
const t2 = serializer.parse('/one/two?u=5');
expect(containsTree(t1, t2, false)).toBe(true);
});

View File

@ -29,7 +29,7 @@ export function init(moduleRef: NgModuleRef<AppModule>) {
}
function detectChanges() {
for (var i = 0; i < 10; i++) {
for (let i = 0; i < 10; i++) {
appRef.tick();
}
detectChangesRuns += 10;

View File

@ -1,6 +1,6 @@
{
"name": "angular-srcs",
"version": "2.4.2",
"version": "2.4.3",
"private": true,
"branchPattern": "2.0.*",
"description": "Angular 2 - a web framework for modern web apps",

View File

@ -82,9 +82,7 @@ System.import('@angular/core/testing')
});
}));
})
.then(
function() { __karma__.start(); },
function(error) { __karma__.error(error.stack || error); });
.then(function() { __karma__.start(); }, function(error) { console.error(error); });
function onlySpecFiles(path) {

View File

@ -1,6 +1,6 @@
{
"name": "@angular/tsc-wrapped",
"version": "0.5.0",
"version": "0.5.1",
"description": "Wraps the tsc CLI, allowing extensions.",
"homepage": "https://github.com/angular/angular/tree/master/tools/tsc-wrapped",
"bugs": "https://github.com/angular/angular/issues",