refactor(change_detection): introduce enum ChangeDetectionStrategy

BREAKING CHANGE

Closes #2497

- change detection strategy type changes from string to ChangeDetectionStrategy
- CHECK_ONCE => ChangeDetectionStrategy.CheckOnce
- CHECKED => ChangeDetectionStrategy.Checked
- CHECK_ALWAYS => ChangeDetectionStrategy.CheckAlways
- DETACHED => ChangeDetectionStrategy.Detached
- ON_PUSH => ChangeDetectionStrategy.OnPush
- DEFAULT => ChangeDetectionStrategy.Default
- ON_PUSH_OBSERVE => ChangeDetectionStrategy.OnPushObserve
This commit is contained in:
Misko Hevery
2015-08-26 11:44:59 -07:00
parent e41d7451bf
commit 69926dd002
35 changed files with 388 additions and 365 deletions

View File

@ -5,12 +5,7 @@
*/ */
export { export {
CHECK_ONCE, ChangeDetectionStrategy,
CHECK_ALWAYS,
DETACHED,
CHECKED,
ON_PUSH,
DEFAULT,
ExpressionChangedAfterItHasBeenCheckedException, ExpressionChangedAfterItHasBeenCheckedException,
ChangeDetectionError, ChangeDetectionError,

View File

@ -12,10 +12,9 @@ import {
} from './exceptions'; } from './exceptions';
import {BindingTarget} from './binding_record'; import {BindingTarget} from './binding_record';
import {Locals} from './parser/locals'; import {Locals} from './parser/locals';
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED} from './constants'; import {ChangeDetectionStrategy} from './constants';
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile'; import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
import {isObservable} from './observable_facade'; import {isObservable} from './observable_facade';
import {ON_PUSH_OBSERVE} from './constants';
var _scope_check: WtfScopeFn = wtfCreateScope(`ChangeDetector#check(ascii id, bool throwOnChange)`); var _scope_check: WtfScopeFn = wtfCreateScope(`ChangeDetector#check(ascii id, bool throwOnChange)`);
@ -36,7 +35,7 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
alreadyChecked: any = false; alreadyChecked: any = false;
context: T; context: T;
locals: Locals = null; locals: Locals = null;
mode: string = null; mode: ChangeDetectionStrategy = null;
pipes: Pipes = null; pipes: Pipes = null;
propertyBindingIndex: number; propertyBindingIndex: number;
@ -46,7 +45,7 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
constructor(public id: string, public dispatcher: ChangeDispatcher, constructor(public id: string, public dispatcher: ChangeDispatcher,
public numberOfPropertyProtoRecords: number, public bindingTargets: BindingTarget[], public numberOfPropertyProtoRecords: number, public bindingTargets: BindingTarget[],
public directiveIndices: DirectiveIndex[], public strategy: string) { public directiveIndices: DirectiveIndex[], public strategy: ChangeDetectionStrategy) {
this.ref = new ChangeDetectorRef(this); this.ref = new ChangeDetectorRef(this);
} }
@ -79,14 +78,16 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
checkNoChanges(): void { throw new BaseException("Not implemented"); } checkNoChanges(): void { throw new BaseException("Not implemented"); }
runDetectChanges(throwOnChange: boolean): void { runDetectChanges(throwOnChange: boolean): void {
if (StringWrapper.equals(this.mode, DETACHED) || StringWrapper.equals(this.mode, CHECKED)) if (this.mode === ChangeDetectionStrategy.Detached ||
this.mode === ChangeDetectionStrategy.Checked)
return; return;
var s = _scope_check(this.id, throwOnChange); var s = _scope_check(this.id, throwOnChange);
this.detectChangesInRecords(throwOnChange); this.detectChangesInRecords(throwOnChange);
this._detectChangesInLightDomChildren(throwOnChange); this._detectChangesInLightDomChildren(throwOnChange);
if (throwOnChange === false) this.callOnAllChangesDone(); if (throwOnChange === false) this.callOnAllChangesDone();
this._detectChangesInShadowDomChildren(throwOnChange); this._detectChangesInShadowDomChildren(throwOnChange);
if (StringWrapper.equals(this.mode, CHECK_ONCE)) this.mode = CHECKED; if (this.mode === ChangeDetectionStrategy.CheckOnce)
this.mode = ChangeDetectionStrategy.Checked;
wtfLeave(s); wtfLeave(s);
} }
@ -121,7 +122,7 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
this.mode = ChangeDetectionUtil.changeDetectionMode(this.strategy); this.mode = ChangeDetectionUtil.changeDetectionMode(this.strategy);
this.context = context; this.context = context;
if (StringWrapper.equals(this.strategy, ON_PUSH_OBSERVE)) { if (this.strategy === ChangeDetectionStrategy.OnPushObserve) {
this.observeComponent(context); this.observeComponent(context);
} }
@ -140,7 +141,7 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
this.dehydrateDirectives(true); this.dehydrateDirectives(true);
// This is an experimental feature. Works only in Dart. // This is an experimental feature. Works only in Dart.
if (StringWrapper.equals(this.strategy, ON_PUSH_OBSERVE)) { if (this.strategy === ChangeDetectionStrategy.OnPushObserve) {
this._unsubsribeFromObservables(); this._unsubsribeFromObservables();
} }
@ -171,12 +172,12 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
} }
} }
markAsCheckOnce(): void { this.mode = CHECK_ONCE; } markAsCheckOnce(): void { this.mode = ChangeDetectionStrategy.CheckOnce; }
markPathToRootAsCheckOnce(): void { markPathToRootAsCheckOnce(): void {
var c: ChangeDetector = this; var c: ChangeDetector = this;
while (isPresent(c) && !StringWrapper.equals(c.mode, DETACHED)) { while (isPresent(c) && c.mode !== ChangeDetectionStrategy.Detached) {
if (StringWrapper.equals(c.mode, CHECKED)) c.mode = CHECK_ONCE; if (c.mode === ChangeDetectionStrategy.Checked) c.mode = ChangeDetectionStrategy.CheckOnce;
c = c.parent; c = c.parent;
} }
} }

View File

@ -48,7 +48,7 @@ export {
DebugContext, DebugContext,
ChangeDetectorGenConfig ChangeDetectorGenConfig
} from './interfaces'; } from './interfaces';
export {CHECK_ONCE, CHECK_ALWAYS, DETACHED, CHECKED, ON_PUSH, DEFAULT} from './constants'; export {ChangeDetectionStrategy} from './constants';
export {DynamicProtoChangeDetector} from './proto_change_detector'; export {DynamicProtoChangeDetector} from './proto_change_detector';
export {BindingRecord, BindingTarget} from './binding_record'; export {BindingRecord, BindingTarget} from './binding_record';
export {DirectiveIndex, DirectiveRecord} from './directive_record'; export {DirectiveIndex, DirectiveRecord} from './directive_record';

View File

@ -12,6 +12,8 @@ import {codify} from './codegen_facade';
import {EventBinding} from './event_binding'; import {EventBinding} from './event_binding';
import {BindingTarget} from './binding_record'; import {BindingTarget} from './binding_record';
import {ChangeDetectorGenConfig} from './interfaces'; import {ChangeDetectorGenConfig} from './interfaces';
import {ChangeDetectionStrategy} from './constants';
/** /**
@ -33,7 +35,7 @@ export class ChangeDetectorJITGenerator {
_names: CodegenNameUtil; _names: CodegenNameUtil;
_typeName: string; _typeName: string;
constructor(private id: string, private changeDetectionStrategy: string, constructor(private id: string, private changeDetectionStrategy: ChangeDetectionStrategy,
private records: List<ProtoRecord>, private propertyBindingTargets: BindingTarget[], private records: List<ProtoRecord>, private propertyBindingTargets: BindingTarget[],
private eventBindings: EventBinding[], private directiveRecords: List<any>, private eventBindings: EventBinding[], private directiveRecords: List<any>,
private genConfig: ChangeDetectorGenConfig) { private genConfig: ChangeDetectorGenConfig) {

View File

@ -8,13 +8,7 @@ import {
} from 'angular2/src/core/facade/lang'; } from 'angular2/src/core/facade/lang';
import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/core/facade/collection'; import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/core/facade/collection';
import {ProtoRecord} from './proto_record'; import {ProtoRecord} from './proto_record';
import { import {ChangeDetectionStrategy, isDefaultChangeDetectionStrategy} from './constants';
CHECK_ALWAYS,
CHECK_ONCE,
CHECKED,
DETACHED,
isDefaultChangeDetectionStrategy
} from './constants';
import {implementsOnDestroy} from './pipe_lifecycle_reflector'; import {implementsOnDestroy} from './pipe_lifecycle_reflector';
import {BindingTarget} from './binding_record'; import {BindingTarget} from './binding_record';
import {DirectiveIndex} from './directive_record'; import {DirectiveIndex} from './directive_record';
@ -180,8 +174,9 @@ export class ChangeDetectionUtil {
} }
} }
static changeDetectionMode(strategy: string): string { static changeDetectionMode(strategy: ChangeDetectionStrategy): ChangeDetectionStrategy {
return isDefaultChangeDetectionStrategy(strategy) ? CHECK_ALWAYS : CHECK_ONCE; return isDefaultChangeDetectionStrategy(strategy) ? ChangeDetectionStrategy.CheckAlways :
ChangeDetectionStrategy.CheckOnce;
} }
static simpleChange(previousValue: any, currentValue: any): SimpleChange { static simpleChange(previousValue: any, currentValue: any): SimpleChange {

View File

@ -1,5 +1,5 @@
import {ChangeDetector} from './interfaces'; import {ChangeDetector} from './interfaces';
import {CHECK_ONCE, DETACHED, CHECK_ALWAYS} from './constants'; import {ChangeDetectionStrategy} from './constants';
/** /**
* Controls change detection. * Controls change detection.
@ -14,7 +14,7 @@ export class ChangeDetectorRef {
constructor(private _cd: ChangeDetector) {} constructor(private _cd: ChangeDetector) {}
/** /**
* Request to check all ON_PUSH ancestors. * Request to check all OnPush ancestors.
*/ */
requestCheck(): void { this._cd.markPathToRootAsCheckOnce(); } requestCheck(): void { this._cd.markPathToRootAsCheckOnce(); }
@ -23,7 +23,7 @@ export class ChangeDetectorRef {
* *
* The detached change detector will not be checked until it is reattached. * The detached change detector will not be checked until it is reattached.
*/ */
detach(): void { this._cd.mode = DETACHED; } detach(): void { this._cd.mode = ChangeDetectionStrategy.Detached; }
/** /**
* Reattach the change detector to the change detector tree. * Reattach the change detector to the change detector tree.
@ -33,7 +33,7 @@ export class ChangeDetectorRef {
* next change detection run. * next change detection run.
*/ */
reattach(): void { reattach(): void {
this._cd.mode = CHECK_ALWAYS; this._cd.mode = ChangeDetectionStrategy.CheckAlways;
this.requestCheck(); this.requestCheck();
} }
} }

View File

@ -11,14 +11,14 @@ import {codify, combineGeneratedStrings, rawString} from './codegen_facade';
import {ProtoRecord, RecordType} from './proto_record'; import {ProtoRecord, RecordType} from './proto_record';
import {BindingTarget} from './binding_record'; import {BindingTarget} from './binding_record';
import {DirectiveRecord} from './directive_record'; import {DirectiveRecord} from './directive_record';
import {ON_PUSH_OBSERVE} from './constants'; import {ChangeDetectionStrategy} from './constants';
/** /**
* Class responsible for providing change detection logic for chagne detector classes. * Class responsible for providing change detection logic for chagne detector classes.
*/ */
export class CodegenLogicUtil { export class CodegenLogicUtil {
constructor(private _names: CodegenNameUtil, private _utilName: string, constructor(private _names: CodegenNameUtil, private _utilName: string,
private _changeDetection: string) {} private _changeDetection: ChangeDetectionStrategy) {}
/** /**
* Generates a statement which updates the local variable representing `protoRec` with the current * Generates a statement which updates the local variable representing `protoRec` with the current
@ -119,7 +119,7 @@ export class CodegenLogicUtil {
_observe(exp: string, rec: ProtoRecord): string { _observe(exp: string, rec: ProtoRecord): string {
// This is an experimental feature. Works only in Dart. // This is an experimental feature. Works only in Dart.
if (StringWrapper.equals(this._changeDetection, ON_PUSH_OBSERVE)) { if (this._changeDetection === ChangeDetectionStrategy.OnPushObserve) {
return `this.observeValue(${exp}, ${rec.selfIndex})`; return `this.observeValue(${exp}, ${rec.selfIndex})`;
} else { } else {
return exp; return exp;
@ -165,7 +165,7 @@ export class CodegenLogicUtil {
private _genReadDirective(index: number) { private _genReadDirective(index: number) {
// This is an experimental feature. Works only in Dart. // This is an experimental feature. Works only in Dart.
if (StringWrapper.equals(this._changeDetection, ON_PUSH_OBSERVE)) { if (this._changeDetection === ChangeDetectionStrategy.OnPushObserve) {
return `this.observeDirective(this.getDirectiveFor(directives, ${index}), ${index})`; return `this.observeDirective(this.getDirectiveFor(directives, ${index}), ${index})`;
} else { } else {
return `this.getDirectiveFor(directives, ${index})`; return `this.getDirectiveFor(directives, ${index})`;

View File

@ -1,46 +1,49 @@
// TODO:vsavkin Use enums after switching to TypeScript // TODO:vsavkin Use enums after switching to TypeScript
import {StringWrapper, normalizeBool, isBlank} from 'angular2/src/core/facade/lang'; import {StringWrapper, normalizeBool, isBlank} from 'angular2/src/core/facade/lang';
/** export enum ChangeDetectionStrategy {
* CHECK_ONCE means that after calling detectChanges the mode of the change detector /**
* will become CHECKED. * `CheckedOnce` means that after calling detectChanges the mode of the change detector
*/ * will become `Checked`.
export const CHECK_ONCE: string = "CHECK_ONCE"; */
CheckOnce,
/** /**
* CHECKED means that the change detector should be skipped until its mode changes to * `Checked` means that the change detector should be skipped until its mode changes to
* CHECK_ONCE or CHECK_ALWAYS. * `CheckOnce`.
*/ */
export const CHECKED: string = "CHECKED"; Checked,
/** /**
* CHECK_ALWAYS means that after calling detectChanges the mode of the change detector * `CheckAlways` means that after calling detectChanges the mode of the change detector
* will remain CHECK_ALWAYS. * will remain `CheckAlways`.
*/ */
export const CHECK_ALWAYS: string = "ALWAYS_CHECK"; CheckAlways,
/** /**
* DETACHED means that the change detector sub tree is not a part of the main tree and * `Detached` means that the change detector sub tree is not a part of the main tree and
* should be skipped. * should be skipped.
*/ */
export const DETACHED: string = "DETACHED"; Detached,
/** /**
* ON_PUSH means that the change detector's mode will be set to CHECK_ONCE during hydration. * `OnPush` means that the change detector's mode will be set to `CheckOnce` during hydration.
*/ */
export const ON_PUSH: string = "ON_PUSH"; OnPush,
/** /**
* DEFAULT means that the change detector's mode will be set to CHECK_ALWAYS during hydration. * `Default` means that the change detector's mode will be set to `CheckAlways` during hydration.
*/ */
export const DEFAULT: string = "DEFAULT"; Default,
export function isDefaultChangeDetectionStrategy(changeDetectionStrategy: string): boolean { /**
return isBlank(changeDetectionStrategy) || StringWrapper.equals(changeDetectionStrategy, DEFAULT); * This is an experimental feature. Works only in Dart.
*/
OnPushObserve
} }
export function isDefaultChangeDetectionStrategy(changeDetectionStrategy: ChangeDetectionStrategy):
/** boolean {
* This is an experimental feature. Works only in Dart. return isBlank(changeDetectionStrategy) ||
*/ changeDetectionStrategy === ChangeDetectionStrategy.Default;
export const ON_PUSH_OBSERVE = "ON_PUSH_OBSERVE"; }

View File

@ -1,5 +1,5 @@
import {StringWrapper, normalizeBool, isBlank} from 'angular2/src/core/facade/lang'; import {StringWrapper, normalizeBool, isBlank} from 'angular2/src/core/facade/lang';
import {isDefaultChangeDetectionStrategy} from './constants'; import {isDefaultChangeDetectionStrategy, ChangeDetectionStrategy} from './constants';
export class DirectiveIndex { export class DirectiveIndex {
constructor(public elementIndex: number, public directiveIndex: number) {} constructor(public elementIndex: number, public directiveIndex: number) {}
@ -13,7 +13,7 @@ export class DirectiveRecord {
callOnChange: boolean; callOnChange: boolean;
callOnCheck: boolean; callOnCheck: boolean;
callOnInit: boolean; callOnInit: boolean;
changeDetection: string; changeDetection: ChangeDetectionStrategy;
constructor({directiveIndex, callOnAllChangesDone, callOnChange, callOnCheck, callOnInit, constructor({directiveIndex, callOnAllChangesDone, callOnChange, callOnCheck, callOnInit,
changeDetection}: { changeDetection}: {
@ -22,7 +22,7 @@ export class DirectiveRecord {
callOnChange?: boolean, callOnChange?: boolean,
callOnCheck?: boolean, callOnCheck?: boolean,
callOnInit?: boolean, callOnInit?: boolean,
changeDetection?: string changeDetection?: ChangeDetectionStrategy
} = {}) { } = {}) {
this.directiveIndex = directiveIndex; this.directiveIndex = directiveIndex;
this.callOnAllChangesDone = normalizeBool(callOnAllChangesDone); this.callOnAllChangesDone = normalizeBool(callOnAllChangesDone);
@ -35,4 +35,4 @@ export class DirectiveRecord {
isDefaultChangeDetection(): boolean { isDefaultChangeDetection(): boolean {
return isDefaultChangeDetectionStrategy(this.changeDetection); return isDefaultChangeDetectionStrategy(this.changeDetection);
} }
} }

View File

@ -14,7 +14,7 @@ import {DirectiveRecord, DirectiveIndex} from './directive_record';
import {Locals} from './parser/locals'; import {Locals} from './parser/locals';
import {ChangeDetectorGenConfig} from './interfaces'; import {ChangeDetectorGenConfig} from './interfaces';
import {ChangeDetectionUtil, SimpleChange} from './change_detection_util'; import {ChangeDetectionUtil, SimpleChange} from './change_detection_util';
import {ON_PUSH_OBSERVE} from './constants'; import {ChangeDetectionStrategy} from './constants';
import {ProtoRecord, RecordType} from './proto_record'; import {ProtoRecord, RecordType} from './proto_record';
export class DynamicChangeDetector extends AbstractChangeDetector<any> { export class DynamicChangeDetector extends AbstractChangeDetector<any> {
@ -26,7 +26,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
constructor(id: string, dispatcher: any, numberOfPropertyProtoRecords: number, constructor(id: string, dispatcher: any, numberOfPropertyProtoRecords: number,
propertyBindingTargets: BindingTarget[], directiveIndices: DirectiveIndex[], propertyBindingTargets: BindingTarget[], directiveIndices: DirectiveIndex[],
strategy: string, private records: ProtoRecord[], strategy: ChangeDetectionStrategy, private records: ProtoRecord[],
private eventBindings: EventBinding[], private directiveRecords: DirectiveRecord[], private eventBindings: EventBinding[], private directiveRecords: DirectiveRecord[],
private genConfig: ChangeDetectorGenConfig) { private genConfig: ChangeDetectorGenConfig) {
super(id, dispatcher, numberOfPropertyProtoRecords, propertyBindingTargets, directiveIndices, super(id, dispatcher, numberOfPropertyProtoRecords, propertyBindingTargets, directiveIndices,
@ -88,7 +88,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
this.values[0] = this.context; this.values[0] = this.context;
this.directives = directives; this.directives = directives;
if (StringWrapper.equals(this.strategy, ON_PUSH_OBSERVE)) { if (this.strategy === ChangeDetectionStrategy.OnPushObserve) {
for (var i = 0; i < this.directiveIndices.length; ++i) { for (var i = 0; i < this.directiveIndices.length; ++i) {
var index = this.directiveIndices[i]; var index = this.directiveIndices[i];
super.observeDirective(directives.getDirectiveFor(index), i); super.observeDirective(directives.getDirectiveFor(index), i);
@ -219,7 +219,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
} }
var currValue = this._calculateCurrValue(proto, values, locals); var currValue = this._calculateCurrValue(proto, values, locals);
if (StringWrapper.equals(this.strategy, ON_PUSH_OBSERVE)) { if (this.strategy === ChangeDetectionStrategy.OnPushObserve) {
super.observeValue(currValue, proto.selfIndex); super.observeValue(currValue, proto.selfIndex);
} }

View File

@ -3,6 +3,7 @@ import {CONST} from 'angular2/src/core/facade/lang';
import {Locals} from './parser/locals'; import {Locals} from './parser/locals';
import {BindingTarget, BindingRecord} from './binding_record'; import {BindingTarget, BindingRecord} from './binding_record';
import {DirectiveIndex, DirectiveRecord} from './directive_record'; import {DirectiveIndex, DirectiveRecord} from './directive_record';
import {ChangeDetectionStrategy} from './constants';
import {ChangeDetectorRef} from './change_detector_ref'; import {ChangeDetectorRef} from './change_detector_ref';
/** /**
@ -55,7 +56,7 @@ export interface ChangeDispatcher {
export interface ChangeDetector { export interface ChangeDetector {
parent: ChangeDetector; parent: ChangeDetector;
mode: string; mode: ChangeDetectionStrategy;
ref: ChangeDetectorRef; ref: ChangeDetectorRef;
addChild(cd: ChangeDetector): void; addChild(cd: ChangeDetector): void;
@ -80,8 +81,8 @@ export class ChangeDetectorGenConfig {
} }
export class ChangeDetectorDefinition { export class ChangeDetectorDefinition {
constructor(public id: string, public strategy: string, public variableNames: List<string>, constructor(public id: string, public strategy: ChangeDetectionStrategy,
public bindingRecords: BindingRecord[], public eventRecords: BindingRecord[], public variableNames: List<string>, public bindingRecords: BindingRecord[],
public directiveRecords: DirectiveRecord[], public eventRecords: BindingRecord[], public directiveRecords: DirectiveRecord[],
public genConfig: ChangeDetectorGenConfig) {} public genConfig: ChangeDetectorGenConfig) {}
} }

View File

@ -7,7 +7,7 @@ export 'dart:core' show List;
export 'package:angular2/src/core/change_detection/abstract_change_detector.dart' export 'package:angular2/src/core/change_detection/abstract_change_detector.dart'
show AbstractChangeDetector; show AbstractChangeDetector;
export 'package:angular2/src/core/change_detection/change_detection.dart' export 'package:angular2/src/core/change_detection/change_detection.dart'
show preGeneratedProtoDetectors; show preGeneratedProtoDetectors, ChangeDetectionStrategy;
export 'package:angular2/src/core/change_detection/directive_record.dart' export 'package:angular2/src/core/change_detection/directive_record.dart'
show DirectiveIndex, DirectiveRecord; show DirectiveIndex, DirectiveRecord;
export 'package:angular2/src/core/change_detection/interfaces.dart' export 'package:angular2/src/core/change_detection/interfaces.dart'

View File

@ -16,7 +16,7 @@ import {
BindingRecord, BindingRecord,
DirectiveRecord, DirectiveRecord,
ProtoChangeDetector, ProtoChangeDetector,
DEFAULT, ChangeDetectionStrategy,
ChangeDetectorDefinition, ChangeDetectorDefinition,
ChangeDetectorGenConfig, ChangeDetectorGenConfig,
ASTWithSource ASTWithSource
@ -305,7 +305,7 @@ function _getChangeDetectorDefinitions(
bindingRecordsCreator.getEventBindingRecords(elementBinders, allRenderDirectiveMetadata); bindingRecordsCreator.getEventBindingRecords(elementBinders, allRenderDirectiveMetadata);
var directiveRecords = var directiveRecords =
bindingRecordsCreator.getDirectiveRecords(elementBinders, allRenderDirectiveMetadata); bindingRecordsCreator.getDirectiveRecords(elementBinders, allRenderDirectiveMetadata);
var strategyName = DEFAULT; var strategyName = ChangeDetectionStrategy.Default;
if (pvWithIndex.renderProtoView.type === ViewType.COMPONENT) { if (pvWithIndex.renderProtoView.type === ViewType.COMPONENT) {
strategyName = hostComponentMetadata.changeDetection; strategyName = hostComponentMetadata.changeDetection;
} }

View File

@ -1,6 +1,7 @@
library angular2.src.core.metadata; library angular2.src.core.metadata;
import "package:angular2/src/core/facade/collection.dart" show List; import "package:angular2/src/core/facade/collection.dart" show List;
import 'package:angular2/src/core/change_detection/change_detection.dart';
import "./metadata/di.dart"; import "./metadata/di.dart";
import "./metadata/directives.dart"; import "./metadata/directives.dart";
import "./metadata/view.dart"; import "./metadata/view.dart";
@ -35,7 +36,7 @@ class Component extends ComponentMetadata {
const Component({String selector, List<String> properties, const Component({String selector, List<String> properties,
List<String> events, Map<String, String> host, List<String> events, Map<String, String> host,
List<LifecycleEvent> lifecycle, List bindings, String exportAs, List<LifecycleEvent> lifecycle, List bindings, String exportAs,
bool compileChildren, List viewBindings, String changeDetection}) bool compileChildren, List viewBindings, ChangeDetectionStrategy changeDetection})
: super( : super(
selector: selector, selector: selector,
properties: properties, properties: properties,

View File

@ -33,6 +33,7 @@ import {
} from './metadata/directives'; } from './metadata/directives';
import {ViewMetadata, ViewEncapsulation} from './metadata/view'; import {ViewMetadata, ViewEncapsulation} from './metadata/view';
import {ChangeDetectionStrategy} from 'angular2/src/core/change_detection/change_detection';
import {makeDecorator, makeParamDecorator, TypeDecorator, Class} from './util/decorators'; import {makeDecorator, makeParamDecorator, TypeDecorator, Class} from './util/decorators';
import {Type} from 'angular2/src/core/facade/lang'; import {Type} from 'angular2/src/core/facade/lang';
@ -191,7 +192,7 @@ export interface ComponentFactory {
exportAs?: string, exportAs?: string,
compileChildren?: boolean, compileChildren?: boolean,
viewBindings?: List<any>, viewBindings?: List<any>,
changeDetection?: string, changeDetection?: ChangeDetectionStrategy,
}): ComponentDecorator; }): ComponentDecorator;
new (obj: { new (obj: {
selector?: string, selector?: string,
@ -203,7 +204,7 @@ export interface ComponentFactory {
exportAs?: string, exportAs?: string,
compileChildren?: boolean, compileChildren?: boolean,
viewBindings?: List<any>, viewBindings?: List<any>,
changeDetection?: string, changeDetection?: ChangeDetectionStrategy,
}): ComponentMetadata; }): ComponentMetadata;
} }

View File

@ -1,7 +1,7 @@
import {CONST, CONST_EXPR} from 'angular2/src/core/facade/lang'; import {CONST, CONST_EXPR} from 'angular2/src/core/facade/lang';
import {List} from 'angular2/src/core/facade/collection'; import {List} from 'angular2/src/core/facade/collection';
import {InjectableMetadata} from 'angular2/src/core/di/metadata'; import {InjectableMetadata} from 'angular2/src/core/di/metadata';
import {DEFAULT} from 'angular2/change_detection'; import {ChangeDetectionStrategy} from 'angular2/change_detection';
/** /**
* Directives allow you to attach behavior to elements in the DOM. * Directives allow you to attach behavior to elements in the DOM.
@ -795,14 +795,12 @@ export class ComponentMetadata extends DirectiveMetadata {
* Defines the used change detection strategy. * Defines the used change detection strategy.
* *
* When a component is instantiated, Angular creates a change detector, which is responsible for * When a component is instantiated, Angular creates a change detector, which is responsible for
* propagating * propagating the component's bindings.
* the component's bindings.
* *
* The `changeDetection` property defines, whether the change detection will be checked every time * The `changeDetection` property defines, whether the change detection will be checked every time
* or only when the component * or only when the component tells it to do so.
* tells it to do so.
*/ */
changeDetection: string; changeDetection: ChangeDetectionStrategy;
/** /**
* Defines the set of injectable objects that are visible to its view dom children. * Defines the set of injectable objects that are visible to its view dom children.
@ -847,7 +845,7 @@ export class ComponentMetadata extends DirectiveMetadata {
viewBindings: List<any>; viewBindings: List<any>;
constructor({selector, properties, events, host, exportAs, lifecycle, bindings, viewBindings, constructor({selector, properties, events, host, exportAs, lifecycle, bindings, viewBindings,
changeDetection = DEFAULT, compileChildren = true}: { changeDetection = ChangeDetectionStrategy.Default, compileChildren = true}: {
selector?: string, selector?: string,
properties?: List<string>, properties?: List<string>,
events?: List<string>, events?: List<string>,
@ -857,7 +855,7 @@ export class ComponentMetadata extends DirectiveMetadata {
exportAs?: string, exportAs?: string,
compileChildren?: boolean, compileChildren?: boolean,
viewBindings?: List<any>, viewBindings?: List<any>,
changeDetection?: string, changeDetection?: ChangeDetectionStrategy,
} = {}) { } = {}) {
super({ super({
selector: selector, selector: selector,

View File

@ -46,7 +46,7 @@ var _observableStrategy = new ObservableStrategy();
* ``` * ```
* @Component({ * @Component({
* selector: "task-cmp", * selector: "task-cmp",
* changeDetection: ON_PUSH * changeDetection: ChangeDetectionStrategy.OnPush
* }) * })
* @View({ * @View({
* template: "Task Description {{ description | async }}" * template: "Task Description {{ description | async }}"

View File

@ -7,7 +7,10 @@ import {
StringMap, StringMap,
StringMapWrapper StringMapWrapper
} from 'angular2/src/core/facade/collection'; } from 'angular2/src/core/facade/collection';
import {ASTWithSource} from 'angular2/src/core/change_detection/change_detection'; import {
ASTWithSource,
ChangeDetectionStrategy
} from 'angular2/src/core/change_detection/change_detection';
/** /**
* General notes: * General notes:
@ -155,7 +158,7 @@ export class RenderDirectiveMetadata {
callOnCheck: boolean; callOnCheck: boolean;
callOnInit: boolean; callOnInit: boolean;
callOnAllChangesDone: boolean; callOnAllChangesDone: boolean;
changeDetection: string; changeDetection: ChangeDetectionStrategy;
exportAs: string; exportAs: string;
hostListeners: Map<string, string>; hostListeners: Map<string, string>;
hostProperties: Map<string, string>; hostProperties: Map<string, string>;
@ -185,7 +188,7 @@ export class RenderDirectiveMetadata {
callOnCheck?: boolean, callOnCheck?: boolean,
callOnInit?: boolean, callOnInit?: boolean,
callOnAllChangesDone?: boolean, callOnAllChangesDone?: boolean,
changeDetection?: string, changeDetection?: ChangeDetectionStrategy,
exportAs?: string exportAs?: string
}) { }) {
this.id = id; this.id = id;
@ -224,7 +227,7 @@ export class RenderDirectiveMetadata {
callOnCheck?: boolean, callOnCheck?: boolean,
callOnInit?: boolean, callOnInit?: boolean,
callOnAllChangesDone?: boolean, callOnAllChangesDone?: boolean,
changeDetection?: string, changeDetection?: ChangeDetectionStrategy,
exportAs?: string exportAs?: string
}): RenderDirectiveMetadata { }): RenderDirectiveMetadata {
let hostListeners = new Map(); let hostListeners = new Map();

View File

@ -1,67 +0,0 @@
import {ListWrapper, MapWrapper} from 'angular2/src/core/facade/collection';
import {isPresent, isArray} from 'angular2/src/core/facade/lang';
import {RenderDirectiveMetadata} from 'angular2/src/core/render/api';
/**
* Converts a [DirectiveMetadata] to a map representation. This creates a copy,
* that is, subsequent changes to `meta` will not be mirrored in the map.
*/
export function directiveMetadataToMap(meta: RenderDirectiveMetadata): Map<string, any> {
return MapWrapper.createFromPairs([
['id', meta.id],
['selector', meta.selector],
['compileChildren', meta.compileChildren],
['hostProperties', _cloneIfPresent(meta.hostProperties)],
['hostListeners', _cloneIfPresent(meta.hostListeners)],
['hostActions', _cloneIfPresent(meta.hostActions)],
['hostAttributes', _cloneIfPresent(meta.hostAttributes)],
['properties', _cloneIfPresent(meta.properties)],
['readAttributes', _cloneIfPresent(meta.readAttributes)],
['type', meta.type],
['exportAs', meta.exportAs],
['callOnDestroy', meta.callOnDestroy],
['callOnCheck', meta.callOnCheck],
['callOnInit', meta.callOnInit],
['callOnChange', meta.callOnChange],
['callOnAllChangesDone', meta.callOnAllChangesDone],
['events', meta.events],
['changeDetection', meta.changeDetection],
['version', 1],
]);
}
/**
* Converts a map representation of [DirectiveMetadata] into a
* [DirectiveMetadata] object. This creates a copy, that is, subsequent changes
* to `map` will not be mirrored in the [DirectiveMetadata] object.
*/
export function directiveMetadataFromMap(map: Map<string, any>): RenderDirectiveMetadata {
return new RenderDirectiveMetadata({
id:<string>map.get('id'),
selector:<string>map.get('selector'),
compileChildren:<boolean>map.get('compileChildren'),
hostProperties:<Map<string, string>>_cloneIfPresent(map.get('hostProperties')),
hostListeners:<Map<string, string>>_cloneIfPresent(map.get('hostListeners')),
hostActions:<Map<string, string>>_cloneIfPresent(map.get('hostActions')),
hostAttributes:<Map<string, string>>_cloneIfPresent(map.get('hostAttributes')),
properties:<List<string>>_cloneIfPresent(map.get('properties')),
readAttributes:<List<string>>_cloneIfPresent(map.get('readAttributes')),
type:<number>map.get('type'),
exportAs:<string>map.get('exportAs'),
callOnDestroy:<boolean>map.get('callOnDestroy'),
callOnCheck:<boolean>map.get('callOnCheck'),
callOnChange:<boolean>map.get('callOnChange'),
callOnInit:<boolean>map.get('callOnInit'),
callOnAllChangesDone:<boolean>map.get('callOnAllChangesDone'),
events:<List<string>>_cloneIfPresent(map.get('events')),
changeDetection:<string>map.get('changeDetection'),
});
}
/**
* Clones the [List] or [Map] `o` if it is present.
*/
function _cloneIfPresent(o): any {
if (!isPresent(o)) return null;
return isArray(o) ? ListWrapper.clone(o) : MapWrapper.clone(o);
}

View File

@ -1,8 +1,7 @@
import {ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/core/facade/collection'; import {ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/core/facade/collection';
import {isBlank, isPresent} from 'angular2/src/core/facade/lang'; import {isBlank, isPresent} from 'angular2/src/core/facade/lang';
import { import {
DEFAULT, ChangeDetectionStrategy,
ON_PUSH,
BindingRecord, BindingRecord,
ChangeDetectorDefinition, ChangeDetectorDefinition,
DirectiveIndex, DirectiveIndex,
@ -12,7 +11,6 @@ import {
Parser, Parser,
ChangeDetectorGenConfig ChangeDetectorGenConfig
} from 'angular2/src/core/change_detection/change_detection'; } from 'angular2/src/core/change_detection/change_detection';
import {ON_PUSH_OBSERVE} from 'angular2/src/core/change_detection/constants';
import {reflector} from 'angular2/src/core/reflection/reflection'; import {reflector} from 'angular2/src/core/reflection/reflection';
import {ReflectionCapabilities} from 'angular2/src/core/reflection/reflection_capabilities'; import {ReflectionCapabilities} from 'angular2/src/core/reflection/reflection_capabilities';
@ -109,15 +107,17 @@ export function getDefinition(id: string): TestDefinition {
} else if (id == "onPushObserveBinding") { } else if (id == "onPushObserveBinding") {
var records = _createBindingRecords("a"); var records = _createBindingRecords("a");
let cdDef = new ChangeDetectorDefinition(id, ON_PUSH_OBSERVE, [], records, [], [], genConfig); let cdDef = new ChangeDetectorDefinition(id, ChangeDetectionStrategy.OnPushObserve, [], records,
[], [], genConfig);
testDef = new TestDefinition(id, cdDef, null); testDef = new TestDefinition(id, cdDef, null);
} else if (id == "onPushObserveComponent") { } else if (id == "onPushObserveComponent") {
let cdDef = new ChangeDetectorDefinition(id, ON_PUSH_OBSERVE, [], [], [], [], genConfig); let cdDef = new ChangeDetectorDefinition(id, ChangeDetectionStrategy.OnPushObserve, [], [], [],
[], genConfig);
testDef = new TestDefinition(id, cdDef, null); testDef = new TestDefinition(id, cdDef, null);
} else if (id == "onPushObserveDirective") { } else if (id == "onPushObserveDirective") {
let cdDef = new ChangeDetectorDefinition(id, ON_PUSH_OBSERVE, [], [], [], let cdDef = new ChangeDetectorDefinition(id, ChangeDetectionStrategy.OnPushObserve, [], [], [],
[_DirectiveUpdating.recordNoCallbacks], genConfig); [_DirectiveUpdating.recordNoCallbacks], genConfig);
testDef = new TestDefinition(id, cdDef, null); testDef = new TestDefinition(id, cdDef, null);
} else if (id == "updateElementProduction") { } else if (id == "updateElementProduction") {
@ -196,7 +196,7 @@ class _ExpressionWithLocals {
} }
class _ExpressionWithMode { class _ExpressionWithMode {
constructor(private _strategy: string, private _withRecords: boolean, constructor(private _strategy: ChangeDetectionStrategy, private _withRecords: boolean,
private _withEvents: boolean) {} private _withEvents: boolean) {}
createChangeDetectorDefinition(): ChangeDetectorDefinition { createChangeDetectorDefinition(): ChangeDetectorDefinition {
@ -205,10 +205,14 @@ class _ExpressionWithMode {
var directiveRecords = []; var directiveRecords = [];
var eventRecords = []; var eventRecords = [];
var dirRecordWithDefault = var dirRecordWithDefault = new DirectiveRecord({
new DirectiveRecord({directiveIndex: new DirectiveIndex(0, 0), changeDetection: DEFAULT}); directiveIndex: new DirectiveIndex(0, 0),
var dirRecordWithOnPush = changeDetection: ChangeDetectionStrategy.Default
new DirectiveRecord({directiveIndex: new DirectiveIndex(0, 1), changeDetection: ON_PUSH}); });
var dirRecordWithOnPush = new DirectiveRecord({
directiveIndex: new DirectiveIndex(0, 1),
changeDetection: ChangeDetectionStrategy.OnPush
});
if (this._withRecords) { if (this._withRecords) {
var updateDirWithOnDefaultRecord = var updateDirWithOnDefaultRecord =
@ -240,11 +244,14 @@ class _ExpressionWithMode {
* Definitions in this map define conditions which allow testing various change detector modes. * Definitions in this map define conditions which allow testing various change detector modes.
*/ */
static availableDefinitions: StringMap<string, _ExpressionWithMode> = { static availableDefinitions: StringMap<string, _ExpressionWithMode> = {
'emptyUsingDefaultStrategy': new _ExpressionWithMode(DEFAULT, false, false), 'emptyUsingDefaultStrategy':
'emptyUsingOnPushStrategy': new _ExpressionWithMode(ON_PUSH, false, false), new _ExpressionWithMode(ChangeDetectionStrategy.Default, false, false),
'onPushRecordsUsingDefaultStrategy': new _ExpressionWithMode(DEFAULT, true, false), 'emptyUsingOnPushStrategy':
'onPushWithEvent': new _ExpressionWithMode(ON_PUSH, false, true), new _ExpressionWithMode(ChangeDetectionStrategy.OnPush, false, false),
'onPushWithHostEvent': new _ExpressionWithMode(ON_PUSH, false, true) 'onPushRecordsUsingDefaultStrategy':
new _ExpressionWithMode(ChangeDetectionStrategy.Default, true, false),
'onPushWithEvent': new _ExpressionWithMode(ChangeDetectionStrategy.OnPush, false, true),
'onPushWithHostEvent': new _ExpressionWithMode(ChangeDetectionStrategy.OnPush, false, true)
}; };
} }
@ -413,4 +420,4 @@ var _availableEventDefinitions = [
'(event)="true"' '(event)="true"'
]; ];
var _availableHostEventDefinitions = ['(host-event)="onEvent(\$event)"']; var _availableHostEventDefinitions = ['(host-event)="onEvent(\$event)"'];

View File

@ -32,12 +32,7 @@ import {
DirectiveIndex, DirectiveIndex,
PipeTransform, PipeTransform,
PipeOnDestroy, PipeOnDestroy,
CHECK_ALWAYS, ChangeDetectionStrategy,
CHECK_ONCE,
CHECKED,
DETACHED,
ON_PUSH,
DEFAULT,
WrappedValue, WrappedValue,
DynamicProtoChangeDetector, DynamicProtoChangeDetector,
ChangeDetectorDefinition, ChangeDetectorDefinition,
@ -673,26 +668,26 @@ export function main() {
}); });
describe('mode', () => { describe('mode', () => {
it('should set the mode to CHECK_ALWAYS when the default change detection is used', () => { it('should set the mode to CheckAlways when the default change detection is used', () => {
var cd = _createWithoutHydrate('emptyUsingDefaultStrategy').changeDetector; var cd = _createWithoutHydrate('emptyUsingDefaultStrategy').changeDetector;
expect(cd.mode).toEqual(null); expect(cd.mode).toEqual(null);
cd.hydrate(_DEFAULT_CONTEXT, null, null, null); cd.hydrate(_DEFAULT_CONTEXT, null, null, null);
expect(cd.mode).toEqual(CHECK_ALWAYS); expect(cd.mode).toEqual(ChangeDetectionStrategy.CheckAlways);
}); });
it('should set the mode to CHECK_ONCE when the push change detection is used', () => { it('should set the mode to CheckOnce when the push change detection is used', () => {
var cd = _createWithoutHydrate('emptyUsingOnPushStrategy').changeDetector; var cd = _createWithoutHydrate('emptyUsingOnPushStrategy').changeDetector;
cd.hydrate(_DEFAULT_CONTEXT, null, null, null); cd.hydrate(_DEFAULT_CONTEXT, null, null, null);
expect(cd.mode).toEqual(CHECK_ONCE); expect(cd.mode).toEqual(ChangeDetectionStrategy.CheckOnce);
}); });
it('should not check a detached change detector', () => { it('should not check a detached change detector', () => {
var val = _createChangeDetector('a', new TestData('value')); var val = _createChangeDetector('a', new TestData('value'));
val.changeDetector.hydrate(_DEFAULT_CONTEXT, null, null, null); val.changeDetector.hydrate(_DEFAULT_CONTEXT, null, null, null);
val.changeDetector.mode = DETACHED; val.changeDetector.mode = ChangeDetectionStrategy.Detached;
val.changeDetector.detectChanges(); val.changeDetector.detectChanges();
expect(val.dispatcher.log).toEqual([]); expect(val.dispatcher.log).toEqual([]);
@ -702,33 +697,33 @@ export function main() {
var val = _createChangeDetector('a', new TestData('value')); var val = _createChangeDetector('a', new TestData('value'));
val.changeDetector.hydrate(_DEFAULT_CONTEXT, null, null, null); val.changeDetector.hydrate(_DEFAULT_CONTEXT, null, null, null);
val.changeDetector.mode = CHECKED; val.changeDetector.mode = ChangeDetectionStrategy.Checked;
val.changeDetector.detectChanges(); val.changeDetector.detectChanges();
expect(val.dispatcher.log).toEqual([]); expect(val.dispatcher.log).toEqual([]);
}); });
it('should change CHECK_ONCE to CHECKED', () => { it('should change CheckOnce to Checked', () => {
var cd = _createChangeDetector('10').changeDetector; var cd = _createChangeDetector('10').changeDetector;
cd.hydrate(_DEFAULT_CONTEXT, null, null, null); cd.hydrate(_DEFAULT_CONTEXT, null, null, null);
cd.mode = CHECK_ONCE; cd.mode = ChangeDetectionStrategy.CheckOnce;
cd.detectChanges(); cd.detectChanges();
expect(cd.mode).toEqual(CHECKED); expect(cd.mode).toEqual(ChangeDetectionStrategy.Checked);
}); });
it('should not change the CHECK_ALWAYS', () => { it('should not change the CheckAlways', () => {
var cd = _createChangeDetector('10').changeDetector; var cd = _createChangeDetector('10').changeDetector;
cd.hydrate(_DEFAULT_CONTEXT, null, null, null); cd.hydrate(_DEFAULT_CONTEXT, null, null, null);
cd.mode = CHECK_ALWAYS; cd.mode = ChangeDetectionStrategy.CheckAlways;
cd.detectChanges(); cd.detectChanges();
expect(cd.mode).toEqual(CHECK_ALWAYS); expect(cd.mode).toEqual(ChangeDetectionStrategy.CheckAlways);
}); });
describe('marking ON_PUSH detectors as CHECK_ONCE after an update', () => { describe('marking OnPush detectors as CheckOnce after an update', () => {
var childDirectiveDetectorRegular; var childDirectiveDetectorRegular;
var childDirectiveDetectorOnPush; var childDirectiveDetectorOnPush;
var directives; var directives;
@ -736,53 +731,53 @@ export function main() {
beforeEach(() => { beforeEach(() => {
childDirectiveDetectorRegular = _createWithoutHydrate('10').changeDetector; childDirectiveDetectorRegular = _createWithoutHydrate('10').changeDetector;
childDirectiveDetectorRegular.hydrate(_DEFAULT_CONTEXT, null, null, null); childDirectiveDetectorRegular.hydrate(_DEFAULT_CONTEXT, null, null, null);
childDirectiveDetectorRegular.mode = CHECK_ALWAYS; childDirectiveDetectorRegular.mode = ChangeDetectionStrategy.CheckAlways;
childDirectiveDetectorOnPush = childDirectiveDetectorOnPush =
_createWithoutHydrate('emptyUsingOnPushStrategy').changeDetector; _createWithoutHydrate('emptyUsingOnPushStrategy').changeDetector;
childDirectiveDetectorOnPush.hydrate(_DEFAULT_CONTEXT, null, null, null); childDirectiveDetectorOnPush.hydrate(_DEFAULT_CONTEXT, null, null, null);
childDirectiveDetectorOnPush.mode = CHECKED; childDirectiveDetectorOnPush.mode = ChangeDetectionStrategy.Checked;
directives = directives =
new FakeDirectives([new TestData(null), new TestData(null)], new FakeDirectives([new TestData(null), new TestData(null)],
[childDirectiveDetectorRegular, childDirectiveDetectorOnPush]); [childDirectiveDetectorRegular, childDirectiveDetectorOnPush]);
}); });
it('should set the mode to CHECK_ONCE when a binding is updated', () => { it('should set the mode to CheckOnce when a binding is updated', () => {
var parentDetector = var parentDetector =
_createWithoutHydrate('onPushRecordsUsingDefaultStrategy').changeDetector; _createWithoutHydrate('onPushRecordsUsingDefaultStrategy').changeDetector;
parentDetector.hydrate(_DEFAULT_CONTEXT, null, directives, null); parentDetector.hydrate(_DEFAULT_CONTEXT, null, directives, null);
parentDetector.detectChanges(); parentDetector.detectChanges();
// making sure that we only change the status of ON_PUSH components // making sure that we only change the status of OnPush components
expect(childDirectiveDetectorRegular.mode).toEqual(CHECK_ALWAYS); expect(childDirectiveDetectorRegular.mode).toEqual(ChangeDetectionStrategy.CheckAlways);
expect(childDirectiveDetectorOnPush.mode).toEqual(CHECK_ONCE); expect(childDirectiveDetectorOnPush.mode).toEqual(ChangeDetectionStrategy.CheckOnce);
}); });
it('should mark ON_PUSH detectors as CHECK_ONCE after an event', () => { it('should mark OnPush detectors as CheckOnce after an event', () => {
var cd = _createWithoutHydrate('onPushWithEvent').changeDetector; var cd = _createWithoutHydrate('onPushWithEvent').changeDetector;
cd.hydrate(_DEFAULT_CONTEXT, null, directives, null); cd.hydrate(_DEFAULT_CONTEXT, null, directives, null);
cd.mode = CHECKED; cd.mode = ChangeDetectionStrategy.Checked;
cd.handleEvent("event", 0, null); cd.handleEvent("event", 0, null);
expect(cd.mode).toEqual(CHECK_ONCE); expect(cd.mode).toEqual(ChangeDetectionStrategy.CheckOnce);
}); });
it('should mark ON_PUSH detectors as CHECK_ONCE after a host event', () => { it('should mark OnPush detectors as CheckOnce after a host event', () => {
var cd = _createWithoutHydrate('onPushWithHostEvent').changeDetector; var cd = _createWithoutHydrate('onPushWithHostEvent').changeDetector;
cd.hydrate(_DEFAULT_CONTEXT, null, directives, null); cd.hydrate(_DEFAULT_CONTEXT, null, directives, null);
cd.handleEvent("host-event", 0, null); cd.handleEvent("host-event", 0, null);
expect(childDirectiveDetectorOnPush.mode).toEqual(CHECK_ONCE); expect(childDirectiveDetectorOnPush.mode).toEqual(ChangeDetectionStrategy.CheckOnce);
}); });
if (IS_DART) { if (IS_DART) {
describe('ON_PUSH_OBSERVE', () => { describe('OnPushObserve', () => {
it('should mark ON_PUSH_OBSERVE detectors as CHECK_ONCE when an observable fires an event', it('should mark OnPushObserve detectors as CheckOnce when an observable fires an event',
fakeAsync(() => { fakeAsync(() => {
var context = new TestDirective(); var context = new TestDirective();
context.a = createObservableModel(); context.a = createObservableModel();
@ -791,15 +786,15 @@ export function main() {
cd.hydrate(context, null, directives, null); cd.hydrate(context, null, directives, null);
cd.detectChanges(); cd.detectChanges();
expect(cd.mode).toEqual(CHECKED); expect(cd.mode).toEqual(ChangeDetectionStrategy.Checked);
context.a.pushUpdate(); context.a.pushUpdate();
tick(); tick();
expect(cd.mode).toEqual(CHECK_ONCE); expect(cd.mode).toEqual(ChangeDetectionStrategy.CheckOnce);
})); }));
it('should mark ON_PUSH_OBSERVE detectors as CHECK_ONCE when an observable context fires an event', it('should mark OnPushObserve detectors as CheckOnce when an observable context fires an event',
fakeAsync(() => { fakeAsync(() => {
var context = createObservableModel(); var context = createObservableModel();
@ -807,15 +802,15 @@ export function main() {
cd.hydrate(context, null, directives, null); cd.hydrate(context, null, directives, null);
cd.detectChanges(); cd.detectChanges();
expect(cd.mode).toEqual(CHECKED); expect(cd.mode).toEqual(ChangeDetectionStrategy.Checked);
context.pushUpdate(); context.pushUpdate();
tick(); tick();
expect(cd.mode).toEqual(CHECK_ONCE); expect(cd.mode).toEqual(ChangeDetectionStrategy.CheckOnce);
})); }));
it('should mark ON_PUSH_OBSERVE detectors as CHECK_ONCE when an observable directive fires an event', it('should mark OnPushObserve detectors as CheckOnce when an observable directive fires an event',
fakeAsync(() => { fakeAsync(() => {
var dir = createObservableModel(); var dir = createObservableModel();
var directives = new FakeDirectives([dir], []); var directives = new FakeDirectives([dir], []);
@ -824,12 +819,12 @@ export function main() {
cd.hydrate(_DEFAULT_CONTEXT, null, directives, null); cd.hydrate(_DEFAULT_CONTEXT, null, directives, null);
cd.detectChanges(); cd.detectChanges();
expect(cd.mode).toEqual(CHECKED); expect(cd.mode).toEqual(ChangeDetectionStrategy.Checked);
dir.pushUpdate(); dir.pushUpdate();
tick(); tick();
expect(cd.mode).toEqual(CHECK_ONCE); expect(cd.mode).toEqual(ChangeDetectionStrategy.CheckOnce);
})); }));
it('should unsubscribe from an old observable when an object changes', it('should unsubscribe from an old observable when an object changes',
@ -843,14 +838,14 @@ export function main() {
cd.detectChanges(); cd.detectChanges();
context.a = createObservableModel(); context.a = createObservableModel();
cd.mode = CHECK_ONCE; cd.mode = ChangeDetectionStrategy.CheckOnce;
cd.detectChanges(); cd.detectChanges();
// Updating this model will not reenable the detector. This model is not longer // Updating this model will not reenable the detector. This model is not longer
// used. // used.
originalModel.pushUpdate(); originalModel.pushUpdate();
tick(); tick();
expect(cd.mode).toEqual(CHECKED); expect(cd.mode).toEqual(ChangeDetectionStrategy.Checked);
})); }));
it('should unsubscribe from observables when dehydrating', fakeAsync(() => { it('should unsubscribe from observables when dehydrating', fakeAsync(() => {
@ -872,7 +867,7 @@ export function main() {
// used. // used.
originalModel.pushUpdate(); originalModel.pushUpdate();
tick(); tick();
expect(cd.mode).toEqual(CHECKED); expect(cd.mode).toEqual(ChangeDetectionStrategy.Checked);
})); }));
}); });
} }
@ -887,22 +882,22 @@ export function main() {
return val.changeDetector; return val.changeDetector;
} }
it('should mark all checked detectors as CHECK_ONCE until reaching a detached one', () => { it('should mark all checked detectors as CheckOnce until reaching a detached one', () => {
var root = changeDetector(CHECK_ALWAYS, null); var root = changeDetector(ChangeDetectionStrategy.CheckAlways, null);
var disabled = changeDetector(DETACHED, root); var disabled = changeDetector(ChangeDetectionStrategy.Detached, root);
var parent = changeDetector(CHECKED, disabled); var parent = changeDetector(ChangeDetectionStrategy.Checked, disabled);
var checkAlwaysChild = changeDetector(CHECK_ALWAYS, parent); var checkAlwaysChild = changeDetector(ChangeDetectionStrategy.CheckAlways, parent);
var checkOnceChild = changeDetector(CHECK_ONCE, checkAlwaysChild); var checkOnceChild = changeDetector(ChangeDetectionStrategy.CheckOnce, checkAlwaysChild);
var checkedChild = changeDetector(CHECKED, checkOnceChild); var checkedChild = changeDetector(ChangeDetectionStrategy.Checked, checkOnceChild);
checkedChild.markPathToRootAsCheckOnce(); checkedChild.markPathToRootAsCheckOnce();
expect(root.mode).toEqual(CHECK_ALWAYS); expect(root.mode).toEqual(ChangeDetectionStrategy.CheckAlways);
expect(disabled.mode).toEqual(DETACHED); expect(disabled.mode).toEqual(ChangeDetectionStrategy.Detached);
expect(parent.mode).toEqual(CHECK_ONCE); expect(parent.mode).toEqual(ChangeDetectionStrategy.CheckOnce);
expect(checkAlwaysChild.mode).toEqual(CHECK_ALWAYS); expect(checkAlwaysChild.mode).toEqual(ChangeDetectionStrategy.CheckAlways);
expect(checkOnceChild.mode).toEqual(CHECK_ONCE); expect(checkOnceChild.mode).toEqual(ChangeDetectionStrategy.CheckOnce);
expect(checkedChild.mode).toEqual(CHECK_ONCE); expect(checkedChild.mode).toEqual(ChangeDetectionStrategy.CheckOnce);
}); });
}); });

View File

@ -7,6 +7,7 @@ import 'package:angular2/test_lib.dart';
import 'package:observe/observe.dart'; import 'package:observe/observe.dart';
import 'package:angular2/src/core/directives/observable_list_diff.dart'; import 'package:angular2/src/core/directives/observable_list_diff.dart';
import 'package:angular2/src/core/change_detection/differs/default_iterable_differ.dart'; import 'package:angular2/src/core/change_detection/differs/default_iterable_differ.dart';
import 'package:angular2/src/core/change_detection/change_detection.dart';
class MockException implements Error { class MockException implements Error {
var message; var message;
@ -281,7 +282,7 @@ class OnChangeComponent implements OnChange {
@Component( @Component(
selector: 'component-with-observable-list', selector: 'component-with-observable-list',
changeDetection: ON_PUSH, changeDetection: ChangeDetectionStrategy.OnPush,
properties: const ['list'], properties: const ['list'],
bindings: const [ bindings: const [
const Binding(IterableDiffers, const Binding(IterableDiffers,

View File

@ -58,7 +58,7 @@ import {
import { import {
PipeTransform, PipeTransform,
ChangeDetectorRef, ChangeDetectorRef,
ON_PUSH, ChangeDetectionStrategy,
ChangeDetection, ChangeDetection,
DynamicChangeDetection, DynamicChangeDetection,
ChangeDetectorGenConfig ChangeDetectorGenConfig
@ -635,7 +635,7 @@ export function main() {
})); }));
}); });
describe("ON_PUSH components", () => { describe("OnPush components", () => {
it("should use ChangeDetectorRef to manually request a check", it("should use ChangeDetectorRef to manually request a check",
inject([TestComponentBuilder, AsyncTestCompleter], inject([TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async) => { (tcb: TestComponentBuilder, async) => {
@ -1672,7 +1672,8 @@ class DirectiveWithTitleAndHostProperty {
title: string; title: string;
} }
@Component({selector: 'push-cmp', properties: ['prop'], changeDetection: ON_PUSH}) @Component(
{selector: 'push-cmp', properties: ['prop'], changeDetection: ChangeDetectionStrategy.OnPush})
@View({template: '{{field}}'}) @View({template: '{{field}}'})
@Injectable() @Injectable()
class PushCmp { class PushCmp {
@ -1687,7 +1688,11 @@ class PushCmp {
} }
} }
@Component({selector: 'push-cmp-with-ref', properties: ['prop'], changeDetection: ON_PUSH}) @Component({
selector: 'push-cmp-with-ref',
properties: ['prop'],
changeDetection: ChangeDetectionStrategy.OnPush
})
@View({template: '{{field}}'}) @View({template: '{{field}}'})
@Injectable() @Injectable()
class PushCmpWithRef { class PushCmpWithRef {
@ -1708,7 +1713,7 @@ class PushCmpWithRef {
propagate() { this.ref.requestCheck(); } propagate() { this.ref.requestCheck(); }
} }
@Component({selector: 'push-cmp-with-async', changeDetection: ON_PUSH}) @Component({selector: 'push-cmp-with-async', changeDetection: ChangeDetectionStrategy.OnPush})
@View({template: '{{field | async}}'}) @View({template: '{{field | async}}'})
@Injectable() @Injectable()
class PushCmpWithAsyncPipe { class PushCmpWithAsyncPipe {

View File

@ -1,95 +0,0 @@
import {MapWrapper} from 'angular2/src/core/facade/collection';
import {RenderDirectiveMetadata} from 'angular2/src/core/render/api';
import {
directiveMetadataFromMap,
directiveMetadataToMap
} from 'angular2/src/core/render/dom/convert';
import {ddescribe, describe, expect, it} from 'angular2/test_lib';
export function main() {
describe('convert', () => {
it('directiveMetadataToMap', () => {
var someComponent = new RenderDirectiveMetadata({
compileChildren: false,
hostListeners: MapWrapper.createFromPairs([['LKey', 'LVal']]),
hostProperties: MapWrapper.createFromPairs([['PKey', 'PVal']]),
hostActions: MapWrapper.createFromPairs([['AcKey', 'AcVal']]),
hostAttributes: MapWrapper.createFromPairs([['AtKey', 'AtVal']]),
id: 'someComponent',
properties: ['propKey: propVal'],
readAttributes: ['read1', 'read2'],
selector: 'some-comp',
type: RenderDirectiveMetadata.COMPONENT_TYPE,
exportAs: 'aaa',
callOnDestroy: true,
callOnChange: true,
callOnCheck: true,
callOnInit: true,
callOnAllChangesDone: true,
events: ['onFoo', 'onBar'],
changeDetection: 'CHECK_ONCE'
});
var map = directiveMetadataToMap(someComponent);
expect(map.get('compileChildren')).toEqual(false);
expect(map.get('hostListeners')).toEqual(MapWrapper.createFromPairs([['LKey', 'LVal']]));
expect(map.get('hostProperties')).toEqual(MapWrapper.createFromPairs([['PKey', 'PVal']]));
expect(map.get('hostActions')).toEqual(MapWrapper.createFromPairs([['AcKey', 'AcVal']]));
expect(map.get('hostAttributes')).toEqual(MapWrapper.createFromPairs([['AtKey', 'AtVal']]));
expect(map.get('id')).toEqual('someComponent');
expect(map.get('properties')).toEqual(['propKey: propVal']);
expect(map.get('readAttributes')).toEqual(['read1', 'read2']);
expect(map.get('selector')).toEqual('some-comp');
expect(map.get('type')).toEqual(RenderDirectiveMetadata.COMPONENT_TYPE);
expect(map.get('callOnDestroy')).toEqual(true);
expect(map.get('callOnCheck')).toEqual(true);
expect(map.get('callOnChange')).toEqual(true);
expect(map.get('callOnInit')).toEqual(true);
expect(map.get('callOnAllChangesDone')).toEqual(true);
expect(map.get('exportAs')).toEqual('aaa');
expect(map.get('events')).toEqual(['onFoo', 'onBar']);
expect(map.get('changeDetection')).toEqual('CHECK_ONCE');
});
it('mapToDirectiveMetadata', () => {
var map = MapWrapper.createFromPairs([
['compileChildren', false],
['hostProperties', MapWrapper.createFromPairs([['PKey', 'testVal']])],
['hostListeners', MapWrapper.createFromPairs([['LKey', 'testVal']])],
['hostActions', MapWrapper.createFromPairs([['AcKey', 'testVal']])],
['hostAttributes', MapWrapper.createFromPairs([['AtKey', 'testVal']])],
['id', 'testId'],
['properties', ['propKey: propVal']],
['readAttributes', ['readTest1', 'readTest2']],
['selector', 'testSelector'],
['type', RenderDirectiveMetadata.DIRECTIVE_TYPE],
['exportAs', 'aaa'],
['callOnDestroy', true],
['callOnCheck', true],
['callOnInit', true],
['callOnChange', true],
['callOnAllChangesDone', true],
['events', ['onFoo', 'onBar']],
['changeDetection', 'CHECK_ONCE']
]);
var meta = directiveMetadataFromMap(map);
expect(meta.compileChildren).toEqual(false);
expect(meta.hostProperties).toEqual(MapWrapper.createFromPairs([['PKey', 'testVal']]));
expect(meta.hostListeners).toEqual(MapWrapper.createFromPairs([['LKey', 'testVal']]));
expect(meta.hostActions).toEqual(MapWrapper.createFromPairs([['AcKey', 'testVal']]));
expect(meta.hostAttributes).toEqual(MapWrapper.createFromPairs([['AtKey', 'testVal']]));
expect(meta.id).toEqual('testId');
expect(meta.properties).toEqual(['propKey: propVal']);
expect(meta.readAttributes).toEqual(['readTest1', 'readTest2']);
expect(meta.selector).toEqual('testSelector');
expect(meta.type).toEqual(RenderDirectiveMetadata.DIRECTIVE_TYPE);
expect(meta.exportAs).toEqual('aaa');
expect(meta.callOnDestroy).toEqual(true);
expect(meta.callOnCheck).toEqual(true);
expect(meta.callOnInit).toEqual(true);
expect(meta.callOnChange).toEqual(true);
expect(meta.callOnAllChangesDone).toEqual(true);
expect(meta.events).toEqual(['onFoo', 'onBar']);
expect(meta.changeDetection).toEqual('CHECK_ONCE');
});
});
}

View File

@ -15,8 +15,7 @@ import {
ChangeDetectorGenConfig, ChangeDetectorGenConfig,
BindingRecord, BindingRecord,
DirectiveRecord, DirectiveRecord,
DirectiveIndex, DirectiveIndex
DEFAULT
} from 'angular2/src/core/change_detection/change_detection'; } from 'angular2/src/core/change_detection/change_detection';

View File

@ -5,7 +5,7 @@ import "package:angular2/src/core/facade/collection.dart"
import "common.dart" import "common.dart"
show Company, Opportunity, Offering, Account, CustomDate, STATUS_LIST; show Company, Opportunity, Offering, Account, CustomDate, STATUS_LIST;
import "package:angular2/directives.dart" show NgFor; import "package:angular2/directives.dart" show NgFor;
import "package:angular2/angular2.dart" show Component, Directive, View; import "package:angular2/angular2.dart" show Component, Directive, View, ChangeDetectionStrategy;
class HasStyle { class HasStyle {
int cellWidth; int cellWidth;
@ -17,7 +17,7 @@ class HasStyle {
@Component( @Component(
selector: "company-name", selector: "company-name",
properties: const ["width: cell-width", "company"], properties: const ["width: cell-width", "company"],
changeDetection: "ON_PUSH_OBSERVE" changeDetection: ChangeDetectionStrategy.OnPushObserve
) )
@View( @View(
directives: const [], directives: const [],
@ -29,7 +29,7 @@ class CompanyNameComponent extends HasStyle {
@Component( @Component(
selector: "opportunity-name", selector: "opportunity-name",
properties: const ["width: cell-width", "opportunity"], properties: const ["width: cell-width", "opportunity"],
changeDetection: "ON_PUSH_OBSERVE" changeDetection: ChangeDetectionStrategy.OnPushObserve
) )
@View( @View(
directives: const [], directives: const [],
@ -41,7 +41,7 @@ class OpportunityNameComponent extends HasStyle {
@Component( @Component(
selector: "offering-name", selector: "offering-name",
properties: const ["width: cell-width", "offering"], properties: const ["width: cell-width", "offering"],
changeDetection: "ON_PUSH_OBSERVE" changeDetection: ChangeDetectionStrategy.OnPushObserve
) )
@View( @View(
directives: const [], directives: const [],
@ -59,7 +59,7 @@ class Stage {
@Component( @Component(
selector: "stage-buttons", selector: "stage-buttons",
properties: const ["width: cell-width", "offering"], properties: const ["width: cell-width", "offering"],
changeDetection: "ON_PUSH_OBSERVE" changeDetection: ChangeDetectionStrategy.OnPushObserve
) )
@View(directives: const [NgFor], template: ''' @View(directives: const [NgFor], template: '''
<div [style.width.px]="cellWidth"> <div [style.width.px]="cellWidth">
@ -103,7 +103,7 @@ class StageButtonsComponent extends HasStyle {
@Component( @Component(
selector: "account-cell", selector: "account-cell",
properties: const ["width: cell-width", "account"], properties: const ["width: cell-width", "account"],
changeDetection: "ON_PUSH_OBSERVE" changeDetection: ChangeDetectionStrategy.OnPushObserve
) )
@View(directives: const [], template: ''' @View(directives: const [], template: '''
<div [style.width.px]="cellWidth"> <div [style.width.px]="cellWidth">
@ -117,7 +117,7 @@ class AccountCellComponent extends HasStyle {
@Component( @Component(
selector: "formatted-cell", selector: "formatted-cell",
properties: const ["width: cell-width", "value"], properties: const ["width: cell-width", "value"],
changeDetection: "ON_PUSH_OBSERVE" changeDetection: ChangeDetectionStrategy.OnPushObserve
) )
@View( @View(
directives: const [], directives: const [],

View File

@ -2,7 +2,7 @@ library benchmarks.src.naive_infinite_scroll.scroll_area;
import "package:angular2/src/core/facade/collection.dart" show ListWrapper; import "package:angular2/src/core/facade/collection.dart" show ListWrapper;
import "package:angular2/src/core/facade/math.dart" show Math; import "package:angular2/src/core/facade/math.dart" show Math;
import "package:angular2/angular2.dart" show Component, Directive, View; import "package:angular2/angular2.dart" show Component, Directive, View, ChangeDetectionStrategy;
import "common.dart" import "common.dart"
show show
Offering, Offering,
@ -16,7 +16,7 @@ import "random_data.dart" show generateOfferings;
import "scroll_item.dart" show ScrollItemComponent; import "scroll_item.dart" show ScrollItemComponent;
import "package:angular2/directives.dart" show NgFor; import "package:angular2/directives.dart" show NgFor;
@Component(selector: "scroll-area", changeDetection: "ON_PUSH_OBSERVE") @Component(selector: "scroll-area", changeDetection: ChangeDetectionStrategy.OnPushObserve)
@View(directives: const [ScrollItemComponent, NgFor], template: ''' @View(directives: const [ScrollItemComponent, NgFor], template: '''
<div> <div>
<div id="scrollDiv" <div id="scrollDiv"

View File

@ -8,7 +8,7 @@ import "cells.dart"
StageButtonsComponent, StageButtonsComponent,
AccountCellComponent, AccountCellComponent,
FormattedCellComponent; FormattedCellComponent;
import "package:angular2/angular2.dart" show Component, Directive, View; import "package:angular2/angular2.dart" show Component, Directive, View, ChangeDetectionStrategy;
import "common.dart" import "common.dart"
show show
Offering, Offering,
@ -25,7 +25,8 @@ import "common.dart"
END_DATE_WIDTH, END_DATE_WIDTH,
AAT_STATUS_WIDTH; AAT_STATUS_WIDTH;
@Component(selector: "scroll-item", properties: const ["offering"], changeDetection: "ON_PUSH_OBSERVE") @Component(selector: "scroll-item", properties: const ["offering"],
changeDetection: ChangeDetectionStrategy.OnPushObserve)
@View( @View(
directives: const [ directives: const [
CompanyNameComponent, CompanyNameComponent,

View File

@ -0,0 +1,71 @@
library angular2.transform.common.convert;
import "package:angular2/src/core/facade/collection.dart"
show ListWrapper, MapWrapper;
import "package:angular2/src/core/facade/lang.dart" show isPresent, isArray;
import "package:angular2/src/core/render/api.dart" show RenderDirectiveMetadata;
import "package:angular2/src/core/change_detection/change_detection.dart"
show ChangeDetectionStrategy;
/**
* Converts a [DirectiveMetadata] to a map representation. This creates a copy,
* that is, subsequent changes to `meta` will not be mirrored in the map.
*/
Map<String, dynamic> directiveMetadataToMap(RenderDirectiveMetadata meta) {
return MapWrapper.createFromPairs([
["id", meta.id],
["selector", meta.selector],
["compileChildren", meta.compileChildren],
["hostProperties", _cloneIfPresent(meta.hostProperties)],
["hostListeners", _cloneIfPresent(meta.hostListeners)],
["hostAttributes", _cloneIfPresent(meta.hostAttributes)],
["properties", _cloneIfPresent(meta.properties)],
["readAttributes", _cloneIfPresent(meta.readAttributes)],
["type", meta.type],
["exportAs", meta.exportAs],
["callOnDestroy", meta.callOnDestroy],
["callOnCheck", meta.callOnCheck],
["callOnInit", meta.callOnInit],
["callOnChange", meta.callOnChange],
["callOnAllChangesDone", meta.callOnAllChangesDone],
["events", meta.events],
["changeDetection", meta.changeDetection == null ? null : meta.changeDetection.index],
["version", 1]
]);
}
/**
* Converts a map representation of [DirectiveMetadata] into a
* [DirectiveMetadata] object. This creates a copy, that is, subsequent changes
* to `map` will not be mirrored in the [DirectiveMetadata] object.
*/
RenderDirectiveMetadata directiveMetadataFromMap(Map<String, dynamic> map) {
return new RenderDirectiveMetadata(
id: (map["id"] as String),
selector: (map["selector"] as String),
compileChildren: (map["compileChildren"] as bool),
hostProperties: (_cloneIfPresent(
map["hostProperties"]) as Map<String, String>),
hostListeners: (_cloneIfPresent(
map["hostListeners"]) as Map<String, String>),
hostAttributes: (_cloneIfPresent(
map["hostAttributes"]) as Map<String, String>),
properties: (_cloneIfPresent(map["properties"]) as List<String>),
readAttributes: (_cloneIfPresent(map["readAttributes"]) as List<String>),
type: (map["type"] as num),
exportAs: (map["exportAs"] as String),
callOnDestroy: (map["callOnDestroy"] as bool),
callOnCheck: (map["callOnCheck"] as bool),
callOnChange: (map["callOnChange"] as bool),
callOnInit: (map["callOnInit"] as bool),
callOnAllChangesDone: (map["callOnAllChangesDone"] as bool),
events: (_cloneIfPresent(map["events"]) as List<String>),
changeDetection: map["changeDetection"] == null ? null
: ChangeDetectionStrategy.values[map["changeDetection"] as int]);
}
/**
* Clones the [List] or [Map] `o` if it is present.
*/
dynamic _cloneIfPresent(o) {
if (!isPresent(o)) return null;
return isArray(o) ? ListWrapper.clone(o) : MapWrapper.clone(o);
}

View File

@ -3,6 +3,7 @@ library angular2.transform.common.directive_metadata_reader;
import 'package:analyzer/analyzer.dart'; import 'package:analyzer/analyzer.dart';
import 'package:analyzer/src/generated/element.dart'; import 'package:analyzer/src/generated/element.dart';
import 'package:angular2/src/core/render/api.dart'; import 'package:angular2/src/core/render/api.dart';
import 'package:angular2/src/core/change_detection/change_detection.dart';
/// Reads [RenderDirectiveMetadata] from the `node`. `node` is expected to be an /// Reads [RenderDirectiveMetadata] from the `node`. `node` is expected to be an
/// instance of [Annotation], [NodeList<Annotation>], ListLiteral, or /// instance of [Annotation], [NodeList<Annotation>], ListLiteral, or
@ -63,7 +64,7 @@ class _DirectiveMetadataVisitor extends Object
bool _callOnCheck; bool _callOnCheck;
bool _callOnInit; bool _callOnInit;
bool _callOnAllChangesDone; bool _callOnAllChangesDone;
String _changeDetection; ChangeDetectionStrategy _changeDetection;
List<String> _events; List<String> _events;
final ConstantEvaluator _evaluator = new ConstantEvaluator(); final ConstantEvaluator _evaluator = new ConstantEvaluator();
@ -283,6 +284,9 @@ class _DirectiveMetadataVisitor extends Object
void _populateChangeDetection(Expression value) { void _populateChangeDetection(Expression value) {
_checkMeta(); _checkMeta();
_changeDetection = _expressionToString(value, 'Directive#changeDetection'); _changeDetection = changeDetectionStrategies[value.toSource()];
} }
} }
final Map<String, ChangeDetectionStrategy> changeDetectionStrategies
= new Map.fromIterable(ChangeDetectionStrategy.values, key: (v) => v.toString());

View File

@ -1,7 +1,7 @@
library angular2.transform.common.ng_meta; library angular2.transform.common.ng_meta;
import 'package:angular2/src/core/render/api.dart'; import 'package:angular2/src/core/render/api.dart';
import 'package:angular2/src/core/render/dom/convert.dart'; import 'convert.dart';
import 'logging.dart'; import 'logging.dart';
/// Metadata about directives and directive aliases. /// Metadata about directives and directive aliases.

View File

@ -1,5 +1,6 @@
library angular2.transform.template_compiler.change_detector_codegen; library angular2.transform.template_compiler.change_detector_codegen;
import 'package:angular2/src/core/change_detection/change_detection.dart';
import 'package:angular2/src/core/change_detection/change_detection_util.dart'; import 'package:angular2/src/core/change_detection/change_detection_util.dart';
import 'package:angular2/src/core/change_detection/codegen_facade.dart'; import 'package:angular2/src/core/change_detection/codegen_facade.dart';
import 'package:angular2/src/core/change_detection/codegen_logic_util.dart'; import 'package:angular2/src/core/change_detection/codegen_logic_util.dart';
@ -75,7 +76,7 @@ class _CodegenState {
/// The name of the generated change detector class. This is an implementation /// The name of the generated change detector class. This is an implementation
/// detail and should not be visible to users. /// detail and should not be visible to users.
final String _changeDetectorTypeName; final String _changeDetectorTypeName;
final String _changeDetectionStrategy; final ChangeDetectionStrategy _changeDetectionStrategy;
final List<DirectiveRecord> _directiveRecords; final List<DirectiveRecord> _directiveRecords;
final List<ProtoRecord> _records; final List<ProtoRecord> _records;
final List<EventBinding> _eventBindings; final List<EventBinding> _eventBindings;
@ -84,6 +85,9 @@ class _CodegenState {
final ChangeDetectorGenConfig _genConfig; final ChangeDetectorGenConfig _genConfig;
final List<BindingTarget> _propertyBindingTargets; final List<BindingTarget> _propertyBindingTargets;
String get _changeDetectionStrategyAsCode =>
_changeDetectionStrategy == null ? 'null' : '${_GEN_PREFIX}.${_changeDetectionStrategy}';
_CodegenState._( _CodegenState._(
this._changeDetectorDefId, this._changeDetectorDefId,
this._contextTypeName, this._contextTypeName,
@ -129,7 +133,7 @@ class _CodegenState {
dispatcher, ${_records.length}, dispatcher, ${_records.length},
${_changeDetectorTypeName}.gen_propertyBindingTargets, ${_changeDetectorTypeName}.gen_propertyBindingTargets,
${_changeDetectorTypeName}.gen_directiveIndices, ${_changeDetectorTypeName}.gen_directiveIndices,
${codify(_changeDetectionStrategy)}) { ${_changeDetectionStrategyAsCode}) {
dehydrateDirectives(false); dehydrateDirectives(false);
} }

View File

@ -0,0 +1,97 @@
library angular2.test.transform.common.convert_spec;
import "package:angular2/src/core/facade/collection.dart" show MapWrapper;
import "package:angular2/src/core/render/api.dart" show RenderDirectiveMetadata;
import "package:angular2/src/transform/common/convert.dart"
show directiveMetadataFromMap, directiveMetadataToMap;
import "package:angular2/test_lib.dart" show ddescribe, describe, expect, it;
import "package:angular2/src/core/change_detection/change_detection.dart"
show ChangeDetectionStrategy;
main() {
describe("convert", () {
it("directiveMetadataToMap", () {
var someComponent = new RenderDirectiveMetadata(
compileChildren: false,
hostListeners: MapWrapper.createFromPairs([["LKey", "LVal"]]),
hostProperties: MapWrapper.createFromPairs([["PKey", "PVal"]]),
hostAttributes: MapWrapper.createFromPairs([["AtKey", "AtVal"]]),
id: "someComponent",
properties: ["propKey: propVal"],
readAttributes: ["read1", "read2"],
selector: "some-comp",
type: RenderDirectiveMetadata.COMPONENT_TYPE,
exportAs: "aaa",
callOnDestroy: true,
callOnChange: true,
callOnCheck: true,
callOnInit: true,
callOnAllChangesDone: true,
events: ["onFoo", "onBar"],
changeDetection: ChangeDetectionStrategy.CheckOnce);
var map = directiveMetadataToMap(someComponent);
expect(map["compileChildren"]).toEqual(false);
expect(map["hostListeners"])
.toEqual(MapWrapper.createFromPairs([["LKey", "LVal"]]));
expect(map["hostProperties"])
.toEqual(MapWrapper.createFromPairs([["PKey", "PVal"]]));
expect(map["hostAttributes"])
.toEqual(MapWrapper.createFromPairs([["AtKey", "AtVal"]]));
expect(map["id"]).toEqual("someComponent");
expect(map["properties"]).toEqual(["propKey: propVal"]);
expect(map["readAttributes"]).toEqual(["read1", "read2"]);
expect(map["selector"]).toEqual("some-comp");
expect(map["type"]).toEqual(RenderDirectiveMetadata.COMPONENT_TYPE);
expect(map["callOnDestroy"]).toEqual(true);
expect(map["callOnCheck"]).toEqual(true);
expect(map["callOnChange"]).toEqual(true);
expect(map["callOnInit"]).toEqual(true);
expect(map["callOnAllChangesDone"]).toEqual(true);
expect(map["exportAs"]).toEqual("aaa");
expect(map["events"]).toEqual(["onFoo", "onBar"]);
expect(map["changeDetection"]).toEqual(ChangeDetectionStrategy.CheckOnce.index);
});
it("mapToDirectiveMetadata", () {
var map = MapWrapper.createFromPairs([
["compileChildren", false],
["hostProperties", MapWrapper.createFromPairs([["PKey", "testVal"]])],
["hostListeners", MapWrapper.createFromPairs([["LKey", "testVal"]])],
["hostAttributes", MapWrapper.createFromPairs([["AtKey", "testVal"]])],
["id", "testId"],
["properties", ["propKey: propVal"]],
["readAttributes", ["readTest1", "readTest2"]],
["selector", "testSelector"],
["type", RenderDirectiveMetadata.DIRECTIVE_TYPE],
["exportAs", "aaa"],
["callOnDestroy", true],
["callOnCheck", true],
["callOnInit", true],
["callOnChange", true],
["callOnAllChangesDone", true],
["events", ["onFoo", "onBar"]],
["changeDetection", ChangeDetectionStrategy.CheckOnce.index]
]);
var meta = directiveMetadataFromMap(map);
expect(meta.compileChildren).toEqual(false);
expect(meta.hostProperties)
.toEqual(MapWrapper.createFromPairs([["PKey", "testVal"]]));
expect(meta.hostListeners)
.toEqual(MapWrapper.createFromPairs([["LKey", "testVal"]]));
expect(meta.hostAttributes)
.toEqual(MapWrapper.createFromPairs([["AtKey", "testVal"]]));
expect(meta.id).toEqual("testId");
expect(meta.properties).toEqual(["propKey: propVal"]);
expect(meta.readAttributes).toEqual(["readTest1", "readTest2"]);
expect(meta.selector).toEqual("testSelector");
expect(meta.type).toEqual(RenderDirectiveMetadata.DIRECTIVE_TYPE);
expect(meta.exportAs).toEqual("aaa");
expect(meta.callOnDestroy).toEqual(true);
expect(meta.callOnCheck).toEqual(true);
expect(meta.callOnInit).toEqual(true);
expect(meta.callOnChange).toEqual(true);
expect(meta.callOnAllChangesDone).toEqual(true);
expect(meta.events).toEqual(["onFoo", "onBar"]);
expect(meta.changeDetection).toEqual(ChangeDetectionStrategy.CheckOnce);
});
});
}

View File

@ -2,7 +2,8 @@ library angular2.test.transform.directive_metadata_extractor.all_tests;
import 'dart:async'; import 'dart:async';
import 'package:angular2/src/core/render/api.dart'; import 'package:angular2/src/core/render/api.dart';
import 'package:angular2/src/core/render/dom/convert.dart'; import 'package:angular2/src/core/change_detection/change_detection.dart';
import 'package:angular2/src/transform/common/convert.dart';
import 'package:angular2/src/transform/common/directive_metadata_reader.dart'; import 'package:angular2/src/transform/common/directive_metadata_reader.dart';
import 'package:angular2/src/transform/common/logging.dart'; import 'package:angular2/src/transform/common/logging.dart';
import 'package:angular2/src/transform/common/ng_deps.dart'; import 'package:angular2/src/transform/common/ng_deps.dart';
@ -122,7 +123,7 @@ void allTests() {
it('should parse changeDetection.', () async { it('should parse changeDetection.', () async {
var metadata = await readMetadata('directive_metadata_extractor/' var metadata = await readMetadata('directive_metadata_extractor/'
'directive_metadata_files/changeDetection.ng_deps.dart'); 'directive_metadata_files/changeDetection.ng_deps.dart');
expect(metadata.changeDetection).toEqual('CHECK_ONCE'); expect(metadata.changeDetection).toEqual(ChangeDetectionStrategy.CheckOnce);
}); });
it('should fail when a class is annotated with multiple Directives.', it('should fail when a class is annotated with multiple Directives.',

View File

@ -2,7 +2,7 @@ library examples.hello_world.index_common_dart.ng_deps.dart;
import 'hello.dart'; import 'hello.dart';
import 'package:angular2/angular2.dart' import 'package:angular2/angular2.dart'
show Component, Directive, View, NgElement, LifecycleEvent; show Component, Directive, View, NgElement, LifecycleEvent, ChangeDetectionStrategy;
var _visited = false; var _visited = false;
void initReflector(reflector) { void initReflector(reflector) {
@ -12,7 +12,7 @@ void initReflector(reflector) {
..registerType( ..registerType(
HelloCmp, HelloCmp,
new ReflectionInfo( new ReflectionInfo(
const [const Component(changeDetection: 'CHECK_ONCE')], const [const Component(changeDetection: ChangeDetectionStrategy.CheckOnce)],
const [const []], const [const []],
() => new HelloCmp())); () => new HelloCmp()));
} }