Skip to content

Commit

Permalink
feat(view): reimplemented property setters using change detection
Browse files Browse the repository at this point in the history
  • Loading branch information
vsavkin committed Apr 23, 2015
1 parent 8a92a1f commit 8ccafb0
Show file tree
Hide file tree
Showing 36 changed files with 510 additions and 469 deletions.
2 changes: 1 addition & 1 deletion modules/angular2/change_detection.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export {ProtoChangeDetector, ChangeDispatcher, ChangeDetector, ChangeDetection}
export {CHECK_ONCE, CHECK_ALWAYS, DETACHED, CHECKED, ON_PUSH, DEFAULT} from './src/change_detection/constants';
export {DynamicProtoChangeDetector, JitProtoChangeDetector} from './src/change_detection/proto_change_detector';
export {BindingRecord} from './src/change_detection/binding_record';
export {DirectiveRecord} from './src/change_detection/directive_record';
export {DirectiveIndex, DirectiveRecord} from './src/change_detection/directive_record';
export {DynamicChangeDetector} from './src/change_detection/dynamic_change_detector';
export {ChangeDetectorRef} from './src/change_detection/change_detector_ref';
export {PipeRegistry} from './src/change_detection/pipes/pipe_registry';
Expand Down
16 changes: 11 additions & 5 deletions modules/angular2/src/change_detection/binding_record.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {isPresent, isBlank} from 'angular2/src/facade/lang';
import {SetterFn} from 'angular2/src/reflection/types';
import {AST} from './parser/ast';
import {DirectiveRecord} from './directive_record';
import {DirectiveIndex, DirectiveRecord} from './directive_record';

const DIRECTIVE="directive";
const ELEMENT="element";
Expand All @@ -11,14 +11,16 @@ export class BindingRecord {
mode:string;
ast:AST;

implicitReceiver:any; //number | DirectiveIndex
elementIndex:number;
propertyName:string;
setter:SetterFn;

directiveRecord:DirectiveRecord;

constructor(mode:string, ast:AST, elementIndex:number, propertyName:string, setter:SetterFn, directiveRecord:DirectiveRecord) {
constructor(mode:string, implicitReceiver:any, ast:AST, elementIndex:number, propertyName:string, setter:SetterFn, directiveRecord:DirectiveRecord) {
this.mode = mode;
this.implicitReceiver = implicitReceiver;
this.ast = ast;

this.elementIndex = elementIndex;
Expand Down Expand Up @@ -49,14 +51,18 @@ export class BindingRecord {
}

static createForDirective(ast:AST, propertyName:string, setter:SetterFn, directiveRecord:DirectiveRecord) {
return new BindingRecord(DIRECTIVE, ast, 0, propertyName, setter, directiveRecord);
return new BindingRecord(DIRECTIVE, 0, ast, 0, propertyName, setter, directiveRecord);
}

static createForElement(ast:AST, elementIndex:number, propertyName:string) {
return new BindingRecord(ELEMENT, ast, elementIndex, propertyName, null, null);
return new BindingRecord(ELEMENT, 0, ast, elementIndex, propertyName, null, null);
}

static createForHostProperty(directiveIndex:DirectiveIndex, ast:AST, propertyName:string) {
return new BindingRecord(ELEMENT, directiveIndex, ast, directiveIndex.elementIndex, propertyName, null, null);
}

static createForTextNode(ast:AST, elementIndex:number) {
return new BindingRecord(TEXT_NODE, ast, elementIndex, null, null, null);
return new BindingRecord(TEXT_NODE, 0, ast, elementIndex, null, null, null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/faca

import {AbstractChangeDetector} from './abstract_change_detector';
import {ChangeDetectionUtil} from './change_detection_util';
import {DirectiveRecord} from './directive_record';
import {DirectiveIndex, DirectiveRecord} from './directive_record';

import {
ProtoRecord,
Expand Down Expand Up @@ -81,12 +81,12 @@ function hydrateTemplate(type:string, mode:string, fieldDefinitions:string, pipe
directiveFieldNames:List<String>, detectorFieldNames:List<String>):string {
var directiveInit = "";
for(var i = 0; i < directiveFieldNames.length; ++i) {
directiveInit += `${directiveFieldNames[i]} = directives.getDirectiveFor(this.directiveRecords[${i}]);\n`;
directiveInit += `${directiveFieldNames[i]} = directives.getDirectiveFor(this.directiveRecords[${i}].directiveIndex);\n`;
}

var detectorInit = "";
for(var i = 0; i < detectorFieldNames.length; ++i) {
detectorInit += `${detectorFieldNames[i]} = directives.getDetectorFor(this.directiveRecords[${i}]);\n`;
detectorInit += `${detectorFieldNames[i]} = directives.getDetectorFor(this.directiveRecords[${i}].directiveIndex);\n`;
}

return `
Expand Down Expand Up @@ -313,18 +313,18 @@ export class ChangeDetectorJITGenerator {
}

getDirectiveFieldNames():List<string> {
return this.directiveRecords.map((d) => this.getDirective(d));
return this.directiveRecords.map((d) => this.getDirective(d.directiveIndex));
}

getDetectorFieldNames():List<string> {
return this.directiveRecords.filter(r => r.isOnPushChangeDetection()).map((d) => this.getDetector(d));
return this.directiveRecords.filter(r => r.isOnPushChangeDetection()).map((d) => this.getDetector(d.directiveIndex));
}

getDirective(d:DirectiveRecord) {
getDirective(d:DirectiveIndex) {
return `this.directive_${d.name}`;
}

getDetector(d:DirectiveRecord) {
getDetector(d:DirectiveIndex) {
return `this.detector_${d.name}`;
}

Expand Down Expand Up @@ -359,7 +359,7 @@ export class ChangeDetectorJITGenerator {
for (var i = dirs.length - 1; i >= 0; --i) {
var dir = dirs[i];
if (dir.callOnAllChangesDone) {
var directive = `this.directive_${dir.name}`;
var directive = `this.directive_${dir.directiveIndex.name}`;
notifications.push(onAllChangesDoneTemplate(directive));
}
}
Expand Down Expand Up @@ -425,7 +425,7 @@ export class ChangeDetectorJITGenerator {
}

genUpdateCurrentValue(r:ProtoRecord):string {
var context = this.localNames[r.contextIndex];
var context = this.getContext(r);
var newValue = this.localNames[r.selfIndex];
var args = this.genArgs(r);

Expand Down Expand Up @@ -463,6 +463,14 @@ export class ChangeDetectorJITGenerator {
}
}

getContext(r:ProtoRecord):string {
if (r.contextIndex == -1) {
return this.getDirective(r.directiveIndex);
} else {
return this.localNames[r.contextIndex];
}
}

ifChangedGuard(r:ProtoRecord, body:string):string {
return ifChangedGuardTemplate(r.args.map((a) => this.changeNames[a]), body);
}
Expand Down Expand Up @@ -491,7 +499,7 @@ export class ChangeDetectorJITGenerator {

var br = r.bindingRecord;
if (br.isDirective()) {
var directiveProperty = `${this.getDirective(br.directiveRecord)}.${br.propertyName}`;
var directiveProperty = `${this.getDirective(br.directiveRecord.directiveIndex)}.${br.propertyName}`;
return updateDirectiveTemplate(oldValue, newValue, directiveProperty);
} else {
return updateElementTemplate(oldValue, newValue);
Expand All @@ -513,7 +521,7 @@ export class ChangeDetectorJITGenerator {
genNotifyOnChanges(r:ProtoRecord):string{
var br = r.bindingRecord;
if (r.lastInDirective && br.callOnChange()) {
return notifyOnChangesTemplate(this.getDirective(br.directiveRecord));
return notifyOnChangesTemplate(this.getDirective(br.directiveRecord.directiveIndex));
} else {
return "";
}
Expand All @@ -522,7 +530,7 @@ export class ChangeDetectorJITGenerator {
genNotifyOnPushDetectors(r:ProtoRecord):string{
var br = r.bindingRecord;
if (r.lastInDirective && br.isOnPushChangeDetection()) {
return notifyOnPushDetectorsTemplate(this.getDetector(br.directiveRecord));
return notifyOnPushDetectorsTemplate(this.getDetector(br.directiveRecord.directiveIndex));
} else {
return "";
}
Expand Down
2 changes: 2 additions & 0 deletions modules/angular2/src/change_detection/coalesce.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ function _selfRecord(r:ProtoRecord, contextIndex:number, selfIndex:number):Proto
[],
r.fixedArgs,
contextIndex,
r.directiveIndex,
selfIndex,
r.bindingRecord,
r.expressionAsString,
Expand Down Expand Up @@ -72,6 +73,7 @@ function _replaceIndices(r:ProtoRecord, selfIndex:number, indexMap:Map) {
args,
r.fixedArgs,
contextIndex,
r.directiveIndex,
selfIndex,
r.bindingRecord,
r.expressionAsString,
Expand Down
23 changes: 15 additions & 8 deletions modules/angular2/src/change_detection/directive_record.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
import {ON_PUSH} from './constants';
import {StringWrapper} from 'angular2/src/facade/lang';

export class DirectiveRecord {
export class DirectiveIndex {
elementIndex:number;
directiveIndex:number;

constructor(elementIndex:number, directiveIndex:number) {
this.elementIndex = elementIndex;
this.directiveIndex = directiveIndex;
}

get name() {
return `${this.elementIndex}_${this.directiveIndex}`;
}
}

export class DirectiveRecord {
directiveIndex:DirectiveIndex;
callOnAllChangesDone:boolean;
callOnChange:boolean;
changeDetection:string;

constructor(elementIndex:number, directiveIndex:number,
callOnAllChangesDone:boolean, callOnChange:boolean, changeDetection:string) {
this.elementIndex = elementIndex;
constructor(directiveIndex:DirectiveIndex, callOnAllChangesDone:boolean, callOnChange:boolean, changeDetection:string) {
this.directiveIndex = directiveIndex;
this.callOnAllChangesDone = callOnAllChangesDone;
this.callOnChange = callOnChange;
Expand All @@ -20,8 +31,4 @@ export class DirectiveRecord {
isOnPushChangeDetection():boolean {
return StringWrapper.equals(this.changeDetection, ON_PUSH);
}

get name() {
return `${this.elementIndex}_${this.directiveIndex}`;
}
}
25 changes: 16 additions & 9 deletions modules/angular2/src/change_detection/dynamic_change_detector.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/faca

import {AbstractChangeDetector} from './abstract_change_detector';
import {BindingRecord} from './binding_record';
import {DirectiveRecord} from './directive_record';
import {PipeRegistry} from './pipes/pipe_registry';
import {ChangeDetectionUtil, uninitialized} from './change_detection_util';

Expand Down Expand Up @@ -111,12 +110,12 @@ export class DynamicChangeDetector extends AbstractChangeDetector {

if (proto.lastInDirective) {
if (isPresent(changes)) {
this._getDirectiveFor(directiveRecord).onChange(changes);
this._getDirectiveFor(directiveRecord.directiveIndex).onChange(changes);
changes = null;
}

if (isChanged && bindingRecord.isOnPushChangeDetection()) {
this._getDetectorFor(directiveRecord).markAsCheckOnce();
this._getDetectorFor(directiveRecord.directiveIndex).markAsCheckOnce();
}

isChanged = false;
Expand All @@ -129,7 +128,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
for (var i = dirs.length - 1; i >= 0; --i) {
var dir = dirs[i];
if (dir.callOnAllChangesDone) {
this._getDirectiveFor(dir).onAllChangesDone();
this._getDirectiveFor(dir.directiveIndex).onAllChangesDone();
}
}
}
Expand All @@ -138,7 +137,8 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
if (isBlank(bindingRecord.directiveRecord)) {
this.dispatcher.notifyOnBinding(bindingRecord, change.currentValue);
} else {
bindingRecord.setter(this._getDirectiveFor(bindingRecord.directiveRecord), change.currentValue);
var directiveIndex = bindingRecord.directiveRecord.directiveIndex;
bindingRecord.setter(this._getDirectiveFor(directiveIndex), change.currentValue);
}
}

Expand All @@ -150,12 +150,12 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
}
}

_getDirectiveFor(directive:DirectiveRecord) {
return this.directives.getDirectiveFor(directive);
_getDirectiveFor(directiveIndex) {
return this.directives.getDirectiveFor(directiveIndex);
}

_getDetectorFor(directive:DirectiveRecord) {
return this.directives.getDetectorFor(directive);
_getDetectorFor(directiveIndex) {
return this.directives.getDetectorFor(directiveIndex);
}

_check(proto:ProtoRecord) {
Expand Down Expand Up @@ -235,6 +235,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
var pipe = this._pipeFor(proto, context);

var newValue = pipe.transform(context);

if (! ChangeDetectionUtil.noChangeMarker(newValue)) {
var prevValue = this._readSelf(proto);
this._writeSelf(proto, newValue);
Expand Down Expand Up @@ -272,6 +273,12 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
}

_readContext(proto:ProtoRecord) {
if (proto.contextIndex == -1) {
return this._getDirectiveFor(proto.directiveIndex);
} else {
return this.values[proto.contextIndex];
}

return this.values[proto.contextIndex];
}

Expand Down
2 changes: 1 addition & 1 deletion modules/angular2/src/change_detection/parser/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ export class AstVisitor {

export class AstTransformer {
visitImplicitReceiver(ast:ImplicitReceiver) {
return new ImplicitReceiver();
return ast;
}

visitInterpolation(ast:Interpolation) {
Expand Down
15 changes: 11 additions & 4 deletions modules/angular2/src/change_detection/proto_change_detector.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {DynamicChangeDetector} from './dynamic_change_detector';
import {ChangeDetectorJITGenerator} from './change_detection_jit_generator';
import {PipeRegistry} from './pipes/pipe_registry';
import {BindingRecord} from './binding_record';
import {DirectiveIndex} from './directive_record';

import {coalesce} from './coalesce';

Expand Down Expand Up @@ -153,7 +154,7 @@ class _ConvertAstIntoProtoRecords {
}

visitImplicitReceiver(ast:ImplicitReceiver) {
return 0;
return this.bindingRecord.implicitReceiver;
}

visitInterpolation(ast:Interpolation) {
Expand Down Expand Up @@ -247,9 +248,15 @@ class _ConvertAstIntoProtoRecords {

_addRecord(type, name, funcOrValue, args, fixedArgs, context) {
var selfIndex = ++ this.contextIndex;
ListWrapper.push(this.protoRecords,
new ProtoRecord(type, name, funcOrValue, args, fixedArgs, context, selfIndex,
this.bindingRecord, this.expressionAsString, false, false));
if (context instanceof DirectiveIndex) {
ListWrapper.push(this.protoRecords,
new ProtoRecord(type, name, funcOrValue, args, fixedArgs, -1, context, selfIndex,
this.bindingRecord, this.expressionAsString, false, false));
} else {
ListWrapper.push(this.protoRecords,
new ProtoRecord(type, name, funcOrValue, args, fixedArgs, context, null, selfIndex,
this.bindingRecord, this.expressionAsString, false, false));
}
return selfIndex;
}
}
Expand Down
8 changes: 8 additions & 0 deletions modules/angular2/src/change_detection/proto_record.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {List} from 'angular2/src/facade/collection';
import {BindingRecord} from './binding_record';
import {DirectiveIndex} from './directive_record';

export const RECORD_TYPE_SELF = 0;
export const RECORD_TYPE_CONST = 1;
Expand All @@ -19,7 +20,10 @@ export class ProtoRecord {
funcOrValue:any;
args:List;
fixedArgs:List;

contextIndex:number;
directiveIndex:DirectiveIndex;

selfIndex:number;
bindingRecord:BindingRecord;
lastInBinding:boolean;
Expand All @@ -32,6 +36,7 @@ export class ProtoRecord {
args:List,
fixedArgs:List,
contextIndex:number,
directiveIndex:DirectiveIndex,
selfIndex:number,
bindingRecord:BindingRecord,
expressionAsString:string,
Expand All @@ -43,7 +48,10 @@ export class ProtoRecord {
this.funcOrValue = funcOrValue;
this.args = args;
this.fixedArgs = fixedArgs;

this.contextIndex = contextIndex;
this.directiveIndex = directiveIndex;

this.selfIndex = selfIndex;
this.bindingRecord = bindingRecord;
this.lastInBinding = lastInBinding;
Expand Down
Loading

0 comments on commit 8ccafb0

Please sign in to comment.