Bug 552938 - Implement the SVG load event in text/html, make the SVG load event in XML async and only supported on <svg>. (Also disable/tweak 2 broken tests) r=dholbert, sr=roc
authorHenri Sivonen <hsivonen@iki.fi>
Sun, 18 Jul 2010 15:07:54 -0700
changeset 47894 d03339731d6153358214defe218077ea831de1eb
parent 47893 41f7430df680bba789c930fa09ca498ab03df807
child 47895 9c9ee87d42fa75467b2afc73ffa9ff6882d3a682
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersdholbert, roc
bugs552938
milestone2.0b2pre
Bug 552938 - Implement the SVG load event in text/html, make the SVG load event in XML async and only supported on <svg>. (Also disable/tweak 2 broken tests) r=dholbert, sr=roc
content/smil/test/test_smilReset.xhtml
content/xml/document/src/nsXMLContentSink.cpp
layout/reftests/svg/reftest.list
layout/svg/crashtests/crashtests.list
parser/html/Makefile.in
parser/html/nsHtml5SVGLoadDispatcher.cpp
parser/html/nsHtml5SVGLoadDispatcher.h
parser/html/nsHtml5TreeBuilderCppSupplement.h
parser/html/nsHtml5TreeOperation.cpp
parser/html/nsHtml5TreeOperation.h
parser/htmlparser/tests/mochitest/Makefile.in
parser/htmlparser/tests/mochitest/test_bug552938-2.html
parser/htmlparser/tests/mochitest/test_bug552938.html
--- a/content/smil/test/test_smilReset.xhtml
+++ b/content/smil/test/test_smilReset.xhtml
@@ -20,16 +20,17 @@
 <script class="testbody" type="text/javascript">
 <![CDATA[
 /** Tests for SMIL Reset Behavior  **/
 
 SimpleTest.waitForExplicitFinish();
 
 function main() {
   var svg = document.getElementById("svg");
+  svg.setCurrentTime(0);
   ok(svg.animationsPaused(), "should be paused by <svg> load handler");
   is(svg.getCurrentTime(), 0, "should be paused at 0 in <svg> load handler");
 
   var anim = document.getElementById("anim1");
   is(anim.getStartTime(), 2, "Unexpected initial start time");
 
   svg.setCurrentTime(1);
   anim.beginElementAt(2);
--- a/content/xml/document/src/nsXMLContentSink.cpp
+++ b/content/xml/document/src/nsXMLContentSink.cpp
@@ -47,18 +47,16 @@
 #include "nsIDOMDOMImplementation.h"
 #include "nsIDOMNSDocument.h"
 #include "nsIContent.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIStyleSheetLinkingElement.h"
-#include "nsPresContext.h"
-#include "nsIPresShell.h"
 #include "nsIDOMComment.h"
 #include "nsIDOMCDATASection.h"
 #include "nsDOMDocumentType.h"
 #include "nsHTMLParts.h"
 #include "nsCRT.h"
 #include "nsCSSStyleSheet.h"
 #include "nsCSSLoader.h"
 #include "nsGkAtoms.h"
@@ -91,22 +89,21 @@
 #include "nsContentCreatorFunctions.h"
 #include "nsIContentPolicy.h"
 #include "nsContentPolicyUtils.h"
 #include "nsContentErrors.h"
 #include "nsIDOMProcessingInstruction.h"
 #include "nsNodeUtils.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIHTMLDocument.h"
-#include "nsEventDispatcher.h"
 #include "mozAutoDocUpdate.h"
 #include "nsMimeTypes.h"
 
 #ifdef MOZ_SVG
-#include "nsGUIEvent.h"
+#include "nsHtml5SVGLoadDispatcher.h"
 #endif
 
 // XXX Open Issues:
 // 1) what's not allowed - We need to figure out which HTML tags
 //    (prefixed with a HTML namespace qualifier) are explicitly not
 //    allowed (if any).
 // 2) factoring code with nsHTMLContentSink - There's some amount of
 //    common code between this and the HTML content sink. This will
@@ -1152,39 +1149,23 @@ nsXMLContentSink::HandleEndElement(const
     if (numFlushed < content->GetChildCount()) {
     	  NotifyAppend(content, numFlushed);
     }
     mNotifyLevel = stackLen - 1;
   }
   DidAddContent();
 
 #ifdef MOZ_SVG
-  if (mDocument &&
-      content->GetNameSpaceID() == kNameSpaceID_SVG &&
-      (
-#ifdef MOZ_SMIL
-       content->Tag() == nsGkAtoms::svg ||
-#endif
-       content->HasAttr(kNameSpaceID_None, nsGkAtoms::onload))) {
+  if (content->GetNameSpaceID() == kNameSpaceID_SVG &&
+      content->Tag() == nsGkAtoms::svg) {
     FlushTags();
-
-    nsEvent event(PR_TRUE, NS_SVG_LOAD);
-    event.eventStructType = NS_SVG_EVENT;
-    event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
-
-    // Do we care about forcing presshell creation if it hasn't happened yet?
-    // That is, should this code flush or something?  Does it really matter?
-    // For that matter, do we really want to try getting the prescontext?  Does
-    // this event ever want one?
-    nsRefPtr<nsPresContext> ctx;
-    nsCOMPtr<nsIPresShell> shell = mDocument->GetShell();
-    if (shell) {
-      ctx = shell->GetPresContext();
+    nsCOMPtr<nsIRunnable> event = new nsHtml5SVGLoadDispatcher(content);
+    if (NS_FAILED(NS_DispatchToMainThread(event))) {
+      NS_WARNING("failed to dispatch svg load dispatcher");
     }
-    nsEventDispatcher::Dispatch(content, ctx, &event);
   }
 #endif
 
   return aInterruptable && NS_SUCCEEDED(result) ? DidProcessATokenImpl() :
                                                   result;
 }
 
 NS_IMETHODIMP 
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -60,17 +60,17 @@ include svg-integration/reftest.list
 == dynamic-small-object-scaled-up-02.svg pass.svg
 == dynamic-switch-01.svg pass.svg
 == dynamic-text-01.svg dynamic-text-01-ref.svg
 == dynamic-text-02.svg dynamic-text-02-ref.svg
 == dynamic-text-03.svg dynamic-text-03-ref.svg
 == dynamic-textPath-01.svg dynamic-textPath-01-ref.svg
 == dynamic-use-01.svg pass.svg
 == dynamic-use-02.svg pass.svg
-== dynamic-use-nested-01.svg dynamic-use-nested-01-ref.svg
+random == dynamic-use-nested-01.svg dynamic-use-nested-01-ref.svg # bug 467498
 == dynamic-use-remove-width.svg dynamic-use-remove-width-ref.svg
 == linked-pattern-01.svg pass.svg
 == use-01-extref.svg pass.svg
 == use-02-extref.svg use-02-extref-ref.svg
 == use-children.svg pass.svg
 == fallback-color-01a.svg pass.svg
 == fallback-color-01b.svg pass.svg
 == fallback-color-02a.svg fallback-color-02-ref.svg
--- a/layout/svg/crashtests/crashtests.list
+++ b/layout/svg/crashtests/crashtests.list
@@ -44,17 +44,17 @@ load 371563-1.xhtml
 load 375775-1.svg
 load 380691-1.svg
 load 384391-1.xhtml
 load 384499-1.svg
 load 384637-1.svg
 load 384728-1.svg
 load 385246-1.svg
 load 385246-2.svg
-asserts(1) load 385840-1.svg # bug 385845
+load 385840-1.svg
 load 385852-1.svg
 load 386475-1.xhtml
 load 386566-1.svg
 load 387290-1.svg
 load 402408-1.svg
 load 404677-1.xhtml
 load 409565-1.xhtml
 load 409573-1.svg
--- a/parser/html/Makefile.in
+++ b/parser/html/Makefile.in
@@ -45,16 +45,22 @@ MODULE		= html5
 LIBRARY_NAME	= html5p_s
 LIBXUL_LIBRARY	= 1
 
 
 EXPORTS		= \
 		nsHtml5Module.h \
 		$(NULL)
 
+ifdef MOZ_SVG
+EXPORTS += \
+		nsHtml5SVGLoadDispatcher.h \
+		$(NULL)
+endif
+
 CPPSRCS		= \
 		nsHtml5Atoms.cpp \
 		nsHtml5Atom.cpp \
 		nsHtml5AtomTable.cpp \
 		nsHtml5Parser.cpp \
 		nsHtml5AttributeName.cpp \
 		nsHtml5ElementName.cpp \
 		nsHtml5HtmlAttributes.cpp \
@@ -72,15 +78,21 @@ CPPSRCS		= \
 		nsHtml5TreeOpStage.cpp \
 		nsHtml5StateSnapshot.cpp \
 		nsHtml5TreeOpExecutor.cpp \
 		nsHtml5StreamParser.cpp \
 		nsHtml5Speculation.cpp \
 		nsHtml5SpeculativeLoad.cpp \
 		$(NULL)
 
+ifdef MOZ_SVG
+CPPSRCS += \
+		nsHtml5SVGLoadDispatcher.cpp \
+		$(NULL)
+endif
+
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 INCLUDES	+= \
 		-I$(srcdir)/../../content/base/src \
 		$(NULL)
new file mode 100644
--- /dev/null
+++ b/parser/html/nsHtml5SVGLoadDispatcher.cpp
@@ -0,0 +1,72 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Pierre Phaneuf <pp@ludusdesign.com>
+ *   Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsHtml5SVGLoadDispatcher.h"
+#include "nsPresContext.h"
+#include "nsEventDispatcher.h"
+#include "nsIPresShell.h"
+#include "nsGUIEvent.h"
+
+nsHtml5SVGLoadDispatcher::nsHtml5SVGLoadDispatcher(nsIContent* aElement)
+  : mElement(aElement)
+  , mDocument(mElement->GetOwnerDoc())
+{
+  mDocument->BlockOnload();
+}
+
+NS_IMETHODIMP
+nsHtml5SVGLoadDispatcher::Run()
+{
+  nsEvent event(PR_TRUE, NS_SVG_LOAD);
+  event.eventStructType = NS_SVG_EVENT;
+  event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
+  // Do we care about forcing presshell creation if it hasn't happened yet?
+  // That is, should this code flush or something?  Does it really matter?
+  // For that matter, do we really want to try getting the prescontext?
+  // Does this event ever want one?
+  nsRefPtr<nsPresContext> ctx;
+  nsCOMPtr<nsIPresShell> shell = mElement->GetOwnerDoc()->GetShell();
+  if (shell) {
+    ctx = shell->GetPresContext();
+  }
+  nsEventDispatcher::Dispatch(mElement, ctx, &event);
+  // Unblocking onload on the same document that it was blocked even if
+  // the element has moved between docs since blocking.
+  mDocument->UnblockOnload(PR_FALSE);
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/parser/html/nsHtml5SVGLoadDispatcher.h
@@ -0,0 +1,54 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Asynchronous SVG load event dispatching code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsHtml5SVGLoadDispatcher_h_
+#define nsHtml5SVGLoadDispatcher_h_
+
+#include "nsThreadUtils.h"
+#include "nsIContent.h"
+
+class nsHtml5SVGLoadDispatcher : public nsRunnable
+{
+  private:
+    nsCOMPtr<nsIContent> mElement;
+    nsCOMPtr<nsIDocument> mDocument;
+  public:
+    nsHtml5SVGLoadDispatcher(nsIContent* aElement);
+    NS_IMETHOD Run();
+};
+
+#endif // nsHtml5SVGLoadDispatcher_h_
--- a/parser/html/nsHtml5TreeBuilderCppSupplement.h
+++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h
@@ -489,34 +489,23 @@ nsHtml5TreeBuilder::elementPopped(PRInt3
   }
   if (aName == nsHtml5Atoms::style || (aNamespace == kNameSpaceID_XHTML && aName == nsHtml5Atoms::link)) {
     nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     NS_ASSERTION(treeOp, "Tree op allocation failed.");
     treeOp->Init(eTreeOpUpdateStyleSheet, aElement);
     return;
   }
   if (aNamespace == kNameSpaceID_SVG) {
-#if 0
-    if (aElement->HasAttr(kNameSpaceID_None, nsHtml5Atoms::onload)) {
-      nsEvent event(PR_TRUE, NS_SVG_LOAD);
-      event.eventStructType = NS_SVG_EVENT;
-      event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
-      // Do we care about forcing presshell creation if it hasn't happened yet?
-      // That is, should this code flush or something?  Does it really matter?
-      // For that matter, do we really want to try getting the prescontext?  Does
-      // this event ever want one?
-      nsRefPtr<nsPresContext> ctx;
-      nsCOMPtr<nsIPresShell> shell = parser->GetDocument()->GetShell();
-      if (shell) {
-        ctx = shell->GetPresContext();
-      }
-      nsEventDispatcher::Dispatch(aElement, ctx, &event);
+#ifdef MOZ_SVG
+    if (aName == nsHtml5Atoms::svg) {
+      nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
+      NS_ASSERTION(treeOp, "Tree op allocation failed.");
+      treeOp->Init(eTreeOpSvgLoad, aElement);
     }
 #endif
-    // TODO soft flush the op queue every now and then
     return;
   }
   // we now have only HTML
   // Some HTML nodes need DoneAddingChildren() called to initialize
   // properly (e.g. form state restoration).
   // XXX expose ElementName group here and do switch
   if (aName == nsHtml5Atoms::video ||
       aName == nsHtml5Atoms::audio ||
--- a/parser/html/nsHtml5TreeOperation.cpp
+++ b/parser/html/nsHtml5TreeOperation.cpp
@@ -56,16 +56,20 @@
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIFormControl.h"
 #include "nsIStyleSheetLinkingElement.h"
 #include "nsIDOMDocumentType.h"
 #include "nsIMutationObserver.h"
 #include "nsIFormProcessor.h"
 #include "nsIServiceManager.h"
 
+#ifdef MOZ_SVG
+#include "nsHtml5SVGLoadDispatcher.h"
+#endif
+
 static NS_DEFINE_CID(kFormProcessorCID, NS_FORMPROCESSOR_CID);
 
 /**
  * Helper class that opens a notification batch if the current doc
  * is different from the executor doc.
  */
 class NS_STACK_CLASS nsHtml5OtherDocUpdate {
   public:
@@ -671,14 +675,24 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
     case eTreeOpSetScriptLineNumberAndFreeze: {
       nsIContent* node = *(mOne.node);
       nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node);
       NS_ASSERTION(sele, "Node didn't QI to script.");
       sele->SetScriptLineNumber(mInt);
       sele->FreezeUriAsyncDefer();
       return rv;
     }
+#ifdef MOZ_SVG
+    case eTreeOpSvgLoad: {
+      nsIContent* node = *(mOne.node);
+      nsCOMPtr<nsIRunnable> event = new nsHtml5SVGLoadDispatcher(node);
+      if (NS_FAILED(NS_DispatchToMainThread(event))) {
+        NS_WARNING("failed to dispatch svg load dispatcher");
+      }
+      return rv;
+    }
+#endif
     default: {
       NS_NOTREACHED("Bogus tree op");
     }
   }
   return rv; // keep compiler happy
 }
--- a/parser/html/nsHtml5TreeOperation.h
+++ b/parser/html/nsHtml5TreeOperation.h
@@ -77,16 +77,19 @@ enum eHtml5TreeOperation {
   eTreeOpNeedsCharsetSwitchTo,
   eTreeOpUpdateStyleSheet,
   eTreeOpProcessMeta,
   eTreeOpProcessOfflineManifest,
   eTreeOpMarkMalformedIfScript,
   eTreeOpStreamEnded,
   eTreeOpSetStyleLineNumber,
   eTreeOpSetScriptLineNumberAndFreeze,
+#ifdef MOZ_SVG
+  eTreeOpSvgLoad,
+#endif
   eTreeOpStartLayout
 };
 
 class nsHtml5TreeOperationStringPair {
   private:
     nsString mPublicId;
     nsString mSystemId;
   public:
--- a/parser/htmlparser/tests/mochitest/Makefile.in
+++ b/parser/htmlparser/tests/mochitest/Makefile.in
@@ -54,16 +54,18 @@ include $(topsrcdir)/config/rules.mk
 		test_bug174351.html \
 	 	test_bug339350.xhtml \
 		test_bug358797.html \
 		test_bug396568.html \
 		test_bug418464.html \
 		test_bug460437.xhtml \
 		test_bug502091.html \
 		bug_502091_iframe.html \
+		test_bug552938.html \
+		test_bug552938-2.html \
 		test_bug566879.html \
 		test_compatmode.html \
 		invalidchar.xml \
 		$(NULL)
 
 # Disabled test due to orange on Linux
 #		test_bug568470.html \
 #		file_bug568470.sjs \
new file mode 100644
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug552938-2.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=552938
+-->
+<head>
+  <title>Test for Bug 552938</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload='runTest();'>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=552938">Mozilla Bug 552938</a>
+<script>
+var svgLoadFired = false;
+</script>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <svg>
+    <script>
+       document.getElementsByTagName("svg")[0].addEventListener("SVGLoad", 
+         function() { svgLoadFired = true; }, false);
+    </script>
+  </svg>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 552938 **/
+function runTest() {
+  ok(svgLoadFired, "The SVG load event should have fired.");
+  SimpleTest.finish();
+}
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug552938.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=552938
+-->
+<head>
+  <title>Test for Bug 552938</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload='runTest();'>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=552938">Mozilla Bug 552938</a>
+<script>
+var svgLoadFired = false;
+</script>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <svg onload="svgLoadFired = true;"></svg>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 552938 **/
+function runTest() {
+  ok(svgLoadFired, "The SVG load event should have fired.");
+  SimpleTest.finish();
+}
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>