fix(change_detection): throw ChangeDetectionError in JIT mode
This commit is contained in:
@ -2,6 +2,8 @@ import {isPresent} from 'angular2/src/facade/lang';
|
||||
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {ChangeDetectorRef} from './change_detector_ref';
|
||||
import {ChangeDetector} from './interfaces';
|
||||
import {ChangeDetectionError} from './exceptions';
|
||||
import {ProtoRecord} from './proto_record';
|
||||
import {Locals} from './parser/locals';
|
||||
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';
|
||||
|
||||
@ -79,4 +81,8 @@ export class AbstractChangeDetector implements ChangeDetector {
|
||||
c = c.parent;
|
||||
}
|
||||
}
|
||||
|
||||
throwError(proto: ProtoRecord, exception: any, stack: any): void {
|
||||
throw new ChangeDetectionError(proto, exception, stack);
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ var IS_CHANGED_LOCAL = "isChanged";
|
||||
var CHANGES_LOCAL = "changes";
|
||||
var LOCALS_ACCESSOR = "this.locals";
|
||||
var MODE_ACCESSOR = "this.mode";
|
||||
var CURRENT_PROTO = "currentProto";
|
||||
var CURRENT_PROTO = "this.currentProto";
|
||||
var ALREADY_CHECKED_ACCESSOR = "this.alreadyChecked";
|
||||
|
||||
|
||||
@ -74,6 +74,7 @@ export class ChangeDetectorJITGenerator {
|
||||
${PROTOS_ACCESSOR} = protos;
|
||||
${DIRECTIVES_ACCESSOR} = directiveRecords;
|
||||
${LOCALS_ACCESSOR} = null;
|
||||
${CURRENT_PROTO} = null;
|
||||
${ALREADY_CHECKED_ACCESSOR} = false;
|
||||
${this._genFieldDefinitions()}
|
||||
}
|
||||
@ -84,19 +85,28 @@ export class ChangeDetectorJITGenerator {
|
||||
if (!this.hydrated()) {
|
||||
${UTIL}.throwDehydrated();
|
||||
}
|
||||
try {
|
||||
this.__detectChangesInRecords(throwOnChange);
|
||||
} catch (e) {
|
||||
this.throwError(${CURRENT_PROTO}, e, e.stack);
|
||||
}
|
||||
}
|
||||
|
||||
${typeName}.prototype.__detectChangesInRecords = function(throwOnChange) {
|
||||
${CURRENT_PROTO} = null;
|
||||
|
||||
${this._genLocalDefinitions()}
|
||||
${this._genChangeDefinitions()}
|
||||
var ${IS_CHANGED_LOCAL} = false;
|
||||
var ${CURRENT_PROTO};
|
||||
var ${CHANGES_LOCAL} = null;
|
||||
|
||||
|
||||
context = ${CONTEXT_ACCESSOR};
|
||||
|
||||
|
||||
${this.records.map((r) => this._genRecord(r)).join("\n")}
|
||||
|
||||
|
||||
${ALREADY_CHECKED_ACCESSOR} = true;
|
||||
}
|
||||
|
||||
|
||||
${typeName}.prototype.callOnAllChangesDone = function() {
|
||||
${this._genCallOnAllChangesDoneBody()}
|
||||
}
|
||||
|
@ -10,8 +10,6 @@ import {ChangeDetectionUtil, SimpleChange, uninitialized} from './change_detecti
|
||||
|
||||
import {ProtoRecord, RecordType} from './proto_record';
|
||||
|
||||
import {ExpressionChangedAfterItHasBeenChecked, ChangeDetectionError} from './exceptions';
|
||||
|
||||
export class DynamicChangeDetector extends AbstractChangeDetector {
|
||||
locals: Locals = null;
|
||||
values: List<any>;
|
||||
@ -149,7 +147,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
|
||||
return this._referenceCheck(proto, throwOnChange);
|
||||
}
|
||||
} catch (e) {
|
||||
throw new ChangeDetectionError(proto, e);
|
||||
this.throwError(proto, e, e.stack);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,29 +2,20 @@ 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}'`;
|
||||
super(`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;
|
||||
location: string;
|
||||
|
||||
constructor(proto: ProtoRecord, public originalException: any) {
|
||||
super();
|
||||
constructor(proto: ProtoRecord, originalException: any, originalStack: any) {
|
||||
super(`${originalException} in [${proto.expressionAsString}]`, originalException,
|
||||
originalStack);
|
||||
this.location = proto.expressionAsString;
|
||||
this.message = `${this.originalException} in [${this.location}]`;
|
||||
}
|
||||
|
||||
toString(): string { return this.message; }
|
||||
}
|
||||
|
||||
export class DehydratedException extends BaseException {
|
||||
|
@ -131,6 +131,7 @@ class _CodegenState {
|
||||
$_DIRECTIVES_ACCESSOR;
|
||||
dynamic $_LOCALS_ACCESSOR = null;
|
||||
dynamic $_ALREADY_CHECKED_ACCESSOR = false;
|
||||
dynamic $_CURRENT_PROTO = null;
|
||||
${_allFields().map((f) {
|
||||
if (f == _CONTEXT_ACCESSOR) {
|
||||
return '$_contextTypeName $f = null;';
|
||||
@ -148,10 +149,18 @@ class _CodegenState {
|
||||
if (!hydrated()) {
|
||||
$_UTIL.throwDehydrated();
|
||||
}
|
||||
try {
|
||||
this.__detectChangesInRecords(throwOnChange);
|
||||
} catch (e, s) {
|
||||
this.throwError($_CURRENT_PROTO, e, s);
|
||||
}
|
||||
}
|
||||
|
||||
void __detectChangesInRecords(throwOnChange) {
|
||||
${_genLocalDefinitions()}
|
||||
${_genChangeDefinitons()}
|
||||
var $_IS_CHANGED_LOCAL = false;
|
||||
var $_CURRENT_PROTO;
|
||||
$_CURRENT_PROTO = null;
|
||||
var $_CHANGES_LOCAL = null;
|
||||
|
||||
context = $_CONTEXT_ACCESSOR;
|
||||
@ -159,7 +168,7 @@ class _CodegenState {
|
||||
|
||||
$_ALREADY_CHECKED_ACCESSOR = true;
|
||||
}
|
||||
|
||||
|
||||
void callOnAllChangesDone() {
|
||||
${_getCallOnAllChangesDoneBody()}
|
||||
}
|
||||
|
Reference in New Issue
Block a user