Răsfoiți Sursa

fix #657: DOM structure change in bind() should not affect compilation

Evan You 11 ani în urmă
părinte
comite
bc254bf942
2 a modificat fișierele cu 31 adăugiri și 4 ștergeri
  1. 6 4
      src/compiler/compile.js
  2. 25 0
      test/unit/specs/misc_spec.js

+ 6 - 4
src/compiler/compile.js

@@ -52,8 +52,10 @@ module.exports = function compile (el, options, partial, asParent) {
   return function link (vm, el) {
     var originalDirCount = vm._directives.length
     if (paramsLinkFn) paramsLinkFn(vm, el)
+    // cache childNodes before linking parent, fix #657
+    var childNodes = _.toArray(el.childNodes)
     if (nodeLinkFn) nodeLinkFn(vm, el)
-    if (childLinkFn) childLinkFn(vm, el.childNodes)
+    if (childLinkFn) childLinkFn(vm, childNodes)
 
     /**
      * If this is a partial compile, the linker function
@@ -300,18 +302,18 @@ function compileNodeList (nodeList, options) {
 
 function makeChildLinkFn (linkFns) {
   return function childLinkFn (vm, nodes) {
-    // stablize nodes
-    nodes = _.toArray(nodes)
     var node, nodeLinkFn, childrenLinkFn
     for (var i = 0, n = 0, l = linkFns.length; i < l; n++) {
       node = nodes[n]
       nodeLinkFn = linkFns[i++]
       childrenLinkFn = linkFns[i++]
+      // cache childNodes before linking parent, fix #657
+      var childNodes = _.toArray(node.childNodes)
       if (nodeLinkFn) {
         nodeLinkFn(vm, node)
       }
       if (childrenLinkFn) {
-        childrenLinkFn(vm, node.childNodes)
+        childrenLinkFn(vm, childNodes)
       }
     }
   }

+ 25 - 0
test/unit/specs/misc_spec.js

@@ -0,0 +1,25 @@
+// test cases for edge cases & bug fixes
+var Vue = require('../../../src/vue')
+
+describe('Misc', function () {
+
+  it('should handle directive.bind() altering its childNode structure', function () {
+    var vm = new Vue({
+      el: document.createElement('div'),
+      template: '<div v-test>{{test}}</div>',
+      data: {
+        test: 'hi'
+      },
+      directives: {
+        test: {
+          bind: function () {
+            this.el.insertBefore(document.createTextNode('yo '),
+              this.el.firstChild)
+          }
+        }
+      }
+    })
+    expect(vm.$el.textContent).toBe('yo hi')
+  })
+
+})