From 678d541da76edb10420ecc613a757ebad0bb6070 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Fri, 10 Apr 2015 16:12:37 +0200 Subject: [PATCH] refactor(compiler): add control.ignoreCurrentElement() to skip the current element relates to #808 --- .../render/dom/compiler/compile_control.js | 23 ++++++++++++++-- .../render/dom/compiler/compile_element.js | 3 --- .../dom/compiler/property_binding_parser.js | 4 --- .../dom/compiler/text_interpolation_parser.js | 2 +- .../dom/shadow_dom/shadow_dom_compile_step.js | 14 +++++----- .../test/render/dom/compiler/pipeline_spec.js | 24 ++++++++++++++++- .../compiler/property_binding_parser_spec.js | 16 ++++-------- .../text_interpolation_parser_spec.js | 26 +++---------------- 8 files changed, 60 insertions(+), 52 deletions(-) diff --git a/modules/angular2/src/render/dom/compiler/compile_control.js b/modules/angular2/src/render/dom/compiler/compile_control.js index 89faa46e03..facc8cb84a 100644 --- a/modules/angular2/src/render/dom/compiler/compile_control.js +++ b/modules/angular2/src/render/dom/compiler/compile_control.js @@ -13,6 +13,8 @@ export class CompileControl { _parent:CompileElement; _results; _additionalChildren; + _ignoreCurrentElement: boolean; + constructor(steps) { this._steps = steps; this._currentStepIndex = 0; @@ -27,14 +29,21 @@ export class CompileControl { var previousStepIndex = this._currentStepIndex; var previousParent = this._parent; - for (var i=startStepIndex; i' : used to provide context in case of error constructor(element, compilationUnit = '') { @@ -34,8 +33,6 @@ export class CompileElement { this.inheritedElementBinder = null; this.distanceToInheritedBinder = 0; this.compileChildren = true; - // set to true to ignore all the bindings on the element - this.ignoreBindings = false; // description is calculated here as compilation steps may change the element var tplDesc = assertionsEnabled()? getElementDescription(element) : null; if (compilationUnit !== '') { diff --git a/modules/angular2/src/render/dom/compiler/property_binding_parser.js b/modules/angular2/src/render/dom/compiler/property_binding_parser.js index 1383c57de5..978853230e 100644 --- a/modules/angular2/src/render/dom/compiler/property_binding_parser.js +++ b/modules/angular2/src/render/dom/compiler/property_binding_parser.js @@ -30,10 +30,6 @@ export class PropertyBindingParser extends CompileStep { } process(parent:CompileElement, current:CompileElement, control:CompileControl) { - if (current.ignoreBindings) { - return; - } - var attrs = current.attrs(); var newAttrs = MapWrapper.create(); diff --git a/modules/angular2/src/render/dom/compiler/text_interpolation_parser.js b/modules/angular2/src/render/dom/compiler/text_interpolation_parser.js index 1a056c138d..2758ae55fc 100644 --- a/modules/angular2/src/render/dom/compiler/text_interpolation_parser.js +++ b/modules/angular2/src/render/dom/compiler/text_interpolation_parser.js @@ -19,7 +19,7 @@ export class TextInterpolationParser extends CompileStep { } process(parent:CompileElement, current:CompileElement, control:CompileControl) { - if (!current.compileChildren || current.ignoreBindings) { + if (!current.compileChildren) { return; } var element = current.element; diff --git a/modules/angular2/src/render/dom/shadow_dom/shadow_dom_compile_step.js b/modules/angular2/src/render/dom/shadow_dom/shadow_dom_compile_step.js index 8a42b9337e..3054ef5564 100644 --- a/modules/angular2/src/render/dom/shadow_dom/shadow_dom_compile_step.js +++ b/modules/angular2/src/render/dom/shadow_dom/shadow_dom_compile_step.js @@ -23,12 +23,9 @@ export class ShadowDomCompileStep extends CompileStep { } process(parent:CompileElement, current:CompileElement, control:CompileControl) { - if (current.ignoreBindings) { - return; - } var tagName = DOM.tagName(current.element).toUpperCase(); if (tagName == 'STYLE') { - this._processStyleElement(current); + this._processStyleElement(current, control); } else if (tagName == 'CONTENT') { this._processContentElement(current); } else { @@ -39,17 +36,20 @@ export class ShadowDomCompileStep extends CompileStep { } } - _processStyleElement(current) { - current.ignoreBindings = true; + _processStyleElement(current:CompileElement, control:CompileControl) { var stylePromise = this._shadowDomStrategy.processStyleElement( this._template.componentId, this._template.absUrl, current.element ); if (isPresent(stylePromise) && PromiseWrapper.isPromise(stylePromise)) { ListWrapper.push(this._subTaskPromises, stylePromise); } + + // Style elements should not be further processed by the compiler, as they can not contain + // bindings. Skipping further compiler steps allow speeding up the compilation process. + control.ignoreCurrentElement(); } - _processContentElement(current) { + _processContentElement(current:CompileElement) { if (this._shadowDomStrategy.hasNativeContentElement()) { return; } diff --git a/modules/angular2/test/render/dom/compiler/pipeline_spec.js b/modules/angular2/test/render/dom/compiler/pipeline_spec.js index ff88cc840a..3fec0d348e 100644 --- a/modules/angular2/test/render/dom/compiler/pipeline_spec.js +++ b/modules/angular2/test/render/dom/compiler/pipeline_spec.js @@ -80,6 +80,19 @@ export function main() { expect(results[3].inheritedElementBinder.parent).toBe(results[0].inheritedElementBinder); }); + it('should not execute further steps when ignoreCurrentElement has been called', () => { + var element = el('
'); + var logs = []; + var pipeline = new CompilePipeline([ + new IgnoreCurrentElementStep(), + createLoggerStep(logs), + ]); + var results = pipeline.process(element); + + expect(results.length).toBe(2); + expect(logs).toEqual(['1', '1<3']) + }); + describe('control.addParent', () => { it('should report the new parent to the following processor and the result', () => { var element = el('
'); @@ -188,6 +201,15 @@ export class IgnoreChildrenStep extends CompileStep { } } +class IgnoreCurrentElementStep extends CompileStep { + process(parent:CompileElement, current:CompileElement, control:CompileControl) { + var attributeMap = DOM.attributeMap(current.element); + if (MapWrapper.contains(attributeMap, 'ignore-current')) { + control.ignoreCurrentElement(); + } + } +} + function logEntry(log, parent, current) { var parentId = ''; if (isPresent(parent)) { @@ -223,4 +245,4 @@ function resultIdLog(result) { logEntry(idLog, null, current); }); return idLog; -} \ No newline at end of file +} diff --git a/modules/angular2/test/render/dom/compiler/property_binding_parser_spec.js b/modules/angular2/test/render/dom/compiler/property_binding_parser_spec.js index e7060d2ba0..a880493f93 100644 --- a/modules/angular2/test/render/dom/compiler/property_binding_parser_spec.js +++ b/modules/angular2/test/render/dom/compiler/property_binding_parser_spec.js @@ -11,10 +11,9 @@ var EMPTY_MAP = MapWrapper.create(); export function main() { describe('PropertyBindingParser', () => { - function createPipeline(ignoreBindings = false, hasNestedProtoView = false) { + function createPipeline(hasNestedProtoView = false) { return new CompilePipeline([ new MockStep((parent, current, control) => { - current.ignoreBindings = ignoreBindings; if (hasNestedProtoView) { current.bindElement().bindNestedProtoView(el('')); } @@ -22,18 +21,13 @@ export function main() { new PropertyBindingParser(new Parser(new Lexer()))]); } - function process(element, ignoreBindings = false, hasNestedProtoView = false) { + function process(element, hasNestedProtoView = false) { return ListWrapper.map( - createPipeline(ignoreBindings, hasNestedProtoView).process(element), + createPipeline(hasNestedProtoView).process(element), (compileElement) => compileElement.inheritedElementBinder ); } - it('should not parse bindings when ignoreBindings is true', () => { - var results = process(el('
'), true); - expect(results[0]).toEqual(null); - }); - it('should detect [] syntax', () => { var results = process(el('
')); expect(MapWrapper.get(results[0].propertyBindings, 'a').source).toEqual('b'); @@ -64,13 +58,13 @@ export function main() { }); it('should store variable binding for a template element on the nestedProtoView', () => { - var results = process(el('