build(typescript): Migrated change detection to typescript

This commit is contained in:
vsavkin
2015-05-07 17:18:04 -07:00
parent f0ef72d6cc
commit fa28b28d0a
45 changed files with 2343 additions and 2576 deletions
@@ -4,12 +4,17 @@ import {ChangeDetectorRef} from './change_detector_ref';
import {ChangeDetector} from './interfaces';
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';
// HACK: workaround for Traceur behavior.
// It expects all transpiled modules to contain this marker.
// TODO: remove this when we no longer use traceur
export var __esModule = true;
export class AbstractChangeDetector extends ChangeDetector {
lightDomChildren:List;
shadowDomChildren:List;
parent:ChangeDetector;
mode:string;
ref:ChangeDetectorRef;
lightDomChildren: List<any>;
shadowDomChildren: List<any>;
parent: ChangeDetector;
mode: string;
ref: ChangeDetectorRef;
constructor() {
super();
@@ -19,37 +24,27 @@ export class AbstractChangeDetector extends ChangeDetector {
this.mode = null;
}
addChild(cd:ChangeDetector) {
addChild(cd: ChangeDetector) {
ListWrapper.push(this.lightDomChildren, cd);
cd.parent = this;
}
removeChild(cd:ChangeDetector) {
ListWrapper.remove(this.lightDomChildren, cd);
}
removeChild(cd: ChangeDetector) { ListWrapper.remove(this.lightDomChildren, cd); }
addShadowDomChild(cd:ChangeDetector) {
addShadowDomChild(cd: ChangeDetector) {
ListWrapper.push(this.shadowDomChildren, cd);
cd.parent = this;
}
removeShadowDomChild(cd:ChangeDetector) {
ListWrapper.remove(this.shadowDomChildren, cd);
}
removeShadowDomChild(cd: ChangeDetector) { ListWrapper.remove(this.shadowDomChildren, cd); }
remove() {
this.parent.removeChild(this);
}
remove() { this.parent.removeChild(this); }
detectChanges() {
this._detectChanges(false);
}
detectChanges() { this._detectChanges(false); }
checkNoChanges() {
this._detectChanges(true);
}
checkNoChanges() { this._detectChanges(true); }
_detectChanges(throwOnChange:boolean) {
_detectChanges(throwOnChange: boolean) {
if (this.mode === DETACHED || this.mode === CHECKED) return;
this.detectChangesInRecords(throwOnChange);
@@ -63,30 +58,28 @@ export class AbstractChangeDetector extends ChangeDetector {
if (this.mode === CHECK_ONCE) this.mode = CHECKED;
}
detectChangesInRecords(throwOnChange:boolean){}
callOnAllChangesDone(){}
detectChangesInRecords(throwOnChange: boolean) {}
callOnAllChangesDone() {}
_detectChangesInLightDomChildren(throwOnChange:boolean) {
_detectChangesInLightDomChildren(throwOnChange: boolean) {
var c = this.lightDomChildren;
for(var i = 0; i < c.length; ++i) {
for (var i = 0; i < c.length; ++i) {
c[i]._detectChanges(throwOnChange);
}
}
_detectChangesInShadowDomChildren(throwOnChange:boolean) {
_detectChangesInShadowDomChildren(throwOnChange: boolean) {
var c = this.shadowDomChildren;
for(var i = 0; i < c.length; ++i) {
for (var i = 0; i < c.length; ++i) {
c[i]._detectChanges(throwOnChange);
}
}
markAsCheckOnce() {
this.mode = CHECK_ONCE;
}
markAsCheckOnce() { this.mode = CHECK_ONCE; }
markPathToRootAsCheckOnce() {
var c = this;
while(isPresent(c) && c.mode != DETACHED) {
var c: ChangeDetector = this;
while (isPresent(c) && c.mode != DETACHED) {
if (c.mode === CHECKED) c.mode = CHECK_ONCE;
c = c.parent;
}
-68
View File
@@ -1,68 +0,0 @@
import {isPresent, isBlank} from 'angular2/src/facade/lang';
import {SetterFn} from 'angular2/src/reflection/types';
import {AST} from './parser/ast';
import {DirectiveIndex, DirectiveRecord} from './directive_record';
const DIRECTIVE="directive";
const ELEMENT="element";
const TEXT_NODE="textNode";
export class BindingRecord {
mode:string;
ast:AST;
implicitReceiver:any; //number | DirectiveIndex
elementIndex:number;
propertyName:string;
setter:SetterFn;
directiveRecord:DirectiveRecord;
constructor(mode:string, implicitReceiver:any, ast:AST, elementIndex:number, propertyName:string, setter:SetterFn, directiveRecord:DirectiveRecord) {
this.mode = mode;
this.implicitReceiver = implicitReceiver;
this.ast = ast;
this.elementIndex = elementIndex;
this.propertyName = propertyName;
this.setter = setter;
this.directiveRecord = directiveRecord;
}
callOnChange() {
return isPresent(this.directiveRecord) && this.directiveRecord.callOnChange;
}
isOnPushChangeDetection() {
return isPresent(this.directiveRecord) && this.directiveRecord.isOnPushChangeDetection();
}
isDirective() {
return this.mode === DIRECTIVE;
}
isElement() {
return this.mode === ELEMENT;
}
isTextNode() {
return this.mode === TEXT_NODE;
}
static createForDirective(ast:AST, propertyName:string, setter:SetterFn, directiveRecord:DirectiveRecord) {
return new BindingRecord(DIRECTIVE, 0, ast, 0, propertyName, setter, directiveRecord);
}
static createForElement(ast:AST, elementIndex:number, propertyName:string) {
return new BindingRecord(ELEMENT, 0, ast, elementIndex, propertyName, null, null);
}
static createForHostProperty(directiveIndex:DirectiveIndex, ast:AST, propertyName:string) {
return new BindingRecord(ELEMENT, directiveIndex, ast, directiveIndex.elementIndex, propertyName, null, null);
}
static createForTextNode(ast:AST, elementIndex:number) {
return new BindingRecord(TEXT_NODE, 0, ast, elementIndex, null, null, null);
}
}
@@ -0,0 +1,49 @@
import {isPresent, isBlank} from 'angular2/src/facade/lang';
import {SetterFn} from 'angular2/src/reflection/types';
import {AST} from './parser/ast';
import {DirectiveIndex, DirectiveRecord} from './directive_record';
// HACK: workaround for Traceur behavior.
// It expects all transpiled modules to contain this marker.
// TODO: remove this when we no longer use traceur
export var __esModule = true;
const DIRECTIVE = "directive";
const ELEMENT = "element";
const TEXT_NODE = "textNode";
export class BindingRecord {
constructor(public mode: string, public implicitReceiver: any, public ast: AST,
public elementIndex: number, public propertyName: string, public setter: SetterFn,
public directiveRecord: DirectiveRecord) {}
callOnChange() { return isPresent(this.directiveRecord) && this.directiveRecord.callOnChange; }
isOnPushChangeDetection() {
return isPresent(this.directiveRecord) && this.directiveRecord.isOnPushChangeDetection();
}
isDirective() { return this.mode === DIRECTIVE; }
isElement() { return this.mode === ELEMENT; }
isTextNode() { return this.mode === TEXT_NODE; }
static createForDirective(ast: AST, propertyName: string, setter: SetterFn,
directiveRecord: DirectiveRecord) {
return new BindingRecord(DIRECTIVE, 0, ast, 0, propertyName, setter, directiveRecord);
}
static createForElement(ast: AST, elementIndex: number, propertyName: string) {
return new BindingRecord(ELEMENT, 0, ast, elementIndex, propertyName, null, null);
}
static createForHostProperty(directiveIndex: DirectiveIndex, ast: AST, propertyName: string) {
return new BindingRecord(ELEMENT, directiveIndex, ast, directiveIndex.elementIndex,
propertyName, null, null);
}
static createForTextNode(ast: AST, elementIndex: number) {
return new BindingRecord(TEXT_NODE, 0, ast, elementIndex, null, null, null);
}
}
@@ -1,96 +0,0 @@
import {DynamicProtoChangeDetector, JitProtoChangeDetector} from './proto_change_detector';
import {PipeFactory} from './pipes/pipe';
import {PipeRegistry} from './pipes/pipe_registry';
import {IterableChangesFactory} from './pipes/iterable_changes';
import {KeyValueChangesFactory} from './pipes/keyvalue_changes';
import {AsyncPipeFactory} from './pipes/async_pipe';
import {NullPipeFactory} from './pipes/null_pipe';
import {BindingRecord} from './binding_record';
import {DirectiveRecord} from './directive_record';
import {DEFAULT} from './constants';
import {ChangeDetection, ProtoChangeDetector} from './interfaces';
import {Injectable} from 'angular2/src/di/annotations_impl';
import {List} from 'angular2/src/facade/collection';
/**
* Structural diffing for `Object`s and `Map`s.
*
* @exportedAs angular2/pipes
*/
export var keyValDiff:List<PipeFactory> = [
new KeyValueChangesFactory(),
new NullPipeFactory()
];
/**
* Structural diffing for `Iterable` types such as `Array`s.
*
* @exportedAs angular2/pipes
*/
export var iterableDiff:List<PipeFactory> = [
new IterableChangesFactory(),
new NullPipeFactory()
];
/**
* Async binding to such types as Observable.
*
* @exportedAs angular2/pipes
*/
export var async:List<PipeFactory> = [
new AsyncPipeFactory(),
new NullPipeFactory()
];
export var defaultPipes:Map<String, List<PipeFactory>> = {
"iterableDiff" : iterableDiff,
"keyValDiff" : keyValDiff,
"async" : async
};
/**
* Implements change detection that does not require `eval()`.
*
* This is slower than {@link JitChangeDetection}.
*
* @exportedAs angular2/change_detection
*/
@Injectable()
export class DynamicChangeDetection extends ChangeDetection {
registry:PipeRegistry;
constructor(registry:PipeRegistry) {
super();
this.registry = registry;
}
createProtoChangeDetector(name:string, bindingRecords:List<BindingRecord>, variableBindings:List<string>,
directiveRecords:List<DirectiveRecord>, changeControlStrategy:string = DEFAULT):ProtoChangeDetector{
return new DynamicProtoChangeDetector(this.registry, bindingRecords, variableBindings, directiveRecords, changeControlStrategy);
}
}
/**
* Implements faster change detection, by generating source code.
*
* This requires `eval()`. For change detection that does not require `eval()`, see {@link DynamicChangeDetection}.
*
* @exportedAs angular2/change_detection
*/
@Injectable()
export class JitChangeDetection extends ChangeDetection {
registry:PipeRegistry;
constructor(registry:PipeRegistry) {
super();
this.registry = registry;
}
createProtoChangeDetector(name:string, bindingRecords:List<BindingRecord>, variableBindings:List<string>,
directiveRecords:List<DirectiveRecord>, changeControlStrategy:string = DEFAULT):ProtoChangeDetector{
return new JitProtoChangeDetector(this.registry, bindingRecords, variableBindings, directiveRecords, changeControlStrategy);
}
}
export var defaultPipeRegistry:PipeRegistry = new PipeRegistry(defaultPipes);
@@ -0,0 +1,88 @@
import {DynamicProtoChangeDetector, JitProtoChangeDetector} from './proto_change_detector';
import {PipeFactory} from './pipes/pipe';
import {PipeRegistry} from './pipes/pipe_registry';
import {IterableChangesFactory} from './pipes/iterable_changes';
import {KeyValueChangesFactory} from './pipes/keyvalue_changes';
import {AsyncPipeFactory} from './pipes/async_pipe';
import {NullPipeFactory} from './pipes/null_pipe';
import {BindingRecord} from './binding_record';
import {DirectiveRecord} from './directive_record';
import {DEFAULT} from './constants';
import {ChangeDetection, ProtoChangeDetector} from './interfaces';
import {Injectable} from 'angular2/src/di/decorators';
import {List} from 'angular2/src/facade/collection';
// HACK: workaround for Traceur behavior.
// It expects all transpiled modules to contain this marker.
// TODO: remove this when we no longer use traceur
export var __esModule = true;
/**
* Structural diffing for `Object`s and `Map`s.
*
* @exportedAs angular2/pipes
*/
export var keyValDiff: List < PipeFactory >= [new KeyValueChangesFactory(), new NullPipeFactory()];
/**
* Structural diffing for `Iterable` types such as `Array`s.
*
* @exportedAs angular2/pipes
*/
export var iterableDiff: List <
PipeFactory >= [new IterableChangesFactory(), new NullPipeFactory()];
/**
* Async binding to such types as Observable.
*
* @exportedAs angular2/pipes
*/
export var async: List < PipeFactory >= [new AsyncPipeFactory(), new NullPipeFactory()];
export var defaultPipes = {
"iterableDiff": iterableDiff,
"keyValDiff": keyValDiff,
"async": async
};
/**
* Implements change detection that does not require `eval()`.
*
* This is slower than {@link JitChangeDetection}.
*
* @exportedAs angular2/change_detection
*/
@Injectable()
export class DynamicChangeDetection extends ChangeDetection {
constructor(public registry: PipeRegistry) { super(); }
createProtoChangeDetector(name: string, bindingRecords: List<BindingRecord>,
variableBindings: List<string>, directiveRecords: List<DirectiveRecord>,
changeControlStrategy: string = DEFAULT): ProtoChangeDetector {
return new DynamicProtoChangeDetector(this.registry, bindingRecords, variableBindings,
directiveRecords, changeControlStrategy);
}
}
/**
* Implements faster change detection, by generating source code.
*
* This requires `eval()`. For change detection that does not require `eval()`, see {@link
*DynamicChangeDetection}.
*
* @exportedAs angular2/change_detection
*/
@Injectable()
export class JitChangeDetection extends ChangeDetection {
constructor(public registry: PipeRegistry) { super(); }
createProtoChangeDetector(name: string, bindingRecords: List<BindingRecord>,
variableBindings: List<string>, directiveRecords: List<DirectiveRecord>,
changeControlStrategy: string = DEFAULT): ProtoChangeDetector {
return new JitProtoChangeDetector(this.registry, bindingRecords, variableBindings,
directiveRecords, changeControlStrategy);
}
}
export var defaultPipeRegistry: PipeRegistry = new PipeRegistry(defaultPipes);
@@ -1,139 +0,0 @@
import {isPresent, isBlank, BaseException, Type} from 'angular2/src/facade/lang';
import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
import {ProtoRecord} from './proto_record';
import {ExpressionChangedAfterItHasBeenChecked} from './exceptions';
import {WrappedValue} from './pipes/pipe';
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';
export var uninitialized = new Object();
export class SimpleChange {
previousValue:any;
currentValue:any;
constructor(previousValue:any, currentValue:any) {
this.previousValue = previousValue;
this.currentValue = currentValue;
}
}
var _simpleChangesIndex = 0;
var _simpleChanges = [
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null)
];
function _simpleChange(previousValue, currentValue) {
var index = _simpleChangesIndex++ % 20;
var s = _simpleChanges[index];
s.previousValue = previousValue;
s.currentValue = currentValue;
return s;
}
export class ChangeDetectionUtil {
static unitialized() {
return uninitialized;
}
static arrayFn0() { return []; }
static arrayFn1(a1) { return [a1]; }
static arrayFn2(a1, a2) { return [a1, a2]; }
static arrayFn3(a1, a2, a3) { return [a1, a2, a3]; }
static arrayFn4(a1, a2, a3, a4) { return [a1, a2, a3, a4]; }
static arrayFn5(a1, a2, a3, a4, a5) { return [a1, a2, a3, a4, a5]; }
static arrayFn6(a1, a2, a3, a4, a5, a6) { return [a1, a2, a3, a4, a5, a6]; }
static arrayFn7(a1, a2, a3, a4, a5, a6, a7) { return [a1, a2, a3, a4, a5, a6, a7]; }
static arrayFn8(a1, a2, a3, a4, a5, a6, a7, a8) { return [a1, a2, a3, a4, a5, a6, a7, a8]; }
static arrayFn9(a1, a2, a3, a4, a5, a6, a7, a8, a9) { return [a1, a2, a3, a4, a5, a6, a7, a8, a9]; }
static operation_negate(value) {return !value;}
static operation_add(left, right) {return left + right;}
static operation_subtract(left, right) {return left - right;}
static operation_multiply(left, right) {return left * right;}
static operation_divide(left, right) {return left / right;}
static operation_remainder(left, right) {return left % right;}
static operation_equals(left, right) {return left == right;}
static operation_not_equals(left, right) {return left != right;}
static operation_less_then(left, right) {return left < right;}
static operation_greater_then(left, right) {return left > right;}
static operation_less_or_equals_then(left, right) {return left <= right;}
static operation_greater_or_equals_then(left, right) {return left >= right;}
static operation_logical_and(left, right) {return left && right;}
static operation_logical_or(left, right) {return left || right;}
static cond(cond, trueVal, falseVal) {return cond ? trueVal : falseVal;}
static mapFn(keys:List) {
function buildMap(values) {
var res = StringMapWrapper.create();
for(var i = 0; i < keys.length; ++i) {
StringMapWrapper.set(res, keys[i], values[i]);
}
return res;
}
switch (keys.length) {
case 0: return () => [];
case 1: return (a1) => buildMap([a1]);
case 2: return (a1, a2) => buildMap([a1, a2]);
case 3: return (a1, a2, a3) => buildMap([a1, a2, a3]);
case 4: return (a1, a2, a3, a4) => buildMap([a1, a2, a3, a4]);
case 5: return (a1, a2, a3, a4, a5) => buildMap([a1, a2, a3, a4, a5]);
case 6: return (a1, a2, a3, a4, a5, a6) => buildMap([a1, a2, a3, a4, a5, a6]);
case 7: return (a1, a2, a3, a4, a5, a6, a7) => buildMap([a1, a2, a3, a4, a5, a6, a7]);
case 8: return (a1, a2, a3, a4, a5, a6, a7, a8) => buildMap([a1, a2, a3, a4, a5, a6, a7, a8]);
case 9: return (a1, a2, a3, a4, a5, a6, a7, a8, a9) => buildMap([a1, a2, a3, a4, a5, a6, a7, a8, a9]);
default: throw new BaseException(`Does not support literal maps with more than 9 elements`);
}
}
static keyedAccess(obj, args) {
return obj[args[0]];
}
static unwrapValue(value:any):any {
if (value instanceof WrappedValue) {
return value.wrapped;
} else {
return value;
}
}
static throwOnChange(proto:ProtoRecord, change) {
throw new ExpressionChangedAfterItHasBeenChecked(proto, change);
}
static changeDetectionMode(strategy:string) {
return strategy == ON_PUSH ? CHECK_ONCE : CHECK_ALWAYS;
}
static simpleChange(previousValue:any, currentValue:any):SimpleChange {
return _simpleChange(previousValue, currentValue);
}
static addChange(changes, propertyName:string, change){
if (isBlank(changes)) {
changes = {};
}
changes[propertyName] = change;
return changes;
}
}
@@ -0,0 +1,148 @@
import {isPresent, isBlank, BaseException, Type} from 'angular2/src/facade/lang';
import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
import {ProtoRecord} from './proto_record';
import {ExpressionChangedAfterItHasBeenChecked} from './exceptions';
import {WrappedValue} from './pipes/pipe';
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';
// HACK: workaround for Traceur behavior.
// It expects all transpiled modules to contain this marker.
// TODO: remove this when we no longer use traceur
export var __esModule = true;
export var uninitialized = new Object();
export class SimpleChange {
constructor(public previousValue: any, public currentValue: any) {}
}
var _simpleChangesIndex = 0;
var _simpleChanges = [
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null),
new SimpleChange(null, null)
];
function _simpleChange(previousValue, currentValue) {
var index = _simpleChangesIndex++ % 20;
var s = _simpleChanges[index];
s.previousValue = previousValue;
s.currentValue = currentValue;
return s;
}
export class ChangeDetectionUtil {
static unitialized() { return uninitialized; }
static arrayFn0() { return []; }
static arrayFn1(a1) { return [a1]; }
static arrayFn2(a1, a2) { return [a1, a2]; }
static arrayFn3(a1, a2, a3) { return [a1, a2, a3]; }
static arrayFn4(a1, a2, a3, a4) { return [a1, a2, a3, a4]; }
static arrayFn5(a1, a2, a3, a4, a5) { return [a1, a2, a3, a4, a5]; }
static arrayFn6(a1, a2, a3, a4, a5, a6) { return [a1, a2, a3, a4, a5, a6]; }
static arrayFn7(a1, a2, a3, a4, a5, a6, a7) { return [a1, a2, a3, a4, a5, a6, a7]; }
static arrayFn8(a1, a2, a3, a4, a5, a6, a7, a8) { return [a1, a2, a3, a4, a5, a6, a7, a8]; }
static arrayFn9(a1, a2, a3, a4, a5, a6, a7, a8, a9) {
return [a1, a2, a3, a4, a5, a6, a7, a8, a9];
}
static operation_negate(value) { return !value; }
static operation_add(left, right) { return left + right; }
static operation_subtract(left, right) { return left - right; }
static operation_multiply(left, right) { return left * right; }
static operation_divide(left, right) { return left / right; }
static operation_remainder(left, right) { return left % right; }
static operation_equals(left, right) { return left == right; }
static operation_not_equals(left, right) { return left != right; }
static operation_less_then(left, right) { return left < right; }
static operation_greater_then(left, right) { return left > right; }
static operation_less_or_equals_then(left, right) { return left <= right; }
static operation_greater_or_equals_then(left, right) { return left >= right; }
static operation_logical_and(left, right) { return left && right; }
static operation_logical_or(left, right) { return left || right; }
static cond(cond, trueVal, falseVal) { return cond ? trueVal : falseVal; }
static mapFn(keys: List<any>) {
function buildMap(values) {
var res = StringMapWrapper.create();
for (var i = 0; i < keys.length; ++i) {
StringMapWrapper.set(res, keys[i], values[i]);
}
return res;
}
switch (keys.length) {
case 0:
return () => [];
case 1:
return (a1) => buildMap([a1]);
case 2:
return (a1, a2) => buildMap([a1, a2]);
case 3:
return (a1, a2, a3) => buildMap([a1, a2, a3]);
case 4:
return (a1, a2, a3, a4) => buildMap([a1, a2, a3, a4]);
case 5:
return (a1, a2, a3, a4, a5) => buildMap([a1, a2, a3, a4, a5]);
case 6:
return (a1, a2, a3, a4, a5, a6) => buildMap([a1, a2, a3, a4, a5, a6]);
case 7:
return (a1, a2, a3, a4, a5, a6, a7) => buildMap([a1, a2, a3, a4, a5, a6, a7]);
case 8:
return (a1, a2, a3, a4, a5, a6, a7, a8) => buildMap([a1, a2, a3, a4, a5, a6, a7, a8]);
case 9:
return (a1, a2, a3, a4, a5, a6, a7, a8, a9) =>
buildMap([a1, a2, a3, a4, a5, a6, a7, a8, a9]);
default:
throw new BaseException(`Does not support literal maps with more than 9 elements`);
}
}
static keyedAccess(obj, args) { return obj[args[0]]; }
static unwrapValue(value: any): any {
if (value instanceof WrappedValue) {
return value.wrapped;
} else {
return value;
}
}
static throwOnChange(proto: ProtoRecord, change) {
throw new ExpressionChangedAfterItHasBeenChecked(proto, change);
}
static changeDetectionMode(strategy: string) {
return strategy == ON_PUSH ? CHECK_ONCE : CHECK_ALWAYS;
}
static simpleChange(previousValue: any, currentValue: any): SimpleChange {
return _simpleChange(previousValue, currentValue);
}
static addChange(changes, propertyName: string, change) {
if (isBlank(changes)) {
changes = {};
}
changes[propertyName] = change;
return changes;
}
}
@@ -1,41 +1,40 @@
import {ChangeDetector} from './interfaces';
import {CHECK_ONCE, DETACHED, CHECK_ALWAYS} from './constants';
// HACK: workaround for Traceur behavior.
// It expects all transpiled modules to contain this marker.
// TODO: remove this when we no longer use traceur
export var __esModule = true;
/**
* Controls change detection.
*
* {@link ChangeDetectorRef} allows requesting checks for detectors that rely on observables. It also allows detaching and
* {@link ChangeDetectorRef} allows requesting checks for detectors that rely on observables. It
*also allows detaching and
* attaching change detector subtrees.
*
* @exportedAs angular2/change_detection
*/
export class ChangeDetectorRef {
_cd:ChangeDetector;
constructor(cd:ChangeDetector) {
this._cd = cd;
}
constructor(private _cd: ChangeDetector) {}
/**
* Request to check all ON_PUSH ancestors.
*/
requestCheck() {
this._cd.markPathToRootAsCheckOnce();
}
requestCheck() { this._cd.markPathToRootAsCheckOnce(); }
/**
* Detaches the change detector from the change detector tree.
*
* The detached change detector will not be checked until it is reattached.
*/
detach() {
this._cd.mode = DETACHED;
}
detach() { this._cd.mode = DETACHED; }
/**
* Reattach the change detector to the change detector tree.
*
* This also requests a check of this change detector. This reattached change detector will be checked during the
* This also requests a check of this change detector. This reattached change detector will be
*checked during the
* next change detection run.
*/
reattach() {
@@ -2,6 +2,11 @@ import {isPresent} from 'angular2/src/facade/lang';
import {List, ListWrapper, Map, MapWrapper} from 'angular2/src/facade/collection';
import {RECORD_TYPE_SELF, ProtoRecord} from './proto_record';
// HACK: workaround for Traceur behavior.
// It expects all transpiled modules to contain this marker.
// TODO: remove this when we no longer use traceur
export var __esModule = true;
/**
* Removes "duplicate" records. It assuming that record evaluation does not
* have side-effects.
@@ -12,7 +17,7 @@ import {RECORD_TYPE_SELF, ProtoRecord} from './proto_record';
* Records that are last in bindings CANNOT be removed, and instead are
* replaced with very cheap SELF records.
*/
export function coalesce(records:List<ProtoRecord>):List<ProtoRecord> {
export function coalesce(records: List<ProtoRecord>): List<ProtoRecord> {
var res = ListWrapper.create();
var indexMap = MapWrapper.create();
@@ -37,52 +42,27 @@ export function coalesce(records:List<ProtoRecord>):List<ProtoRecord> {
return res;
}
function _selfRecord(r:ProtoRecord, contextIndex:number, selfIndex:number):ProtoRecord {
return new ProtoRecord(
RECORD_TYPE_SELF,
"self",
null,
[],
r.fixedArgs,
contextIndex,
r.directiveIndex,
selfIndex,
r.bindingRecord,
r.expressionAsString,
r.lastInBinding,
r.lastInDirective
);
function _selfRecord(r: ProtoRecord, contextIndex: number, selfIndex: number): ProtoRecord {
return new ProtoRecord(RECORD_TYPE_SELF, "self", null, [], r.fixedArgs, contextIndex,
r.directiveIndex, selfIndex, r.bindingRecord, r.expressionAsString,
r.lastInBinding, r.lastInDirective);
}
function _findMatching(r:ProtoRecord, rs:List<ProtoRecord>){
return ListWrapper.find(rs, (rr) =>
rr.mode === r.mode &&
rr.funcOrValue === r.funcOrValue &&
rr.contextIndex === r.contextIndex &&
ListWrapper.equals(rr.args, r.args)
);
function _findMatching(r: ProtoRecord, rs: List<ProtoRecord>) {
return ListWrapper.find(rs, (rr) => rr.mode === r.mode && rr.funcOrValue === r.funcOrValue &&
rr.contextIndex === r.contextIndex &&
ListWrapper.equals(rr.args, r.args));
}
function _replaceIndices(r:ProtoRecord, selfIndex:number, indexMap:Map) {
function _replaceIndices(r: ProtoRecord, selfIndex: number, indexMap: Map<any, any>) {
var args = ListWrapper.map(r.args, (a) => _map(indexMap, a));
var contextIndex = _map(indexMap, r.contextIndex);
return new ProtoRecord(
r.mode,
r.name,
r.funcOrValue,
args,
r.fixedArgs,
contextIndex,
r.directiveIndex,
selfIndex,
r.bindingRecord,
r.expressionAsString,
r.lastInBinding,
r.lastInDirective
);
return new ProtoRecord(r.mode, r.name, r.funcOrValue, args, r.fixedArgs, contextIndex,
r.directiveIndex, selfIndex, r.bindingRecord, r.expressionAsString,
r.lastInBinding, r.lastInDirective);
}
function _map(indexMap:Map, value:number) {
var r = MapWrapper.get(indexMap, value)
function _map(indexMap: Map<any, any>, value: number) {
var r = MapWrapper.get(indexMap, value);
return isPresent(r) ? r : value;
}
@@ -1,28 +1,33 @@
//TODO:vsavkin Use enums after switching to TypeScript
// TODO:vsavkin Use enums after switching to TypeScript
// HACK: workaround for Traceur behavior.
// It expects all transpiled modules to contain this marker.
// TODO: remove this when we no longer use traceur
export var __esModule = true;
/**
* CHECK_ONCE means that after calling detectChanges the mode of the change detector
* will become CHECKED.
*/
export const CHECK_ONCE="CHECK_ONCE";
export const CHECK_ONCE = "CHECK_ONCE";
/**
* CHECKED means that the change detector should be skipped until its mode changes to
* CHECK_ONCE or CHECK_ALWAYS.
*/
export const CHECKED="CHECKED";
export const CHECKED = "CHECKED";
/**
* CHECK_ALWAYS means that after calling detectChanges the mode of the change detector
* will remain CHECK_ALWAYS.
*/
export const CHECK_ALWAYS="ALWAYS_CHECK";
export const CHECK_ALWAYS = "ALWAYS_CHECK";
/**
* DETACHED means that the change detector sub tree is not a part of the main tree and
* should be skipped.
*/
export const DETACHED="DETACHED";
export const DETACHED = "DETACHED";
/**
* ON_PUSH means that the change detector's mode will be set to CHECK_ONCE during hydration.
@@ -1,34 +0,0 @@
import {ON_PUSH} from './constants';
import {StringWrapper} from 'angular2/src/facade/lang';
export class DirectiveIndex {
elementIndex:number;
directiveIndex:number;
constructor(elementIndex:number, directiveIndex:number) {
this.elementIndex = elementIndex;
this.directiveIndex = directiveIndex;
}
get name() {
return `${this.elementIndex}_${this.directiveIndex}`;
}
}
export class DirectiveRecord {
directiveIndex:DirectiveIndex;
callOnAllChangesDone:boolean;
callOnChange:boolean;
changeDetection:string;
constructor(directiveIndex:DirectiveIndex, callOnAllChangesDone:boolean, callOnChange:boolean, changeDetection:string) {
this.directiveIndex = directiveIndex;
this.callOnAllChangesDone = callOnAllChangesDone;
this.callOnChange = callOnChange;
this.changeDetection = changeDetection;
}
isOnPushChangeDetection():boolean {
return StringWrapper.equals(this.changeDetection, ON_PUSH);
}
}
@@ -0,0 +1,20 @@
import {ON_PUSH} from './constants';
import {StringWrapper} from 'angular2/src/facade/lang';
// HACK: workaround for Traceur behavior.
// It expects all transpiled modules to contain this marker.
// TODO: remove this when we no longer use traceur
export var __esModule = true;
export class DirectiveIndex {
constructor(public elementIndex: number, public directiveIndex: number) {}
get name() { return `${this.elementIndex}_${this.directiveIndex}`; }
}
export class DirectiveRecord {
constructor(public directiveIndex: DirectiveIndex, public callOnAllChangesDone: boolean,
public callOnChange: boolean, public changeDetection: string) {}
isOnPushChangeDetection(): boolean { return StringWrapper.equals(this.changeDetection, ON_PUSH); }
}
@@ -4,7 +4,7 @@ import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/faca
import {AbstractChangeDetector} from './abstract_change_detector';
import {BindingRecord} from './binding_record';
import {PipeRegistry} from './pipes/pipe_registry';
import {ChangeDetectionUtil, uninitialized} from './change_detection_util';
import {ChangeDetectionUtil, SimpleChange, uninitialized} from './change_detection_util';
import {
@@ -20,35 +20,31 @@ import {
RECORD_TYPE_PIPE,
RECORD_TYPE_BINDING_PIPE,
RECORD_TYPE_INTERPOLATE
} from './proto_record';
} from './proto_record';
import {ExpressionChangedAfterItHasBeenChecked, ChangeDetectionError} from './exceptions';
// HACK: workaround for Traceur behavior.
// It expects all transpiled modules to contain this marker.
// TODO: remove this when we no longer use traceur
export var __esModule = true;
export class DynamicChangeDetector extends AbstractChangeDetector {
dispatcher:any;
pipeRegistry;
locals: any;
values: List<any>;
changes: List<any>;
pipes: List<any>;
prevContexts: List<any>;
directives: any;
locals:any;
values:List;
changes:List;
pipes:List;
prevContexts:List;
protos:List<ProtoRecord>;
directives:any;
directiveRecords:List;
changeControlStrategy:string;
constructor(changeControlStrategy:string, dispatcher:any, pipeRegistry:PipeRegistry,
protoRecords:List<ProtoRecord>, directiveRecords:List) {
constructor(private changeControlStrategy: string, private dispatcher: any,
private pipeRegistry: PipeRegistry, private protos: List<ProtoRecord>,
private directiveRecords: List<any>) {
super();
this.dispatcher = dispatcher;
this.pipeRegistry = pipeRegistry;
this.values = ListWrapper.createFixedSize(protoRecords.length + 1);
this.pipes = ListWrapper.createFixedSize(protoRecords.length + 1);
this.prevContexts = ListWrapper.createFixedSize(protoRecords.length + 1);
this.changes = ListWrapper.createFixedSize(protoRecords.length + 1);
this.values = ListWrapper.createFixedSize(protos.length + 1);
this.pipes = ListWrapper.createFixedSize(protos.length + 1);
this.prevContexts = ListWrapper.createFixedSize(protos.length + 1);
this.changes = ListWrapper.createFixedSize(protos.length + 1);
ListWrapper.fill(this.values, uninitialized);
ListWrapper.fill(this.pipes, null);
@@ -56,13 +52,9 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
ListWrapper.fill(this.changes, false);
this.locals = null;
this.directives = null;
this.protos = protoRecords;
this.directiveRecords = directiveRecords;
this.changeControlStrategy = changeControlStrategy;
}
hydrate(context:any, locals:any, directives:any) {
hydrate(context: any, locals: any, directives: any) {
this.mode = ChangeDetectionUtil.changeDetectionMode(this.changeControlStrategy);
this.values[0] = context;
this.locals = locals;
@@ -79,24 +71,22 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
}
_destroyPipes() {
for(var i = 0; i < this.pipes.length; ++i) {
for (var i = 0; i < this.pipes.length; ++i) {
if (isPresent(this.pipes[i])) {
this.pipes[i].onDestroy();
}
}
}
hydrated():boolean {
return this.values[0] !== uninitialized;
}
hydrated(): boolean { return this.values[0] !== uninitialized; }
detectChangesInRecords(throwOnChange:boolean) {
var protos:List<ProtoRecord> = this.protos;
detectChangesInRecords(throwOnChange: boolean) {
var protos: List < ProtoRecord >= this.protos;
var changes = null;
var isChanged = false;
for (var i = 0; i < protos.length; ++i) {
var proto:ProtoRecord = protos[i];
var proto: ProtoRecord = protos[i];
var bindingRecord = proto.bindingRecord;
var directiveRecord = bindingRecord.directiveRecord;
@@ -142,7 +132,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
}
}
_addChange(bindingRecord:BindingRecord, change, changes) {
_addChange(bindingRecord: BindingRecord, change, changes) {
if (bindingRecord.callOnChange()) {
return ChangeDetectionUtil.addChange(changes, bindingRecord.propertyName, change);
} else {
@@ -150,15 +140,11 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
}
}
_getDirectiveFor(directiveIndex) {
return this.directives.getDirectiveFor(directiveIndex);
}
_getDirectiveFor(directiveIndex) { return this.directives.getDirectiveFor(directiveIndex); }
_getDetectorFor(directiveIndex) {
return this.directives.getDetectorFor(directiveIndex);
}
_getDetectorFor(directiveIndex) { return this.directives.getDetectorFor(directiveIndex); }
_check(proto:ProtoRecord) {
_check(proto: ProtoRecord): SimpleChange {
try {
if (proto.mode === RECORD_TYPE_PIPE || proto.mode === RECORD_TYPE_BINDING_PIPE) {
return this._pipeCheck(proto);
@@ -170,7 +156,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
}
}
_referenceCheck(proto:ProtoRecord) {
_referenceCheck(proto: ProtoRecord) {
if (this._pureFuncAndArgsDidNotChange(proto)) {
this._setChanged(proto, false);
return null;
@@ -194,7 +180,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
}
}
_calculateCurrValue(proto:ProtoRecord) {
_calculateCurrValue(proto: ProtoRecord) {
switch (proto.mode) {
case RECORD_TYPE_SELF:
return this._readContext(proto);
@@ -230,7 +216,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
}
}
_pipeCheck(proto:ProtoRecord) {
_pipeCheck(proto: ProtoRecord) {
var context = this._readContext(proto);
var pipe = this._pipeFor(proto, context);
var prevValue = this._readSelf(proto);
@@ -254,7 +240,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
}
}
_pipeFor(proto:ProtoRecord, context) {
_pipeFor(proto: ProtoRecord, context) {
var storedPipe = this._readPipe(proto);
if (isPresent(storedPipe) && storedPipe.supports(context)) {
return storedPipe;
@@ -274,7 +260,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
return pipe;
}
_readContext(proto:ProtoRecord) {
_readContext(proto: ProtoRecord) {
if (proto.contextIndex == -1) {
return this._getDirectiveFor(proto.directiveIndex);
} else {
@@ -284,33 +270,23 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
return this.values[proto.contextIndex];
}
_readSelf(proto:ProtoRecord) {
return this.values[proto.selfIndex];
}
_readSelf(proto: ProtoRecord) { return this.values[proto.selfIndex]; }
_writeSelf(proto:ProtoRecord, value) {
this.values[proto.selfIndex] = value;
}
_writeSelf(proto: ProtoRecord, value) { this.values[proto.selfIndex] = value; }
_readPipe(proto:ProtoRecord) {
return this.pipes[proto.selfIndex];
}
_readPipe(proto: ProtoRecord) { return this.pipes[proto.selfIndex]; }
_writePipe(proto:ProtoRecord, value) {
this.pipes[proto.selfIndex] = value;
}
_writePipe(proto: ProtoRecord, value) { this.pipes[proto.selfIndex] = value; }
_setChanged(proto:ProtoRecord, value:boolean) {
this.changes[proto.selfIndex] = value;
}
_setChanged(proto: ProtoRecord, value: boolean) { this.changes[proto.selfIndex] = value; }
_pureFuncAndArgsDidNotChange(proto:ProtoRecord):boolean {
_pureFuncAndArgsDidNotChange(proto: ProtoRecord): boolean {
return proto.isPureFunction() && !this._argsChanged(proto);
}
_argsChanged(proto:ProtoRecord):boolean {
_argsChanged(proto: ProtoRecord): boolean {
var args = proto.args;
for(var i = 0; i < args.length; ++i) {
for (var i = 0; i < args.length; ++i) {
if (this.changes[args[i]]) {
return true;
}
@@ -318,7 +294,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
return false;
}
_readArgs(proto:ProtoRecord) {
_readArgs(proto: ProtoRecord) {
var res = ListWrapper.createFixedSize(proto.args.length);
var args = proto.args;
for (var i = 0; i < args.length; ++i) {
@@ -334,6 +310,3 @@ function isSame(a, b) {
if ((a !== a) && (b !== b)) return true;
return false;
}
-33
View File
@@ -1,33 +0,0 @@
import {ProtoRecord} from './proto_record';
import {BaseException} from "angular2/src/facade/lang";
export class ExpressionChangedAfterItHasBeenChecked extends BaseException {
message:string;
constructor(proto:ProtoRecord, change:any) {
super();
this.message = `Expression '${proto.expressionAsString}' has changed after it was checked. ` +
`Previous value: '${change.previousValue}'. Current value: '${change.currentValue}'`;
}
toString():string {
return this.message;
}
}
export class ChangeDetectionError extends BaseException {
message:string;
originalException:any;
location:string;
constructor(proto:ProtoRecord, originalException:any) {
super();
this.originalException = originalException;
this.location = proto.expressionAsString;
this.message = `${this.originalException} in [${this.location}]`;
}
toString():string {
return this.message;
}
}
@@ -0,0 +1,36 @@
import {ProtoRecord} from './proto_record';
import {BaseException} from "angular2/src/facade/lang";
// HACK: workaround for Traceur behavior.
// It expects all transpiled modules to contain this marker.
// TODO: remove this when we no longer use traceur
export var __esModule = true;
export class ExpressionChangedAfterItHasBeenChecked extends BaseException {
message: string;
constructor(proto: ProtoRecord, change: any) {
super();
this.message =
`Expression '${proto.expressionAsString}' has changed after it was checked. ` +
`Previous value: '${change.previousValue}'. Current value: '${change.currentValue}'`;
}
toString(): string { return this.message; }
}
export class ChangeDetectionError extends BaseException {
message: string;
originalException: any;
location: string;
constructor(proto: ProtoRecord, originalException: any) {
super();
this.originalException = originalException;
this.location = proto.expressionAsString;
this.message = `${this.originalException} in [${this.location}]`;
}
toString(): string { return this.message; }
}
@@ -3,10 +3,13 @@ import {Locals} from './parser/locals';
import {DEFAULT} from './constants';
import {BindingRecord} from './binding_record';
export class ProtoChangeDetector {
instantiate(dispatcher:any):ChangeDetector{
return null;
}
// HACK: workaround for Traceur behavior.
// It expects all transpiled modules to contain this marker.
// TODO: remove this when we no longer use traceur
export var __esModule = true;
export class ProtoChangeDetector {
instantiate(dispatcher: any): ChangeDetector { return null; }
}
/**
@@ -17,10 +20,12 @@ export class ProtoChangeDetector {
* - {@link DynamicChangeDetection}: slower, but does not require `eval()`.
* - {@link JitChangeDetection}: faster, but requires `eval()`.
*
* In JavaScript, you should always use `JitChangeDetection`, unless you are in an environment that has
* In JavaScript, you should always use `JitChangeDetection`, unless you are in an environment that
*has
* [CSP](https://developer.mozilla.org/en-US/docs/Web/Security/CSP), such as a Chrome Extension.
*
* In Dart, use `DynamicChangeDetection` during development. The Angular transformer generates an analog to the
* In Dart, use `DynamicChangeDetection` during development. The Angular transformer generates an
*analog to the
* `JitChangeDetection` strategy at compile time.
*
*
@@ -33,26 +38,27 @@ export class ProtoChangeDetector {
* @exportedAs angular2/change_detection
*/
export class ChangeDetection {
createProtoChangeDetector(name:string, bindingRecords:List, variableBindings:List, directiveRecords:List,
changeControlStrategy:string=DEFAULT):ProtoChangeDetector{
createProtoChangeDetector(name: string, bindingRecords: List<any>, variableBindings: List<any>,
directiveRecords: List<any>,
changeControlStrategy: string = DEFAULT): ProtoChangeDetector {
return null;
}
}
export class ChangeDispatcher {
notifyOnBinding(bindingRecord:BindingRecord, value:any) {}
notifyOnBinding(bindingRecord: BindingRecord, value: any) {}
}
export class ChangeDetector {
parent:ChangeDetector;
mode:string;
parent: ChangeDetector;
mode: string;
addChild(cd:ChangeDetector) {}
addShadowDomChild(cd:ChangeDetector) {}
removeChild(cd:ChangeDetector) {}
removeShadowDomChild(cd:ChangeDetector) {}
addChild(cd: ChangeDetector) {}
addShadowDomChild(cd: ChangeDetector) {}
removeChild(cd: ChangeDetector) {}
removeShadowDomChild(cd: ChangeDetector) {}
remove() {}
hydrate(context:any, locals:Locals, directives:any) {}
hydrate(context: any, locals: Locals, directives: any) {}
dehydrate() {}
markPathToRootAsCheckOnce() {}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,16 +1,15 @@
import {isPresent, BaseException} from 'angular2/src/facade/lang';
import {ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
// HACK: workaround for Traceur behavior.
// It expects all transpiled modules to contain this marker.
// TODO: remove this when we no longer use traceur
export var __esModule = true;
export class Locals {
parent:Locals;
current:Map;
constructor(public parent: Locals, public current: Map<any, any>) {}
constructor(parent:Locals, current:Map) {
this.parent = parent;
this.current = current;
}
contains(name:string):boolean {
contains(name: string): boolean {
if (MapWrapper.contains(this.current, name)) {
return true;
}
@@ -22,7 +21,7 @@ export class Locals {
return false;
}
get(name:string) {
get(name: string) {
if (MapWrapper.contains(this.current, name)) {
return MapWrapper.get(this.current, name);
}
@@ -34,7 +33,7 @@ export class Locals {
throw new BaseException(`Cannot find '${name}'`);
}
set(name:string, value):void {
set(name: string, value): void {
// TODO(rado): consider removing this check if we can guarantee this is not
// exposed to the public API.
// TODO: vsavkin maybe it should check only the local map
@@ -45,7 +44,5 @@ export class Locals {
}
}
clearValues():void {
MapWrapper.clearValues(this.current);
}
clearValues(): void { MapWrapper.clearValues(this.current); }
}
@@ -3,13 +3,21 @@ import {isBlank, isPresent, CONST} from 'angular2/src/facade/lang';
import {Pipe, WrappedValue, PipeFactory} from './pipe';
import {ChangeDetectorRef} from '../change_detector_ref';
// HACK: workaround for Traceur behavior.
// It expects all transpiled modules to contain this marker.
// TODO: remove this when we no longer use traceur
export var __esModule = true;
/**
* Implements async bindings to Observable.
*
* # Example
*
* In this example we bind the description observable to the DOM. The async pipe will convert an observable to the
* latest value it emitted. It will also request a change detection check when a new value is emitted.
* In this example we bind the description observable to the DOM. The async pipe will convert an
*observable to the
* latest value it emitted. It will also request a change detection check when a new value is
*emitted.
*
* ```
* @Component({
@@ -28,15 +36,15 @@ import {ChangeDetectorRef} from '../change_detector_ref';
* @exportedAs angular2/pipes
*/
export class AsyncPipe extends Pipe {
_ref:ChangeDetectorRef;
_ref: ChangeDetectorRef;
_latestValue:Object;
_latestReturnedValue:Object;
_latestValue: Object;
_latestReturnedValue: Object;
_subscription:Object;
_observable:Observable;
_subscription: Object;
_observable: Observable;
constructor(ref:ChangeDetectorRef) {
constructor(ref: ChangeDetectorRef) {
super();
this._ref = ref;
this._latestValue = null;
@@ -45,17 +53,15 @@ export class AsyncPipe extends Pipe {
this._observable = null;
}
supports(obs):boolean {
return ObservableWrapper.isObservable(obs);
}
supports(obs): boolean { return ObservableWrapper.isObservable(obs); }
onDestroy():void {
onDestroy(): void {
if (isPresent(this._subscription)) {
this._dispose();
}
}
transform(obs:Observable):any {
transform(obs: Observable): any {
if (isBlank(this._subscription)) {
this._subscribe(obs);
return null;
@@ -74,15 +80,13 @@ export class AsyncPipe extends Pipe {
}
}
_subscribe(obs:Observable):void {
_subscribe(obs: Observable): void {
this._observable = obs;
this._subscription = ObservableWrapper.subscribe(obs,
value => this._updateLatestValue(value),
e => {throw e;}
);
this._subscription = ObservableWrapper.subscribe(obs, value => {this._updateLatestValue(value)},
e => { throw e; });
}
_dispose():void {
_dispose(): void {
ObservableWrapper.dispose(this._subscription);
this._latestValue = null;
this._latestReturnedValue = null;
@@ -90,7 +94,7 @@ export class AsyncPipe extends Pipe {
this._observable = null;
}
_updateLatestValue(value:Object) {
_updateLatestValue(value: Object) {
this._latestValue = value;
this._ref.requestCheck();
}
@@ -101,17 +105,11 @@ export class AsyncPipe extends Pipe {
*
* @exportedAs angular2/pipes
*/
@CONST()
export class AsyncPipeFactory extends PipeFactory {
@CONST()
constructor() {
super();
}
constructor() { super(); }
supports(obs):boolean {
return ObservableWrapper.isObservable(obs);
}
supports(obs): boolean { return ObservableWrapper.isObservable(obs); }
create(cdRef):Pipe {
return new AsyncPipe(cdRef);
}
create(cdRef): Pipe { return new AsyncPipe(cdRef); }
}
@@ -1,48 +0,0 @@
import {isBlank, CONST} from 'angular2/src/facade/lang';
import {Pipe, WrappedValue, PipeFactory} from './pipe';
/**
* @exportedAs angular2/pipes
*/
export class NullPipeFactory extends PipeFactory {
@CONST()
constructor() {
super();
}
supports(obj):boolean {
return NullPipe.supportsObj(obj);
}
create(cdRef):Pipe {
return new NullPipe();
}
}
/**
* @exportedAs angular2/pipes
*/
export class NullPipe extends Pipe {
called:boolean;
constructor() {
super();
this.called = false;
}
static supportsObj(obj):boolean {
return isBlank(obj);
}
supports(obj) {
return NullPipe.supportsObj(obj);
}
transform(value) {
if (! this.called) {
this.called = true;
return WrappedValue.wrap(null);
} else {
return null;
}
}
}
@@ -0,0 +1,43 @@
import {isBlank, CONST} from 'angular2/src/facade/lang';
import {Pipe, WrappedValue, PipeFactory} from './pipe';
// HACK: workaround for Traceur behavior.
// It expects all transpiled modules to contain this marker.
// TODO: remove this when we no longer use traceur
export var __esModule = true;
/**
* @exportedAs angular2/pipes
*/
@CONST()
export class NullPipeFactory extends PipeFactory {
constructor() { super(); }
supports(obj): boolean { return NullPipe.supportsObj(obj); }
create(cdRef): Pipe { return new NullPipe(); }
}
/**
* @exportedAs angular2/pipes
*/
export class NullPipe extends Pipe {
called: boolean;
constructor() {
super();
this.called = false;
}
static supportsObj(obj): boolean { return isBlank(obj); }
supports(obj) { return NullPipe.supportsObj(obj); }
transform(value) {
if (!this.called) {
this.called = true;
return WrappedValue.wrap(null);
} else {
return null;
}
}
}
@@ -1,20 +1,22 @@
import {ABSTRACT, BaseException, CONST} from 'angular2/src/facade/lang';
// HACK: workaround for Traceur behavior.
// It expects all transpiled modules to contain this marker.
// TODO: remove this when we no longer use traceur
export var __esModule = true;
/**
* Indicates that the result of a {@link Pipe} transformation has changed even though the reference has not changed.
* Indicates that the result of a {@link Pipe} transformation has changed even though the reference
*has not changed.
*
* The wrapped value will be unwrapped by change detection, and the unwrapped value will be stored.
*
* @exportedAs angular2/pipes
*/
export class WrappedValue {
wrapped:any;
constructor(public wrapped: any) {}
constructor(wrapped:any) {
this.wrapped = wrapped;
}
static wrap(value:any):WrappedValue {
static wrap(value: any): WrappedValue {
var w = _wrappedValues[_wrappedIndex++ % 5];
w.wrapped = value;
return w;
@@ -53,26 +55,25 @@ var _wrappedIndex = 0;
* @exportedAs angular2/pipes
*/
export class Pipe {
supports(obj):boolean {return false;}
supports(obj): boolean { return false; }
onDestroy() {}
transform(value:any):any {return null;}
transform(value: any): any { return null; }
}
@ABSTRACT()
// TODO: vsavkin: make it an interface
@CONST()
export class PipeFactory {
@CONST()
constructor() {
supports(obs): boolean {
_abstract();
return false;
}
supports(obs):boolean {
return _abstract();
}
create(cdRef):Pipe {
return _abstract();
create(cdRef): Pipe {
_abstract();
return null;
}
}
function _abstract() {
return new BaseException('This method is abstract');
throw new BaseException('This method is abstract');
}
@@ -1,25 +1,25 @@
import {List, ListWrapper} from 'angular2/src/facade/collection';
import {isBlank, isPresent, BaseException, CONST} from 'angular2/src/facade/lang';
import {Pipe} from './pipe';
import {Injectable} from 'angular2/src/di/annotations_impl';
import {Injectable} from 'angular2/src/di/decorators';
import {ChangeDetectorRef} from '../change_detector_ref';
// HACK: workaround for Traceur behavior.
// It expects all transpiled modules to contain this marker.
// TODO: remove this when we no longer use traceur
export var __esModule = true;
@Injectable()
export class PipeRegistry {
config;
constructor(public config) {}
constructor(config){
this.config = config;
}
get(type:string, obj, cdRef:ChangeDetectorRef):Pipe {
get(type: string, obj, cdRef: ChangeDetectorRef): Pipe {
var listOfConfigs = this.config[type];
if (isBlank(listOfConfigs)) {
throw new BaseException(`Cannot find '${type}' pipe supporting object '${obj}'`);
}
var matchingConfig = ListWrapper.find(listOfConfigs,
(pipeConfig) => pipeConfig.supports(obj));
var matchingConfig = ListWrapper.find(listOfConfigs, (pipeConfig) => pipeConfig.supports(obj));
if (isBlank(matchingConfig)) {
throw new BaseException(`Cannot find '${type}' pipe supporting object '${obj}'`);

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