Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions modules/angular2/change_detection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ export {
KeyValueDiffers,
KeyValueDiffer,
KeyValueDifferFactory

} from 'angular2/src/change_detection/change_detection';
1 change: 0 additions & 1 deletion modules/angular2/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,5 @@ export {
ViewDefinition,
DOCUMENT,
APP_ID,
DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES,
MAX_IN_MEMORY_ELEMENTS_PER_TEMPLATE
} from './src/render/render';
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
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,
newValue: any): StringMap<string, any> {
if (isBlank(changes)) {
Expand Down
3 changes: 2 additions & 1 deletion modules/angular2/src/change_detection/binding_record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ export class BindingRecord {

static createForDirective(ast: AST, propertyName: string, setter: SetterFn,
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);
}

Expand Down
50 changes: 42 additions & 8 deletions modules/angular2/src/change_detection/change_detection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,21 @@ import {IterableDiffers, IterableDifferFactory} from './differs/iterable_differs
import {DefaultIterableDifferFactory} from './differs/default_iterable_differ';
import {KeyValueDiffers, KeyValueDifferFactory} from './differs/keyvalue_differs';
import {DefaultKeyValueDifferFactory} from './differs/default_keyvalue_differ';
import {ChangeDetection, ProtoChangeDetector, ChangeDetectorDefinition} from './interfaces';
import {
ChangeDetection,
ProtoChangeDetector,
ChangeDetectorDefinition,
ChangeDetectorGenConfig
} from './interfaces';
import {Injector, Inject, Injectable, OpaqueToken, Optional, Binding} from 'angular2/di';
import {List, StringMap, StringMapWrapper} from 'angular2/src/facade/collection';
import {CONST, CONST_EXPR, isPresent, BaseException} from 'angular2/src/facade/lang';
import {
CONST,
CONST_EXPR,
isPresent,
BaseException,
assertionsEnabled
} from 'angular2/src/facade/lang';

export {
ASTWithSource,
Expand All @@ -34,7 +45,8 @@ export {
ChangeDispatcher,
ChangeDetection,
ChangeDetectorDefinition,
DebugContext
DebugContext,
ChangeDetectorGenConfig
} from './interfaces';
export {CHECK_ONCE, CHECK_ALWAYS, DETACHED, CHECKED, ON_PUSH, DEFAULT} from './constants';
export {DynamicProtoChangeDetector} from './proto_change_detector';
Expand Down Expand Up @@ -72,23 +84,26 @@ export const defaultKeyValueDiffers = CONST_EXPR(new KeyValueDiffers(keyValDiff)
// dart2js. See https://github.com/dart-lang/sdk/issues/23630 for details.
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.
*/
@Injectable()
export class PreGeneratedChangeDetection extends ChangeDetection {
_dynamicChangeDetection: ChangeDetection;
_protoChangeDetectorFactories: StringMap<string, Function>;
_genConfig: ChangeDetectorGenConfig;

constructor(@Inject(PROTO_CHANGE_DETECTOR) @Optional() protoChangeDetectorsForTest?:
StringMap<string, Function>) {
constructor(config?: ChangeDetectorGenConfig,
protoChangeDetectorsForTest?: StringMap<string, Function>) {
super();
this._dynamicChangeDetection = new DynamicChangeDetection();
this._protoChangeDetectorFactories = isPresent(protoChangeDetectorsForTest) ?
protoChangeDetectorsForTest :
preGeneratedProtoDetectors;

this._genConfig =
isPresent(config) ? config : new ChangeDetectorGenConfig(assertionsEnabled(),
assertionsEnabled(), false);
}

static isSupported(): boolean { return PregenProtoChangeDetector.isSupported(); }
Expand All @@ -100,6 +115,7 @@ export class PreGeneratedChangeDetection extends ChangeDetection {
return this._dynamicChangeDetection.getProtoChangeDetector(id, definition);
}

get genConfig(): ChangeDetectorGenConfig { return this._genConfig; }
get generateDetectors(): boolean { return true; }
}

Expand All @@ -111,10 +127,20 @@ export class PreGeneratedChangeDetection extends ChangeDetection {
*/
@Injectable()
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 {
return new DynamicProtoChangeDetector(definition);
}

get genConfig(): ChangeDetectorGenConfig { return this._genConfig; }
get generateDetectors(): boolean { return true; }
}

Expand All @@ -125,13 +151,21 @@ export class DynamicChangeDetection extends ChangeDetection {
* {@link DynamicChangeDetection} and {@link PreGeneratedChangeDetection}.
*/
@Injectable()
@CONST()
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(); }

getProtoChangeDetector(id: string, definition: ChangeDetectorDefinition): ProtoChangeDetector {
return new JitProtoChangeDetector(definition);
}

get genConfig(): ChangeDetectorGenConfig { return this._genConfig; }
get generateDetectors(): boolean { return true; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {CodegenNameUtil, sanitizeName} from './codegen_name_util';
import {CodegenLogicUtil} from './codegen_logic_util';
import {EventBinding} from './event_binding';
import {BindingTarget} from './binding_record';
import {ChangeDetectorGenConfig} from './interfaces';


/**
Expand All @@ -34,7 +35,7 @@ export class ChangeDetectorJITGenerator {
constructor(private id: string, private changeDetectionStrategy: string,
private records: List<ProtoRecord>, private propertyBindingTargets: BindingTarget[],
private eventBindings: EventBinding[], private directiveRecords: List<any>,
private devMode: boolean) {
private genConfig: ChangeDetectorGenConfig) {
this._names =
new CodegenNameUtil(this.records, this.eventBindings, this.directiveRecords, UTIL);
this._logic = new CodegenLogicUtil(this._names, UTIL, changeDetectionStrategy);
Expand Down Expand Up @@ -81,13 +82,13 @@ export class ChangeDetectorJITGenerator {
return new ${this._typeName}(dispatcher);
}
`;

return new Function(ABSTRACT_CHANGE_DETECTOR, UTIL, classDefinition)(AbstractChangeDetector,
ChangeDetectionUtil);
}

_genPropertyBindingTargets(): string {
var targets = this._logic.genPropertyBindingTargets(this.propertyBindingTargets, true);
var targets = this._logic.genPropertyBindingTargets(this.propertyBindingTargets,
this.genConfig.genDebugInfo);
return `${this._typeName}.gen_propertyBindingTargets = ${targets};`;
}

Expand Down Expand Up @@ -299,6 +300,7 @@ export class ChangeDetectorJITGenerator {

var newValue = this._names.getLocalName(r.selfIndex);
var oldValue = this._names.getFieldName(r.selfIndex);
var notifyDebug = this.genConfig.logBindingUpdate ? `this.logBindingUpdate(${newValue});` : "";

var br = r.bindingRecord;
if (br.target.isDirective()) {
Expand All @@ -307,18 +309,20 @@ export class ChangeDetectorJITGenerator {
return `
${this._genThrowOnChangeCheck(oldValue, newValue)}
${directiveProperty} = ${newValue};
${notifyDebug}
${IS_CHANGED_LOCAL} = true;
`;
} else {
return `
${this._genThrowOnChangeCheck(oldValue, newValue)}
this.notifyDispatcher(${newValue});
${notifyDebug}
`;
}
}

_genThrowOnChangeCheck(oldValue: string, newValue: string): string {
if (this.devMode) {
if (this.genConfig.genCheckNoChanges) {
return `
if(throwOnChange) {
this.throwOnChangeError(${oldValue}, ${newValue});
Expand All @@ -330,7 +334,7 @@ export class ChangeDetectorJITGenerator {
}

_genCheckNoChanges(): string {
if (this.devMode) {
if (this.genConfig.genCheckNoChanges) {
return `${this._typeName}.prototype.checkNoChanges = function() { this.runDetectChanges(true); }`;
} else {
return '';
Expand Down
5 changes: 3 additions & 2 deletions modules/angular2/src/change_detection/codegen_logic_util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,12 @@ export class CodegenLogicUtil {
}
}

genPropertyBindingTargets(propertyBindingTargets: BindingTarget[], devMode: boolean): string {
genPropertyBindingTargets(propertyBindingTargets: BindingTarget[],
genDebugInfo: boolean): string {
var bs = propertyBindingTargets.map(b => {
if (isBlank(b)) return "null";

var debug = devMode ? codify(b.debug) : "null";
var debug = genDebugInfo ? codify(b.debug) : "null";
return `${this._utilName}.bindingTarget(${codify(b.mode)}, ${b.elementIndex}, ${codify(b.name)}, ${codify(b.unit)}, ${debug})`;
});
return `[${bs.join(", ")}]`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {EventBinding} from './event_binding';
import {BindingRecord, BindingTarget} from './binding_record';
import {DirectiveRecord, DirectiveIndex} from './directive_record';
import {Locals} from './parser/locals';
import {ChangeDetectorGenConfig} from './interfaces';
import {ChangeDetectionUtil, SimpleChange} from './change_detection_util';

import {ProtoRecord, RecordType} from './proto_record';
Expand All @@ -26,7 +27,8 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
constructor(id: string, dispatcher: any, numberOfPropertyProtoRecords: number,
propertyBindingTargets: BindingTarget[], directiveIndices: DirectiveIndex[],
modeOnHydrate: string, private records: ProtoRecord[],
private eventBindings: EventBinding[], private directiveRecords: DirectiveRecord[]) {
private eventBindings: EventBinding[], private directiveRecords: DirectiveRecord[],
private genConfig: ChangeDetectorGenConfig) {
super(id, dispatcher, numberOfPropertyProtoRecords, propertyBindingTargets, directiveIndices,
modeOnHydrate);
var len = records.length + 1;
Expand Down Expand Up @@ -177,6 +179,10 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
var directiveIndex = bindingRecord.directiveRecord.directiveIndex;
bindingRecord.setter(this._getDirectiveFor(directiveIndex), change.currentValue);
}

if (this.genConfig.logBindingUpdate) {
super.logBindingUpdate(change.currentValue);
}
}

_addChange(bindingRecord: BindingRecord, change, changes) {
Expand Down
13 changes: 11 additions & 2 deletions modules/angular2/src/change_detection/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {ChangeDetectorRef} from './change_detector_ref';
*
* # Example
* ```javascript
* bootstrap(MyApp, [bind(ChangeDetection).toClass(DynamicChangeDetection)]);
* bootstrap(MyApp, [bind(ChangeDetection).toValue(new DynamicChangeDetection())]);
* ```
*/
@CONST()
Expand All @@ -37,6 +37,8 @@ export class ChangeDetection {
}

get generateDetectors(): boolean { return null; }

get genConfig(): ChangeDetectorGenConfig { return null; }
}

export class DebugContext {
Expand All @@ -47,6 +49,7 @@ export class DebugContext {
export interface ChangeDispatcher {
getDebugContext(elementIndex: number, directiveIndex: DirectiveIndex): DebugContext;
notifyOnBinding(bindingTarget: BindingTarget, value: any): void;
logBindingUpdate(bindingTarget: BindingTarget, value: any): void;
notifyOnAllChangesDone(): void;
}

Expand All @@ -71,8 +74,14 @@ export interface ChangeDetector {

export interface ProtoChangeDetector { instantiate(dispatcher: ChangeDispatcher): ChangeDetector; }

export class ChangeDetectorGenConfig {
constructor(public genCheckNoChanges: boolean, public genDebugInfo: boolean,
public logBindingUpdate: boolean) {}
}

export class ChangeDetectorDefinition {
constructor(public id: string, public strategy: string, public variableNames: List<string>,
public bindingRecords: BindingRecord[], public eventRecords: BindingRecord[],
public directiveRecords: DirectiveRecord[], public devMode: boolean) {}
public directiveRecords: DirectiveRecord[],
public genConfig: ChangeDetectorGenConfig) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export class JitProtoChangeDetector implements ProtoChangeDetector {

return new ChangeDetectorJITGenerator(
definition.id, definition.strategy, propertyBindingRecords, propertyBindingTargets,
eventBindingRecords, this.definition.directiveRecords, this.definition.devMode)
eventBindingRecords, this.definition.directiveRecords, this.definition.genConfig)
.generate();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ export class DynamicProtoChangeDetector implements ProtoChangeDetector {
this.definition.id, dispatcher, this._propertyBindingRecords.length,
this._propertyBindingTargets, this._directiveIndices,
ChangeDetectionUtil.changeDetectionMode(this.definition.strategy),
this._propertyBindingRecords, this._eventBindingRecords, this.definition.directiveRecords);
this._propertyBindingRecords, this._eventBindingRecords, this.definition.directiveRecords,
this.definition.genConfig);
}
}

Expand Down
10 changes: 4 additions & 6 deletions modules/angular2/src/core/application_common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ import {Renderer, RenderCompiler} from 'angular2/src/render/api';
import {
DomRenderer,
DOCUMENT,
DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES,
DefaultDomCompiler,
APP_ID_RANDOM_BINDING,
MAX_IN_MEMORY_ELEMENTS_PER_TEMPLATE,
Expand All @@ -83,16 +82,15 @@ var _rootInjector: Injector;
var _rootBindings = [bind(Reflector).toValue(reflector), TestabilityRegistry];

function _injectorBindings(appComponentType): List<Type | Binding | List<any>> {
var bestChangeDetection: Type = DynamicChangeDetection;
var bestChangeDetection = new DynamicChangeDetection();
if (PreGeneratedChangeDetection.isSupported()) {
bestChangeDetection = PreGeneratedChangeDetection;
bestChangeDetection = new PreGeneratedChangeDetection();
} else if (JitChangeDetection.isSupported()) {
bestChangeDetection = JitChangeDetection;
bestChangeDetection = new JitChangeDetection();
}
return [
bind(DOCUMENT)
.toValue(DOM.defaultDoc()),
bind(DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES).toValue(false),
bind(APP_COMPONENT).toValue(appComponentType),
bind(APP_COMPONENT_REF_PROMISE)
.toFactory(
Expand Down Expand Up @@ -140,7 +138,7 @@ function _injectorBindings(appComponentType): List<Type | Binding | List<any>> {
DEFAULT_PIPES,
bind(IterableDiffers).toValue(defaultIterableDiffers),
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
bind(ChangeDetection).toClass(bestChangeDetection),
bind(ChangeDetection).toValue(bestChangeDetection),
ViewLoader,
DirectiveResolver,
PipeResolver,
Expand Down
Loading