diff --git a/mozilla/layout/reftests/reftest-sanity/reftest.list b/mozilla/layout/reftests/reftest-sanity/reftest.list
new file mode 100644
index 00000000000..7b0c0b612cd
--- /dev/null
+++ b/mozilla/layout/reftests/reftest-sanity/reftest.list
@@ -0,0 +1,7 @@
+== data:text/html,
about:blank
+== data:text/plain, about:blank
+!= data:text/plain,HELLO about:blank
+
+# these tests make sure async reftests work:
+== test-async.xul test-async-ref.xul
+== test-async.html test-async-ref.html
diff --git a/mozilla/layout/reftests/reftest-sanity/test-async-ref.html b/mozilla/layout/reftests/reftest-sanity/test-async-ref.html
new file mode 100644
index 00000000000..7d92f683df9
--- /dev/null
+++ b/mozilla/layout/reftests/reftest-sanity/test-async-ref.html
@@ -0,0 +1,2 @@
+
+
diff --git a/mozilla/layout/reftests/reftest-sanity/test-async-ref.xul b/mozilla/layout/reftests/reftest-sanity/test-async-ref.xul
new file mode 100644
index 00000000000..690fc60aa98
--- /dev/null
+++ b/mozilla/layout/reftests/reftest-sanity/test-async-ref.xul
@@ -0,0 +1,3 @@
+
+
diff --git a/mozilla/layout/reftests/reftest-sanity/test-async.html b/mozilla/layout/reftests/reftest-sanity/test-async.html
new file mode 100644
index 00000000000..db24cf42b7f
--- /dev/null
+++ b/mozilla/layout/reftests/reftest-sanity/test-async.html
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/mozilla/layout/reftests/reftest-sanity/test-async.xul b/mozilla/layout/reftests/reftest-sanity/test-async.xul
new file mode 100644
index 00000000000..e8dc869ad34
--- /dev/null
+++ b/mozilla/layout/reftests/reftest-sanity/test-async.xul
@@ -0,0 +1,15 @@
+
+
+
+
diff --git a/mozilla/layout/reftests/reftest.list b/mozilla/layout/reftests/reftest.list
index 32b47c2844f..bdad55dad36 100644
--- a/mozilla/layout/reftests/reftest.list
+++ b/mozilla/layout/reftests/reftest.list
@@ -3,9 +3,7 @@
# failing test.
# verify the tests work
-== data:text/html, about:blank
-== data:text/plain, about:blank
-!= data:text/plain,HELLO about:blank
+include reftest-sanity/reftest.list
# bugs/
include bugs/reftest.list
diff --git a/mozilla/layout/tools/reftest/README.txt b/mozilla/layout/tools/reftest/README.txt
index 417eb869067..44b924fa055 100644
--- a/mozilla/layout/tools/reftest/README.txt
+++ b/mozilla/layout/tools/reftest/README.txt
@@ -146,7 +146,7 @@ avoided.
In general, the best way to achieve this is to make the test and the
reference identical in as many aspects as possible. For example:
- Good test Markup:
+ Good test markup:
@@ -163,3 +163,24 @@ reference identical in as many aspects as possible. For example:
+
+Asynchronous Tests
+==================
+
+Normally reftest takes a snapshot of the given markup's rendering right
+after the load event fires for content. If your test needs to postpone
+the moment the snapshot is taken, it should make sure a class
+'reftest-wait' is on the root element by the moment the load event
+fires. The easiest way to do this is to put it in the markup, e.g.:
+
+
+When your test is ready, you should remove this class from the root
+element, for example using this code:
+ document.documentElement.className = "";
+
+
+Note that in layout tests it is often enough to trigger layout using
+ document.body.offsetWidth // HTML example
+
+When possible, you should use this technique instead of making your
+test async.
diff --git a/mozilla/layout/tools/reftest/reftest.js b/mozilla/layout/tools/reftest/reftest.js
index bec6721135c..da408b7659c 100644
--- a/mozilla/layout/tools/reftest/reftest.js
+++ b/mozilla/layout/tools/reftest/reftest.js
@@ -203,16 +203,39 @@ function OnDocumentLoad(event)
// Ignore load events for subframes.
return;
- clearTimeout(gFailureTimeout);
- // Since we can't use a bubbling-phase load listener from chrome,
- // this is a capturing phase listener. So do setTimeout twice, the
- // first to get us after the onload has fired in the content, and
- // the second to get us after any setTimeout(foo, 0) in the content.
- setTimeout(setTimeout, 0, DocumentLoaded, 0);
+ function shouldWait() {
+ return contentRootElement.className.split(/\s+/)
+ .indexOf("reftest-wait") != -1;
+ }
+
+ var contentRootElement = gBrowser.contentDocument.documentElement;
+ if (shouldWait()) {
+ // The testcase will let us know when the test snapshot should be made.
+ // Register a mutation listener to know when the 'reftest-wait' class
+ // gets removed.
+ contentRootElement.addEventListener(
+ "DOMAttrModified",
+ function(event) {
+ if (!shouldWait()) {
+ contentRootElement.removeEventListener(
+ "DOMAttrModified",
+ arguments.callee,
+ false);
+ setTimeout(DocumentLoaded, 0);
+ }
+ }, false);
+ } else {
+ // Since we can't use a bubbling-phase load listener from chrome,
+ // this is a capturing phase listener. So do setTimeout twice, the
+ // first to get us after the onload has fired in the content, and
+ // the second to get us after any setTimeout(foo, 0) in the content.
+ setTimeout(setTimeout, 0, DocumentLoaded, 0);
+ }
}
function DocumentLoaded()
{
+ clearTimeout(gFailureTimeout);
var key = IFrameToKey();
switch (gState) {
case 1: