关于javascript event flow 的一个bug详解

  我最近调netsurf也遇到一个相关的bug : alert() 被调了两次。html 代码:

  

复制代码 代码如下:

  <html>

  <head>

  <title>alert onclick example</title>

  <script type="text/javascript">

  function causealert()

  {

  var txt = document.getElementById("p1").textContent;

  alert(txt);

  }

  </script>

  </head>

  <body>

  <div style="border: 1px solid red">

  <p id="p1">First line of paragraph.<br /></p>

  </div><br />

  <button id="button1" >add another textNode.</button>

  <script>

  var Button1 = document.getElementById("button1");

  /*var Button1Click = function() { alert(1); };

  Button1.addEventListener("click", Button1Click, false);*/

  Button1.onclick = causealert;

  </script>

  </body>

  </html>

  通过gdb, 定位到是_dom_node_dispatch_event()里面的问题:

  

复制代码 代码如下:

  /* The capture phase */ for (targetnr = ntargets; targetnr > 0; --targetnr)...

  /* Bubbling phase */

  evt->phase = DOM_BUBBLING_PHASE;

  for (targetnr = 0; targetnr < ntargets; ++targetnr)

  

  事件流是这样的: p1(root)-->p2-->... --> pm --> T  (capturing phase), T (target phase), T--> pm --> ... --> p1 (bubbling phase).

  规范规定capturing 和bubbling 只能选其一, 代码中在 js_dom_event_add_listener()是选capturing。因此就解释了为什么alert 被执行两回了。

  修改: 根据DOM 3 规范,把上面的0改成1就行了。