feat(core): drop ChangeDetectionStrategy.OnPushObserve

BREAKING CHANGE:

`OnPushObserve` was an experimental
feature for Dart and had
conceptual performance problems,
as setting up observables is slow.
Use `OnPush` instead.
This commit is contained in:
Tobias Bosch
2016-02-16 14:36:34 -08:00
committed by vsavkin
parent d900f5c075
commit f60fa14767
23 changed files with 14 additions and 1019 deletions

View File

@ -16,7 +16,6 @@ import {BindingTarget} from './binding_record';
import {Locals} from './parser/locals';
import {ChangeDetectionStrategy, ChangeDetectorState} from './constants';
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
import {isObservable} from './observable_facade';
import {ObservableWrapper} from 'angular2/src/facade/async';
var _scope_check: WtfScopeFn = wtfCreateScope(`ChangeDetector#check(ascii id, bool throwOnChange)`);
@ -42,10 +41,6 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
propertyBindingIndex: number;
outputSubscriptions: any[];
// This is an experimental feature. Works only in Dart.
subscriptions: any[];
streams: any[];
dispatcher: ChangeDispatcher;
@ -158,10 +153,6 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
this.mode = ChangeDetectionUtil.changeDetectionMode(this.strategy);
this.context = context;
if (this.strategy === ChangeDetectionStrategy.OnPushObserve) {
this.observeComponent(context);
}
this.locals = locals;
this.pipes = pipes;
this.hydrateDirectives(dispatcher);
@ -176,11 +167,6 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
dehydrate(): void {
this.dehydrateDirectives(true);
// This is an experimental feature. Works only in Dart.
if (this.strategy === ChangeDetectionStrategy.OnPushObserve) {
this._unsubsribeFromObservables();
}
this._unsubscribeFromOutputs();
this.dispatcher = null;
@ -248,19 +234,6 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
}
}
// This is an experimental feature. Works only in Dart.
private _unsubsribeFromObservables(): void {
if (isPresent(this.subscriptions)) {
for (var i = 0; i < this.subscriptions.length; ++i) {
var s = this.subscriptions[i];
if (isPresent(this.subscriptions[i])) {
s.cancel();
this.subscriptions[i] = null;
}
}
}
}
private _unsubscribeFromOutputs(): void {
if (isPresent(this.outputSubscriptions)) {
for (var i = 0; i < this.outputSubscriptions.length; ++i) {
@ -270,53 +243,6 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
}
}
// This is an experimental feature. Works only in Dart.
observeValue(value: any, index: number): any {
if (isObservable(value)) {
this._createArrayToStoreObservables();
if (isBlank(this.subscriptions[index])) {
this.streams[index] = value.changes;
this.subscriptions[index] = value.changes.listen((_) => this.ref.markForCheck());
} else if (this.streams[index] !== value.changes) {
this.subscriptions[index].cancel();
this.streams[index] = value.changes;
this.subscriptions[index] = value.changes.listen((_) => this.ref.markForCheck());
}
}
return value;
}
// This is an experimental feature. Works only in Dart.
observeDirective(value: any, index: number): any {
if (isObservable(value)) {
this._createArrayToStoreObservables();
var arrayIndex = this.numberOfPropertyProtoRecords + index + 2; // +1 is component
this.streams[arrayIndex] = value.changes;
this.subscriptions[arrayIndex] = value.changes.listen((_) => this.ref.markForCheck());
}
return value;
}
// This is an experimental feature. Works only in Dart.
observeComponent(value: any): any {
if (isObservable(value)) {
this._createArrayToStoreObservables();
var index = this.numberOfPropertyProtoRecords + 1;
this.streams[index] = value.changes;
this.subscriptions[index] = value.changes.listen((_) => this.ref.markForCheck());
}
return value;
}
private _createArrayToStoreObservables(): void {
if (isBlank(this.subscriptions)) {
this.subscriptions = ListWrapper.createFixedSize(this.numberOfPropertyProtoRecords +
this.directiveIndices.length + 2);
this.streams = ListWrapper.createFixedSize(this.numberOfPropertyProtoRecords +
this.directiveIndices.length + 2);
}
}
getDirectiveFor(directives: any, index: number): any {
return directives.getDirectiveFor(this.directiveIndices[index]);
}

View File

@ -57,9 +57,8 @@ export class ChangeDetectorJITGenerator {
this.directiveRecords = definition.directiveRecords;
this._names = new CodegenNameUtil(this.records, this.eventBindings, this.directiveRecords,
this.changeDetectionUtilVarName);
this._logic =
new CodegenLogicUtil(this._names, this.changeDetectionUtilVarName,
this.changeDetectorStateVarName, this.changeDetectionStrategy);
this._logic = new CodegenLogicUtil(this._names, this.changeDetectionUtilVarName,
this.changeDetectorStateVarName);
this.typeName = sanitizeName(`ChangeDetector_${this.id}`);
}

View File

@ -4,7 +4,6 @@ import {codify, combineGeneratedStrings, rawString} from './codegen_facade';
import {ProtoRecord, RecordType} from './proto_record';
import {BindingTarget} from './binding_record';
import {DirectiveRecord} from './directive_record';
import {ChangeDetectionStrategy} from './constants';
import {BaseException} from 'angular2/src/facade/exceptions';
/**
@ -12,8 +11,7 @@ import {BaseException} from 'angular2/src/facade/exceptions';
*/
export class CodegenLogicUtil {
constructor(private _names: CodegenNameUtil, private _utilName: string,
private _changeDetectorStateName: string,
private _changeDetection: ChangeDetectionStrategy) {}
private _changeDetectorStateName: string) {}
/**
* Generates a statement which updates the local variable representing `protoRec` with the current
@ -51,13 +49,12 @@ export class CodegenLogicUtil {
break;
case RecordType.PropertyRead:
rhs = this._observe(`${context}.${protoRec.name}`, protoRec);
rhs = `${context}.${protoRec.name}`;
break;
case RecordType.SafeProperty:
var read = this._observe(`${context}.${protoRec.name}`, protoRec);
rhs =
`${this._utilName}.isValueBlank(${context}) ? null : ${this._observe(read, protoRec)}`;
var read = `${context}.${protoRec.name}`;
rhs = `${this._utilName}.isValueBlank(${context}) ? null : ${read}`;
break;
case RecordType.PropertyWrite:
@ -65,17 +62,16 @@ export class CodegenLogicUtil {
break;
case RecordType.Local:
rhs = this._observe(`${localsAccessor}.get(${rawString(protoRec.name)})`, protoRec);
rhs = `${localsAccessor}.get(${rawString(protoRec.name)})`;
break;
case RecordType.InvokeMethod:
rhs = this._observe(`${context}.${protoRec.name}(${argString})`, protoRec);
rhs = `${context}.${protoRec.name}(${argString})`;
break;
case RecordType.SafeMethodInvoke:
var invoke = `${context}.${protoRec.name}(${argString})`;
rhs =
`${this._utilName}.isValueBlank(${context}) ? null : ${this._observe(invoke, protoRec)}`;
rhs = `${this._utilName}.isValueBlank(${context}) ? null : ${invoke}`;
break;
case RecordType.InvokeClosure:
@ -95,7 +91,7 @@ export class CodegenLogicUtil {
break;
case RecordType.KeyedRead:
rhs = this._observe(`${context}[${getLocalName(protoRec.args[0])}]`, protoRec);
rhs = `${context}[${getLocalName(protoRec.args[0])}]`;
break;
case RecordType.KeyedWrite:
@ -112,16 +108,6 @@ export class CodegenLogicUtil {
return `${getLocalName(protoRec.selfIndex)} = ${rhs};`;
}
/** @internal */
_observe(exp: string, rec: ProtoRecord): string {
// This is an experimental feature. Works only in Dart.
if (this._changeDetection === ChangeDetectionStrategy.OnPushObserve) {
return `this.observeValue(${exp}, ${rec.selfIndex})`;
} else {
return exp;
}
}
genPropertyBindingTargets(propertyBindingTargets: BindingTarget[],
genDebugInfo: boolean): string {
var bs = propertyBindingTargets.map(b => {
@ -202,15 +188,7 @@ export class CodegenLogicUtil {
}
}
private _genReadDirective(index: number) {
var directiveExpr = `this.getDirectiveFor(directives, ${index})`;
// This is an experimental feature. Works only in Dart.
if (this._changeDetection === ChangeDetectionStrategy.OnPushObserve) {
return `this.observeDirective(${directiveExpr}, ${index})`;
} else {
return directiveExpr;
}
}
private _genReadDirective(index: number) { return `this.getDirectiveFor(directives, ${index})`; }
genHydrateDetectors(directiveRecords: DirectiveRecord[]): string {
var res = [];

View File

@ -62,11 +62,6 @@ export enum ChangeDetectionStrategy {
* `Default` means that the change detector's mode will be set to `CheckAlways` during hydration.
*/
Default,
/**
* This is an experimental feature. Works only in Dart.
*/
OnPushObserve
}
/**
@ -78,8 +73,7 @@ export var CHANGE_DETECTION_STRATEGY_VALUES = [
ChangeDetectionStrategy.CheckAlways,
ChangeDetectionStrategy.Detached,
ChangeDetectionStrategy.OnPush,
ChangeDetectionStrategy.Default,
ChangeDetectionStrategy.OnPushObserve
ChangeDetectionStrategy.Default
];
/**

View File

@ -110,12 +110,6 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
this.values[0] = this.context;
this.dispatcher = dispatcher;
if (this.strategy === ChangeDetectionStrategy.OnPushObserve) {
for (var i = 0; i < this.directiveIndices.length; ++i) {
var index = this.directiveIndices[i];
super.observeDirective(this._getDirectiveFor(index), i);
}
}
this.outputSubscriptions = [];
for (var i = 0; i < this._directiveRecords.length; ++i) {
var r = this._directiveRecords[i];
@ -300,9 +294,6 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
}
var currValue = this._calculateCurrValue(proto, values, locals);
if (this.strategy === ChangeDetectionStrategy.OnPushObserve) {
super.observeValue(currValue, proto.selfIndex);
}
if (proto.shouldBeChecked()) {
var prevValue = this._readSelf(proto, values);

View File

@ -1,5 +0,0 @@
library change_detection.observable_facade;
import 'package:observe/observe.dart';
bool isObservable(value) => value is Observable;

View File

@ -1,3 +0,0 @@
export function isObservable(value: any): boolean {
return false;
}