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

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

View File

@ -48,7 +48,7 @@ export {
DebugContext,
ChangeDetectorGenConfig
} 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 {BindingRecord, BindingTarget} from './binding_record';
export {DirectiveIndex, DirectiveRecord} from './directive_record';

View File

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

View File

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

View File

@ -1,5 +1,5 @@
import {ChangeDetector} from './interfaces';
import {CHECK_ONCE, DETACHED, CHECK_ALWAYS} from './constants';
import {ChangeDetectionStrategy} from './constants';
/**
* Controls change detection.
@ -14,7 +14,7 @@ export class ChangeDetectorRef {
constructor(private _cd: ChangeDetector) {}
/**
* Request to check all ON_PUSH ancestors.
* Request to check all OnPush ancestors.
*/
requestCheck(): void { this._cd.markPathToRootAsCheckOnce(); }
@ -23,7 +23,7 @@ export class ChangeDetectorRef {
*
* 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.
@ -33,7 +33,7 @@ export class ChangeDetectorRef {
* next change detection run.
*/
reattach(): void {
this._cd.mode = CHECK_ALWAYS;
this._cd.mode = ChangeDetectionStrategy.CheckAlways;
this.requestCheck();
}
}

View File

@ -11,14 +11,14 @@ import {codify, combineGeneratedStrings, rawString} from './codegen_facade';
import {ProtoRecord, RecordType} from './proto_record';
import {BindingTarget} from './binding_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.
*/
export class CodegenLogicUtil {
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
@ -119,7 +119,7 @@ export class CodegenLogicUtil {
_observe(exp: string, rec: ProtoRecord): string {
// 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})`;
} else {
return exp;
@ -165,7 +165,7 @@ export class CodegenLogicUtil {
private _genReadDirective(index: number) {
// 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})`;
} else {
return `this.getDirectiveFor(directives, ${index})`;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -33,6 +33,7 @@ import {
} from './metadata/directives';
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 {Type} from 'angular2/src/core/facade/lang';
@ -191,7 +192,7 @@ export interface ComponentFactory {
exportAs?: string,
compileChildren?: boolean,
viewBindings?: List<any>,
changeDetection?: string,
changeDetection?: ChangeDetectionStrategy,
}): ComponentDecorator;
new (obj: {
selector?: string,
@ -203,7 +204,7 @@ export interface ComponentFactory {
exportAs?: string,
compileChildren?: boolean,
viewBindings?: List<any>,
changeDetection?: string,
changeDetection?: ChangeDetectionStrategy,
}): ComponentMetadata;
}

View File

@ -1,7 +1,7 @@
import {CONST, CONST_EXPR} from 'angular2/src/core/facade/lang';
import {List} from 'angular2/src/core/facade/collection';
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.
@ -795,14 +795,12 @@ export class ComponentMetadata extends DirectiveMetadata {
* Defines the used change detection strategy.
*
* When a component is instantiated, Angular creates a change detector, which is responsible for
* propagating
* the component's bindings.
* propagating the component's bindings.
*
* The `changeDetection` property defines, whether the change detection will be checked every time
* or only when the component
* tells it to do so.
* or only when the component tells it to do so.
*/
changeDetection: string;
changeDetection: ChangeDetectionStrategy;
/**
* 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>;
constructor({selector, properties, events, host, exportAs, lifecycle, bindings, viewBindings,
changeDetection = DEFAULT, compileChildren = true}: {
changeDetection = ChangeDetectionStrategy.Default, compileChildren = true}: {
selector?: string,
properties?: List<string>,
events?: List<string>,
@ -857,7 +855,7 @@ export class ComponentMetadata extends DirectiveMetadata {
exportAs?: string,
compileChildren?: boolean,
viewBindings?: List<any>,
changeDetection?: string,
changeDetection?: ChangeDetectionStrategy,
} = {}) {
super({
selector: selector,

View File

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

View File

@ -7,7 +7,10 @@ import {
StringMap,
StringMapWrapper
} 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:
@ -155,7 +158,7 @@ export class RenderDirectiveMetadata {
callOnCheck: boolean;
callOnInit: boolean;
callOnAllChangesDone: boolean;
changeDetection: string;
changeDetection: ChangeDetectionStrategy;
exportAs: string;
hostListeners: Map<string, string>;
hostProperties: Map<string, string>;
@ -185,7 +188,7 @@ export class RenderDirectiveMetadata {
callOnCheck?: boolean,
callOnInit?: boolean,
callOnAllChangesDone?: boolean,
changeDetection?: string,
changeDetection?: ChangeDetectionStrategy,
exportAs?: string
}) {
this.id = id;
@ -224,7 +227,7 @@ export class RenderDirectiveMetadata {
callOnCheck?: boolean,
callOnInit?: boolean,
callOnAllChangesDone?: boolean,
changeDetection?: string,
changeDetection?: ChangeDetectionStrategy,
exportAs?: string
}): RenderDirectiveMetadata {
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);
}