ZK-5370 causes JS error if component has client data-handler onBind listener

XMLWordPrintable

    • Type: Bug
    • Resolution: Unresolved
    • Priority: Major
    • None
    • Affects Version/s: 10.0.0, 10.2.1
    • Component/s: None
    • Security Level: Jimmy
    • None

      Steps to Reproduce

      Add data-handler to zk.xml:

      	<client-config>
      	    <data-handler>
      	        <name>foo</name>
      	        <script>
      	            function (wgt, dataValue) {
      	             console.log(dataValue);
      	            }
      	        </script>
      	    </data-handler>
      	</client-config>
      

      Run attached zul
      Click on "onBind Listener" <- No error
      Click on "data-handler"

      Current Result

      Uncaught TypeError: Failed to mount: Cannot read properties of undefined (reading '0')
          at Widget.fireX (zk.wpd:5:1152660)
          at Widget.fire (zk.wpd:5:1153444)
          at zk.wpd:5:1145125
          at window.zk.mount_.doAfterMount (zk.wpd:5:1084780)
          at window.zk.mount_.mtAU0 (zk.wpd:5:1084606)
          at window.zk.mount_.mtAU (zk.wpd:5:1084531)
          at zkx (zk.wpd:5:1086812)
          at zkx_ (zk.wpd:5:1087332)
          at Object.addChd (zk.wpd:5:32071)
          at window.zk.au_.doProcess (zk.wpd:5:8896)
      

      Expected Result

      No error

      Debug Information

      https://github.com/zkoss/zk/commit/142f50c5eb8bf9fcb4fdbb983ed4070e74f23aa6#diff-8d797950e7fb394c3fd08cccfd2fd0efcdb8bb1732a9d88cd7596ca9ddd367d0R490-R492

      callOnce unlisten block is called during the onBind listener

      https://github.com/zkoss/zk/blob/fe50262ce8b5c027b0644671a17a64227efc234e/zk/src/main/resources/web/js/zk/widget.ts#L4579-L4583

      zk.Widget.prototype.fireX invokes the listeners sequentially.

      a direct onBind listener is placed in the lsns array before the callOnce listener.
      setWidgetListener onBind is called
      callOnce is called and self-removes

      a data-handler is place after the callOnce listener in the array
      j is 0: lsns array looks like [callOnceLsnr, datahandlerLsnr]
      lsnr[j] is callOnceLsrn, lsnr[j] function is called, which removes callOnceLsrn from the lsnr array
      lsnr now looks like [datahandlerLsnr], for completes a loop, j is 1
      attempt to invoke lsnr[1][0]() where lsnr[1] is null

      Workaround

      	<script><![CDATA[
      		zk.afterLoad("zk", function(){
      			window.zk.mount_.create = function(e, z, M) {
                          var b, t, n, c = z[0], O = z[1], r = z[2] || {}, a = z[3] || {};
                          if (0 === c) {
                              var A = (c = zk.cut(r, "wc")) ? zk.$import(c) : zk.Page;
                              (t = new A({
                                  uuid: O
                              },zk.cut(r, "ct"))).inServer = !0,
                              e && e.appendChild(t, M)
                          } else {
                              if ((n = "#stub" == c) || "#stubs" == c) {
                                  if (!(t = (p || o.$)(O) || zAu._wgt$(O)))
                                      throw "Unknown stub " + O;
                                  var d = new zk.Widget;
                                  (t.desktop || 9 === t.z_rod) && t.unbind(),
                                  zk._wgtutl.replace(t, d, n)
                              } else {
                                  if (!(A = zk.$import(c)))
                                      throw "Unknown widget: " + c;
                                  (t = new A(window.zkac)).inServer = !0,
                                  t.uuid = O;
                                  var q = z[5];
                                  q && t.setMold(q)
                              }
                              e && e.appendChild(t, M),
                              zk.cut(r, "z$is") && (t.z$is = !0,
                              t._fellows = {});
                              var u = zk.cut(r, "z$al");
                              u && zk.afterLoad((function() {
                                  for (var e in u)
                                      t.set(e, u[e](), !0)
                              }
                              ));
                              var l = zk.cut(a, "z$al");
                              l && zk.afterLoad((function() {
                                  for (var e = 0, z = l.length; e < z; e++) {
                                      var M = l[e];
                                      for (var o in M)
                                          t.set(o, M[o](), !0)
                                  }
                              }
                              ))
                          }
                          for (b in r)
                              t.set(b, r[b], !0);
                          for (b in a)
                              for (var W = a[b], h = 0, R = W.length; h < R; h++) {
                                  var g = W[h];
                                  t.set(b, g, !0)
                              }
                          for (var m = 0, L = z[4], _ = L.length; m < _; ++m)
                              window.zk.mount_.create(t, L[m]);
                          if (zk.loading)
                              zk.afterLoad((function() {
                                  return t.afterCompose_()
                              }
                              ));
                          else if (e)
                              t.afterCompose_();
                          else {
                              var callOnce_1 = function() {
                                  t.afterCompose_();
                                  setTimeout(function(){
      	                            t.unlisten({
      	                                onBind: callOnce_1
      	                            })
                                  },0);
                              };
                              t.listen({
                                  onBind: callOnce_1
                              })
                          }
                          return t
                      }
      		});
      	]]></script>
      

            Assignee:
            Unassigned
            Reporter:
            MDuchemin
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: