Skip to content

Commit 8c566dc

Browse files
committed
feat(elementBinder): introduce element binder.
It is a plain-old-data class to seperate the protoInjector from the textNodes and elementBinding data.
1 parent ec7e853 commit 8c566dc

File tree

8 files changed

+71
-57
lines changed

8 files changed

+71
-57
lines changed

modules/benchmarks/src/element_injector/instantiate_benchmark.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export function run () {
88
var appInjector = new Injector([]);
99

1010
var bindings = [A, B, C];
11-
var proto = new ProtoElementInjector(null, bindings, [], false);
11+
var proto = new ProtoElementInjector(null, bindings);
1212
for (var i = 0; i < ITERATIONS; ++i) {
1313
var ei = proto.instantiate({view:null});
1414
ei.instantiateDirectives(appInjector);

modules/benchmarks/src/element_injector/instantiate_benchmark_codegen.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export function run () {
1616
], false)];
1717

1818

19-
var proto = new ProtoElementInjector(null, bindings, [], false);
19+
var proto = new ProtoElementInjector(null, bindings);
2020
for (var i = 0; i < ITERATIONS; ++i) {
2121
var ei = proto.instantiate({view:null});
2222
ei.instantiateDirectives(appInjector);
@@ -39,4 +39,4 @@ class C {
3939
constructor(a:A, b:B) {
4040
count++;
4141
}
42-
}
42+
}

modules/benchmarks/src/element_injector/instantiate_directive_benchmark.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export function run () {
88
var appInjector = new Injector([]);
99

1010
var bindings = [A, B, C];
11-
var proto = new ProtoElementInjector(null, bindings, [], false);
11+
var proto = new ProtoElementInjector(null, bindings);
1212
var ei = proto.instantiate({view:null});
1313

1414
for (var i = 0; i < ITERATIONS; ++i) {
@@ -33,4 +33,4 @@ class C {
3333
constructor(a:A, b:B) {
3434
count++;
3535
}
36-
}
36+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {ProtoElementInjector} from './element_injector';
2+
import {FIELD} from 'facade/lang';
3+
import {List} from 'facade/collection';
4+
5+
export class ElementBinder {
6+
@FIELD('final protoElementInjector:ProtoElementInjector')
7+
@FIELD('final textNodeIndices:List<int>')
8+
@FIELD('final hasElementPropertyBindings:bool')
9+
constructor(protoElementInjector: ProtoElementInjector,
10+
textNodeIndices:List, hasElementPropertyBindings:boolean) {
11+
this.protoElementInjector = protoElementInjector;
12+
this.textNodeIndices = textNodeIndices;
13+
this.hasElementPropertyBindings = hasElementPropertyBindings;
14+
}
15+
}

modules/core/src/compiler/element_injector.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,7 @@ export class ProtoElementInjector extends TreeNode {
146146
@FIELD('_key7:int')
147147
@FIELD('_key8:int')
148148
@FIELD('_key9:int')
149-
@FIELD('textNodeIndices:List<int>')
150-
@FIELD('hasElementPropertyBindings:bool')
151-
constructor(parent:ProtoElementInjector, bindings:List, textNodeIndices:List,
152-
hasElementPropertyBindings:boolean) {
149+
constructor(parent:ProtoElementInjector, bindings:List) {
153150
super(parent);
154151

155152
this._elementInjector = null;
@@ -180,9 +177,6 @@ export class ProtoElementInjector extends TreeNode {
180177
if (length > 10) {
181178
throw 'Maximum number of directives per element has been reached.';
182179
}
183-
184-
this.textNodeIndices = textNodeIndices;
185-
this.hasElementPropertyBindings = hasElementPropertyBindings;
186180
}
187181

188182
instantiate({view}):ElementInjector {

modules/core/src/compiler/view.js

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {ListWrapper} from 'facade/collection';
33
import {ProtoWatchGroup, WatchGroup, WatchGroupDispatcher} from 'change_detection/watch_group';
44
import {Record} from 'change_detection/record';
55
import {ProtoElementInjector, ElementInjector} from './element_injector';
6+
import {ElementBinder} from './element_binder';
67
import {SetterFn} from 'change_detection/facade';
78
import {FIELD, IMPLEMENTS, int, isPresent, isBlank} from 'facade/lang';
89
import {List} from 'facade/collection';
@@ -57,19 +58,16 @@ export class View {
5758

5859
export class ProtoView {
5960
@FIELD('final _template:TemplateElement')
60-
@FIELD('final _bindings:List')
61-
@FIELD('final _protoElementInjectors:List<ProtoElementInjector>')
61+
@FIELD('final _elementBinders:List<ElementBinder>')
6262
@FIELD('final _protoWatchGroup:ProtoWatchGroup')
6363
@FIELD('final _useRootElement:bool')
6464
constructor(
6565
template:TemplateElement,
66-
bindings:List,
67-
protoElementInjectors:List,
66+
elementBinders:List,
6867
protoWatchGroup:ProtoWatchGroup,
6968
useRootElement:boolean) {
7069
this._template = template;
71-
this._bindings = bindings;
72-
this._protoElementInjectors = protoElementInjectors;
70+
this._elementBinders = elementBinders;
7371
this._protoWatchGroup = protoWatchGroup;
7472

7573
// not implemented
@@ -79,31 +77,32 @@ export class ProtoView {
7977
instantiate(context, appInjector:Injector):View {
8078
var fragment = DOM.clone(this._template.content);
8179
var elements = DOM.querySelectorAll(fragment, ".ng-binding");
82-
var protos = this._protoElementInjectors;
80+
var binders = this._elementBinders;
8381

8482
/**
8583
* TODO: vsavkin: benchmark
8684
* If this performs poorly, the five loops can be collapsed into one.
8785
*/
88-
var elementInjectors = ProtoView._createElementInjectors(elements, protos);
86+
var elementInjectors = ProtoView._createElementInjectors(elements, binders);
8987
var rootElementInjectors = ProtoView._rootElementInjectors(elementInjectors);
90-
var textNodes = ProtoView._textNodes(elements, protos);
91-
var bindElements = ProtoView._bindElements(elements, protos);
88+
var textNodes = ProtoView._textNodes(elements, binders);
89+
var bindElements = ProtoView._bindElements(elements, binders);
9290
ProtoView._instantiateDirectives(elementInjectors, appInjector);
9391

9492
return new View(fragment, elementInjectors, rootElementInjectors, textNodes,
9593
bindElements, this._protoWatchGroup, context);
9694
}
9795

98-
static _createElementInjectors(elements, protos) {
99-
var injectors = ListWrapper.createFixedSize(protos.length);
100-
for (var i = 0; i < protos.length; ++i) {
101-
injectors[i] = ProtoView._createElementInjector(elements[i], protos[i]);
96+
static _createElementInjectors(elements, binders) {
97+
var injectors = ListWrapper.createFixedSize(binders.length);
98+
for (var i = 0; i < binders.length; ++i) {
99+
injectors[i] = ProtoView._createElementInjector(
100+
elements[i], binders[i].protoElementInjector);
102101
}
103102
// Cannot be rolled into loop above, because parentInjector pointers need
104103
// to be set on the children.
105-
for (var i = 0; i < protos.length; ++i) {
106-
protos[i].clearElementInjector();
104+
for (var i = 0; i < binders.length; ++i) {
105+
binders[i].protoElementInjector.clearElementInjector();
107106
}
108107
return injectors;
109108
}
@@ -124,19 +123,19 @@ export class ProtoView {
124123
return ListWrapper.filter(injectors, inj => isPresent(inj) && isBlank(inj.parent));
125124
}
126125

127-
static _textNodes(elements, protos) {
126+
static _textNodes(elements, binders) {
128127
var textNodes = [];
129-
for (var i = 0; i < protos.length; ++i) {
128+
for (var i = 0; i < binders.length; ++i) {
130129
ProtoView._collectTextNodes(textNodes, elements[i],
131-
protos[i].textNodeIndices);
130+
binders[i].textNodeIndices);
132131
}
133132
return textNodes;
134133
}
135134

136-
static _bindElements(elements, protos):List<Element> {
135+
static _bindElements(elements, binders):List<Element> {
137136
var bindElements = [];
138-
for (var i = 0; i < protos.length; ++i) {
139-
if (protos[i].hasElementPropertyBindings) ListWrapper.push(
137+
for (var i = 0; i < binders.length; ++i) {
138+
if (binders[i].hasElementPropertyBindings) ListWrapper.push(
140139
bindElements, elements[i]);
141140
}
142141
return bindElements;

modules/core/test/compiler/element_injector_spec.js

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export function main() {
7070
if (isBlank(appInjector)) appInjector = new Injector([]);
7171
if (isBlank(props)) props = {};
7272

73-
var proto = new ProtoElementInjector(null, bindings, [], false);
73+
var proto = new ProtoElementInjector(null, bindings);
7474
var inj = proto.instantiate({view: props["view"]});
7575
inj.instantiateDirectives(appInjector);
7676
return inj;
@@ -79,12 +79,11 @@ export function main() {
7979
function parentChildInjectors(parentBindings, childBindings) {
8080
var inj = new Injector([]);
8181

82-
var protoParent = new ProtoElementInjector(null, parentBindings, [], false);
82+
var protoParent = new ProtoElementInjector(null, parentBindings);
8383
var parent = protoParent.instantiate({view: null});
8484
parent.instantiateDirectives(inj);
8585

86-
var protoChild = new ProtoElementInjector(protoParent, childBindings, [],
87-
false);
86+
var protoChild = new ProtoElementInjector(protoParent, childBindings);
8887
var child = protoChild.instantiate({view: null});
8988
child.instantiateDirectives(inj);
9089

@@ -94,9 +93,9 @@ export function main() {
9493
describe("ElementInjector", function () {
9594
describe("proto injectors", function () {
9695
it("should construct a proto tree", function () {
97-
var p = new ProtoElementInjector(null, [], [], false);
98-
var c1 = new ProtoElementInjector(p, [], [], false);
99-
var c2 = new ProtoElementInjector(p, [], [], false);
96+
var p = new ProtoElementInjector(null, []);
97+
var c1 = new ProtoElementInjector(p, []);
98+
var c2 = new ProtoElementInjector(p, []);
10099

101100
expect(humanize(p, [
102101
[p, 'parent'],
@@ -108,9 +107,9 @@ export function main() {
108107

109108
describe("instantiate", function () {
110109
it("should create an element injector", function () {
111-
var protoParent = new ProtoElementInjector(null, [], [], false);
112-
var protoChild1 = new ProtoElementInjector(protoParent, [], [], false);
113-
var protoChild2 = new ProtoElementInjector(protoParent, [], [], false);
110+
var protoParent = new ProtoElementInjector(null, []);
111+
var protoChild1 = new ProtoElementInjector(protoParent, []);
112+
var protoChild2 = new ProtoElementInjector(protoParent, []);
114113

115114
var p = protoParent.instantiate({view: null});
116115
var c1 = protoChild1.instantiate({view: null});
@@ -126,12 +125,12 @@ export function main() {
126125

127126
describe("hasBindings", function () {
128127
it("should be true when there are bindings", function () {
129-
var p = new ProtoElementInjector(null, [Directive], [], false);
128+
var p = new ProtoElementInjector(null, [Directive]);
130129
expect(p.hasBindings).toBeTruthy();
131130
});
132131

133132
it("should be false otherwise", function () {
134-
var p = new ProtoElementInjector(null, [], [], false);
133+
var p = new ProtoElementInjector(null, []);
135134
expect(p.hasBindings).toBeFalsy();
136135
});
137136
});

modules/core/test/compiler/view_spec.js

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {DOM, Element} from 'facade/dom';
88
import {FIELD} from 'facade/lang';
99
import {ImplicitReceiver, FieldRead} from 'change_detection/parser/ast';
1010
import {ClosureMap} from 'change_detection/parser/closure_map';
11+
import {ElementBinder} from 'core/compiler/element_binder';
1112

1213
class Directive {
1314
@FIELD('prop')
@@ -30,20 +31,24 @@ export function main() {
3031
'</div>' +
3132
'</section>';
3233

33-
function templateElInj() {
34-
var sectionPI = new ProtoElementInjector(null, [], [0], false);
35-
var divPI = new ProtoElementInjector(sectionPI, [Directive], [], false);
36-
var spanPI = new ProtoElementInjector(divPI, [], [], true);
34+
function templateElementBinders() {
35+
var sectionPI = new ElementBinder(new ProtoElementInjector(null, []),
36+
[0], false);
37+
38+
var divPI = new ElementBinder(new ProtoElementInjector(
39+
sectionPI.protoElementInjector, [Directive]), [], false);
40+
41+
var spanPI = new ElementBinder(new ProtoElementInjector(
42+
divPI.protoElementInjector, []), [], true);
3743
return [sectionPI, divPI, spanPI];
3844
}
3945

4046
describe('ProtoView', function() {
4147
it('should create view instance and locate basic parts', function() {
4248
var template = DOM.createTemplate(tempalteWithThreeTypesOfBindings);
4349

44-
var diBindings = [];
4550
var hasSingleRoot = false;
46-
var pv = new ProtoView(template, diBindings, templateElInj(),
51+
var pv = new ProtoView(template, templateElementBinders(),
4752
new ProtoWatchGroup(), hasSingleRoot);
4853

4954
var view = pv.instantiate(null, null);
@@ -68,10 +73,12 @@ export function main() {
6873
'<div directive class="ng-binding"></div>' +
6974
'</section>');
7075

71-
var sectionPI = new ProtoElementInjector(null, [Directive], [], false);
72-
var divPI = new ProtoElementInjector(sectionPI, [Directive], [], false);
76+
var sectionPI = new ElementBinder(new ProtoElementInjector(
77+
null, [Directive]), [], false);
78+
var divPI = new ElementBinder(new ProtoElementInjector(
79+
sectionPI.protoElementInjector, [Directive]), [], false);
7380

74-
var pv = new ProtoView(template, [], [sectionPI, divPI],
81+
var pv = new ProtoView(template, [sectionPI, divPI],
7582
new ProtoWatchGroup(), false);
7683
var view = pv.instantiate(null, null);
7784

@@ -82,7 +89,7 @@ export function main() {
8289
var view;
8390
beforeEach(() => {
8491
var template = DOM.createTemplate(tempalteWithThreeTypesOfBindings);
85-
var pv = new ProtoView(template, [], templateElInj(),
92+
var pv = new ProtoView(template, templateElementBinders(),
8693
new ProtoWatchGroup(), false);
8794
view = pv.instantiate(null, null);
8895
});
@@ -125,7 +132,7 @@ export function main() {
125132
var protoWatchGroup = new ProtoWatchGroup();
126133
protoWatchGroup.watch(oneFieldAst('foo'), memento);
127134

128-
var pv = new ProtoView(template, [], templateElInj(),
135+
var pv = new ProtoView(template, templateElementBinders(),
129136
protoWatchGroup, false);
130137

131138
ctx = new MyEvaluationContext();

0 commit comments

Comments
 (0)