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 id14467
push userdholbert@mozilla.com
push dateSun, 18 Jul 2010 22:11:20 +0000
treeherdermozilla-central@d03339731d61 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert, roc
bugs552938
milestone2.0b2pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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>