Import W3C tests for requestidlecallback
https://bugs.webkit.org/show_bug.cgi?id=202946

Reviewed by Wenson Hsieh.

LayoutTests/imported/w3c:

Imported web platform tests for requestidlecallback as of 38c2e8d53c9e54f5c4a914d1528aff4e60f07cdf.

* resources/import-expectations.json:
* web-platform-tests/requestidlecallback/META.yml: Added.
* web-platform-tests/requestidlecallback/basic-expected.txt: Added.
* web-platform-tests/requestidlecallback/basic.html: Added.
* web-platform-tests/requestidlecallback/callback-exception-expected.txt: Added.
* web-platform-tests/requestidlecallback/callback-exception.html: Added.
* web-platform-tests/requestidlecallback/callback-idle-periods-expected.txt: Added.
* web-platform-tests/requestidlecallback/callback-idle-periods.html: Added.
* web-platform-tests/requestidlecallback/callback-iframe-expected.txt: Added.
* web-platform-tests/requestidlecallback/callback-iframe.html: Added.
* web-platform-tests/requestidlecallback/callback-invoked-expected.txt: Added.
* web-platform-tests/requestidlecallback/callback-invoked.html: Added.
* web-platform-tests/requestidlecallback/callback-multiple-calls-expected.txt: Added.
* web-platform-tests/requestidlecallback/callback-multiple-calls.html: Added.
* web-platform-tests/requestidlecallback/callback-removed-frame-expected.txt: Added.
* web-platform-tests/requestidlecallback/callback-removed-frame.html: Added.
* web-platform-tests/requestidlecallback/callback-suspended-expected.txt: Added.
* web-platform-tests/requestidlecallback/callback-suspended.html: Added.
* web-platform-tests/requestidlecallback/callback-timeout-expected.txt: Added.
* web-platform-tests/requestidlecallback/callback-timeout-when-busy-expected.txt: Added.
* web-platform-tests/requestidlecallback/callback-timeout-when-busy.html: Added.
* web-platform-tests/requestidlecallback/callback-timeout.html: Added.
* web-platform-tests/requestidlecallback/callback-xhr-sync-expected.txt: Added.
* web-platform-tests/requestidlecallback/callback-xhr-sync.html: Added.
* web-platform-tests/requestidlecallback/cancel-invoked-expected.txt: Added.
* web-platform-tests/requestidlecallback/cancel-invoked.html: Added.
* web-platform-tests/requestidlecallback/idlharness.window-expected.txt: Added.
* web-platform-tests/requestidlecallback/idlharness.window.html: Added.
* web-platform-tests/requestidlecallback/idlharness.window.js: Added.
(async.idl_array.await.new.Promise.resolve.resolve):
* web-platform-tests/requestidlecallback/resources/post_name_on_load.html: Added.
* web-platform-tests/requestidlecallback/resources/w3c-import.log: Added.
* web-platform-tests/requestidlecallback/w3c-import.log: Added.

LayoutTests:

* tests-options.json:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@251120 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 5c58c09..754b2e9 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,12 @@
+2019-10-14  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Import W3C tests for requestidlecallback
+        https://bugs.webkit.org/show_bug.cgi?id=202946
+
+        Reviewed by Wenson Hsieh.
+
+        * tests-options.json:
+
 2019-10-14  Said Abou-Hallawa  <sabouhallawa@apple.com>
 
         Outsets for referenced SVG filters are always zero
diff --git a/LayoutTests/imported/w3c/ChangeLog b/LayoutTests/imported/w3c/ChangeLog
index a04a033..ef1905e 100644
--- a/LayoutTests/imported/w3c/ChangeLog
+++ b/LayoutTests/imported/w3c/ChangeLog
@@ -1,3 +1,46 @@
+2019-10-14  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Import W3C tests for requestidlecallback
+        https://bugs.webkit.org/show_bug.cgi?id=202946
+
+        Reviewed by Wenson Hsieh.
+
+        Imported web platform tests for requestidlecallback as of 38c2e8d53c9e54f5c4a914d1528aff4e60f07cdf.
+
+        * resources/import-expectations.json:
+        * web-platform-tests/requestidlecallback/META.yml: Added.
+        * web-platform-tests/requestidlecallback/basic-expected.txt: Added.
+        * web-platform-tests/requestidlecallback/basic.html: Added.
+        * web-platform-tests/requestidlecallback/callback-exception-expected.txt: Added.
+        * web-platform-tests/requestidlecallback/callback-exception.html: Added.
+        * web-platform-tests/requestidlecallback/callback-idle-periods-expected.txt: Added.
+        * web-platform-tests/requestidlecallback/callback-idle-periods.html: Added.
+        * web-platform-tests/requestidlecallback/callback-iframe-expected.txt: Added.
+        * web-platform-tests/requestidlecallback/callback-iframe.html: Added.
+        * web-platform-tests/requestidlecallback/callback-invoked-expected.txt: Added.
+        * web-platform-tests/requestidlecallback/callback-invoked.html: Added.
+        * web-platform-tests/requestidlecallback/callback-multiple-calls-expected.txt: Added.
+        * web-platform-tests/requestidlecallback/callback-multiple-calls.html: Added.
+        * web-platform-tests/requestidlecallback/callback-removed-frame-expected.txt: Added.
+        * web-platform-tests/requestidlecallback/callback-removed-frame.html: Added.
+        * web-platform-tests/requestidlecallback/callback-suspended-expected.txt: Added.
+        * web-platform-tests/requestidlecallback/callback-suspended.html: Added.
+        * web-platform-tests/requestidlecallback/callback-timeout-expected.txt: Added.
+        * web-platform-tests/requestidlecallback/callback-timeout-when-busy-expected.txt: Added.
+        * web-platform-tests/requestidlecallback/callback-timeout-when-busy.html: Added.
+        * web-platform-tests/requestidlecallback/callback-timeout.html: Added.
+        * web-platform-tests/requestidlecallback/callback-xhr-sync-expected.txt: Added.
+        * web-platform-tests/requestidlecallback/callback-xhr-sync.html: Added.
+        * web-platform-tests/requestidlecallback/cancel-invoked-expected.txt: Added.
+        * web-platform-tests/requestidlecallback/cancel-invoked.html: Added.
+        * web-platform-tests/requestidlecallback/idlharness.window-expected.txt: Added.
+        * web-platform-tests/requestidlecallback/idlharness.window.html: Added.
+        * web-platform-tests/requestidlecallback/idlharness.window.js: Added.
+        (async.idl_array.await.new.Promise.resolve.resolve):
+        * web-platform-tests/requestidlecallback/resources/post_name_on_load.html: Added.
+        * web-platform-tests/requestidlecallback/resources/w3c-import.log: Added.
+        * web-platform-tests/requestidlecallback/w3c-import.log: Added.
+
 2019-10-14  Youenn Fablet  <youenn@apple.com>
 
         A response body promise should be rejected in case of a failure happening after the HTTP response
diff --git a/LayoutTests/imported/w3c/resources/import-expectations.json b/LayoutTests/imported/w3c/resources/import-expectations.json
index c717282..3a73d46 100644
--- a/LayoutTests/imported/w3c/resources/import-expectations.json
+++ b/LayoutTests/imported/w3c/resources/import-expectations.json
@@ -308,7 +308,7 @@
     "web-platform-tests/quirks/unitless-length": "import", 
     "web-platform-tests/referrer-policy": "import", 
     "web-platform-tests/remote-playback": "skip", 
-    "web-platform-tests/requestidlecallback": "skip", 
+    "web-platform-tests/requestidlecallback": "import", 
     "web-platform-tests/resize-observer": "skip", 
     "web-platform-tests/resize-observer/": "import", 
     "web-platform-tests/resource-timing": "import", 
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/META.yml b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/META.yml
new file mode 100644
index 0000000..9c829d3
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/META.yml
@@ -0,0 +1,4 @@
+spec: https://w3c.github.io/requestidlecallback/
+suggested_reviewers:
+  - farre
+  - rmcilroy
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/basic-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/basic-expected.txt
new file mode 100644
index 0000000..983c6e12
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/basic-expected.txt
@@ -0,0 +1,10 @@
+Basic requestIdleCallback Tests
+
+
+PASS window.requestIdleCallback is defined 
+PASS window.cancelIdleCallback is defined 
+PASS window.requestIdleCallback() returns a number 
+PASS window.cancelIdleCallback() returns undefined 
+FAIL requestIdleCallback schedules callbacks assert_true: IdleDeadline.timeRemaining() MUST be less than or equal to 50ms in the future. expected true got false
+PASS cancelIdleCallback cancels callbacks 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/basic.html b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/basic.html
new file mode 100644
index 0000000..267ada2
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/basic.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:RequestIdleCallbackEnabled=true ] -->
+<title>window.requestIdleCallback exists</title>
+<link rel="author" title="Ross McIlroy" href="mailto:rmcilroy@chromium.org" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+// The window.requestIdleCallback function is used to request callbacks during browser-defined idle time.
+test(function() {
+  assert_equals(typeof window.requestIdleCallback, "function");
+}, "window.requestIdleCallback is defined");
+
+// The window.cancelIdleCallback function is used to cancel callbacks scheduled via requestIdleCallback.
+test(function() {
+  assert_equals(typeof window.cancelIdleCallback, "function");
+}, "window.cancelIdleCallback is defined");
+
+// The requestIdleCallback method MUST return a long
+test(function() {
+  assert_equals(typeof window.requestIdleCallback(function() {}), "number");
+}, "window.requestIdleCallback() returns a number");
+
+// The cancelIdleCallback method MUST return void
+test(function() {
+  assert_equals(typeof window.cancelIdleCallback(1), "undefined");
+}, "window.cancelIdleCallback() returns undefined");
+
+async_test(function() {
+  // Check whether requestIdleCallback schedules a callback which gets executed
+  // and the deadline argument is passed correctly.
+  requestIdleCallback(this.step_func_done(function(deadline) {
+    assert_equals(arguments.length, 1, "Only one argument should be passed to callback.");
+    assert_class_string(deadline, "IdleDeadline");
+    assert_equals(typeof deadline.timeRemaining, "function", "IdleDeadline.timeRemaining MUST be a function which returns the time remaining in milliseconds");
+    assert_equals(typeof deadline.timeRemaining(), "number", "IdleDeadline.timeRemaining MUST return a double of the time remaining in milliseconds");
+    assert_true(deadline.timeRemaining() <= 50, "IdleDeadline.timeRemaining() MUST be less than or equal to 50ms in the future.");
+    assert_equals(typeof deadline.didTimeout, "boolean", "IdleDeadline.didTimeout MUST be a boolean");
+    assert_false(deadline.didTimeout, "IdleDeadline.didTimeout MUST be false if requestIdleCallback wasn't scheduled due to a timeout");
+  }));
+}, 'requestIdleCallback schedules callbacks');
+
+async_test(function() {
+  // Check whether requestIdleCallback schedules a callback which gets executed
+  // and the deadline argument is passed correctly.
+  var handle = requestIdleCallback(this.step_func(function(deadline) {
+    assert_unreached("callback should not be called if canceled with cancelIdleCallback");
+  }));
+  cancelIdleCallback(handle);
+  step_timeout(this.step_func_done(), 200);
+}, 'cancelIdleCallback cancels callbacks');
+
+</script>
+<h1>Basic requestIdleCallback Tests</h1>
+<div id="log"></div>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-exception-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-exception-expected.txt
new file mode 100644
index 0000000..450dba6
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-exception-expected.txt
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: line 19: Error: requestIdleCallbackException
+
+PASS requestIdleCallback callback exceptions are reported to error handler 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-exception.html b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-exception.html
new file mode 100644
index 0000000..8566fca
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-exception.html
@@ -0,0 +1,22 @@
+<!doctype html><!-- webkit-test-runner [ experimental:RequestIdleCallbackEnabled=true ] -->
+<meta charset=utf-8>
+<title>requestIdleCallback callback exception reported to error handler</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id="log"></div>
+<script>
+  var custom_exception = 'requestIdleCallbackException';
+  setup({allow_uncaught_exception : true});
+  async_test(function (t) {
+    assert_false(document.hidden, "document.hidden must exist and be false to run this test properly");
+    addEventListener("error",function(e) {
+      t.step(function() {
+        assert_equals(e.error.message, custom_exception);
+        t.done();
+      })
+    });
+    window.requestIdleCallback(function () {
+      throw new Error(custom_exception);
+    });
+  }, "requestIdleCallback callback exceptions are reported to error handler");
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-idle-periods-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-idle-periods-expected.txt
new file mode 100644
index 0000000..5d43a00
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-idle-periods-expected.txt
@@ -0,0 +1,9 @@
+Test of requestIdleCallback idle period behavior
+
+This test validates that window.requestIdleCallback deals with callbacks during idle periods correctly.
+
+
+Harness Error (TIMEOUT), message = null
+
+TIMEOUT Check that if an idle callback calls requestIdleCallback the new callback doesn't run in the current idle period. Test timed out
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-idle-periods.html b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-idle-periods.html
new file mode 100644
index 0000000..4753be5
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-idle-periods.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:RequestIdleCallbackEnabled=true ] -->
+<title>window.requestIdleCallback callback behavior during idle periods.</title>
+<link rel="author" title="Ross McIlroy" href="mailto:rmcilroy@chromium.org" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+async_test(function() {
+  // Check that if an idle callback calls requestIdleCallback, the new callback
+  // doesn't get the same deadline (i.e., runs in a new idle period).
+  var previous_deadline = undefined;
+  var idle_callbacks_remaining = 10;
+  var rIC = this.step_func(function(deadline) {
+    var now = performance.now();
+    var remaining = deadline.timeRemaining();
+    var new_deadline = now + remaining;
+    if (previous_deadline != undefined) {
+      assert_true(new_deadline > previous_deadline, "A requestIdleCallback scheduled during an idle period should be called back with a deadline greater than that in the current idle period.");
+    }
+
+    // Schedule a new requestIdleCallback.
+    if (--idle_callbacks_remaining > 0) {
+      previous_deadline = new_deadline;
+      requestIdleCallback(rIC);
+    } else {
+      this.done();
+    }
+  });
+
+  // Spin an empty rAF loop to cause an idle period each frame.
+  var idle_task_posted = false;
+  requestAnimationFrame(function rAFLoop() {
+    if (!idle_task_posted) {
+      requestIdleCallback(rIC);
+      idle_task_posted = true;
+    }
+    requestAnimationFrame(rAFLoop);
+  });
+}, 'Check that if an idle callback calls requestIdleCallback the new callback doesn\'t run in the current idle period.');
+</script>
+<h1>Test of requestIdleCallback idle period behavior</h1>
+<p>This test validates that window.requestIdleCallback deals with callbacks during idle periods correctly.</p>
+<div id="log"></div>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-iframe-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-iframe-expected.txt
new file mode 100644
index 0000000..b5cff193
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-iframe-expected.txt
@@ -0,0 +1,3 @@
+
+PASS callback-iframe 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-iframe.html b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-iframe.html
new file mode 100644
index 0000000..64a7222
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-iframe.html
@@ -0,0 +1,18 @@
+<!doctype html><!-- webkit-test-runner [ experimental:RequestIdleCallbackEnabled=true ] -->
+<meta charset=utf-8>
+<title></title>
+<meta name="timeout" content="long">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id="log"></div>
+<iframe style="display:none" id="frame"></iframe>
+<script>
+  async_test(function (t) {
+    let frame = document.getElementById("frame");
+    frame.contentWindow.test = function() {
+      frame.contentWindow.requestIdleCallback(t.step_func_done());
+    }
+
+    frame.contentWindow.test();
+  });
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-invoked-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-invoked-expected.txt
new file mode 100644
index 0000000..e9658b9
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-invoked-expected.txt
@@ -0,0 +1,3 @@
+
+PASS requestIdleCallback callback is invoked at least once before the timeout 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-invoked.html b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-invoked.html
new file mode 100644
index 0000000..e775609
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-invoked.html
@@ -0,0 +1,12 @@
+<!doctype html><!-- webkit-test-runner [ experimental:RequestIdleCallbackEnabled=true ] -->
+<meta charset=utf-8>
+<title>requestIdleCallback callback must be called eventually</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id="log"></div>
+<script>
+  async_test(function (t) {
+    assert_false(document.hidden, "document.hidden must exist and be false to run this test properly");
+    window.requestIdleCallback(t.step_func_done());
+  }, "requestIdleCallback callback is invoked at least once before the timeout");
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-multiple-calls-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-multiple-calls-expected.txt
new file mode 100644
index 0000000..c2b1bb4
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-multiple-calls-expected.txt
@@ -0,0 +1,6 @@
+
+Harness Error (TIMEOUT), message = null
+
+PASS requestIdleCallback callbacks should be invoked in order (called iteratively) 
+TIMEOUT requestIdleCallback callbacks should be invoked in order (called recursively) Test timed out
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-multiple-calls.html b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-multiple-calls.html
new file mode 100644
index 0000000..068153d
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-multiple-calls.html
@@ -0,0 +1,46 @@
+<!doctype html><!-- webkit-test-runner [ experimental:RequestIdleCallbackEnabled=true ] -->
+<meta charset=utf-8>
+<title>multiple calls to requestIdleCallback</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id="log"></div>
+<script>
+  let option = {timeout: 50};
+
+  async_test(function (t) {
+    assert_false(document.hidden, "document.hidden must exist and be false to run this test properly");
+    var counter = 0;
+    function f(c) {
+      assert_equals(counter, c);
+      if (counter === 49) {
+        t.done();
+      }
+
+      ++counter;
+    }
+    for (var i = 0; i < 100; ++i) {
+      let j = i;
+      window.requestIdleCallback(t.step_func(function () { f(j) }), option);
+    }
+  }, "requestIdleCallback callbacks should be invoked in order (called iteratively)");
+
+  async_test(function (t) {
+    assert_false(document.hidden, "document.hidden must exist and be false to run this test properly");
+    var counter = 0;
+
+    function f(c) {
+      assert_equals(counter, c);
+      if (counter === 49) {
+        t.done();
+      }
+
+      ++counter;
+      window.requestIdleCallback(t.step_func(function () { f(c + 1) }), option);
+    }
+
+    window.requestIdleCallback(t.step_func(function () { f(0) }), option);
+  }, "requestIdleCallback callbacks should be invoked in order (called recursively)");
+
+  let generateIdlePeriods = _ => requestAnimationFrame(generateIdlePeriods);
+  generateIdlePeriods();
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-removed-frame-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-removed-frame-expected.txt
new file mode 100644
index 0000000..1e60e9b
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-removed-frame-expected.txt
@@ -0,0 +1,3 @@
+
+PASS calling requestIdleCallback on a contentWindow from a removed iframe should not trigger the callback 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-removed-frame.html b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-removed-frame.html
new file mode 100644
index 0000000..64a25df
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-removed-frame.html
@@ -0,0 +1,30 @@
+<!doctype html><!-- webkit-test-runner [ experimental:RequestIdleCallbackEnabled=true ] -->
+<meta charset=utf-8>
+<title>requestIdleCallback on removed frame shouldn't call back</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+  async_test(function (t) {
+    assert_false(document.hidden, "document.hidden must exist and be false to run this test properly");
+
+    function start() {
+      var frame = document.createElement('iframe');
+      frame.addEventListener('load', _ => connect(frame), {once:true});
+      frame.src = "about:blank";
+      document.body.appendChild(frame);
+    }
+
+    function connect(frame) {
+      var contentWindow = frame.contentWindow;
+      contentWindow.requestIdleCallback(_ => callback0(frame, contentWindow));
+      t.step_timeout(function() { t.done(); }, 1000);
+    }
+
+    function callback0(f, w) {
+      document.body.removeChild(f);
+      w.requestIdleCallback(t.unreached_func("requestIdleCallback callback should not trigger the callback"));
+    }
+
+    addEventListener('load', start, {once:true});
+  }, "calling requestIdleCallback on a contentWindow from a removed iframe should not trigger the callback");
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-suspended-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-suspended-expected.txt
new file mode 100644
index 0000000..f202b7c
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-suspended-expected.txt
@@ -0,0 +1,3 @@
+
+PASS Dispatching idle callbacks should be able to be suspended and then resumed 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-suspended.html b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-suspended.html
new file mode 100644
index 0000000..e0b641b
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-suspended.html
@@ -0,0 +1,94 @@
+<!doctype html><!-- webkit-test-runner [ experimental:RequestIdleCallbackEnabled=true ] -->
+<meta charset=utf-8>
+<title>Dispatching idle callbacks should be able to be suspended and then resumed</title>
+<meta name="timeout" content="long">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id="log"></div>
+<script>
+  function withEventListener(target, event, handler) {
+    handler = handler || (e => e);
+    return new Promise(resolve => {
+      let wrapper = function(e) {
+        let result = handler(e);
+        if (!result) {
+          return;
+        }
+
+        resolve(result);
+      }
+      target.addEventListener(event, wrapper, { once: true });
+    });
+  }
+
+  function makePostBackUrl(name) {
+    return new URL('resources/post_name_on_load.html?name=' + name,
+                   window.location).href;
+  }
+
+  function waitForMessage(message, handler) {
+    return withEventListener(window, 'message', e => (e.data === message) && handler(e));;
+  }
+
+  function withWindow(name) {
+    let win = window.open(makePostBackUrl(name))
+    return waitForMessage(name, _ => win);
+  }
+
+  function navigateWindow(win, name) {
+    win.location = makePostBackUrl(name);
+    return waitForMessage(name, _ => win);
+  }
+
+  function waitDuration(delay) {
+    return new Promise(resolve => {
+      step_timeout(resolve, delay);
+    })
+  }
+
+  function goBack(win) {
+    var p = withEventListener(win, 'pagehide');
+    win.history.back();
+    return p;
+  }
+
+  promise_test(t => {
+    let idleCalled = false;
+    let running = true;
+    return withWindow('foo')
+      .then(win => {
+        let callback = function(d) {
+          idleCalled = true;
+          if (running) {
+            win.requestIdleCallback(callback);
+          }
+        };
+
+        win.requestIdleCallback(callback);
+
+        return navigateWindow(win, 'bar')
+          .then(_ => idleCalled = false)
+          .then(_ => waitDuration(2000))
+          .then(_ => {
+            assert_false(idleCalled, "idle callback shouldn't have been called yet");
+            return goBack(win);
+          })
+          .then(_ => Promise.race([
+            // At this point it's a matter of having bfcache ...
+            waitDuration(2000)
+              .then(_ => {
+                assert_true(idleCalled, "idle callback should've been called by now");
+                running = false;
+              }),
+            // ... or not. If not, we expect a load event.
+            waitForMessage("foo", _ => win)
+          ]))
+          .then(_ => win.close())
+          .catch(e => {
+            win.close();
+            throw e;
+          })
+      });
+  });
+
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-timeout-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-timeout-expected.txt
new file mode 100644
index 0000000..d430405
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-timeout-expected.txt
@@ -0,0 +1,4 @@
+
+FAIL requestIdleCallback callback should time out assert_false: expected false got true
+FAIL requestIdleCallback callback should not time out assert_false: expected false got true
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-timeout-when-busy-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-timeout-when-busy-expected.txt
new file mode 100644
index 0000000..19a49ca
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-timeout-when-busy-expected.txt
@@ -0,0 +1,6 @@
+Test of requestIdleCallback timeout behavior
+
+
+FAIL requestIdleCallback not scheduled when event loop is busy. assert_false: IdleDeadline.didTimeout MUST be false if requestIdleCallback wasn't scheduled due to a timeout expected false got true
+FAIL requestIdleCallback scheduled with timeout when event loop is busy. assert_true: Should only have been run after timeout expected true got false
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-timeout-when-busy.html b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-timeout-when-busy.html
new file mode 100644
index 0000000..7f1191f
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-timeout-when-busy.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:RequestIdleCallbackEnabled=true ] -->
+<title>window.requestIdleCallback deals with timeouts correctly</title>
+<meta name="timeout" content="long">
+<link rel="author" title="Ross McIlroy" href="mailto:rmcilroy@chromium.org" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+async_test(function() {
+  // Check whether requestIdleCallback with a timeout works when the event loop
+  // is busy.
+  var busy_loop_iterations_remaining = 10;  // Should take 20 * 40 = 400ms
+  var idle_callback_scheduled;
+  var idle_callback = this.step_func_done(function(deadline) {
+    assert_false(deadline.didTimeout, "IdleDeadline.didTimeout MUST be false if requestIdleCallback wasn't scheduled due to a timeout");
+    assert_equals(busy_loop_iterations_remaining, 0, "Busy event loop should be finished by the time we get scheduled");
+  });
+
+  var busy_loop_iterations_remaining = 10;  // Should take 20 * 40 = 400ms
+  step_timeout(this.step_func(function busyLoop() {
+    var start_time = performance.now();
+    if (!idle_callback_scheduled) {
+      idle_callback_scheduled = start_time;
+      requestIdleCallback(idle_callback);
+    }
+
+    // Use up more than a frames worth of budget.
+    while (performance.now() - start_time < 40) {
+    }
+    if (busy_loop_iterations_remaining > 0) {
+      busy_loop_iterations_remaining--;
+      step_timeout(busyLoop);
+    }
+  }));
+}, 'requestIdleCallback not scheduled when event loop is busy.');
+
+async_test(function() {
+  // Check whether requestIdleCallback with a timeout works when the event loop
+  // is busy.
+  var busy_loop_iterations_remaining = 10;  // Should take 20 * 40 = 400ms
+  var timeout = 200;
+  var idle_callback_scheduled;
+  var idle_callback = this.step_func_done(function(deadline) {
+    var time_delta = performance.now() - idle_callback_scheduled;
+    assert_true(time_delta >= timeout, "Should only have been run after timeout");
+    assert_true(deadline.timeRemaining() == 0, "IdleDeadline.timeRemaining MUST be equal to zero if requestIdleCallback was scheduled due to a timeout");
+    assert_true(deadline.didTimeout, "IdleDeadline.didTimeout MUST be true if requestIdleCallback was scheduled due to a timeout");
+    assert_true(busy_loop_iterations_remaining > 0, "Busy event loop should still be going");
+  });
+
+  step_timeout(this.step_func(function busyLoop() {
+    var start_time = performance.now();
+    if (!idle_callback_scheduled) {
+      idle_callback_scheduled = start_time;
+      requestIdleCallback(idle_callback, { timeout: timeout });
+    }
+
+    // Use up more than a frames worth of budget.
+    while (performance.now() - start_time < 40) {
+    }
+    if (busy_loop_iterations_remaining > 0) {
+      busy_loop_iterations_remaining--;
+      step_timeout(busyLoop);
+    }
+  }));
+}, 'requestIdleCallback scheduled with timeout when event loop is busy.');
+
+</script>
+<h1>Test of requestIdleCallback timeout behavior</h1>
+<div id="log"></div>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-timeout.html b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-timeout.html
new file mode 100644
index 0000000..8c32438
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-timeout.html
@@ -0,0 +1,44 @@
+<!doctype html><!-- webkit-test-runner [ experimental:RequestIdleCallbackEnabled=true ] -->
+<meta charset=utf-8>
+<title>requestIdleCallback timeout callback must be called with didTimeout equal to true</title>
+<meta name="timeout" content="long">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id="log"></div>
+<script>
+  async_test(function (t) {
+    assert_false(document.hidden, "document.hidden must exist and be false to run this test properly");
+    var counter = 0;
+
+    function g(deadline) {
+      assert_true(deadline.didTimeout)
+      t.done();
+    }
+
+    function f(deadline) {
+      assert_false(deadline.didTimeout);
+      window.requestIdleCallback(t.step_func(g), {timeout:300});
+
+      var d = Date.now() + 500;
+      while (Date.now() < d) {
+
+      }
+    }
+    window.requestIdleCallback(t.step_func(f));
+  }, "requestIdleCallback callback should time out");
+
+  async_test(function (t) {
+    assert_false(document.hidden, "document.hidden must exist and be false to run this test properly");
+    function g(deadline) {
+      assert_false(deadline.didTimeout)
+      t.done();
+    }
+
+    function f(deadline) {
+      assert_false(deadline.didTimeout);
+      window.requestIdleCallback(t.step_func(g), {timeout:100000});
+    }
+    window.requestIdleCallback(t.step_func(f));
+  }, "requestIdleCallback callback should not time out");
+
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-xhr-sync-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-xhr-sync-expected.txt
new file mode 100644
index 0000000..c75fdbf
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-xhr-sync-expected.txt
@@ -0,0 +1,5 @@
+
+Harness Error (TIMEOUT), message = null
+
+TIMEOUT re-schedule idle callbacks after sync xhr Test timed out
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-xhr-sync.html b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-xhr-sync.html
new file mode 100644
index 0000000..05c6d10
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-xhr-sync.html
@@ -0,0 +1,17 @@
+<!doctype html><!-- webkit-test-runner [ experimental:RequestIdleCallbackEnabled=true ] -->
+<meta charset=utf-8>
+<title></title>
+<meta name="timeout" content="long">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+  async_test(function (t) {
+    requestIdleCallback(function() {
+      requestIdleCallback(t.step_func_done(function () {}))
+      var xhr = new XMLHttpRequest();
+      xhr.open("GET", "www.emample.com", false);
+      xhr.onload = t.step_func(function () {});
+      xhr.send(null);
+    });
+  }, "re-schedule idle callbacks after sync xhr");
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/cancel-invoked-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/cancel-invoked-expected.txt
new file mode 100644
index 0000000..4d54cf1
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/cancel-invoked-expected.txt
@@ -0,0 +1,5 @@
+
+PASS cancelIdleCallback does nothing if there is no callback with the given handle 
+PASS A cancelled callback is never invoked 
+PASS Cancelling the currently executing idle callback should be allowed 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/cancel-invoked.html b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/cancel-invoked.html
new file mode 100644
index 0000000..ef15076
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/cancel-invoked.html
@@ -0,0 +1,32 @@
+<!doctype html><!-- webkit-test-runner [ experimental:RequestIdleCallbackEnabled=true ] -->
+<meta charset=utf-8>
+<title>cancelling idle requests</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id="log"></div>
+<script>
+  test(function (t) {
+    window.cancelIdleCallback(42);
+    assert_true(true);
+  }, "cancelIdleCallback does nothing if there is no callback with the given handle");
+
+  async_test(function (t) {
+    assert_false(document.hidden, "document.hidden must exist and be false to run this test properly");
+    var neverCalled = true;
+    var handle = window.requestIdleCallback(function () {
+      neverCalled = false;
+    });
+    window.cancelIdleCallback(handle);
+
+    t.step_timeout(function() {
+      assert_true(neverCalled);
+      t.done();
+    }, 2000);
+  }, "A cancelled callback is never invoked");
+
+  async_test(function (t) {
+    var handle = requestIdleCallback(t.step_func_done(function () {
+      cancelIdleCallback(handle);
+    }));
+  }, "Cancelling the currently executing idle callback should be allowed");
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/idlharness.window-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/idlharness.window-expected.txt
new file mode 100644
index 0000000..6e52c6d
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/idlharness.window-expected.txt
@@ -0,0 +1,22 @@
+
+PASS idl_test setup 
+PASS Partial interface Window: original interface defined 
+PASS IdleDeadline interface: existence and properties of interface object 
+PASS IdleDeadline interface object length 
+PASS IdleDeadline interface object name 
+PASS IdleDeadline interface: existence and properties of interface prototype object 
+PASS IdleDeadline interface: existence and properties of interface prototype object's "constructor" property 
+PASS IdleDeadline interface: existence and properties of interface prototype object's @@unscopables property 
+PASS IdleDeadline interface: operation timeRemaining() 
+PASS IdleDeadline interface: attribute didTimeout 
+PASS IdleDeadline must be primary interface of deadline 
+PASS Stringification of deadline 
+PASS IdleDeadline interface: deadline must inherit property "timeRemaining()" with the proper type 
+PASS IdleDeadline interface: deadline must inherit property "didTimeout" with the proper type 
+PASS Window interface: operation requestIdleCallback(IdleRequestCallback, IdleRequestOptions) 
+PASS Window interface: operation cancelIdleCallback(unsigned long) 
+PASS Window interface: window must inherit property "requestIdleCallback(IdleRequestCallback, IdleRequestOptions)" with the proper type 
+PASS Window interface: calling requestIdleCallback(IdleRequestCallback, IdleRequestOptions) on window with too few arguments must throw TypeError 
+PASS Window interface: window must inherit property "cancelIdleCallback(unsigned long)" with the proper type 
+PASS Window interface: calling cancelIdleCallback(unsigned long) on window with too few arguments must throw TypeError 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/idlharness.window.html b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/idlharness.window.html
new file mode 100644
index 0000000..4c8b289
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/idlharness.window.html
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test --><!-- webkit-test-runner [ experimental:RequestIdleCallbackEnabled=true ] -->
\ No newline at end of file
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/idlharness.window.js b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/idlharness.window.js
new file mode 100644
index 0000000..69cd5a4
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/idlharness.window.js
@@ -0,0 +1,24 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+// https://w3c.github.io/requestidlecallback/
+
+'use strict';
+
+idl_test(
+  ['requestidlecallback'],
+  ['html', 'dom'],
+  async idl_array => {
+    idl_array.add_objects({
+      IdleDeadline: ['deadline'],
+      Window: ['window'],
+    });
+
+    await new Promise(resolve => {
+      requestIdleCallback(d => {
+        self.deadline = d;
+        resolve();
+      }, { timeout: 100 });
+    });
+  }
+);
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/resources/post_name_on_load.html b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/resources/post_name_on_load.html
new file mode 100644
index 0000000..4679a6e
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/resources/post_name_on_load.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<script>
+  addEventListener('load', _ => {
+    let params = new URLSearchParams(window.location.search);
+    window.opener.postMessage(params.get('name'), '*');
+  });
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/resources/w3c-import.log b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/resources/w3c-import.log
new file mode 100644
index 0000000..4c4d4e6
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/resources/w3c-import.log
@@ -0,0 +1,17 @@
+The tests in this directory were imported from the W3C repository.
+Do NOT modify these tests directly in WebKit.
+Instead, create a pull request on the WPT github:
+	https://github.com/web-platform-tests/wpt
+
+Then run the Tools/Scripts/import-w3c-tests in WebKit to reimport
+
+Do NOT modify or remove this file.
+
+------------------------------------------------------------------------
+Properties requiring vendor prefixes:
+None
+Property values requiring vendor prefixes:
+None
+------------------------------------------------------------------------
+List of files:
+/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/resources/post_name_on_load.html
diff --git a/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/w3c-import.log b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/w3c-import.log
new file mode 100644
index 0000000..d9da438
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/w3c-import.log
@@ -0,0 +1,30 @@
+The tests in this directory were imported from the W3C repository.
+Do NOT modify these tests directly in WebKit.
+Instead, create a pull request on the WPT github:
+	https://github.com/web-platform-tests/wpt
+
+Then run the Tools/Scripts/import-w3c-tests in WebKit to reimport
+
+Do NOT modify or remove this file.
+
+------------------------------------------------------------------------
+Properties requiring vendor prefixes:
+None
+Property values requiring vendor prefixes:
+None
+------------------------------------------------------------------------
+List of files:
+/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/META.yml
+/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/basic.html
+/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-exception.html
+/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-idle-periods.html
+/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-iframe.html
+/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-invoked.html
+/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-multiple-calls.html
+/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-removed-frame.html
+/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-suspended.html
+/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-timeout-when-busy.html
+/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-timeout.html
+/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/callback-xhr-sync.html
+/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/cancel-invoked.html
+/LayoutTests/imported/w3c/web-platform-tests/requestidlecallback/idlharness.window.js
diff --git a/LayoutTests/tests-options.json b/LayoutTests/tests-options.json
index 52ebd65..8584f9e 100644
--- a/LayoutTests/tests-options.json
+++ b/LayoutTests/tests-options.json
@@ -1802,6 +1802,21 @@
     "imported/w3c/web-platform-tests/quirks/hashless-hex-color.html": [
         "slow"
     ],
+    "imported/w3c/web-platform-tests/requestidlecallback/callback-iframe.html": [
+        "slow"
+    ],
+    "imported/w3c/web-platform-tests/requestidlecallback/callback-suspended.html": [
+        "slow"
+    ],
+    "imported/w3c/web-platform-tests/requestidlecallback/callback-timeout-when-busy.html": [
+        "slow"
+    ],
+    "imported/w3c/web-platform-tests/requestidlecallback/callback-timeout.html": [
+        "slow"
+    ],
+    "imported/w3c/web-platform-tests/requestidlecallback/callback-xhr-sync.html": [
+        "slow"
+    ],
     "imported/w3c/web-platform-tests/resource-timing/resource-timing-level1.sub.html": [
         "slow"
     ],