feat(change_detection): provide error context for change detection errors
This commit is contained in:
@ -7,6 +7,12 @@ import {ProtoRecord} from './proto_record';
|
||||
import {Locals} from './parser/locals';
|
||||
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';
|
||||
|
||||
class _Context {
|
||||
constructor(public element: any, public componentElement: any, public instance: any,
|
||||
public context: any, public locals: any, public injector: any,
|
||||
public expression: any) {}
|
||||
}
|
||||
|
||||
export class AbstractChangeDetector implements ChangeDetector {
|
||||
lightDomChildren: List<any> = [];
|
||||
shadowDomChildren: List<any> = [];
|
||||
@ -14,7 +20,7 @@ export class AbstractChangeDetector implements ChangeDetector {
|
||||
mode: string = null;
|
||||
ref: ChangeDetectorRef;
|
||||
|
||||
constructor(public id: string) { this.ref = new ChangeDetectorRef(this); }
|
||||
constructor(public id: string, public dispatcher: any) { this.ref = new ChangeDetectorRef(this); }
|
||||
|
||||
addChild(cd: ChangeDetector): void {
|
||||
this.lightDomChildren.push(cd);
|
||||
@ -83,6 +89,9 @@ export class AbstractChangeDetector implements ChangeDetector {
|
||||
}
|
||||
|
||||
throwError(proto: ProtoRecord, exception: any, stack: any): void {
|
||||
throw new ChangeDetectionError(proto, exception, stack);
|
||||
var c = this.dispatcher.getDebugContext(proto.bindingRecord.elementIndex, proto.directiveIndex);
|
||||
var context = new _Context(c["element"], c["componentElement"], c["directive"], c["context"],
|
||||
c["locals"], c["injector"], proto.expressionAsString);
|
||||
throw new ChangeDetectionError(proto, exception, stack, context);
|
||||
}
|
||||
}
|
||||
}
|
@ -68,8 +68,7 @@ export class ChangeDetectorJITGenerator {
|
||||
var typeName = _sanitizeName(`ChangeDetector_${this.id}`);
|
||||
var classDefinition = `
|
||||
var ${typeName} = function ${typeName}(dispatcher, protos, directiveRecords) {
|
||||
${ABSTRACT_CHANGE_DETECTOR}.call(this, ${JSON.stringify(this.id)});
|
||||
${DISPATCHER_ACCESSOR} = dispatcher;
|
||||
${ABSTRACT_CHANGE_DETECTOR}.call(this, ${JSON.stringify(this.id)}, dispatcher);
|
||||
${PROTOS_ACCESSOR} = protos;
|
||||
${DIRECTIVES_ACCESSOR} = directiveRecords;
|
||||
${LOCALS_ACCESSOR} = null;
|
||||
|
@ -129,7 +129,7 @@ export class ChangeDetectionUtil {
|
||||
}
|
||||
|
||||
static throwOnChange(proto: ProtoRecord, change) {
|
||||
throw new ExpressionChangedAfterItHasBeenChecked(proto, change);
|
||||
throw new ExpressionChangedAfterItHasBeenChecked(proto, change, null);
|
||||
}
|
||||
|
||||
static throwDehydrated() { throw new DehydratedException(); }
|
||||
|
@ -20,9 +20,9 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
|
||||
alreadyChecked: boolean = false;
|
||||
private pipes: Pipes = null;
|
||||
|
||||
constructor(id: string, private changeControlStrategy: string, private dispatcher: any,
|
||||
constructor(id: string, private changeControlStrategy: string, dispatcher: any,
|
||||
private protos: List<ProtoRecord>, private directiveRecords: List<any>) {
|
||||
super(id);
|
||||
super(id, dispatcher);
|
||||
this.values = ListWrapper.createFixedSize(protos.length + 1);
|
||||
this.localPipes = ListWrapper.createFixedSize(protos.length + 1);
|
||||
this.prevContexts = ListWrapper.createFixedSize(protos.length + 1);
|
||||
|
@ -2,7 +2,7 @@ import {ProtoRecord} from './proto_record';
|
||||
import {BaseException} from "angular2/src/facade/lang";
|
||||
|
||||
export class ExpressionChangedAfterItHasBeenChecked extends BaseException {
|
||||
constructor(proto: ProtoRecord, change: any) {
|
||||
constructor(proto: ProtoRecord, change: any, context: any) {
|
||||
super(`Expression '${proto.expressionAsString}' has changed after it was checked. ` +
|
||||
`Previous value: '${change.previousValue}'. Current value: '${change.currentValue}'`);
|
||||
}
|
||||
@ -11,9 +11,9 @@ export class ExpressionChangedAfterItHasBeenChecked extends BaseException {
|
||||
export class ChangeDetectionError extends BaseException {
|
||||
location: string;
|
||||
|
||||
constructor(proto: ProtoRecord, originalException: any, originalStack: any) {
|
||||
super(`${originalException} in [${proto.expressionAsString}]`, originalException,
|
||||
originalStack);
|
||||
constructor(proto: ProtoRecord, originalException: any, originalStack: any, context: any) {
|
||||
super(`${originalException} in [${proto.expressionAsString}]`, originalException, originalStack,
|
||||
context);
|
||||
this.location = proto.expressionAsString;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user