diff --git a/spec/dom-element-pool-spec.js b/spec/dom-element-pool-spec.js index 52f4d772e..959003ca8 100644 --- a/spec/dom-element-pool-spec.js +++ b/spec/dom-element-pool-spec.js @@ -51,29 +51,44 @@ describe('DOMElementPool', function () { expect(domElementPool.buildElement('div')).not.toBe(div) }) + it('does not attempt to free nodes that were not created by the pool', () => { + let assertionFailure + atom.onDidFailAssertion((error) => assertionFailure = error) + + const foreignDiv = document.createElement('div') + const div = domElementPool.buildElement('div') + div.appendChild(foreignDiv) + domElementPool.freeElementAndDescendants(div) + const span = domElementPool.buildElement('span') + span.appendChild(foreignDiv) + domElementPool.freeElementAndDescendants(span) + + expect(assertionFailure).toBeUndefined() + }) + it('fails an assertion when freeing the same element twice', function () { - let failure - atom.onDidFailAssertion((error) => failure = error) + let assertionFailure + atom.onDidFailAssertion((error) => assertionFailure = error) const div = domElementPool.buildElement('div') div.textContent = 'testing' domElementPool.freeElementAndDescendants(div) - expect(failure).toBeUndefined() + expect(assertionFailure).toBeUndefined() domElementPool.freeElementAndDescendants(div) - expect(failure.message).toBe('Assertion failed: The element has already been freed!') - expect(failure.metadata.content).toBe('
testing
') + expect(assertionFailure.message).toBe('Assertion failed: The element has already been freed!') + expect(assertionFailure.metadata.content).toBe('
testing
') }) it('fails an assertion when freeing the same text node twice', function () { - let failure - atom.onDidFailAssertion((error) => failure = error) + let assertionFailure + atom.onDidFailAssertion((error) => assertionFailure = error) const node = domElementPool.buildText('testing') domElementPool.freeElementAndDescendants(node) - expect(failure).toBeUndefined() + expect(assertionFailure).toBeUndefined() domElementPool.freeElementAndDescendants(node) - expect(failure.message).toBe('Assertion failed: The element has already been freed!') - expect(failure.metadata.content).toBe('testing') + expect(assertionFailure.message).toBe('Assertion failed: The element has already been freed!') + expect(assertionFailure.metadata.content).toBe('testing') }) it('throws an error when trying to free an invalid element', function () { diff --git a/src/dom-element-pool.js b/src/dom-element-pool.js index 624e0b74f..683a1d247 100644 --- a/src/dom-element-pool.js +++ b/src/dom-element-pool.js @@ -1,11 +1,13 @@ module.exports = class DOMElementPool { constructor () { + this.managedElements = new Set() this.freeElementsByTagName = new Map() this.freedElements = new Set() } clear () { + this.managedElements.clear() this.freedElements.clear() this.freeElementsByTagName.clear() } @@ -27,6 +29,7 @@ class DOMElementPool { this.freedElements.delete(element) } else { element = document.createElement(tagName) + this.managedElements.add(element) } return element } @@ -39,6 +42,7 @@ class DOMElementPool { this.freedElements.delete(element) } else { element = document.createTextNode(textContent) + this.managedElements.add(element) } return element } @@ -50,6 +54,7 @@ class DOMElementPool { free (element) { if (element == null) { throw new Error('The element cannot be null or undefined.') } + if (!this.managedElements.has(element)) return if (this.freedElements.has(element)) { atom.assert(false, 'The element has already been freed!', { content: element instanceof Text ? element.textContent : element.outerHTML.toString()