Reviewed by Oliver Hunt & Sam Weining.
authorzimmermann@webkit.org <zimmermann@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Oct 2008 03:34:43 +0000 (03:34 +0000)
committerzimmermann@webkit.org <zimmermann@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Oct 2008 03:34:43 +0000 (03:34 +0000)
 Fixes: https://bugs.webkit.org/show_bug.cgi?id=15413 (SVGElementInstance does not implement EventTarget)
 Fixes: https://bugs.webkit.org/show_bug.cgi?id=15430 (SVGElementInstances should rebuild themselves lazily)
 Fixes: https://bugs.webkit.org/show_bug.cgi?id=20550 (SVGUseElement.setAttribute crashes Safari)

 Rebuild SVG use element shadow tree lazily. Mark SVGElementInstance with the "needsUpdate" flag.
 Next time SVGUseElement::recalcStyle is invoked (ie. via Document::updateDocumentsRendering()) the
 use tree is rebuild.

 Make SVGElementInstance a real EventTarget, as the SVG specification demands.
 When dispatching events to a shadow tree element of a use element, the associated SVGElementInstance
 is used as event target. The SVGElementInstance, the shadow tree element and the corresponding element
 share an event listener list. Every event listener change on the SVGElementInstance object is forwared
 to the corresponding element. Each change marks the SVGElementInstance tree dirty, and causes a reclone.
 Each event listener defined via attributes (onclick/onkeydown/...) is copied from the correspondingElement
 to the shadow tree element - through the cloneNode calls - if the use element's shadow tree gets rebuild.
 Each listener, dynamically created using addEventListener, gets copied to the corersponding element as well.

 Now that the target/currentTarget properties of the Events are correct, event bubbling works as expected,
 see resources/use-instanceRoot-event-bubbling.js for details.

 Tests: svg/custom/use-elementInstance-event-target.svg (reenabled)
        svg/custom/use-elementInstance-methods.svg (reenabled)
        svg/custom/use-setAttribute-crash.svg (covers bug 20550)
        svg/custom/use-instanceRoot-as-event-target.xhtml (covers bug 15413)
        svg/custom/use-instanceRoot-event-bubbling.xhtml (covers bug 15413)
        svg/custom/use-instanceRoot-event-listeners.xhtml (covers bug 15413 & 15430)

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@37435 268f45cc-cd09-0410-ab3c-d52691b4dbfc

48 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/mac/svg/custom/use-instanceRoot-as-event-target-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/svg/custom/use-instanceRoot-as-event-target-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/custom/use-instanceRoot-event-bubbling-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/svg/custom/use-instanceRoot-event-bubbling-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/custom/use-instanceRoot-event-listeners-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/svg/custom/use-instanceRoot-event-listeners-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/custom/use-setAttribute-crash-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/svg/custom/use-setAttribute-crash-expected.png [new file with mode: 0644]
LayoutTests/svg/custom/resources/use-instanceRoot-event-bubbling.js [new file with mode: 0644]
LayoutTests/svg/custom/resources/use-instanceRoot-event-listeners.js [new file with mode: 0644]
LayoutTests/svg/custom/use-elementInstance-event-target-expected.txt [moved from LayoutTests/platform/mac/svg/custom/use-elementInstance-event-target-expected.txt with 100% similarity]
LayoutTests/svg/custom/use-elementInstance-event-target.svg [moved from LayoutTests/svg/custom/use-elementInstance-event-target.svg-disabled with 100% similarity]
LayoutTests/svg/custom/use-elementInstance-methods-expected.txt [moved from LayoutTests/platform/mac/svg/custom/use-elementInstance-methods-expected.txt with 100% similarity]
LayoutTests/svg/custom/use-elementInstance-methods.svg [moved from LayoutTests/svg/custom/use-elementInstance-methods.svg-disabled with 100% similarity]
LayoutTests/svg/custom/use-instanceRoot-as-event-target-expected.txt [new file with mode: 0644]
LayoutTests/svg/custom/use-instanceRoot-as-event-target.xhtml [new file with mode: 0644]
LayoutTests/svg/custom/use-instanceRoot-event-bubbling-expected.txt [new file with mode: 0644]
LayoutTests/svg/custom/use-instanceRoot-event-bubbling.xhtml [new file with mode: 0644]
LayoutTests/svg/custom/use-instanceRoot-event-listeners-expected.txt [new file with mode: 0644]
LayoutTests/svg/custom/use-instanceRoot-event-listeners.xhtml [new file with mode: 0644]
LayoutTests/svg/custom/use-setAttribute-crash-expected.txt [new file with mode: 0644]
LayoutTests/svg/custom/use-setAttribute-crash.svg [new file with mode: 0644]
WebCore/ChangeLog
WebCore/DerivedSources.make
WebCore/GNUmakefile.am
WebCore/WebCore.pro
WebCore/WebCore.vcproj/WebCore.vcproj
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/bindings/js/JSEventListener.h
WebCore/bindings/js/JSEventTarget.cpp
WebCore/bindings/js/JSEventTargetSVGElementInstance.cpp [deleted file]
WebCore/bindings/js/JSEventTargetSVGElementInstance.h [deleted file]
WebCore/bindings/js/JSSVGElementInstanceCustom.cpp
WebCore/bindings/scripts/CodeGeneratorJS.pm
WebCore/bindings/scripts/CodeGeneratorObjC.pm
WebCore/dom/EventListener.h
WebCore/dom/EventTargetNode.cpp
WebCore/page/EventHandler.cpp
WebCore/page/EventHandler.h
WebCore/svg/EventTargetSVGElementInstance.cpp [deleted file]
WebCore/svg/EventTargetSVGElementInstance.h [deleted file]
WebCore/svg/SVGElementInstance.cpp
WebCore/svg/SVGElementInstance.h
WebCore/svg/SVGElementInstance.idl
WebCore/svg/SVGStyledElement.cpp
WebCore/svg/SVGUseElement.cpp
WebCore/svg/SVGUseElement.h

index 091f5d4..dbf6e34 100644 (file)
@@ -1,3 +1,39 @@
+2008-10-08  Nikolas Zimmermann  <zimmermann@kde.org>
+
+        Reviewed by Oliver Hunt & Sam Weining.
+
+        The SVGElementInstance tree should be rebuild lazily.
+        Allow SVGElementInstance to be used as EventTarget, as described in SVG 1.1 spec.
+
+        Reenable temporarily disabled tests.
+
+        * platform/mac/svg/custom/use-elementInstance-event-target-expected.txt: Removed.
+        * platform/mac/svg/custom/use-elementInstance-methods-expected.txt: Removed.
+        * platform/mac/svg/custom/use-instanceRoot-as-event-target-expected.checksum: Added.
+        * platform/mac/svg/custom/use-instanceRoot-as-event-target-expected.png: Added.
+        * platform/mac/svg/custom/use-instanceRoot-event-bubbling-expected.checksum: Added.
+        * platform/mac/svg/custom/use-instanceRoot-event-bubbling-expected.png: Added.
+        * platform/mac/svg/custom/use-instanceRoot-event-listeners-expected.checksum: Added.
+        * platform/mac/svg/custom/use-instanceRoot-event-listeners-expected.png: Added.
+        * platform/mac/svg/custom/use-setAttribute-crash-expected.checksum: Added.
+        * platform/mac/svg/custom/use-setAttribute-crash-expected.png: Added.
+        * svg/custom/resources/use-instanceRoot-event-bubbling.js: Added.
+        * svg/custom/resources/use-instanceRoot-event-listeners.js: Added.
+        * svg/custom/use-elementInstance-event-target-expected.txt: Copied from LayoutTests/platform/mac/svg/custom/use-elementInstance-event-target-expected.txt.
+        * svg/custom/use-elementInstance-event-target.svg: Copied from LayoutTests/svg/custom/use-elementInstance-event-target.svg-disabled.
+        * svg/custom/use-elementInstance-event-target.svg-disabled: Removed.
+        * svg/custom/use-elementInstance-methods-expected.txt: Copied from LayoutTests/platform/mac/svg/custom/use-elementInstance-methods-expected.txt.
+        * svg/custom/use-elementInstance-methods.svg: Copied from LayoutTests/svg/custom/use-elementInstance-methods.svg-disabled.
+        * svg/custom/use-elementInstance-methods.svg-disabled: Removed.
+        * svg/custom/use-instanceRoot-as-event-target-expected.txt: Added.
+        * svg/custom/use-instanceRoot-as-event-target.xhtml: Added.
+        * svg/custom/use-instanceRoot-event-bubbling-expected.txt: Added.
+        * svg/custom/use-instanceRoot-event-bubbling.xhtml: Added.
+        * svg/custom/use-instanceRoot-event-listeners-expected.txt: Added.
+        * svg/custom/use-instanceRoot-event-listeners.xhtml: Added.
+        * svg/custom/use-setAttribute-crash-expected.txt: Added.
+        * svg/custom/use-setAttribute-crash.svg: Added.
+
 2008-10-08  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Cameron Zwarich.
diff --git a/LayoutTests/platform/mac/svg/custom/use-instanceRoot-as-event-target-expected.checksum b/LayoutTests/platform/mac/svg/custom/use-instanceRoot-as-event-target-expected.checksum
new file mode 100644 (file)
index 0000000..120e309
--- /dev/null
@@ -0,0 +1 @@
+30b8bb08bfb9aaaa884b503c084c8643
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/svg/custom/use-instanceRoot-as-event-target-expected.png b/LayoutTests/platform/mac/svg/custom/use-instanceRoot-as-event-target-expected.png
new file mode 100644 (file)
index 0000000..e2a9cea
Binary files /dev/null and b/LayoutTests/platform/mac/svg/custom/use-instanceRoot-as-event-target-expected.png differ
diff --git a/LayoutTests/platform/mac/svg/custom/use-instanceRoot-event-bubbling-expected.checksum b/LayoutTests/platform/mac/svg/custom/use-instanceRoot-event-bubbling-expected.checksum
new file mode 100644 (file)
index 0000000..b3f1209
--- /dev/null
@@ -0,0 +1 @@
+1a6bca283b3fdc0d6b19f5ce8a75421b
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/svg/custom/use-instanceRoot-event-bubbling-expected.png b/LayoutTests/platform/mac/svg/custom/use-instanceRoot-event-bubbling-expected.png
new file mode 100644 (file)
index 0000000..3060d39
Binary files /dev/null and b/LayoutTests/platform/mac/svg/custom/use-instanceRoot-event-bubbling-expected.png differ
diff --git a/LayoutTests/platform/mac/svg/custom/use-instanceRoot-event-listeners-expected.checksum b/LayoutTests/platform/mac/svg/custom/use-instanceRoot-event-listeners-expected.checksum
new file mode 100644 (file)
index 0000000..4cce096
--- /dev/null
@@ -0,0 +1 @@
+7ed8c45697a8c96e153f08cd57e93078
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/svg/custom/use-instanceRoot-event-listeners-expected.png b/LayoutTests/platform/mac/svg/custom/use-instanceRoot-event-listeners-expected.png
new file mode 100644 (file)
index 0000000..903e041
Binary files /dev/null and b/LayoutTests/platform/mac/svg/custom/use-instanceRoot-event-listeners-expected.png differ
diff --git a/LayoutTests/platform/mac/svg/custom/use-setAttribute-crash-expected.checksum b/LayoutTests/platform/mac/svg/custom/use-setAttribute-crash-expected.checksum
new file mode 100644 (file)
index 0000000..10b8603
--- /dev/null
@@ -0,0 +1 @@
+367e0c69bc9f21610a618f04a494237f
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/svg/custom/use-setAttribute-crash-expected.png b/LayoutTests/platform/mac/svg/custom/use-setAttribute-crash-expected.png
new file mode 100644 (file)
index 0000000..fd11fef
Binary files /dev/null and b/LayoutTests/platform/mac/svg/custom/use-setAttribute-crash-expected.png differ
diff --git a/LayoutTests/svg/custom/resources/use-instanceRoot-event-bubbling.js b/LayoutTests/svg/custom/resources/use-instanceRoot-event-bubbling.js
new file mode 100644 (file)
index 0000000..c992ef6
--- /dev/null
@@ -0,0 +1,129 @@
+description("Tests wheter SVG event bubbling works accross shadow trees.");
+
+if (window.layoutTestController)
+    layoutTestController.waitUntilDone();
+
+var svgNS = "http://www.w3.org/2000/svg";
+var xhtmlNS = "http://www.w3.org/1999/xhtml";
+var expected = new Array(4);
+var tests = 4;
+var counter = 0;
+var eventCounter = 0;
+
+function log(message) {
+    var logDiv = document.getElementById("console");
+    var newDiv = document.createElementNS(xhtmlNS, "div");
+    newDiv.appendChild(document.createTextNode(message));
+    logDiv.appendChild(newDiv);
+}
+
+function eventHandler(evt, label) {
+    var targetId = evt.target.correspondingElement ? evt.target.correspondingElement.id : evt.target.id;
+    var curTargetId = evt.currentTarget.correspondingElement ? evt.currentTarget.correspondingElement.id : evt.currentTarget.id;
+
+    var phaseString = "";
+    switch (evt.eventPhase) {
+    case 1: phaseString = "CAPTURING"; break;
+    case 2: phaseString = "AT_TARGET"; break;
+    case 3: phaseString = "BUBBLING"; break;
+    }
+
+    msg = '[EventHandler ' + label + '] type: ' + evt.type + ' phase: ' + phaseString +
+          ' target: '         + evt.target        + ' (id: ' + targetId    + ')' +
+          ' currentTarget: '  + evt.currentTarget + ' (id: ' + curTargetId + ')';
+
+    shouldBeEqualToString("msg", expected[eventCounter]);
+    ++eventCounter;
+
+    if (label == counter) {
+        if (label == tests)
+            setTimeout("finishTest()", 100);
+        else
+            setTimeout("nextTest()", 100);
+    }
+}
+
+function finishTest()
+{
+    successfullyParsed = true;
+
+    use.instanceRoot.correspondingElement.setAttribute("fill", "green");
+    shouldBeTrue("successfullyParsed");
+    debug('<br /><span class="pass">TEST COMPLETE</span>');
+
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+
+function nextTest()
+{
+    eventCounter = 0;
+    ++counter;
+
+    switch (counter) {
+    case 1:
+        rect.onclick = function(evt) { eventHandler(evt, 1); };
+        expected[0] = "[EventHandler 1] type: click phase: AT_TARGET target: [object SVGElementInstance] (id: rect) currentTarget: [object SVGElementInstance] (id: rect)";
+        testListeners();
+        break;
+    case 2:
+        rectContainer.addEventListener("click", function(evt) { eventHandler(evt, 2) }, false);
+        expected[1] = "[EventHandler 2] type: click phase: BUBBLING target: [object SVGElementInstance] (id: rect) currentTarget: [object SVGElementInstance] (id: rectParent)";    
+        testListeners();
+        break;
+    case 3:
+        use.setAttribute("onclick", "eventHandler(evt, 3)");
+        expected[2] = "[EventHandler 3] type: click phase: BUBBLING target: [object SVGElementInstance] (id: rect) currentTarget: [object SVGUseElement] (id: use)";
+        testListeners();
+        break;
+    case 4:
+        useContainer.onclick = function(evt) { eventHandler(evt, 4) };
+        expected[3] = "[EventHandler 4] type: click phase: BUBBLING target: [object SVGElementInstance] (id: rect) currentTarget: [object SVGGElement] (id: useParent)";
+        testListeners();
+        break;
+    }
+}
+
+function testListeners()
+{
+    if (window.eventSender) {
+        eventSender.mouseMoveTo(50, 50);
+        eventSender.mouseDown();
+        eventSender.mouseUp();
+    }
+}
+
+// Create root element
+var svg = document.createElementNS(svgNS, "svg");
+svg.id = "rootSVG";
+svg.setAttribute("width", 100);
+svg.setAttribute("height", 100);
+document.body.insertBefore(svg, document.body.firstChild);
+
+// Create defs section
+var defs = document.createElementNS(svgNS, "defs");
+svg.appendChild(defs);
+
+var rectContainer = document.createElementNS(svgNS, "g");
+rectContainer.id = "rectParent";
+defs.appendChild(rectContainer);
+
+var rect = document.createElementNS(svgNS, "rect");
+rect.id = "rect";
+rect.style.fill = "red";
+rect.width.baseVal.value = 100;
+rect.height.baseVal.value = 100;
+rectContainer.appendChild(rect);
+
+// Create content section
+var useContainer = document.createElementNS(svgNS, "g");
+useContainer.id = "useParent";
+svg.appendChild(useContainer);
+
+var use = document.createElementNS(svgNS, "use");
+use.id = "use";
+use.href.baseVal = "#rectParent";
+useContainer.appendChild(use);
+
+// Start test
+nextTest();
diff --git a/LayoutTests/svg/custom/resources/use-instanceRoot-event-listeners.js b/LayoutTests/svg/custom/resources/use-instanceRoot-event-listeners.js
new file mode 100644 (file)
index 0000000..88653da
--- /dev/null
@@ -0,0 +1,179 @@
+var counter = 0;
+var tests = 8;
+var expected = "";
+var logEvent = false;
+var rectElement = document.getElementById("target");
+var useElement = document.getElementById("test");
+description("Test attaching event listeners on SVG use elements in different ways: ");
+
+if (window.layoutTestController)
+    layoutTestController.waitUntilDone();
+
+function eventHandler(evt)
+{
+    if (logEvent) {
+        if (expected == evt.type)
+            debug("Test " + counter + " / " + tests + " PASSED");
+        else
+            debug("Test " + counter + " / " + tests + " FAILED (expected: '" + expected + "' actual: '" + evt.type + "')");
+    }
+
+    setTimeout(counter < tests ? driveTests : finishTest, 100);
+}
+
+function finishTest()
+{
+    successfullyParsed = true;
+
+    useElement.instanceRoot.correspondingElement.setAttribute("fill", "green");
+    shouldBeTrue("successfullyParsed");
+    debug('<br /><span class="pass">TEST COMPLETE</span>');
+
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+
+function recordMouseEvent(type)
+{
+    expected = type;
+    logEvent = true;
+
+    ++counter;
+    fireDelayedEvent();
+}
+
+function sendMouseEvent(type, increment)
+{
+    expected = type;
+    logEvent = false;
+    fireDelayedEvent();
+}
+
+function fireDelayedEvent()
+{
+    if (expected == "mouseover")
+        eventSender.mouseMoveTo(50, 50);
+    else if (expected == "mouseout")
+        eventSender.mouseMoveTo(115, 55);
+    else if (expected == "mouseup") {
+        eventSender.mouseMoveTo(50, 50);
+        eventSender.mouseDown();
+        eventSender.mouseUp();
+    } else if (expected == "mousedown") {
+        eventSender.mouseMoveTo(50, 50);
+        eventSender.mouseDown();
+        eventSender.mouseUp();
+    }
+}
+
+function testOne()
+{
+    // Install event listener on correspondingElement via setAttribute
+    useElement.instanceRoot.correspondingElement.setAttribute("onmouseover", "eventHandler(evt)");
+    recordMouseEvent("mouseover");
+}
+
+function testTwo()
+{
+    // Install event listener on correspondingElement via onmouseout JS magic
+    useElement.instanceRoot.correspondingElement.onmouseout = eventHandler;
+    recordMouseEvent("mouseout");
+}
+
+function testThree()
+{
+    // Clean event listeners on different ways
+    useElement.instanceRoot.correspondingElement.removeAttribute("onmouseover");
+    useElement.instanceRoot.correspondingElement.onmouseout = 0;
+
+    // Verify they really got removed
+    sendMouseEvent("mouseover");
+    sendMouseEvent("mouseout");
+
+    // Verify the original listener still works
+    recordMouseEvent("mousedown");
+}
+
+function testFour()
+{
+    useElement.instanceRoot.correspondingElement.removeAttribute("onmousedown");
+
+    // Install event listener on the referenced element, without using the SVGElementInstance interface
+    rectElement.setAttribute("onmouseup", "eventHandler(evt)");
+    recordMouseEvent("mouseup");
+}
+
+function testFive()
+{
+    rectElement.onmouseout = eventHandler;
+    recordMouseEvent("mouseout");
+}
+
+function testSix()
+{
+    useElement.instanceRoot.correspondingElement.onmouseout = null;
+    sendMouseEvent("mouseout");
+
+    useElement.instanceRoot.correspondingElement.removeAttribute('onmouseup');
+    sendMouseEvent("mouseup");
+
+    useElement.instanceRoot.correspondingElement.onmouseup = eventHandler;
+    recordMouseEvent("mouseup");
+}
+
+function testSeven()
+{
+    useElement.instanceRoot.addEventListener("mouseout", eventHandler, false);
+    recordMouseEvent("mouseout");
+}
+
+function testEight()
+{
+    useElement.instanceRoot.correspondingElement.addEventListener("mouseover", eventHandler, false);
+    recordMouseEvent("mouseover");
+}
+
+function testNine()
+{
+    rectElement.addEventListener("mousedown", eventHandler, false);
+    recordMouseEvent("mousedown");
+}
+
+function driveTests()
+{
+    switch (counter) {
+    case 0:
+        testOne();
+        break;
+    case 1:
+        testTwo();
+        break;
+    case 2:
+        testThree();
+        break;
+    case 3:
+        testFour();
+        break;
+    case 4:
+        testFive();
+        break;
+    case 5:
+        testSix();
+        break;
+    case 6:
+        testSeven();
+        break;
+    case 7:
+        testEight();
+        break;
+    }
+}
+
+if (!window.eventSender) {
+    alert("This test must be run via DRT!");
+    return;
+}
+
+// Start tests
+eventSender.mouseMoveTo(115, 55);
+driveTests();
diff --git a/LayoutTests/svg/custom/use-instanceRoot-as-event-target-expected.txt b/LayoutTests/svg/custom/use-instanceRoot-as-event-target-expected.txt
new file mode 100644 (file)
index 0000000..164a7c7
--- /dev/null
@@ -0,0 +1,144 @@
+Test SVG use element specific event handling using SVGElementInstance:
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+'useElement' is the original use element
+'rectElement' is the original element which gets cloned by the use element
+
+Test #1: Verify that the use element and the contained SVGElementInstance objects are valid
+
+PASS useElement.toString() is "[object SVGUseElement]"
+PASS useElement.instanceRoot.toString() is "[object SVGElementInstance]"
+PASS useElement.instanceRoot.correspondingElement.toString() is "[object SVGRectElement]"
+PASS useElement.instanceRoot.correspondingElement == rectElement is true
+PASS useElement.instanceRoot.correspondingUseElement.toString() is "[object SVGUseElement]"
+PASS useElement.instanceRoot.correspondingUseElement == useElement is true
+PASS typeof useElement.addEventListener is "function"
+PASS typeof useElement.removeEventListener is "function"
+PASS typeof useElement.dispatchEvent is "function"
+
+Test #2: Verify that events dispatched to the SVGElementInstance objects have correct target property values
+
+PASS currentEvent.toString() is "[object MouseEvent]"
+PASS currentEvent.type.toString() is "mouseover"
+PASS currentEvent.target.toString() is "[object SVGElementInstance]"
+PASS currentEvent.currentTarget.toString() is "[object SVGElementInstance]"
+PASS currentEvent.target.correspondingElement == rectElement is true
+PASS currentEvent.target.correspondingUseElement == useElement is true
+PASS currentEvent.currentTarget.correspondingElement == rectElement is true
+PASS currentEvent.currentTarget.correspondingUseElement == useElement is true
+PASS currentEvent.target == currentEvent.currentTarget is true
+PASS currentEvent.target.correspondingElement == currentEvent.currentTarget.correspondingElement is true
+PASS currentEvent.target.correspondingUseElement == currentEvent.currentTarget.correspondingUseElement is true
+
+Test #3: Verify that event listeners attached to the shadow tree elements are copied when use reclones the internal shadow tree
+
+PASS currentEvent.toString() is "[object MouseEvent]"
+PASS currentEvent.type.toString() is "mouseover"
+PASS currentEvent.target.toString() is "[object SVGElementInstance]"
+PASS currentEvent.currentTarget.toString() is "[object SVGElementInstance]"
+PASS currentEvent.target.correspondingElement == rectElement is true
+PASS currentEvent.target.correspondingUseElement == useElement is true
+PASS currentEvent.currentTarget.correspondingElement == rectElement is true
+PASS currentEvent.currentTarget.correspondingUseElement == useElement is true
+PASS currentEvent.target == currentEvent.currentTarget is true
+PASS currentEvent.target.correspondingElement == currentEvent.currentTarget.correspondingElement is true
+PASS currentEvent.target.correspondingUseElement == currentEvent.currentTarget.correspondingUseElement is true
+
+Test #4: Verify that events dispatched to the referenced element end up on the SVElementInstance objects
+
+PASS currentEvent.toString() is "[object MouseEvent]"
+PASS currentEvent.type.toString() is "mouseover"
+PASS currentEvent.target.toString() is "[object SVGElementInstance]"
+PASS currentEvent.currentTarget.toString() is "[object SVGElementInstance]"
+PASS currentEvent.target.correspondingElement == rectElement is true
+PASS currentEvent.target.correspondingUseElement == useElement is true
+PASS currentEvent.currentTarget.correspondingElement == rectElement is true
+PASS currentEvent.currentTarget.correspondingUseElement == useElement is true
+PASS currentEvent.target == currentEvent.currentTarget is true
+PASS currentEvent.target.correspondingElement == currentEvent.currentTarget.correspondingElement is true
+PASS currentEvent.target.correspondingUseElement == currentEvent.currentTarget.correspondingUseElement is true
+
+Test #5: Verify that event listeners attached to the referenced elements are copied when use reclones the internal shadow tree
+
+PASS currentEvent.toString() is "[object MouseEvent]"
+PASS currentEvent.type.toString() is "mouseover"
+PASS currentEvent.target.toString() is "[object SVGElementInstance]"
+PASS currentEvent.currentTarget.toString() is "[object SVGElementInstance]"
+PASS currentEvent.target.correspondingElement == rectElement is true
+PASS currentEvent.target.correspondingUseElement == useElement is true
+PASS currentEvent.currentTarget.correspondingElement == rectElement is true
+PASS currentEvent.currentTarget.correspondingUseElement == useElement is true
+PASS currentEvent.target == currentEvent.currentTarget is true
+PASS currentEvent.target.correspondingElement == currentEvent.currentTarget.correspondingElement is true
+PASS currentEvent.target.correspondingUseElement == currentEvent.currentTarget.correspondingUseElement is true
+
+Test #6: Verify that a click event got dispatched to the original tree as defined in the markup, when sent to the 'rectElement'
+
+PASS currentEvent.toString() is "[object MouseEvent]"
+PASS currentEvent.type.toString() is "click"
+PASS currentEvent.target.toString() is "[object SVGRectElement]"
+PASS currentEvent.currentTarget.toString() is "[object SVGRectElement]"
+PASS currentEvent.target == rectElement is true
+PASS currentEvent.currentTarget == rectElement is true
+PASS currentEvent.target == currentEvent.currentTarget is true
+
+Test #7: Verify that a click event got dispatched to the instance tree when sent to the 'useElement.instanceRoot' with an event listener attached to 'rectElement'
+
+PASS currentEvent.toString() is "[object MouseEvent]"
+PASS currentEvent.type.toString() is "click"
+PASS currentEvent.target.toString() is "[object SVGElementInstance]"
+PASS currentEvent.currentTarget.toString() is "[object SVGElementInstance]"
+PASS currentEvent.target.correspondingElement == rectElement is true
+PASS currentEvent.target.correspondingUseElement == useElement is true
+PASS currentEvent.currentTarget.correspondingElement == rectElement is true
+PASS currentEvent.currentTarget.correspondingUseElement == useElement is true
+PASS currentEvent.target == currentEvent.currentTarget is true
+PASS currentEvent.target.correspondingElement == currentEvent.currentTarget.correspondingElement is true
+PASS currentEvent.target.correspondingUseElement == currentEvent.currentTarget.correspondingUseElement is true
+
+Test #8: Verify that the original click event listener defined in markup is still working properly
+
+PASS currentEvent.toString() is "[object MouseEvent]"
+PASS currentEvent.type.toString() is "click"
+PASS currentEvent.target.toString() is "[object SVGElementInstance]"
+PASS currentEvent.currentTarget.toString() is "[object SVGElementInstance]"
+PASS currentEvent.target.correspondingElement == rectElement is true
+PASS currentEvent.target.correspondingUseElement == useElement is true
+PASS currentEvent.currentTarget.correspondingElement == rectElement is true
+PASS currentEvent.currentTarget.correspondingUseElement == useElement is true
+PASS currentEvent.target == currentEvent.currentTarget is true
+PASS currentEvent.target.correspondingElement == currentEvent.currentTarget.correspondingElement is true
+PASS currentEvent.target.correspondingUseElement == currentEvent.currentTarget.correspondingUseElement is true
+
+Test #9: Verify that the original click event listener got removed and a new one attached to the use root SVGElementInstance
+
+PASS currentEvent.toString() is "[object MouseEvent]"
+PASS currentEvent.type.toString() is "click"
+PASS currentEvent.target.toString() is "[object SVGElementInstance]"
+PASS currentEvent.currentTarget.toString() is "[object SVGElementInstance]"
+PASS currentEvent.target.correspondingElement == rectElement is true
+PASS currentEvent.target.correspondingUseElement == useElement is true
+PASS currentEvent.currentTarget.correspondingElement == rectElement is true
+PASS currentEvent.currentTarget.correspondingUseElement == useElement is true
+PASS currentEvent.target == currentEvent.currentTarget is true
+PASS currentEvent.target.correspondingElement == currentEvent.currentTarget.correspondingElement is true
+PASS currentEvent.target.correspondingUseElement == currentEvent.currentTarget.correspondingUseElement is true
+
+Test #10: Verify that the simulated click event got dispatched to the right target
+
+PASS currentEvent.toString() is "[object MouseEvent]"
+PASS currentEvent.type.toString() is "click"
+PASS currentEvent.target.toString() is "[object SVGElementInstance]"
+PASS currentEvent.currentTarget.toString() is "[object SVGElementInstance]"
+PASS currentEvent.target.correspondingElement == rectElement is true
+PASS currentEvent.target.correspondingUseElement == useElement is true
+PASS currentEvent.currentTarget.correspondingElement == rectElement is true
+PASS currentEvent.currentTarget.correspondingUseElement == useElement is true
+PASS currentEvent.target == currentEvent.currentTarget is true
+PASS currentEvent.target.correspondingElement == currentEvent.currentTarget.correspondingElement is true
+PASS currentEvent.target.correspondingUseElement == currentEvent.currentTarget.correspondingUseElement is true
+PASS successfullyParsed is true
+
+
diff --git a/LayoutTests/svg/custom/use-instanceRoot-as-event-target.xhtml b/LayoutTests/svg/custom/use-instanceRoot-as-event-target.xhtml
new file mode 100644 (file)
index 0000000..967be54
--- /dev/null
@@ -0,0 +1,300 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css"/>
+<script src="../../fast/js/resources/js-test-pre.js"/>
+</head>
+<body>
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100px" height="100px">
+  <defs>
+      <rect id="target" fill="red" width="100" height="100" onclick="eventHandler(evt)"/>
+  </defs>
+  <use id="test" xlink:href="url(#target)"/>
+</svg>
+
+<p id="description"/>
+<div id="console"/>
+
+<script>
+var currentEvent;
+var nextEventType;
+var eventNotification;
+
+function eventHandler(evt)
+{
+    if (evt.type != nextEventType)
+        return;
+
+    currentEvent = evt;
+    eval(eventNotification);
+}
+
+function fireMouseOverEvent(newEventNotification)
+{
+    currentEvent = undefined;
+    nextEventType = "mouseover";
+    eventNotification = newEventNotification;
+
+    if (window.eventSender)
+        eventSender.mouseMoveTo(50, 50);
+}
+
+function fireMouseClickEvent(newEventNotification)
+{
+    currentEvent = undefined;
+    nextEventType = "click";
+    eventNotification = newEventNotification;
+
+    if (window.eventSender) {
+        eventSender.mouseMoveTo(50, 50);
+        eventSender.mouseDown();
+        eventSender.mouseUp();
+    }
+}
+
+function fireSimulatedMouseClickEvent(newEventNotification, eventTarget)
+{
+    currentEvent = undefined;
+    nextEventType = "click";
+    eventNotification = newEventNotification;
+
+    var event = document.createEvent("MouseEvents");
+    event.initMouseEvent(nextEventType, true, true, document.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
+
+    eventTarget.dispatchEvent(event);
+}
+
+if (window.layoutTestController)
+    layoutTestController.waitUntilDone();
+
+var useElement = document.getElementById("test");
+var rectElement = document.getElementById("target");
+
+function verifyEvent(evtString, targetString, currentTargetString)
+{
+    shouldBeEqualToString("currentEvent.toString()", "[object MouseEvent]");
+    shouldBeEqualToString("currentEvent.type.toString()", evtString);
+    shouldBeEqualToString("currentEvent.target.toString()", targetString);
+    shouldBeEqualToString("currentEvent.currentTarget.toString()", currentTargetString);
+}
+
+function verifyMouseOverEvent()
+{
+    verifyEvent("mouseover", "[object SVGElementInstance]", "[object SVGElementInstance]");
+
+    shouldBeTrue("currentEvent.target.correspondingElement == rectElement");
+    shouldBeTrue("currentEvent.target.correspondingUseElement == useElement");
+    shouldBeTrue("currentEvent.currentTarget.correspondingElement == rectElement");
+    shouldBeTrue("currentEvent.currentTarget.correspondingUseElement == useElement");
+    shouldBeTrue("currentEvent.target == currentEvent.currentTarget");
+    shouldBeTrue("currentEvent.target.correspondingElement == currentEvent.currentTarget.correspondingElement");
+    shouldBeTrue("currentEvent.target.correspondingUseElement == currentEvent.currentTarget.correspondingUseElement");
+}
+
+function verifyClickEvent()
+{
+    verifyEvent("click", "[object SVGElementInstance]", "[object SVGElementInstance]");
+
+    shouldBeTrue("currentEvent.target.correspondingElement == rectElement");
+    shouldBeTrue("currentEvent.target.correspondingUseElement == useElement");
+    shouldBeTrue("currentEvent.currentTarget.correspondingElement == rectElement");
+    shouldBeTrue("currentEvent.currentTarget.correspondingUseElement == useElement");
+    shouldBeTrue("currentEvent.target == currentEvent.currentTarget");
+    shouldBeTrue("currentEvent.target.correspondingElement == currentEvent.currentTarget.correspondingElement");
+    shouldBeTrue("currentEvent.target.correspondingUseElement == currentEvent.currentTarget.correspondingUseElement");
+}
+
+function verifyClickEventOnReferenced()
+{
+    verifyEvent("click", "[object SVGRectElement]", "[object SVGRectElement]");
+
+    shouldBeTrue("currentEvent.target == rectElement");
+    shouldBeTrue("currentEvent.currentTarget == rectElement");
+    shouldBeTrue("currentEvent.target == currentEvent.currentTarget");
+}
+
+description("Test SVG use element specific event handling using SVGElementInstance: ");
+debug("'useElement' is the original use element");
+debug("'rectElement' is the original element which gets cloned by the use element");
+
+debug("");
+debug("Test #1: Verify that the use element and the contained SVGElementInstance objects are valid");
+debug("");
+
+shouldBeEqualToString("useElement.toString()", "[object SVGUseElement]");
+shouldBeEqualToString("useElement.instanceRoot.toString()", "[object SVGElementInstance]");
+
+shouldBeEqualToString("useElement.instanceRoot.correspondingElement.toString()", "[object SVGRectElement]");
+shouldBeTrue("useElement.instanceRoot.correspondingElement == rectElement");
+
+shouldBeEqualToString("useElement.instanceRoot.correspondingUseElement.toString()", "[object SVGUseElement]");
+shouldBeTrue("useElement.instanceRoot.correspondingUseElement == useElement");
+
+shouldBeEqualToString("typeof useElement.addEventListener", "function");
+shouldBeEqualToString("typeof useElement.removeEventListener", "function");
+shouldBeEqualToString("typeof useElement.dispatchEvent", "function");
+
+// Spec: An element and all its corresponding SVGElementInstance objects share an event
+// listener list. The currentTarget attribute of the event can be used to determine through
+// which object an event listener was invoked.
+useElement.instanceRoot.addEventListener("mouseover", eventHandler, false);
+
+function startEventTests()
+{
+    debug("");
+    debug("Test #2: Verify that events dispatched to the SVGElementInstance objects have correct target property values");
+    debug("");
+
+    // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included as
+    // a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects.
+    // The event's target and currentTarget attributes are set to the SVGElementInstance that corresponds to the target
+    // and current target elements in the referenced subtree. An event propagates through the exposed and non-exposed
+    // portions of the tree in the same manner as it would in the regular document tree: first going from the root element
+    // to the 'use' element and then through non-exposed tree elements in the capture phase, followed by the target phase
+    // at the target of the event, then bubbling back through non-exposed tree to the use element and then back through
+    // regular tree to the root element in bubbling phase.
+    verifyMouseOverEvent();
+
+    // Prepare for next test
+    useElement.instanceRoot.removeEventListener("mouseover", eventHandler, false);
+    useElement.instanceRoot.addEventListener("mouseover", eventHandler, false);
+
+    // Causes svgAttributeChanged() logic to reclone the shadow tree
+    // If 'Test #3' is not executed, then it didn't properly reclone the event listeners.
+    useElement.instanceRoot.correspondingElement.setAttribute("x", useElement.instanceRoot.correspondingElement.getAttribute("x"));
+
+    fireMouseOverEvent("eventTestOne()");
+}
+
+function eventTestOne()
+{
+    debug("");
+    debug("Test #3: Verify that event listeners attached to the shadow tree elements are copied when use reclones the internal shadow tree");
+    debug("");
+
+    // Spec: If event attributes are assigned to referenced elements, then the actual target for the event will be the
+    // SVGElementInstance object within the "instance tree" corresponding to the given referenced element.
+    verifyMouseOverEvent();
+
+    // Prepare for next test
+    useElement.instanceRoot.removeEventListener("mouseover", eventHandler, false);
+    rectElement.addEventListener("mouseover", eventHandler, false);
+
+    fireMouseOverEvent("eventTestTwo()");
+}
+
+function eventTestTwo()
+{
+    debug("");
+    debug("Test #4: Verify that events dispatched to the referenced element end up on the SVElementInstance objects");
+    debug("");
+
+    verifyMouseOverEvent();
+
+    // Prepare for next test
+    rectElement.removeEventListener("mouseover", eventHandler, false);
+    rectElement.addEventListener("mouseover", eventHandler, false);
+
+    // Causes svgAttributeChanged() logic to reclone the shadow tree
+    // If 'Test #5' is not executed, then it didn't properly reclone the event listeners.
+    rectElement.setAttribute("x", rectElement.getAttribute("x"));
+
+    fireMouseOverEvent("eventTestThree()");
+}
+
+function eventTestThree()
+{
+    debug("");
+    debug("Test #5: Verify that event listeners attached to the referenced elements are copied when use reclones the internal shadow tree");
+    debug("");
+
+    verifyMouseOverEvent();
+
+    // Prepare for next test
+    rectElement.removeEventListener("mouseover", eventHandler, false);
+
+    fireSimulatedMouseClickEvent("eventTestFour()", rectElement);
+}
+
+function eventTestFour()
+{
+    debug("");
+    debug("Test #6: Verify that a click event got dispatched to the original tree as defined in the markup, when sent to the 'rectElement'"); 
+    debug("");
+
+    verifyClickEventOnReferenced();
+
+    // Prepare for next test
+    fireSimulatedMouseClickEvent("eventTestFive()", useElement.instanceRoot);
+}
+
+function eventTestFive()
+{
+    debug("");
+    debug("Test #7: Verify that a click event got dispatched to the instance tree when sent to the 'useElement.instanceRoot' with an event listener attached to 'rectElement'"); 
+    debug("");
+
+    verifyClickEvent();
+
+    // Prepare for next test
+    fireMouseClickEvent("eventTestSix()");
+}
+
+function eventTestSix()
+{
+    debug("");
+    debug("Test #8: Verify that the original click event listener defined in markup is still working properly");
+    debug("");
+
+    verifyClickEvent();
+
+    // Prepare for next test
+    rectElement.removeEventListener("click", eventHandler, false);
+    useElement.instanceRoot.addEventListener("click", eventHandler, false);
+
+    fireMouseClickEvent("eventTestSeven()");
+}
+
+function eventTestSeven()
+{
+    debug("");
+    debug("Test #9: Verify that the original click event listener got removed and a new one attached to the use root SVGElementInstance");
+    debug("");
+
+    verifyClickEvent();
+
+    // Prepare for next tests
+    fireSimulatedMouseClickEvent("eventTestEight()", useElement.instanceRoot);
+}
+
+function eventTestEight()
+{
+    debug("");
+    debug("Test #10: Verify that the simulated click event got dispatched to the right target");
+    debug("");
+
+    verifyClickEvent();
+
+    // Cleanup
+    useElement.instanceRoot.removeEventListener("click", eventHandler, false);
+
+    stopEventTests();
+}
+
+function stopEventTests()
+{
+    successfullyParsed = true;
+
+    rectElement.setAttribute("fill", "green");
+    shouldBeTrue("successfullyParsed");
+    debug('<br /><span class="pass">TEST COMPLETE</span>');
+
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+
+fireMouseOverEvent("startEventTests()");
+</script>
+
+</body>
+</html>
diff --git a/LayoutTests/svg/custom/use-instanceRoot-event-bubbling-expected.txt b/LayoutTests/svg/custom/use-instanceRoot-event-bubbling-expected.txt
new file mode 100644 (file)
index 0000000..ec6b5c5
--- /dev/null
@@ -0,0 +1,19 @@
+Tests wheter SVG event bubbling works accross shadow trees.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS msg is "[EventHandler 1] type: click phase: AT_TARGET target: [object SVGElementInstance] (id: rect) currentTarget: [object SVGElementInstance] (id: rect)"
+PASS msg is "[EventHandler 1] type: click phase: AT_TARGET target: [object SVGElementInstance] (id: rect) currentTarget: [object SVGElementInstance] (id: rect)"
+PASS msg is "[EventHandler 2] type: click phase: BUBBLING target: [object SVGElementInstance] (id: rect) currentTarget: [object SVGElementInstance] (id: rectParent)"
+PASS msg is "[EventHandler 1] type: click phase: AT_TARGET target: [object SVGElementInstance] (id: rect) currentTarget: [object SVGElementInstance] (id: rect)"
+PASS msg is "[EventHandler 2] type: click phase: BUBBLING target: [object SVGElementInstance] (id: rect) currentTarget: [object SVGElementInstance] (id: rectParent)"
+PASS msg is "[EventHandler 3] type: click phase: BUBBLING target: [object SVGElementInstance] (id: rect) currentTarget: [object SVGUseElement] (id: use)"
+PASS msg is "[EventHandler 1] type: click phase: AT_TARGET target: [object SVGElementInstance] (id: rect) currentTarget: [object SVGElementInstance] (id: rect)"
+PASS msg is "[EventHandler 2] type: click phase: BUBBLING target: [object SVGElementInstance] (id: rect) currentTarget: [object SVGElementInstance] (id: rectParent)"
+PASS msg is "[EventHandler 3] type: click phase: BUBBLING target: [object SVGElementInstance] (id: rect) currentTarget: [object SVGUseElement] (id: use)"
+PASS msg is "[EventHandler 4] type: click phase: BUBBLING target: [object SVGElementInstance] (id: rect) currentTarget: [object SVGGElement] (id: useParent)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/custom/use-instanceRoot-event-bubbling.xhtml b/LayoutTests/svg/custom/use-instanceRoot-event-bubbling.xhtml
new file mode 100644 (file)
index 0000000..5e3c14f
--- /dev/null
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css"/>
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="resources/use-instanceRoot-event-bubbling.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/custom/use-instanceRoot-event-listeners-expected.txt b/LayoutTests/svg/custom/use-instanceRoot-event-listeners-expected.txt
new file mode 100644 (file)
index 0000000..c6215a2
--- /dev/null
@@ -0,0 +1,17 @@
+Test attaching event listeners on SVG use elements in different ways:
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Test 1 / 8 PASSED
+Test 2 / 8 PASSED
+Test 3 / 8 PASSED
+Test 4 / 8 PASSED
+Test 5 / 8 PASSED
+Test 6 / 8 PASSED
+Test 7 / 8 PASSED
+Test 8 / 8 PASSED
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/custom/use-instanceRoot-event-listeners.xhtml b/LayoutTests/svg/custom/use-instanceRoot-event-listeners.xhtml
new file mode 100644 (file)
index 0000000..9dbb538
--- /dev/null
@@ -0,0 +1,19 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css"/>
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="150" height="150">
+  <defs>
+      <rect id="target" fill="red" width="100" height="100" onmousedown="eventHandler(evt)"/>
+  </defs>
+  <use id="test" xlink:href="#target"/>
+</svg>
+
+<p id="description"></p>
+<div id="console"></div>
+<script src="resources/use-instanceRoot-event-listeners.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/custom/use-setAttribute-crash-expected.txt b/LayoutTests/svg/custom/use-setAttribute-crash-expected.txt
new file mode 100644 (file)
index 0000000..5a1185d
--- /dev/null
@@ -0,0 +1,12 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x220
+  RenderBlock {html} at (0,0) size 800x220
+    RenderBody {body} at (8,8) size 784x204
+      RenderSVGRoot {svg:svg} at (33.00,33.00) size 50.00x50.00
+        RenderSVGHiddenContainer {svg:defs} at (0,0) size 0x0
+        RenderSVGContainer {svg:use} at (33.00,33.00) size 50.00x50.00
+          RenderSVGContainer {g} at (33.00,33.00) size 50.00x50.00 [transform={m=((1.00,0.00)(0.00,1.00)) t=(50.00,50.00)}]
+            RenderSVGViewportContainer {svg} at (33.00,33.00) size 50.00x50.00
+              RenderPath {svg:circle} at (33.00,33.00) size 50.00x50.00 [transform={m=((10.00,0.00)(0.00,10.00)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#FF0000]}] [data="M2.00,0.00 L2.00,0.13 L1.98,0.25 L1.96,0.37 L1.94,0.50 L1.90,0.62 L1.86,0.74 L1.81,0.85 L1.75,0.96 L1.69,1.07 L1.62,1.18 L1.54,1.27 L1.46,1.37 L1.37,1.46 L1.27,1.54 L1.18,1.62 L1.07,1.69 L0.96,1.75 L0.85,1.81 L0.74,1.86 L0.62,1.90 L0.50,1.94 L0.37,1.96 L0.25,1.98 L0.13,2.00 L-0.00,2.00 L-0.13,2.00 L-0.25,1.98 L-0.37,1.96 L-0.50,1.94 L-0.62,1.90 L-0.74,1.86 L-0.85,1.81 L-0.96,1.75 L-1.07,1.69 L-1.18,1.62 L-1.27,1.54 L-1.37,1.46 L-1.46,1.37 L-1.54,1.27 L-1.62,1.18 L-1.69,1.07 L-1.75,0.96 L-1.81,0.85 L-1.86,0.74 L-1.90,0.62 L-1.94,0.50 L-1.96,0.37 L-1.98,0.25 L-2.00,0.13 L-2.00,-0.00 L-2.00,-0.13 L-1.98,-0.25 L-1.96,-0.37 L-1.94,-0.50 L-1.90,-0.62 L-1.86,-0.74 L-1.81,-0.85 L-1.75,-0.96 L-1.69,-1.07 L-1.62,-1.18 L-1.54,-1.27 L-1.46,-1.37 L-1.37,-1.46 L-1.27,-1.54 L-1.18,-1.62 L-1.07,-1.69 L-0.96,-1.75 L-0.85,-1.81 L-0.74,-1.86 L-0.62,-1.90 L-0.50,-1.94 L-0.37,-1.96 L-0.25,-1.98 L-0.13,-2.00 L0.00,-2.00 L0.13,-2.00 L0.25,-1.98 L0.37,-1.96 L0.50,-1.94 L0.62,-1.90 L0.74,-1.86 L0.85,-1.81 L0.96,-1.75 L1.07,-1.69 L1.18,-1.62 L1.27,-1.54 L1.37,-1.46 L1.46,-1.37 L1.54,-1.27 L1.62,-1.18 L1.69,-1.07 L1.75,-0.96 L1.81,-0.85 L1.86,-0.74 L1.90,-0.62 L1.94,-0.50 L1.96,-0.37 L1.98,-0.25 L2.00,-0.13"]
+      RenderText {#text} at (0,0) size 0x0
diff --git a/LayoutTests/svg/custom/use-setAttribute-crash.svg b/LayoutTests/svg/custom/use-setAttribute-crash.svg
new file mode 100644 (file)
index 0000000..bbd4804
--- /dev/null
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">\r
+<head><script type="text/javascript"><![CDATA[\r
+var state = true;\r
+\r
+if (window.layoutTestController)\r
+    layoutTestController.waitUntilDone();\r
+\r
+function test()\r
+{\r
+    if (state) {\r
+        var svg = document.getElementById('svg');\r
+        var circle = document.getElementById('circle');\r
+        var use = document.getElementById('use');\r
+        use.setAttribute('fill', '#f00');\r
+        svg.setAttribute('width', 200);\r
+        svg.setAttribute('height', 200);\r
+        circle.setAttribute('transform', 'scale(' + 10 + ')');\r
+    } else {\r
+        var svg = document.getElementById('svg');\r
+        var circle = document.getElementById('circle');\r
+        var use = document.getElementById('use');\r
+        use.setAttribute('fill', '#fff');\r
+        svg.setAttribute('width', 100);\r
+        svg.setAttribute('height', 100);\r
+        circle.setAttribute('transform', 'scale(' + 2 + ')');\r
+    }\r
+\r
+    if (window.layoutTestController)\r
+        layoutTestController.notifyDone();\r
+\r
+    state = !state;\r
+}\r
+\r
+function startTest() {\r
+    if (window.eventSender) {\r
+        eventSender.mouseMoveTo(10, 10);\r
+        eventSender.mouseDown();\r
+        eventSender.mouseUp();\r
+    }\r
+}\r
+\r
+setTimeout("startTest()", 100);\r
+]]></script>\r
+\r
+<title>test</title>\r
+\r
+</head>\r
+<body onclick="test()">\r
+<svg:svg id="svg" width="100" height="100">\r
+<svg:defs>\r
+<svg:symbol id="symbol" overflow="visible">\r
+<svg:circle id="circle" cx="0" cy="0" r="2" stroke="#000" transform="scale(2)" />\r
+</svg:symbol>\r
+</svg:defs>\r
+<svg:use id="use" x="50" y="50" fill="#fff" xlink:href="#symbol" />\r
+</svg:svg>\r
+</body>\r
+</html>\r
+\r
index 766388a..770700c 100644 (file)
@@ -1,3 +1,195 @@
+2008-10-08  Nikolas Zimmermann  <zimmermann@kde.org>
+
+        Reviewed by Oliver Hunt & Sam Weining.
+
+        Fixes: https://bugs.webkit.org/show_bug.cgi?id=15413 (SVGElementInstance does not implement EventTarget)
+        Fixes: https://bugs.webkit.org/show_bug.cgi?id=15430 (SVGElementInstances should rebuild themselves lazily)
+        Fixes: https://bugs.webkit.org/show_bug.cgi?id=20550 (SVGUseElement.setAttribute crashes Safari)
+
+        Rebuild SVG use element shadow tree lazily. Mark SVGElementInstance with the "needsUpdate" flag.
+        Next time SVGUseElement::recalcStyle is invoked (ie. via Document::updateDocumentsRendering()) the
+        use tree is rebuild.
+
+        Make SVGElementInstance a real EventTarget, as the SVG specification demands.
+        When dispatching events to a shadow tree element of a use element, the associated SVGElementInstance
+        is used as event target. The SVGElementInstance, the shadow tree element and the corresponding element
+        share an event listener list. Every event listener change on the SVGElementInstance object is forwared
+        to the corresponding element. Each change marks the SVGElementInstance tree dirty, and causes a reclone.
+        Each event listener defined via attributes (onclick/onkeydown/...) is copied from the correspondingElement
+        to the shadow tree element - through the cloneNode calls - if the use element's shadow tree gets rebuild.
+        Each listener, dynamically created using addEventListener, gets copied to the corersponding element as well.
+
+        Now that the target/currentTarget properties of the Events are correct, event bubbling works as expected,
+        see resources/use-instanceRoot-event-bubbling.js for details.
+
+        Tests: svg/custom/use-elementInstance-event-target.svg (reenabled)
+               svg/custom/use-elementInstance-methods.svg (reenabled)
+               svg/custom/use-setAttribute-crash.svg (covers bug 20550)
+               svg/custom/use-instanceRoot-as-event-target.xhtml (covers bug 15413)
+               svg/custom/use-instanceRoot-event-bubbling.xhtml (covers bug 15413)
+               svg/custom/use-instanceRoot-event-listeners.xhtml (covers bug 15413 & 15430)
+
+        * DerivedSources.make:
+        * GNUmakefile.am:
+        * WebCore.pro:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/JSEventListener.h:
+        (WebCore::JSLazyEventListener::wasCreatedFromMarkup):
+        * bindings/js/JSEventTarget.cpp:
+        * bindings/js/JSEventTargetSVGElementInstance.cpp: Removed.
+        * bindings/js/JSEventTargetSVGElementInstance.h: Removed.
+        * bindings/js/JSSVGElementInstanceCustom.cpp:
+        (WebCore::JSSVGElementInstance::addEventListener):
+        (WebCore::JSSVGElementInstance::removeEventListener):
+        (WebCore::JSSVGElementInstance::pushEventHandlerScope):
+        * bindings/scripts/CodeGeneratorJS.pm:
+        * bindings/scripts/CodeGeneratorObjC.pm:
+        * dom/EventListener.h:
+        (WebCore::EventListener::wasCreatedFromMarkup):
+        * dom/EventTargetNode.cpp:
+        (WebCore::updateSVGElementInstancesAfterEventListenerChange):
+        (WebCore::EventTargetNode::addEventListener):
+        (WebCore::EventTargetNode::removeEventListener):
+        (WebCore::eventTargetAsSVGElementInstance):
+        (WebCore::eventTargetRespectingSVGTargetRules):
+        (WebCore::EventTargetNode::dispatchEvent):
+        (WebCore::EventTargetNode::dispatchGenericEvent):
+        (WebCore::EventTargetNode::removeEventListenerForType):
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::clear):
+        (WebCore::instanceAssociatedWithShadowTreeElement):
+        (WebCore::EventHandler::updateMouseEventTargetNode):
+        * page/EventHandler.h:
+        * svg/EventTargetSVGElementInstance.cpp: Removed.
+        * svg/EventTargetSVGElementInstance.h: Removed.
+        * svg/SVGElementInstance.cpp:
+        (WebCore::SVGElementInstance::SVGElementInstance):
+        (WebCore::SVGElementInstance::~SVGElementInstance):
+        (WebCore::SVGElementInstance::childNodes):
+        (WebCore::SVGElementInstance::setShadowTreeElement):
+        (WebCore::SVGElementInstance::forgetWrapper):
+        (WebCore::SVGElementInstance::appendChild):
+        (WebCore::SVGElementInstance::invalidateAllInstancesOfElement):
+        (WebCore::SVGElementInstance::setNeedsUpdate):
+        (WebCore::SVGElementInstance::associatedFrame):
+        (WebCore::SVGElementInstance::addEventListener):
+        (WebCore::SVGElementInstance::removeEventListener):
+        (WebCore::SVGElementInstance::dispatchEvent):
+        (WebCore::SVGElementInstance::onabort):
+        (WebCore::SVGElementInstance::setOnabort):
+        (WebCore::SVGElementInstance::onblur):
+        (WebCore::SVGElementInstance::setOnblur):
+        (WebCore::SVGElementInstance::onchange):
+        (WebCore::SVGElementInstance::setOnchange):
+        (WebCore::SVGElementInstance::onclick):
+        (WebCore::SVGElementInstance::setOnclick):
+        (WebCore::SVGElementInstance::oncontextmenu):
+        (WebCore::SVGElementInstance::setOncontextmenu):
+        (WebCore::SVGElementInstance::ondblclick):
+        (WebCore::SVGElementInstance::setOndblclick):
+        (WebCore::SVGElementInstance::onerror):
+        (WebCore::SVGElementInstance::setOnerror):
+        (WebCore::SVGElementInstance::onfocus):
+        (WebCore::SVGElementInstance::setOnfocus):
+        (WebCore::SVGElementInstance::oninput):
+        (WebCore::SVGElementInstance::setOninput):
+        (WebCore::SVGElementInstance::onkeydown):
+        (WebCore::SVGElementInstance::setOnkeydown):
+        (WebCore::SVGElementInstance::onkeypress):
+        (WebCore::SVGElementInstance::setOnkeypress):
+        (WebCore::SVGElementInstance::onkeyup):
+        (WebCore::SVGElementInstance::setOnkeyup):
+        (WebCore::SVGElementInstance::onload):
+        (WebCore::SVGElementInstance::setOnload):
+        (WebCore::SVGElementInstance::onmousedown):
+        (WebCore::SVGElementInstance::setOnmousedown):
+        (WebCore::SVGElementInstance::onmousemove):
+        (WebCore::SVGElementInstance::setOnmousemove):
+        (WebCore::SVGElementInstance::onmouseout):
+        (WebCore::SVGElementInstance::setOnmouseout):
+        (WebCore::SVGElementInstance::onmouseover):
+        (WebCore::SVGElementInstance::setOnmouseover):
+        (WebCore::SVGElementInstance::onmouseup):
+        (WebCore::SVGElementInstance::setOnmouseup):
+        (WebCore::SVGElementInstance::onmousewheel):
+        (WebCore::SVGElementInstance::setOnmousewheel):
+        (WebCore::SVGElementInstance::onbeforecut):
+        (WebCore::SVGElementInstance::setOnbeforecut):
+        (WebCore::SVGElementInstance::oncut):
+        (WebCore::SVGElementInstance::setOncut):
+        (WebCore::SVGElementInstance::onbeforecopy):
+        (WebCore::SVGElementInstance::setOnbeforecopy):
+        (WebCore::SVGElementInstance::oncopy):
+        (WebCore::SVGElementInstance::setOncopy):
+        (WebCore::SVGElementInstance::onbeforepaste):
+        (WebCore::SVGElementInstance::setOnbeforepaste):
+        (WebCore::SVGElementInstance::onpaste):
+        (WebCore::SVGElementInstance::setOnpaste):
+        (WebCore::SVGElementInstance::ondragenter):
+        (WebCore::SVGElementInstance::setOndragenter):
+        (WebCore::SVGElementInstance::ondragover):
+        (WebCore::SVGElementInstance::setOndragover):
+        (WebCore::SVGElementInstance::ondragleave):
+        (WebCore::SVGElementInstance::setOndragleave):
+        (WebCore::SVGElementInstance::ondrop):
+        (WebCore::SVGElementInstance::setOndrop):
+        (WebCore::SVGElementInstance::ondragstart):
+        (WebCore::SVGElementInstance::setOndragstart):
+        (WebCore::SVGElementInstance::ondrag):
+        (WebCore::SVGElementInstance::setOndrag):
+        (WebCore::SVGElementInstance::ondragend):
+        (WebCore::SVGElementInstance::setOndragend):
+        (WebCore::SVGElementInstance::onreset):
+        (WebCore::SVGElementInstance::setOnreset):
+        (WebCore::SVGElementInstance::onresize):
+        (WebCore::SVGElementInstance::setOnresize):
+        (WebCore::SVGElementInstance::onscroll):
+        (WebCore::SVGElementInstance::setOnscroll):
+        (WebCore::SVGElementInstance::onsearch):
+        (WebCore::SVGElementInstance::setOnsearch):
+        (WebCore::SVGElementInstance::onselect):
+        (WebCore::SVGElementInstance::setOnselect):
+        (WebCore::SVGElementInstance::onselectstart):
+        (WebCore::SVGElementInstance::setOnselectstart):
+        (WebCore::SVGElementInstance::onsubmit):
+        (WebCore::SVGElementInstance::setOnsubmit):
+        (WebCore::SVGElementInstance::onunload):
+        (WebCore::SVGElementInstance::setOnunload):
+        * svg/SVGElementInstance.h:
+        (WebCore::SVGElementInstance::needsUpdate):
+        (WebCore::SVGElementInstance::toNode):
+        (WebCore::SVGElementInstance::toSVGElementInstance):
+        (WebCore::SVGElementInstance::correspondingElement):
+        (WebCore::SVGElementInstance::correspondingUseElement):
+        (WebCore::SVGElementInstance::shadowTreeElement):
+        (WebCore::SVGElementInstance::parentNode):
+        (WebCore::SVGElementInstance::previousSibling):
+        (WebCore::SVGElementInstance::nextSibling):
+        (WebCore::SVGElementInstance::firstChild):
+        (WebCore::SVGElementInstance::lastChild):
+        (WebCore::SVGElementInstance::ownerDocument):
+        (WebCore::SVGElementInstance::hasChildNodes):
+        (WebCore::SVGElementInstance::setFirstChild):
+        (WebCore::SVGElementInstance::setLastChild):
+        (WebCore::SVGElementInstance::setNextSibling):
+        (WebCore::SVGElementInstance::setPreviousSibling):
+        (WebCore::SVGElementInstance::refEventTarget):
+        (WebCore::SVGElementInstance::derefEventTarget):
+        * svg/SVGElementInstance.idl:
+        * svg/SVGStyledElement.cpp:
+        (WebCore::SVGStyledElement::svgAttributeChanged):
+        (WebCore::SVGStyledElement::childrenChanged):
+        * svg/SVGUseElement.cpp:
+        (WebCore::SVGUseElement::svgAttributeChanged):
+        (WebCore::shadowTreeContainsChangedNodes):
+        (WebCore::SVGUseElement::recalcStyle):
+        (WebCore::dumpInstanceTree):
+        (WebCore::SVGUseElement::buildPendingResource):
+        (WebCore::SVGUseElement::buildInstanceTree):
+        (WebCore::SVGUseElement::transferEventListenersToShadowTree):
+        * svg/SVGUseElement.h:
+
 2008-10-08  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Cameron Zwarich.
index 25562d4..af168f9 100644 (file)
@@ -371,7 +371,6 @@ all : \
     $(filter-out JSEventListener.h JSRGBColor.h,$(DOM_CLASSES:%=JS%.h)) \
     \
     JSDOMWindowBase.lut.h \
-    JSEventTargetSVGElementInstance.lut.h \
     JSRGBColor.lut.h \
     \
     JSJavaScriptCallFrame.h \
index fdb43fb..48281a5 100644 (file)
@@ -55,7 +55,6 @@ webcore_built_nosources += \
        DerivedSources/tokenizer.cpp \
        DerivedSources/ColorData.c \
        WebCore/bindings/js/JSDOMWindowBase.lut.h \
-       WebCore/bindings/js/JSEventTargetSVGElementInstance.lut.h \
        WebCore/bindings/js/JSRGBColor.lut.h
 
 webcore_built_sources += \
@@ -348,8 +347,6 @@ webcore_sources += \
        WebCore/bindings/js/JSEventTarget.h \
        WebCore/bindings/js/JSEventTargetBase.h \
        WebCore/bindings/js/JSEventTargetNodeCustom.cpp \
-       WebCore/bindings/js/JSEventTargetSVGElementInstance.cpp \
-       WebCore/bindings/js/JSEventTargetSVGElementInstance.h \
        WebCore/bindings/js/JSHTMLAllCollection.cpp \
        WebCore/bindings/js/JSHTMLAllCollection.h \
        WebCore/bindings/js/JSHTMLAppletElementCustom.cpp \
@@ -2394,8 +2391,6 @@ webcore_sources += \
        WebCore/svg/ColorDistance.cpp \
        WebCore/svg/ColorDistance.h \
        WebCore/svg/ElementTimeControl.h \
-       WebCore/svg/EventTargetSVGElementInstance.cpp \
-       WebCore/svg/EventTargetSVGElementInstance.h \
        WebCore/svg/Filter.cpp \
        WebCore/svg/Filter.h \
        WebCore/svg/FilterBuilder.h \
@@ -2997,7 +2992,6 @@ webcore_dist += \
 # Clean rules for WebCore
 
 CLEANFILES += \
-       WebCore/bindings/js/JSEventTargetSVGElementInstance.lut.h \
        WebCore/bindings/js/JSDOMWindowBase.lut.h \
        WebCore/bindings/js/JSRGBColor.lut.h
 
index f8badaf..76523b1 100644 (file)
@@ -202,7 +202,6 @@ STYLESHEETS_EMBED = $$PWD/css/html4.css
 
 LUT_FILES += \
     bindings/js/JSDOMWindowBase.cpp \
-    bindings/js/JSEventTargetSVGElementInstance.cpp \
     bindings/js/JSRGBColor.cpp
 
 IDL_BINDINGS += \
@@ -381,7 +380,6 @@ SOURCES += \
     bindings/js/JSEventCustom.cpp \
     bindings/js/JSEventTarget.cpp \
     bindings/js/JSEventTargetNodeCustom.cpp \
-    bindings/js/JSEventTargetSVGElementInstance.cpp \
     bindings/js/JSHTMLAllCollection.cpp \
     bindings/js/JSHistoryCustom.cpp \
     bindings/js/JSJavaScriptCallFrameCustom.cpp \
@@ -1469,7 +1467,6 @@ contains(DEFINES, ENABLE_SVG=1) {
         rendering/style/SVGRenderStyleDefs.cpp \
         svg/SVGZoomEvent.cpp \
         rendering/PointerEventsHitRules.cpp \
-        svg/EventTargetSVGElementInstance.cpp \
         svg/FilterEffect.cpp \
         svg/SVGDocumentExtensions.cpp \
         svg/SVGImageLoader.cpp \
index 608ed54..8a4226e 100644 (file)
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSEventTargetSVGElementInstance.lut.h"\r
-                               >\r
-                       </File>\r
-                       <File\r
                                RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSFile.h"\r
                                >\r
                        </File>\r
                                        >\r
                                </File>\r
                                <File\r
-                                       RelativePath="..\bindings\js\JSEventTargetSVGElementInstance.cpp"\r
-                                       >\r
-                               </File>\r
-                               <File\r
-                                       RelativePath="..\bindings\js\JSEventTargetSVGElementInstance.h"\r
-                                       >\r
-                               </File>\r
-                               <File\r
                                        RelativePath="..\bindings\js\JSHistoryCustom.cpp"\r
                                        >\r
                                </File>\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\svg\EventTargetSVGElementInstance.cpp"\r
-                               >\r
-                               <FileConfiguration\r
-                                       Name="Release_PGO|Win32"\r
-                                       >\r
-                                       <Tool\r
-                                               Name="VCCLCompilerTool"\r
-                                               WholeProgramOptimization="true"\r
-                                       />\r
-                               </FileConfiguration>\r
-                       </File>\r
-                       <File\r
-                               RelativePath="..\svg\EventTargetSVGElementInstance.h"\r
-                               >\r
-                       </File>\r
-                       <File\r
                                RelativePath="..\svg\SVGAElement.cpp"\r
                                >\r
                        </File>\r
index 34f4826..996712e 100644 (file)
                066C77310AB603FD00238CC4 /* RenderFileUploadControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 066C772F0AB603FD00238CC4 /* RenderFileUploadControl.h */; };
                06E81ED70AB5D5E900C87837 /* LocalCurrentGraphicsContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 06E81ED60AB5D5E900C87837 /* LocalCurrentGraphicsContext.h */; };
                06E81EEC0AB5DA9700C87837 /* LocalCurrentGraphicsContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = 06E81EEB0AB5DA9700C87837 /* LocalCurrentGraphicsContext.mm */; };
-               084174F30E85CED800AFB1C5 /* JSEventTargetSVGElementInstance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 084174F10E85CED800AFB1C5 /* JSEventTargetSVGElementInstance.cpp */; };
-               084174F40E85CED800AFB1C5 /* JSEventTargetSVGElementInstance.h in Headers */ = {isa = PBXBuildFile; fileRef = 084174F20E85CED800AFB1C5 /* JSEventTargetSVGElementInstance.h */; };
                089582550E857A7E00F82C83 /* ImageLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 089582530E857A7E00F82C83 /* ImageLoader.cpp */; };
                089582560E857A7E00F82C83 /* ImageLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 089582540E857A7E00F82C83 /* ImageLoader.h */; };
                08A484770E5272C500C3FE76 /* ScriptElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08A484750E5272C500C3FE76 /* ScriptElement.cpp */; };
                08A484780E5272C500C3FE76 /* ScriptElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 08A484760E5272C500C3FE76 /* ScriptElement.h */; };
                08A48A6E0E86CF6D00E225DD /* JSSVGElementInstanceCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08A48A6D0E86CF6D00E225DD /* JSSVGElementInstanceCustom.cpp */; };
-               08A48A790E86CF8C00E225DD /* EventTargetSVGElementInstance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08A48A770E86CF8C00E225DD /* EventTargetSVGElementInstance.cpp */; };
-               08A48A7A0E86CF8C00E225DD /* EventTargetSVGElementInstance.h in Headers */ = {isa = PBXBuildFile; fileRef = 08A48A780E86CF8C00E225DD /* EventTargetSVGElementInstance.h */; };
                08E4FE460E2BD41400F4CAE0 /* JSSVGLengthCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08E4FE450E2BD41400F4CAE0 /* JSSVGLengthCustom.cpp */; };
                0A4844990CA44CB200B7BD48 /* SoftLinking.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A4844980CA44CB200B7BD48 /* SoftLinking.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F56028F0E4B76580065B038 /* RenderMarquee.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F56028D0E4B76580065B038 /* RenderMarquee.h */; };
                BC3B7AF30E919CA900D54065 /* JSEventTargetNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC3B7AF10E919CA900D54065 /* JSEventTargetNode.cpp */; };
                BC3B7AF40E919CA900D54065 /* JSEventTargetNode.h in Headers */ = {isa = PBXBuildFile; fileRef = BC3B7AF20E919CA900D54065 /* JSEventTargetNode.h */; };
                BC3B7B210E91AAF400D54065 /* JSEventTargetNodeCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC3B7B200E91AAF400D54065 /* JSEventTargetNodeCustom.cpp */; };
-               BC3BA04F0E8C46DA00FC5D20 /* JSEventTargetSVGElementInstance.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = BC3BA04D0E8C46DA00FC5D20 /* JSEventTargetSVGElementInstance.lut.h */; };
                BC3BC29C0E91AB0F00835588 /* HostWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = BC3BC29B0E91AB0F00835588 /* HostWindow.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BC3BE12B0E98092F00835588 /* PopupMenuStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = BC3BE12A0E98092F00835588 /* PopupMenuStyle.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BC3C39B60C0D3D8D005F4D7A /* JSMediaList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC3C39B40C0D3D8D005F4D7A /* JSMediaList.cpp */; };
                066C772F0AB603FD00238CC4 /* RenderFileUploadControl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RenderFileUploadControl.h; sourceTree = "<group>"; };
                06E81ED60AB5D5E900C87837 /* LocalCurrentGraphicsContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalCurrentGraphicsContext.h; sourceTree = "<group>"; };
                06E81EEB0AB5DA9700C87837 /* LocalCurrentGraphicsContext.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = LocalCurrentGraphicsContext.mm; sourceTree = "<group>"; };
-               084174F10E85CED800AFB1C5 /* JSEventTargetSVGElementInstance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSEventTargetSVGElementInstance.cpp; sourceTree = "<group>"; };
-               084174F20E85CED800AFB1C5 /* JSEventTargetSVGElementInstance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSEventTargetSVGElementInstance.h; sourceTree = "<group>"; };
                089582530E857A7E00F82C83 /* ImageLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageLoader.cpp; sourceTree = "<group>"; };
                089582540E857A7E00F82C83 /* ImageLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageLoader.h; sourceTree = "<group>"; };
                08A484750E5272C500C3FE76 /* ScriptElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptElement.cpp; sourceTree = "<group>"; };
                08A484760E5272C500C3FE76 /* ScriptElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptElement.h; sourceTree = "<group>"; };
                08A48A6D0E86CF6D00E225DD /* JSSVGElementInstanceCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSVGElementInstanceCustom.cpp; sourceTree = "<group>"; };
-               08A48A770E86CF8C00E225DD /* EventTargetSVGElementInstance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventTargetSVGElementInstance.cpp; sourceTree = "<group>"; };
-               08A48A780E86CF8C00E225DD /* EventTargetSVGElementInstance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventTargetSVGElementInstance.h; sourceTree = "<group>"; };
                08E4FE450E2BD41400F4CAE0 /* JSSVGLengthCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSVGLengthCustom.cpp; sourceTree = "<group>"; };
                0A4844980CA44CB200B7BD48 /* SoftLinking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SoftLinking.h; sourceTree = "<group>"; };
                0F56028D0E4B76580065B038 /* RenderMarquee.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderMarquee.h; sourceTree = "<group>"; };
                BC3B7AF10E919CA900D54065 /* JSEventTargetNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSEventTargetNode.cpp; sourceTree = "<group>"; };
                BC3B7AF20E919CA900D54065 /* JSEventTargetNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSEventTargetNode.h; sourceTree = "<group>"; };
                BC3B7B200E91AAF400D54065 /* JSEventTargetNodeCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSEventTargetNodeCustom.cpp; sourceTree = "<group>"; };
-               BC3BA04D0E8C46DA00FC5D20 /* JSEventTargetSVGElementInstance.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSEventTargetSVGElementInstance.lut.h; sourceTree = "<group>"; };
                BC3BC29B0E91AB0F00835588 /* HostWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HostWindow.h; sourceTree = "<group>"; };
                BC3BE12A0E98092F00835588 /* PopupMenuStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PopupMenuStyle.h; sourceTree = "<group>"; };
                BC3C39B40C0D3D8D005F4D7A /* JSMediaList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaList.cpp; sourceTree = "<group>"; };
                                14E8378D09F85D4F00B85AE4 /* JSEvent.h */,
                                BC60D9BD0D2A269A00B9918F /* JSEventException.cpp */,
                                BC60D9BE0D2A269A00B9918F /* JSEventException.h */,
-                               BC3BA04D0E8C46DA00FC5D20 /* JSEventTargetSVGElementInstance.lut.h */,
                                A86629CE09DA2B47009633A5 /* JSKeyboardEvent.cpp */,
                                A86629CD09DA2B47009633A5 /* JSKeyboardEvent.h */,
                                E107400B0E77BDC00033AF24 /* JSMessageChannel.cpp */,
                                B22277CC0D00BF1F0071B782 /* ColorDistance.h */,
                                E415F1830D9A1A830033CE97 /* ElementTimeControl.h */,
                                E415F10C0D9A05870033CE97 /* ElementTimeControl.idl */,
-                               08A48A770E86CF8C00E225DD /* EventTargetSVGElementInstance.cpp */,
-                               08A48A780E86CF8C00E225DD /* EventTargetSVGElementInstance.h */,
                                50A5E4710E1AEF3A000A03AE /* Filter.cpp */,
                                50A5DF730E1A13C9000A03AE /* Filter.h */,
                                50A5DF740E1A13C9000A03AE /* FilterBuilder.h */,
                                93B70D4D09EB0C7C009D8468 /* JSEventListener.cpp */,
                                93B70D4E09EB0C7C009D8468 /* JSEventListener.h */,
                                B25BE50F0D06B70800B524C6 /* JSEventTargetBase.h */,
-                               084174F10E85CED800AFB1C5 /* JSEventTargetSVGElementInstance.cpp */,
-                               084174F20E85CED800AFB1C5 /* JSEventTargetSVGElementInstance.h */,
                                BC6DC7A00C1A4BFA004E2017 /* JSHTMLAllCollection.h */,
                                9350E70C0E87500B00189FFF /* JSHTMLAllCollection.cpp */,
                                A826E8AD0A1A8F2300CD1BB6 /* JSHTMLOptionElementConstructor.cpp */,
                                BC22747B0E8366E200E7F975 /* SVGRenderStyleDefs.h in Headers */,
                                B2F34FE60E82F81400F627CD /* DNS.h in Headers */,
                                089582560E857A7E00F82C83 /* ImageLoader.h in Headers */,
-                               084174F40E85CED800AFB1C5 /* JSEventTargetSVGElementInstance.h in Headers */,
                                A8CB413E0E8633FD0032C4F0 /* DashArray.h in Headers */,
-                               08A48A7A0E86CF8C00E225DD /* EventTargetSVGElementInstance.h in Headers */,
                                930B3BE20E884921009770C5 /* JSCanvasPixelArrayCustom.h in Headers */,
                                BCF937E70E8B2E95005C7AB7 /* JSDOMWindowBase.lut.h in Headers */,
-                               BC3BA04F0E8C46DA00FC5D20 /* JSEventTargetSVGElementInstance.lut.h in Headers */,
                                63F5D4F70E8C4B7100C0BD04 /* ElementRareData.h in Headers */,
                                BC3B7AF40E919CA900D54065 /* JSEventTargetNode.h in Headers */,
                                BC60901F0E91B8EC000C68B5 /* JSEventTarget.h in Headers */,
                                B2F34FE90E82F82700F627CD /* DNSCFNet.cpp in Sources */,
                                BCEF869F0E844E9D00A85CD5 /* ScrollbarThemeMac.mm in Sources */,
                                089582550E857A7E00F82C83 /* ImageLoader.cpp in Sources */,
-                               084174F30E85CED800AFB1C5 /* JSEventTargetSVGElementInstance.cpp in Sources */,
                                08A48A6E0E86CF6D00E225DD /* JSSVGElementInstanceCustom.cpp in Sources */,
-                               08A48A790E86CF8C00E225DD /* EventTargetSVGElementInstance.cpp in Sources */,
                                9350E70D0E87500B00189FFF /* JSHTMLAllCollection.cpp in Sources */,
                                BCC438780E886CC700533DD5 /* JSHTMLInputElementCustom.cpp in Sources */,
                                BC2441C40E8B65D00055320F /* ScrollView.cpp in Sources */,
index a6ee2d7..f950922 100644 (file)
@@ -97,6 +97,8 @@ namespace WebCore {
 #endif
         };
 
+        virtual bool wasCreatedFromMarkup() const { return true; }
+
         static PassRefPtr<JSLazyEventListener> create(LazyEventListenerType type, const String& functionName, const String& code, JSDOMWindow* window, Node* node, int lineNumber)
         {
             return adoptRef(new JSLazyEventListener(type, functionName, code, window, node, lineNumber));
index a8f9bb9..185756d 100644 (file)
@@ -33,8 +33,8 @@
 #include "JSXMLHttpRequestUpload.h"
 
 #if ENABLE(SVG)
-#include "EventTargetSVGElementInstance.h"
-#include "JSEventTargetSVGElementInstance.h"
+#include "SVGElementInstance.h"
+#include "JSSVGElementInstance.h"
 #endif
 
 using namespace JSC;
diff --git a/WebCore/bindings/js/JSEventTargetSVGElementInstance.cpp b/WebCore/bindings/js/JSEventTargetSVGElementInstance.cpp
deleted file mode 100644 (file)
index 456666c..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(SVG)
-#include "JSEventTargetSVGElementInstance.h"
-
-#include "Document.h"
-#include "EventNames.h"
-#include "JSDOMWindow.h"
-#include "JSEventListener.h"
-
-using namespace JSC;
-
-using namespace WebCore::EventNames;
-
-ASSERT_CLASS_FITS_IN_CELL(WebCore::JSEventTargetSVGElementInstance)
-
-static JSValue* jsEventTargetAddEventListener(ExecState*, JSObject*, JSValue*, const ArgList&);
-static JSValue* jsEventTargetRemoveEventListener(ExecState*, JSObject*, JSValue*, const ArgList&);
-static JSValue* jsEventTargetDispatchEvent(ExecState*, JSObject*, JSValue*, const ArgList&);
-
-static JSValue* jsEventTargetSVGElementInstanceOnAbort(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnAbort(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnBlur(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnBlur(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnChange(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnChange(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnClick(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnClick(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnContextMenu(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnContextMenu(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnDblClick(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnDblClick(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnBeforeCut(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnBeforeCut(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnCut(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnCut(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnBeforeCopy(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnBeforeCopy(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnCopy(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnCopy(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnBeforePaste(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnBeforePaste(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnPaste(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnPaste(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnDrag(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnDrag(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnDragEnd(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnDragEnd(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnDragEnter(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnDragEnter(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnDragLeave(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnDragLeave(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnDragOver(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnDragOver(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnDragStart(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnDragStart(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnDrop(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnDrop(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnError(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnError(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnFocus(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnFocus(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnInput(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnInput(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnKeyDown(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnKeyDown(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnKeyPress(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnKeyPress(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnKeyUp(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnKeyUp(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnLoad(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnLoad(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnMouseDown(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnMouseDown(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnMouseMove(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnMouseMove(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnMouseOut(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnMouseOut(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnMouseOver(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnMouseOver(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnMouseUp(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnMouseUp(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnMouseWheel(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnMouseWheel(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnReset(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnReset(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnResize(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnResize(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnScroll(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnScroll(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnSearch(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnSearch(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnSelect(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnSelect(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnSelectStart(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnSelectStart(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnSubmit(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnSubmit(ExecState*, JSObject*, JSValue*);
-static JSValue* jsEventTargetSVGElementInstanceOnUnload(ExecState*, const Identifier&, const PropertySlot&);
-static void setJSEventTargetSVGElementInstanceOnUnload(ExecState*, JSObject*, JSValue*);
-
-/* Source for JSEventTargetSVGElementInstanceTable
-@begin JSEventTargetSVGElementInstanceTable
-onabort       jsEventTargetSVGElementInstanceOnAbort        DontDelete|DontEnum
-onblur        jsEventTargetSVGElementInstanceOnBlur         DontDelete|DontEnum
-onchange      jsEventTargetSVGElementInstanceOnChange       DontDelete|DontEnum
-onclick       jsEventTargetSVGElementInstanceOnClick        DontDelete|DontEnum
-oncontextmenu jsEventTargetSVGElementInstanceOnContextMenu  DontDelete|DontEnum
-ondblclick    jsEventTargetSVGElementInstanceOnDblClick     DontDelete|DontEnum
-onbeforecut   jsEventTargetSVGElementInstanceOnBeforeCut    DontDelete|DontEnum
-oncut         jsEventTargetSVGElementInstanceOnCut          DontDelete|DontEnum
-onbeforecopy  jsEventTargetSVGElementInstanceOnBeforeCopy   DontDelete|DontEnum
-oncopy        jsEventTargetSVGElementInstanceOnCopy         DontDelete|DontEnum
-onbeforepaste jsEventTargetSVGElementInstanceOnBeforePaste  DontDelete|DontEnum
-onpaste       jsEventTargetSVGElementInstanceOnPaste        DontDelete|DontEnum
-ondrag        jsEventTargetSVGElementInstanceOnDrag         DontDelete|DontEnum
-ondragend     jsEventTargetSVGElementInstanceOnDragEnd      DontDelete|DontEnum
-ondragenter   jsEventTargetSVGElementInstanceOnDragEnter    DontDelete|DontEnum
-ondragleave   jsEventTargetSVGElementInstanceOnDragLeave    DontDelete|DontEnum
-ondragover    jsEventTargetSVGElementInstanceOnDragOver     DontDelete|DontEnum
-ondragstart   jsEventTargetSVGElementInstanceOnDragStart    DontDelete|DontEnum
-ondrop        jsEventTargetSVGElementInstanceOnDrop         DontDelete|DontEnum
-onerror       jsEventTargetSVGElementInstanceOnError        DontDelete|DontEnum
-onfocus       jsEventTargetSVGElementInstanceOnFocus        DontDelete|DontEnum
-oninput       jsEventTargetSVGElementInstanceOnInput        DontDelete|DontEnum
-onkeydown     jsEventTargetSVGElementInstanceOnKeyDown      DontDelete|DontEnum
-onkeypress    jsEventTargetSVGElementInstanceOnKeyPress     DontDelete|DontEnum
-onkeyup       jsEventTargetSVGElementInstanceOnKeyUp        DontDelete|DontEnum
-onload        jsEventTargetSVGElementInstanceOnLoad         DontDelete|DontEnum
-onmousedown   jsEventTargetSVGElementInstanceOnMouseDown    DontDelete|DontEnum
-onmousemove   jsEventTargetSVGElementInstanceOnMouseMove    DontDelete|DontEnum
-onmouseout    jsEventTargetSVGElementInstanceOnMouseOut     DontDelete|DontEnum
-onmouseover   jsEventTargetSVGElementInstanceOnMouseOver    DontDelete|DontEnum
-onmouseup     jsEventTargetSVGElementInstanceOnMouseUp      DontDelete|DontEnum
-onmousewheel  jsEventTargetSVGElementInstanceOnMouseWheel   DontDelete|DontEnum
-onreset       jsEventTargetSVGElementInstanceOnReset        DontDelete|DontEnum
-onresize      jsEventTargetSVGElementInstanceOnResize       DontDelete|DontEnum
-onscroll      jsEventTargetSVGElementInstanceOnScroll       DontDelete|DontEnum
-onsearch      jsEventTargetSVGElementInstanceOnSearch       DontDelete|DontEnum
-onselect      jsEventTargetSVGElementInstanceOnSelect       DontDelete|DontEnum
-onselectstart jsEventTargetSVGElementInstanceOnSelectStart  DontDelete|DontEnum
-onsubmit      jsEventTargetSVGElementInstanceOnSubmit       DontDelete|DontEnum
-onunload      jsEventTargetSVGElementInstanceOnUnload       DontDelete|DontEnum
-@end
-*/
-
-/*
-@begin JSEventTargetSVGElementInstancePrototypeTable
-addEventListener    jsEventTargetAddEventListener       DontDelete|Function 3
-removeEventListener jsEventTargetRemoveEventListener    DontDelete|Function 3
-dispatchEvent       jsEventTargetDispatchEvent          DontDelete|Function 1
-@end
-*/
-
-using namespace WebCore;
-
-DECLARE_JS_EVENT_LISTENERS(EventTargetSVGElementInstance)
-
-#include "JSEventTargetSVGElementInstance.lut.h"
-
-namespace WebCore {
-
-const ClassInfo JSEventTargetSVGElementInstancePrototype::s_info = { "EventTargetSVGElementInstancePrototype", 0, &JSEventTargetSVGElementInstancePrototypeTable, 0 };
-
-JSObject* JSEventTargetSVGElementInstancePrototype::self(ExecState* exec)
-{
-    return getDOMPrototype<JSEventTargetSVGElementInstance>(exec);
-}
-
-bool JSEventTargetSVGElementInstancePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
-    return getStaticFunctionSlot<JSObject>(exec, &JSEventTargetSVGElementInstancePrototypeTable, this, propertyName, slot);
-}
-
-const ClassInfo JSEventTargetSVGElementInstance::s_info = { "EventTargetSVGElementInstance", &JSSVGElementInstance::s_info, &JSEventTargetSVGElementInstanceTable, 0 };
-
-JSEventTargetSVGElementInstance::JSEventTargetSVGElementInstance(PassRefPtr<StructureID> structure, PassRefPtr<EventTargetSVGElementInstance> node)
-    : JSSVGElementInstance(structure, node)
-{
-}
-
-bool JSEventTargetSVGElementInstance::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
-    return getStaticValueSlot<JSEventTargetSVGElementInstance, JSSVGElementInstance>(exec, &JSEventTargetSVGElementInstanceTable, this, propertyName, slot);
-}
-
-void JSEventTargetSVGElementInstance::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)
-{
-    lookupPut<JSEventTargetSVGElementInstance, JSSVGElementInstance>(exec, propertyName, value, &JSEventTargetSVGElementInstanceTable, this, slot);
-}
-
-JSObject* JSEventTargetSVGElementInstance::createPrototype(ExecState* exec)
-{
-    return new (exec) JSEventTargetSVGElementInstancePrototype(JSEventTargetSVGElementInstancePrototype::createStructureID(JSSVGElementInstancePrototype::self(exec)));
-}
-
-void JSEventTargetSVGElementInstance::setListener(ExecState* exec, const AtomicString& eventType, JSValue* func) const
-{
-    SVGElement* element = impl()->correspondingElement();
-    if (Frame* frame = element->document()->frame())
-        element->setEventListenerForType(eventType, toJSDOMWindow(frame)->findOrCreateJSEventListener(exec, func, true));
-}
-
-JSValue* JSEventTargetSVGElementInstance::getListener(const AtomicString& eventType) const
-{
-    SVGElement* element = impl()->correspondingElement();
-    EventListener* listener = element->eventListenerForType(eventType);
-
-    JSEventListener* jsListener = static_cast<JSEventListener*>(listener);
-    if (jsListener && jsListener->listenerObj())
-        return jsListener->listenerObj();
-
-    return jsNull();
-}
-
-EventTargetSVGElementInstance* toEventTargetSVGElementInstance(JSValue* val)
-{
-    if (!val || !val->isObject(&JSSVGElementInstance::s_info))
-        return 0;
-
-    return static_cast<EventTargetSVGElementInstance*>(static_cast<JSEventTargetSVGElementInstance*>(val)->impl());
-}
-
-} // namespace WebCore
-
-using namespace WebCore;
-
-JSValue* jsEventTargetAddEventListener(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
-{
-    if (!thisValue->isObject(&JSSVGElementInstance::s_info))
-        return throwError(exec, TypeError);
-
-    JSEventTargetSVGElementInstance* jsElementInstance = static_cast<JSEventTargetSVGElementInstance*>(thisValue);
-    EventTargetSVGElementInstance* elementInstance = static_cast<EventTargetSVGElementInstance*>(jsElementInstance->impl());
-    WebCore::Node* eventNode = elementInstance->correspondingElement();
-
-    Frame* frame = eventNode->document()->frame();
-    if (!frame)
-        return jsUndefined();
-
-    if (RefPtr<JSEventListener> listener = toJSDOMWindow(frame)->findOrCreateJSEventListener(exec, args.at(exec, 1)))
-        elementInstance->addEventListener(args.at(exec, 0)->toString(exec), listener.release(), args.at(exec, 2)->toBoolean(exec));
-
-    return jsUndefined();
-}
-
-JSValue* jsEventTargetRemoveEventListener(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
-{
-    if (!thisValue->isObject(&JSSVGElementInstance::s_info))
-        return throwError(exec, TypeError);
-
-    JSEventTargetSVGElementInstance* jsElementInstance = static_cast<JSEventTargetSVGElementInstance*>(thisValue);
-    EventTargetSVGElementInstance* elementInstance = static_cast<EventTargetSVGElementInstance*>(jsElementInstance->impl());
-    WebCore::Node* eventNode = elementInstance->correspondingElement();
-
-    Frame* frame = eventNode->document()->frame();
-    if (!frame)
-        return jsUndefined();
-
-    if (JSEventListener* listener = toJSDOMWindow(frame)->findJSEventListener(args.at(exec, 1)))
-        elementInstance->removeEventListener(args.at(exec, 0)->toString(exec), listener, args.at(exec, 2)->toBoolean(exec));
-
-    return jsUndefined();
-}
-
-JSValue* jsEventTargetDispatchEvent(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
-{
-    if (!thisValue->isObject(&JSSVGElementInstance::s_info))
-        return throwError(exec, TypeError);
-
-    JSEventTargetSVGElementInstance* jsElementInstance = static_cast<JSEventTargetSVGElementInstance*>(thisValue);
-    EventTargetSVGElementInstance* elementInstance = static_cast<EventTargetSVGElementInstance*>(jsElementInstance->impl());
-
-    ExceptionCode ec = 0;
-    JSValue* result = jsBoolean(elementInstance->dispatchEvent(toEvent(args.at(exec, 0)), ec));
-    setDOMException(exec, ec);
-    return result;
-}
-
-#endif // ENABLE(SVG)
diff --git a/WebCore/bindings/js/JSEventTargetSVGElementInstance.h b/WebCore/bindings/js/JSEventTargetSVGElementInstance.h
deleted file mode 100644 (file)
index 5676dc4..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#ifndef JSEventTargetSVGElementInstance_h
-#define JSEventTargetSVGElementInstance_h
-
-#if ENABLE(SVG)
-#include "JSEventTargetBase.h"
-#include "JSSVGElementInstance.h"
-#include <wtf/AlwaysInline.h>
-
-namespace WebCore {
-
-    class EventTargetSVGElementInstance;
-    class SVGElementInstance;
-
-    class JSEventTargetSVGElementInstance : public JSSVGElementInstance {
-    public:
-        JSEventTargetSVGElementInstance(PassRefPtr<JSC::StructureID>, PassRefPtr<EventTargetSVGElementInstance>);
-
-        static JSC::JSObject* createPrototype(JSC::ExecState*);
-
-        void setListener(JSC::ExecState*, const AtomicString& eventType, JSC::JSValue* func) const;
-        JSC::JSValue* getListener(const AtomicString& eventType) const;
-
-        virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);
-        virtual void put(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue*, JSC::PutPropertySlot&);
-
-        virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
-        static const JSC::ClassInfo s_info;
-    };
-
-    class JSEventTargetSVGElementInstancePrototype : public JSC::JSObject {
-    public:
-        JSEventTargetSVGElementInstancePrototype(PassRefPtr<JSC::StructureID> structure)
-            : JSC::JSObject(structure)
-        {
-        }
-
-        static JSC::JSObject* self(JSC::ExecState*);
-        virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);
-
-        virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
-        static const JSC::ClassInfo s_info;
-    };
-
-    EventTargetSVGElementInstance* toEventTargetSVGElementInstance(JSC::JSValue*);
-
-} // namespace WebCore
-
-#endif // ENABLE(SVG)
-#endif // JSEventTargetSVGElementInstance_h
index 5a558c9..278236f 100644 (file)
 #include "config.h"
 
 #if ENABLE(SVG)
-#include "EventTargetSVGElementInstance.h"
-#include "JSEventTargetSVGElementInstance.h"
+#include "SVGElementInstance.h"
+#include "JSSVGElementInstance.h"
+
+#include "JSEventListener.h"
+#include "JSDOMWindow.h"
 
 using namespace JSC;
 
 namespace WebCore {
 
-JSValue* toJS(ExecState* exec, SVGElementInstance* object)
+JSValue* JSSVGElementInstance::addEventListener(ExecState* exec, const ArgList& args)
+{
+    Frame* frame = impl()->associatedFrame();
+    if (!frame)
+        return jsUndefined();
+
+    if (RefPtr<JSEventListener> listener = toJSDOMWindow(frame)->findOrCreateJSEventListener(exec, args.at(exec, 1)))
+        impl()->addEventListener(args.at(exec, 0)->toString(exec), listener.release(), args.at(exec, 2)->toBoolean(exec));
+
+    return jsUndefined();
+}
+
+JSValue* JSSVGElementInstance::removeEventListener(ExecState* exec, const ArgList& args)
 {
-    if (!object)
-        return jsNull();
+    Frame* frame = impl()->associatedFrame();
+    if (!frame)
+        return jsUndefined();
+
+    if (JSEventListener* listener = toJSDOMWindow(frame)->findJSEventListener(args.at(exec, 1)))
+        impl()->removeEventListener(args.at(exec, 0)->toString(exec), listener, args.at(exec, 2)->toBoolean(exec));
 
-    return getDOMObjectWrapper<JSSVGElementInstance>(exec, object);
+    return jsUndefined();
+}
+
+void JSSVGElementInstance::pushEventHandlerScope(ExecState*, ScopeChain&) const
+{
 }
 
 }
index 99a55b6..98e5495 100644 (file)
@@ -145,7 +145,7 @@ sub UsesManualToJSImplementation
 {
     my $type = shift;
 
-    return 1 if $type eq "Node" or $type eq "Document" or $type eq "HTMLCollection" or $type eq "SVGPathSeg" or $type eq "StyleSheet" or $type eq "CSSRule" or $type eq "CSSValue" or $type eq "Event" or $type eq "ImageData" or $type eq "Element" or $type eq "Text" or $type eq "SVGElementInstance";
+    return 1 if $type eq "Node" or $type eq "Document" or $type eq "HTMLCollection" or $type eq "SVGPathSeg" or $type eq "StyleSheet" or $type eq "CSSRule" or $type eq "CSSValue" or $type eq "Event" or $type eq "ImageData" or $type eq "Element" or $type eq "Text";
     return 0;
 }
 
@@ -365,8 +365,6 @@ sub GenerateHeader
     }
     if ($interfaceName eq "Node") {
         push(@headerContentHeader, "#include \"EventTargetNode.h\"\n");
-    } elsif ($interfaceName eq "SVGElementInstance") {
-        push(@headerContentHeader, "#include \"EventTargetSVGElementInstance.h\"\n");
     }
 
     if ($dataNode->extendedAttributes->{"CustomCall"}) {
@@ -611,8 +609,6 @@ sub GenerateHeader
         # Resolve ambiguity with EventTarget that otherwise exists.
         if ($interfaceName eq "Node") {
             push(@headerContent, "inline JSC::JSValue* toJS(JSC::ExecState* exec, EventTargetNode* node) { return toJS(exec, static_cast<Node*>(node)); }\n");
-        } elsif ($interfaceName eq "SVGElementInstance") {
-            push(@headerContent, "inline JSC::JSValue* toJS(JSC::ExecState* exec, EventTargetSVGElementInstance* instance) { return toJS(exec, static_cast<SVGElementInstance*>(instance)); }\n");
         }
     }
     if (!$hasParent || $dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
@@ -1629,10 +1625,7 @@ sub NativeToJSValue
         $implIncludes{"NameNodeList.h"} = 1;
     }
 
-    if ($type eq "SVGElementInstance") {
-        $implIncludes{"EventTargetSVGElementInstance.h"} = 1;
-        $implIncludes{"JSEventTargetSVGElementInstance.h"} = 1;
-    } elsif ($type eq "DOMObject") {
+    if ($type eq "DOMObject") {
         $implIncludes{"JSCanvasRenderingContext2D.h"} = 1;
     } elsif ($type =~ /SVGPathSeg/) {
         $implIncludes{"JS$type.h"} = 1;
index df06677..2b828b0 100644 (file)
@@ -657,7 +657,6 @@ sub AddIncludesForType
 
     $implIncludes{"ObjCEventListener.h"} = 1 if $type eq "EventListener";
     $implIncludes{"ObjCNodeFilterCondition.h"} = 1 if $type eq "NodeFilter";
-    $implIncludes{"EventTargetSVGElementInstance.h"} = 1 if $type eq "SVGElementInstance";
     $implIncludes{"DOMCustomXPathNSResolver.h"} = 1 if $type eq "XPathNSResolver";
 
     # FIXME: won't compile without these
@@ -1372,14 +1371,12 @@ sub GenerateImplementation
 
             if ($function->signature->extendedAttributes->{"EventTargetNodeCast"}) {
                 if ($dataNode->name =~ /^SVG/) {
-                    push(@functionContent, "    if (!$caller->isEventTargetSVGElementInstance())\n");
-                    $caller = "WebCore::EventTargetSVGElementInstanceCast($caller)";
+                    $caller = "static_cast<WebCore::SVGElementInstance*>($caller)";
                 } else {
                     push(@functionContent, "    if (!$caller->isEventTargetNode())\n");
                     $caller = "WebCore::EventTargetNodeCast($caller)";
+                    push(@functionContent, "        WebCore::raiseDOMException(DOM_NOT_SUPPORTED_ERR);\n");
                 }
-
-                push(@functionContent, "        WebCore::raiseDOMException(DOM_NOT_SUPPORTED_ERR);\n");
             }
 
             # special case the EventListener
index 350f095..22a683a 100644 (file)
@@ -32,6 +32,7 @@ namespace WebCore {
         virtual ~EventListener() { }
         virtual void handleEvent(Event*, bool isWindowEvent = false) = 0;
         virtual bool isAttachedToEventTargetNode() const { return false; }
+        virtual bool wasCreatedFromMarkup() const { return false; }
     };
 
 }
index 023423e..05ae1ce 100644 (file)
 #include "StorageEvent.h"
 #endif
 
+#if ENABLE(SVG)
+#include "SVGElementInstance.h"
+#include "SVGUseElement.h"
+#endif
+
 namespace WebCore {
 
 using namespace EventNames;
@@ -109,6 +114,30 @@ void EventTargetNode::didMoveToNewOwnerDocument()
     Node::didMoveToNewOwnerDocument();
 }
 
+static inline void updateSVGElementInstancesAfterEventListenerChange(EventTargetNode* referenceNode)
+{
+    ASSERT(referenceNode);
+
+#if ENABLE(SVG)
+    if (!referenceNode->isSVGElement())
+        return;
+
+    // Elements living inside a <use> shadow tree, never cause any updates!
+    if (referenceNode->shadowTreeRootNode())
+        return;
+
+    // We're possibly (a child of) an element that is referenced by a <use> client
+    // If an event listeners changes on a referenced element, update all instances.
+    for (Node* node = referenceNode; node; node = node->parentNode()) {
+        if (!node->hasID() || !node->isSVGElement())
+            continue;
+
+        SVGElementInstance::invalidateAllInstancesOfElement(static_cast<SVGElement*>(node));
+        break;
+    }
+#endif
+}
+
 void EventTargetNode::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
 {
     Document* doc = document();
@@ -129,6 +158,7 @@ void EventTargetNode::addEventListener(const AtomicString& eventType, PassRefPtr
         doc->registerDisconnectedNodeWithEventListeners(this);
 
     m_regdListeners->append(RegisteredEventListener::create(eventType, listener, useCapture));
+    updateSVGElementInstancesAfterEventListenerChange(this);
 }
 
 void EventTargetNode::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
@@ -147,6 +177,7 @@ void EventTargetNode::removeEventListener(const AtomicString& eventType, EventLi
             if (m_regdListeners->isEmpty() && !inDocument())
                 document()->unregisterDisconnectedNodeWithEventListeners(this);
 
+            updateSVGElementInstancesAfterEventListenerChange(this);
             return;
         }
     }
@@ -175,12 +206,41 @@ void EventTargetNode::handleLocalEvents(Event *evt, bool useCapture)
     }
 }
 
-static inline EventTargetNode* setCurrentEventTargetRespectingSVGTargetRules(EventTargetNode* referenceNode, Event* event)
+#if ENABLE(SVG)
+static inline SVGElementInstance* eventTargetAsSVGElementInstance(EventTargetNode* referenceNode)
+{
+    ASSERT(referenceNode);
+    if (!referenceNode->isSVGElement())
+        return 0;
+
+    // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
+    // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects
+    for (Node* n = referenceNode; n; n = n->parentNode()) {
+        if (!n->isShadowNode() || !n->isSVGElement())
+            continue;
+
+        Node* shadowTreeParentElement = n->shadowParentNode();
+        ASSERT(shadowTreeParentElement->hasTagName(SVGNames::useTag));
+
+        if (SVGElementInstance* instance = static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode))
+            return instance;
+    }
+
+    return 0;
+}
+#endif
+
+static inline EventTarget* eventTargetRespectingSVGTargetRules(EventTargetNode* referenceNode)
 {
     ASSERT(referenceNode);
 
-    // TODO: SVG will add logic here soon.
-    event->setCurrentTarget(referenceNode);
+#if ENABLE(SVG)
+    if (SVGElementInstance* instance = eventTargetAsSVGElementInstance(referenceNode)) {
+        ASSERT(instance->shadowTreeElement() == referenceNode);
+        return instance;
+    }
+#endif
+
     return referenceNode;
 }
 
@@ -193,10 +253,7 @@ bool EventTargetNode::dispatchEvent(PassRefPtr<Event> e, ExceptionCode& ec, bool
         return false;
     }
 
-    EventTarget* target = this;
-
-    // TODO: SVG will add logic here soon.
-    evt->setTarget(target);
+    evt->setTarget(eventTargetRespectingSVGTargetRules(this));
 
     RefPtr<FrameView> view = document()->view();
     return dispatchGenericEvent(evt.release(), ec, tempEvent);
@@ -214,7 +271,13 @@ bool EventTargetNode::dispatchGenericEvent(PassRefPtr<Event> e, ExceptionCode& e
     DeprecatedPtrList<Node> nodeChain;
 
     if (inDocument()) {
-        for (Node* n = this; n; n = n->eventParentNode()) {
+            for (Node* n = this; n; n = n->eventParentNode()) {
+#if ENABLE(SVG)
+            // Skip <use> shadow tree elements    
+            if (n->isSVGElement() && n->isShadowNode())
+                continue;
+#endif
+
             n->ref();
             nodeChain.prepend(n);
         }
@@ -241,7 +304,9 @@ bool EventTargetNode::dispatchGenericEvent(PassRefPtr<Event> e, ExceptionCode& e
 
     EventTargetNode* eventTargetNode = 0;
     for (; it.current() && it.current() != this && !evt->propagationStopped(); ++it) {
-        eventTargetNode = setCurrentEventTargetRespectingSVGTargetRules(EventTargetNodeCast(it.current()), evt.get());
+        eventTargetNode = EventTargetNodeCast(it.current());
+        evt->setCurrentTarget(eventTargetRespectingSVGTargetRules(eventTargetNode));
+
         eventTargetNode->handleLocalEvents(evt.get(), true);
     }
 
@@ -250,7 +315,9 @@ bool EventTargetNode::dispatchGenericEvent(PassRefPtr<Event> e, ExceptionCode& e
 
     if (!evt->propagationStopped()) {
         evt->setEventPhase(Event::AT_TARGET);
-        eventTargetNode = setCurrentEventTargetRespectingSVGTargetRules(EventTargetNodeCast(it.current()), evt.get());
+
+        eventTargetNode = EventTargetNodeCast(it.current());
+        evt->setCurrentTarget(eventTargetRespectingSVGTargetRules(eventTargetNode));
 
         // We do want capturing event listeners to be invoked here, even though
         // that violates the specification since Mozilla does it.
@@ -277,7 +344,9 @@ bool EventTargetNode::dispatchGenericEvent(PassRefPtr<Event> e, ExceptionCode& e
         evt->setEventPhase(Event::BUBBLING_PHASE);
 
         for (; it.current() && !evt->propagationStopped() && !evt->cancelBubble(); --it) {
-            eventTargetNode = setCurrentEventTargetRespectingSVGTargetRules(EventTargetNodeCast(it.current()), evt.get());
+            eventTargetNode = EventTargetNodeCast(it.current());
+            evt->setCurrentTarget(eventTargetRespectingSVGTargetRules(eventTargetNode));
+
             eventTargetNode->handleLocalEvents(evt.get(), false);
         }
 
@@ -620,15 +689,17 @@ void EventTargetNode::removeEventListenerForType(const AtomicString& eventType)
     
     RegisteredEventListenerList::Iterator end = m_regdListeners->end();
     for (RegisteredEventListenerList::Iterator it = m_regdListeners->begin(); it != end; ++it) {
-        if ((*it)->eventType() != eventType || !(*it)->listener()->isAttachedToEventTargetNode())
+        EventListener* listener = (*it)->listener();
+        if ((*it)->eventType() != eventType || !listener->isAttachedToEventTargetNode())
             continue;
-        
+
         it = m_regdListeners->remove(it);
 
         // removed last
         if (m_regdListeners->isEmpty() && !inDocument())
             document()->unregisterDisconnectedNodeWithEventListeners(this);
 
+        updateSVGElementInstancesAfterEventListenerChange(this);
         return;
     }
 }
index 25b3840..52b6970 100644 (file)
@@ -66,7 +66,9 @@
 
 #if ENABLE(SVG)
 #include "SVGDocument.h"
+#include "SVGElementInstance.h"
 #include "SVGNames.h"
+#include "SVGUseElement.h"
 #endif
 
 namespace WebCore {
@@ -159,6 +161,10 @@ void EventHandler::clear()
     m_resizeLayer = 0;
     m_nodeUnderMouse = 0;
     m_lastNodeUnderMouse = 0;
+#if ENABLE(SVG)
+    m_instanceUnderMouse = 0;
+    m_lastInstanceUnderMouse = 0;
+#endif
     m_lastMouseMoveEventSubframe = 0;
     m_lastScrollbarUnderMouse = 0;
     m_clickCount = 0;
@@ -1398,11 +1404,6 @@ void EventHandler::clearDragState()
 #endif
 }
 
-Node* EventHandler::nodeUnderMouse() const
-{
-    return m_nodeUnderMouse.get();
-}
-
 void EventHandler::setCapturingMouseEventsNode(PassRefPtr<Node> n)
 {
     m_capturingMouseEventsNode = n;
@@ -1417,6 +1418,25 @@ MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestReques
     return m_frame->document()->prepareMouseEvent(request, documentPoint, mev);
 }
 
+#if ENABLE(SVG)
+static inline SVGElementInstance* instanceAssociatedWithShadowTreeElement(Node* referenceNode)
+{
+    if (!referenceNode || !referenceNode->isSVGElement())
+        return 0;
+
+    Node* shadowTreeElement = referenceNode->shadowTreeRootNode();
+    if (!shadowTreeElement)
+        return 0;
+
+    Node* shadowTreeParentElement = shadowTreeElement->shadowParentNode();
+    if (!shadowTreeParentElement)
+        return 0;
+
+    ASSERT(shadowTreeParentElement->hasTagName(useTag));
+    return static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode);
+}
+#endif
+
 void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMouseEvent& mouseEvent, bool fireMouseOverOut)
 {
     Node* result = targetNode;
@@ -1432,12 +1452,49 @@ void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo
             result = result->shadowAncestorNode();
     }
     m_nodeUnderMouse = result;
-    
+#if ENABLE(SVG)
+    m_instanceUnderMouse = instanceAssociatedWithShadowTreeElement(result);
+
+    // <use> shadow tree elements may have been recloned, update node under mouse in any case
+    if (m_lastInstanceUnderMouse) {
+        SVGElement* lastCorrespondingElement = m_lastInstanceUnderMouse->correspondingElement();
+        SVGElement* lastCorrespondingUseElement = m_lastInstanceUnderMouse->correspondingUseElement();
+
+        if (lastCorrespondingElement && lastCorrespondingUseElement) {
+            HashSet<SVGElementInstance*> instances = lastCorrespondingElement->instancesForElement();
+
+            // Locate the recloned shadow tree element for our corresponding instance
+            HashSet<SVGElementInstance*>::iterator end = instances.end();
+            for (HashSet<SVGElementInstance*>::iterator it = instances.begin(); it != end; ++it) {
+                SVGElementInstance* instance = (*it);
+                ASSERT(instance->correspondingElement() == lastCorrespondingElement);
+
+                if (instance == m_lastInstanceUnderMouse)
+                    continue;
+
+                if (instance->correspondingUseElement() != lastCorrespondingUseElement)
+                    continue;
+
+                SVGElement* shadowTreeElement = instance->shadowTreeElement();
+                if (!shadowTreeElement->inDocument() || m_lastNodeUnderMouse == shadowTreeElement)
+                    continue;
+
+                m_lastNodeUnderMouse = shadowTreeElement;
+                m_lastInstanceUnderMouse = instance;
+                break;
+            }
+        }
+    }
+#endif
+
     // Fire mouseout/mouseover if the mouse has shifted to a different node.
     if (fireMouseOverOut) {
         if (m_lastNodeUnderMouse && m_lastNodeUnderMouse->document() != m_frame->document()) {
             m_lastNodeUnderMouse = 0;
             m_lastScrollbarUnderMouse = 0;
+#if ENABLE(SVG)
+            m_lastInstanceUnderMouse = 0;
+#endif
         }
 
         if (m_lastNodeUnderMouse != m_nodeUnderMouse) {
@@ -1449,6 +1506,9 @@ void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo
                 EventTargetNodeCast(m_nodeUnderMouse.get())->dispatchMouseEvent(mouseEvent, mouseoverEvent, 0, m_lastNodeUnderMouse.get());
         }
         m_lastNodeUnderMouse = m_nodeUnderMouse;
+#if ENABLE(SVG)
+        m_lastInstanceUnderMouse = instanceAssociatedWithShadowTreeElement(m_nodeUnderMouse.get());
+#endif
     }
 }
 
index 79746a0..865829c 100644 (file)
@@ -66,6 +66,7 @@ class RenderObject;
 class RenderWidget;
 class Scrollbar;
 class String;
+class SVGElementInstance;
 class TextEvent;
 class VisiblePosition;
 class Widget;
@@ -307,6 +308,8 @@ private:
     bool m_mouseDownWasInSubframe;
 #if ENABLE(SVG)
     bool m_svgPan;
+    RefPtr<SVGElementInstance> m_instanceUnderMouse;
+    RefPtr<SVGElementInstance> m_lastInstanceUnderMouse;
 #endif
 
     RenderLayer* m_resizeLayer;
diff --git a/WebCore/svg/EventTargetSVGElementInstance.cpp b/WebCore/svg/EventTargetSVGElementInstance.cpp
deleted file mode 100644 (file)
index ab0fb68..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-
-#if ENABLE(SVG)
-#include "EventTargetSVGElementInstance.h"
-
-#include "Document.h"
-#include "Event.h"
-#include "EventListener.h"
-#include "EventException.h"
-#include "FrameView.h"
-
-namespace WebCore {
-
-EventTargetSVGElementInstance::EventTargetSVGElementInstance(SVGUseElement* useElement, SVGElement* originalElement)
-    : SVGElementInstance(useElement, originalElement)
-{
-}
-
-EventTargetSVGElementInstance::~EventTargetSVGElementInstance()
-{
-}
-
-Frame* EventTargetSVGElementInstance::associatedFrame() const
-{
-    if (SVGElement* element = correspondingElement())
-        return element->associatedFrame();
-    return 0;
-}
-
-void EventTargetSVGElementInstance::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
-{
-    if (SVGElement* element = correspondingElement())
-        element->addEventListener(eventType, listener, useCapture);
-}
-
-void EventTargetSVGElementInstance::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
-{
-    if (SVGElement* element = correspondingElement())
-        element->removeEventListener(eventType, listener, useCapture);
-}
-
-bool EventTargetSVGElementInstance::dispatchEvent(PassRefPtr<Event> e, ExceptionCode& ec, bool tempEvent)
-{
-    RefPtr<Event> evt(e);
-    ASSERT(!eventDispatchForbidden());
-    if (!evt || evt->type().isEmpty()) {
-        ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
-        return false;
-    }
-
-    // The event has to be dispatched to the shadowTreeElement(), not the correspondingElement()!
-    SVGElement* element = shadowTreeElement();
-    if (!element)
-        return false;
-
-    evt->setTarget(this);
-
-    RefPtr<FrameView> view = element->document()->view();
-    return element->dispatchGenericEvent(evt.release(), ec, tempEvent);
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(SVG)
diff --git a/WebCore/svg/EventTargetSVGElementInstance.h b/WebCore/svg/EventTargetSVGElementInstance.h
deleted file mode 100644 (file)
index 577ba56..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef EventTargetSVGElementInstance_h
-#define EventTargetSVGElementInstance_h
-
-#if ENABLE(SVG)
-#include "EventTarget.h"
-#include "SVGElement.h"
-#include "SVGElementInstance.h"
-
-namespace WebCore {
-
-class EventTargetSVGElementInstance : public SVGElementInstance,
-                                      public EventTarget {
-public:
-    EventTargetSVGElementInstance(SVGUseElement*, SVGElement* originalElement);
-    virtual ~EventTargetSVGElementInstance();
-
-    virtual bool isEventTargetSVGElementInstance() const { return true; }
-
-    virtual Frame* associatedFrame() const;
-
-    virtual EventTargetNode* toNode() { return shadowTreeElement(); }
-    virtual EventTargetSVGElementInstance* toSVGElementInstance() { return this; }
-
-    virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
-    virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture);
-    virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&, bool tempEvent = false);
-
-    using SVGElementInstance::ref;
-    using SVGElementInstance::deref;
-
-private:
-    virtual void refEventTarget() { ref(); }
-    virtual void derefEventTarget() { deref(); }
-};
-
-inline EventTargetSVGElementInstance* EventTargetSVGElementInstanceCast(SVGElementInstance* e) 
-{ 
-    return static_cast<EventTargetSVGElementInstance*>(e);
-}
-
-inline const EventTargetSVGElementInstance* EventTargetSVGElementInstanceCast(const SVGElementInstance* e) 
-{ 
-    return static_cast<const EventTargetSVGElementInstance*>(e);
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(SVG)
-#endif // EventTargetSVGElementInstance_h
index fea7a40..f318303 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+    Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
 
     This file is part of the KDE project
 
 #if ENABLE(SVG)
 #include "SVGElementInstance.h"
 
+#include "ContainerNodeAlgorithms.h"
 #include "Document.h"
 #include "Event.h"
+#include "EventException.h"
 #include "EventListener.h"
+#include "EventNames.h"
+#include "FrameView.h"
+#include "GCController.h"
 #include "SVGElementInstanceList.h"
 #include "SVGUseElement.h"
 
-#include <wtf/Assertions.h>
+#include <wtf/RefCountedLeakCounter.h>
 
 namespace WebCore {
 
-SVGElementInstance::SVGElementInstance(SVGUseElement* useElement, PassRefPtr<SVGElement> originalElement)
-    : m_useElement(useElement)
+using namespace EventNames;
+
+#ifndef NDEBUG
+static WTF::RefCountedLeakCounter instanceCounter("WebCoreSVGElementInstance");
+#endif
+
+SVGElementInstance::SVGElementInstance(SVGUseElement* useElement, SVGElement* originalElement)
+    : m_needsUpdate(false)
+    , m_useElement(useElement)
     , m_element(originalElement)
-    , m_shadowTreeElement(0)
     , m_previousSibling(0)
     , m_nextSibling(0)
     , m_firstChild(0)
@@ -48,113 +59,514 @@ SVGElementInstance::SVGElementInstance(SVGUseElement* useElement, PassRefPtr<SVG
 
     // Register as instance for passed element.
     m_element->mapInstanceToElement(this);
+
+#ifndef NDEBUG
+    instanceCounter.increment();
+#endif
 }
 
 SVGElementInstance::~SVGElementInstance()
 {
-    for (RefPtr<SVGElementInstance> child = m_firstChild; child; child = child->m_nextSibling)
-        child->setParent(0);
+#ifndef NDEBUG
+    instanceCounter.decrement();
+#endif
 
     // Deregister as instance for passed element.
     m_element->removeInstanceMapping(this);
+
+    removeAllChildrenInContainer<SVGElementInstance, SVGElementInstance>(this);
 }
 
-SVGElement* SVGElementInstance::correspondingElement() const
+PassRefPtr<SVGElementInstanceList> SVGElementInstance::childNodes()
 {
-    return m_element.get();
+    return SVGElementInstanceList::create(this);
 }
 
-SVGUseElement* SVGElementInstance::correspondingUseElement() const
+void SVGElementInstance::setShadowTreeElement(SVGElement* element)
 {
-    return m_useElement;
+    ASSERT(element);
+    m_shadowTreeElement = element;
 }
 
-SVGElementInstance* SVGElementInstance::parentNode() const
+void SVGElementInstance::forgetWrapper()
 {
-    return parent();
+    // FIXME: This is fragile, as discussed with Sam. Need to find a better solution.
+    // Think about the case where JS explicitely holds "var root = useElement.instanceRoot;".
+    // We still have to recreate this wrapper somehow. The gc collection below, won't catch it.
+
+    // If the use shadow tree has been rebuilt, just the JSSVGElementInstance objects
+    // are still holding RefPtrs of SVGElementInstance objects, which prevent us to
+    // be deleted (and the shadow tree is not destructed as well). Force JS GC.
+    gcController().garbageCollectNow();    
 }
 
-PassRefPtr<SVGElementInstanceList> SVGElementInstance::childNodes()
+void SVGElementInstance::appendChild(PassRefPtr<SVGElementInstance> child)
 {
-    return SVGElementInstanceList::create(this);
+    appendChildToContainer<SVGElementInstance, SVGElementInstance>(child.get(), this);
 }
 
-SVGElementInstance* SVGElementInstance::previousSibling() const
+void SVGElementInstance::invalidateAllInstancesOfElement(SVGElement* element)
 {
-    return m_previousSibling;
+    if (!element)
+        return;
+
+    HashSet<SVGElementInstance*> set = element->instancesForElement();
+    if (set.isEmpty())
+        return;
+
+    // Find all use elements referencing the instances - ask them _once_ to rebuild.
+    HashSet<SVGElementInstance*>::const_iterator it = set.begin();
+    const HashSet<SVGElementInstance*>::const_iterator end = set.end();
+
+    for (; it != end; ++it)
+        (*it)->setNeedsUpdate(true);
 }
 
-SVGElementInstance* SVGElementInstance::nextSibling() const
+void SVGElementInstance::setNeedsUpdate(bool value)
 {
-    return m_nextSibling;
+    m_needsUpdate = value;
+
+    if (m_needsUpdate)
+        correspondingUseElement()->setChanged();
 }
 
-SVGElementInstance* SVGElementInstance::firstChild() const
+Frame* SVGElementInstance::associatedFrame() const
 {
-    return m_firstChild;
+    if (SVGElement* element = correspondingElement())
+        return element->associatedFrame();
+    return 0;
 }
 
-SVGElementInstance* SVGElementInstance::lastChild() const
+void SVGElementInstance::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
 {
-    return m_lastChild;
+    if (SVGElement* element = correspondingElement())
+        element->addEventListener(eventType, listener, useCapture);
 }
 
-SVGElement* SVGElementInstance::shadowTreeElement() const
+void SVGElementInstance::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
 {
-    return m_shadowTreeElement;
+    if (SVGElement* element = correspondingElement())
+        element->removeEventListener(eventType, listener, useCapture);
 }
 
-void SVGElementInstance::setShadowTreeElement(SVGElement* element)
+bool SVGElementInstance::dispatchEvent(PassRefPtr<Event> e, ExceptionCode& ec, bool tempEvent)
 {
-    ASSERT(element);
-    m_shadowTreeElement = element;
+    RefPtr<Event> evt(e);
+    ASSERT(!eventDispatchForbidden());
+    if (!evt || evt->type().isEmpty()) {
+        ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
+        return false;
+    }
+
+    // The event has to be dispatched to the shadowTreeElement(), not the correspondingElement()!
+    SVGElement* element = shadowTreeElement();
+    if (!element)
+        return false;
+
+    evt->setTarget(this);
+
+    RefPtr<FrameView> view = element->document()->view();
+    return element->dispatchGenericEvent(evt.release(), ec, tempEvent);
 }
 
-void SVGElementInstance::appendChild(PassRefPtr<SVGElementInstance> child)
+EventListener* SVGElementInstance::onabort() const
+{
+    return correspondingElement()->eventListenerForType(abortEvent);
+}
+
+void SVGElementInstance::setOnabort(PassRefPtr<EventListener> eventListener)
 {
-    child->setParent(this);
+    correspondingElement()->setEventListenerForType(abortEvent, eventListener);
+}
 
-    if (m_lastChild) {
-        child->m_previousSibling = m_lastChild;
-        m_lastChild->m_nextSibling = child.get();
-    } else
-        m_firstChild = child.get();
+EventListener* SVGElementInstance::onblur() const
+{
+    return correspondingElement()->eventListenerForType(blurEvent);
+}
 
-    m_lastChild = child.get();
+void SVGElementInstance::setOnblur(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(blurEvent, eventListener);
 }
 
-SVGElementInstance* SVGElementInstance::toSVGElementInstance()
+EventListener* SVGElementInstance::onchange() const
 {
-    return this;
+    return correspondingElement()->eventListenerForType(changeEvent);
 }
 
-EventTargetNode* SVGElementInstance::toNode()
+void SVGElementInstance::setOnchange(PassRefPtr<EventListener> eventListener)
 {
-    return m_element.get();
+    correspondingElement()->setEventListenerForType(changeEvent, eventListener);
 }
 
-void SVGElementInstance::updateAllInstancesOfElement(SVGElement* element)
+EventListener* SVGElementInstance::onclick() const
 {
-    if (!element)
-        return;
+    return correspondingElement()->eventListenerForType(clickEvent);
+}
 
-    HashSet<SVGElementInstance*> set = element->instancesForElement();
-    if (set.isEmpty())
-        return;
+void SVGElementInstance::setOnclick(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(clickEvent, eventListener);
+}
 
-    // Find all use elements referencing the instances - ask them _once_ to rebuild.
-    HashSet<SVGElementInstance*>::const_iterator it = set.begin();
-    const HashSet<SVGElementInstance*>::const_iterator end = set.end();
+EventListener* SVGElementInstance::oncontextmenu() const
+{
+    return correspondingElement()->eventListenerForType(contextmenuEvent);
+}
 
-    HashSet<SVGUseElement*> useHash;
-    for (; it != end; ++it)
-        useHash.add((*it)->correspondingUseElement());
+void SVGElementInstance::setOncontextmenu(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(contextmenuEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::ondblclick() const
+{
+    return correspondingElement()->eventListenerForType(dblclickEvent);
+}
+
+void SVGElementInstance::setOndblclick(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(dblclickEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onerror() const
+{
+    return correspondingElement()->eventListenerForType(errorEvent);
+}
+
+void SVGElementInstance::setOnerror(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(errorEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onfocus() const
+{
+    return correspondingElement()->eventListenerForType(focusEvent);
+}
+
+void SVGElementInstance::setOnfocus(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(focusEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::oninput() const
+{
+    return correspondingElement()->eventListenerForType(inputEvent);
+}
+
+void SVGElementInstance::setOninput(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(inputEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onkeydown() const
+{
+    return correspondingElement()->eventListenerForType(keydownEvent);
+}
+
+void SVGElementInstance::setOnkeydown(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(keydownEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onkeypress() const
+{
+    return correspondingElement()->eventListenerForType(keypressEvent);
+}
+
+void SVGElementInstance::setOnkeypress(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(keypressEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onkeyup() const
+{
+    return correspondingElement()->eventListenerForType(keyupEvent);
+}
+
+void SVGElementInstance::setOnkeyup(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(keyupEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onload() const
+{
+    return correspondingElement()->eventListenerForType(loadEvent);
+}
 
-    HashSet<SVGUseElement*>::const_iterator itUse = useHash.begin();
-    const HashSet<SVGUseElement*>::const_iterator endUse = useHash.end();
-    for (; itUse != endUse; ++itUse)
-        (*itUse)->buildPendingResource();
+void SVGElementInstance::setOnload(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(loadEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onmousedown() const
+{
+    return correspondingElement()->eventListenerForType(mousedownEvent);
+}
+
+void SVGElementInstance::setOnmousedown(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(mousedownEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onmousemove() const
+{
+    return correspondingElement()->eventListenerForType(mousemoveEvent);
+}
+
+void SVGElementInstance::setOnmousemove(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(mousemoveEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onmouseout() const
+{
+    return correspondingElement()->eventListenerForType(mouseoutEvent);
+}
+
+void SVGElementInstance::setOnmouseout(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(mouseoutEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onmouseover() const
+{
+    return correspondingElement()->eventListenerForType(mouseoverEvent);
+}
+
+void SVGElementInstance::setOnmouseover(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(mouseoverEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onmouseup() const
+{
+    return correspondingElement()->eventListenerForType(mouseupEvent);
+}
+
+void SVGElementInstance::setOnmouseup(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(mouseupEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onmousewheel() const
+{
+    return correspondingElement()->eventListenerForType(mousewheelEvent);
+}
+
+void SVGElementInstance::setOnmousewheel(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(mousewheelEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onbeforecut() const
+{
+    return correspondingElement()->eventListenerForType(beforecutEvent);
+}
+
+void SVGElementInstance::setOnbeforecut(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(beforecutEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::oncut() const
+{
+    return correspondingElement()->eventListenerForType(cutEvent);
+}
+
+void SVGElementInstance::setOncut(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(cutEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onbeforecopy() const
+{
+    return correspondingElement()->eventListenerForType(beforecopyEvent);
+}
+
+void SVGElementInstance::setOnbeforecopy(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(beforecopyEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::oncopy() const
+{
+    return correspondingElement()->eventListenerForType(copyEvent);
+}
+
+void SVGElementInstance::setOncopy(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(copyEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onbeforepaste() const
+{
+    return correspondingElement()->eventListenerForType(beforepasteEvent);
+}
+
+void SVGElementInstance::setOnbeforepaste(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(beforepasteEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onpaste() const
+{
+    return correspondingElement()->eventListenerForType(pasteEvent);
+}
+
+void SVGElementInstance::setOnpaste(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(pasteEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::ondragenter() const
+{
+    return correspondingElement()->eventListenerForType(dragenterEvent);
+}
+
+void SVGElementInstance::setOndragenter(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(dragenterEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::ondragover() const
+{
+    return correspondingElement()->eventListenerForType(dragoverEvent);
+}
+
+void SVGElementInstance::setOndragover(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(dragoverEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::ondragleave() const
+{
+    return correspondingElement()->eventListenerForType(dragleaveEvent);
+}
+
+void SVGElementInstance::setOndragleave(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(dragleaveEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::ondrop() const
+{
+    return correspondingElement()->eventListenerForType(dropEvent);
+}
+
+void SVGElementInstance::setOndrop(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(dropEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::ondragstart() const
+{
+    return correspondingElement()->eventListenerForType(dragstartEvent);
+}
+
+void SVGElementInstance::setOndragstart(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(dragstartEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::ondrag() const
+{
+    return correspondingElement()->eventListenerForType(dragEvent);
+}
+
+void SVGElementInstance::setOndrag(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(dragEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::ondragend() const
+{
+    return correspondingElement()->eventListenerForType(dragendEvent);
+}
+
+void SVGElementInstance::setOndragend(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(dragendEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onreset() const
+{
+    return correspondingElement()->eventListenerForType(resetEvent);
+}
+
+void SVGElementInstance::setOnreset(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(resetEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onresize() const
+{
+    return correspondingElement()->eventListenerForType(resizeEvent);
+}
+
+void SVGElementInstance::setOnresize(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(resizeEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onscroll() const
+{
+    return correspondingElement()->eventListenerForType(scrollEvent);
+}
+
+void SVGElementInstance::setOnscroll(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(scrollEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onsearch() const
+{
+    return correspondingElement()->eventListenerForType(searchEvent);
+}
+
+void SVGElementInstance::setOnsearch(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(searchEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onselect() const
+{
+    return correspondingElement()->eventListenerForType(selectEvent);
+}
+
+void SVGElementInstance::setOnselect(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(selectEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onselectstart() const
+{
+    return correspondingElement()->eventListenerForType(selectstartEvent);
+}
+
+void SVGElementInstance::setOnselectstart(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(selectstartEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onsubmit() const
+{
+    return correspondingElement()->eventListenerForType(submitEvent);
+}
+
+void SVGElementInstance::setOnsubmit(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(submitEvent, eventListener);
+}
+
+EventListener* SVGElementInstance::onunload() const
+{
+    return correspondingElement()->eventListenerForType(unloadEvent);
+}
+
+void SVGElementInstance::setOnunload(PassRefPtr<EventListener> eventListener)
+{
+    correspondingElement()->setEventListenerForType(unloadEvent, eventListener);
 }
 
 }
index b57844d..5bd919e 100644 (file)
 
 #if ENABLE(SVG)
 #include "EventTarget.h"
-
+#include "SVGElement.h"
 #include "TreeShared.h"
+
 #include <wtf/RefPtr.h>
 #include <wtf/PassRefPtr.h>
 
 namespace WebCore {
-    class SVGElement;
+
+    namespace Private { 
+        template<class GenericNode, class GenericNodeContainer>
+        void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer* container);
+    };
+
+    class EventListener;
+    class Frame;
     class SVGUseElement;
     class SVGElementInstanceList;
 
     // SVGElementInstance mimics Node, but without providing all its functionality
-    class SVGElementInstance : public TreeShared<SVGElementInstance> {
+    class SVGElementInstance : public TreeShared<SVGElementInstance>,
+                               public EventTarget
+    {
     public:
-        SVGElementInstance(SVGUseElement*, PassRefPtr<SVGElement> originalElement);
+        SVGElementInstance(SVGUseElement*, SVGElement* originalElement);
         virtual ~SVGElementInstance();
 
-        virtual bool isEventTargetSVGElementInstance() const { return false; }
+        bool needsUpdate() const { return m_needsUpdate; }
+        void setNeedsUpdate(bool);
 
-        // 'SVGElementInstance' functions
-        SVGElement* correspondingElement() const;
-        SVGUseElement* correspondingUseElement() const;
+        virtual Frame* associatedFrame() const;
 
-        SVGElementInstance* parentNode() const;
-        PassRefPtr<SVGElementInstanceList> childNodes();
+        virtual EventTargetNode* toNode() { return shadowTreeElement(); }
+        virtual SVGElementInstance* toSVGElementInstance() { return this; }
 
-        SVGElementInstance* previousSibling() const;
-        SVGElementInstance* nextSibling() const;
+        virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
+        virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture);
+        virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&, bool tempEvent = false);
 
-        SVGElementInstance* firstChild() const;
-        SVGElementInstance* lastChild() const;
+        SVGElement* correspondingElement() const { return m_element.get(); }
+        SVGUseElement* correspondingUseElement() const { return m_useElement; }
+        SVGElement* shadowTreeElement() const { return m_shadowTreeElement.get(); }
 
-        // Internal usage only!
-        SVGElement* shadowTreeElement() const; 
-        void setShadowTreeElement(SVGElement*);
+        SVGElementInstance* parentNode() const { return parent(); }
+        PassRefPtr<SVGElementInstanceList> childNodes();
 
-        // SVGElementInstance supports both toSVGElementInstance and toNode since so much mouse handling code depends on toNode returning a valid node.
-        virtual EventTargetNode* toNode();
-        virtual SVGElementInstance* toSVGElementInstance();
+        SVGElementInstance* previousSibling() const { return m_previousSibling; }
+        SVGElementInstance* nextSibling() const { return m_nextSibling; }
+
+        SVGElementInstance* firstChild() const { return m_firstChild; }
+        SVGElementInstance* lastChild() const { return m_lastChild; }
+
+        Document* ownerDocument() const { return m_element ? m_element->ownerDocument() : 0; }
+
+        static void invalidateAllInstancesOfElement(SVGElement*);
+
+        using TreeShared<SVGElementInstance>::ref;
+        using TreeShared<SVGElementInstance>::deref;
+
+        // EventTarget API
+        EventListener* onabort() const;
+        void setOnabort(PassRefPtr<EventListener>);
+        EventListener* onblur() const;
+        void setOnblur(PassRefPtr<EventListener>);
+        EventListener* onchange() const;
+        void setOnchange(PassRefPtr<EventListener>);
+        EventListener* onclick() const;
+        void setOnclick(PassRefPtr<EventListener>);
+        EventListener* oncontextmenu() const;
+        void setOncontextmenu(PassRefPtr<EventListener>);
+        EventListener* ondblclick() const;
+        void setOndblclick(PassRefPtr<EventListener>);
+        EventListener* onerror() const;
+        void setOnerror(PassRefPtr<EventListener>);
+        EventListener* onfocus() const;
+        void setOnfocus(PassRefPtr<EventListener>);
+        EventListener* oninput() const;
+        void setOninput(PassRefPtr<EventListener>);
+        EventListener* onkeydown() const;
+        void setOnkeydown(PassRefPtr<EventListener>);
+        EventListener* onkeypress() const;
+        void setOnkeypress(PassRefPtr<EventListener>);
+        EventListener* onkeyup() const;
+        void setOnkeyup(PassRefPtr<EventListener>);
+        EventListener* onload() const;
+        void setOnload(PassRefPtr<EventListener>);
+        EventListener* onmousedown() const;
+        void setOnmousedown(PassRefPtr<EventListener>);
+        EventListener* onmousemove() const;
+        void setOnmousemove(PassRefPtr<EventListener>);
+        EventListener* onmouseout() const;
+        void setOnmouseout(PassRefPtr<EventListener>);
+        EventListener* onmouseover() const;
+        void setOnmouseover(PassRefPtr<EventListener>);
+        EventListener* onmouseup() const;
+        void setOnmouseup(PassRefPtr<EventListener>);
+        EventListener* onmousewheel() const;
+        void setOnmousewheel(PassRefPtr<EventListener>);
+        EventListener* onbeforecut() const;
+        void setOnbeforecut(PassRefPtr<EventListener>);
+        EventListener* oncut() const;
+        void setOncut(PassRefPtr<EventListener>);
+        EventListener* onbeforecopy() const;
+        void setOnbeforecopy(PassRefPtr<EventListener>);
+        EventListener* oncopy() const;
+        void setOncopy(PassRefPtr<EventListener>);
+        EventListener* onbeforepaste() const;
+        void setOnbeforepaste(PassRefPtr<EventListener>);
+        EventListener* onpaste() const;
+        void setOnpaste(PassRefPtr<EventListener>);
+        EventListener* ondragenter() const;
+        void setOndragenter(PassRefPtr<EventListener>);
+        EventListener* ondragover() const;
+        void setOndragover(PassRefPtr<EventListener>);
+        EventListener* ondragleave() const;
+        void setOndragleave(PassRefPtr<EventListener>);
+        EventListener* ondrop() const;
+        void setOndrop(PassRefPtr<EventListener>);
+        EventListener* ondragstart() const;
+        void setOndragstart(PassRefPtr<EventListener>);
+        EventListener* ondrag() const;
+        void setOndrag(PassRefPtr<EventListener>);
+        EventListener* ondragend() const;
+        void setOndragend(PassRefPtr<EventListener>);
+        EventListener* onreset() const;
+        void setOnreset(PassRefPtr<EventListener>);
+        EventListener* onresize() const;
+        void setOnresize(PassRefPtr<EventListener>);
+        EventListener* onscroll() const;
+        void setOnscroll(PassRefPtr<EventListener>);
+        EventListener* onsearch() const;
+        void setOnsearch(PassRefPtr<EventListener>);
+        EventListener* onselect() const;
+        void setOnselect(PassRefPtr<EventListener>);
+        EventListener* onselectstart() const;
+        void setOnselectstart(PassRefPtr<EventListener>);
+        EventListener* onsubmit() const;
+        void setOnsubmit(PassRefPtr<EventListener>);
+        EventListener* onunload() const;
+        void setOnunload(PassRefPtr<EventListener>);
 
-        static void updateAllInstancesOfElement(SVGElement*);
-    private: // Helper methods
+    private:
         friend class SVGUseElement;
+
         void appendChild(PassRefPtr<SVGElementInstance> child);
+        void setShadowTreeElement(SVGElement*);
+        void forgetWrapper();
+
+        template<class GenericNode, class GenericNodeContainer>
+        friend void appendChildToContainer(GenericNode* child, GenericNodeContainer* container);
+
+        template<class GenericNode, class GenericNodeContainer>
+        friend void removeAllChildrenInContainer(GenericNodeContainer* container);
+
+        template<class GenericNode, class GenericNodeContainer>
+        friend void Private::addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer* container);
+
+        bool hasChildNodes() const { return m_firstChild; }
+
+        void setFirstChild(SVGElementInstance* child) { m_firstChild = child; }
+        void setLastChild(SVGElementInstance* child) { m_lastChild = child; }
+
+        void setNextSibling(SVGElementInstance* sibling) { m_nextSibling = sibling; }
+        void setPreviousSibling(SVGElementInstance* sibling) { m_previousSibling = sibling; }    
+
+        virtual void refEventTarget() { ref(); }
+        virtual void derefEventTarget() { deref(); }
 
     private:
+        bool m_needsUpdate : 1;
+
         SVGUseElement* m_useElement;
         RefPtr<SVGElement> m_element;
-        SVGElement* m_shadowTreeElement;
+        RefPtr<SVGElement> m_shadowTreeElement;
 
         SVGElementInstance* m_previousSibling;
         SVGElementInstance* m_nextSibling;
@@ -85,5 +209,3 @@ namespace WebCore {
 
 #endif // ENABLE(SVG)
 #endif
-
-// vim:ts=4:noet
index 0035681..92da5a6 100644 (file)
  */
 
 module svg {
-    interface [Conditional=SVG, ObjCCustomInternalImpl] SVGElementInstance
+
+    interface [
+        Conditional=SVG,
+        ObjCCustomInternalImpl,
+        CustomListeners,
+        CustomPushEventHandlerScope,
+        GenerateToJS,
+        GenerateNativeConverter
+    ] SVGElementInstance
 #if defined(LANGUAGE_OBJECTIVE_C)
         : Object, EventTarget
 #endif /* defined(LANGUAGE_OBJECTIVE_C) */
@@ -38,5 +46,58 @@ module svg {
         readonly attribute SVGElementInstance lastChild;
         readonly attribute SVGElementInstance previousSibling;
         readonly attribute SVGElementInstance nextSibling;
+
+        // EventTarget
+#if !defined(LANGUAGE_OBJECTIVE_C)
+        attribute [DontEnum, ProtectedListener] EventListener onabort;
+        attribute [DontEnum, ProtectedListener] EventListener onblur;
+        attribute [DontEnum, ProtectedListener] EventListener onchange;
+        attribute [DontEnum, ProtectedListener] EventListener onclick;
+        attribute [DontEnum, ProtectedListener] EventListener oncontextmenu;
+        attribute [DontEnum, ProtectedListener] EventListener ondblclick;
+        attribute [DontEnum, ProtectedListener] EventListener onerror;
+        attribute [DontEnum, ProtectedListener] EventListener onfocus;
+        attribute [DontEnum, ProtectedListener] EventListener oninput;
+        attribute [DontEnum, ProtectedListener] EventListener onkeydown;
+        attribute [DontEnum, ProtectedListener] EventListener onkeypress;
+        attribute [DontEnum, ProtectedListener] EventListener onkeyup;
+        attribute [DontEnum, ProtectedListener] EventListener onload;
+        attribute [DontEnum, ProtectedListener] EventListener onmousedown;
+        attribute [DontEnum, ProtectedListener] EventListener onmousemove;
+        attribute [DontEnum, ProtectedListener] EventListener onmouseout;
+        attribute [DontEnum, ProtectedListener] EventListener onmouseover;
+        attribute [DontEnum, ProtectedListener] EventListener onmouseup;
+        attribute [DontEnum, ProtectedListener] EventListener onmousewheel;
+        attribute [DontEnum, ProtectedListener] EventListener onbeforecut;
+        attribute [DontEnum, ProtectedListener] EventListener oncut;
+        attribute [DontEnum, ProtectedListener] EventListener onbeforecopy;
+        attribute [DontEnum, ProtectedListener] EventListener oncopy;
+        attribute [DontEnum, ProtectedListener] EventListener onbeforepaste;
+        attribute [DontEnum, ProtectedListener] EventListener onpaste;
+        attribute [DontEnum, ProtectedListener] EventListener ondragenter;
+        attribute [DontEnum, ProtectedListener] EventListener ondragover;
+        attribute [DontEnum, ProtectedListener] EventListener ondragleave;
+        attribute [DontEnum, ProtectedListener] EventListener ondrop;
+        attribute [DontEnum, ProtectedListener] EventListener ondragstart;
+        attribute [DontEnum, ProtectedListener] EventListener ondrag;
+        attribute [DontEnum, ProtectedListener] EventListener ondragend;
+        attribute [DontEnum, ProtectedListener] EventListener onreset;
+        attribute [DontEnum, ProtectedListener] EventListener onresize;
+        attribute [DontEnum, ProtectedListener] EventListener onscroll;
+        attribute [DontEnum, ProtectedListener] EventListener onsearch;
+        attribute [DontEnum, ProtectedListener] EventListener onselect;
+        attribute [DontEnum, ProtectedListener] EventListener onselectstart;
+        attribute [DontEnum, ProtectedListener] EventListener onsubmit;
+        attribute [DontEnum, ProtectedListener] EventListener onunload;
+
+        [Custom] void addEventListener(in DOMString type, 
+                                       in EventListener listener, 
+                                       in boolean useCapture);
+        [Custom] void removeEventListener(in DOMString type, 
+                                          in EventListener listener, 
+                                          in boolean useCapture);
+        boolean dispatchEvent(in Event event)
+            raises(EventException);
+#endif /* defined(LANGUAGE_OBJECTIVE_C) */
     };
 }
index baa436a..63fa428 100644 (file)
@@ -200,12 +200,8 @@ void SVGStyledElement::svgAttributeChanged(const QualifiedName& attrName)
     // If we're the child of a resource element, be sure to invalidate it.
     invalidateResourcesInAncestorChain();
 
-    // TODO: Fix bug http://bugs.webkit.org/show_bug.cgi?id=15430 (SVGElementInstances should rebuild themselves lazily)
-
-    // In case we're referenced by a <use> element, we have element instances registered
-    // to us in the SVGDocument. If svgAttributeChanged() is called, we need
-    // to recursively update all children including ourselves.
-    SVGElementInstance::updateAllInstancesOfElement(this);
+    // Invalidate all SVGElementInstances associated with us
+    SVGElementInstance::invalidateAllInstancesOfElement(this);
 }
 
 void SVGStyledElement::invalidateResourcesInAncestorChain() const
@@ -231,12 +227,8 @@ void SVGStyledElement::childrenChanged(bool changedByParser, Node* beforeChange,
     if (document()->parsing())
         return;
 
-    // TODO: Fix bug http://bugs.webkit.org/show_bug.cgi?id=15430 (SVGElementInstances should rebuild themselves lazily)
-
-    // In case we're referenced by a <use> element, we have element instances registered
-    // to us in the SVGDocument. If childrenChanged() is called, we need
-    // to recursively update all children including ourselves.
-    SVGElementInstance::updateAllInstancesOfElement(this);
+    // Invalidate all SVGElementInstances associated with us
+    SVGElementInstance::invalidateAllInstancesOfElement(this);
 }
 
 RenderStyle* SVGStyledElement::resolveStyle(RenderStyle* parentStyle)
index 8b89a17..d715fb6 100644 (file)
 #include "CString.h"
 #include "Document.h"
 #include "Event.h"
+#include "EventListener.h"
 #include "HTMLNames.h"
+#include "NodeRenderStyle.h"
+#include "RegisteredEventListener.h"
 #include "RenderSVGTransformableContainer.h"
 #include "SVGElementInstance.h"
 #include "SVGElementInstanceList.h"
@@ -47,8 +50,6 @@
 #include "SVGSymbolElement.h"
 #include "XLinkNames.h"
 #include "XMLSerializer.h"
-#include "NodeRenderStyle.h"
-#include <wtf/OwnPtr.h>
 
 namespace WebCore {
 
@@ -134,8 +135,6 @@ void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName)
         SVGExternalResourcesRequired::isKnownAttribute(attrName) ||
         SVGURIReference::isKnownAttribute(attrName) ||
         SVGStyledTransformableElement::isKnownAttribute(attrName)) {
-        // TODO: Now that we're aware of the attribute name, we can finally optimize
-        // updating <use> attributes - to not reclone every time.
         buildPendingResource();
 
         if (m_shadowTreeRootElement)
@@ -155,9 +154,28 @@ void SVGUseElement::childrenChanged(bool changedByParser, Node* beforeChange, No
     if (m_shadowTreeRootElement)
         m_shadowTreeRootElement->setChanged();
 }
+static bool shadowTreeContainsChangedNodes(SVGElementInstance* target)
+{
+    if (target->needsUpdate())
+        return true;
+
+    for (SVGElementInstance* instance = target->firstChild(); instance; instance = instance->nextSibling())
+        if (shadowTreeContainsChangedNodes(instance))
+            return true;
+
+    return false;
+}
 
 void SVGUseElement::recalcStyle(StyleChange change)
 {
+    if (attached() && changed() && shadowTreeContainsChangedNodes(m_targetElementInstance.get())) {
+        buildPendingResource();
+
+        if (m_shadowTreeRootElement)
+            m_shadowTreeRootElement->setChanged();
+    }
+
     SVGStyledElement::recalcStyle(change);
 
     // The shadow tree root element is NOT a direct child element of us.
@@ -204,15 +222,31 @@ void dumpInstanceTree(unsigned int& depth, String& text, SVGElementInstance* tar
     for (unsigned int i = 0; i < depth; ++i)
         text += "  ";
 
-    text += String::format("SVGElementInstance (parentNode=%s, firstChild=%s, correspondingElement=%s, id=%s)\n",
-                           parentNodeName.latin1().data(), firstChildNodeName.latin1().data(), elementNodeName.latin1().data(), elementId.latin1().data());
-    depth++;
+    text += String::format("SVGElementInstance this=%p, (parentNode=%s, firstChild=%s, correspondingElement=%s (%p), shadowTreeElement=%p, id=%s)\n",
+                           targetInstance, parentNodeName.latin1().data(), firstChildNodeName.latin1().data(), elementNodeName.latin1().data(),
+                           element, targetInstance->shadowTreeElement(), elementId.latin1().data());
+
+    for (unsigned int i = 0; i < depth; ++i)
+        text += "  ";
+
+    HashSet<SVGElementInstance*> elementInstances = element->instancesForElement();
+    text += String::format("Corresponding element is associated with %i instance(s):\n", elementInstances.size());
+
+    HashSet<SVGElementInstance*>::iterator end = elementInstances.end();
+    for (HashSet<SVGElementInstance*>::iterator it = elementInstances.begin(); it != end; ++it) {
+        for (unsigned int i = 0; i < depth; ++i)
+            text += "  ";
+
+        text += String::format(" -> SVGElementInstance this=%p, (refCount: %i, shadowTreeElement in document? %i)\n",
+                               *it, (*it)->refCount(), (*it)->shadowTreeElement()->inDocument());
+    }
+
+    ++depth;
 
     for (SVGElementInstance* instance = targetInstance->firstChild(); instance; instance = instance->nextSibling())
         dumpInstanceTree(depth, text, instance);
 
-    depth--;
+    --depth;
 }
 #endif
 
@@ -270,10 +304,14 @@ void SVGUseElement::buildPendingResource()
     if (targetElement && targetElement->isSVGElement())
         target = static_cast<SVGElement*>(targetElement);
 
+    if (m_targetElementInstance) {
+        m_targetElementInstance->forgetWrapper();
+        m_targetElementInstance = 0;
+    }
+
     // Do not allow self-referencing.
     // 'target' may be null, if it's a non SVG namespaced element.
     if (!target || target == this) {
-        m_targetElementInstance = 0;
         m_shadowTreeRootElement = 0;
         return;
     }
@@ -359,6 +397,9 @@ void SVGUseElement::buildPendingResource()
     fprintf(stderr, "Dumping <use> shadow tree markup:\n%s\n", markup.latin1().data());
 #endif
 
+    // Transfer event listeners assigned to the referenced element to our shadow tree elements.
+    transferEventListenersToShadowTree(m_targetElementInstance.get());
+
     // The DOM side is setup properly. Now we have to attach the root shadow
     // tree element manually - using attach() won't work for "shadow nodes".
     attachShadowTree();
@@ -436,9 +477,7 @@ void SVGUseElement::buildInstanceTree(SVGElement* target, SVGElementInstance* ta
 
         // Create SVGElementInstance object, for both container/non-container nodes.
         SVGElementInstance* instancePtr = new SVGElementInstance(this, element);
-
-        RefPtr<SVGElementInstance> instance = instancePtr;
-        targetInstance->appendChild(instance.release());
+        targetInstance->appendChild(instancePtr);
 
         // Enter recursion, appending new instance tree nodes to the "instance" object.
         if (element->hasChildNodes())
@@ -723,6 +762,34 @@ void SVGUseElement::attachShadowTree()
             child->attach();
     }
 }
+void SVGUseElement::transferEventListenersToShadowTree(SVGElementInstance* target)
+{
+    if (!target)
+        return;
+
+    SVGElement* originalElement = target->correspondingElement();
+    ASSERT(originalElement);
+
+    if (SVGElement* shadowTreeElement = target->shadowTreeElement()) {
+        if (RegisteredEventListenerList* localEventListeners = originalElement->localEventListeners()) {
+            RegisteredEventListenerList::Iterator end = localEventListeners->end();
+            for (RegisteredEventListenerList::Iterator it = localEventListeners->begin(); it != end; ++it) {
+                EventListener* listener = (*it)->listener();
+                ASSERT(listener);
+
+                // Event listeners created from markup have already been transfered to the shadow tree during cloning!
+                if (listener->wasCreatedFromMarkup())
+                    continue;
+
+                shadowTreeElement->addEventListener((*it)->eventType(), listener, (*it)->useCapture());
+            }
+        }
+    }
+
+    for (SVGElementInstance* instance = target->firstChild(); instance; instance = instance->nextSibling())
+        transferEventListenersToShadowTree(instance);
+}
 
 void SVGUseElement::associateInstancesWithShadowTreeElements(Node* target, SVGElementInstance* targetInstance)
 {
index 1bb52e5..1e5b81c 100644 (file)
@@ -66,6 +66,7 @@ namespace WebCore {
         virtual Path toClipPath() const;
 
         static void removeDisallowedElementsFromSubtree(Node* element);
+        SVGElementInstance* instanceForShadowTreeElement(Node* element) const;
 
     protected:
         virtual const SVGElement* contextElement() const { return this; }
@@ -77,9 +78,6 @@ namespace WebCore {
         ANIMATED_PROPERTY_DECLARATIONS(SVGUseElement, SVGNames::useTagString, SVGNames::heightAttrString, SVGLength, Height, height)
 
     private:
-        friend class SVGElement;
-        SVGElementInstance* instanceForShadowTreeElement(Node* element) const;
-
         // Instance tree handling
         void buildInstanceTree(SVGElement* target, SVGElementInstance* targetInstance, bool& foundCycle);
         void handleDeepUseReferencing(SVGUseElement* use, SVGElementInstance* targetInstance, bool& foundCycle);
@@ -99,9 +97,10 @@ namespace WebCore {
 
         // "Tree connector" 
         void associateInstancesWithShadowTreeElements(Node* target, SVGElementInstance* targetInstance);
-
         SVGElementInstance* instanceForShadowTreeElement(Node* element, SVGElementInstance* instance) const;
+
         void transferUseAttributesToReplacedElement(SVGElement* from, SVGElement* to) const;
+        void transferEventListenersToShadowTree(SVGElementInstance* target);
 
         RefPtr<SVGElement> m_shadowTreeRootElement;
         RefPtr<SVGElementInstance> m_targetElementInstance;