From 6f8957b4ccc5aa50384d6df0fccd2b96f661ec11 Mon Sep 17 00:00:00 2001 From: Javan Makhmali Date: Fri, 1 Jun 2018 08:38:58 -0400 Subject: [PATCH 1/4] Ignore synchronously removed / moved matched elements --- .../src/element_observer.ts | 8 +++--- .../test/cases/attribute_observer_tests.ts | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/packages/@stimulus/mutation-observers/src/element_observer.ts b/packages/@stimulus/mutation-observers/src/element_observer.ts index c71c5c64..7dd27d29 100644 --- a/packages/@stimulus/mutation-observers/src/element_observer.ts +++ b/packages/@stimulus/mutation-observers/src/element_observer.ts @@ -129,9 +129,11 @@ export class ElementObserver { private addElement(element: Element) { if (!this.elements.has(element)) { - this.elements.add(element) - if (this.delegate.elementMatched) { - this.delegate.elementMatched(element) + if (this.element.contains(element)) { + this.elements.add(element) + if (this.delegate.elementMatched) { + this.delegate.elementMatched(element) + } } } } diff --git a/packages/@stimulus/mutation-observers/test/cases/attribute_observer_tests.ts b/packages/@stimulus/mutation-observers/test/cases/attribute_observer_tests.ts index e115451e..e1484622 100644 --- a/packages/@stimulus/mutation-observers/test/cases/attribute_observer_tests.ts +++ b/packages/@stimulus/mutation-observers/test/cases/attribute_observer_tests.ts @@ -68,6 +68,32 @@ export default class AttributeObserverTests extends ObserverTestCase implements ]) } + async "test ignores synchronously disconnected elements"() { + const { innerElement, outerElement } = this + + outerElement.removeChild(innerElement) + innerElement.setAttribute(this.attributeName, "") + await this.nextFrame + + this.assert.deepEqual(this.calls, [ + ["elementMatchedAttribute", outerElement, this.attributeName] + ]) + } + + async "test ignores synchronously moved elements"() { + const { innerElement, outerElement } = this + + document.body.appendChild(innerElement) + innerElement.setAttribute(this.attributeName, "") + await this.nextFrame + + this.assert.deepEqual(this.calls, [ + ["elementMatchedAttribute", outerElement, this.attributeName] + ]) + + document.body.removeChild(innerElement) + } + get outerElement() { return this.findElement("#outer") } From eee9d6346af7a3bc53e522054ed4e391c1252f27 Mon Sep 17 00:00:00 2001 From: Javan Makhmali Date: Fri, 1 Jun 2018 12:20:19 -0400 Subject: [PATCH 2/4] Optimization: Compare isConnected states --- .../mutation-observers/src/element_observer.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/@stimulus/mutation-observers/src/element_observer.ts b/packages/@stimulus/mutation-observers/src/element_observer.ts index 7dd27d29..a32c27bc 100644 --- a/packages/@stimulus/mutation-observers/src/element_observer.ts +++ b/packages/@stimulus/mutation-observers/src/element_observer.ts @@ -125,11 +125,19 @@ export class ElementObserver { } } + private elementIsActive(element: Element): boolean { + if (element.isConnected != this.element.isConnected) { + return false + } else { + return this.element.contains(element) + } + } + // Element tracking private addElement(element: Element) { if (!this.elements.has(element)) { - if (this.element.contains(element)) { + if (this.elementIsActive(element)) { this.elements.add(element) if (this.delegate.elementMatched) { this.delegate.elementMatched(element) From 42ec073ea94b242527f517e67749b2dce423e493 Mon Sep 17 00:00:00 2001 From: Javan Makhmali Date: Fri, 1 Jun 2018 12:22:40 -0400 Subject: [PATCH 3/4] Optimization: Skip processing inactive added trees --- .../src/element_observer.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/@stimulus/mutation-observers/src/element_observer.ts b/packages/@stimulus/mutation-observers/src/element_observer.ts index a32c27bc..4cbe42b4 100644 --- a/packages/@stimulus/mutation-observers/src/element_observer.ts +++ b/packages/@stimulus/mutation-observers/src/element_observer.ts @@ -90,13 +90,19 @@ export class ElementObserver { private processRemovedNodes(nodes: NodeList) { for (const node of Array.from(nodes)) { - this.processNode(node, this.removeElement) + const element = this.elementFromNode(node) + if (element) { + this.processTree(element, this.removeElement) + } } } private processAddedNodes(nodes: NodeList) { for (const node of Array.from(nodes)) { - this.processNode(node, this.addElement) + const element = this.elementFromNode(node) + if (element && this.elementIsActive(element)) { + this.processTree(element, this.addElement) + } } } @@ -110,12 +116,9 @@ export class ElementObserver { return this.delegate.matchElementsInTree(tree) } - private processNode(node: Node, processor: (element: Element) => void) { - const tree = this.elementFromNode(node) - if (tree) { - for (const element of this.matchElementsInTree(tree)) { - processor.call(this, element) - } + private processTree(tree: Element, processor: (element: Element) => void) { + for (const element of this.matchElementsInTree(tree)) { + processor.call(this, element) } } From d3ea33716e2315ae3a1c0189e61bb1e136eccd82 Mon Sep 17 00:00:00 2001 From: Javan Makhmali Date: Fri, 1 Jun 2018 12:23:36 -0400 Subject: [PATCH 4/4] Bump TypeScript for Node.isConnected support https://github.com/Microsoft/TypeScript/issues/22322 --- package.json | 2 +- yarn.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 19b63cbf..e878d09c 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "tslint": "^5.7.0", "typedoc": "^0.11.1", "typedoc-plugin-stimulus": "file:packages/typedoc-plugin-stimulus", - "typescript": "^2.8.1", + "typescript": "^2.8.4", "webpack": "^3.10.0" } } diff --git a/yarn.lock b/yarn.lock index 880ffc26..0dbc7f2a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5626,9 +5626,9 @@ typescript@2.7.2: version "2.7.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.2.tgz#2d615a1ef4aee4f574425cdff7026edf81919836" -typescript@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.1.tgz#6160e4f8f195d5ba81d4876f9c0cc1fbc0820624" +typescript@^2.8.4: + version "2.9.1" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.1.tgz#fdb19d2c67a15d11995fd15640e373e09ab09961" uglify-es@^3.3.7: version "3.3.9"