feat(change_detection): implement a change detector generator
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
Parser,
|
||||
ChangeDetector,
|
||||
ProtoChangeDetector,
|
||||
DynamicProtoChangeDetector,
|
||||
ChangeDispatcher,
|
||||
} from 'change_detection/change_detection';
|
||||
|
||||
@@ -102,7 +103,7 @@ function setUpChangeDetection(iterations) {
|
||||
var dispatcher = new DummyDispatcher();
|
||||
var parser = new Parser(new Lexer());
|
||||
|
||||
var parentProto = new ProtoChangeDetector();
|
||||
var parentProto = new DynamicProtoChangeDetector();
|
||||
var parentCD = parentProto.instantiate(dispatcher, MapWrapper.create());
|
||||
|
||||
var astWithSource = [
|
||||
@@ -119,7 +120,7 @@ function setUpChangeDetection(iterations) {
|
||||
];
|
||||
|
||||
function proto(i) {
|
||||
var pcd = new ProtoChangeDetector();
|
||||
var pcd = new DynamicProtoChangeDetector();
|
||||
pcd.addAst(astWithSource[i % 10].ast, "memo", i, false);
|
||||
return pcd;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import {isBlank, Type} from 'facade/lang';
|
||||
import {MapWrapper} from 'facade/collection';
|
||||
import {DirectiveMetadata} from 'core/compiler/directive_metadata';
|
||||
|
||||
import {Parser, Lexer, ProtoRecordRange} from 'change_detection/change_detection';
|
||||
import {Parser, Lexer, ProtoRecordRange, dynamicChangeDetection} from 'change_detection/change_detection';
|
||||
|
||||
import {Compiler, CompilerCache} from 'core/compiler/compiler';
|
||||
import {DirectiveMetadataReader} from 'core/compiler/directive_metadata_reader';
|
||||
@@ -79,7 +79,7 @@ export function main() {
|
||||
setupReflector();
|
||||
var reader = new DirectiveMetadataReader();
|
||||
var cache = new CompilerCache();
|
||||
var compiler = new Compiler(null, reader, new Parser(new Lexer()), cache);
|
||||
var compiler = new Compiler(dynamicChangeDetection, null, reader, new Parser(new Lexer()), cache);
|
||||
var annotatedComponent = reader.read(BenchmarkComponent);
|
||||
|
||||
var templateNoBindings = loadTemplate('templateNoBindings', count);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {Parser, Lexer, ChangeDetector} from 'change_detection/change_detection';
|
||||
import {Parser, Lexer, ChangeDetector, ChangeDetection, jitChangeDetection}
|
||||
from 'change_detection/change_detection';
|
||||
|
||||
import {bootstrap, Component, Template, TemplateConfig, ViewPort, Compiler} from 'angular/angular';
|
||||
|
||||
@@ -38,11 +39,7 @@ function setupReflector() {
|
||||
},
|
||||
template: new TemplateConfig({
|
||||
directives: [TreeComponent, NgIf],
|
||||
inline: `
|
||||
<span> {{data.value}}
|
||||
<span template='ng-if data.right != null'><tree [data]='data.right'></tree></span>
|
||||
<span template='ng-if data.left != null'><tree [data]='data.left'></tree></span>
|
||||
</span>`
|
||||
inline: `<span>{{data.value}}<span template='ng-if data.right != null'><tree [data]='data.right'></tree></span><span template='ng-if data.left != null'><tree [data]='data.left'></tree></span></span>`
|
||||
})
|
||||
})]
|
||||
});
|
||||
@@ -59,8 +56,8 @@ function setupReflector() {
|
||||
});
|
||||
|
||||
reflector.registerType(Compiler, {
|
||||
'factory': (templateLoader, reader, parser, compilerCache) => new Compiler(templateLoader, reader, parser, compilerCache),
|
||||
'parameters': [[TemplateLoader], [DirectiveMetadataReader], [Parser], [CompilerCache]],
|
||||
'factory': (cd, templateLoader, reader, parser, compilerCache) => new Compiler(cd, templateLoader, reader, parser, compilerCache),
|
||||
'parameters': [[ChangeDetection], [TemplateLoader], [DirectiveMetadataReader], [Parser], [CompilerCache]],
|
||||
'annotations': []
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import {List, ListWrapper} from 'facade/collection';
|
||||
import {ChangeDetector} from './interfaces';
|
||||
|
||||
export class AbstractChangeDetector extends ChangeDetector {
|
||||
children:List;
|
||||
parent:ChangeDetector;
|
||||
|
||||
constructor() {
|
||||
this.children = [];
|
||||
}
|
||||
|
||||
addChild(cd:ChangeDetector) {
|
||||
ListWrapper.push(this.children, cd);
|
||||
cd.parent = this;
|
||||
}
|
||||
|
||||
removeChild(cd:ChangeDetector) {
|
||||
ListWrapper.remove(this.children, cd);
|
||||
}
|
||||
|
||||
remove() {
|
||||
this.parent.removeChild(this);
|
||||
}
|
||||
|
||||
detectChanges() {
|
||||
this._detectChanges(false);
|
||||
}
|
||||
|
||||
checkNoChanges() {
|
||||
this._detectChanges(true);
|
||||
}
|
||||
|
||||
_detectChanges(throwOnChange:boolean) {
|
||||
this.detectChangesInRecords(throwOnChange);
|
||||
this._detectChangesInChildren(throwOnChange);
|
||||
}
|
||||
|
||||
detectChangesInRecords(throwOnChange:boolean){}
|
||||
|
||||
_detectChangesInChildren(throwOnChange:boolean) {
|
||||
var children = this.children;
|
||||
for(var i = 0; i < children.length; ++i) {
|
||||
children[i]._detectChanges(throwOnChange);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,5 +5,26 @@ export {ContextWithVariableBindings} from './parser/context_with_variable_bindin
|
||||
|
||||
export {ExpressionChangedAfterItHasBeenChecked, ChangeDetectionError} from './exceptions';
|
||||
export {ChangeRecord, ChangeDispatcher, ChangeDetector} from './interfaces';
|
||||
export {ProtoChangeDetector} from './proto_change_detector';
|
||||
export {DynamicChangeDetector} from './dynamic_change_detector';
|
||||
export {ProtoChangeDetector, DynamicProtoChangeDetector, JitProtoChangeDetector} from './proto_change_detector';
|
||||
export {DynamicChangeDetector} from './dynamic_change_detector';
|
||||
|
||||
import {ProtoChangeDetector, DynamicProtoChangeDetector, JitProtoChangeDetector} from './proto_change_detector';
|
||||
|
||||
export class ChangeDetection {
|
||||
createProtoChangeDetector(name:string){}
|
||||
}
|
||||
|
||||
export class DynamicChangeDetection extends ChangeDetection {
|
||||
createProtoChangeDetector(name:string):ProtoChangeDetector{
|
||||
return new DynamicProtoChangeDetector();
|
||||
}
|
||||
}
|
||||
|
||||
export class JitChangeDetection extends ChangeDetection {
|
||||
createProtoChangeDetector(name:string):ProtoChangeDetector{
|
||||
return new JitProtoChangeDetector();
|
||||
}
|
||||
}
|
||||
|
||||
export var dynamicChangeDetection = new DynamicChangeDetection();
|
||||
export var jitChangeDetection = new JitChangeDetection();
|
||||
@@ -0,0 +1,10 @@
|
||||
library change_detectoin.change_detection_jit_generator;
|
||||
|
||||
class ChangeDetectorJITGenerator {
|
||||
ChangeDetectorJITGenerator(typeName, records) {
|
||||
}
|
||||
|
||||
generate() {
|
||||
throw "Not supported in Dart";
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,138 @@
|
||||
import {isPresent, isBlank, BaseException, Type} from 'facade/lang';
|
||||
import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'facade/collection';
|
||||
import {ContextWithVariableBindings} from './parser/context_with_variable_bindings';
|
||||
import {ArrayChanges} from './array_changes';
|
||||
import {KeyValueChanges} from './keyvalue_changes';
|
||||
import {ProtoRecord} from './proto_change_detector';
|
||||
import {ExpressionChangedAfterItHasBeenChecked} from './exceptions';
|
||||
import {ChangeRecord} from './interfaces';
|
||||
|
||||
export var uninitialized = new Object();
|
||||
|
||||
export class SimpleChange {
|
||||
previousValue:any;
|
||||
currentValue:any;
|
||||
|
||||
constructor(previousValue:any, currentValue:any) {
|
||||
this.previousValue = previousValue;
|
||||
this.currentValue = currentValue;
|
||||
}
|
||||
}
|
||||
|
||||
export class ChangeDetectionUtil {
|
||||
static unitialized() {
|
||||
return uninitialized;
|
||||
}
|
||||
|
||||
static arrayFn0() { return []; }
|
||||
static arrayFn1(a1) { return [a1]; }
|
||||
static arrayFn2(a1, a2) { return [a1, a2]; }
|
||||
static arrayFn3(a1, a2, a3) { return [a1, a2, a3]; }
|
||||
static arrayFn4(a1, a2, a3, a4) { return [a1, a2, a3, a4]; }
|
||||
static arrayFn5(a1, a2, a3, a4, a5) { return [a1, a2, a3, a4, a5]; }
|
||||
static arrayFn6(a1, a2, a3, a4, a5, a6) { return [a1, a2, a3, a4, a5, a6]; }
|
||||
static arrayFn7(a1, a2, a3, a4, a5, a6, a7) { return [a1, a2, a3, a4, a5, a6, a7]; }
|
||||
static arrayFn8(a1, a2, a3, a4, a5, a6, a7, a8) { return [a1, a2, a3, a4, a5, a6, a7, a8]; }
|
||||
static arrayFn9(a1, a2, a3, a4, a5, a6, a7, a8, a9) { return [a1, a2, a3, a4, a5, a6, a7, a8, a9]; }
|
||||
|
||||
static operation_negate(value) {return !value;}
|
||||
static operation_add(left, right) {return left + right;}
|
||||
static operation_subtract(left, right) {return left - right;}
|
||||
static operation_multiply(left, right) {return left * right;}
|
||||
static operation_divide(left, right) {return left / right;}
|
||||
static operation_remainder(left, right) {return left % right;}
|
||||
static operation_equals(left, right) {return left == right;}
|
||||
static operation_not_equals(left, right) {return left != right;}
|
||||
static operation_less_then(left, right) {return left < right;}
|
||||
static operation_greater_then(left, right) {return left > right;}
|
||||
static operation_less_or_equals_then(left, right) {return left <= right;}
|
||||
static operation_greater_or_equals_then(left, right) {return left >= right;}
|
||||
static operation_logical_and(left, right) {return left && right;}
|
||||
static operation_logical_or(left, right) {return left || right;}
|
||||
static cond(cond, trueVal, falseVal) {return cond ? trueVal : falseVal;}
|
||||
|
||||
static mapFn(keys:List) {
|
||||
function buildMap(values) {
|
||||
var res = StringMapWrapper.create();
|
||||
for(var i = 0; i < keys.length; ++i) {
|
||||
StringMapWrapper.set(res, keys[i], values[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
switch (keys.length) {
|
||||
case 0: return () => [];
|
||||
case 1: return (a1) => buildMap([a1]);
|
||||
case 2: return (a1, a2) => buildMap([a1, a2]);
|
||||
case 3: return (a1, a2, a3) => buildMap([a1, a2, a3]);
|
||||
case 4: return (a1, a2, a3, a4) => buildMap([a1, a2, a3, a4]);
|
||||
case 5: return (a1, a2, a3, a4, a5) => buildMap([a1, a2, a3, a4, a5]);
|
||||
case 6: return (a1, a2, a3, a4, a5, a6) => buildMap([a1, a2, a3, a4, a5, a6]);
|
||||
case 7: return (a1, a2, a3, a4, a5, a6, a7) => buildMap([a1, a2, a3, a4, a5, a6, a7]);
|
||||
case 8: return (a1, a2, a3, a4, a5, a6, a7, a8) => buildMap([a1, a2, a3, a4, a5, a6, a7, a8]);
|
||||
case 9: return (a1, a2, a3, a4, a5, a6, a7, a8, a9) => buildMap([a1, a2, a3, a4, a5, a6, a7, a8, a9]);
|
||||
default: throw new BaseException(`Does not support literal maps with more than 9 elements`);
|
||||
}
|
||||
}
|
||||
|
||||
static keyedAccess(obj, args) {
|
||||
return obj[args[0]];
|
||||
}
|
||||
|
||||
static structuralCheck(self, context) {
|
||||
if (isBlank(self) || self === uninitialized) {
|
||||
if (ArrayChanges.supports(context)) {
|
||||
self = new ArrayChanges();
|
||||
} else if (KeyValueChanges.supports(context)) {
|
||||
self = new KeyValueChanges();
|
||||
}
|
||||
}
|
||||
|
||||
if (isBlank(context) || context === uninitialized) {
|
||||
return new SimpleChange(null, null);
|
||||
|
||||
} else {
|
||||
if (ArrayChanges.supports(context)) {
|
||||
|
||||
if (self.check(context)) {
|
||||
return new SimpleChange(null, self); // TODO: don't wrap and return self instead
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
} else if (KeyValueChanges.supports(context)) {
|
||||
|
||||
if (self.check(context)) {
|
||||
return new SimpleChange(null, self); // TODO: don't wrap and return self instead
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new BaseException(`Unsupported type (${context})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static findContext(name:string, c){
|
||||
while (c instanceof ContextWithVariableBindings) {
|
||||
if (c.hasBinding(name)) {
|
||||
return c;
|
||||
}
|
||||
c = c.parent;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static throwOnChange(proto:ProtoRecord, change) {
|
||||
throw new ExpressionChangedAfterItHasBeenChecked(proto, change);
|
||||
}
|
||||
|
||||
static changeRecord(memento:any, change:any):ChangeRecord {
|
||||
return new ChangeRecord(memento, change);
|
||||
}
|
||||
|
||||
static simpleChangeRecord(memento:any, previousValue:any, currentValue:any):ChangeRecord {
|
||||
return new ChangeRecord(memento, new SimpleChange(previousValue, currentValue));
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,9 @@ import {isPresent, isBlank, BaseException, FunctionWrapper} from 'facade/lang';
|
||||
import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'facade/collection';
|
||||
import {ContextWithVariableBindings} from './parser/context_with_variable_bindings';
|
||||
|
||||
import {AbstractChangeDetector} from './abstract_change_detector';
|
||||
import {ChangeDetectionUtil, SimpleChange, uninitialized} from './change_detection_util';
|
||||
|
||||
import {ArrayChanges} from './array_changes';
|
||||
import {KeyValueChanges} from './keyvalue_changes';
|
||||
|
||||
@@ -12,76 +15,37 @@ import {
|
||||
RECORD_TYPE_INVOKE_METHOD,
|
||||
RECORD_TYPE_CONST,
|
||||
RECORD_TYPE_INVOKE_CLOSURE,
|
||||
RECORD_TYPE_INVOKE_PURE_FUNCTION,
|
||||
RECORD_TYPE_PRIMITIVE_OP,
|
||||
RECORD_TYPE_KEYED_ACCESS,
|
||||
RECORD_TYPE_INVOKE_FORMATTER,
|
||||
RECORD_TYPE_STRUCTURAL_CHECK,
|
||||
RECORD_TYPE_INTERPOLATE,
|
||||
ProtoChangeDetector
|
||||
} from './proto_change_detector';
|
||||
|
||||
import {ChangeDetector, ChangeRecord, ChangeDispatcher} from './interfaces';
|
||||
import {ChangeDetector, ChangeDispatcher} from './interfaces';
|
||||
import {ExpressionChangedAfterItHasBeenChecked, ChangeDetectionError} from './exceptions';
|
||||
|
||||
var _uninitialized = new Object();
|
||||
|
||||
class SimpleChange {
|
||||
previousValue:any;
|
||||
currentValue:any;
|
||||
|
||||
constructor(previousValue:any, currentValue:any) {
|
||||
this.previousValue = previousValue;
|
||||
this.currentValue = currentValue;
|
||||
}
|
||||
}
|
||||
|
||||
export class DynamicChangeDetector extends ChangeDetector {
|
||||
export class DynamicChangeDetector extends AbstractChangeDetector {
|
||||
dispatcher:any;
|
||||
formatters:Map;
|
||||
children:List;
|
||||
values:List;
|
||||
protos:List<ProtoRecord>;
|
||||
parent:ChangeDetector;
|
||||
|
||||
constructor(dispatcher:any, formatters:Map, protoRecords:List<ProtoRecord>) {
|
||||
super();
|
||||
this.dispatcher = dispatcher;
|
||||
this.formatters = formatters;
|
||||
this.values = ListWrapper.createFixedSize(protoRecords.length + 1);
|
||||
ListWrapper.fill(this.values, _uninitialized);
|
||||
ListWrapper.fill(this.values, uninitialized);
|
||||
this.protos = protoRecords;
|
||||
|
||||
this.children = [];
|
||||
}
|
||||
|
||||
addChild(cd:ChangeDetector) {
|
||||
ListWrapper.push(this.children, cd);
|
||||
cd.parent = this;
|
||||
}
|
||||
|
||||
removeChild(cd:ChangeDetector) {
|
||||
ListWrapper.remove(this.children, cd);
|
||||
}
|
||||
|
||||
remove() {
|
||||
this.parent.removeChild(this);
|
||||
}
|
||||
|
||||
setContext(context:any) {
|
||||
this.values[0] = context;
|
||||
}
|
||||
|
||||
detectChanges() {
|
||||
this._detectChanges(false);
|
||||
}
|
||||
|
||||
checkNoChanges() {
|
||||
this._detectChanges(true);
|
||||
}
|
||||
|
||||
_detectChanges(throwOnChange:boolean) {
|
||||
this._detectChangesInRecords(throwOnChange);
|
||||
this._detectChangesInChildren(throwOnChange);
|
||||
}
|
||||
|
||||
_detectChangesInRecords(throwOnChange:boolean) {
|
||||
detectChangesInRecords(throwOnChange:boolean) {
|
||||
var protos:List<ProtoRecord> = this.protos;
|
||||
|
||||
var updatedRecords = null;
|
||||
@@ -91,21 +55,16 @@ export class DynamicChangeDetector extends ChangeDetector {
|
||||
var proto:ProtoRecord = protos[i];
|
||||
var change = this._check(proto);
|
||||
|
||||
// only when the terminal record, which ends a binding, changes
|
||||
// we need to add it to a list of changed records
|
||||
if (isPresent(change) && proto.terminal) {
|
||||
if (throwOnChange) throw new ExpressionChangedAfterItHasBeenChecked(proto, change);
|
||||
if (isPresent(change)) {
|
||||
currentGroup = proto.groupMemento;
|
||||
updatedRecords = this._addRecord(updatedRecords, proto, change);
|
||||
}
|
||||
|
||||
if (isPresent(updatedRecords)) {
|
||||
var lastRecordOfCurrentGroup = protos.length == i + 1 ||
|
||||
currentGroup !== protos[i + 1].groupMemento;
|
||||
if (lastRecordOfCurrentGroup) {
|
||||
this.dispatcher.onRecordChange(currentGroup, updatedRecords);
|
||||
updatedRecords = null;
|
||||
}
|
||||
if (proto.lastInGroup && isPresent(updatedRecords)) {
|
||||
if (throwOnChange) ChangeDetectionUtil.throwOnChange(proto, updatedRecords[0]);
|
||||
|
||||
this.dispatcher.onRecordChange(currentGroup, updatedRecords);
|
||||
updatedRecords = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,7 +87,11 @@ export class DynamicChangeDetector extends ChangeDetector {
|
||||
|
||||
if (!isSame(prevValue, currValue)) {
|
||||
this._writeSelf(proto, currValue);
|
||||
return new SimpleChange(prevValue === _uninitialized ? null : prevValue, currValue);
|
||||
if (proto.lastInBinding) {
|
||||
return new SimpleChange(prevValue, currValue);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -144,23 +107,28 @@ export class DynamicChangeDetector extends ChangeDetector {
|
||||
|
||||
case RECORD_TYPE_PROPERTY:
|
||||
var context = this._readContext(proto);
|
||||
while (context instanceof ContextWithVariableBindings) {
|
||||
if (context.hasBinding(proto.name)) {
|
||||
return context.get(proto.name);
|
||||
}
|
||||
context = context.parent;
|
||||
var c = ChangeDetectionUtil.findContext(proto.name, context);
|
||||
if (c instanceof ContextWithVariableBindings) {
|
||||
return c.get(proto.name);
|
||||
} else {
|
||||
var propertyGetter:Function = proto.funcOrValue;
|
||||
return propertyGetter(c);
|
||||
}
|
||||
var propertyGetter:Function = proto.funcOrValue;
|
||||
return propertyGetter(context);
|
||||
break;
|
||||
|
||||
case RECORD_TYPE_INVOKE_METHOD:
|
||||
var methodInvoker:Function = proto.funcOrValue;
|
||||
return methodInvoker(this._readContext(proto), this._readArgs(proto));
|
||||
|
||||
case RECORD_TYPE_KEYED_ACCESS:
|
||||
var arg = this._readArgs(proto)[0];
|
||||
return this._readContext(proto)[arg];
|
||||
|
||||
case RECORD_TYPE_INVOKE_CLOSURE:
|
||||
return FunctionWrapper.apply(this._readContext(proto), this._readArgs(proto));
|
||||
|
||||
case RECORD_TYPE_INVOKE_PURE_FUNCTION:
|
||||
case RECORD_TYPE_INTERPOLATE:
|
||||
case RECORD_TYPE_PRIMITIVE_OP:
|
||||
return FunctionWrapper.apply(proto.funcOrValue, this._readArgs(proto));
|
||||
|
||||
case RECORD_TYPE_INVOKE_FORMATTER:
|
||||
@@ -176,39 +144,16 @@ export class DynamicChangeDetector extends ChangeDetector {
|
||||
var self = this._readSelf(proto);
|
||||
var context = this._readContext(proto);
|
||||
|
||||
if (isBlank(self) || self === _uninitialized) {
|
||||
if (ArrayChanges.supports(context)) {
|
||||
self = new ArrayChanges();
|
||||
} else if (KeyValueChanges.supports(context)) {
|
||||
self = new KeyValueChanges();
|
||||
}
|
||||
var change = ChangeDetectionUtil.structuralCheck(self, context);
|
||||
if (isPresent(change)) {
|
||||
this._writeSelf(proto, change.currentValue);
|
||||
}
|
||||
|
||||
if (ArrayChanges.supports(context)) {
|
||||
if (self.check(context)) {
|
||||
this._writeSelf(proto, self);
|
||||
return new SimpleChange(null, self); // TODO: don't wrap and return self instead
|
||||
}
|
||||
|
||||
} else if (KeyValueChanges.supports(context)) {
|
||||
if (self.check(context)) {
|
||||
this._writeSelf(proto, self);
|
||||
return new SimpleChange(null, self); // TODO: don't wrap and return self instead
|
||||
}
|
||||
|
||||
} else if (context == null) {
|
||||
this._writeSelf(proto, null);
|
||||
return new SimpleChange(null, null);
|
||||
|
||||
} else {
|
||||
throw new BaseException(`Unsupported type (${context})`);
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
_addRecord(updatedRecords:List, proto:ProtoRecord, change):List {
|
||||
// we can use a pool of change records not to create extra garbage
|
||||
var record = new ChangeRecord(proto.bindingMemento, change);
|
||||
var record = ChangeDetectionUtil.changeRecord(proto.bindingMemento, change);
|
||||
if (isBlank(updatedRecords)) {
|
||||
updatedRecords = _singleElementList;
|
||||
updatedRecords[0] = record;
|
||||
@@ -222,23 +167,16 @@ export class DynamicChangeDetector extends ChangeDetector {
|
||||
return updatedRecords;
|
||||
}
|
||||
|
||||
_detectChangesInChildren(throwOnChange:boolean) {
|
||||
var children = this.children;
|
||||
for(var i = 0; i < children.length; ++i) {
|
||||
children[i]._detectChanges(throwOnChange);
|
||||
}
|
||||
}
|
||||
|
||||
_readContext(proto:ProtoRecord) {
|
||||
return this.values[proto.contextIndex];
|
||||
}
|
||||
|
||||
_readSelf(proto:ProtoRecord) {
|
||||
return this.values[proto.record_type_selfIndex];
|
||||
return this.values[proto.selfIndex];
|
||||
}
|
||||
|
||||
_writeSelf(proto:ProtoRecord, value) {
|
||||
this.values[proto.record_type_selfIndex] = value;
|
||||
this.values[proto.selfIndex] = value;
|
||||
}
|
||||
|
||||
_readArgs(proto:ProtoRecord) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@ import {DOM, Element} from 'facade/dom';
|
||||
import {Compiler, CompilerCache} from './compiler/compiler';
|
||||
import {ProtoView} from './compiler/view';
|
||||
import {Reflector, reflector} from 'reflection/reflection';
|
||||
import {Parser, Lexer, ChangeDetector} from 'change_detection/change_detection';
|
||||
import {Parser, Lexer, ChangeDetection, dynamicChangeDetection, jitChangeDetection} from 'change_detection/change_detection';
|
||||
import {TemplateLoader} from './compiler/template_loader';
|
||||
import {DirectiveMetadataReader} from './compiler/directive_metadata_reader';
|
||||
import {DirectiveMetadata} from './compiler/directive_metadata';
|
||||
@@ -17,7 +17,14 @@ var _rootInjector: Injector;
|
||||
|
||||
// Contains everything that is safe to share between applications.
|
||||
var _rootBindings = [
|
||||
bind(Reflector).toValue(reflector), Compiler, CompilerCache, TemplateLoader, DirectiveMetadataReader, Parser, Lexer
|
||||
bind(Reflector).toValue(reflector),
|
||||
bind(ChangeDetection).toValue(dynamicChangeDetection),
|
||||
Compiler,
|
||||
CompilerCache,
|
||||
TemplateLoader,
|
||||
DirectiveMetadataReader,
|
||||
Parser,
|
||||
Lexer
|
||||
];
|
||||
|
||||
export var appViewToken = new OpaqueToken('AppView');
|
||||
@@ -45,20 +52,20 @@ function _injectorBindings(appComponentType) {
|
||||
return element;
|
||||
}, [appComponentAnnotatedTypeToken, appDocumentToken]),
|
||||
|
||||
bind(appViewToken).toAsyncFactory((compiler, injector, appElement,
|
||||
bind(appViewToken).toAsyncFactory((changeDetection, compiler, injector, appElement,
|
||||
appComponentAnnotatedType) => {
|
||||
return compiler.compile(appComponentAnnotatedType.type, null).then(
|
||||
(protoView) => {
|
||||
var appProtoView = ProtoView.createRootProtoView(protoView,
|
||||
appElement, appComponentAnnotatedType);
|
||||
var appProtoView = ProtoView.createRootProtoView(protoView,
|
||||
appElement, appComponentAnnotatedType, changeDetection.createProtoChangeDetector('root'));
|
||||
// The light Dom of the app element is not considered part of
|
||||
// the angular application. Thus the context and lightDomInjector are
|
||||
// empty.
|
||||
var view = appProtoView.instantiate(null);
|
||||
view.hydrate(injector, null, new Object());
|
||||
var view = appProtoView.instantiate(null);
|
||||
view.hydrate(injector, null, new Object());
|
||||
return view;
|
||||
});
|
||||
}, [Compiler, Injector, appElementToken, appComponentAnnotatedTypeToken]),
|
||||
}, [ChangeDetection, Compiler, Injector, appElementToken, appComponentAnnotatedTypeToken]),
|
||||
|
||||
bind(appChangeDetectorToken).toFactory((rootView) => rootView.changeDetector,
|
||||
[appViewToken]),
|
||||
|
||||
@@ -3,7 +3,7 @@ import {Promise, PromiseWrapper} from 'facade/async';
|
||||
import {List, ListWrapper, MapWrapper} from 'facade/collection';
|
||||
import {DOM, Element} from 'facade/dom';
|
||||
|
||||
import {Parser} from 'change_detection/change_detection';
|
||||
import {ChangeDetection, Parser} from 'change_detection/change_detection';
|
||||
|
||||
import {DirectiveMetadataReader} from './directive_metadata_reader';
|
||||
import {ProtoView} from './view';
|
||||
@@ -52,7 +52,10 @@ export class Compiler {
|
||||
_reader: DirectiveMetadataReader;
|
||||
_parser:Parser;
|
||||
_compilerCache:CompilerCache;
|
||||
constructor(templateLoader:TemplateLoader, reader: DirectiveMetadataReader, parser:Parser, cache:CompilerCache) {
|
||||
_changeDetection:ChangeDetection;
|
||||
|
||||
constructor(changeDetection:ChangeDetection, templateLoader:TemplateLoader, reader: DirectiveMetadataReader, parser:Parser, cache:CompilerCache) {
|
||||
this._changeDetection = changeDetection;
|
||||
this._reader = reader;
|
||||
this._parser = parser;
|
||||
this._compilerCache = cache;
|
||||
@@ -60,7 +63,7 @@ export class Compiler {
|
||||
|
||||
createSteps(component:DirectiveMetadata):List<CompileStep> {
|
||||
var dirs = ListWrapper.map(component.componentDirectives, (d) => this._reader.read(d));
|
||||
return createDefaultSteps(this._parser, component, dirs);
|
||||
return createDefaultSteps(this._changeDetection, this._parser, component, dirs);
|
||||
}
|
||||
|
||||
compile(component:Type, templateRoot:Element = null):Promise<ProtoView> {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Parser} from 'change_detection/change_detection';
|
||||
import {ChangeDetection, Parser} from 'change_detection/change_detection';
|
||||
import {List} from 'facade/collection';
|
||||
|
||||
import {PropertyBindingParser} from './property_binding_parser';
|
||||
@@ -17,8 +17,12 @@ import {stringify} from 'facade/lang';
|
||||
* Takes in an HTMLElement and produces the ProtoViews,
|
||||
* ProtoElementInjectors and ElementBinders in the end.
|
||||
*/
|
||||
export function createDefaultSteps(parser:Parser, compiledComponent: DirectiveMetadata,
|
||||
export function createDefaultSteps(
|
||||
changeDetection:ChangeDetection,
|
||||
parser:Parser,
|
||||
compiledComponent: DirectiveMetadata,
|
||||
directives: List<DirectiveMetadata>) {
|
||||
|
||||
var compilationUnit = stringify(compiledComponent.type);
|
||||
|
||||
return [
|
||||
@@ -27,7 +31,7 @@ export function createDefaultSteps(parser:Parser, compiledComponent: DirectiveMe
|
||||
new DirectiveParser(directives),
|
||||
new TextInterpolationParser(parser, compilationUnit),
|
||||
new ElementBindingMarker(),
|
||||
new ProtoViewBuilder(),
|
||||
new ProtoViewBuilder(changeDetection),
|
||||
new ProtoElementInjectorBuilder(),
|
||||
new ElementBinderBuilder()
|
||||
];
|
||||
|
||||
@@ -2,7 +2,7 @@ import {isPresent, BaseException} from 'facade/lang';
|
||||
import {ListWrapper, MapWrapper} from 'facade/collection';
|
||||
|
||||
import {ProtoView} from '../view';
|
||||
import {ProtoChangeDetector} from 'change_detection/change_detection';
|
||||
import {ChangeDetection} from 'change_detection/change_detection';
|
||||
|
||||
import {CompileStep} from './compile_step';
|
||||
import {CompileElement} from './compile_element';
|
||||
@@ -18,10 +18,16 @@ import {CompileControl} from './compile_control';
|
||||
* - CompileElement#isViewRoot
|
||||
*/
|
||||
export class ProtoViewBuilder extends CompileStep {
|
||||
changeDetection:ChangeDetection;
|
||||
constructor(changeDetection:ChangeDetection) {
|
||||
this.changeDetection = changeDetection;
|
||||
}
|
||||
|
||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
||||
var inheritedProtoView = null;
|
||||
if (current.isViewRoot) {
|
||||
inheritedProtoView = new ProtoView(current.element, new ProtoChangeDetector());
|
||||
var protoChangeDetector = this.changeDetection.createProtoChangeDetector('dummy');
|
||||
inheritedProtoView = new ProtoView(current.element, protoChangeDetector);
|
||||
if (isPresent(parent)) {
|
||||
if (isPresent(parent.inheritedElementBinder.nestedProtoView)) {
|
||||
throw new BaseException('Only one nested view per element is allowed');
|
||||
|
||||
@@ -492,9 +492,12 @@ export class ProtoView {
|
||||
// and the component template is already compiled into protoView.
|
||||
// Used for bootstrapping.
|
||||
static createRootProtoView(protoView: ProtoView,
|
||||
insertionElement, rootComponentAnnotatedType: DirectiveMetadata): ProtoView {
|
||||
insertionElement, rootComponentAnnotatedType: DirectiveMetadata,
|
||||
protoChangeDetector:ProtoChangeDetector
|
||||
): ProtoView {
|
||||
|
||||
DOM.addClass(insertionElement, 'ng-binding');
|
||||
var rootProtoView = new ProtoView(insertionElement, new ProtoChangeDetector());
|
||||
var rootProtoView = new ProtoView(insertionElement, protoChangeDetector);
|
||||
rootProtoView.instantiateInPlace = true;
|
||||
var binder = rootProtoView.bindElement(
|
||||
new ProtoElementInjector(null, 0, [rootComponentAnnotatedType.type], true));
|
||||
|
||||
@@ -12,7 +12,7 @@ import {CompileElement} from 'core/compiler/pipeline/compile_element';
|
||||
import {CompileStep} from 'core/compiler/pipeline/compile_step'
|
||||
import {CompileControl} from 'core/compiler/pipeline/compile_control';
|
||||
|
||||
import {Lexer, Parser} from 'change_detection/change_detection';
|
||||
import {Lexer, Parser, dynamicChangeDetection} from 'change_detection/change_detection';
|
||||
|
||||
export function main() {
|
||||
describe('compiler', function() {
|
||||
@@ -134,7 +134,7 @@ class RecursiveComponent {}
|
||||
class TestableCompiler extends Compiler {
|
||||
steps:List;
|
||||
constructor(reader:DirectiveMetadataReader, steps:List<CompileStep>) {
|
||||
super(null, reader, new Parser(new Lexer()), new CompilerCache());
|
||||
super(dynamicChangeDetection, null, reader, new Parser(new Lexer()), new CompilerCache());
|
||||
this.steps = steps;
|
||||
}
|
||||
createSteps(component):List<CompileStep> {
|
||||
|
||||
@@ -3,7 +3,7 @@ import {describe, xit, it, expect, beforeEach, ddescribe, iit, el} from 'test_li
|
||||
import {DOM} from 'facade/dom';
|
||||
|
||||
import {Injector} from 'di/di';
|
||||
import {Lexer, Parser, ChangeDetector} from 'change_detection/change_detection';
|
||||
import {Lexer, Parser, ChangeDetector, dynamicChangeDetection} from 'change_detection/change_detection';
|
||||
|
||||
import {Compiler, CompilerCache} from 'core/compiler/compiler';
|
||||
import {DirectiveMetadataReader} from 'core/compiler/directive_metadata_reader';
|
||||
@@ -20,7 +20,8 @@ export function main() {
|
||||
var compiler;
|
||||
|
||||
beforeEach( () => {
|
||||
compiler = new Compiler(null, new DirectiveMetadataReader(), new Parser(new Lexer()), new CompilerCache());
|
||||
compiler = new Compiler(dynamicChangeDetection, null, new DirectiveMetadataReader(),
|
||||
new Parser(new Lexer()), new CompilerCache());
|
||||
});
|
||||
|
||||
describe('react to record changes', function() {
|
||||
|
||||
@@ -16,7 +16,8 @@ import {ProtoView, ElementPropertyMemento, DirectivePropertyMemento} from 'core/
|
||||
import {ProtoElementInjector} from 'core/compiler/element_injector';
|
||||
import {DirectiveMetadataReader} from 'core/compiler/directive_metadata_reader';
|
||||
|
||||
import {ChangeDetector, Lexer, Parser, ProtoChangeDetector} from 'change_detection/change_detection';
|
||||
import {ChangeDetector, Lexer, Parser, DynamicProtoChangeDetector,
|
||||
} from 'change_detection/change_detection';
|
||||
import {Injector} from 'di/di';
|
||||
|
||||
export function main() {
|
||||
@@ -66,7 +67,7 @@ export function main() {
|
||||
}
|
||||
if (isPresent(current.element.getAttribute('viewroot'))) {
|
||||
current.isViewRoot = true;
|
||||
current.inheritedProtoView = new ProtoView(current.element, new ProtoChangeDetector());
|
||||
current.inheritedProtoView = new ProtoView(current.element, new DynamicProtoChangeDetector());
|
||||
} else if (isPresent(parent)) {
|
||||
current.inheritedProtoView = parent.inheritedProtoView;
|
||||
}
|
||||
@@ -205,7 +206,7 @@ export function main() {
|
||||
var results = pipeline.process(el('<div viewroot prop-binding directives></div>'));
|
||||
var pv = results[0].inheritedProtoView;
|
||||
results[0].inheritedElementBinder.nestedProtoView = new ProtoView(
|
||||
el('<div></div>'), new ProtoChangeDetector());
|
||||
el('<div></div>'), new DynamicProtoChangeDetector());
|
||||
|
||||
instantiateView(pv);
|
||||
evalContext.prop1 = 'a';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {describe, beforeEach, it, expect, iit, ddescribe, el} from 'test_lib/test_lib';
|
||||
import {isPresent} from 'facade/lang';
|
||||
import {dynamicChangeDetection} from 'change_detection/change_detection';
|
||||
import {ElementBinder} from 'core/compiler/element_binder';
|
||||
import {ProtoViewBuilder} from 'core/compiler/pipeline/proto_view_builder';
|
||||
import {CompilePipeline} from 'core/compiler/pipeline/compile_pipeline';
|
||||
@@ -20,7 +21,7 @@ export function main() {
|
||||
current.variableBindings = MapWrapper.createFromStringMap(variableBindings);
|
||||
}
|
||||
current.inheritedElementBinder = new ElementBinder(null, null, null);
|
||||
}), new ProtoViewBuilder()]);
|
||||
}), new ProtoViewBuilder(dynamicChangeDetection)]);
|
||||
}
|
||||
|
||||
it('should not create a ProtoView when the isViewRoot flag is not set', () => {
|
||||
|
||||
@@ -3,7 +3,7 @@ import {describe, xit, it, expect, beforeEach, ddescribe, iit, el} from 'test_li
|
||||
import {DOM} from 'facade/dom';
|
||||
|
||||
import {Injector} from 'di/di';
|
||||
import {Lexer, Parser, ChangeDetector} from 'change_detection/change_detection';
|
||||
import {Lexer, Parser, ChangeDetector, dynamicChangeDetection} from 'change_detection/change_detection';
|
||||
|
||||
import {Compiler, CompilerCache} from 'core/compiler/compiler';
|
||||
import {LifeCycle} from 'core/life_cycle/life_cycle';
|
||||
@@ -26,7 +26,8 @@ export function main() {
|
||||
var compiler;
|
||||
|
||||
beforeEach( () => {
|
||||
compiler = new Compiler(null, new TestDirectiveMetadataReader(strategy),
|
||||
compiler = new Compiler(dynamicChangeDetection, null,
|
||||
new TestDirectiveMetadataReader(strategy),
|
||||
new Parser(new Lexer()), new CompilerCache());
|
||||
});
|
||||
|
||||
|
||||
@@ -5,7 +5,8 @@ import {ShadowDomEmulated} from 'core/compiler/shadow_dom';
|
||||
import {DirectiveMetadataReader} from 'core/compiler/directive_metadata_reader';
|
||||
import {Component, Decorator, Template} from 'core/annotations/annotations';
|
||||
import {OnChange} from 'core/core';
|
||||
import {Lexer, Parser, ProtoChangeDetector, ChangeDetector} from 'change_detection/change_detection';
|
||||
import {Lexer, Parser, DynamicProtoChangeDetector,
|
||||
ChangeDetector} from 'change_detection/change_detection';
|
||||
import {TemplateConfig} from 'core/annotations/template_config';
|
||||
import {EventEmitter} from 'core/annotations/events';
|
||||
import {List, MapWrapper} from 'facade/collection';
|
||||
@@ -52,7 +53,7 @@ export function main() {
|
||||
describe('instantiated from protoView', () => {
|
||||
var view;
|
||||
beforeEach(() => {
|
||||
var pv = new ProtoView(el('<div id="1"></div>'), new ProtoChangeDetector());
|
||||
var pv = new ProtoView(el('<div id="1"></div>'), new DynamicProtoChangeDetector());
|
||||
view = pv.instantiate(null);
|
||||
});
|
||||
|
||||
@@ -73,7 +74,7 @@ export function main() {
|
||||
describe('with locals', function() {
|
||||
var view;
|
||||
beforeEach(() => {
|
||||
var pv = new ProtoView(el('<div id="1"></div>'), new ProtoChangeDetector());
|
||||
var pv = new ProtoView(el('<div id="1"></div>'), new DynamicProtoChangeDetector());
|
||||
pv.bindVariable('context-foo', 'template-foo');
|
||||
view = createView(pv);
|
||||
});
|
||||
@@ -109,7 +110,7 @@ export function main() {
|
||||
}
|
||||
|
||||
it('should collect the root node in the ProtoView element', () => {
|
||||
var pv = new ProtoView(templateAwareCreateElement('<div id="1"></div>'), new ProtoChangeDetector());
|
||||
var pv = new ProtoView(templateAwareCreateElement('<div id="1"></div>'), new DynamicProtoChangeDetector());
|
||||
var view = pv.instantiate(null);
|
||||
view.hydrate(null, null, null);
|
||||
expect(view.nodes.length).toBe(1);
|
||||
@@ -119,7 +120,7 @@ export function main() {
|
||||
describe('collect elements with property bindings', () => {
|
||||
|
||||
it('should collect property bindings on the root element if it has the ng-binding class', () => {
|
||||
var pv = new ProtoView(templateAwareCreateElement('<div [prop]="a" class="ng-binding"></div>'), new ProtoChangeDetector());
|
||||
var pv = new ProtoView(templateAwareCreateElement('<div [prop]="a" class="ng-binding"></div>'), new DynamicProtoChangeDetector());
|
||||
pv.bindElement(null);
|
||||
pv.bindElementProperty(parser.parseBinding('a', null), 'prop', reflector.setter('prop'));
|
||||
|
||||
@@ -131,7 +132,7 @@ export function main() {
|
||||
|
||||
it('should collect property bindings on child elements with ng-binding class', () => {
|
||||
var pv = new ProtoView(templateAwareCreateElement('<div><span></span><span class="ng-binding"></span></div>'),
|
||||
new ProtoChangeDetector());
|
||||
new DynamicProtoChangeDetector());
|
||||
pv.bindElement(null);
|
||||
pv.bindElementProperty(parser.parseBinding('b', null), 'a', reflector.setter('a'));
|
||||
|
||||
@@ -146,7 +147,7 @@ export function main() {
|
||||
describe('collect text nodes with bindings', () => {
|
||||
|
||||
it('should collect text nodes under the root element', () => {
|
||||
var pv = new ProtoView(templateAwareCreateElement('<div class="ng-binding">{{}}<span></span>{{}}</div>'), new ProtoChangeDetector());
|
||||
var pv = new ProtoView(templateAwareCreateElement('<div class="ng-binding">{{}}<span></span>{{}}</div>'), new DynamicProtoChangeDetector());
|
||||
pv.bindElement(null);
|
||||
pv.bindTextNode(0, parser.parseBinding('a', null));
|
||||
pv.bindTextNode(2, parser.parseBinding('b', null));
|
||||
@@ -160,7 +161,7 @@ export function main() {
|
||||
|
||||
it('should collect text nodes with bindings on child elements with ng-binding class', () => {
|
||||
var pv = new ProtoView(templateAwareCreateElement('<div><span> </span><span class="ng-binding">{{}}</span></div>'),
|
||||
new ProtoChangeDetector());
|
||||
new DynamicProtoChangeDetector());
|
||||
pv.bindElement(null);
|
||||
pv.bindTextNode(0, parser.parseBinding('b', null));
|
||||
|
||||
@@ -176,7 +177,7 @@ export function main() {
|
||||
describe('inplace instantiation', () => {
|
||||
it('should be supported.', () => {
|
||||
var template = el('<div></div>');
|
||||
var pv = new ProtoView(template, new ProtoChangeDetector());
|
||||
var pv = new ProtoView(template, new DynamicProtoChangeDetector());
|
||||
pv.instantiateInPlace = true;
|
||||
var view = pv.instantiate(null);
|
||||
view.hydrate(null, null, null);
|
||||
@@ -185,7 +186,7 @@ export function main() {
|
||||
|
||||
it('should be off by default.', () => {
|
||||
var template = el('<div></div>')
|
||||
var view = new ProtoView(template, new ProtoChangeDetector())
|
||||
var view = new ProtoView(template, new DynamicProtoChangeDetector())
|
||||
.instantiate(null);
|
||||
view.hydrate(null, null, null);
|
||||
expect(view.nodes[0]).not.toBe(template);
|
||||
@@ -202,7 +203,7 @@ export function main() {
|
||||
|
||||
describe('create ElementInjectors', () => {
|
||||
it('should use the directives of the ProtoElementInjector', () => {
|
||||
var pv = new ProtoView(el('<div class="ng-binding"></div>'), new ProtoChangeDetector());
|
||||
var pv = new ProtoView(el('<div class="ng-binding"></div>'), new DynamicProtoChangeDetector());
|
||||
pv.bindElement(new ProtoElementInjector(null, 1, [SomeDirective]));
|
||||
|
||||
var view = pv.instantiate(null);
|
||||
@@ -213,7 +214,7 @@ export function main() {
|
||||
|
||||
it('should use the correct parent', () => {
|
||||
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
|
||||
new ProtoChangeDetector());
|
||||
new DynamicProtoChangeDetector());
|
||||
var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]);
|
||||
pv.bindElement(protoParent);
|
||||
pv.bindElement(new ProtoElementInjector(protoParent, 1, [AnotherDirective]));
|
||||
@@ -227,7 +228,7 @@ export function main() {
|
||||
|
||||
it('should not pass the host injector when a parent injector exists', () => {
|
||||
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
|
||||
new ProtoChangeDetector());
|
||||
new DynamicProtoChangeDetector());
|
||||
var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]);
|
||||
pv.bindElement(protoParent);
|
||||
var testProtoElementInjector = new TestProtoElementInjector(protoParent, 1, [AnotherDirective]);
|
||||
@@ -243,7 +244,7 @@ export function main() {
|
||||
|
||||
it('should pass the host injector when there is no parent injector', () => {
|
||||
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
|
||||
new ProtoChangeDetector());
|
||||
new DynamicProtoChangeDetector());
|
||||
pv.bindElement(new ProtoElementInjector(null, 0, [SomeDirective]));
|
||||
var testProtoElementInjector = new TestProtoElementInjector(null, 1, [AnotherDirective]);
|
||||
pv.bindElement(testProtoElementInjector);
|
||||
@@ -260,7 +261,7 @@ export function main() {
|
||||
|
||||
it('should collect a single root element injector', () => {
|
||||
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
|
||||
new ProtoChangeDetector());
|
||||
new DynamicProtoChangeDetector());
|
||||
var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]);
|
||||
pv.bindElement(protoParent);
|
||||
pv.bindElement(new ProtoElementInjector(protoParent, 1, [AnotherDirective]));
|
||||
@@ -273,7 +274,7 @@ export function main() {
|
||||
|
||||
it('should collect multiple root element injectors', () => {
|
||||
var pv = new ProtoView(el('<div><span class="ng-binding"></span><span class="ng-binding"></span></div>'),
|
||||
new ProtoChangeDetector());
|
||||
new DynamicProtoChangeDetector());
|
||||
pv.bindElement(new ProtoElementInjector(null, 1, [SomeDirective]));
|
||||
pv.bindElement(new ProtoElementInjector(null, 2, [AnotherDirective]));
|
||||
|
||||
@@ -290,7 +291,7 @@ export function main() {
|
||||
var ctx;
|
||||
|
||||
function createComponentWithSubPV(subProtoView) {
|
||||
var pv = new ProtoView(el('<cmp class="ng-binding"></cmp>'), new ProtoChangeDetector());
|
||||
var pv = new ProtoView(el('<cmp class="ng-binding"></cmp>'), new DynamicProtoChangeDetector());
|
||||
var binder = pv.bindElement(new ProtoElementInjector(null, 0, [SomeComponent], true));
|
||||
binder.componentDirective = someComponentDirective;
|
||||
binder.nestedProtoView = subProtoView;
|
||||
@@ -305,7 +306,7 @@ export function main() {
|
||||
}
|
||||
|
||||
it('should expose component services to the component', () => {
|
||||
var subpv = new ProtoView(el('<span></span>'), new ProtoChangeDetector());
|
||||
var subpv = new ProtoView(el('<span></span>'), new DynamicProtoChangeDetector());
|
||||
var pv = createComponentWithSubPV(subpv);
|
||||
|
||||
var view = createNestedView(pv);
|
||||
@@ -317,7 +318,7 @@ export function main() {
|
||||
it('should expose component services and component instance to directives in the shadow Dom',
|
||||
() => {
|
||||
var subpv = new ProtoView(
|
||||
el('<div dec class="ng-binding">hello shadow dom</div>'), new ProtoChangeDetector());
|
||||
el('<div dec class="ng-binding">hello shadow dom</div>'), new DynamicProtoChangeDetector());
|
||||
subpv.bindElement(
|
||||
new ProtoElementInjector(null, 0, [ServiceDependentDecorator]));
|
||||
var pv = createComponentWithSubPV(subpv);
|
||||
@@ -340,7 +341,7 @@ export function main() {
|
||||
|
||||
it('dehydration should dehydrate child component views too', () => {
|
||||
var subpv = new ProtoView(
|
||||
el('<div dec class="ng-binding">hello shadow dom</div>'), new ProtoChangeDetector());
|
||||
el('<div dec class="ng-binding">hello shadow dom</div>'), new DynamicProtoChangeDetector());
|
||||
subpv.bindElement(
|
||||
new ProtoElementInjector(null, 0, [ServiceDependentDecorator]));
|
||||
var pv = createComponentWithSubPV(subpv);
|
||||
@@ -355,7 +356,7 @@ export function main() {
|
||||
});
|
||||
|
||||
it('should create shadow dom', () => {
|
||||
var subpv = new ProtoView(el('<span>hello shadow dom</span>'), new ProtoChangeDetector());
|
||||
var subpv = new ProtoView(el('<span>hello shadow dom</span>'), new DynamicProtoChangeDetector());
|
||||
var pv = createComponentWithSubPV(subpv);
|
||||
|
||||
var view = createNestedView(pv);
|
||||
@@ -364,9 +365,9 @@ export function main() {
|
||||
});
|
||||
|
||||
it('should use the provided shadow DOM strategy', () => {
|
||||
var subpv = new ProtoView(el('<span>hello shadow dom</span>'), new ProtoChangeDetector());
|
||||
var subpv = new ProtoView(el('<span>hello shadow dom</span>'), new DynamicProtoChangeDetector());
|
||||
|
||||
var pv = new ProtoView(el('<cmp class="ng-binding"></cmp>'), new ProtoChangeDetector());
|
||||
var pv = new ProtoView(el('<cmp class="ng-binding"></cmp>'), new DynamicProtoChangeDetector());
|
||||
var binder = pv.bindElement(new ProtoElementInjector(null, 0, [SomeComponentWithEmulatedShadowDom], true));
|
||||
binder.componentDirective = new DirectiveMetadataReader().read(SomeComponentWithEmulatedShadowDom);
|
||||
binder.nestedProtoView = subpv;
|
||||
@@ -380,8 +381,8 @@ export function main() {
|
||||
describe('with template views', () => {
|
||||
function createViewWithTemplate() {
|
||||
var templateProtoView = new ProtoView(
|
||||
el('<div id="1"></div>'), new ProtoChangeDetector());
|
||||
var pv = new ProtoView(el('<someTmpl class="ng-binding"></someTmpl>'), new ProtoChangeDetector());
|
||||
el('<div id="1"></div>'), new DynamicProtoChangeDetector());
|
||||
var pv = new ProtoView(el('<someTmpl class="ng-binding"></someTmpl>'), new DynamicProtoChangeDetector());
|
||||
var binder = pv.bindElement(new ProtoElementInjector(null, 0, [SomeTemplate]));
|
||||
binder.templateDirective = someTemplateDirective;
|
||||
binder.nestedProtoView = templateProtoView;
|
||||
@@ -425,7 +426,7 @@ export function main() {
|
||||
|
||||
function createProtoView() {
|
||||
var pv = new ProtoView(el('<div class="ng-binding"><div></div></div>'),
|
||||
new ProtoChangeDetector());
|
||||
new DynamicProtoChangeDetector());
|
||||
pv.bindElement(new TestProtoElementInjector(null, 0, []));
|
||||
pv.bindEvent('click', parser.parseBinding('callMe(\$event)', null));
|
||||
return pv;
|
||||
@@ -460,7 +461,7 @@ export function main() {
|
||||
|
||||
it('should support custom event emitters', () => {
|
||||
var pv = new ProtoView(el('<div class="ng-binding"><div></div></div>'),
|
||||
new ProtoChangeDetector());
|
||||
new DynamicProtoChangeDetector());
|
||||
pv.bindElement(new TestProtoElementInjector(null, 0, [EventEmitterDirective]));
|
||||
pv.bindEvent('click', parser.parseBinding('callMe(\$event)', null));
|
||||
|
||||
@@ -491,7 +492,7 @@ export function main() {
|
||||
|
||||
it('should consume text node changes', () => {
|
||||
var pv = new ProtoView(el('<div class="ng-binding">{{}}</div>'),
|
||||
new ProtoChangeDetector());
|
||||
new DynamicProtoChangeDetector());
|
||||
pv.bindElement(null);
|
||||
pv.bindTextNode(0, parser.parseBinding('foo', null));
|
||||
createViewAndChangeDetector(pv);
|
||||
@@ -503,7 +504,7 @@ export function main() {
|
||||
|
||||
it('should consume element binding changes', () => {
|
||||
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
|
||||
new ProtoChangeDetector());
|
||||
new DynamicProtoChangeDetector());
|
||||
pv.bindElement(null);
|
||||
pv.bindElementProperty(parser.parseBinding('foo', null), 'id', reflector.setter('id'));
|
||||
createViewAndChangeDetector(pv);
|
||||
@@ -515,7 +516,7 @@ export function main() {
|
||||
|
||||
it('should consume directive watch expression change', () => {
|
||||
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
|
||||
new ProtoChangeDetector());
|
||||
new DynamicProtoChangeDetector());
|
||||
pv.bindElement(new ProtoElementInjector(null, 0, [SomeDirective]));
|
||||
pv.bindDirectiveProperty(0, parser.parseBinding('foo', null), 'prop', reflector.setter('prop'), false);
|
||||
createViewAndChangeDetector(pv);
|
||||
@@ -527,7 +528,7 @@ export function main() {
|
||||
|
||||
it('should notify a directive about changes after all its properties have been set', () => {
|
||||
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
|
||||
new ProtoChangeDetector());
|
||||
new DynamicProtoChangeDetector());
|
||||
|
||||
pv.bindElement(new ProtoElementInjector(null, 0, [DirectiveImplementingOnChange]));
|
||||
pv.bindDirectiveProperty( 0, parser.parseBinding('a', null), 'a', reflector.setter('a'), false);
|
||||
@@ -544,7 +545,7 @@ export function main() {
|
||||
|
||||
it('should provide a map of updated properties', () => {
|
||||
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
|
||||
new ProtoChangeDetector());
|
||||
new DynamicProtoChangeDetector());
|
||||
|
||||
pv.bindElement(new ProtoElementInjector(null, 0, [DirectiveImplementingOnChange]));
|
||||
pv.bindDirectiveProperty( 0, parser.parseBinding('a', null), 'a', reflector.setter('a'), false);
|
||||
@@ -569,18 +570,20 @@ export function main() {
|
||||
var element, pv;
|
||||
beforeEach(() => {
|
||||
element = DOM.createElement('div');
|
||||
pv = new ProtoView(el('<div>hi</div>'), new ProtoChangeDetector());
|
||||
pv = new ProtoView(el('<div>hi</div>'), new DynamicProtoChangeDetector());
|
||||
});
|
||||
|
||||
it('should create the root component when instantiated', () => {
|
||||
var rootProtoView = ProtoView.createRootProtoView(pv, element, someComponentDirective);
|
||||
var rootProtoView = ProtoView.createRootProtoView(pv, element,
|
||||
someComponentDirective, new DynamicProtoChangeDetector());
|
||||
var view = rootProtoView.instantiate(null);
|
||||
view.hydrate(new Injector([]), null, null);
|
||||
expect(view.rootElementInjectors[0].get(SomeComponent)).not.toBe(null);
|
||||
});
|
||||
|
||||
it('should inject the protoView into the shadowDom', () => {
|
||||
var rootProtoView = ProtoView.createRootProtoView(pv, element, someComponentDirective);
|
||||
var rootProtoView = ProtoView.createRootProtoView(pv, element,
|
||||
someComponentDirective, new DynamicProtoChangeDetector());
|
||||
var view = rootProtoView.instantiate(null);
|
||||
view.hydrate(new Injector([]), null, null);
|
||||
expect(element.shadowRoot.childNodes[0].childNodes[0].nodeValue).toEqual('hi');
|
||||
|
||||
@@ -6,10 +6,10 @@ import {DOM} from 'facade/dom';
|
||||
import {ListWrapper, MapWrapper} from 'facade/collection';
|
||||
import {Injector} from 'di/di';
|
||||
import {ProtoElementInjector, ElementInjector} from 'core/compiler/element_injector';
|
||||
import {ProtoChangeDetector, ChangeDetector, Lexer, Parser} from 'change_detection/change_detection';
|
||||
import {DynamicProtoChangeDetector, ChangeDetector, Lexer, Parser} from 'change_detection/change_detection';
|
||||
|
||||
function createView(nodes) {
|
||||
var view = new View(null, nodes, new ProtoChangeDetector(), MapWrapper.create());
|
||||
var view = new View(null, nodes, new DynamicProtoChangeDetector(), MapWrapper.create());
|
||||
view.init([], [], [], [], [], [], []);
|
||||
return view;
|
||||
}
|
||||
@@ -68,7 +68,7 @@ export function main() {
|
||||
dom = el(`<div><stuff></stuff><div insert-after-me></div><stuff></stuff></div>`);
|
||||
var insertionElement = dom.childNodes[1];
|
||||
parentView = createView([dom.childNodes[0]]);
|
||||
protoView = new ProtoView(el('<div>hi</div>'), new ProtoChangeDetector());
|
||||
protoView = new ProtoView(el('<div>hi</div>'), new DynamicProtoChangeDetector());
|
||||
elementInjector = new ElementInjector(null, null, null, null);
|
||||
viewPort = new ViewPort(parentView, insertionElement, protoView, elementInjector);
|
||||
customViewWithOneNode = createView([el('<div>single</div>')]);
|
||||
@@ -165,7 +165,7 @@ export function main() {
|
||||
expect(textInViewPort()).toEqual('filler one two');
|
||||
expect(viewPort.length).toBe(2);
|
||||
});
|
||||
|
||||
|
||||
it('should keep views hydration state during insert', () => {
|
||||
var hydratedView = new HydrateAwareFakeView(true);
|
||||
var dehydratedView = new HydrateAwareFakeView(false);
|
||||
@@ -212,7 +212,7 @@ export function main() {
|
||||
viewPort.hydrate(new Injector([]), null);
|
||||
|
||||
var pv = new ProtoView(el('<div class="ng-binding">{{}}</div>'),
|
||||
new ProtoChangeDetector());
|
||||
new DynamicProtoChangeDetector());
|
||||
pv.bindElement(new ProtoElementInjector(null, 1, [SomeDirective]));
|
||||
pv.bindTextNode(0, parser.parseBinding('foo', null));
|
||||
fancyView = pv.instantiate(null);
|
||||
|
||||
@@ -3,7 +3,7 @@ import {describe, xit, it, expect, beforeEach, ddescribe, iit, IS_DARTIUM, el} f
|
||||
import {DOM} from 'facade/dom';
|
||||
|
||||
import {Injector} from 'di/di';
|
||||
import {Lexer, Parser, ChangeDetector} from 'change_detection/change_detection';
|
||||
import {Lexer, Parser, ChangeDetector, dynamicChangeDetection} from 'change_detection/change_detection';
|
||||
|
||||
import {Compiler, CompilerCache} from 'core/compiler/compiler';
|
||||
import {DirectiveMetadataReader} from 'core/compiler/directive_metadata_reader';
|
||||
@@ -17,7 +17,8 @@ export function main() {
|
||||
describe('ng-if', () => {
|
||||
var view, cd, compiler, component;
|
||||
beforeEach(() => {
|
||||
compiler = new Compiler(null, new DirectiveMetadataReader(), new Parser(new Lexer()), new CompilerCache());
|
||||
compiler = new Compiler(dynamicChangeDetection, null, new DirectiveMetadataReader(),
|
||||
new Parser(new Lexer()), new CompilerCache());
|
||||
});
|
||||
|
||||
function createView(pv) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {describe, xit, it, expect, beforeEach, ddescribe, iit, el} from 'test_lib/test_lib';
|
||||
import {DOM} from 'facade/dom';
|
||||
import {Injector} from 'di/di';
|
||||
import {Lexer, Parser, ChangeDetector} from 'change_detection/change_detection';
|
||||
import {Lexer, Parser, ChangeDetector, dynamicChangeDetection} from 'change_detection/change_detection';
|
||||
import {Compiler, CompilerCache} from 'core/compiler/compiler';
|
||||
import {DirectiveMetadataReader} from 'core/compiler/directive_metadata_reader';
|
||||
import {Decorator, Component} from 'core/annotations/annotations';
|
||||
@@ -13,7 +13,8 @@ export function main() {
|
||||
describe('ng-non-bindable', () => {
|
||||
var view, cd, compiler, component;
|
||||
beforeEach(() => {
|
||||
compiler = new Compiler(null, new DirectiveMetadataReader(), new Parser(new Lexer()), new CompilerCache());
|
||||
compiler = new Compiler(dynamicChangeDetection,
|
||||
null, new DirectiveMetadataReader(), new Parser(new Lexer()), new CompilerCache());
|
||||
});
|
||||
|
||||
function createView(pv) {
|
||||
|
||||
@@ -3,7 +3,7 @@ import {describe, xit, it, expect, beforeEach, ddescribe, iit, el} from 'test_li
|
||||
import {DOM} from 'facade/dom';
|
||||
|
||||
import {Injector} from 'di/di';
|
||||
import {Lexer, Parser} from 'change_detection/change_detection';
|
||||
import {Lexer, Parser, ChangeDetector, dynamicChangeDetection} from 'change_detection/change_detection';
|
||||
|
||||
import {Compiler, CompilerCache} from 'core/compiler/compiler';
|
||||
import {OnChange} from 'core/compiler/interfaces';
|
||||
@@ -20,7 +20,8 @@ export function main() {
|
||||
describe('ng-repeat', () => {
|
||||
var view, cd, compiler, component;
|
||||
beforeEach(() => {
|
||||
compiler = new Compiler(null, new DirectiveMetadataReader(), new Parser(new Lexer()), new CompilerCache());
|
||||
compiler = new Compiler(dynamicChangeDetection, null, new DirectiveMetadataReader(),
|
||||
new Parser(new Lexer()), new CompilerCache());
|
||||
});
|
||||
|
||||
function createView(pv) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {describe, xit, it, expect, beforeEach, ddescribe, iit, el} from 'test_lib/test_lib';
|
||||
import {DOM} from 'facade/dom';
|
||||
import {Injector} from 'di/di';
|
||||
import {Lexer, Parser} from 'change_detection/change_detection';
|
||||
import {Lexer, Parser, dynamicChangeDetection} from 'change_detection/change_detection';
|
||||
import {Compiler, CompilerCache} from 'core/compiler/compiler';
|
||||
import {DirectiveMetadataReader} from 'core/compiler/directive_metadata_reader';
|
||||
import {Component} from 'core/annotations/annotations';
|
||||
@@ -12,7 +12,8 @@ export function main() {
|
||||
describe('ng-switch', () => {
|
||||
var view, cd, compiler, component;
|
||||
beforeEach(() => {
|
||||
compiler = new Compiler(null, new DirectiveMetadataReader(), new Parser(new Lexer()), new CompilerCache());
|
||||
compiler = new Compiler(dynamicChangeDetection, null, new DirectiveMetadataReader(),
|
||||
new Parser(new Lexer()), new CompilerCache());
|
||||
});
|
||||
|
||||
function createView(pv) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as app from './index_common';
|
||||
|
||||
import {Component, Decorator, TemplateConfig, NgElement} from 'angular/angular';
|
||||
import {Lexer, Parser, ChangeDetector} from 'change_detection/change_detection';
|
||||
import {Lexer, Parser, ChangeDetection, ChangeDetector} from 'change_detection/change_detection';
|
||||
import {LifeCycle} from 'core/life_cycle/life_cycle';
|
||||
|
||||
import {Compiler, CompilerCache} from 'core/compiler/compiler';
|
||||
@@ -37,8 +37,8 @@ function setup() {
|
||||
});
|
||||
|
||||
reflector.registerType(Compiler, {
|
||||
"factory": (templateLoader, reader, parser, compilerCache) => new Compiler(templateLoader, reader, parser, compilerCache),
|
||||
"parameters": [[TemplateLoader], [DirectiveMetadataReader], [Parser], [CompilerCache]],
|
||||
"factory": (changeDetection, templateLoader, reader, parser, compilerCache) => new Compiler(changeDetection, templateLoader, reader, parser, compilerCache),
|
||||
"parameters": [[ChangeDetection], [TemplateLoader], [DirectiveMetadataReader], [Parser], [CompilerCache]],
|
||||
"annotations": []
|
||||
});
|
||||
|
||||
|
||||
@@ -89,8 +89,8 @@ class ListWrapper {
|
||||
static reduce(List list, Function fn, init) {
|
||||
return list.fold(init, fn);
|
||||
}
|
||||
static first(List list) => list.first;
|
||||
static last(List list) => list.last;
|
||||
static first(List list) => list.isEmpty ? null : list.first;
|
||||
static last(List list) => list.isEmpty ? null : list.last;
|
||||
static List reversed(List list) => list.reversed.toList();
|
||||
static void push(List l, e) { l.add(e); }
|
||||
static List concat(List a, List b) {a.addAll(b); return a;}
|
||||
|
||||
@@ -27,6 +27,7 @@ class IMPLEMENTS {
|
||||
|
||||
bool isPresent(obj) => obj != null;
|
||||
bool isBlank(obj) => obj == null;
|
||||
bool isString(obj) => obj is String;
|
||||
|
||||
String stringify(obj) => obj.toString();
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user