fix(change_detection): fixed reflect properties as attributes
Closes #3761
This commit is contained in:
parent
b6146394ae
commit
a9ce454b21
|
@ -28,4 +28,5 @@ export {
|
||||||
KeyValueDiffers,
|
KeyValueDiffers,
|
||||||
KeyValueDiffer,
|
KeyValueDiffer,
|
||||||
KeyValueDifferFactory
|
KeyValueDifferFactory
|
||||||
|
|
||||||
} from 'angular2/src/change_detection/change_detection';
|
} from 'angular2/src/change_detection/change_detection';
|
||||||
|
|
|
@ -17,6 +17,5 @@ export {
|
||||||
ViewDefinition,
|
ViewDefinition,
|
||||||
DOCUMENT,
|
DOCUMENT,
|
||||||
APP_ID,
|
APP_ID,
|
||||||
DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES,
|
|
||||||
MAX_IN_MEMORY_ELEMENTS_PER_TEMPLATE
|
MAX_IN_MEMORY_ELEMENTS_PER_TEMPLATE
|
||||||
} from './src/render/render';
|
} from './src/render/render';
|
||||||
|
|
|
@ -211,6 +211,10 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
||||||
this.dispatcher.notifyOnBinding(this._currentBinding(), value);
|
this.dispatcher.notifyOnBinding(this._currentBinding(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected logBindingUpdate(value: any): void {
|
||||||
|
this.dispatcher.logBindingUpdate(this._currentBinding(), value);
|
||||||
|
}
|
||||||
|
|
||||||
protected addChange(changes: StringMap<string, any>, oldValue: any,
|
protected addChange(changes: StringMap<string, any>, oldValue: any,
|
||||||
newValue: any): StringMap<string, any> {
|
newValue: any): StringMap<string, any> {
|
||||||
if (isBlank(changes)) {
|
if (isBlank(changes)) {
|
||||||
|
|
|
@ -64,7 +64,8 @@ export class BindingRecord {
|
||||||
|
|
||||||
static createForDirective(ast: AST, propertyName: string, setter: SetterFn,
|
static createForDirective(ast: AST, propertyName: string, setter: SetterFn,
|
||||||
directiveRecord: DirectiveRecord): BindingRecord {
|
directiveRecord: DirectiveRecord): BindingRecord {
|
||||||
var t = new BindingTarget(DIRECTIVE, null, propertyName, null, ast.toString());
|
var elementIndex = directiveRecord.directiveIndex.elementIndex;
|
||||||
|
var t = new BindingTarget(DIRECTIVE, elementIndex, propertyName, null, ast.toString());
|
||||||
return new BindingRecord(DIRECTIVE, t, 0, ast, setter, null, directiveRecord);
|
return new BindingRecord(DIRECTIVE, t, 0, ast, setter, null, directiveRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,8 +84,6 @@ export const defaultKeyValueDiffers = CONST_EXPR(new KeyValueDiffers(keyValDiff)
|
||||||
// dart2js. See https://github.com/dart-lang/sdk/issues/23630 for details.
|
// dart2js. See https://github.com/dart-lang/sdk/issues/23630 for details.
|
||||||
export var preGeneratedProtoDetectors: StringMap<string, Function> = {};
|
export var preGeneratedProtoDetectors: StringMap<string, Function> = {};
|
||||||
|
|
||||||
export const PROTO_CHANGE_DETECTOR = CONST_EXPR(new OpaqueToken('ProtoChangeDetectors'));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements change detection using a map of pregenerated proto detectors.
|
* Implements change detection using a map of pregenerated proto detectors.
|
||||||
*/
|
*/
|
||||||
|
@ -93,14 +91,19 @@ export const PROTO_CHANGE_DETECTOR = CONST_EXPR(new OpaqueToken('ProtoChangeDete
|
||||||
export class PreGeneratedChangeDetection extends ChangeDetection {
|
export class PreGeneratedChangeDetection extends ChangeDetection {
|
||||||
_dynamicChangeDetection: ChangeDetection;
|
_dynamicChangeDetection: ChangeDetection;
|
||||||
_protoChangeDetectorFactories: StringMap<string, Function>;
|
_protoChangeDetectorFactories: StringMap<string, Function>;
|
||||||
|
_genConfig: ChangeDetectorGenConfig;
|
||||||
|
|
||||||
constructor(@Inject(PROTO_CHANGE_DETECTOR) @Optional() protoChangeDetectorsForTest?:
|
constructor(config?: ChangeDetectorGenConfig,
|
||||||
StringMap<string, Function>) {
|
protoChangeDetectorsForTest?: StringMap<string, Function>) {
|
||||||
super();
|
super();
|
||||||
this._dynamicChangeDetection = new DynamicChangeDetection();
|
this._dynamicChangeDetection = new DynamicChangeDetection();
|
||||||
this._protoChangeDetectorFactories = isPresent(protoChangeDetectorsForTest) ?
|
this._protoChangeDetectorFactories = isPresent(protoChangeDetectorsForTest) ?
|
||||||
protoChangeDetectorsForTest :
|
protoChangeDetectorsForTest :
|
||||||
preGeneratedProtoDetectors;
|
preGeneratedProtoDetectors;
|
||||||
|
|
||||||
|
this._genConfig =
|
||||||
|
isPresent(config) ? config : new ChangeDetectorGenConfig(assertionsEnabled(),
|
||||||
|
assertionsEnabled(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static isSupported(): boolean { return PregenProtoChangeDetector.isSupported(); }
|
static isSupported(): boolean { return PregenProtoChangeDetector.isSupported(); }
|
||||||
|
@ -112,11 +115,8 @@ export class PreGeneratedChangeDetection extends ChangeDetection {
|
||||||
return this._dynamicChangeDetection.getProtoChangeDetector(id, definition);
|
return this._dynamicChangeDetection.getProtoChangeDetector(id, definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get genConfig(): ChangeDetectorGenConfig { return this._genConfig; }
|
||||||
get generateDetectors(): boolean { return true; }
|
get generateDetectors(): boolean { return true; }
|
||||||
|
|
||||||
get genConfig(): ChangeDetectorGenConfig {
|
|
||||||
return new ChangeDetectorGenConfig(assertionsEnabled(), assertionsEnabled());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -127,15 +127,21 @@ export class PreGeneratedChangeDetection extends ChangeDetection {
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DynamicChangeDetection extends ChangeDetection {
|
export class DynamicChangeDetection extends ChangeDetection {
|
||||||
|
_genConfig: ChangeDetectorGenConfig;
|
||||||
|
|
||||||
|
constructor(config?: ChangeDetectorGenConfig) {
|
||||||
|
super();
|
||||||
|
this._genConfig =
|
||||||
|
isPresent(config) ? config : new ChangeDetectorGenConfig(assertionsEnabled(),
|
||||||
|
assertionsEnabled(), false);
|
||||||
|
}
|
||||||
|
|
||||||
getProtoChangeDetector(id: string, definition: ChangeDetectorDefinition): ProtoChangeDetector {
|
getProtoChangeDetector(id: string, definition: ChangeDetectorDefinition): ProtoChangeDetector {
|
||||||
return new DynamicProtoChangeDetector(definition);
|
return new DynamicProtoChangeDetector(definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get genConfig(): ChangeDetectorGenConfig { return this._genConfig; }
|
||||||
get generateDetectors(): boolean { return true; }
|
get generateDetectors(): boolean { return true; }
|
||||||
|
|
||||||
get genConfig(): ChangeDetectorGenConfig {
|
|
||||||
return new ChangeDetectorGenConfig(assertionsEnabled(), assertionsEnabled());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -145,17 +151,21 @@ export class DynamicChangeDetection extends ChangeDetection {
|
||||||
* {@link DynamicChangeDetection} and {@link PreGeneratedChangeDetection}.
|
* {@link DynamicChangeDetection} and {@link PreGeneratedChangeDetection}.
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@CONST()
|
|
||||||
export class JitChangeDetection extends ChangeDetection {
|
export class JitChangeDetection extends ChangeDetection {
|
||||||
|
_genConfig: ChangeDetectorGenConfig;
|
||||||
|
constructor(config?: ChangeDetectorGenConfig) {
|
||||||
|
super();
|
||||||
|
this._genConfig =
|
||||||
|
isPresent(config) ? config : new ChangeDetectorGenConfig(assertionsEnabled(),
|
||||||
|
assertionsEnabled(), false);
|
||||||
|
}
|
||||||
|
|
||||||
static isSupported(): boolean { return JitProtoChangeDetector.isSupported(); }
|
static isSupported(): boolean { return JitProtoChangeDetector.isSupported(); }
|
||||||
|
|
||||||
getProtoChangeDetector(id: string, definition: ChangeDetectorDefinition): ProtoChangeDetector {
|
getProtoChangeDetector(id: string, definition: ChangeDetectorDefinition): ProtoChangeDetector {
|
||||||
return new JitProtoChangeDetector(definition);
|
return new JitProtoChangeDetector(definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get genConfig(): ChangeDetectorGenConfig { return this._genConfig; }
|
||||||
get generateDetectors(): boolean { return true; }
|
get generateDetectors(): boolean { return true; }
|
||||||
|
|
||||||
get genConfig(): ChangeDetectorGenConfig {
|
|
||||||
return new ChangeDetectorGenConfig(assertionsEnabled(), assertionsEnabled());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,6 @@ export class ChangeDetectorJITGenerator {
|
||||||
return new ${this._typeName}(dispatcher);
|
return new ${this._typeName}(dispatcher);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return new Function(ABSTRACT_CHANGE_DETECTOR, UTIL, classDefinition)(AbstractChangeDetector,
|
return new Function(ABSTRACT_CHANGE_DETECTOR, UTIL, classDefinition)(AbstractChangeDetector,
|
||||||
ChangeDetectionUtil);
|
ChangeDetectionUtil);
|
||||||
}
|
}
|
||||||
|
@ -301,6 +300,7 @@ export class ChangeDetectorJITGenerator {
|
||||||
|
|
||||||
var newValue = this._names.getLocalName(r.selfIndex);
|
var newValue = this._names.getLocalName(r.selfIndex);
|
||||||
var oldValue = this._names.getFieldName(r.selfIndex);
|
var oldValue = this._names.getFieldName(r.selfIndex);
|
||||||
|
var notifyDebug = this.genConfig.logBindingUpdate ? `this.logBindingUpdate(${newValue});` : "";
|
||||||
|
|
||||||
var br = r.bindingRecord;
|
var br = r.bindingRecord;
|
||||||
if (br.target.isDirective()) {
|
if (br.target.isDirective()) {
|
||||||
|
@ -309,12 +309,14 @@ export class ChangeDetectorJITGenerator {
|
||||||
return `
|
return `
|
||||||
${this._genThrowOnChangeCheck(oldValue, newValue)}
|
${this._genThrowOnChangeCheck(oldValue, newValue)}
|
||||||
${directiveProperty} = ${newValue};
|
${directiveProperty} = ${newValue};
|
||||||
|
${notifyDebug}
|
||||||
${IS_CHANGED_LOCAL} = true;
|
${IS_CHANGED_LOCAL} = true;
|
||||||
`;
|
`;
|
||||||
} else {
|
} else {
|
||||||
return `
|
return `
|
||||||
${this._genThrowOnChangeCheck(oldValue, newValue)}
|
${this._genThrowOnChangeCheck(oldValue, newValue)}
|
||||||
this.notifyDispatcher(${newValue});
|
this.notifyDispatcher(${newValue});
|
||||||
|
${notifyDebug}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,6 +179,10 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
|
||||||
var directiveIndex = bindingRecord.directiveRecord.directiveIndex;
|
var directiveIndex = bindingRecord.directiveRecord.directiveIndex;
|
||||||
bindingRecord.setter(this._getDirectiveFor(directiveIndex), change.currentValue);
|
bindingRecord.setter(this._getDirectiveFor(directiveIndex), change.currentValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.genConfig.logBindingUpdate) {
|
||||||
|
super.logBindingUpdate(change.currentValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_addChange(bindingRecord: BindingRecord, change, changes) {
|
_addChange(bindingRecord: BindingRecord, change, changes) {
|
||||||
|
|
|
@ -27,7 +27,7 @@ import {ChangeDetectorRef} from './change_detector_ref';
|
||||||
*
|
*
|
||||||
* # Example
|
* # Example
|
||||||
* ```javascript
|
* ```javascript
|
||||||
* bootstrap(MyApp, [bind(ChangeDetection).toClass(DynamicChangeDetection)]);
|
* bootstrap(MyApp, [bind(ChangeDetection).toValue(new DynamicChangeDetection())]);
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@CONST()
|
@CONST()
|
||||||
|
@ -49,6 +49,7 @@ export class DebugContext {
|
||||||
export interface ChangeDispatcher {
|
export interface ChangeDispatcher {
|
||||||
getDebugContext(elementIndex: number, directiveIndex: DirectiveIndex): DebugContext;
|
getDebugContext(elementIndex: number, directiveIndex: DirectiveIndex): DebugContext;
|
||||||
notifyOnBinding(bindingTarget: BindingTarget, value: any): void;
|
notifyOnBinding(bindingTarget: BindingTarget, value: any): void;
|
||||||
|
logBindingUpdate(bindingTarget: BindingTarget, value: any): void;
|
||||||
notifyOnAllChangesDone(): void;
|
notifyOnAllChangesDone(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +75,8 @@ export interface ChangeDetector {
|
||||||
export interface ProtoChangeDetector { instantiate(dispatcher: ChangeDispatcher): ChangeDetector; }
|
export interface ProtoChangeDetector { instantiate(dispatcher: ChangeDispatcher): ChangeDetector; }
|
||||||
|
|
||||||
export class ChangeDetectorGenConfig {
|
export class ChangeDetectorGenConfig {
|
||||||
constructor(public genCheckNoChanges: boolean, public genDebugInfo: boolean) {}
|
constructor(public genCheckNoChanges: boolean, public genDebugInfo: boolean,
|
||||||
|
public logBindingUpdate: boolean) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ChangeDetectorDefinition {
|
export class ChangeDetectorDefinition {
|
||||||
|
|
|
@ -60,7 +60,6 @@ import {Renderer, RenderCompiler} from 'angular2/src/render/api';
|
||||||
import {
|
import {
|
||||||
DomRenderer,
|
DomRenderer,
|
||||||
DOCUMENT,
|
DOCUMENT,
|
||||||
DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES,
|
|
||||||
DefaultDomCompiler,
|
DefaultDomCompiler,
|
||||||
APP_ID_RANDOM_BINDING,
|
APP_ID_RANDOM_BINDING,
|
||||||
MAX_IN_MEMORY_ELEMENTS_PER_TEMPLATE,
|
MAX_IN_MEMORY_ELEMENTS_PER_TEMPLATE,
|
||||||
|
@ -84,16 +83,15 @@ var _rootInjector: Injector;
|
||||||
var _rootBindings = [bind(Reflector).toValue(reflector), TestabilityRegistry];
|
var _rootBindings = [bind(Reflector).toValue(reflector), TestabilityRegistry];
|
||||||
|
|
||||||
function _injectorBindings(appComponentType): List<Type | Binding | List<any>> {
|
function _injectorBindings(appComponentType): List<Type | Binding | List<any>> {
|
||||||
var bestChangeDetection: Type = DynamicChangeDetection;
|
var bestChangeDetection = new DynamicChangeDetection();
|
||||||
if (PreGeneratedChangeDetection.isSupported()) {
|
if (PreGeneratedChangeDetection.isSupported()) {
|
||||||
bestChangeDetection = PreGeneratedChangeDetection;
|
bestChangeDetection = new PreGeneratedChangeDetection();
|
||||||
} else if (JitChangeDetection.isSupported()) {
|
} else if (JitChangeDetection.isSupported()) {
|
||||||
bestChangeDetection = JitChangeDetection;
|
bestChangeDetection = new JitChangeDetection();
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
bind(DOCUMENT)
|
bind(DOCUMENT)
|
||||||
.toValue(DOM.defaultDoc()),
|
.toValue(DOM.defaultDoc()),
|
||||||
bind(DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES).toValue(false),
|
|
||||||
bind(APP_COMPONENT).toValue(appComponentType),
|
bind(APP_COMPONENT).toValue(appComponentType),
|
||||||
bind(APP_COMPONENT_REF_PROMISE)
|
bind(APP_COMPONENT_REF_PROMISE)
|
||||||
.toFactory(
|
.toFactory(
|
||||||
|
@ -141,7 +139,7 @@ function _injectorBindings(appComponentType): List<Type | Binding | List<any>> {
|
||||||
DEFAULT_PIPES,
|
DEFAULT_PIPES,
|
||||||
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
||||||
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
||||||
bind(ChangeDetection).toClass(bestChangeDetection),
|
bind(ChangeDetection).toValue(bestChangeDetection),
|
||||||
ViewLoader,
|
ViewLoader,
|
||||||
DirectiveResolver,
|
DirectiveResolver,
|
||||||
PipeResolver,
|
PipeResolver,
|
||||||
|
|
|
@ -32,9 +32,12 @@ import {RenderEventDispatcher} from 'angular2/src/render/api';
|
||||||
import {ViewRef, ProtoViewRef, internalView} from './view_ref';
|
import {ViewRef, ProtoViewRef, internalView} from './view_ref';
|
||||||
import {ElementRef} from './element_ref';
|
import {ElementRef} from './element_ref';
|
||||||
import {ProtoPipes} from 'angular2/src/core/pipes/pipes';
|
import {ProtoPipes} from 'angular2/src/core/pipes/pipes';
|
||||||
|
import {camelCaseToDashCase} from 'angular2/src/render/dom/util';
|
||||||
|
|
||||||
export {DebugContext} from 'angular2/src/change_detection/interfaces';
|
export {DebugContext} from 'angular2/src/change_detection/interfaces';
|
||||||
|
|
||||||
|
const REFLECT_PREFIX: string = 'ng-reflect-';
|
||||||
|
|
||||||
export class AppProtoViewMergeMapping {
|
export class AppProtoViewMergeMapping {
|
||||||
renderProtoViewRef: renderApi.RenderProtoViewRef;
|
renderProtoViewRef: renderApi.RenderProtoViewRef;
|
||||||
renderFragmentCount: number;
|
renderFragmentCount: number;
|
||||||
|
@ -193,6 +196,14 @@ export class AppView implements ChangeDispatcher, RenderEventDispatcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logBindingUpdate(b: BindingTarget, value: any): void {
|
||||||
|
if (b.isDirective() || b.isElementProperty()) {
|
||||||
|
var elementRef = this.elementRefs[this.elementOffset + b.elementIndex];
|
||||||
|
this.renderer.setElementAttribute(
|
||||||
|
elementRef, `${REFLECT_PREFIX}${camelCaseToDashCase(b.name)}`, `${value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
notifyOnAllChangesDone(): void {
|
notifyOnAllChangesDone(): void {
|
||||||
var eiCount = this.proto.elementBinders.length;
|
var eiCount = this.proto.elementBinders.length;
|
||||||
var ei = this.elementInjectors;
|
var ei = this.elementInjectors;
|
||||||
|
|
|
@ -72,4 +72,4 @@ export class NgModel extends NgControl {
|
||||||
this.viewModel = newValue;
|
this.viewModel = newValue;
|
||||||
ObservableWrapper.callNext(this.update, newValue);
|
ObservableWrapper.callNext(this.update, newValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -35,7 +35,7 @@ import {
|
||||||
|
|
||||||
import {TemplateCloner} from './template_cloner';
|
import {TemplateCloner} from './template_cloner';
|
||||||
|
|
||||||
import {DOCUMENT, DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES} from './dom_tokens';
|
import {DOCUMENT} from './dom_tokens';
|
||||||
|
|
||||||
const REFLECT_PREFIX: string = 'ng-reflect-';
|
const REFLECT_PREFIX: string = 'ng-reflect-';
|
||||||
|
|
||||||
|
@ -43,15 +43,11 @@ const REFLECT_PREFIX: string = 'ng-reflect-';
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DomRenderer extends Renderer {
|
export class DomRenderer extends Renderer {
|
||||||
_document;
|
_document;
|
||||||
_reflectPropertiesAsAttributes: boolean;
|
|
||||||
|
|
||||||
constructor(private _eventManager: EventManager,
|
constructor(private _eventManager: EventManager,
|
||||||
private _domSharedStylesHost: DomSharedStylesHost,
|
private _domSharedStylesHost: DomSharedStylesHost,
|
||||||
private _templateCloner: TemplateCloner, @Inject(DOCUMENT) document,
|
private _templateCloner: TemplateCloner, @Inject(DOCUMENT) document) {
|
||||||
@Inject(DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES) reflectPropertiesAsAttributes:
|
|
||||||
boolean) {
|
|
||||||
super();
|
super();
|
||||||
this._reflectPropertiesAsAttributes = reflectPropertiesAsAttributes;
|
|
||||||
this._document = document;
|
this._document = document;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,11 +161,6 @@ export class DomRenderer extends Renderer {
|
||||||
}
|
}
|
||||||
var view = resolveInternalDomView(location.renderView);
|
var view = resolveInternalDomView(location.renderView);
|
||||||
view.setElementProperty(location.renderBoundElementIndex, propertyName, propertyValue);
|
view.setElementProperty(location.renderBoundElementIndex, propertyName, propertyValue);
|
||||||
// Reflect the property value as an attribute value with ng-reflect- prefix.
|
|
||||||
if (this._reflectPropertiesAsAttributes) {
|
|
||||||
this.setElementAttribute(location, `${REFLECT_PREFIX}${camelCaseToDashCase(propertyName)}`,
|
|
||||||
`${propertyValue}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setElementAttribute(location: RenderElementRef, attributeName: string, attributeValue: string):
|
setElementAttribute(location: RenderElementRef, attributeName: string, attributeValue: string):
|
||||||
|
|
|
@ -3,10 +3,6 @@ import {CONST_EXPR, StringWrapper, Math} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
export const DOCUMENT: OpaqueToken = CONST_EXPR(new OpaqueToken('DocumentToken'));
|
export const DOCUMENT: OpaqueToken = CONST_EXPR(new OpaqueToken('DocumentToken'));
|
||||||
|
|
||||||
export const DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES: OpaqueToken =
|
|
||||||
CONST_EXPR(new OpaqueToken('DomReflectPropertiesAsAttributes'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A unique id (string) for an angular application.
|
* A unique id (string) for an angular application.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -54,7 +54,6 @@ import {RenderCompiler, Renderer} from 'angular2/src/render/api';
|
||||||
import {
|
import {
|
||||||
DomRenderer,
|
DomRenderer,
|
||||||
DOCUMENT,
|
DOCUMENT,
|
||||||
DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES,
|
|
||||||
DefaultDomCompiler,
|
DefaultDomCompiler,
|
||||||
APP_ID,
|
APP_ID,
|
||||||
SharedStylesHost,
|
SharedStylesHost,
|
||||||
|
@ -111,7 +110,6 @@ function _getAppBindings() {
|
||||||
bind(ElementSchemaRegistry).toValue(new DomElementSchemaRegistry()),
|
bind(ElementSchemaRegistry).toValue(new DomElementSchemaRegistry()),
|
||||||
DomSharedStylesHost,
|
DomSharedStylesHost,
|
||||||
bind(SharedStylesHost).toAlias(DomSharedStylesHost),
|
bind(SharedStylesHost).toAlias(DomSharedStylesHost),
|
||||||
bind(DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES).toValue(false),
|
|
||||||
ProtoViewFactory,
|
ProtoViewFactory,
|
||||||
AppViewPool,
|
AppViewPool,
|
||||||
AppViewManager,
|
AppViewManager,
|
||||||
|
@ -125,7 +123,7 @@ function _getAppBindings() {
|
||||||
DEFAULT_PIPES,
|
DEFAULT_PIPES,
|
||||||
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
||||||
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
||||||
bind(ChangeDetection).toClass(DynamicChangeDetection),
|
bind(ChangeDetection).toValue(new DynamicChangeDetection()),
|
||||||
Log,
|
Log,
|
||||||
ViewLoader,
|
ViewLoader,
|
||||||
DynamicComponentLoader,
|
DynamicComponentLoader,
|
||||||
|
|
|
@ -10,6 +10,7 @@ const CUSTOM_ANNOTATIONS_PARAM = 'custom_annotations';
|
||||||
const ENTRY_POINT_PARAM = 'entry_points';
|
const ENTRY_POINT_PARAM = 'entry_points';
|
||||||
const FORMAT_CODE_PARAM = 'format_code';
|
const FORMAT_CODE_PARAM = 'format_code';
|
||||||
const GENERATE_CHANGE_DETECTORS_PARAM = 'generate_change_detectors';
|
const GENERATE_CHANGE_DETECTORS_PARAM = 'generate_change_detectors';
|
||||||
|
const REFLECT_PROPERTIES_AS_ATTRIBUTES = 'reflectPropertiesAsAttributes';
|
||||||
const INIT_REFLECTOR_PARAM = 'init_reflector';
|
const INIT_REFLECTOR_PARAM = 'init_reflector';
|
||||||
const INLINE_VIEWS_PARAM = 'inline_views';
|
const INLINE_VIEWS_PARAM = 'inline_views';
|
||||||
const MIRROR_MODE_PARAM = 'mirror_mode';
|
const MIRROR_MODE_PARAM = 'mirror_mode';
|
||||||
|
@ -43,6 +44,8 @@ class TransformerOptions {
|
||||||
/// Whether to create change detector classes for discovered `@View`s.
|
/// Whether to create change detector classes for discovered `@View`s.
|
||||||
final bool generateChangeDetectors;
|
final bool generateChangeDetectors;
|
||||||
|
|
||||||
|
final bool reflectPropertiesAsAttributes;
|
||||||
|
|
||||||
/// The number of phases to spend optimizing output size.
|
/// The number of phases to spend optimizing output size.
|
||||||
/// Each additional phase adds time to the transformation but may decrease
|
/// Each additional phase adds time to the transformation but may decrease
|
||||||
/// final output size. There is a limit beyond which this will no longer
|
/// final output size. There is a limit beyond which this will no longer
|
||||||
|
@ -66,6 +69,7 @@ class TransformerOptions {
|
||||||
this.annotationMatcher,
|
this.annotationMatcher,
|
||||||
this.optimizationPhases,
|
this.optimizationPhases,
|
||||||
{this.generateChangeDetectors,
|
{this.generateChangeDetectors,
|
||||||
|
this.reflectPropertiesAsAttributes,
|
||||||
this.inlineViews,
|
this.inlineViews,
|
||||||
this.formatCode});
|
this.formatCode});
|
||||||
|
|
||||||
|
@ -78,6 +82,7 @@ class TransformerOptions {
|
||||||
int optimizationPhases: DEFAULT_OPTIMIZATION_PHASES,
|
int optimizationPhases: DEFAULT_OPTIMIZATION_PHASES,
|
||||||
bool inlineViews: true,
|
bool inlineViews: true,
|
||||||
bool generateChangeDetectors: true,
|
bool generateChangeDetectors: true,
|
||||||
|
bool reflectPropertiesAsAttributes: true,
|
||||||
bool formatCode: false}) {
|
bool formatCode: false}) {
|
||||||
if (reflectionEntryPoints == null || reflectionEntryPoints.isEmpty) {
|
if (reflectionEntryPoints == null || reflectionEntryPoints.isEmpty) {
|
||||||
reflectionEntryPoints = entryPoints;
|
reflectionEntryPoints = entryPoints;
|
||||||
|
@ -94,6 +99,7 @@ class TransformerOptions {
|
||||||
annotationMatcher,
|
annotationMatcher,
|
||||||
optimizationPhases,
|
optimizationPhases,
|
||||||
generateChangeDetectors: generateChangeDetectors,
|
generateChangeDetectors: generateChangeDetectors,
|
||||||
|
reflectPropertiesAsAttributes: reflectPropertiesAsAttributes,
|
||||||
inlineViews: inlineViews,
|
inlineViews: inlineViews,
|
||||||
formatCode: formatCode);
|
formatCode: formatCode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@ TransformerOptions parseBarbackSettings(BarbackSettings settings) {
|
||||||
var inlineViews = _readBool(config, INLINE_VIEWS_PARAM, defaultValue: true);
|
var inlineViews = _readBool(config, INLINE_VIEWS_PARAM, defaultValue: true);
|
||||||
var generateChangeDetectors =
|
var generateChangeDetectors =
|
||||||
_readBool(config, GENERATE_CHANGE_DETECTORS_PARAM, defaultValue: true);
|
_readBool(config, GENERATE_CHANGE_DETECTORS_PARAM, defaultValue: true);
|
||||||
|
var reflectPropertiesAsAttributes =
|
||||||
|
_readBool(config, REFLECT_PROPERTIES_AS_ATTRIBUTES, defaultValue: false);
|
||||||
var formatCode = _readBool(config, FORMAT_CODE_PARAM, defaultValue: false);
|
var formatCode = _readBool(config, FORMAT_CODE_PARAM, defaultValue: false);
|
||||||
String mirrorModeVal =
|
String mirrorModeVal =
|
||||||
config.containsKey(MIRROR_MODE_PARAM) ? config[MIRROR_MODE_PARAM] : '';
|
config.containsKey(MIRROR_MODE_PARAM) ? config[MIRROR_MODE_PARAM] : '';
|
||||||
|
@ -41,6 +43,7 @@ TransformerOptions parseBarbackSettings(BarbackSettings settings) {
|
||||||
customAnnotationDescriptors: _readCustomAnnotations(config),
|
customAnnotationDescriptors: _readCustomAnnotations(config),
|
||||||
optimizationPhases: optimizationPhases,
|
optimizationPhases: optimizationPhases,
|
||||||
generateChangeDetectors: generateChangeDetectors,
|
generateChangeDetectors: generateChangeDetectors,
|
||||||
|
reflectPropertiesAsAttributes: reflectPropertiesAsAttributes,
|
||||||
formatCode: formatCode);
|
formatCode: formatCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -399,6 +399,7 @@ class _CodegenState {
|
||||||
|
|
||||||
var newValue = _names.getLocalName(r.selfIndex);
|
var newValue = _names.getLocalName(r.selfIndex);
|
||||||
var oldValue = _names.getFieldName(r.selfIndex);
|
var oldValue = _names.getFieldName(r.selfIndex);
|
||||||
|
var notifyDebug = _genConfig.logBindingUpdate ? "this.logBindingUpdate(${newValue});" : "";
|
||||||
|
|
||||||
var br = r.bindingRecord;
|
var br = r.bindingRecord;
|
||||||
if (br.target.isDirective()) {
|
if (br.target.isDirective()) {
|
||||||
|
@ -407,12 +408,14 @@ class _CodegenState {
|
||||||
return '''
|
return '''
|
||||||
${_genThrowOnChangeCheck(oldValue, newValue)}
|
${_genThrowOnChangeCheck(oldValue, newValue)}
|
||||||
$directiveProperty = $newValue;
|
$directiveProperty = $newValue;
|
||||||
|
${notifyDebug}
|
||||||
$_IS_CHANGED_LOCAL = true;
|
$_IS_CHANGED_LOCAL = true;
|
||||||
''';
|
''';
|
||||||
} else {
|
} else {
|
||||||
return '''
|
return '''
|
||||||
${_genThrowOnChangeCheck(oldValue, newValue)}
|
${_genThrowOnChangeCheck(oldValue, newValue)}
|
||||||
this.notifyDispatcher(${newValue});
|
this.notifyDispatcher(${newValue});
|
||||||
|
${notifyDebug}
|
||||||
''';
|
''';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ import 'view_definition_creator.dart';
|
||||||
/// This method assumes a {@link DomAdapter} has been registered.
|
/// This method assumes a {@link DomAdapter} has been registered.
|
||||||
Future<String> processTemplates(AssetReader reader, AssetId entryPoint,
|
Future<String> processTemplates(AssetReader reader, AssetId entryPoint,
|
||||||
{bool generateRegistrations: true,
|
{bool generateRegistrations: true,
|
||||||
bool generateChangeDetectors: true}) async {
|
bool generateChangeDetectors: true, bool reflectPropertiesAsAttributes: false}) async {
|
||||||
var viewDefResults = await createViewDefinitions(reader, entryPoint);
|
var viewDefResults = await createViewDefinitions(reader, entryPoint);
|
||||||
// Note: TemplateCloner(-1) never serializes Nodes into strings.
|
// Note: TemplateCloner(-1) never serializes Nodes into strings.
|
||||||
// we might want to change this to TemplateCloner(0) to force the serialization
|
// we might want to change this to TemplateCloner(0) to force the serialization
|
||||||
|
@ -58,7 +58,8 @@ Future<String> processTemplates(AssetReader reader, AssetId entryPoint,
|
||||||
}
|
}
|
||||||
if (generateChangeDetectors) {
|
if (generateChangeDetectors) {
|
||||||
var saved = reflector.reflectionCapabilities;
|
var saved = reflector.reflectionCapabilities;
|
||||||
var genConfig = new ChangeDetectorGenConfig(assertionsEnabled(), assertionsEnabled());
|
var genConfig = new ChangeDetectorGenConfig(assertionsEnabled(), assertionsEnabled(), reflectPropertiesAsAttributes);
|
||||||
|
|
||||||
reflector.reflectionCapabilities = const NullReflectionCapabilities();
|
reflector.reflectionCapabilities = const NullReflectionCapabilities();
|
||||||
var defs = getChangeDetectorDefinitions(viewDefEntry.hostMetadata,
|
var defs = getChangeDetectorDefinitions(viewDefEntry.hostMetadata,
|
||||||
protoView, viewDefEntry.viewDef.directives, genConfig);
|
protoView, viewDefEntry.viewDef.directives, genConfig);
|
||||||
|
|
|
@ -33,7 +33,8 @@ class TemplateCompiler extends Transformer {
|
||||||
var id = transform.primaryInput.id;
|
var id = transform.primaryInput.id;
|
||||||
var reader = new AssetReader.fromTransform(transform);
|
var reader = new AssetReader.fromTransform(transform);
|
||||||
var transformedCode = formatter.format(await processTemplates(reader, id,
|
var transformedCode = formatter.format(await processTemplates(reader, id,
|
||||||
generateChangeDetectors: options.generateChangeDetectors));
|
generateChangeDetectors: options.generateChangeDetectors,
|
||||||
|
reflectPropertiesAsAttributes: options.reflectPropertiesAsAttributes));
|
||||||
transform.addOutput(new Asset.fromString(id, transformedCode));
|
transform.addOutput(new Asset.fromString(id, transformedCode));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// TODO (jteplitz602): This whole file is nearly identical to core/application.ts.
|
// TODO (jteplitz602): This whole file is nearly identical to core/application.ts.
|
||||||
// There should be a way to refactor application so that this file is unnecessary. See #3277
|
// There should be a way to refactor application so that this file is unnecessary. See #3277
|
||||||
import {Injector, bind, Binding} from "angular2/di";
|
import {Injector, bind, Binding} from "angular2/di";
|
||||||
import {Type, isBlank, isPresent} from "angular2/src/facade/lang";
|
|
||||||
import {Reflector, reflector} from 'angular2/src/reflection/reflection';
|
import {Reflector, reflector} from 'angular2/src/reflection/reflection';
|
||||||
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {
|
import {
|
||||||
|
@ -24,7 +23,6 @@ import {AppRootUrl} from 'angular2/src/services/app_root_url';
|
||||||
import {
|
import {
|
||||||
DomRenderer,
|
DomRenderer,
|
||||||
DOCUMENT,
|
DOCUMENT,
|
||||||
DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES,
|
|
||||||
DefaultDomCompiler,
|
DefaultDomCompiler,
|
||||||
APP_ID_RANDOM_BINDING,
|
APP_ID_RANDOM_BINDING,
|
||||||
MAX_IN_MEMORY_ELEMENTS_PER_TEMPLATE,
|
MAX_IN_MEMORY_ELEMENTS_PER_TEMPLATE,
|
||||||
|
@ -75,12 +73,12 @@ var _rootBindings = [bind(Reflector).toValue(reflector)];
|
||||||
|
|
||||||
// TODO: This code is nearly identitcal to core/application. There should be a way to only write it
|
// TODO: This code is nearly identitcal to core/application. There should be a way to only write it
|
||||||
// once
|
// once
|
||||||
function _injectorBindings(): List<Type | Binding | List<any>> {
|
function _injectorBindings(): List<any> {
|
||||||
var bestChangeDetection: Type = DynamicChangeDetection;
|
var bestChangeDetection = new DynamicChangeDetection();
|
||||||
if (PreGeneratedChangeDetection.isSupported()) {
|
if (PreGeneratedChangeDetection.isSupported()) {
|
||||||
bestChangeDetection = PreGeneratedChangeDetection;
|
bestChangeDetection = new PreGeneratedChangeDetection();
|
||||||
} else if (JitChangeDetection.isSupported()) {
|
} else if (JitChangeDetection.isSupported()) {
|
||||||
bestChangeDetection = JitChangeDetection;
|
bestChangeDetection = new JitChangeDetection();
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -94,7 +92,6 @@ function _injectorBindings(): List<Type | Binding | List<any>> {
|
||||||
return new EventManager(plugins, ngZone);
|
return new EventManager(plugins, ngZone);
|
||||||
},
|
},
|
||||||
[NgZone]),
|
[NgZone]),
|
||||||
bind(DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES).toValue(false),
|
|
||||||
DomRenderer,
|
DomRenderer,
|
||||||
bind(Renderer).toAlias(DomRenderer),
|
bind(Renderer).toAlias(DomRenderer),
|
||||||
APP_ID_RANDOM_BINDING,
|
APP_ID_RANDOM_BINDING,
|
||||||
|
@ -119,7 +116,7 @@ function _injectorBindings(): List<Type | Binding | List<any>> {
|
||||||
CompilerCache,
|
CompilerCache,
|
||||||
ViewResolver,
|
ViewResolver,
|
||||||
DEFAULT_PIPES,
|
DEFAULT_PIPES,
|
||||||
bind(ChangeDetection).toClass(bestChangeDetection),
|
bind(ChangeDetection).toValue(bestChangeDetection),
|
||||||
ViewLoader,
|
ViewLoader,
|
||||||
DirectiveResolver,
|
DirectiveResolver,
|
||||||
Parser,
|
Parser,
|
||||||
|
|
|
@ -79,11 +79,11 @@ class PrintLogger {
|
||||||
|
|
||||||
function _injectorBindings(appComponentType, bus: MessageBusInterface,
|
function _injectorBindings(appComponentType, bus: MessageBusInterface,
|
||||||
initData: StringMap<string, any>): List<Type | Binding | List<any>> {
|
initData: StringMap<string, any>): List<Type | Binding | List<any>> {
|
||||||
var bestChangeDetection: Type = DynamicChangeDetection;
|
var bestChangeDetection = new DynamicChangeDetection();
|
||||||
if (PreGeneratedChangeDetection.isSupported()) {
|
if (PreGeneratedChangeDetection.isSupported()) {
|
||||||
bestChangeDetection = PreGeneratedChangeDetection;
|
bestChangeDetection = new PreGeneratedChangeDetection();
|
||||||
} else if (JitChangeDetection.isSupported()) {
|
} else if (JitChangeDetection.isSupported()) {
|
||||||
bestChangeDetection = JitChangeDetection;
|
bestChangeDetection = new JitChangeDetection();
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
bind(APP_COMPONENT)
|
bind(APP_COMPONENT)
|
||||||
|
@ -123,7 +123,7 @@ function _injectorBindings(appComponentType, bus: MessageBusInterface,
|
||||||
DEFAULT_PIPES,
|
DEFAULT_PIPES,
|
||||||
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
||||||
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
||||||
bind(ChangeDetection).toClass(bestChangeDetection),
|
bind(ChangeDetection).toValue(bestChangeDetection),
|
||||||
DirectiveResolver,
|
DirectiveResolver,
|
||||||
PipeResolver,
|
PipeResolver,
|
||||||
Parser,
|
Parser,
|
||||||
|
|
|
@ -28,13 +28,13 @@ export function main() {
|
||||||
|
|
||||||
it("should return a proto change detector when one is available", () => {
|
it("should return a proto change detector when one is available", () => {
|
||||||
var map = {'id': (def) => proto};
|
var map = {'id': (def) => proto};
|
||||||
var cd = new PreGeneratedChangeDetection(map);
|
var cd = new PreGeneratedChangeDetection(null, map);
|
||||||
|
|
||||||
expect(cd.getProtoChangeDetector('id', def)).toBe(proto)
|
expect(cd.getProtoChangeDetector('id', def)).toBe(proto)
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should delegate to dynamic change detection otherwise", () => {
|
it("should delegate to dynamic change detection otherwise", () => {
|
||||||
var cd = new PreGeneratedChangeDetection({});
|
var cd = new PreGeneratedChangeDetection(null, {});
|
||||||
expect(cd.getProtoChangeDetector('id', def)).toBeAnInstanceOf(DynamicProtoChangeDetector);
|
expect(cd.getProtoChangeDetector('id', def)).toBeAnInstanceOf(DynamicProtoChangeDetector);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -66,7 +66,7 @@ export var PROP_NAME = 'propName';
|
||||||
* In this case, we expect `id` and `expression` to be the same string.
|
* In this case, we expect `id` and `expression` to be the same string.
|
||||||
*/
|
*/
|
||||||
export function getDefinition(id: string): TestDefinition {
|
export function getDefinition(id: string): TestDefinition {
|
||||||
var genConfig = new ChangeDetectorGenConfig(true, true);
|
var genConfig = new ChangeDetectorGenConfig(true, true, true);
|
||||||
var testDef = null;
|
var testDef = null;
|
||||||
if (StringMapWrapper.contains(_ExpressionWithLocals.availableDefinitions, id)) {
|
if (StringMapWrapper.contains(_ExpressionWithLocals.availableDefinitions, id)) {
|
||||||
let val = StringMapWrapper.get(_ExpressionWithLocals.availableDefinitions, id);
|
let val = StringMapWrapper.get(_ExpressionWithLocals.availableDefinitions, id);
|
||||||
|
@ -110,6 +110,12 @@ export function getDefinition(id: string): TestDefinition {
|
||||||
var records = _createBindingRecords("a");
|
var records = _createBindingRecords("a");
|
||||||
let cdDef = new ChangeDetectorDefinition(id, "ON_PUSH_OBSERVE", [], records, [], [], genConfig);
|
let cdDef = new ChangeDetectorDefinition(id, "ON_PUSH_OBSERVE", [], records, [], [], genConfig);
|
||||||
testDef = new TestDefinition(id, cdDef, null);
|
testDef = new TestDefinition(id, cdDef, null);
|
||||||
|
|
||||||
|
} else if (id == "updateElementProduction") {
|
||||||
|
var genConfig = new ChangeDetectorGenConfig(false, false, false);
|
||||||
|
var records = _createBindingRecords("name");
|
||||||
|
let cdDef = new ChangeDetectorDefinition(id, null, [], records, [], [], genConfig);
|
||||||
|
testDef = new TestDefinition(id, cdDef, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -138,7 +144,7 @@ export function getAllDefinitions(): List<TestDefinition> {
|
||||||
ListWrapper.concat(allDefs, StringMapWrapper.keys(_DirectiveUpdating.availableDefinitions));
|
ListWrapper.concat(allDefs, StringMapWrapper.keys(_DirectiveUpdating.availableDefinitions));
|
||||||
allDefs = ListWrapper.concat(allDefs, _availableEventDefinitions);
|
allDefs = ListWrapper.concat(allDefs, _availableEventDefinitions);
|
||||||
allDefs = ListWrapper.concat(allDefs, _availableHostEventDefinitions);
|
allDefs = ListWrapper.concat(allDefs, _availableHostEventDefinitions);
|
||||||
allDefs = ListWrapper.concat(allDefs, ["onPushObserve"]);
|
allDefs = ListWrapper.concat(allDefs, ["onPushObserve", "updateElementProduction"]);
|
||||||
return ListWrapper.map(allDefs, (id) => getDefinition(id));
|
return ListWrapper.map(allDefs, (id) => getDefinition(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +156,7 @@ class _ExpressionWithLocals {
|
||||||
var variableBindings = _convertLocalsToVariableBindings(this.locals);
|
var variableBindings = _convertLocalsToVariableBindings(this.locals);
|
||||||
var bindingRecords = _createBindingRecords(this._expression);
|
var bindingRecords = _createBindingRecords(this._expression);
|
||||||
var directiveRecords = [];
|
var directiveRecords = [];
|
||||||
var genConfig = new ChangeDetectorGenConfig(true, true);
|
var genConfig = new ChangeDetectorGenConfig(true, true, true);
|
||||||
return new ChangeDetectorDefinition('(empty id)', strategy, variableBindings, bindingRecords,
|
return new ChangeDetectorDefinition('(empty id)', strategy, variableBindings, bindingRecords,
|
||||||
[], directiveRecords, genConfig);
|
[], directiveRecords, genConfig);
|
||||||
}
|
}
|
||||||
|
@ -210,7 +216,7 @@ class _ExpressionWithMode {
|
||||||
_createHostEventRecords("(host-event)='false'", dirRecordWithOnPush))
|
_createHostEventRecords("(host-event)='false'", dirRecordWithOnPush))
|
||||||
}
|
}
|
||||||
|
|
||||||
var genConfig = new ChangeDetectorGenConfig(true, true);
|
var genConfig = new ChangeDetectorGenConfig(true, true, true);
|
||||||
|
|
||||||
return new ChangeDetectorDefinition('(empty id)', this._strategy, variableBindings,
|
return new ChangeDetectorDefinition('(empty id)', this._strategy, variableBindings,
|
||||||
bindingRecords, eventRecords, directiveRecords, genConfig);
|
bindingRecords, eventRecords, directiveRecords, genConfig);
|
||||||
|
@ -236,7 +242,7 @@ class _DirectiveUpdating {
|
||||||
createChangeDetectorDefinition(): ChangeDetectorDefinition {
|
createChangeDetectorDefinition(): ChangeDetectorDefinition {
|
||||||
var strategy = null;
|
var strategy = null;
|
||||||
var variableBindings = [];
|
var variableBindings = [];
|
||||||
var genConfig = new ChangeDetectorGenConfig(true, true);
|
var genConfig = new ChangeDetectorGenConfig(true, true, true);
|
||||||
|
|
||||||
return new ChangeDetectorDefinition('(empty id)', strategy, variableBindings,
|
return new ChangeDetectorDefinition('(empty id)', strategy, variableBindings,
|
||||||
this._bindingRecords, [], this._directiveRecords,
|
this._bindingRecords, [], this._directiveRecords,
|
||||||
|
|
|
@ -535,6 +535,31 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("logBindingUpdate", () => {
|
||||||
|
it('should be called for element updates in the dev mode', () => {
|
||||||
|
var person = new Person('bob');
|
||||||
|
var val = _createChangeDetector('name', person);
|
||||||
|
val.changeDetector.detectChanges();
|
||||||
|
expect(val.dispatcher.debugLog).toEqual(['propName=bob']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be called for directive updates in the dev mode', () => {
|
||||||
|
var val = _createWithoutHydrate('directNoDispatcher');
|
||||||
|
val.changeDetector.hydrate(_DEFAULT_CONTEXT, null,
|
||||||
|
new FakeDirectives([new TestDirective()], []), null);
|
||||||
|
val.changeDetector.detectChanges();
|
||||||
|
expect(val.dispatcher.debugLog).toEqual(["a=42"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not be called in the prod mode', () => {
|
||||||
|
var person = new Person('bob');
|
||||||
|
var val = _createChangeDetector('updateElementProduction', person);
|
||||||
|
val.changeDetector.detectChanges();
|
||||||
|
expect(val.dispatcher.debugLog).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
describe('reading directives', () => {
|
describe('reading directives', () => {
|
||||||
it('should read directive properties', () => {
|
it('should read directive properties', () => {
|
||||||
var directive = new TestDirective();
|
var directive = new TestDirective();
|
||||||
|
@ -1123,7 +1148,8 @@ class FakeDirectives {
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestDispatcher implements ChangeDispatcher {
|
class TestDispatcher implements ChangeDispatcher {
|
||||||
log: List<string>;
|
log: string[];
|
||||||
|
debugLog: string[];
|
||||||
loggedValues: List<any>;
|
loggedValues: List<any>;
|
||||||
onAllChangesDoneCalled: boolean = false;
|
onAllChangesDoneCalled: boolean = false;
|
||||||
|
|
||||||
|
@ -1131,6 +1157,7 @@ class TestDispatcher implements ChangeDispatcher {
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
this.log = [];
|
this.log = [];
|
||||||
|
this.debugLog = [];
|
||||||
this.loggedValues = [];
|
this.loggedValues = [];
|
||||||
this.onAllChangesDoneCalled = true;
|
this.onAllChangesDoneCalled = true;
|
||||||
}
|
}
|
||||||
|
@ -1140,6 +1167,8 @@ class TestDispatcher implements ChangeDispatcher {
|
||||||
this.loggedValues.push(value);
|
this.loggedValues.push(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logBindingUpdate(target, value) { this.debugLog.push(`${target.name}=${this._asString(value)}`); }
|
||||||
|
|
||||||
notifyOnAllChangesDone() { this.onAllChangesDoneCalled = true; }
|
notifyOnAllChangesDone() { this.onAllChangesDoneCalled = true; }
|
||||||
|
|
||||||
getDebugContext(a, b) { return null; }
|
getDebugContext(a, b) { return null; }
|
||||||
|
|
|
@ -58,7 +58,10 @@ import {
|
||||||
import {
|
import {
|
||||||
PipeTransform,
|
PipeTransform,
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
ON_PUSH
|
ON_PUSH,
|
||||||
|
ChangeDetection,
|
||||||
|
DynamicChangeDetection,
|
||||||
|
ChangeDetectorGenConfig
|
||||||
} from 'angular2/src/change_detection/change_detection';
|
} from 'angular2/src/change_detection/change_detection';
|
||||||
|
|
||||||
import {Directive, Component, View, ViewMetadata, Attribute, Query, Pipe} from 'angular2/metadata';
|
import {Directive, Component, View, ViewMetadata, Attribute, Query, Pipe} from 'angular2/metadata';
|
||||||
|
@ -1518,6 +1521,30 @@ export function main() {
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('logging property updates', () => {
|
||||||
|
beforeEachBindings(() => [
|
||||||
|
bind(ChangeDetection)
|
||||||
|
.toValue(new DynamicChangeDetection(new ChangeDetectorGenConfig(true, true, true)))
|
||||||
|
]);
|
||||||
|
|
||||||
|
it('should reflect property values as attributes',
|
||||||
|
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||||
|
var tpl = '<div>' +
|
||||||
|
'<div my-dir [elprop]="ctxProp"></div>' +
|
||||||
|
'</div>';
|
||||||
|
tcb.overrideView(MyComp, new ViewMetadata({template: tpl, directives: [MyDir]}))
|
||||||
|
|
||||||
|
.createAsync(MyComp)
|
||||||
|
.then((rootTC) => {
|
||||||
|
rootTC.componentInstance.ctxProp = 'hello';
|
||||||
|
rootTC.detectChanges();
|
||||||
|
|
||||||
|
expect(DOM.getInnerHTML(rootTC.nativeElement))
|
||||||
|
.toContain('ng-reflect-dir-prop="hello"');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
describe('different proto view storages', () => {
|
describe('different proto view storages', () => {
|
||||||
function runWithMode(mode: string) {
|
function runWithMode(mode: string) {
|
||||||
|
|
|
@ -24,8 +24,6 @@ import {
|
||||||
RenderViewRef,
|
RenderViewRef,
|
||||||
ViewEncapsulation
|
ViewEncapsulation
|
||||||
} from 'angular2/src/render/api';
|
} from 'angular2/src/render/api';
|
||||||
import {DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES} from 'angular2/src/render/dom/dom_tokens';
|
|
||||||
import {bind} from 'angular2/di';
|
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('DomRenderer integration', () => {
|
describe('DomRenderer integration', () => {
|
||||||
|
@ -106,72 +104,6 @@ export function main() {
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
it('should NOT reflect property values as attributes if flag is NOT set',
|
|
||||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAndMerge(someComponent,
|
|
||||||
[
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'someComponent',
|
|
||||||
template: '<input [title]="y">',
|
|
||||||
directives: []
|
|
||||||
})
|
|
||||||
])
|
|
||||||
.then((protoViewMergeMappings) => {
|
|
||||||
var rootView = tb.createView(protoViewMergeMappings);
|
|
||||||
var el = DOM.childNodes(rootView.hostElement)[0];
|
|
||||||
tb.renderer.setElementProperty(elRef(rootView.viewRef, 1), 'maxLength', '20');
|
|
||||||
expect(DOM.getAttribute(<HTMLInputElement>el, 'ng-reflect-max-length'))
|
|
||||||
.toEqual(null);
|
|
||||||
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('reflection', () => {
|
|
||||||
beforeEachBindings(() => [bind(DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES).toValue(true)]);
|
|
||||||
|
|
||||||
it('should reflect property values as attributes if flag is set',
|
|
||||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAndMerge(someComponent,
|
|
||||||
[
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'someComponent',
|
|
||||||
template: '<input [title]="y">',
|
|
||||||
directives: []
|
|
||||||
})
|
|
||||||
])
|
|
||||||
.then((protoViewMergeMappings) => {
|
|
||||||
var rootView = tb.createView(protoViewMergeMappings);
|
|
||||||
var el = DOM.childNodes(rootView.hostElement)[0];
|
|
||||||
tb.renderer.setElementProperty(elRef(rootView.viewRef, 1), 'maxLength', '20');
|
|
||||||
expect(DOM.getAttribute(<HTMLInputElement>el, 'ng-reflect-max-length'))
|
|
||||||
.toEqual('20');
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should reflect non-string property values as attributes if flag is set',
|
|
||||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAndMerge(someComponent,
|
|
||||||
[
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'someComponent',
|
|
||||||
template: '<input [title]="y">',
|
|
||||||
directives: []
|
|
||||||
})
|
|
||||||
])
|
|
||||||
.then((protoViewMergeMappings) => {
|
|
||||||
var rootView = tb.createView(protoViewMergeMappings);
|
|
||||||
var el = DOM.childNodes(rootView.hostElement)[0];
|
|
||||||
tb.renderer.setElementProperty(elRef(rootView.viewRef, 1), 'maxLength', 20);
|
|
||||||
expect(DOM.getAttribute(<HTMLInputElement>el, 'ng-reflect-max-length'))
|
|
||||||
.toEqual('20');
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
if (DOM.supportsDOMEvents()) {
|
if (DOM.supportsDOMEvents()) {
|
||||||
it('should call actions on the element independent of the compilation',
|
it('should call actions on the element independent of the compilation',
|
||||||
inject([AsyncTestCompleter, DomTestbed], (async, tb: DomTestbed) => {
|
inject([AsyncTestCompleter, DomTestbed], (async, tb: DomTestbed) => {
|
||||||
|
|
|
@ -58,6 +58,7 @@ class _MyComponent_ChangeDetector0
|
||||||
}
|
}
|
||||||
|
|
||||||
this.notifyDispatcher(l_interpolate1);
|
this.notifyDispatcher(l_interpolate1);
|
||||||
|
this.logBindingUpdate(l_interpolate1);
|
||||||
|
|
||||||
this.interpolate1 = l_interpolate1;
|
this.interpolate1 = l_interpolate1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
DynamicChangeDetection,
|
DynamicChangeDetection,
|
||||||
JitChangeDetection,
|
JitChangeDetection,
|
||||||
ChangeDetectorDefinition,
|
ChangeDetectorDefinition,
|
||||||
|
ChangeDetectorGenConfig,
|
||||||
BindingRecord,
|
BindingRecord,
|
||||||
DirectiveRecord,
|
DirectiveRecord,
|
||||||
DirectiveIndex,
|
DirectiveIndex,
|
||||||
|
@ -249,8 +250,9 @@ function setUpChangeDetection(changeDetection: ChangeDetection, iterations, obje
|
||||||
var dispatcher = new DummyDispatcher();
|
var dispatcher = new DummyDispatcher();
|
||||||
var parser = new Parser(new Lexer());
|
var parser = new Parser(new Lexer());
|
||||||
|
|
||||||
|
var genConfig = new ChangeDetectorGenConfig(false, false, false);
|
||||||
var parentProto = changeDetection.getProtoChangeDetector(
|
var parentProto = changeDetection.getProtoChangeDetector(
|
||||||
"id", new ChangeDetectorDefinition('parent', null, [], [], [], [], false));
|
"id", new ChangeDetectorDefinition('parent', null, [], [], [], [], genConfig));
|
||||||
var parentCd = parentProto.instantiate(dispatcher);
|
var parentCd = parentProto.instantiate(dispatcher);
|
||||||
|
|
||||||
var directiveRecord = new DirectiveRecord({directiveIndex: new DirectiveIndex(0, 0)});
|
var directiveRecord = new DirectiveRecord({directiveIndex: new DirectiveIndex(0, 0)});
|
||||||
|
@ -279,7 +281,7 @@ function setUpChangeDetection(changeDetection: ChangeDetection, iterations, obje
|
||||||
|
|
||||||
var proto = changeDetection.getProtoChangeDetector(
|
var proto = changeDetection.getProtoChangeDetector(
|
||||||
"id",
|
"id",
|
||||||
new ChangeDetectorDefinition("proto", null, [], bindings, [], [directiveRecord], false));
|
new ChangeDetectorDefinition("proto", null, [], bindings, [], [directiveRecord], genConfig));
|
||||||
|
|
||||||
var targetObj = new Obj();
|
var targetObj = new Obj();
|
||||||
parentCd.hydrate(object, null, new FakeDirectives(targetObj), null);
|
parentCd.hydrate(object, null, new FakeDirectives(targetObj), null);
|
||||||
|
@ -385,6 +387,7 @@ class DummyDispatcher implements ChangeDispatcher {
|
||||||
getDebugContext(elementIndex: number, directiveIndex: DirectiveIndex): DebugContext {
|
getDebugContext(elementIndex: number, directiveIndex: DirectiveIndex): DebugContext {
|
||||||
throw "getDebugContext not implemented.";
|
throw "getDebugContext not implemented.";
|
||||||
}
|
}
|
||||||
notifyOnBinding(bindingRecord, newValue) { throw "Should not be used"; }
|
notifyOnBinding(bindingTarget, newValue) { throw "Should not be used"; }
|
||||||
|
logBindingUpdate(bindingTarget, newValue) { throw "Should not be used"; }
|
||||||
notifyOnAllChangesDone() {}
|
notifyOnAllChangesDone() {}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue