Skip to content

Commit 678d541

Browse files
vicbmhevery
authored andcommitted
refactor(compiler): add control.ignoreCurrentElement() to skip the current element
relates to angular#808
1 parent f0477e1 commit 678d541

File tree

8 files changed

+60
-52
lines changed

8 files changed

+60
-52
lines changed

modules/angular2/src/render/dom/compiler/compile_control.js

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ export class CompileControl {
1313
_parent:CompileElement;
1414
_results;
1515
_additionalChildren;
16+
_ignoreCurrentElement: boolean;
17+
1618
constructor(steps) {
1719
this._steps = steps;
1820
this._currentStepIndex = 0;
@@ -27,14 +29,21 @@ export class CompileControl {
2729
var previousStepIndex = this._currentStepIndex;
2830
var previousParent = this._parent;
2931

30-
for (var i=startStepIndex; i<this._steps.length; i++) {
32+
this._ignoreCurrentElement = false;
33+
34+
for (var i = startStepIndex;
35+
i < this._steps.length && !this._ignoreCurrentElement;
36+
i++) {
3137
var step = this._steps[i];
3238
this._parent = parent;
3339
this._currentStepIndex = i;
3440
step.process(parent, current, this);
3541
parent = this._parent;
3642
}
37-
ListWrapper.push(results, current);
43+
44+
if (!this._ignoreCurrentElement) {
45+
ListWrapper.push(results, current);
46+
}
3847

3948
this._currentStepIndex = previousStepIndex;
4049
this._parent = previousParent;
@@ -55,4 +64,14 @@ export class CompileControl {
5564
}
5665
ListWrapper.push(this._additionalChildren, element);
5766
}
67+
68+
/**
69+
* Ignores the current element.
70+
*
71+
* When a step call [ignoreCurrentElement], no further steps are executed on the current
72+
* element and no [CompileElement] is added to the result list.
73+
*/
74+
ignoreCurrentElement() {
75+
this._ignoreCurrentElement = true;
76+
}
5877
}

modules/angular2/src/render/dom/compiler/compile_element.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ export class CompileElement {
1818
distanceToInheritedBinder:number;
1919
inheritedElementBinder:ElementBinderBuilder;
2020
compileChildren: boolean;
21-
ignoreBindings: boolean;
2221
elementDescription: string; // e.g. '<div [class]="foo">' : used to provide context in case of error
2322

2423
constructor(element, compilationUnit = '') {
@@ -34,8 +33,6 @@ export class CompileElement {
3433
this.inheritedElementBinder = null;
3534
this.distanceToInheritedBinder = 0;
3635
this.compileChildren = true;
37-
// set to true to ignore all the bindings on the element
38-
this.ignoreBindings = false;
3936
// description is calculated here as compilation steps may change the element
4037
var tplDesc = assertionsEnabled()? getElementDescription(element) : null;
4138
if (compilationUnit !== '') {

modules/angular2/src/render/dom/compiler/property_binding_parser.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@ export class PropertyBindingParser extends CompileStep {
3030
}
3131

3232
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
33-
if (current.ignoreBindings) {
34-
return;
35-
}
36-
3733
var attrs = current.attrs();
3834
var newAttrs = MapWrapper.create();
3935

modules/angular2/src/render/dom/compiler/text_interpolation_parser.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export class TextInterpolationParser extends CompileStep {
1919
}
2020

2121
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
22-
if (!current.compileChildren || current.ignoreBindings) {
22+
if (!current.compileChildren) {
2323
return;
2424
}
2525
var element = current.element;

modules/angular2/src/render/dom/shadow_dom/shadow_dom_compile_step.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,9 @@ export class ShadowDomCompileStep extends CompileStep {
2323
}
2424

2525
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
26-
if (current.ignoreBindings) {
27-
return;
28-
}
2926
var tagName = DOM.tagName(current.element).toUpperCase();
3027
if (tagName == 'STYLE') {
31-
this._processStyleElement(current);
28+
this._processStyleElement(current, control);
3229
} else if (tagName == 'CONTENT') {
3330
this._processContentElement(current);
3431
} else {
@@ -39,17 +36,20 @@ export class ShadowDomCompileStep extends CompileStep {
3936
}
4037
}
4138

42-
_processStyleElement(current) {
43-
current.ignoreBindings = true;
39+
_processStyleElement(current:CompileElement, control:CompileControl) {
4440
var stylePromise = this._shadowDomStrategy.processStyleElement(
4541
this._template.componentId, this._template.absUrl, current.element
4642
);
4743
if (isPresent(stylePromise) && PromiseWrapper.isPromise(stylePromise)) {
4844
ListWrapper.push(this._subTaskPromises, stylePromise);
4945
}
46+
47+
// Style elements should not be further processed by the compiler, as they can not contain
48+
// bindings. Skipping further compiler steps allow speeding up the compilation process.
49+
control.ignoreCurrentElement();
5050
}
5151

52-
_processContentElement(current) {
52+
_processContentElement(current:CompileElement) {
5353
if (this._shadowDomStrategy.hasNativeContentElement()) {
5454
return;
5555
}

modules/angular2/test/render/dom/compiler/pipeline_spec.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,19 @@ export function main() {
8080
expect(results[3].inheritedElementBinder.parent).toBe(results[0].inheritedElementBinder);
8181
});
8282

83+
it('should not execute further steps when ignoreCurrentElement has been called', () => {
84+
var element = el('<div id="1"><span id="2" ignore-current></span><span id="3"></span></div>');
85+
var logs = [];
86+
var pipeline = new CompilePipeline([
87+
new IgnoreCurrentElementStep(),
88+
createLoggerStep(logs),
89+
]);
90+
var results = pipeline.process(element);
91+
92+
expect(results.length).toBe(2);
93+
expect(logs).toEqual(['1', '1<3'])
94+
});
95+
8396
describe('control.addParent', () => {
8497
it('should report the new parent to the following processor and the result', () => {
8598
var element = el('<div id="1"><span wrap0="1" id="2"><b id="3"></b></span></div>');
@@ -188,6 +201,15 @@ export class IgnoreChildrenStep extends CompileStep {
188201
}
189202
}
190203

204+
class IgnoreCurrentElementStep extends CompileStep {
205+
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
206+
var attributeMap = DOM.attributeMap(current.element);
207+
if (MapWrapper.contains(attributeMap, 'ignore-current')) {
208+
control.ignoreCurrentElement();
209+
}
210+
}
211+
}
212+
191213
function logEntry(log, parent, current) {
192214
var parentId = '';
193215
if (isPresent(parent)) {
@@ -223,4 +245,4 @@ function resultIdLog(result) {
223245
logEntry(idLog, null, current);
224246
});
225247
return idLog;
226-
}
248+
}

modules/angular2/test/render/dom/compiler/property_binding_parser_spec.js

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,23 @@ var EMPTY_MAP = MapWrapper.create();
1111

1212
export function main() {
1313
describe('PropertyBindingParser', () => {
14-
function createPipeline(ignoreBindings = false, hasNestedProtoView = false) {
14+
function createPipeline(hasNestedProtoView = false) {
1515
return new CompilePipeline([
1616
new MockStep((parent, current, control) => {
17-
current.ignoreBindings = ignoreBindings;
1817
if (hasNestedProtoView) {
1918
current.bindElement().bindNestedProtoView(el('<template></template>'));
2019
}
2120
}),
2221
new PropertyBindingParser(new Parser(new Lexer()))]);
2322
}
2423

25-
function process(element, ignoreBindings = false, hasNestedProtoView = false) {
24+
function process(element, hasNestedProtoView = false) {
2625
return ListWrapper.map(
27-
createPipeline(ignoreBindings, hasNestedProtoView).process(element),
26+
createPipeline(hasNestedProtoView).process(element),
2827
(compileElement) => compileElement.inheritedElementBinder
2928
);
3029
}
3130

32-
it('should not parse bindings when ignoreBindings is true', () => {
33-
var results = process(el('<div [a]="b"></div>'), true);
34-
expect(results[0]).toEqual(null);
35-
});
36-
3731
it('should detect [] syntax', () => {
3832
var results = process(el('<div [a]="b"></div>'));
3933
expect(MapWrapper.get(results[0].propertyBindings, 'a').source).toEqual('b');
@@ -64,13 +58,13 @@ export function main() {
6458
});
6559

6660
it('should store variable binding for a template element on the nestedProtoView', () => {
67-
var results = process(el('<template var-george="washington"></p>'), false, true);
61+
var results = process(el('<template var-george="washington"></p>'), true);
6862
expect(results[0].variableBindings).toEqual(EMPTY_MAP);
6963
expect(MapWrapper.get(results[0].nestedProtoView.variableBindings, 'washington')).toEqual('george');
7064
});
7165

7266
it('should store variable binding for a non-template element using shorthand syntax on the nestedProtoView', () => {
73-
var results = process(el('<template #george="washington"></template>'), false, true);
67+
var results = process(el('<template #george="washington"></template>'), true);
7468
expect(results[0].variableBindings).toEqual(EMPTY_MAP);
7569
expect(MapWrapper.get(results[0].nestedProtoView.variableBindings, 'washington')).toEqual('george');
7670
});

modules/angular2/test/render/dom/compiler/text_interpolation_parser_spec.js

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,20 @@ import {TextInterpolationParser} from 'angular2/src/render/dom/compiler/text_int
33
import {CompilePipeline} from 'angular2/src/render/dom/compiler/compile_pipeline';
44
import {MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
55
import {Lexer, Parser} from 'angular2/change_detection';
6-
import {CompileElement} from 'angular2/src/render/dom/compiler/compile_element';
7-
import {CompileStep} from 'angular2/src/render/dom/compiler/compile_step'
8-
import {CompileControl} from 'angular2/src/render/dom/compiler/compile_control';
96
import {IgnoreChildrenStep} from './pipeline_spec';
107

118
export function main() {
129
describe('TextInterpolationParser', () => {
13-
function createPipeline(ignoreBindings = false) {
10+
function createPipeline() {
1411
return new CompilePipeline([
15-
new MockStep((parent, current, control) => { current.ignoreBindings = ignoreBindings; }),
1612
new IgnoreChildrenStep(),
1713
new TextInterpolationParser(new Parser(new Lexer()))
1814
]);
1915
}
2016

21-
function process(element, ignoreBindings = false) {
17+
function process(element) {
2218
return ListWrapper.map(
23-
createPipeline(ignoreBindings).process(element),
19+
createPipeline().process(element),
2420
(compileElement) => compileElement.inheritedElementBinder
2521
);
2622
}
@@ -30,11 +26,6 @@ export function main() {
3026
expect(elementBinder.textBindingIndices[bindingIndex]).toEqual(nodeIndex);
3127
}
3228

33-
it('should not look for text interpolation when ignoreBindings is true', () => {
34-
var results = process(el('<div>{{expr1}}<span></span>{{expr2}}</div>'), true);
35-
expect(results[0]).toEqual(null);
36-
});
37-
3829
it('should find text interpolation in normal elements', () => {
3930
var result = process(el('<div>{{expr1}}<span></span>{{expr2}}</div>'))[0];
4031
assertTextBinding(result, 0, 0, "{{expr1}}");
@@ -69,14 +60,3 @@ export function main() {
6960
});
7061
});
7162
}
72-
73-
class MockStep extends CompileStep {
74-
processClosure:Function;
75-
constructor(process) {
76-
super();
77-
this.processClosure = process;
78-
}
79-
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
80-
this.processClosure(parent, current, control);
81-
}
82-
}

0 commit comments

Comments
 (0)