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:
Tim Blasi
2015-06-05 17:33:51 -07:00
parent cd95e078fe
commit b6e95bb96e
10 changed files with 78 additions and 33 deletions

View File

@ -1,5 +1,11 @@
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 {
ChangeDetectorJITGenerator(typeName, strategy, records, directiveMementos) {}

View File

@ -98,6 +98,9 @@ export class ChangeDetectorJITGenerator {
${this.typeName}.prototype = Object.create(${ABSTRACT_CHANGE_DETECTOR}.prototype);
${this.typeName}.prototype.detectChangesInRecords = function(throwOnChange) {
if (!this.hydrated()) {
${UTIL}.throwDehydrated();
}
${this._genLocalDefinitions()}
${this._genChangeDefinitions()}
var ${IS_CHANGED_LOCAL} = false;
@ -131,7 +134,7 @@ export class ChangeDetectorJITGenerator {
}
${this.typeName}.prototype.hydrated = function() {
return Boolean(${CONTEXT_ACCESSOR});
return ${CONTEXT_ACCESSOR} !== null;
}
return function(dispatcher, pipeRegistry) {

View File

@ -1,7 +1,7 @@
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 {DehydratedException, ExpressionChangedAfterItHasBeenChecked} from './exceptions';
import {WrappedValue} from './pipes/pipe';
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';
@ -127,6 +127,8 @@ export class ChangeDetectionUtil {
throw new ExpressionChangedAfterItHasBeenChecked(proto, change);
}
static throwDehydrated() { throw new DehydratedException(); }
static changeDetectionMode(strategy: string) {
return strategy == ON_PUSH ? CHECK_ONCE : CHECK_ALWAYS;
}

View File

@ -44,7 +44,8 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
this.prevContexts = 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.prevContexts, uninitialized);
ListWrapper.fill(this.changes, false);
@ -60,7 +61,8 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
dehydrate() {
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.pipes, null);
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) {
if (!this.hydrated()) {
ChangeDetectionUtil.throwDehydrated();
}
var protos: List<ProtoRecord> = this.protos;
var changes = null;

View File

@ -27,4 +27,8 @@ export class ChangeDetectionError extends BaseException {
}
toString(): string { return this.message; }
}
}
export class DehydratedException extends BaseException {
constructor() { super('Attempt to detect changes on a dehydrated detector.'); }
}

View File

@ -113,6 +113,9 @@ class _CodegenState {
this.$_DIRECTIVES_ACCESSOR) : super();
void detectChangesInRecords(throwOnChange) {
if (!hydrated()) {
$_UTIL.throwDehydrated();
}
${_genLocalDefinitions()}
${_genChangeDefinitons()}
var $_IS_CHANGED_LOCAL = false;
@ -145,7 +148,7 @@ class _CodegenState {
$_LOCALS_ACCESSOR = null;
}
hydrated() => $_CONTEXT_ACCESSOR == null;
hydrated() => $_CONTEXT_ACCESSOR != null;
static $_GEN_PREFIX.ProtoChangeDetector
$PROTO_CHANGE_DETECTOR_FACTORY_METHOD(