2015-07-27 13:16:20 -07:00
|
|
|
import {isPresent, BaseException} from 'angular2/src/facade/lang';
|
2015-02-05 13:08:05 -08:00
|
|
|
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
2015-04-14 07:47:12 -07:00
|
|
|
import {ChangeDetectorRef} from './change_detector_ref';
|
2015-07-28 12:43:41 -07:00
|
|
|
import {DirectiveRecord} from './directive_record';
|
|
|
|
import {ChangeDetector, ChangeDispatcher} from './interfaces';
|
2015-07-05 14:46:35 -07:00
|
|
|
import {ChangeDetectionError} from './exceptions';
|
|
|
|
import {ProtoRecord} from './proto_record';
|
2015-06-18 14:47:38 -07:00
|
|
|
import {Locals} from './parser/locals';
|
2015-07-28 12:43:41 -07:00
|
|
|
import {Pipes} from './pipes/pipes';
|
2015-03-30 16:54:10 -07:00
|
|
|
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';
|
2015-01-21 12:05:52 -08:00
|
|
|
|
2015-07-23 18:01:34 -07:00
|
|
|
class _Context {
|
|
|
|
constructor(public element: any, public componentElement: any, public instance: any,
|
|
|
|
public context: any, public locals: any, public injector: any,
|
|
|
|
public expression: any) {}
|
|
|
|
}
|
|
|
|
|
2015-07-28 12:43:41 -07:00
|
|
|
export class AbstractChangeDetector<T> implements ChangeDetector {
|
2015-06-16 08:47:24 +02:00
|
|
|
lightDomChildren: List<any> = [];
|
|
|
|
shadowDomChildren: List<any> = [];
|
2015-05-01 14:05:19 -07:00
|
|
|
parent: ChangeDetector;
|
|
|
|
ref: ChangeDetectorRef;
|
2015-01-21 12:05:52 -08:00
|
|
|
|
2015-07-28 12:43:41 -07:00
|
|
|
// The names of the below fields must be kept in sync with codegen_name_util.ts or
|
|
|
|
// change detection will fail.
|
|
|
|
alreadyChecked: any = false;
|
|
|
|
context: T;
|
|
|
|
currentProto: ProtoRecord = null;
|
|
|
|
directiveRecords: List<DirectiveRecord>;
|
|
|
|
dispatcher: ChangeDispatcher;
|
|
|
|
locals: Locals = null;
|
|
|
|
mode: string = null;
|
|
|
|
pipes: Pipes = null;
|
|
|
|
protos: List<ProtoRecord>;
|
|
|
|
|
|
|
|
constructor(public id: string, dispatcher: ChangeDispatcher, protos: List<ProtoRecord>,
|
|
|
|
directiveRecords: List<DirectiveRecord>) {
|
|
|
|
this.ref = new ChangeDetectorRef(this);
|
|
|
|
this.directiveRecords = directiveRecords;
|
|
|
|
this.dispatcher = dispatcher;
|
|
|
|
this.protos = protos;
|
|
|
|
}
|
2015-01-21 12:05:52 -08:00
|
|
|
|
2015-06-16 08:47:24 +02:00
|
|
|
addChild(cd: ChangeDetector): void {
|
2015-06-17 11:17:21 -07:00
|
|
|
this.lightDomChildren.push(cd);
|
2015-01-21 12:05:52 -08:00
|
|
|
cd.parent = this;
|
|
|
|
}
|
|
|
|
|
2015-06-16 08:47:24 +02:00
|
|
|
removeChild(cd: ChangeDetector): void { ListWrapper.remove(this.lightDomChildren, cd); }
|
2015-03-27 11:02:55 -07:00
|
|
|
|
2015-06-16 08:47:24 +02:00
|
|
|
addShadowDomChild(cd: ChangeDetector): void {
|
2015-06-17 11:17:21 -07:00
|
|
|
this.shadowDomChildren.push(cd);
|
2015-03-27 11:02:55 -07:00
|
|
|
cd.parent = this;
|
2015-01-21 12:05:52 -08:00
|
|
|
}
|
|
|
|
|
2015-06-16 08:47:24 +02:00
|
|
|
removeShadowDomChild(cd: ChangeDetector): void { ListWrapper.remove(this.shadowDomChildren, cd); }
|
2015-04-14 18:01:08 -07:00
|
|
|
|
2015-06-16 08:47:24 +02:00
|
|
|
remove(): void { this.parent.removeChild(this); }
|
2015-01-21 12:05:52 -08:00
|
|
|
|
2015-07-27 13:16:20 -07:00
|
|
|
detectChanges(): void { this.runDetectChanges(false); }
|
2015-01-21 12:05:52 -08:00
|
|
|
|
2015-07-27 13:16:20 -07:00
|
|
|
checkNoChanges(): void { throw new BaseException("Not implemented"); }
|
2015-01-21 12:05:52 -08:00
|
|
|
|
2015-07-27 13:16:20 -07:00
|
|
|
runDetectChanges(throwOnChange: boolean): void {
|
2015-02-01 12:09:35 -08:00
|
|
|
if (this.mode === DETACHED || this.mode === CHECKED) return;
|
|
|
|
|
2015-01-21 12:05:52 -08:00
|
|
|
this.detectChangesInRecords(throwOnChange);
|
2015-03-27 11:02:55 -07:00
|
|
|
|
|
|
|
this._detectChangesInLightDomChildren(throwOnChange);
|
|
|
|
|
2015-05-18 21:29:23 -07:00
|
|
|
if (throwOnChange === false) this.callOnAllChangesDone();
|
2015-02-01 12:09:35 -08:00
|
|
|
|
2015-03-27 11:02:55 -07:00
|
|
|
this._detectChangesInShadowDomChildren(throwOnChange);
|
|
|
|
|
2015-02-01 12:09:35 -08:00
|
|
|
if (this.mode === CHECK_ONCE) this.mode = CHECKED;
|
|
|
|
}
|
|
|
|
|
2015-06-16 08:47:24 +02:00
|
|
|
detectChangesInRecords(throwOnChange: boolean): void {}
|
2015-06-18 14:47:38 -07:00
|
|
|
|
2015-07-28 12:43:41 -07:00
|
|
|
hydrate(context: T, locals: Locals, directives: any, pipes: any): void {}
|
2015-06-18 14:47:38 -07:00
|
|
|
|
2015-07-27 18:31:22 -07:00
|
|
|
hydrateDirectives(directives: any): void {}
|
|
|
|
|
2015-06-18 14:47:38 -07:00
|
|
|
dehydrate(): void {}
|
|
|
|
|
2015-07-27 18:31:22 -07:00
|
|
|
dehydrateDirectives(destroyPipes: boolean): void {}
|
|
|
|
|
2015-06-16 08:47:24 +02:00
|
|
|
callOnAllChangesDone(): void {}
|
2015-01-21 12:05:52 -08:00
|
|
|
|
2015-06-16 08:47:24 +02:00
|
|
|
_detectChangesInLightDomChildren(throwOnChange: boolean): void {
|
2015-03-27 11:02:55 -07:00
|
|
|
var c = this.lightDomChildren;
|
2015-05-01 14:05:19 -07:00
|
|
|
for (var i = 0; i < c.length; ++i) {
|
2015-07-27 13:16:20 -07:00
|
|
|
c[i].runDetectChanges(throwOnChange);
|
2015-03-27 11:02:55 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-16 08:47:24 +02:00
|
|
|
_detectChangesInShadowDomChildren(throwOnChange: boolean): void {
|
2015-03-27 11:02:55 -07:00
|
|
|
var c = this.shadowDomChildren;
|
2015-05-01 14:05:19 -07:00
|
|
|
for (var i = 0; i < c.length; ++i) {
|
2015-07-27 13:16:20 -07:00
|
|
|
c[i].runDetectChanges(throwOnChange);
|
2015-01-21 12:05:52 -08:00
|
|
|
}
|
|
|
|
}
|
2015-02-11 16:28:10 -08:00
|
|
|
|
2015-06-16 08:47:24 +02:00
|
|
|
markAsCheckOnce(): void { this.mode = CHECK_ONCE; }
|
2015-04-14 08:54:09 -07:00
|
|
|
|
2015-06-16 08:47:24 +02:00
|
|
|
markPathToRootAsCheckOnce(): void {
|
2015-05-01 14:05:19 -07:00
|
|
|
var c: ChangeDetector = this;
|
|
|
|
while (isPresent(c) && c.mode != DETACHED) {
|
2015-02-11 16:28:10 -08:00
|
|
|
if (c.mode === CHECKED) c.mode = CHECK_ONCE;
|
|
|
|
c = c.parent;
|
|
|
|
}
|
|
|
|
}
|
2015-07-05 14:46:35 -07:00
|
|
|
|
|
|
|
throwError(proto: ProtoRecord, exception: any, stack: any): void {
|
2015-07-23 18:01:34 -07:00
|
|
|
var c = this.dispatcher.getDebugContext(proto.bindingRecord.elementIndex, proto.directiveIndex);
|
2015-07-27 15:47:42 -07:00
|
|
|
var context = isPresent(c) ? new _Context(c.element, c.componentElement, c.directive, c.context,
|
|
|
|
c.locals, c.injector, proto.expressionAsString) :
|
|
|
|
null;
|
2015-07-23 18:01:34 -07:00
|
|
|
throw new ChangeDetectionError(proto, exception, stack, context);
|
2015-07-05 14:46:35 -07:00
|
|
|
}
|
2015-07-27 18:31:22 -07:00
|
|
|
}
|