feat(change detect): Throw on attempts to use dehydrated detector
- Modify change detectors to `throw` when attempting to detect changes on a dehydrated detector. - Modify `DynamicChagneDetector` to use `null` for the `context` of a dehydrated detector.
This commit is contained in:
parent
cd95e078fe
commit
b6e95bb96e
|
@ -19,6 +19,7 @@ export {Parser} from './src/change_detection/parser/parser';
|
||||||
export {Locals} from './src/change_detection/parser/locals';
|
export {Locals} from './src/change_detection/parser/locals';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
DehydratedException,
|
||||||
ExpressionChangedAfterItHasBeenChecked,
|
ExpressionChangedAfterItHasBeenChecked,
|
||||||
ChangeDetectionError
|
ChangeDetectionError
|
||||||
} from './src/change_detection/exceptions';
|
} from './src/change_detection/exceptions';
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
library change_detectoin.change_detection_jit_generator;
|
library change_detectoin.change_detection_jit_generator;
|
||||||
|
|
||||||
|
/// Placeholder JIT generator for Dart.
|
||||||
|
/// Dart does not support `eval`, so JIT generation is not an option. Instead,
|
||||||
|
/// the Dart transformer pre-generates these Change Detector classes and
|
||||||
|
/// registers them with the system. See `PreGeneratedChangeDetection`,
|
||||||
|
/// `PregenProtoChangeDetector`, and
|
||||||
|
/// `src/transform/template_compiler/change_detector_codegen.dart` for details.
|
||||||
class ChangeDetectorJITGenerator {
|
class ChangeDetectorJITGenerator {
|
||||||
ChangeDetectorJITGenerator(typeName, strategy, records, directiveMementos) {}
|
ChangeDetectorJITGenerator(typeName, strategy, records, directiveMementos) {}
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,9 @@ export class ChangeDetectorJITGenerator {
|
||||||
${this.typeName}.prototype = Object.create(${ABSTRACT_CHANGE_DETECTOR}.prototype);
|
${this.typeName}.prototype = Object.create(${ABSTRACT_CHANGE_DETECTOR}.prototype);
|
||||||
|
|
||||||
${this.typeName}.prototype.detectChangesInRecords = function(throwOnChange) {
|
${this.typeName}.prototype.detectChangesInRecords = function(throwOnChange) {
|
||||||
|
if (!this.hydrated()) {
|
||||||
|
${UTIL}.throwDehydrated();
|
||||||
|
}
|
||||||
${this._genLocalDefinitions()}
|
${this._genLocalDefinitions()}
|
||||||
${this._genChangeDefinitions()}
|
${this._genChangeDefinitions()}
|
||||||
var ${IS_CHANGED_LOCAL} = false;
|
var ${IS_CHANGED_LOCAL} = false;
|
||||||
|
@ -131,7 +134,7 @@ export class ChangeDetectorJITGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
${this.typeName}.prototype.hydrated = function() {
|
${this.typeName}.prototype.hydrated = function() {
|
||||||
return Boolean(${CONTEXT_ACCESSOR});
|
return ${CONTEXT_ACCESSOR} !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return function(dispatcher, pipeRegistry) {
|
return function(dispatcher, pipeRegistry) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {isPresent, isBlank, BaseException, Type} from 'angular2/src/facade/lang';
|
import {isPresent, isBlank, BaseException, Type} from 'angular2/src/facade/lang';
|
||||||
import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {ProtoRecord} from './proto_record';
|
import {ProtoRecord} from './proto_record';
|
||||||
import {ExpressionChangedAfterItHasBeenChecked} from './exceptions';
|
import {DehydratedException, ExpressionChangedAfterItHasBeenChecked} from './exceptions';
|
||||||
import {WrappedValue} from './pipes/pipe';
|
import {WrappedValue} from './pipes/pipe';
|
||||||
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';
|
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';
|
||||||
|
|
||||||
|
@ -127,6 +127,8 @@ export class ChangeDetectionUtil {
|
||||||
throw new ExpressionChangedAfterItHasBeenChecked(proto, change);
|
throw new ExpressionChangedAfterItHasBeenChecked(proto, change);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static throwDehydrated() { throw new DehydratedException(); }
|
||||||
|
|
||||||
static changeDetectionMode(strategy: string) {
|
static changeDetectionMode(strategy: string) {
|
||||||
return strategy == ON_PUSH ? CHECK_ONCE : CHECK_ALWAYS;
|
return strategy == ON_PUSH ? CHECK_ONCE : CHECK_ALWAYS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,8 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
|
||||||
this.prevContexts = ListWrapper.createFixedSize(protos.length + 1);
|
this.prevContexts = ListWrapper.createFixedSize(protos.length + 1);
|
||||||
this.changes = ListWrapper.createFixedSize(protos.length + 1);
|
this.changes = ListWrapper.createFixedSize(protos.length + 1);
|
||||||
|
|
||||||
ListWrapper.fill(this.values, uninitialized);
|
this.values[0] = null;
|
||||||
|
ListWrapper.fill(this.values, uninitialized, 1);
|
||||||
ListWrapper.fill(this.pipes, null);
|
ListWrapper.fill(this.pipes, null);
|
||||||
ListWrapper.fill(this.prevContexts, uninitialized);
|
ListWrapper.fill(this.prevContexts, uninitialized);
|
||||||
ListWrapper.fill(this.changes, false);
|
ListWrapper.fill(this.changes, false);
|
||||||
|
@ -60,7 +61,8 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
|
||||||
|
|
||||||
dehydrate() {
|
dehydrate() {
|
||||||
this._destroyPipes();
|
this._destroyPipes();
|
||||||
ListWrapper.fill(this.values, uninitialized);
|
this.values[0] = null;
|
||||||
|
ListWrapper.fill(this.values, uninitialized, 1);
|
||||||
ListWrapper.fill(this.changes, false);
|
ListWrapper.fill(this.changes, false);
|
||||||
ListWrapper.fill(this.pipes, null);
|
ListWrapper.fill(this.pipes, null);
|
||||||
ListWrapper.fill(this.prevContexts, uninitialized);
|
ListWrapper.fill(this.prevContexts, uninitialized);
|
||||||
|
@ -75,9 +77,12 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hydrated(): boolean { return this.values[0] !== uninitialized; }
|
hydrated(): boolean { return this.values[0] !== null; }
|
||||||
|
|
||||||
detectChangesInRecords(throwOnChange: boolean) {
|
detectChangesInRecords(throwOnChange: boolean) {
|
||||||
|
if (!this.hydrated()) {
|
||||||
|
ChangeDetectionUtil.throwDehydrated();
|
||||||
|
}
|
||||||
var protos: List<ProtoRecord> = this.protos;
|
var protos: List<ProtoRecord> = this.protos;
|
||||||
|
|
||||||
var changes = null;
|
var changes = null;
|
||||||
|
|
|
@ -27,4 +27,8 @@ export class ChangeDetectionError extends BaseException {
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(): string { return this.message; }
|
toString(): string { return this.message; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class DehydratedException extends BaseException {
|
||||||
|
constructor() { super('Attempt to detect changes on a dehydrated detector.'); }
|
||||||
|
}
|
||||||
|
|
|
@ -113,6 +113,9 @@ class _CodegenState {
|
||||||
this.$_DIRECTIVES_ACCESSOR) : super();
|
this.$_DIRECTIVES_ACCESSOR) : super();
|
||||||
|
|
||||||
void detectChangesInRecords(throwOnChange) {
|
void detectChangesInRecords(throwOnChange) {
|
||||||
|
if (!hydrated()) {
|
||||||
|
$_UTIL.throwDehydrated();
|
||||||
|
}
|
||||||
${_genLocalDefinitions()}
|
${_genLocalDefinitions()}
|
||||||
${_genChangeDefinitons()}
|
${_genChangeDefinitons()}
|
||||||
var $_IS_CHANGED_LOCAL = false;
|
var $_IS_CHANGED_LOCAL = false;
|
||||||
|
@ -145,7 +148,7 @@ class _CodegenState {
|
||||||
$_LOCALS_ACCESSOR = null;
|
$_LOCALS_ACCESSOR = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
hydrated() => $_CONTEXT_ACCESSOR == null;
|
hydrated() => $_CONTEXT_ACCESSOR != null;
|
||||||
|
|
||||||
static $_GEN_PREFIX.ProtoChangeDetector
|
static $_GEN_PREFIX.ProtoChangeDetector
|
||||||
$PROTO_CHANGE_DETECTOR_FACTORY_METHOD(
|
$PROTO_CHANGE_DETECTOR_FACTORY_METHOD(
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
} from 'angular2/test_lib';
|
} from 'angular2/test_lib';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
CONST_EXPR,
|
||||||
isPresent,
|
isPresent,
|
||||||
isBlank,
|
isBlank,
|
||||||
isJsObject,
|
isJsObject,
|
||||||
|
@ -21,6 +22,7 @@ import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/faca
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ChangeDispatcher,
|
ChangeDispatcher,
|
||||||
|
DehydratedException,
|
||||||
DynamicChangeDetector,
|
DynamicChangeDetector,
|
||||||
ChangeDetectionError,
|
ChangeDetectionError,
|
||||||
BindingRecord,
|
BindingRecord,
|
||||||
|
@ -47,6 +49,7 @@ import {
|
||||||
import {getDefinition} from './simple_watch_config';
|
import {getDefinition} from './simple_watch_config';
|
||||||
import {getFactoryById} from './generated/simple_watch_classes';
|
import {getFactoryById} from './generated/simple_watch_classes';
|
||||||
|
|
||||||
|
const _DEFAULT_CONTEXT = CONST_EXPR(new Object());
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
// These tests also run against pre-generated Dart Change Detectors. We will move tests up from
|
// These tests also run against pre-generated Dart Change Detectors. We will move tests up from
|
||||||
|
@ -72,7 +75,7 @@ export function main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _bindSimpleValue(expression: string, context = null) {
|
function _bindSimpleValue(expression: string, context = _DEFAULT_CONTEXT) {
|
||||||
var dispatcher = new TestDispatcher();
|
var dispatcher = new TestDispatcher();
|
||||||
var testDef = getDefinition(expression);
|
var testDef = getDefinition(expression);
|
||||||
var protoCd = _getProtoChangeDetector(testDef.cdDef);
|
var protoCd = _getProtoChangeDetector(testDef.cdDef);
|
||||||
|
@ -297,7 +300,7 @@ export function main() {
|
||||||
|
|
||||||
function dirs(directives: List<any>) { return new FakeDirectives(directives, []); }
|
function dirs(directives: List<any>) { return new FakeDirectives(directives, []); }
|
||||||
|
|
||||||
function createChangeDetector(propName: string, exp: string, context = null,
|
function createChangeDetector(propName: string, exp: string, context = _DEFAULT_CONTEXT,
|
||||||
registry = null) {
|
registry = null) {
|
||||||
var dispatcher = new TestDispatcher();
|
var dispatcher = new TestDispatcher();
|
||||||
|
|
||||||
|
@ -444,7 +447,7 @@ export function main() {
|
||||||
|
|
||||||
var cd = pcd.instantiate(dispatcher);
|
var cd = pcd.instantiate(dispatcher);
|
||||||
|
|
||||||
cd.hydrate(null, null, dirs([directive1]));
|
cd.hydrate(_DEFAULT_CONTEXT, null, dirs([directive1]));
|
||||||
|
|
||||||
cd.detectChanges();
|
cd.detectChanges();
|
||||||
|
|
||||||
|
@ -465,7 +468,7 @@ export function main() {
|
||||||
|
|
||||||
var cd = pcd.instantiate(dispatcher);
|
var cd = pcd.instantiate(dispatcher);
|
||||||
|
|
||||||
cd.hydrate(null, null, dirs([directive1, directive2]));
|
cd.hydrate(_DEFAULT_CONTEXT, null, dirs([directive1, directive2]));
|
||||||
|
|
||||||
cd.detectChanges();
|
cd.detectChanges();
|
||||||
|
|
||||||
|
@ -482,7 +485,7 @@ export function main() {
|
||||||
|
|
||||||
var cd = pcd.instantiate(dispatcher);
|
var cd = pcd.instantiate(dispatcher);
|
||||||
|
|
||||||
cd.hydrate(null, null, dirs([directive1]));
|
cd.hydrate(_DEFAULT_CONTEXT, null, dirs([directive1]));
|
||||||
|
|
||||||
cd.detectChanges();
|
cd.detectChanges();
|
||||||
|
|
||||||
|
@ -502,7 +505,7 @@ export function main() {
|
||||||
|
|
||||||
var cd = pcd.instantiate(dispatcher);
|
var cd = pcd.instantiate(dispatcher);
|
||||||
|
|
||||||
cd.hydrate(null, null, dirs([directive1]));
|
cd.hydrate(_DEFAULT_CONTEXT, null, dirs([directive1]));
|
||||||
|
|
||||||
cd.checkNoChanges();
|
cd.checkNoChanges();
|
||||||
|
|
||||||
|
@ -518,7 +521,7 @@ export function main() {
|
||||||
|
|
||||||
var cd = pcd.instantiate(dispatcher);
|
var cd = pcd.instantiate(dispatcher);
|
||||||
|
|
||||||
cd.hydrate(null, null, dirs([directive1]));
|
cd.hydrate(_DEFAULT_CONTEXT, null, dirs([directive1]));
|
||||||
|
|
||||||
cd.detectChanges();
|
cd.detectChanges();
|
||||||
|
|
||||||
|
@ -538,7 +541,7 @@ export function main() {
|
||||||
|
|
||||||
var cd = pcd.instantiate(dispatcher);
|
var cd = pcd.instantiate(dispatcher);
|
||||||
|
|
||||||
cd.hydrate(null, null, dirs([directive1]));
|
cd.hydrate(_DEFAULT_CONTEXT, null, dirs([directive1]));
|
||||||
|
|
||||||
cd.checkNoChanges();
|
cd.checkNoChanges();
|
||||||
|
|
||||||
|
@ -551,7 +554,7 @@ export function main() {
|
||||||
var pcd = createProtoChangeDetector([], [], [dirRecord1, dirRecord2]);
|
var pcd = createProtoChangeDetector([], [], [dirRecord1, dirRecord2]);
|
||||||
|
|
||||||
var cd = pcd.instantiate(dispatcher);
|
var cd = pcd.instantiate(dispatcher);
|
||||||
cd.hydrate(null, null, dirs([directive1, directive2]));
|
cd.hydrate(_DEFAULT_CONTEXT, null, dirs([directive1, directive2]));
|
||||||
|
|
||||||
cd.detectChanges();
|
cd.detectChanges();
|
||||||
|
|
||||||
|
@ -582,7 +585,7 @@ export function main() {
|
||||||
|
|
||||||
var cd = pcd.instantiate(dispatcher);
|
var cd = pcd.instantiate(dispatcher);
|
||||||
|
|
||||||
cd.hydrate(null, null, dirs([directive1]));
|
cd.hydrate(_DEFAULT_CONTEXT, null, dirs([directive1]));
|
||||||
|
|
||||||
cd.detectChanges();
|
cd.detectChanges();
|
||||||
|
|
||||||
|
@ -599,7 +602,7 @@ export function main() {
|
||||||
td1 = new TestDirective(() => ListWrapper.push(onChangesDoneCalls, td1));
|
td1 = new TestDirective(() => ListWrapper.push(onChangesDoneCalls, td1));
|
||||||
var td2;
|
var td2;
|
||||||
td2 = new TestDirective(() => ListWrapper.push(onChangesDoneCalls, td2));
|
td2 = new TestDirective(() => ListWrapper.push(onChangesDoneCalls, td2));
|
||||||
cd.hydrate(null, null, dirs([td1, td2]));
|
cd.hydrate(_DEFAULT_CONTEXT, null, dirs([td1, td2]));
|
||||||
|
|
||||||
cd.detectChanges();
|
cd.detectChanges();
|
||||||
|
|
||||||
|
@ -620,8 +623,8 @@ export function main() {
|
||||||
var parentDirective =
|
var parentDirective =
|
||||||
new TestDirective(() => { expect(directiveInShadowDom.a).toBe(null); });
|
new TestDirective(() => { expect(directiveInShadowDom.a).toBe(null); });
|
||||||
|
|
||||||
parent.hydrate(null, null, dirs([parentDirective]));
|
parent.hydrate(_DEFAULT_CONTEXT, null, dirs([parentDirective]));
|
||||||
child.hydrate(null, null, dirs([directiveInShadowDom]));
|
child.hydrate(_DEFAULT_CONTEXT, null, dirs([directiveInShadowDom]));
|
||||||
|
|
||||||
parent.detectChanges();
|
parent.detectChanges();
|
||||||
});
|
});
|
||||||
|
@ -641,7 +644,7 @@ export function main() {
|
||||||
[BindingRecord.createForHostProperty(index, ast("a"), "prop")], null,
|
[BindingRecord.createForHostProperty(index, ast("a"), "prop")], null,
|
||||||
[dirRecord]);
|
[dirRecord]);
|
||||||
var cd = pcd.instantiate(dispatcher);
|
var cd = pcd.instantiate(dispatcher);
|
||||||
cd.hydrate(null, null, dirs([directive]));
|
cd.hydrate(_DEFAULT_CONTEXT, null, dirs([directive]));
|
||||||
|
|
||||||
cd.detectChanges();
|
cd.detectChanges();
|
||||||
|
|
||||||
|
@ -688,7 +691,7 @@ export function main() {
|
||||||
var cd = pcd.instantiate(
|
var cd = pcd.instantiate(
|
||||||
new TestDispatcher(),
|
new TestDispatcher(),
|
||||||
[BindingRecord.createForElement(ast("invalidProp"), 0, "a")], null, []);
|
[BindingRecord.createForElement(ast("invalidProp"), 0, "a")], null, []);
|
||||||
cd.hydrate(null, null);
|
cd.hydrate(_DEFAULT_CONTEXT, null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cd.detectChanges();
|
cd.detectChanges();
|
||||||
|
@ -747,7 +750,7 @@ export function main() {
|
||||||
|
|
||||||
expect(cd.mode).toEqual(null);
|
expect(cd.mode).toEqual(null);
|
||||||
|
|
||||||
cd.hydrate(null, null, null);
|
cd.hydrate(_DEFAULT_CONTEXT, null, null);
|
||||||
|
|
||||||
expect(cd.mode).toEqual(CHECK_ALWAYS);
|
expect(cd.mode).toEqual(CHECK_ALWAYS);
|
||||||
});
|
});
|
||||||
|
@ -755,7 +758,7 @@ export function main() {
|
||||||
it("should set the mode to CHECK_ONCE when the push change detection is used", () => {
|
it("should set the mode to CHECK_ONCE when the push change detection is used", () => {
|
||||||
var proto = createProtoChangeDetector([], [], [], null, ON_PUSH);
|
var proto = createProtoChangeDetector([], [], [], null, ON_PUSH);
|
||||||
var cd = proto.instantiate(null);
|
var cd = proto.instantiate(null);
|
||||||
cd.hydrate(null, null, null);
|
cd.hydrate(_DEFAULT_CONTEXT, null, null);
|
||||||
|
|
||||||
expect(cd.mode).toEqual(CHECK_ONCE);
|
expect(cd.mode).toEqual(CHECK_ONCE);
|
||||||
});
|
});
|
||||||
|
@ -765,6 +768,7 @@ export function main() {
|
||||||
var cd = c["changeDetector"];
|
var cd = c["changeDetector"];
|
||||||
var dispatcher = c["dispatcher"];
|
var dispatcher = c["dispatcher"];
|
||||||
|
|
||||||
|
cd.hydrate(_DEFAULT_CONTEXT, null, null);
|
||||||
cd.mode = DETACHED;
|
cd.mode = DETACHED;
|
||||||
cd.detectChanges();
|
cd.detectChanges();
|
||||||
|
|
||||||
|
@ -776,6 +780,7 @@ export function main() {
|
||||||
var cd = c["changeDetector"];
|
var cd = c["changeDetector"];
|
||||||
var dispatcher = c["dispatcher"];
|
var dispatcher = c["dispatcher"];
|
||||||
|
|
||||||
|
cd.hydrate(_DEFAULT_CONTEXT, null, null);
|
||||||
cd.mode = CHECKED;
|
cd.mode = CHECKED;
|
||||||
cd.detectChanges();
|
cd.detectChanges();
|
||||||
|
|
||||||
|
@ -784,6 +789,7 @@ export function main() {
|
||||||
|
|
||||||
it("should change CHECK_ONCE to CHECKED", () => {
|
it("should change CHECK_ONCE to CHECKED", () => {
|
||||||
var cd = createProtoChangeDetector([]).instantiate(null);
|
var cd = createProtoChangeDetector([]).instantiate(null);
|
||||||
|
cd.hydrate(_DEFAULT_CONTEXT, null, null);
|
||||||
cd.mode = CHECK_ONCE;
|
cd.mode = CHECK_ONCE;
|
||||||
|
|
||||||
cd.detectChanges();
|
cd.detectChanges();
|
||||||
|
@ -793,6 +799,7 @@ export function main() {
|
||||||
|
|
||||||
it("should not change the CHECK_ALWAYS", () => {
|
it("should not change the CHECK_ALWAYS", () => {
|
||||||
var cd = createProtoChangeDetector([]).instantiate(null);
|
var cd = createProtoChangeDetector([]).instantiate(null);
|
||||||
|
cd.hydrate(_DEFAULT_CONTEXT, null, null);
|
||||||
cd.mode = CHECK_ALWAYS;
|
cd.mode = CHECK_ALWAYS;
|
||||||
|
|
||||||
cd.detectChanges();
|
cd.detectChanges();
|
||||||
|
@ -809,7 +816,7 @@ export function main() {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
var proto = createProtoChangeDetector([], [], [], null, ON_PUSH);
|
var proto = createProtoChangeDetector([], [], [], null, ON_PUSH);
|
||||||
checkedDetector = proto.instantiate(null);
|
checkedDetector = proto.instantiate(null);
|
||||||
checkedDetector.hydrate(null, null, null);
|
checkedDetector.hydrate(_DEFAULT_CONTEXT, null, null);
|
||||||
checkedDetector.mode = CHECKED;
|
checkedDetector.mode = CHECKED;
|
||||||
|
|
||||||
// this directive is a component with ON_PUSH change detection
|
// this directive is a component with ON_PUSH change detection
|
||||||
|
@ -829,7 +836,7 @@ export function main() {
|
||||||
[dirRecordWithOnPush]);
|
[dirRecordWithOnPush]);
|
||||||
|
|
||||||
var cd = proto.instantiate(null);
|
var cd = proto.instantiate(null);
|
||||||
cd.hydrate(null, null, directives);
|
cd.hydrate(_DEFAULT_CONTEXT, null, directives);
|
||||||
|
|
||||||
expect(checkedDetector.mode).toEqual(CHECKED);
|
expect(checkedDetector.mode).toEqual(CHECKED);
|
||||||
|
|
||||||
|
@ -898,6 +905,21 @@ export function main() {
|
||||||
|
|
||||||
expect(pipe.destroyCalled).toBe(true);
|
expect(pipe.destroyCalled).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should throw when detectChanges is called on a dehydrated detector", () => {
|
||||||
|
var context = new Person('Bob');
|
||||||
|
var c = createChangeDetector("propName", "name", context);
|
||||||
|
var cd = c["changeDetector"];
|
||||||
|
var log = c["dispatcher"].log;
|
||||||
|
|
||||||
|
cd.detectChanges();
|
||||||
|
expect(log).toEqual(["propName=Bob"]);
|
||||||
|
|
||||||
|
cd.dehydrate();
|
||||||
|
var dehydratedException = new DehydratedException();
|
||||||
|
expect(() => {cd.detectChanges()}).toThrowError(dehydratedException.toString());
|
||||||
|
expect(log).toEqual(["propName=Bob"]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("pipes", () => {
|
describe("pipes", () => {
|
||||||
|
@ -1098,13 +1120,8 @@ class TestDirective {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Person {
|
class Person {
|
||||||
name: string;
|
|
||||||
age: number;
|
age: number;
|
||||||
address: Address;
|
constructor(public name: string, public address: Address = null) {}
|
||||||
constructor(name: string, address: Address = null) {
|
|
||||||
this.name = name;
|
|
||||||
this.address = address;
|
|
||||||
}
|
|
||||||
|
|
||||||
sayHi(m) { return `Hi, ${m}`; }
|
sayHi(m) { return `Hi, ${m}`; }
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,9 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector {
|
||||||
: super();
|
: super();
|
||||||
|
|
||||||
void detectChangesInRecords(throwOnChange) {
|
void detectChangesInRecords(throwOnChange) {
|
||||||
|
if (!hydrated()) {
|
||||||
|
_gen.ChangeDetectionUtil.throwDehydrated();
|
||||||
|
}
|
||||||
var context = null;
|
var context = null;
|
||||||
var change_context = false;
|
var change_context = false;
|
||||||
var isChanged = false;
|
var isChanged = false;
|
||||||
|
@ -56,7 +59,7 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector {
|
||||||
_locals = null;
|
_locals = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
hydrated() => _context == null;
|
hydrated() => _context != null;
|
||||||
|
|
||||||
static _gen.ProtoChangeDetector newProtoChangeDetector(
|
static _gen.ProtoChangeDetector newProtoChangeDetector(
|
||||||
_gen.PipeRegistry registry, _gen.ChangeDetectorDefinition def) {
|
_gen.PipeRegistry registry, _gen.ChangeDetectorDefinition def) {
|
||||||
|
|
|
@ -280,6 +280,7 @@ function setUpChangeDetection(changeDetection: ChangeDetection, iterations, obje
|
||||||
new ChangeDetectorDefinition("proto", null, [], bindings, [directiveRecord]));
|
new ChangeDetectorDefinition("proto", null, [], bindings, [directiveRecord]));
|
||||||
|
|
||||||
var targetObj = new Obj();
|
var targetObj = new Obj();
|
||||||
|
parentCd.hydrate(object, null, new FakeDirectives(targetObj));
|
||||||
for (var i = 0; i < iterations; ++i) {
|
for (var i = 0; i < iterations; ++i) {
|
||||||
var cd = proto.instantiate(dispatcher);
|
var cd = proto.instantiate(dispatcher);
|
||||||
cd.hydrate(object, null, new FakeDirectives(targetObj));
|
cd.hydrate(object, null, new FakeDirectives(targetObj));
|
||||||
|
|
Loading…
Reference in New Issue