Import Resize Observer test cases from WPTs
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 29 Jan 2019 14:58:05 +0000 (14:58 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 29 Jan 2019 14:58:05 +0000 (14:58 +0000)
https://bugs.webkit.org/show_bug.cgi?id=193821

Patch by cathie chen <cathiechen@igalia.com> on 2019-01-29
Reviewed by Frédéric Wang.

* resources/import-expectations.json:
* web-platform-tests/resize-observer/META.yml: Added.
* web-platform-tests/resize-observer/eventloop-expected.txt: Added.
* web-platform-tests/resize-observer/eventloop.html: Added.
* web-platform-tests/resize-observer/idlharness.window-expected.txt: Added.
* web-platform-tests/resize-observer/idlharness.window.html: Added.
* web-platform-tests/resize-observer/idlharness.window.js: Added.
* web-platform-tests/resize-observer/notify-expected.txt: Added.
* web-platform-tests/resize-observer/notify.html: Added.
* web-platform-tests/resize-observer/observe-expected.txt: Added.
* web-platform-tests/resize-observer/observe.html: Added.
* web-platform-tests/resize-observer/resources/iframe.html: Added.
* web-platform-tests/resize-observer/resources/resizeTestHelper.js: Added.
(ResizeTestHelper):
(ResizeTestHelper.prototype.get _currentStep):
(ResizeTestHelper.prototype._nextStep):
(ResizeTestHelper.prototype._handleNotification):
(ResizeTestHelper.prototype._handleTimeout):
(ResizeTestHelper.prototype._done):
(ResizeTestHelper.prototype.start):
(ResizeTestHelper.prototype.get rafCount):
(ResizeTestHelper.prototype._incrementRaf):
(ResizeTestHelper.prototype.startCountingRaf):
* web-platform-tests/resize-observer/resources/w3c-import.log: Added.
* web-platform-tests/resize-observer/svg-expected.txt: Added.
* web-platform-tests/resize-observer/svg.html: Added.
* web-platform-tests/resize-observer/w3c-import.log: Added.

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

18 files changed:
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/resources/import-expectations.json
LayoutTests/imported/w3c/web-platform-tests/resize-observer/META.yml [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resize-observer/eventloop-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resize-observer/eventloop.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resize-observer/idlharness.window-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resize-observer/idlharness.window.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resize-observer/idlharness.window.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resize-observer/notify-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resize-observer/notify.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resize-observer/observe-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resize-observer/observe.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resize-observer/resources/iframe.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resize-observer/resources/resizeTestHelper.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resize-observer/resources/w3c-import.log [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resize-observer/svg-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resize-observer/svg.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resize-observer/w3c-import.log [new file with mode: 0644]

index caabb42..a6538c6 100644 (file)
@@ -1,3 +1,38 @@
+2019-01-29  cathie chen  <cathiechen@igalia.com>
+
+        Import Resize Observer test cases from WPTs
+        https://bugs.webkit.org/show_bug.cgi?id=193821
+
+        Reviewed by Frédéric Wang.
+
+        * resources/import-expectations.json:
+        * web-platform-tests/resize-observer/META.yml: Added.
+        * web-platform-tests/resize-observer/eventloop-expected.txt: Added.
+        * web-platform-tests/resize-observer/eventloop.html: Added.
+        * web-platform-tests/resize-observer/idlharness.window-expected.txt: Added.
+        * web-platform-tests/resize-observer/idlharness.window.html: Added.
+        * web-platform-tests/resize-observer/idlharness.window.js: Added.
+        * web-platform-tests/resize-observer/notify-expected.txt: Added.
+        * web-platform-tests/resize-observer/notify.html: Added.
+        * web-platform-tests/resize-observer/observe-expected.txt: Added.
+        * web-platform-tests/resize-observer/observe.html: Added.
+        * web-platform-tests/resize-observer/resources/iframe.html: Added.
+        * web-platform-tests/resize-observer/resources/resizeTestHelper.js: Added.
+        (ResizeTestHelper):
+        (ResizeTestHelper.prototype.get _currentStep):
+        (ResizeTestHelper.prototype._nextStep):
+        (ResizeTestHelper.prototype._handleNotification):
+        (ResizeTestHelper.prototype._handleTimeout):
+        (ResizeTestHelper.prototype._done):
+        (ResizeTestHelper.prototype.start):
+        (ResizeTestHelper.prototype.get rafCount):
+        (ResizeTestHelper.prototype._incrementRaf):
+        (ResizeTestHelper.prototype.startCountingRaf):
+        * web-platform-tests/resize-observer/resources/w3c-import.log: Added.
+        * web-platform-tests/resize-observer/svg-expected.txt: Added.
+        * web-platform-tests/resize-observer/svg.html: Added.
+        * web-platform-tests/resize-observer/w3c-import.log: Added.
+
 2019-01-28  Rob Buis  <rbuis@igalia.com>
 
         Update MIME type parser
index 6ec7ef4..70adea5 100644 (file)
     "web-platform-tests/remote-playback": "skip", 
     "web-platform-tests/requestidlecallback": "skip", 
     "web-platform-tests/resize-observer": "skip", 
+    "web-platform-tests/resize-observer/": "import", 
     "web-platform-tests/resource-timing": "import", 
     "web-platform-tests/resources": "import", 
     "web-platform-tests/screen-orientation": "skip", 
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resize-observer/META.yml b/LayoutTests/imported/w3c/web-platform-tests/resize-observer/META.yml
new file mode 100644 (file)
index 0000000..ef66856
--- /dev/null
@@ -0,0 +1,4 @@
+spec: https://wicg.github.io/ResizeObserver/
+suggested_reviewers:
+  - atotic
+  - dholbert
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resize-observer/eventloop-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/resize-observer/eventloop-expected.txt
new file mode 100644 (file)
index 0000000..7b23106
--- /dev/null
@@ -0,0 +1,7 @@
+CONSOLE MESSAGE: line 50: ReferenceError: Can't find variable: ResizeObserver
+ResizeObserver notification event loop tests
+
+t1
+
+FAIL ResizeObserver implemented assert_own_property: expected property "ResizeObserver" missing
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resize-observer/eventloop.html b/LayoutTests/imported/w3c/web-platform-tests/resize-observer/eventloop.html
new file mode 100644 (file)
index 0000000..559f52a
--- /dev/null
@@ -0,0 +1,259 @@
+<!doctype html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="./resources/resizeTestHelper.js"></script>
+<style>
+  div {
+    border: 1px dotted gray
+  }
+</style>
+<p>ResizeObserver notification event loop tests</p>
+<div id="target1" style="width:100px;height:100px;">t1
+</div>
+<div id="container">
+  <div id="a1" style="width:100px;height:100px">
+    <div id="a2" style="width:100px;height:100px">
+    </div>
+  </div>
+  <div id="b1" style="width:100px;height:100px">
+    <div id="b2" style="width:100px;height:100px">
+    </div>
+  </div>
+</div>
+<script>
+'use strict';
+
+let t1 = document.querySelector('#target1');
+
+// allow uncaught exception because ResizeObserver posts exceptions
+// to window error handler when limit is exceeded.
+// This codepath is tested in this file.
+
+setup({allow_uncaught_exception: true});
+
+function template() {
+  let helper = new ResizeTestHelper(
+    "test0: title",
+  [
+    {
+      setup: observer => {
+      },
+      notify: (entries, observer) => {
+        return true;  // Delay next step
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+var onErrorCalled = false;
+
+window.onerror = err => {
+  onErrorCalled = true;
+}
+
+function test0() {
+
+  let divs = [t1];
+  let rAF = 0;
+  let helper = new ResizeTestHelper(
+    "test0: multiple notifications inside same event loop",
+  [
+    {
+      setup: observer => {
+        onErrorCalled = false;
+        let t2 = document.createElement('div');
+        let t3 = document.createElement('div');
+        t2.appendChild(t3);
+        t1.appendChild(t2);
+        divs.push(t2);
+        divs.push(t3);
+        observer.observe(t1);
+        observer.observe(t2);
+        observer.observe(t3);
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 3, "3 notifications");
+      }
+    },
+    {
+      setup: observer => {
+        helper.startCountingRaf();
+        divs.forEach( el => { el.style.width = "101px";});
+      },
+      notify: (entries, observer) => {
+        // t1 is not delivered
+        assert_equals(entries.length, 2, "2 notifications");
+        assert_equals(helper.rafCount, 0, "still in same loop");
+      }
+    },
+    {
+      setup: observer => {
+        divs.forEach( el => { el.style.width = "102px";});
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1, "1 notifications");
+        assert_equals(helper.rafCount, 0, "same loop");
+      }
+    },
+    { // t1 and t2 get notified
+      setup: observer => {
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 2, "2 notifications");
+        assert_equals(helper.rafCount, 1, "new loop");
+        assert_equals(onErrorCalled, true, "error was fired");
+        observer.disconnect();
+        while (t1.childNodes.length > 0)
+          t1.removeChild(t1.childNodes[0]);
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test1() {
+
+  var resizers = [t1];
+  // Testing depths of shadow roots
+  // DOM: t1 <- t2 <- t3 <-shadow- t4 <- t5
+  let helper = new ResizeTestHelper(
+    "test1: depths of shadow roots",
+  [
+    {
+      setup: observer => {
+        onErrorCalled = false;
+        let t2 = document.createElement('div');
+        t1.appendChild(t2);
+        resizers.push(t2);
+        let t3 = document.createElement('div');
+        resizers.push(t3);
+        t2.appendChild(t3);
+        let shadow = t3.attachShadow({ mode: "open" });
+        let t4 = document.createElement('div');
+        resizers.push(t4);
+        shadow.appendChild(t4);
+        let t5 = document.createElement('div');
+        resizers.push(t5);
+        t4.appendChild(t5);
+        resizers.forEach( el => observer.observe(el) );
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 5, "all entries resized");
+      }
+    },
+    {
+      setup: observer => {
+        resizers.forEach( el => el.style.width = "111px" );
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 4, "depth limited");
+      }
+    },
+    {
+      setup: observer => {
+        resizers.forEach( el => el.style.width = "112px" );
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 3, "depth limited");
+      }
+    },
+    {
+      setup: observer => {
+        resizers.forEach( el => el.style.width = "113px" );
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 2, "depth limited");
+      }
+    },
+    {
+      setup: observer => {
+        resizers.forEach( el => el.style.width = "114px" );
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1, "depth limited");
+      }
+    },
+    {
+      setup: observer => {
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 4, "limit notifications");
+        assert_equals(onErrorCalled, true, "breached limit");
+        observer.disconnect();
+        t1.removeChild(t1.firstChild);
+      }
+    },
+  ]);
+  return helper.start();
+}
+
+function test2() {
+  let container = document.querySelector('#container');
+  let a1 = document.querySelector('#a1');
+  let a2 = document.querySelector('#a2');
+  let b1 = document.querySelector('#b1');
+  let b2 = document.querySelector('#b2');
+  let targets = [a1, a2, b1, b2];
+
+  let helper = new ResizeTestHelper(
+    "test2: move target in dom while inside event loop",
+  [
+    {
+      setup: observer => {
+        for (let t of targets)
+          observer.observe(t);
+      },
+      notify: (entries, observer) => {
+        return true;  // delay next observation
+      }
+    },
+    { // resize them all
+      setup: observer => {
+        for (let t of targets)
+          t.style.width = "110px";
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, targets.length, "all targets observed");
+      }
+    },
+    { // resize all, move dom upwards
+      setup: observer => {
+        for (let t of targets)
+          t.style.width = "130px";
+        container.appendChild(b2);
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1, "b2 moved upwards");
+        assert_equals(entries[0].target, a2);
+      }
+    },
+    { // resize all, move dom downwards
+      setup: observer => {
+        for (let t of targets)
+          t.style.width = "130px";
+        a2.appendChild(b2);
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1, "b2 moved downwards");
+        assert_equals(entries[0].target, b2);
+        a1.appendChild(a2);
+      }
+    },
+  ]);
+  return helper.start();
+}
+
+let guard;
+test(_ => {
+  assert_own_property(window, "ResizeObserver");
+  guard = async_test('guard');
+}, "ResizeObserver implemented")
+
+test0()
+  .then(() => { return test1(); })
+  .then(() => { return test2(); })
+  .then(() => { guard.done(); });
+
+</script>
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resize-observer/idlharness.window-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/resize-observer/idlharness.window-expected.txt
new file mode 100644 (file)
index 0000000..a7ea327
--- /dev/null
@@ -0,0 +1,30 @@
+
+FAIL idl_test setup promise_test: Unhandled rejection with value: object "Got an error before parsing any named definition: Unrecognised tokens, line 1 (tokens: "{\"error\": {\"message\"")
+[
+    {
+        "type": "{",
+        "value": "{",
+        "trivia": ""
+    },
+    {
+        "type": "string",
+        "value": "\"error\"",
+        "trivia": ""
+    },
+    {
+        "type": ":",
+        "value": ":",
+        "trivia": ""
+    },
+    {
+        "type": "{",
+        "value": "{",
+        "trivia": " "
+    },
+    {
+        "type": "string",
+        "value": "\"message\"",
+        "trivia": ""
+    }
+]"
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resize-observer/idlharness.window.html b/LayoutTests/imported/w3c/web-platform-tests/resize-observer/idlharness.window.html
new file mode 100644 (file)
index 0000000..2382913
--- /dev/null
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resize-observer/idlharness.window.js b/LayoutTests/imported/w3c/web-platform-tests/resize-observer/idlharness.window.js
new file mode 100644 (file)
index 0000000..592af2e
--- /dev/null
@@ -0,0 +1,37 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+// META: script=resources/resizeTestHelper.js
+
+'use strict';
+
+// https://wicg.github.io/ResizeObserver/
+
+idl_test(
+  ['ResizeObserver'],
+  ['dom', 'geometry'],
+  async idl_array => {
+    idl_array.add_objects({
+      ResizeObserver: ['observer'],
+      ResizeObserverEntry: ['entry'],
+    });
+
+    const div = document.createElement('div');
+    document.body.appendChild(div);
+    let helper = new ResizeTestHelper(
+      "ResizeObserverEntry creator",
+      [
+        {
+          setup: observer => {
+            self.observer = observer;
+            observer.observe(div);
+            div.style.width = "5px";
+          },
+          notify: entries => {
+            self.entry = entries[0];
+            assert_equals(entries[0].contentRect.width, 5, "target width");
+          }
+        }
+      ]);
+    await helper.start();
+  }
+);
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resize-observer/notify-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/resize-observer/notify-expected.txt
new file mode 100644 (file)
index 0000000..9532784
--- /dev/null
@@ -0,0 +1,11 @@
+CONSOLE MESSAGE: line 50: ReferenceError: Can't find variable: ResizeObserver
+ResizeObserver tests
+
+t1
+t2
+t3 inline
+
+Harness Error (FAIL), message = ReferenceError: Can't find variable: ResizeObserver
+
+FAIL ResizeObserver implemented assert_own_property: expected property "ResizeObserver" missing
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resize-observer/notify.html b/LayoutTests/imported/w3c/web-platform-tests/resize-observer/notify.html
new file mode 100644 (file)
index 0000000..d588851
--- /dev/null
@@ -0,0 +1,351 @@
+<!doctype html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="./resources/resizeTestHelper.js"></script>
+<style>
+  div {
+    border: 1px dotted gray
+  }
+  .transform {
+    transform: scale(2,2) rotate(90deg)
+  }
+</style>
+<p>ResizeObserver tests</p>
+<div id="target1" style="width:100px;height:100px;">t1
+  <div id="target2" style="width:100px;height:100px;">t2
+    <div id="target3" style="width:100px;height:100px;">t3
+      <span id="inline">inline</span>
+    </div>
+  </div>
+</div>
+<div id="absolute" style="width:100.5px;height:100.5px;position:absolute;top:10.3px;left:10.3px"></div>
+<script>
+'use strict';
+
+let t1 = document.querySelector('#target1');
+let t2 = document.querySelector('#target2');
+let t3 = document.querySelector('#target3');
+let abs = document.querySelector('#absolute');
+let inline = document.querySelector('#inline');
+
+function test0() {
+  let helper = new ResizeTestHelper(
+    "test0: notification ordering",
+  [
+    {
+      setup: observer => {
+        observer.observe(t3);
+        observer.observe(t2);
+        observer.observe(t1);
+        t1.style.width = "5px";
+        t3.style.width = "5px";
+        t2.style.width = "5px";
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 3, "3 resizes");
+        assert_equals(entries[0].target, t3, "ordering");
+        assert_equals(entries[1].target, t2, "ordering");
+        assert_equals(entries[2].target, t1, "ordering");
+        observer.disconnect();
+        t1.style.width = "100px";
+        t2.style.width = "100px";
+        t3.style.width = "100px";
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test1() {
+  let helper = new ResizeTestHelper(
+    "test1: display:none triggers notification",
+  [
+    {
+      setup: observer => {
+        observer.observe(t1);
+      },
+      notify: (entries, observer) => {
+        return true;  // Delay next step
+      }
+    },
+    {
+      setup: observer => {
+        t1.style.display = "none";
+      },
+      notify: (entries, observer) => {
+        t1.style.display = "";
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+
+function test2() {
+  let helper = new ResizeTestHelper(
+    "test2: remove/appendChild trigger notification",
+  [
+    {
+      setup: observer => {
+        observer.observe(t1);
+      },
+      notify: (entries, observer) => {
+        return true;  // Delay next step
+      }
+    },
+    { // "removeChild triggers notification"
+      setup: observer => {
+        t1.parentNode.removeChild(t1);
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries[0].target, t1);
+        return true;  // Delay next step
+      }
+    },
+    { // "appendChild triggers notification",
+      setup: observer => {
+        document.body.appendChild(t1);
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries[0].target, t1)
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+
+function test3() {
+  let helper = new ResizeTestHelper(
+    "test3: dimensions match",
+  [
+    {
+      setup: observer => {
+        observer.observe(t1);
+        t1.style.width = "200.5px";
+        t1.style.height = "100px";
+        t1.style.paddingLeft = "20px";
+        t1.style.paddingTop = "10px";
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries[0].contentRect.left,20);
+        assert_equals(entries[0].contentRect.top,10);
+        assert_between_inclusive(entries[0].contentRect.width, 200.4, 200.6, "width is not rounded");
+        assert_equals(entries[0].contentRect.height, 100);
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test4() {
+  let helper = new ResizeTestHelper(
+    "test4: transform do not cause notifications",
+  [
+    {
+      setup: observer => {
+        observer.observe(t2);
+      },
+      notify: (entries, observer) => {
+        return true; // Delay next step
+      }
+    },
+    {
+      setup: observer => {
+        t2.classList.add("transform");
+      },
+      notify: (entries, observer) => {
+        assert_unreached("transform must not trigger notifications");
+      },
+      timeout: () => {
+        t2.classList.remove("transform");
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test5() {
+  let helper = new ResizeTestHelper(
+    "test5: moving an element does not trigger notifications",
+  [
+    {
+      setup: observer => {
+        observer.observe(abs);
+      },
+      notify: (entries, observer) => {
+        return true; // Delay next step
+      }
+    },
+    {
+      setup: observer => {
+        abs.style.top = "20.33px";
+        abs.style.left = "20.33px";
+      },
+      notify: (entries, observer) => {
+        assert_unreached("movement should not cause resize notifications");
+      },
+      timeout: () => {
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test6() {
+  let helper = new ResizeTestHelper(
+    "test6: inline element does not notify",
+  [
+    {
+      setup: observer => {
+        observer.observe(inline);
+        observer.observe(t1);
+        t1.style.width = "66px";
+        inline.style.width = "66px";
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1, "inline elements must not trigger notifications");
+        assert_equals(entries[0].target, t1, "inline elements must not trigger notifications");
+        return true; // Delay next step
+      }
+    },
+    { // "inline element that becomes block should notify",
+      setup: observer => {
+        inline.style.display = "block";
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries[0].target, inline);
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test7() {
+  let helper = new ResizeTestHelper(
+    "test7: unobserve inside notify callback",
+  [
+    {
+      setup: observer => {
+        observer.observe(t1);
+        observer.observe(t2);
+      },
+      notify: (entries, observer) => {
+        t1.style.width = "777px";
+        t2.style.width = "777px";
+        observer.unobserve(t1);
+        return true;  // Delay next step
+      }
+    },
+    {
+      setup: observer => {
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1, "only t2 is observed");
+        assert_equals(entries[0].target, t2, "only t2 is observed");
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test8() {
+  let helper = new ResizeTestHelper(
+    "test8: observe inside notify callback",
+  [
+    {
+      setup: observer => {
+        observer.observe(t1);
+      },
+      notify: (entries, observer) => {
+        observer.observe(t2);
+        t2.style.width = "888px";
+        return true;  // Delay next step
+      }
+    },
+    {
+      setup: observer => {
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1, "only t2 is observed");
+        assert_equals(entries[0].target, t2, "only t2 is observed");
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test9() {
+  let helper = new ResizeTestHelper(
+    "test9: disconnect inside notify callback",
+  [
+    {
+      setup: observer => {
+        observer.observe(t1);
+      },
+      notify: (entries, observer) => {
+        t1.style.width = "999px";
+        observer.disconnect();
+        return true;  // Delay next step
+      }
+    },
+    {
+      setup: observer => {
+      },
+      notify: (entries, observer) => {
+        assert_unreached("there should be no notifications after disconnect");
+      },
+      timeout: () => {
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test10() {
+  var parent = t1.parentNode;
+  let helper = new ResizeTestHelper(
+    "test10: element notifies when parent removed",
+  [
+    {
+      setup: observer => {
+        observer.observe(t3);
+      },
+      notify: (entries, observer) => {
+        return true;  // Delay next step
+      }
+    },
+    {
+      setup: observer => {
+        t1.parentNode.removeChild(t1);
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1);
+        assert_equals(entries[0].target, t3);
+        parent.appendChild(t1);
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+let guard;
+test(_ => {
+  assert_own_property(window, "ResizeObserver");
+  guard = async_test('guard');
+}, "ResizeObserver implemented")
+
+test0()
+  .then(() => { return test1(); })
+  .then(() => { return test2(); })
+  .then(() => { return test3(); })
+  .then(() => { return test4(); })
+  .then(() => { return test5(); })
+  .then(() => { return test6(); })
+  .then(() => { return test7(); })
+  .then(() => { return test8(); })
+  .then(() => { return test9(); })
+  .then(() => { return test10(); })
+  .then(() => { guard.done(); });
+
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resize-observer/observe-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/resize-observer/observe-expected.txt
new file mode 100644 (file)
index 0000000..75003e0
--- /dev/null
@@ -0,0 +1,9 @@
+CONSOLE MESSAGE: line 50: ReferenceError: Can't find variable: ResizeObserver
+ResizeObserver tests
+
+t1
+t2
+
+FAIL ResizeObserver implemented assert_own_property: expected property "ResizeObserver" missing
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resize-observer/observe.html b/LayoutTests/imported/w3c/web-platform-tests/resize-observer/observe.html
new file mode 100644 (file)
index 0000000..dc1f195
--- /dev/null
@@ -0,0 +1,207 @@
+<!doctype html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="./resources/resizeTestHelper.js"></script>
+<p>ResizeObserver tests</p>
+<div id="target1" style="width:100px;height:100px;">t1</div>
+<div id="target2" style="width:100px;height:100px;">t2</div>
+<img id="target3" style="width:100px;height:100px;">
+<iframe src="./resources/iframe.html" width="300px" height="100px" style="display:block"></iframe>
+<script>
+'use strict';
+
+let t1 = document.querySelector('#target1');
+let t2 = document.querySelector('#target2');
+
+// allow uncaught exception because ResizeObserver posts exceptions
+// to window error handler when limit is exceeded.
+setup({allow_uncaught_exception: true});
+
+function test0() {
+  let helper = new ResizeTestHelper(
+    "test0: simple observation",
+  [
+    {
+      setup: observer => {
+        observer.observe(t1);
+        t1.style.width = "5px";
+      },
+      notify: entries => {
+        assert_equals(entries.length, 1, "1 pending notification");
+        assert_equals(entries[0].target, t1, "target is t1");
+        assert_equals(entries[0].contentRect.width, 5, "target width");
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test1() {
+  let helper = new ResizeTestHelper(
+    "test1: multiple observation on same element trigger only one",
+  [
+    {
+      setup: observer => {
+        observer.observe(t1);
+        observer.observe(t1);
+        t1.style.width = "10px";
+      },
+      notify: entries => {
+        assert_equals(entries.length, 1, "1 pending notification");
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test2() {
+  test(() => {
+      assert_throws({name: "TypeError"}, _=> {
+        let ro = new ResizeObserver(() => {});
+        ro.observe({});
+      });
+    },
+    "test2: throw exception when observing non-element"
+  );
+  return Promise.resolve();
+}
+
+function test3() {
+  let helper = new ResizeTestHelper(
+    "test3: disconnect stops all notifications", [
+    {
+      setup: observer => {
+        observer.observe(t1);
+        observer.observe(t2);
+        observer.disconnect();
+        t1.style.width = "30px";
+      },
+      notify: entries => {
+         assert_unreached("no entries should be observed");
+      },
+      timeout: () => {
+        // expected
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test4() {
+  let helper = new ResizeTestHelper(
+    "test4: unobserve target stops notifications, unobserve non-observed does nothing", [
+    {
+      setup: observer => {
+        observer.observe(t1);
+        observer.observe(t2);
+        observer.unobserve(t1);
+        observer.unobserve(document.body);
+        t1.style.width = "40px";
+        t2.style.width = "40px";
+      },
+      notify: entries => {
+        assert_equals(entries.length, 1, "only t2");
+        assert_equals(entries[0].target, t2, "t2 was observed");
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test5() {
+  let t3 = document.querySelector('#target3');
+  var helper = new ResizeTestHelper("test5: observe img",[
+    {
+      setup: observer => {
+        observer.observe(t3);
+      },
+      notify: entries => {
+      }
+    },
+    {
+      setup: observer => {
+        t3.style.width = "100.5px";
+      },
+      notify: entries => {
+        assert_equals(entries.length, 1);
+        assert_equals(entries[0].contentRect.width, 100.5);
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test6() {
+  let resolvePromise;
+  let promise = new Promise((resolve) => {
+    resolvePromise = resolve;
+  });
+  let test = async_test('test6: iframe notifications');
+  let testRequested = false;
+  let iframe = document.querySelector('iframe');
+  window.addEventListener('message', event => {
+    switch(event.data) {
+    case 'readyToTest':
+      if (!testRequested) {
+        iframe.contentWindow.postMessage('startTest', '*');
+        testRequested = true;
+      }
+    break;
+    case 'success':
+    case 'fail':
+      window.requestAnimationFrame(() => {
+        test.step( () => {
+          assert_equals(event.data, 'success');
+          test.done();
+          resolvePromise();
+        });
+      });
+    break;
+    }
+  }, false);
+  return promise;
+}
+
+function test7() {
+  let harnessTest = async_test("test7: callback.this");
+  let resolvePromise;
+  let ro = new ResizeObserver( function(entries, obs)  {
+    let callbackThis = this;
+    resolvePromise();
+    harnessTest.step(() => {
+      assert_equals(callbackThis, ro, "callback.this is ResizeObserver");
+      assert_equals(obs, ro, "2nd argument is ResizeObserver");
+      ro.disconnect();
+      // every reference to RO must be null before test completes
+      // to avoid triggering test leak-detection
+      ro = null;
+      callbackThis = null;
+      obs = null;
+      harnessTest.done();
+     });
+    }
+  );
+  ro.observe(t1);
+
+  return new Promise( (resolve, reject) => {
+    resolvePromise = resolve;
+  });
+}
+
+let guard;
+test(_ => {
+  assert_own_property(window, "ResizeObserver");
+  guard = async_test('guard');
+}, "ResizeObserver implemented")
+
+test0()
+  .then(() => { return test1(); })
+  .then(() => { return test2(); })
+  .then(() => { return test3(); })
+  .then(() => { return test4(); })
+  .then(() => { return test5(); })
+  .then(() => { return test6(); })
+  .then(() => { return test7(); })
+  .then(() => { guard.done(); });
+
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resize-observer/resources/iframe.html b/LayoutTests/imported/w3c/web-platform-tests/resize-observer/resources/iframe.html
new file mode 100644 (file)
index 0000000..518317b
--- /dev/null
@@ -0,0 +1,38 @@
+<!doctype html>
+<head>
+  <script src="./resizeTestHelper.js"></script>
+</head>
+<p>iframe test</p>
+<div id="itarget1" style="width:100px;height:100px;">t1</div>
+<script>
+'use strict';
+let t1 = document.querySelector('#itarget1');
+function test0() {
+  let timeoutId = window.setTimeout( () => {
+    window.parent.postMessage('fail', '*');
+  }, ResizeTestHelper.TIMEOUT);
+  let ro = new ResizeObserver(function(entries) {
+    window.clearTimeout(timeoutId);
+    window.parent.postMessage('success', '*');
+  });
+  ro.observe(t1);
+}
+let testStarted = false;
+window.addEventListener('message', function(ev) {
+    switch(ev.data) {
+        case 'startTest':
+          testStarted = true;
+          test0();
+        break;
+    }
+});
+// How does parent know we've loaded problem is solved by
+// broadcasting readyToTest message repeatedly until test starts.
+function broadcastReady() {
+  if (!testStarted) {
+    window.parent.postMessage('readyToTest', '*');
+    window.requestAnimationFrame(broadcastReady);
+  }
+}
+broadcastReady();
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resize-observer/resources/resizeTestHelper.js b/LayoutTests/imported/w3c/web-platform-tests/resize-observer/resources/resizeTestHelper.js
new file mode 100644 (file)
index 0000000..60c681b
--- /dev/null
@@ -0,0 +1,148 @@
+'use strict';
+
+/**
+  ResizeTestHelper is a framework to test ResizeObserver
+  notifications. Use it to make assertions about ResizeObserverEntries.
+  This framework is needed because ResizeObservations are
+  delivered asynchronously inside the event loop.
+
+  Features:
+  - can queue multiple notification steps in a test
+  - handles timeouts
+  - returns Promise that is fullfilled when test completes.
+    Use to chain tests (since parallel async ResizeObserver tests
+    would conflict if reusing same DOM elements).
+
+  Usage:
+
+  create ResizeTestHelper for every test.
+  Make assertions inside notify, timeout callbacks.
+  Start tests with helper.start()
+  Chain tests with Promises.
+  Counts animation frames, see startCountingRaf
+*/
+
+/*
+  @param name: test name
+  @param steps:
+  {
+    setup: function(ResizeObserver) {
+      // called at the beginning of the test step
+      // your observe/resize code goes here
+    },
+    notify: function(entries, observer) {
+      // ResizeObserver callback.
+      // Make assertions here.
+      // Return true if next step should start on the next event loop.
+    },
+    timeout: function() {
+      // Define this if your test expects to time out.
+      // If undefined, timeout is assert_unreached.
+    }
+  }
+*/
+function ResizeTestHelper(name, steps)
+{
+    this._name = name;
+    this._steps = steps || [];
+    this._stepIdx = -1;
+    this._harnessTest = null;
+    this._observer = new ResizeObserver(this._handleNotification.bind(this));
+    this._timeoutBind = this._handleTimeout.bind(this);
+    this._nextStepBind = this._nextStep.bind(this);
+}
+
+ResizeTestHelper.TIMEOUT = 100;
+
+ResizeTestHelper.prototype = {
+  get _currentStep() {
+    return this._steps[this._stepIdx];
+  },
+
+  _nextStep: function() {
+    if (++this._stepIdx == this._steps.length)
+      return this._done();
+    this._timeoutId = this._harnessTest.step_timeout(
+      this._timeoutBind, ResizeTestHelper.TIMEOUT);
+    try {
+      this._steps[this._stepIdx].setup(this._observer);
+    }
+    catch(err) {
+      this._harnessTest.step(() => {
+        assert_unreached("Caught a throw, possible syntax error");
+      });
+    }
+  },
+
+  _handleNotification: function(entries) {
+    if (this._timeoutId) {
+      window.clearTimeout(this._timeoutId);
+      delete this._timeoutId;
+    }
+    this._harnessTest.step(() => {
+      let rafDelay = this._currentStep.notify(entries, this._observer);
+      if (rafDelay)
+        window.requestAnimationFrame(this._nextStepBind);
+      else
+        this._nextStep();
+    });
+  },
+
+  _handleTimeout: function() {
+    delete this._timeoutId;
+    this._harnessTest.step(() => {
+      if (this._currentStep.timeout) {
+        this._currentStep.timeout();
+      }
+      else {
+        assert_unreached("Timed out waiting for notification. (" + ResizeTestHelper.TIMEOUT + "ms)");
+      }
+      this._nextStep();
+    });
+  },
+
+  _done: function() {
+    this._observer.disconnect();
+    delete this._observer;
+    this._harnessTest.done();
+    if (this._rafCountRequest) {
+      window.cancelAnimationFrame(this._rafCountRequest);
+      delete this._rafCountRequest;
+    }
+    window.requestAnimationFrame(() => { this._resolvePromise(); });
+  },
+
+  start: function() {
+    this._harnessTest = async_test(this._name);
+    this._harnessTest.step(() => {
+      assert_equals(this._stepIdx, -1, "start can only be called once");
+      this._nextStep();
+    });
+    return new Promise( (resolve, reject) => {
+      this._resolvePromise = resolve;
+      this._rejectPromise = reject;
+    });
+  },
+
+  get rafCount() {
+    if (!this._rafCountRequest)
+      throw "rAF count is not active";
+    return this._rafCount;
+  },
+
+  _incrementRaf: function() {
+    if (this._rafCountRequest) {
+      this._rafCount++;
+      this._rafCountRequest = window.requestAnimationFrame(this._incrementRafBind);
+    }
+  },
+
+  startCountingRaf: function() {
+    if (this._rafCountRequest)
+      window.cancelAnimationFrame(this._rafCountRequest);
+    if (!this._incrementRafBind)
+      this._incrementRafBind = this._incrementRaf.bind(this);
+    this._rafCount = 0;
+    this._rafCountRequest = window.requestAnimationFrame(this._incrementRafBind);
+  }
+}
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resize-observer/resources/w3c-import.log b/LayoutTests/imported/w3c/web-platform-tests/resize-observer/resources/w3c-import.log
new file mode 100644 (file)
index 0000000..af37cea
--- /dev/null
@@ -0,0 +1,18 @@
+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/resize-observer/resources/iframe.html
+/LayoutTests/imported/w3c/web-platform-tests/resize-observer/resources/resizeTestHelper.js
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resize-observer/svg-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/resize-observer/svg-expected.txt
new file mode 100644 (file)
index 0000000..dcf836e
--- /dev/null
@@ -0,0 +1,9 @@
+CONSOLE MESSAGE: line 50: ReferenceError: Can't find variable: ResizeObserver
+ResizeObserver svg tests
+
+Here is a paragraph that requires word wrap
+
+svg text tag
+
+FAIL ResizeObserver implemented assert_own_property: expected property "ResizeObserver" missing
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resize-observer/svg.html b/LayoutTests/imported/w3c/web-platform-tests/resize-observer/svg.html
new file mode 100644 (file)
index 0000000..e3a1ab6
--- /dev/null
@@ -0,0 +1,333 @@
+<!doctype html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="./resources/resizeTestHelper.js"></script>
+<p>ResizeObserver svg tests</p>
+<svg height="430" width="500" >
+  <circle cx="10" cy="10" r="5" style="fill:orange;stroke:black;stroke-width:1" />
+  <ellipse cx="10" cy="30" rx="5" ry="5" style="fill:orange;stroke:black;stroke-width:1"/>
+  <foreignObject cy="50" width="100" height="20">
+    <body>
+      <p>Here is a paragraph that requires word wrap</p>
+    </body>
+  </foreignObject>
+  <image xlink:href="" x="0" y="100" height="30" width="100" />
+  <line x1="0" y1="50" x2="20" y2="70" stroke="black" stroke-width="2"/>
+  <path d="M 0 100 L 100 100 L 50 150 z"
+        style="fill:orange;stroke:black;stroke-width:1" />
+  <polygon points="0,200 100,200 50,250" style="fill:orange;stroke:black;stroke-width:1" />
+  <polyline points="0,300 100,300 50,350" style="fill:orange;stroke:black;stroke-width:1"/>
+  <rect x="0" y="380" width="10" height="10" style="fill:orange; stroke:black; stroke-width:1" />
+  <text x="0" y="400" font-size="20">svg text tag</text>
+</svg>
+<script>
+'use strict';
+
+setup({allow_uncaught_exception: true});
+
+function test0() {
+  let target = document.querySelector('circle');
+  let helper = new ResizeTestHelper(
+    "test0: observe svg:circle",
+  [
+    {
+      setup: observer => {
+        observer.observe(target);
+      },
+      notify: (entries, observer) => {
+        return true;  // Delay next step
+      }
+    },
+    {
+      setup: observer => {
+        target.setAttribute('r', 10);
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1);
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test1() {
+  let target = document.querySelector('ellipse');
+  let helper = new ResizeTestHelper(
+    "test1: observe svg:ellipse",
+  [
+    {
+      setup: observer => {
+        observer.observe(target);
+      },
+      notify: (entries, observer) => {
+        return true;  // Delay next step
+      }
+    },
+    {
+      setup: observer => {
+        target.setAttribute('rx', 10);
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1);
+        assert_equals(entries[0].contentRect.width, 20);
+        assert_equals(entries[0].contentRect.height, 10);
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test2() {
+  let target = document.querySelector('foreignObject');
+  let helper = new ResizeTestHelper(
+    "test2: observe svg:foreignObject",
+  [
+    {
+      setup: observer => {
+        observer.observe(target);
+      },
+      notify: (entries, observer) => {
+        return true;  // Delay next step
+      }
+    },
+    {
+      setup: observer => {
+        target.setAttribute('width', 200);
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1);
+        assert_equals(entries[0].contentRect.width, 200);
+        assert_equals(entries[0].contentRect.height, 20);
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test3() {
+  let target = document.querySelector('image');
+  let helper = new ResizeTestHelper(
+    "test3: observe svg:image",
+  [
+    {
+      setup: observer => {
+        observer.observe(target);
+      },
+      notify: (entries, observer) => {
+        return true;  // Delay next step
+      }
+    },
+    {
+      setup: observer => {
+        target.setAttribute('height', 40);
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1);
+        assert_equals(entries[0].contentRect.width, 100);
+        assert_equals(entries[0].contentRect.height, 40);
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test4() {
+  let target = document.querySelector('line');
+  let helper = new ResizeTestHelper(
+    "test4: observe svg:line",
+  [
+    {
+      setup: observer => {
+        observer.observe(target);
+      },
+      notify: (entries, observer) => {
+        return true;  // Delay next step
+      }
+    },
+    {
+      setup: observer => {
+        target.setAttribute('y2', 80);
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1);
+        assert_equals(entries[0].contentRect.width, 20);
+        assert_equals(entries[0].contentRect.height, 30);
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test5() {
+  let target = document.querySelector('path');
+  let helper = new ResizeTestHelper(
+    "test5: observe svg:path",
+  [
+    {
+      setup: observer => {
+        observer.observe(target);
+      },
+      notify: (entries, observer) => {
+        return true;  // Delay next step
+      }
+    },
+    {
+      setup: observer => {
+        target.setAttribute('d', "M 0 100 L 100 100 L 50 160 z");
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1);
+        assert_equals(entries[0].contentRect.width, 100);
+        assert_equals(entries[0].contentRect.height, 60);
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test6() {
+  let target = document.querySelector('polygon');
+  let helper = new ResizeTestHelper(
+    "test6: observe svg:path",
+  [
+    {
+      setup: observer => {
+        observer.observe(target);
+      },
+      notify: (entries, observer) => {
+        return true;  // Delay next step
+      }
+    },
+    {
+      setup: observer => {
+        target.setAttribute('points', "0,200 100,200 50,260");
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1);
+        assert_equals(entries[0].contentRect.width, 100);
+        assert_equals(entries[0].contentRect.height, 60);
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test7() {
+  let target = document.querySelector('polyline');
+  let helper = new ResizeTestHelper(
+    "test7: observe svg:polyline",
+  [
+    {
+      setup: observer => {
+        observer.observe(target);
+      },
+      notify: (entries, observer) => {
+        return true;  // Delay next step
+      }
+    },
+    {
+      setup: observer => {
+        target.setAttribute('points', "0,300 100,300 50,360");
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1);
+        assert_equals(entries[0].contentRect.width, 100);
+        assert_equals(entries[0].contentRect.height, 60);
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test8() {
+  let target = document.querySelector('rect');
+  let helper = new ResizeTestHelper(
+    "test8: observe svg:rect",
+  [
+    {
+      setup: observer => {
+        observer.observe(target);
+      },
+      notify: (entries, observer) => {
+        return true;  // Delay next step
+      }
+    },
+    {
+      setup: observer => {
+        target.setAttribute('width', "20");
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1);
+        assert_equals(entries[0].contentRect.width, 20);
+        assert_equals(entries[0].contentRect.height, 10);
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+function test9() {
+  let target = document.querySelector('text');
+  let helper = new ResizeTestHelper(
+    "test9: observe svg:text",
+  [
+    {
+      setup: observer => {
+        observer.observe(target);
+      },
+      notify: (entries, observer) => {
+        return true;  // Delay next step
+      }
+    },
+    {
+      setup: observer => {
+        target.setAttribute('font-size', "25");
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1);
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+
+function test10() {
+  let target = document.querySelector('svg');
+  let helper = new ResizeTestHelper(
+    "test10: observe svg:svg, top/left is 0 even with padding",
+  [
+    {
+      setup: observer => {
+        observer.observe(target);
+      },
+      notify: (entries, observer) => {
+        assert_equals(entries.length, 1);
+        assert_equals(entries[0].contentRect.top, 0);
+        assert_equals(entries[0].contentRect.left, 0);
+      }
+    }
+  ]);
+  return helper.start();
+}
+
+let guard;
+test(_ => {
+  assert_own_property(window, "ResizeObserver");
+  guard = async_test('guard');
+}, "ResizeObserver implemented")
+
+test0()
+  .then(() => { return test1(); })
+  .then(() => { return test2(); })
+  .then(() => { return test3(); })
+  .then(() => { return test4(); })
+  .then(() => { return test5(); })
+  .then(() => { return test6(); })
+  .then(() => { return test7(); })
+  .then(() => { return test8(); })
+  .then(() => { return test9(); })
+  .then(() => { return test10(); })
+  .then(() => { guard.done(); });
+
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resize-observer/w3c-import.log b/LayoutTests/imported/w3c/web-platform-tests/resize-observer/w3c-import.log
new file mode 100644 (file)
index 0000000..5641eec
--- /dev/null
@@ -0,0 +1,22 @@
+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/resize-observer/META.yml
+/LayoutTests/imported/w3c/web-platform-tests/resize-observer/eventloop.html
+/LayoutTests/imported/w3c/web-platform-tests/resize-observer/idlharness.window.js
+/LayoutTests/imported/w3c/web-platform-tests/resize-observer/notify.html
+/LayoutTests/imported/w3c/web-platform-tests/resize-observer/observe.html
+/LayoutTests/imported/w3c/web-platform-tests/resize-observer/svg.html