refactor(ElementInjector): use `index` instead of the `elementInjector` field to instantiate element injectors

This commit is contained in:
vsavkin 2014-11-04 17:03:35 -08:00
parent 7908533336
commit b5f6417635
7 changed files with 38 additions and 94 deletions

View File

@ -8,9 +8,9 @@ export function run () {
var appInjector = new Injector([]);
var bindings = [A, B, C];
var proto = new ProtoElementInjector(null, bindings);
var proto = new ProtoElementInjector(null, 0, bindings);
for (var i = 0; i < ITERATIONS; ++i) {
var ei = proto.instantiate({view:null});
var ei = proto.instantiate({view:null, parentElementInjector: null});
ei.instantiateDirectives(appInjector);
}
}

View File

@ -16,9 +16,9 @@ export function run () {
], false)];
var proto = new ProtoElementInjector(null, bindings);
var proto = new ProtoElementInjector(null, 0, bindings);
for (var i = 0; i < ITERATIONS; ++i) {
var ei = proto.instantiate({view:null});
var ei = proto.instantiate({view:null, parentElementInjector: null});
ei.instantiateDirectives(appInjector);
}
}

View File

@ -8,8 +8,8 @@ export function run () {
var appInjector = new Injector([]);
var bindings = [A, B, C];
var proto = new ProtoElementInjector(null, bindings);
var ei = proto.instantiate({view:null});
var proto = new ProtoElementInjector(null, 0, bindings);
var ei = proto.instantiate({view:null, parentElementInjector: null});
for (var i = 0; i < ITERATIONS; ++i) {
ei.clearDirectives();

View File

@ -93,39 +93,7 @@ ElementInjector (ElementModule):
PERF BENCHMARK: http://www.williambrownstreet.net/blog/2014/04/faster-angularjs-rendering-angularjs-and-reactjs/
*/
export class ProtoElementInjector extends TreeNode {
/**
parent:ProtoDirectiveInjector;
next:ProtoDirectiveInjector;
prev:ProtoDirectiveInjector;
head:ProtoDirectiveInjector;
tail:ProtoDirectiveInjector;
DirectiveInjector cloningInstance;
KeyMap keyMap;
/// Because DI tree is sparse, this shows how far away is the Parent DI
parentDistance:int = 1; /// 1 for non-sparse/normal depth.
cKey:int; cFactory:Function; cParams:List<int>;
_keyId0:int; factory0:Function; params0:List<int>;
_keyId1:int; factory1:Function; params1:List<int>;
_keyId2:int; factory2:Function; params2:List<int>;
_keyId3:int; factory3:Function; params3:List<int>;
_keyId4:int; factory4:Function; params4:List<int>;
_keyId5:int; factory5:Function; params5:List<int>;
_keyId6:int; factory6:Function; params6:List<int>;
_keyId7:int; factory7:Function; params7:List<int>;
_keyId8:int; factory8:Function; params8:List<int>;
_keyId9:int; factory9:Function; params9:List<int>;
query_keyId0:int;
query_keyId1:int;
textNodes:List<int>;
events:Map<string, Expression>;
elementInjector:ElementInjector;
*/
@FIELD('_elementInjector:ElementInjector')
export class ProtoElementInjector {
@FIELD('_binding0:Binding')
@FIELD('_binding1:Binding')
@FIELD('_binding2:Binding')
@ -146,10 +114,11 @@ export class ProtoElementInjector extends TreeNode {
@FIELD('_key7:int')
@FIELD('_key8:int')
@FIELD('_key9:int')
constructor(parent:ProtoElementInjector, bindings:List) {
super(parent);
this._elementInjector = null;
@FIELD('final parent:ProtoElementInjector')
@FIELD('final index:int')
constructor(parent:ProtoElementInjector, index:int, bindings:List) {
this.parent = parent;
this.index = index;
this._binding0 = null; this._keyId0 = null;
this._binding1 = null; this._keyId1 = null;
@ -179,15 +148,12 @@ export class ProtoElementInjector extends TreeNode {
}
}
instantiate({view}):ElementInjector {
var p = this._parent;
var parentElementInjector = p === null ? null : p._elementInjector;
this._elementInjector = new ElementInjector({
instantiate({view, parentElementInjector}):ElementInjector {
return new ElementInjector({
proto: this,
parent: parentElementInjector,
view: view
});
return this._elementInjector;
}
_createBinding(bindingOrType) {
@ -198,10 +164,6 @@ export class ProtoElementInjector extends TreeNode {
return new Binding(b.key, b.factory, deps, b.providedAsPromise);
}
clearElementInjector() {
this._elementInjector = null;
}
get hasBindings():boolean {
return isPresent(this._binding0);
}

View File

@ -99,13 +99,9 @@ export class ProtoView {
static _createElementInjectors(elements, binders) {
var injectors = ListWrapper.createFixedSize(binders.length);
for (var i = 0; i < binders.length; ++i) {
injectors[i] = ProtoView._createElementInjector(
elements[i], binders[i].protoElementInjector);
}
// Cannot be rolled into loop above, because parentInjector pointers need
// to be set on the children.
for (var i = 0; i < binders.length; ++i) {
binders[i].protoElementInjector.clearElementInjector();
var proto = binders[i].protoElementInjector;
var parentElementInjector = isPresent(proto.parent) ? injectors[proto.parent.index] : null;
injectors[i] = ProtoView._createElementInjector(elements[i], parentElementInjector, proto);
}
return injectors;
}
@ -117,9 +113,9 @@ export class ProtoView {
}
}
static _createElementInjector(element, proto) {
static _createElementInjector(element, parent:ElementInjector, proto:ProtoElementInjector) {
//TODO: vsavkin: pass element to `proto.instantiate()` once https://github.com/angular/angular/pull/98 is merged
return proto.hasBindings ? proto.instantiate({view:null}) : null;
return proto.hasBindings ? proto.instantiate({view:null, parentElementInjector:parent}) : null;
}
static _rootElementInjectors(injectors) {

View File

@ -70,8 +70,8 @@ export function main() {
if (isBlank(appInjector)) appInjector = new Injector([]);
if (isBlank(props)) props = {};
var proto = new ProtoElementInjector(null, bindings);
var inj = proto.instantiate({view: props["view"]});
var proto = new ProtoElementInjector(null, 0, bindings);
var inj = proto.instantiate({view: props["view"], parentElementInjector:null});
inj.instantiateDirectives(appInjector);
return inj;
}
@ -79,41 +79,27 @@ export function main() {
function parentChildInjectors(parentBindings, childBindings) {
var inj = new Injector([]);
var protoParent = new ProtoElementInjector(null, parentBindings);
var parent = protoParent.instantiate({view: null});
var protoParent = new ProtoElementInjector(null, 0, parentBindings);
var parent = protoParent.instantiate({view: null, parentElementInjector: null});
parent.instantiateDirectives(inj);
var protoChild = new ProtoElementInjector(protoParent, childBindings);
var child = protoChild.instantiate({view: null});
var protoChild = new ProtoElementInjector(protoParent, 1, childBindings);
var child = protoChild.instantiate({view: null, parentElementInjector: parent});
child.instantiateDirectives(inj);
return child;
}
describe("ElementInjector", function () {
describe("proto injectors", function () {
it("should construct a proto tree", function () {
var p = new ProtoElementInjector(null, []);
var c1 = new ProtoElementInjector(p, []);
var c2 = new ProtoElementInjector(p, []);
expect(humanize(p, [
[p, 'parent'],
[c1, 'child1'],
[c2, 'child2']
])).toEqual(["parent", ["child1", "child2"]]);
});
});
describe("instantiate", function () {
it("should create an element injector", function () {
var protoParent = new ProtoElementInjector(null, []);
var protoChild1 = new ProtoElementInjector(protoParent, []);
var protoChild2 = new ProtoElementInjector(protoParent, []);
var protoParent = new ProtoElementInjector(null, 0, []);
var protoChild1 = new ProtoElementInjector(protoParent, 1, []);
var protoChild2 = new ProtoElementInjector(protoParent, 2, []);
var p = protoParent.instantiate({view: null});
var c1 = protoChild1.instantiate({view: null});
var c2 = protoChild2.instantiate({view: null});
var p = protoParent.instantiate({view: null, parentElementInjector: null});
var c1 = protoChild1.instantiate({view: null, parentElementInjector: p});
var c2 = protoChild2.instantiate({view: null, parentElementInjector: p});
expect(humanize(p, [
[p, 'parent'],
@ -125,12 +111,12 @@ export function main() {
describe("hasBindings", function () {
it("should be true when there are bindings", function () {
var p = new ProtoElementInjector(null, [Directive]);
var p = new ProtoElementInjector(null, 0, [Directive]);
expect(p.hasBindings).toBeTruthy();
});
it("should be false otherwise", function () {
var p = new ProtoElementInjector(null, []);
var p = new ProtoElementInjector(null, 0, []);
expect(p.hasBindings).toBeFalsy();
});
});

View File

@ -34,14 +34,14 @@ export function main() {
'</section>';
function templateElementBinders() {
var sectionPI = new ElementBinder(new ProtoElementInjector(null, []),
var sectionPI = new ElementBinder(new ProtoElementInjector(null, 0, []),
[0], false);
var divPI = new ElementBinder(new ProtoElementInjector(
sectionPI.protoElementInjector, [Directive]), [], false);
sectionPI.protoElementInjector, 1, [Directive]), [], false);
var spanPI = new ElementBinder(new ProtoElementInjector(
divPI.protoElementInjector, []), [], true);
divPI.protoElementInjector, 2, []), [], true);
return [sectionPI, divPI, spanPI];
}
@ -76,9 +76,9 @@ export function main() {
'</section>');
var sectionPI = new ElementBinder(new ProtoElementInjector(
null, [Directive]), [], false);
null, 0, [Directive]), [], false);
var divPI = new ElementBinder(new ProtoElementInjector(
sectionPI.protoElementInjector, [Directive]), [], false);
sectionPI.protoElementInjector, 1, [Directive]), [], false);
var pv = new ProtoView(template, [sectionPI, divPI],
new ProtoWatchGroup(), false);