Skip to content

Commit 30ea3a4

Browse files
vsavkingoderbauer
authored andcommitted
refactor(pipes): use Injector instead of pipe factories for pipe instantiation
BREAKING CHANGE - Pipe factories have been removed. - PIpe names to pipe implementations are 1-to-1 instead of 1-to-* Before: class DateFormatter { transform(date, args){} } class DateFormatterFactory { supporst(obj) { return true; } create(cdRef) { return new DateFormatter(); } } new Pipes({date: [new DateFormatterFactory()]}) After class DateFormatter { transform(date, args){} } new Pipes({date: DateFormatter})
1 parent 3283b81 commit 30ea3a4

28 files changed

+249
-524
lines changed

modules/angular2/change_detection.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,5 @@ export {
2929
KeyValueDiffers,
3030
KeyValueDiffer,
3131
KeyValueDifferFactory,
32-
PipeFactory,
33-
BasePipe,
34-
NullPipe,
35-
NullPipeFactory
32+
BasePipe
3633
} from 'angular2/src/change_detection/change_detection';

modules/angular2/src/change_detection/change_detection.ts

Lines changed: 23 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
11
import {JitProtoChangeDetector} from './jit_proto_change_detector';
22
import {PregenProtoChangeDetector} from './pregen_proto_change_detector';
33
import {DynamicProtoChangeDetector} from './proto_change_detector';
4-
import {PipeFactory, Pipe} from './pipes/pipe';
54
import {Pipes} from './pipes/pipes';
65
import {IterableDiffers, IterableDifferFactory} from './differs/iterable_differs';
76
import {DefaultIterableDifferFactory} from './differs/default_iterable_differ';
87
import {KeyValueDiffers, KeyValueDifferFactory} from './differs/keyvalue_differs';
98
import {DefaultKeyValueDifferFactory} from './differs/default_keyvalue_differ';
10-
import {AsyncPipeFactory} from './pipes/async_pipe';
9+
import {AsyncPipe} from './pipes/async_pipe';
1110
import {UpperCasePipe} from './pipes/uppercase_pipe';
1211
import {LowerCasePipe} from './pipes/lowercase_pipe';
1312
import {JsonPipe} from './pipes/json_pipe';
14-
import {LimitToPipeFactory} from './pipes/limit_to_pipe';
13+
import {LimitToPipe} from './pipes/limit_to_pipe';
1514
import {DatePipe} from './pipes/date_pipe';
1615
import {DecimalPipe, PercentPipe, CurrencyPipe} from './pipes/number_pipe';
17-
import {NullPipeFactory} from './pipes/null_pipe';
1816
import {ChangeDetection, ProtoChangeDetector, ChangeDetectorDefinition} from './interfaces';
19-
import {Inject, Injectable, OpaqueToken, Optional} from 'angular2/di';
17+
import {Injector, Inject, Injectable, OpaqueToken, Optional, Binding} from 'angular2/di';
2018
import {List, StringMap, StringMapWrapper} from 'angular2/src/facade/collection';
2119
import {CONST, CONST_EXPR, isPresent, BaseException} from 'angular2/src/facade/lang';
2220

@@ -55,9 +53,27 @@ export {ChangeDetectorRef} from './change_detector_ref';
5553
export {Pipes} from './pipes/pipes';
5654
export {IterableDiffers, IterableDiffer, IterableDifferFactory} from './differs/iterable_differs';
5755
export {KeyValueDiffers, KeyValueDiffer, KeyValueDifferFactory} from './differs/keyvalue_differs';
58-
export {WrappedValue, Pipe, PipeFactory, BasePipe} from './pipes/pipe';
59-
export {NullPipe, NullPipeFactory} from './pipes/null_pipe';
56+
export {WrappedValue, Pipe, BasePipe} from './pipes/pipe';
57+
58+
59+
function createPipes(inj: Injector): Pipes {
60+
return new Pipes(
61+
{
62+
"async": AsyncPipe,
63+
"uppercase": UpperCasePipe,
64+
"lowercase": LowerCasePipe,
65+
"json": JsonPipe,
66+
"limitTo": LimitToPipe,
67+
"number": DecimalPipe,
68+
"percent": PercentPipe,
69+
"currency": CurrencyPipe,
70+
"date": DatePipe
71+
},
72+
inj);
73+
}
6074

75+
export const defaultPipes: Binding =
76+
CONST_EXPR(new Binding(Pipes, {toFactory: createPipes, deps: [Injector]}));
6177

6278
/**
6379
* Structural diffing for `Object`s and `Map`s.
@@ -71,73 +87,6 @@ export const keyValDiff: KeyValueDifferFactory[] =
7187
export const iterableDiff: IterableDifferFactory[] =
7288
CONST_EXPR([CONST_EXPR(new DefaultIterableDifferFactory())]);
7389

74-
/**
75-
* Async binding to such types as Observable.
76-
*/
77-
export const async: List<PipeFactory> =
78-
CONST_EXPR([CONST_EXPR(new AsyncPipeFactory()), CONST_EXPR(new NullPipeFactory())]);
79-
80-
/**
81-
* Uppercase text transform.
82-
*/
83-
export const uppercase: List<PipeFactory> =
84-
CONST_EXPR([CONST_EXPR(new UpperCasePipe()), CONST_EXPR(new NullPipeFactory())]);
85-
86-
/**
87-
* Lowercase text transform.
88-
*/
89-
export const lowercase: List<PipeFactory> =
90-
CONST_EXPR([CONST_EXPR(new LowerCasePipe()), CONST_EXPR(new NullPipeFactory())]);
91-
92-
/**
93-
* Json stringify transform.
94-
*/
95-
export const json: List<PipeFactory> =
96-
CONST_EXPR([CONST_EXPR(new JsonPipe()), CONST_EXPR(new NullPipeFactory())]);
97-
98-
/**
99-
* LimitTo text transform.
100-
*/
101-
export const limitTo: List<PipeFactory> =
102-
CONST_EXPR([CONST_EXPR(new LimitToPipeFactory()), CONST_EXPR(new NullPipeFactory())]);
103-
104-
/**
105-
* Number number transform.
106-
*/
107-
export const decimal: List<PipeFactory> =
108-
CONST_EXPR([CONST_EXPR(new DecimalPipe()), CONST_EXPR(new NullPipeFactory())]);
109-
110-
/**
111-
* Percent number transform.
112-
*/
113-
export const percent: List<PipeFactory> =
114-
CONST_EXPR([CONST_EXPR(new PercentPipe()), CONST_EXPR(new NullPipeFactory())]);
115-
116-
/**
117-
* Currency number transform.
118-
*/
119-
export const currency: List<PipeFactory> =
120-
CONST_EXPR([CONST_EXPR(new CurrencyPipe()), CONST_EXPR(new NullPipeFactory())]);
121-
122-
/**
123-
* Date/time formatter.
124-
*/
125-
export const date: List<PipeFactory> =
126-
CONST_EXPR([CONST_EXPR(new DatePipe()), CONST_EXPR(new NullPipeFactory())]);
127-
128-
129-
export const defaultPipes: Pipes = CONST_EXPR(new Pipes({
130-
"async": async,
131-
"uppercase": uppercase,
132-
"lowercase": lowercase,
133-
"json": json,
134-
"limitTo": limitTo,
135-
"number": decimal,
136-
"percent": percent,
137-
"currency": currency,
138-
"date": date
139-
}));
140-
14190
export const defaultIterableDiffers = CONST_EXPR(new IterableDiffers(iterableDiff));
14291

14392
export const defaultKeyValueDiffers = CONST_EXPR(new KeyValueDiffers(keyValDiff));

modules/angular2/src/change_detection/change_detection_jit_generator.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,7 @@ export class ChangeDetectorJITGenerator {
184184

185185
var read = `
186186
if (${pipe} === ${UTIL}.uninitialized) {
187-
${pipe} = ${this._names.getPipesAccessorName()}.get('${pipeType}', ${context}, ${cdRef});
188-
} else if (!${pipe}.supports(${context})) {
189-
${pipe}.onDestroy();
190-
${pipe} = ${this._names.getPipesAccessorName()}.get('${pipeType}', ${context}, ${cdRef});
187+
${pipe} = ${this._names.getPipesAccessorName()}.get('${pipeType}', ${cdRef});
191188
}
192189
${newValue} = ${pipe}.transform(${context}, [${argString}]);
193190
`;

modules/angular2/src/change_detection/dynamic_change_detector.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -267,13 +267,9 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
267267

268268
_pipeFor(proto: ProtoRecord, context) {
269269
var storedPipe = this._readPipe(proto);
270-
if (isPresent(storedPipe) && storedPipe.supports(context)) {
271-
return storedPipe;
272-
}
273-
if (isPresent(storedPipe)) {
274-
storedPipe.onDestroy();
275-
}
276-
var pipe = this.pipes.get(proto.name, context, this.ref);
270+
if (isPresent(storedPipe)) return storedPipe;
271+
272+
var pipe = this.pipes.get(proto.name, this.ref);
277273
this._writePipe(proto, pipe);
278274
return pipe;
279275
}

modules/angular2/src/change_detection/pipes/async_pipe.ts

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {isBlank, isPresent, isPromise, CONST, BaseException} from 'angular2/src/facade/lang';
22
import {Observable, Promise, ObservableWrapper} from 'angular2/src/facade/async';
3-
import {Pipe, WrappedValue, PipeFactory} from './pipe';
3+
import {Injectable} from 'angular2/di';
4+
import {Pipe, WrappedValue, InvalidPipeArgumentException} from './pipe';
45
import {ChangeDetectorRef} from '../change_detector_ref';
56

67

@@ -52,6 +53,7 @@ var _observableStrategy = new ObservableStrategy();
5253
*
5354
* ```
5455
*/
56+
@Injectable()
5557
export class AsyncPipe implements Pipe {
5658
_latestValue: Object = null;
5759
_latestReturnedValue: Object = null;
@@ -62,8 +64,6 @@ export class AsyncPipe implements Pipe {
6264

6365
constructor(public _ref: ChangeDetectorRef) {}
6466

65-
supports(obj: any): boolean { return true; }
66-
6767
onDestroy(): void {
6868
if (isPresent(this._subscription)) {
6969
this._dispose();
@@ -98,13 +98,13 @@ export class AsyncPipe implements Pipe {
9898
this._strategy.createSubscription(obj, value => this._updateLatestValue(obj, value));
9999
}
100100

101-
_selectStrategy(obj: Observable | Promise<any>) {
101+
_selectStrategy(obj: Observable | Promise<any>): any {
102102
if (isPromise(obj)) {
103103
return _promiseStrategy;
104104
} else if (ObservableWrapper.isObservable(obj)) {
105105
return _observableStrategy;
106106
} else {
107-
throw new BaseException(`Async pipe does not support object '${obj}'`);
107+
throw new InvalidPipeArgumentException(AsyncPipe, obj);
108108
}
109109
}
110110

@@ -122,13 +122,4 @@ export class AsyncPipe implements Pipe {
122122
this._ref.requestCheck();
123123
}
124124
}
125-
}
126-
127-
/**
128-
* Provides a factory for [AsyncPipe].
129-
*/
130-
@CONST()
131-
export class AsyncPipeFactory implements PipeFactory {
132-
supports(obj: any): boolean { return true; }
133-
create(cdRef: ChangeDetectorRef): Pipe { return new AsyncPipe(cdRef); }
134-
}
125+
}

modules/angular2/src/change_detection/pipes/date_pipe.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ import {
55
Date,
66
DateWrapper,
77
CONST,
8+
isBlank,
89
FunctionWrapper
910
} from 'angular2/src/facade/lang';
1011
import {DateFormatter} from 'angular2/src/facade/intl';
12+
import {Injectable} from 'angular2/di';
1113
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
12-
import {Pipe, BasePipe, PipeFactory} from './pipe';
13-
import {ChangeDetectorRef} from '../change_detector_ref';
14+
import {Pipe, BasePipe, InvalidPipeArgumentException} from './pipe';
1415

1516
// TODO: move to a global configable location along with other i18n components.
1617
var defaultLocale: string = 'en-US';
@@ -70,7 +71,8 @@ var defaultLocale: string = 'en-US';
7071
* {{ dateObj | date:'mmss' }} // output is '43:11'
7172
*/
7273
@CONST()
73-
export class DatePipe extends BasePipe implements PipeFactory {
74+
@Injectable()
75+
export class DatePipe extends BasePipe {
7476
static _ALIASES = {
7577
'medium': 'yMMMdjms',
7678
'short': 'yMdjm',
@@ -84,6 +86,12 @@ export class DatePipe extends BasePipe implements PipeFactory {
8486

8587

8688
transform(value: any, args: List<any>): string {
89+
if (isBlank(value)) return null;
90+
91+
if (!this.supports(value)) {
92+
throw new InvalidPipeArgumentException(DatePipe, value);
93+
}
94+
8795
var pattern: string = isPresent(args) && args.length > 0 ? args[0] : 'mediumDate';
8896
if (isNumber(value)) {
8997
value = DateWrapper.fromMillis(value);
@@ -95,6 +103,4 @@ export class DatePipe extends BasePipe implements PipeFactory {
95103
}
96104

97105
supports(obj: any): boolean { return isDate(obj) || isNumber(obj); }
98-
99-
create(cdRef: ChangeDetectorRef): Pipe { return this; }
100106
}

modules/angular2/src/change_detection/pipes/json_pipe.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {isBlank, isPresent, Json, CONST} from 'angular2/src/facade/lang';
2-
import {Pipe, BasePipe, PipeFactory} from './pipe';
3-
import {ChangeDetectorRef} from '../change_detector_ref';
2+
import {Injectable} from 'angular2/di';
3+
import {Pipe, BasePipe} from './pipe';
44

55
/**
66
* Implements json transforms to any object.
@@ -26,8 +26,7 @@ import {ChangeDetectorRef} from '../change_detector_ref';
2626
* ```
2727
*/
2828
@CONST()
29-
export class JsonPipe extends BasePipe implements PipeFactory {
29+
@Injectable()
30+
export class JsonPipe extends BasePipe {
3031
transform(value: any, args: List<any> = null): string { return Json.stringify(value); }
31-
32-
create(cdRef: ChangeDetectorRef): Pipe { return this; }
3332
}

modules/angular2/src/change_detection/pipes/limit_to_pipe.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import {
88
} from 'angular2/src/facade/lang';
99
import {ListWrapper} from 'angular2/src/facade/collection';
1010
import {Math} from 'angular2/src/facade/math';
11-
import {WrappedValue, Pipe, PipeFactory} from './pipe';
12-
import {ChangeDetectorRef} from '../change_detector_ref';
11+
import {Injectable} from 'angular2/di';
12+
import {WrappedValue, Pipe, InvalidPipeArgumentException} from './pipe';
1313

1414
/**
1515
* Creates a new List or String containing only a prefix/suffix of the
@@ -50,15 +50,18 @@ import {ChangeDetectorRef} from '../change_detector_ref';
5050
* {{ 'abcdefghij' | limitTo: -4 }} // output is 'ghij'
5151
* {{ 'abcdefghij' | limitTo: -100 }} // output is 'abcdefghij'
5252
*/
53+
@Injectable()
5354
export class LimitToPipe implements Pipe {
54-
static supportsObj(obj: any): boolean { return isString(obj) || isArray(obj); }
55-
56-
supports(obj: any): boolean { return LimitToPipe.supportsObj(obj); }
55+
supports(obj: any): boolean { return isString(obj) || isArray(obj); }
5756

5857
transform(value: any, args: List<any> = null): any {
5958
if (isBlank(args) || args.length == 0) {
6059
throw new BaseException('limitTo pipe requires one argument');
6160
}
61+
if (!this.supports(value)) {
62+
throw new InvalidPipeArgumentException(LimitToPipe, value);
63+
}
64+
if (isBlank(value)) return value;
6265
var limit: int = args[0];
6366
var left = 0, right = Math.min(limit, value.length);
6467
if (limit < 0) {
@@ -73,10 +76,3 @@ export class LimitToPipe implements Pipe {
7376

7477
onDestroy(): void {}
7578
}
76-
77-
@CONST()
78-
export class LimitToPipeFactory implements PipeFactory {
79-
supports(obj: any): boolean { return LimitToPipe.supportsObj(obj); }
80-
81-
create(cdRef: ChangeDetectorRef): Pipe { return new LimitToPipe(); }
82-
}

modules/angular2/src/change_detection/pipes/lowercase_pipe.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import {isString, StringWrapper, CONST} from 'angular2/src/facade/lang';
2-
import {Pipe, BasePipe, PipeFactory} from './pipe';
3-
import {ChangeDetectorRef} from '../change_detector_ref';
1+
import {isString, StringWrapper, CONST, isBlank} from 'angular2/src/facade/lang';
2+
import {Injectable} from 'angular2/di';
3+
import {Pipe, BasePipe, InvalidPipeArgumentException} from './pipe';
44

55
/**
66
* Implements lowercase transforms to text.
@@ -23,12 +23,13 @@ import {ChangeDetectorRef} from '../change_detector_ref';
2323
* ```
2424
*/
2525
@CONST()
26-
export class LowerCasePipe extends BasePipe implements PipeFactory {
27-
supports(str: any): boolean { return isString(str); }
28-
26+
@Injectable()
27+
export class LowerCasePipe extends BasePipe {
2928
transform(value: string, args: List<any> = null): string {
29+
if (isBlank(value)) return value;
30+
if (!isString(value)) {
31+
throw new InvalidPipeArgumentException(LowerCasePipe, value);
32+
}
3033
return StringWrapper.toLowerCase(value);
3134
}
32-
33-
create(cdRef: ChangeDetectorRef): Pipe { return this; }
3435
}

modules/angular2/src/change_detection/pipes/null_pipe.ts

Lines changed: 0 additions & 27 deletions
This file was deleted.

0 commit comments

Comments
 (0)