Browse Source

Merge pull request #456 from alpinejs/fix-nikolays-bug

Fix obscure mutation observer bug
Caleb Porzio 5 years ago
parent
commit
254330253a
4 changed files with 53 additions and 4 deletions
  1. 1 1
      dist/alpine-ie11.js
  2. 1 1
      dist/alpine.js
  3. 3 2
      src/component.js
  4. 48 0
      test/constructor.spec.js

+ 1 - 1
dist/alpine-ie11.js

@@ -6971,7 +6971,7 @@
           for (var i = 0; i < mutations.length; i++) {
             // Filter out mutations triggered from child components.
             var closestParentComponent = mutations[i].target.closest('[x-data]');
-            if (!(closestParentComponent && closestParentComponent.isSameNode(this.$el))) return;
+            if (!(closestParentComponent && closestParentComponent.isSameNode(this.$el))) continue;
 
             if (mutations[i].type === 'attributes' && mutations[i].attributeName === 'x-data') {
               (function () {

+ 1 - 1
dist/alpine.js

@@ -1579,7 +1579,7 @@
         for (let i = 0; i < mutations.length; i++) {
           // Filter out mutations triggered from child components.
           const closestParentComponent = mutations[i].target.closest('[x-data]');
-          if (!(closestParentComponent && closestParentComponent.isSameNode(this.$el))) return;
+          if (!(closestParentComponent && closestParentComponent.isSameNode(this.$el))) continue;
 
           if (mutations[i].type === 'attributes' && mutations[i].attributeName === 'x-data') {
             const rawData = saferEval(mutations[i].target.getAttribute('x-data'), {});

+ 3 - 2
src/component.js

@@ -333,10 +333,11 @@ export default class Component {
         }
 
         const observer = new MutationObserver((mutations) => {
-            for (let i=0; i < mutations.length; i++){
+            for (let i=0; i < mutations.length; i++) {
                 // Filter out mutations triggered from child components.
                 const closestParentComponent = mutations[i].target.closest('[x-data]')
-                if (! (closestParentComponent && closestParentComponent.isSameNode(this.$el))) return
+
+                if (! (closestParentComponent && closestParentComponent.isSameNode(this.$el))) continue
 
                 if (mutations[i].type === 'attributes' && mutations[i].attributeName === 'x-data') {
                     const rawData = saferEval(mutations[i].target.getAttribute('x-data'), {})

+ 48 - 0
test/constructor.spec.js

@@ -1,5 +1,6 @@
 import Alpine from 'alpinejs'
 import { fireEvent, wait } from '@testing-library/dom'
+const timeout = ms => new Promise(resolve => setTimeout(resolve, ms))
 
 test('auto-detect new components at the top level', async () => {
     var runObservers = []
@@ -340,3 +341,50 @@ test('x-attributes are matched exactly', async () => {
     expect(document.getElementById('el2').style.display).not.toEqual('none')
     await wait(() => { expect(document.getElementById('el3').style.display).not.toEqual('none') })
 })
+
+
+test('a mutation from another part of the HTML doesnt prevent a different alpine component from initializing', async () => {
+    document.body.innerHTML = `
+        <div x-data x-init="registerInit()">
+        </div>
+    `
+
+    var initCount = 0
+    window.registerInit = function () {
+        initCount = initCount + 1
+    }
+
+    var runObservers = []
+
+    global.MutationObserver = class {
+        constructor(callback) { runObservers.push(callback) }
+        observe() {}
+    }
+
+    Alpine.start()
+
+    await wait(() => { expect(initCount).toEqual(1) })
+
+    document.querySelector('div').innerHTML = `
+        <h1 x-data x-init="registerInit()"></h1>
+    `
+    let h2 = document.createElement('h2')
+    document.querySelector('div').parentElement.appendChild(h2)
+
+    await timeout(5)
+
+    runObservers[0]([
+        {
+            target: document.querySelector('h2'),
+            type: 'attributes',
+            addedNodes: [],
+        },
+        {
+            target: document.querySelector('div'),
+            type: 'childList',
+            addedNodes: [ document.querySelector('h1') ],
+        }
+    ])
+
+    await wait(() => { expect(initCount).toEqual(2) })
+})