diff --git a/spec/dom-element-pool-spec.coffee b/spec/dom-element-pool-spec.coffee new file mode 100644 index 000000000..f16185cca --- /dev/null +++ b/spec/dom-element-pool-spec.coffee @@ -0,0 +1,44 @@ +DOMElementPool = require '../src/dom-element-pool' + +describe "DOMElementPool", -> + domElementPool = null + + beforeEach -> + domElementPool = new DOMElementPool + + it "builds DOM nodes, recycling them when they are freed", -> + [div, span1, span2, span3, span4, span5] = elements = [ + domElementPool.build("div") + domElementPool.build("span") + domElementPool.build("span") + domElementPool.build("span") + domElementPool.build("span") + domElementPool.build("span") + ] + + div.appendChild(span1) + span1.appendChild(span2) + div.appendChild(span3) + span3.appendChild(span4) + + domElementPool.freeElementAndDescendants(div) + domElementPool.freeElementAndDescendants(span5) + + expect(elements).toContain(domElementPool.build("div")) + expect(elements).toContain(domElementPool.build("span")) + expect(elements).toContain(domElementPool.build("span")) + expect(elements).toContain(domElementPool.build("span")) + expect(elements).toContain(domElementPool.build("span")) + expect(elements).toContain(domElementPool.build("span")) + + expect(elements).not.toContain(domElementPool.build("div")) + expect(elements).not.toContain(domElementPool.build("span")) + + it "throws an error when trying to free the same node twice", -> + div = domElementPool.build("div") + domElementPool.freeElementAndDescendants(div) + expect(-> domElementPool.freeElementAndDescendants(div)).toThrow() + + it "throws an error when trying to free an invalid element", -> + expect(-> domElementPool.freeElementAndDescendants(null)).toThrow() + expect(-> domElementPool.freeElementAndDescendants(undefined)).toThrow() diff --git a/spec/dom-elements-pool-spec.coffee b/spec/dom-elements-pool-spec.coffee deleted file mode 100644 index 56cf15761..000000000 --- a/spec/dom-elements-pool-spec.coffee +++ /dev/null @@ -1,40 +0,0 @@ -DomElementsPool = require '../src/dom-elements-pool' - -describe "DomElementsPool", -> - domElementsPool = null - - beforeEach -> - domElementsPool = new DomElementsPool - - it "builds DOM nodes, recycling them when they are freed", -> - [div, span1, span2, span3, span4] = elements = [ - domElementsPool.build("div") - domElementsPool.build("span") - domElementsPool.build("span") - domElementsPool.build("span") - domElementsPool.build("span") - ] - - div.appendChild(span1) - span1.appendChild(span2) - div.appendChild(span3) - span3.appendChild(span4) - - domElementsPool.freeElementAndDescendants(div) - - expect(elements).toContain(domElementsPool.build("div")) - expect(elements).toContain(domElementsPool.build("span")) - expect(elements).toContain(domElementsPool.build("span")) - expect(elements).toContain(domElementsPool.build("span")) - expect(elements).toContain(domElementsPool.build("span")) - - expect(elements).not.toContain(domElementsPool.build("span")) - - it "throws an error when trying to free the same node twice", -> - div = domElementsPool.build("div") - domElementsPool.freeElementAndDescendants(div) - expect(-> domElementsPool.freeElementAndDescendants(div)).toThrow() - - it "throws an error when trying to free an invalid element", -> - expect(-> domElementsPool.freeElementAndDescendants(null)).toThrow() - expect(-> domElementsPool.freeElementAndDescendants(undefined)).toThrow() diff --git a/src/dom-elements-pool.coffee b/src/dom-element-pool.coffee similarity index 84% rename from src/dom-elements-pool.coffee rename to src/dom-element-pool.coffee index f75c904aa..4cea8b89e 100644 --- a/src/dom-elements-pool.coffee +++ b/src/dom-element-pool.coffee @@ -1,5 +1,5 @@ module.exports = -class DomElementsPool +class DOMElementPool constructor: -> @freeElementsByTagName = {} @freedElements = new Set @@ -25,8 +25,9 @@ class DomElementsPool throw new Error("The element cannot be null or undefined.") unless element? throw new Error("The element has already been freed!") if @freedElements.has(element) - @freeElementsByTagName[element.tagName.toLowerCase()] ?= [] - @freeElementsByTagName[element.tagName.toLowerCase()].push(element) + tagName = element.tagName.toLowerCase() + @freeElementsByTagName[tagName] ?= [] + @freeElementsByTagName[tagName].push(element) @freedElements.add(element) element.remove() diff --git a/src/line-number-gutter-component.coffee b/src/line-number-gutter-component.coffee index 390aba41b..c95d43641 100644 --- a/src/line-number-gutter-component.coffee +++ b/src/line-number-gutter-component.coffee @@ -1,7 +1,7 @@ TiledComponent = require './tiled-component' LineNumbersTileComponent = require './line-numbers-tile-component' WrapperDiv = document.createElement('div') -DomElementsPool = require './dom-elements-pool' +DOMElementPool = require './dom-element-pool' module.exports = class LineNumberGutterComponent extends TiledComponent @@ -10,9 +10,9 @@ class LineNumberGutterComponent extends TiledComponent constructor: ({@onMouseDown, @editor, @gutter}) -> @visible = true - @elementsPool = new DomElementsPool + @domElementPool = new DOMElementPool - @dummyLineNumberComponent = LineNumbersTileComponent.createDummy(@elementsPool) + @dummyLineNumberComponent = LineNumbersTileComponent.createDummy(@domElementPool) @domNode = atom.views.getView(@gutter) @lineNumbersNode = @domNode.firstChild @@ -64,7 +64,7 @@ class LineNumberGutterComponent extends TiledComponent @oldState.styles = {} @oldState.maxLineNumberDigits = @newState.maxLineNumberDigits - buildComponentForTile: (id) -> new LineNumbersTileComponent({id, @elementsPool}) + buildComponentForTile: (id) -> new LineNumbersTileComponent({id, @domElementPool}) ### Section: Private Methods diff --git a/src/line-numbers-tile-component.coffee b/src/line-numbers-tile-component.coffee index 0b4ca43b8..5a54b8208 100644 --- a/src/line-numbers-tile-component.coffee +++ b/src/line-numbers-tile-component.coffee @@ -2,18 +2,18 @@ _ = require 'underscore-plus' module.exports = class LineNumbersTileComponent - @createDummy: (elementsPool) -> - new LineNumbersTileComponent({id: -1, elementsPool}) + @createDummy: (domElementPool) -> + new LineNumbersTileComponent({id: -1, domElementPool}) - constructor: ({@id, @elementsPool}) -> + constructor: ({@id, @domElementPool}) -> @lineNumberNodesById = {} - @domNode = @elementsPool.build("div", "tile") + @domNode = @domElementPool.build("div", "tile") @domNode.style.position = "absolute" @domNode.style.display = "block" @domNode.style.top = 0 # Cover the space occupied by a dummy lineNumber destroy: -> - @elementsPool.freeElementAndDescendants(@domNode) + @domElementPool.freeElementAndDescendants(@domNode) getDomNode: -> @domNode @@ -49,7 +49,7 @@ class LineNumbersTileComponent if @newState.maxLineNumberDigits isnt @oldState.maxLineNumberDigits for id, node of @lineNumberNodesById - @elementsPool.freeElementAndDescendants(node) + @domElementPool.freeElementAndDescendants(node) @oldState.tiles[@id] = {lineNumbers: {}} @oldTileState = @oldState.tiles[@id] @@ -64,7 +64,7 @@ class LineNumbersTileComponent for id, lineNumberState of @oldTileState.lineNumbers unless @newTileState.lineNumbers.hasOwnProperty(id) - @elementsPool.freeElementAndDescendants(@lineNumberNodesById[id]) + @domElementPool.freeElementAndDescendants(@lineNumberNodesById[id]) delete @lineNumberNodesById[id] delete @oldTileState.lineNumbers[id] @@ -91,7 +91,7 @@ class LineNumbersTileComponent {screenRow, bufferRow, softWrapped, top, decorationClasses, zIndex} = lineNumberState className = @buildLineNumberClassName(lineNumberState) - lineNumberNode = @elementsPool.build("div", className) + lineNumberNode = @domElementPool.build("div", className) lineNumberNode.dataset.screenRow = screenRow lineNumberNode.dataset.bufferRow = bufferRow @@ -114,7 +114,7 @@ class LineNumbersTileComponent lineNumber = (bufferRow + 1).toString() padding = _.multiplyString("\u00a0", maxLineNumberDigits - lineNumber.length) - iconRight = @elementsPool.build("div", "icon-right") + iconRight = @domElementPool.build("div", "icon-right") lineNumberNode.innerText = padding + lineNumber lineNumberNode.appendChild(iconRight) diff --git a/src/lines-component.coffee b/src/lines-component.coffee index d3d1f9b0a..a96c4b91d 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -3,7 +3,7 @@ CursorsComponent = require './cursors-component' LinesTileComponent = require './lines-tile-component' TiledComponent = require './tiled-component' -DomElementsPool = require './dom-elements-pool' +DOMElementPool = require './dom-element-pool' DummyLineNode = $$(-> @div className: 'line', style: 'position: absolute; visibility: hidden;', => @span 'x')[0] @@ -24,7 +24,7 @@ class LinesComponent extends TiledComponent @cursorsComponent = new CursorsComponent @domNode.appendChild(@cursorsComponent.getDomNode()) - @elementsPool = new DomElementsPool + @domElementPool = new DOMElementPool if @useShadowDOM insertionPoint = document.createElement('content') @@ -63,7 +63,7 @@ class LinesComponent extends TiledComponent @oldState.indentGuidesVisible = @newState.indentGuidesVisible - buildComponentForTile: (id) -> new LinesTileComponent({id, @presenter, @elementsPool}) + buildComponentForTile: (id) -> new LinesTileComponent({id, @presenter, @domElementPool}) buildEmptyState: -> {tiles: {}} diff --git a/src/lines-tile-component.coffee b/src/lines-tile-component.coffee index 2b4762c76..c23c97055 100644 --- a/src/lines-tile-component.coffee +++ b/src/lines-tile-component.coffee @@ -13,13 +13,13 @@ cloneObject = (object) -> module.exports = class LinesTileComponent - constructor: ({@presenter, @id, @elementsPool}) -> + constructor: ({@presenter, @id, @domElementPool}) -> @tokenIterator = new TokenIterator @measuredLines = new Set @lineNodesByLineId = {} @screenRowsByLineId = {} @lineIdsByScreenRow = {} - @domNode = @elementsPool.build("div", "tile") + @domNode = @domElementPool.build("div", "tile") @domNode.classList.add("tile") @domNode.style.position = "absolute" @domNode.style.display = "block" @@ -28,7 +28,7 @@ class LinesTileComponent @domNode.appendChild(@highlightsComponent.getDomNode()) destroy: -> - @elementsPool.freeElementAndDescendants(@domNode) + @domElementPool.freeElementAndDescendants(@domNode) getDomNode: -> @domNode @@ -79,7 +79,7 @@ class LinesTileComponent return removeLineNode: (id) -> - @elementsPool.freeElementAndDescendants(@lineNodesByLineId[id]) + @domElementPool.freeElementAndDescendants(@lineNodesByLineId[id]) delete @lineNodesByLineId[id] delete @lineIdsByScreenRow[@screenRowsByLineId[id]] delete @screenRowsByLineId[id] @@ -118,7 +118,7 @@ class LinesTileComponent {width} = @newState {screenRow, tokens, text, top, lineEnding, fold, isSoftWrapped, indentLevel, decorationClasses} = @newTileState.lines[id] - lineNode = @elementsPool.build("div", "line") + lineNode = @domElementPool.build("div", "line") if decorationClasses? for decorationClass in decorationClasses lineNode.classList.add(decorationClass) @@ -133,7 +133,7 @@ class LinesTileComponent else @appendLineInnerNodes(id, lineNode) - lineNode.appendChild(@elementsPool.build("span", "fold-marker")) if fold + lineNode.appendChild(@domElementPool.build("span", "fold-marker")) if fold lineNode appendEmptyLineInnerNodes: (id, lineNode) -> @@ -143,11 +143,11 @@ class LinesTileComponent if indentGuidesVisible and indentLevel > 0 invisibleIndex = 0 for i in [0...indentLevel] - indentGuide = @elementsPool.build("span", "indent-guide") + indentGuide = @domElementPool.build("span", "indent-guide") for j in [0...tabLength] if invisible = endOfLineInvisibles?[invisibleIndex++] indentGuide.appendChild( - @elementsPool.build("span", "invisible-character", invisible) + @domElementPool.build("span", "invisible-character", invisible) ) else indentGuide.insertAdjacentText("beforeend", " ") @@ -156,7 +156,7 @@ class LinesTileComponent while invisibleIndex < endOfLineInvisibles?.length invisible = endOfLineInvisibles[invisibleIndex++] lineNode.appendChild( - @elementsPool.build("span", "invisible-character", invisible) + @domElementPool.build("span", "invisible-character", invisible) ) else unless @appendEndOfLineNodes(id, lineNode) @@ -175,7 +175,7 @@ class LinesTileComponent openScopeNode = openScopeNode.parentElement for scope in @tokenIterator.getScopeStarts() - newScopeNode = @elementsPool.build("span", scope.replace(/\.+/g, ' ')) + newScopeNode = @domElementPool.build("span", scope.replace(/\.+/g, ' ')) openScopeNode.appendChild(newScopeNode) openScopeNode = newScopeNode @@ -208,7 +208,7 @@ class LinesTileComponent appendTokenNodes: (tokenText, isHardTab, firstNonWhitespaceIndex, firstTrailingWhitespaceIndex, hasIndentGuide, hasInvisibleCharacters, scopeNode) -> if isHardTab - hardTabNode = @elementsPool.build("span", "hard-tab", tokenText) + hardTabNode = @domElementPool.build("span", "hard-tab", tokenText) hardTabNode.classList.add("leading-whitespace") if firstNonWhitespaceIndex? hardTabNode.classList.add("trailing-whitespace") if firstTrailingWhitespaceIndex? hardTabNode.classList.add("indent-guide") if hasIndentGuide @@ -223,7 +223,7 @@ class LinesTileComponent trailingWhitespaceNode = null if firstNonWhitespaceIndex? - leadingWhitespaceNode = @elementsPool.build( + leadingWhitespaceNode = @domElementPool.build( "span", "leading-whitespace", tokenText.substring(0, firstNonWhitespaceIndex) @@ -236,7 +236,7 @@ class LinesTileComponent if firstTrailingWhitespaceIndex? tokenIsOnlyWhitespace = firstTrailingWhitespaceIndex is 0 - trailingWhitespaceNode = @elementsPool.build( + trailingWhitespaceNode = @domElementPool.build( "span", "trailing-whitespace", tokenText.substring(firstTrailingWhitespaceIndex) @@ -251,7 +251,7 @@ class LinesTileComponent if tokenText.length > MaxTokenLength while startIndex < endIndex text = @sliceText(tokenText, startIndex, startIndex + MaxTokenLength) - scopeNode.appendChild(@elementsPool.build("span", null, text)) + scopeNode.appendChild(@domElementPool.build("span", null, text)) startIndex += MaxTokenLength else scopeNode.insertAdjacentText("beforeend", @sliceText(tokenText, startIndex, endIndex)) @@ -271,7 +271,7 @@ class LinesTileComponent for invisible in endOfLineInvisibles hasInvisibles = true lineNode.appendChild( - @elementsPool.build("span", "invisible-character", invisible) + @domElementPool.build("span", "invisible-character", invisible) ) hasInvisibles