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:
@ -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]);
|
||||
}
|
||||
|
@ -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}`);
|
||||
}
|
||||
|
||||
|
@ -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 = [];
|
||||
|
@ -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
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
@ -1,5 +0,0 @@
|
||||
library change_detection.observable_facade;
|
||||
|
||||
import 'package:observe/observe.dart';
|
||||
|
||||
bool isObservable(value) => value is Observable;
|
@ -1,3 +0,0 @@
|
||||
export function isObservable(value: any): boolean {
|
||||
return false;
|
||||
}
|
Reference in New Issue
Block a user