You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-users@xmlgraphics.apache.org by sy...@echelon.com on 2002/10/12 02:28:56 UTC

2 addEventListener() bugs

(1) I was trying to use like something the following ECMAScript, but I
noticed some strange behavior:

 

========= START CODE =========

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">

<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"
id="testSVG">

    <script type="text/ecmascript"><![CDATA[

    function TestObj()

    {

        this.root = document.documentElement;

        this.abc = 123;

        this.myFunc = function()

        { alert(this.abc); }

        this.root.addEventListener("click", this.myFunc, false);

    }

    var obj = new TestObj();

    ]]></script>

    <rect width="100%" height="100%" fill="green"/>

    <rect x="45%" y="45%" width="10%" height="10%"
onmouseover="obj.myFunc()"/>

</svg> 

 ========= END CODE =========

 

When addEventListener() is explicitly called to add the TestObj.myFunc
method as an event listener, and myFunc gets called as the result of an
event, the "instance variable" this.abc is undefined.  However, if I add the
same function as a listener via an onmouseover attribute, that instance
variable is properly defined.  This is true with Batik and Adobe's viewer as
well.

 

To see the undefined variable behavior, click anywhere in the SVG window.
To see the "proper" behavior, mouse over the black rectangle.

 

It seems to me the click behavior should be the same as the mouseover
behavior.

 

(2) Also, in looking at the source for addEventListener() in
org.apache.batik.dom.events.EventSupport, I noticed a bug due to a possible
race condition.  I'm not sure if the bug is related to the above-described
behavior, but I kind of doubt it.  Anyway, the bug is that the method starts
out as follows:

 

========= START CODE =========

    public void addEventListener(String type, EventListener listener, 

                                                 boolean useCapture) {
HashTable listeners;

            if (useCapture) {

                if (capturingListeners == null) {

                        capturingListeners = new HashTable();

                }

                listeners = capturingListeners;

            } else {

                if (bubblingListeners == null) {

                        bubblingListeners = new HashTable();

                }

                listeners = bubblingListeners;

            }

.

.

.

 ========= END CODE =========

 

You'll notice that nothing is synchronized, so if multiple threads call
addEventListener() at around the same time, it is possible for the
capturingListeners and/or bubblingListeners objects to be created multiple
times.  If that happens, the initially created Hashtable objects are simply
thrown away, and any listeners they might have contained are forgotten.  It
seems the code should at least have a "synchronize(this)" block  around the
if/else statement.