Picture element needs to work with the preload scanner and select the correct
authorhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Jan 2016 21:49:20 +0000 (21:49 +0000)
committerhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Jan 2016 21:49:20 +0000 (21:49 +0000)
source element instead of loading the image.
https://bugs.webkit.org/show_bug.cgi?id=152983

Reviewed by Dean Jackson.

Source/WebCore:

Added new tests in http/tests/loading.

* html/parser/HTMLPreloadScanner.cpp:
(WebCore::TokenPreloadScanner::tagIdFor):
(WebCore::TokenPreloadScanner::initiatorFor):
(WebCore::TokenPreloadScanner::StartTagScanner::StartTagScanner):
(WebCore::TokenPreloadScanner::StartTagScanner::processAttributes):
(WebCore::TokenPreloadScanner::StartTagScanner::processImageAndScriptAttribute):
(WebCore::TokenPreloadScanner::StartTagScanner::processAttribute):
(WebCore::TokenPreloadScanner::StartTagScanner::resourceType):
(WebCore::TokenPreloadScanner::scan):
* html/parser/HTMLPreloadScanner.h:
(WebCore::TokenPreloadScanner::setPredictedBaseElementURL):
(WebCore::TokenPreloadScanner::inPicture):

LayoutTests:

These tests are imported from Blink, although they have been modified slightly to
reflect the fact that we pass the nested <picture> cases that Blink fails.

* http/tests/loading/hidpi-preload-picture-sizes-expected.txt: Added.
* http/tests/loading/hidpi-preload-picture-sizes.html: Added.
* http/tests/loading/preload-picture-invalid-expected.txt: Added.
* http/tests/loading/preload-picture-invalid.html: Added.
* http/tests/loading/preload-picture-nested-expected.txt: Added.
* http/tests/loading/preload-picture-nested.html: Added.
* http/tests/loading/preload-picture-sizes-expected.txt: Added.
* http/tests/loading/preload-picture-sizes.html: Added.
* http/tests/loading/resources/base-image1.png: Added.
* http/tests/loading/resources/base-image2.png: Added.
* http/tests/loading/resources/base-image3.png: Added.
* http/tests/loading/resources/dup-image1.png: Added.
* http/tests/loading/resources/dup-image2.png: Added.
* http/tests/loading/resources/dup-image3.png: Added.
* http/tests/loading/resources/image1.png: Added.
* http/tests/loading/resources/image2.png: Added.
* http/tests/loading/resources/picture-preload-helper.js: Added.

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

21 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/loading/hidpi-preload-picture-sizes-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/loading/hidpi-preload-picture-sizes.html [new file with mode: 0644]
LayoutTests/http/tests/loading/preload-picture-invalid-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/loading/preload-picture-invalid.html [new file with mode: 0644]
LayoutTests/http/tests/loading/preload-picture-nested-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/loading/preload-picture-nested.html [new file with mode: 0644]
LayoutTests/http/tests/loading/preload-picture-sizes-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/loading/preload-picture-sizes.html [new file with mode: 0644]
LayoutTests/http/tests/loading/resources/base-image1.png [new file with mode: 0644]
LayoutTests/http/tests/loading/resources/base-image2.png [new file with mode: 0644]
LayoutTests/http/tests/loading/resources/base-image3.png [new file with mode: 0644]
LayoutTests/http/tests/loading/resources/dup-image1.png [new file with mode: 0644]
LayoutTests/http/tests/loading/resources/dup-image2.png [new file with mode: 0644]
LayoutTests/http/tests/loading/resources/dup-image3.png [new file with mode: 0644]
LayoutTests/http/tests/loading/resources/image1.png [new file with mode: 0644]
LayoutTests/http/tests/loading/resources/image2.png [new file with mode: 0644]
LayoutTests/http/tests/loading/resources/picture-preload-helper.js [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/html/parser/HTMLPreloadScanner.cpp
Source/WebCore/html/parser/HTMLPreloadScanner.h

index aa9f482..532923d 100644 (file)
@@ -1,3 +1,32 @@
+2016-01-11  Dave Hyatt  <hyatt@apple.com>
+
+        Picture element needs to work with the preload scanner and select the correct
+        source element instead of loading the image.
+        https://bugs.webkit.org/show_bug.cgi?id=152983
+
+        Reviewed by Dean Jackson.
+
+        These tests are imported from Blink, although they have been modified slightly to
+        reflect the fact that we pass the nested <picture> cases that Blink fails.
+
+        * http/tests/loading/hidpi-preload-picture-sizes-expected.txt: Added.
+        * http/tests/loading/hidpi-preload-picture-sizes.html: Added.
+        * http/tests/loading/preload-picture-invalid-expected.txt: Added.
+        * http/tests/loading/preload-picture-invalid.html: Added.
+        * http/tests/loading/preload-picture-nested-expected.txt: Added.
+        * http/tests/loading/preload-picture-nested.html: Added.
+        * http/tests/loading/preload-picture-sizes-expected.txt: Added.
+        * http/tests/loading/preload-picture-sizes.html: Added.
+        * http/tests/loading/resources/base-image1.png: Added.
+        * http/tests/loading/resources/base-image2.png: Added.
+        * http/tests/loading/resources/base-image3.png: Added.
+        * http/tests/loading/resources/dup-image1.png: Added.
+        * http/tests/loading/resources/dup-image2.png: Added.
+        * http/tests/loading/resources/dup-image3.png: Added.
+        * http/tests/loading/resources/image1.png: Added.
+        * http/tests/loading/resources/image2.png: Added.
+        * http/tests/loading/resources/picture-preload-helper.js: Added.
+
 2016-01-11  Brady Eidson  <beidson@apple.com>
 
         Modern IDB: storage/indexeddb/key-generator.html fails.
diff --git a/LayoutTests/http/tests/loading/hidpi-preload-picture-sizes-expected.txt b/LayoutTests/http/tests/loading/hidpi-preload-picture-sizes-expected.txt
new file mode 100644 (file)
index 0000000..a0e87f4
--- /dev/null
@@ -0,0 +1,54 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+main frame - didHandleOnloadEventsForFrame
+main frame - didFinishLoadForFrame
+PASS internals.isPreloaded('resources/image2.png'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?1'); is false
+PASS internals.isPreloaded('resources/base-image1.png?1'); is false
+PASS internals.isPreloaded('resources/base-image2.png?1'); is true
+PASS internals.isPreloaded('resources/base-image3.png?1'); is false
+PASS internals.isPreloaded('resources/preload-test.jpg?2'); is false
+PASS internals.isPreloaded('resources/base-image1.png?2'); is false
+PASS internals.isPreloaded('resources/base-image2.png?2'); is true
+PASS internals.isPreloaded('resources/base-image3.png?2'); is false
+PASS internals.isPreloaded('resources/preload-test.jpg?3'); is false
+PASS internals.isPreloaded('resources/base-image1.png?3'); is false
+PASS internals.isPreloaded('resources/base-image2.png?3'); is true
+PASS internals.isPreloaded('resources/base-image3.png?3'); is false
+PASS internals.isPreloaded('resources/preload-test.jpg?4'); is false
+PASS internals.isPreloaded('resources/base-image1.png?4'); is false
+PASS internals.isPreloaded('resources/base-image2.png?4'); is true
+PASS internals.isPreloaded('resources/base-image3.png?4'); is false
+PASS internals.isPreloaded('resources/preload-test.jpg?5'); is false
+PASS internals.isPreloaded('resources/base-image1.png?5'); is false
+PASS internals.isPreloaded('resources/base-image2.png?5'); is true
+PASS internals.isPreloaded('resources/base-image3.png?5'); is false
+PASS internals.isPreloaded('resources/preload-test.jpg?6'); is false
+PASS internals.isPreloaded('resources/base-image1.png?6'); is false
+PASS internals.isPreloaded('resources/base-image2.png?6'); is true
+PASS internals.isPreloaded('resources/base-image3.png?6'); is false
+PASS internals.isPreloaded('resources/preload-test.jpg?7'); is false
+PASS internals.isPreloaded('resources/base-image1.png?7'); is false
+PASS internals.isPreloaded('resources/base-image2.png?7'); is true
+PASS internals.isPreloaded('resources/base-image3.png?7'); is false
+PASS internals.isPreloaded('resources/preload-test.jpg?8'); is false
+PASS internals.isPreloaded('resources/base-image1.png?8'); is false
+PASS internals.isPreloaded('resources/base-image2.png?8'); is true
+PASS internals.isPreloaded('resources/base-image3.png?8'); is false
+PASS internals.isPreloaded('resources/preload-test.jpg?9'); is false
+PASS internals.isPreloaded('resources/base-image1.png?9'); is false
+PASS internals.isPreloaded('resources/base-image2.png?9'); is true
+PASS internals.isPreloaded('resources/base-image3.png?9'); is false
+PASS internals.isPreloaded('resources/dup-image1.png?7'); is false
+PASS internals.isPreloaded('resources/dup-image1.png?8'); is false
+PASS internals.isPreloaded('resources/dup-image2.png?8'); is false
+PASS internals.isPreloaded('resources/dup-image3.png?8'); is false
+PASS internals.isPreloaded('resources/preload-test.jpg?10'); is false
+PASS internals.isPreloaded('resources/base-image1.png?10'); is true
+PASS internals.isPreloaded('resources/base-image2.png?10'); is false
+PASS internals.isPreloaded('resources/base-image3.png?10'); is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+                  
diff --git a/LayoutTests/http/tests/loading/hidpi-preload-picture-sizes.html b/LayoutTests/http/tests/loading/hidpi-preload-picture-sizes.html
new file mode 100644 (file)
index 0000000..995cf3e
--- /dev/null
@@ -0,0 +1,77 @@
+<html>
+<head>
+<script src="/js-test-resources/js-test.js"></script>
+<script src="../resources/srcset-helper.js"></script>
+<script src="http://127.0.0.1:8000/resources/slow-script.pl?delay=100"></script>
+<script src="resources/picture-preload-helper.js"></script>
+</head>
+<body>
+<script>
+    if (window.testRunner)
+        testRunner.dumpAsText();
+    shouldBeTrue("internals.isPreloaded('resources/image2.png');");
+    for (var i = 1; i <= 9; ++i) {
+        loadFromSource2x(i);
+    }
+    shouldBeFalse("internals.isPreloaded('resources/dup-image1.png?7');");
+    shouldBeFalse("internals.isPreloaded('resources/dup-image1.png?8');");
+    shouldBeFalse("internals.isPreloaded('resources/dup-image2.png?8');");
+    shouldBeFalse("internals.isPreloaded('resources/dup-image3.png?8');");
+    shouldBeFalse("internals.isPreloaded('resources/preload-test.jpg?10');");
+    shouldBeTrue("internals.isPreloaded('resources/base-image1.png?10');");
+    shouldBeFalse("internals.isPreloaded('resources/base-image2.png?10');");
+    shouldBeFalse("internals.isPreloaded('resources/base-image3.png?10');");
+</script>
+<!-- Control group -->
+<picture>
+    <source srcset="resources/image2.png">
+    <img src="preload-test.jpg?1">
+</picture>
+<!-- All permutations of src, srcset and sizes -->
+<picture>
+    <source sizes="400px" srcset="resources/base-image1.png?1 200w, resources/base-image3.png?1 400w, resources/base-image2.png?1 800w">
+    <img src="preload-test.jpg?1">
+</picture>
+<picture>
+    <source srcset="resources/base-image1.png?2 200w, resources/base-image3.png?2 400w, resources/base-image2.png?2 800w" sizes="400px">
+    <img src="preload-test.jpg?2">
+</picture>
+<picture>
+    <source sizes="400px" srcset="resources/base-image1.png?3 200w, resources/base-image3.png?3 400w, resources/base-image2.png?3 800w">
+    <img src="preload-test.jpg?3">
+</picture>
+<picture>
+    <source sizes="400px" srcset="resources/base-image1.png?4 200w, resources/base-image3.png?4 400w, resources/base-image2.png?4 800w">
+    <img src="preload-test.jpg?4">
+</picture>
+<picture>
+    <source srcset="resources/base-image1.png?5 200w, resources/base-image3.png?5 400w, resources/base-image2.png?5 800w" sizes="400px">
+    <img src="preload-test.jpg?5">
+</picture>
+<picture>
+    <source srcset="resources/base-image1.png?6 200w, resources/base-image3.png?6 400w, resources/base-image2.png?6 800w" sizes="400px">
+    <img src="preload-test.jpg?6">
+</picture>
+<!-- Duplicate attributes -->
+<picture>
+    <source srcset="resources/base-image1.png?7 200w, resources/base-image3.png?7 400w, resources/base-image2.png?7 800w" sizes="400px"
+     src="resources/dup-image1.png?7">
+    <img src="preload-test.jpg?7">
+</picture>
+<picture>
+    <source srcset="resources/base-image1.png?8 200w, resources/base-image3.png?8 400w, resources/base-image2.png?8 800w" sizes="400px"
+     srcset="resources/dup-image1.png?8 200w, resources/dup-image3.png?8 400w, resources/dup-image2.png?8 800w">
+    <img src="preload-test.jpg?8">
+</picture>
+<picture>
+    <source srcset="resources/base-image1.png?9 200w, resources/base-image3.png?9 400w, resources/base-image2.png?9 800w" sizes="400px"
+     sizes="800px">
+    <img src="preload-test.jpg?9">
+</picture>
+<!-- Sizes with 'x' descriptors -->
+<picture>
+    <source srcset="resources/preload-test.jpg?10, resources/base-image1.png?10 2x, resources/base-image3.png?10 4x, resources/base-image2.png?10 8x" sizes="400px">
+    <img src="preload-test.jpg?10">
+</picture>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/loading/preload-picture-invalid-expected.txt b/LayoutTests/http/tests/loading/preload-picture-invalid-expected.txt
new file mode 100644 (file)
index 0000000..fabcd9b
--- /dev/null
@@ -0,0 +1,40 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+main frame - didHandleOnloadEventsForFrame
+main frame - didFinishLoadForFrame
+PASS internals.isPreloaded('resources/preload-test.jpg?0'); is true
+PASS internals.isPreloaded('resources/image2.png'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?2'); is true
+PASS internals.isPreloaded('resources/base-image1.png?2'); is false
+PASS internals.isPreloaded('resources/base-image2.png?2'); is false
+PASS internals.isPreloaded('resources/base-image3.png?2'); is false
+PASS internals.isPreloaded('resources/preload-test.jpg?3'); is false
+PASS internals.isPreloaded('resources/base-image1.png?3'); is false
+PASS internals.isPreloaded('resources/base-image2.png?3'); is false
+PASS internals.isPreloaded('resources/base-image3.png?3'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?4'); is false
+PASS internals.isPreloaded('resources/base-image1.png?4'); is false
+PASS internals.isPreloaded('resources/base-image2.png?4'); is false
+PASS internals.isPreloaded('resources/base-image3.png?4'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?5'); is false
+PASS internals.isPreloaded('resources/base-image1.png?5'); is false
+PASS internals.isPreloaded('resources/base-image2.png?5'); is false
+PASS internals.isPreloaded('resources/base-image3.png?5'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?6'); is true
+PASS internals.isPreloaded('resources/base-image1.png?6'); is false
+PASS internals.isPreloaded('resources/base-image2.png?6'); is false
+PASS internals.isPreloaded('resources/base-image3.png?6'); is false
+PASS internals.isPreloaded('resources/preload-test.jpg?7'); is true
+PASS internals.isPreloaded('resources/base-image1.png?7'); is false
+PASS internals.isPreloaded('resources/base-image2.png?7'); is false
+PASS internals.isPreloaded('resources/base-image3.png?7'); is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+  
+
+  bla 
+  
diff --git a/LayoutTests/http/tests/loading/preload-picture-invalid.html b/LayoutTests/http/tests/loading/preload-picture-invalid.html
new file mode 100644 (file)
index 0000000..eedf0b4
--- /dev/null
@@ -0,0 +1,84 @@
+<html>
+<head>
+<script src="/js-test-resources/js-test.js"></script>
+<script src="http://127.0.0.1:8000/resources/slow-script.pl?delay=100"></script>
+<script src="resources/picture-preload-helper.js"></script>
+</head>
+<body>
+<script>
+    if (window.testRunner)
+        testRunner.dumpAsText();
+    shouldBeTrue("internals.isPreloaded('resources/preload-test.jpg?0');");
+    shouldBeTrue("internals.isPreloaded('resources/image2.png');");
+    loadFromImg(2);
+    loadFromSource(3);
+    loadFromSource(4);
+    loadFromSource(5);
+    loadFromImg(6);
+    loadFromImg(7);
+</script>
+<!-- Control group -->
+<img src="resources/preload-test.jpg?0">
+<picture>
+<source srcset="resources/image2.png">
+<img></picture>
+<!-- Invalid nesting tests -->
+<!-- In the following tests, nesting messes up the selection algorithm -->
+<picture>
+    <picture>
+        <source sizes="400px" srcset="resources/base-image1.png?1 200w, resources/base-image3.png?1 400w, resources/base-image2.png?1 800w">
+        <div>
+            </picture>
+        </div>
+        <img src="resources/preload-test.jpg?1">
+    </picture>
+</picture>
+<picture>
+    <div>
+        </picture>
+        </picture>
+        </picture>
+    </div>
+    <source sizes="400px" srcset="resources/base-image1.png?2 200w, resources/base-image3.png?2 400w, resources/base-image2.png?2 800w">
+    <img src="resources/preload-test.jpg?2">
+</picture>
+<!-- Here we preload the correct resource, since document.write is not modifying the DOM -->
+<picture>
+    <script>document.write("bla");</script>
+    <source sizes="400px" srcset="resources/base-image1.png?3 200w, resources/base-image3.png?3 400w, resources/base-image2.png?3 800w">
+    <img src="resources/preload-test.jpg?3">
+</picture>
+<!-- In the following tests, nesting messes up the selection algorithm, but we don't get it -->
+<picture>
+    <div>
+        <picture>
+            <div>
+                <source sizes="400px" srcset="resources/base-image1.png?4 200w, resources/base-image3.png?4 400w, resources/base-image2.png?4 800w">
+            </div>
+            <img src="resources/preload-test.jpg?4">
+        </picture>
+    </div>
+</picture>
+<picture>
+    <div>
+        <picture>
+            <div>
+                <source sizes="400px" srcset="resources/base-image1.png?5 200w, resources/base-image3.png?5 400w, resources/base-image2.png?5 800w">
+                <img src="resources/preload-test.jpg?5">
+            </div>
+        </picture>
+    </div>
+</picture>
+<!-- We don't keep a checkpoint of the picture stack, so document.write inside picture 
+     *that modifies the DOM* will result in a false prediction -->
+<!-- In the following tests, we preload the wrong resource, because document.write is modifying the DOM -->
+<script>document.write('<picture>');</script>
+    <source sizes="400px" srcset="resources/base-image1.png?6 200w, resources/base-image3.png?6 400w, resources/base-image2.png?6 800w">
+    <img src="resources/preload-test.jpg?6">
+</picture>
+<picture>
+    <script>document.write('<source sizes="400px" srcset="resources/base-image1.png?7 200w, resources/base-image3.png?7 400w, resources/base-image2.png?7 800w">');</script>
+    <img src="resources/preload-test.jpg?7">
+</picture>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/loading/preload-picture-nested-expected.txt b/LayoutTests/http/tests/loading/preload-picture-nested-expected.txt
new file mode 100644 (file)
index 0000000..129c11b
--- /dev/null
@@ -0,0 +1,47 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+main frame - didHandleOnloadEventsForFrame
+main frame - didFinishLoadForFrame
+PASS internals.isPreloaded('resources/preload-test.jpg?0'); is true
+PASS internals.isPreloaded('resources/image2.png'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?1'); is false
+PASS internals.isPreloaded('resources/base-image1.png?1'); is false
+PASS internals.isPreloaded('resources/base-image2.png?1'); is false
+PASS internals.isPreloaded('resources/base-image3.png?1'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?2'); is false
+PASS internals.isPreloaded('resources/base-image1.png?2'); is false
+PASS internals.isPreloaded('resources/base-image2.png?2'); is false
+PASS internals.isPreloaded('resources/base-image3.png?2'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?3'); is false
+PASS internals.isPreloaded('resources/base-image1.png?3'); is false
+PASS internals.isPreloaded('resources/base-image2.png?3'); is false
+PASS internals.isPreloaded('resources/base-image3.png?3'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?4'); is false
+PASS internals.isPreloaded('resources/base-image1.png?4'); is false
+PASS internals.isPreloaded('resources/base-image2.png?4'); is false
+PASS internals.isPreloaded('resources/base-image3.png?4'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?5'); is false
+PASS internals.isPreloaded('resources/base-image1.png?5'); is false
+PASS internals.isPreloaded('resources/base-image2.png?5'); is false
+PASS internals.isPreloaded('resources/base-image3.png?5'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?6'); is false
+PASS internals.isPreloaded('resources/base-image1.png?6'); is false
+PASS internals.isPreloaded('resources/base-image2.png?6'); is false
+PASS internals.isPreloaded('resources/base-image3.png?6'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?7'); is false
+PASS internals.isPreloaded('resources/base-image1.png?7'); is false
+PASS internals.isPreloaded('resources/base-image2.png?7'); is false
+PASS internals.isPreloaded('resources/base-image3.png?7'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?71'); is false
+PASS internals.isPreloaded('resources/preload-test.jpg?72'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?8'); is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+   
+
+      
diff --git a/LayoutTests/http/tests/loading/preload-picture-nested.html b/LayoutTests/http/tests/loading/preload-picture-nested.html
new file mode 100644 (file)
index 0000000..f38226a
--- /dev/null
@@ -0,0 +1,77 @@
+<html>
+<head>
+<script src="/js-test-resources/js-test.js"></script>
+<script src="http://127.0.0.1:8000/resources/slow-script.pl?delay=100"></script>
+<script src="resources/picture-preload-helper.js"></script>
+</head>
+<body>
+<script>
+    if (window.testRunner)
+        testRunner.dumpAsText();
+    shouldBeTrue("internals.isPreloaded('resources/preload-test.jpg?0');");
+    shouldBeTrue("internals.isPreloaded('resources/image2.png');");
+    loadFromSource(1);
+    loadFromSource(2);
+    loadFromSource(3);
+    loadFromSource(4);
+    loadFromSource(5);
+    loadFromSource(6);
+    loadFromSource(7);
+    shouldBeFalse("internals.isPreloaded('resources/preload-test.jpg?71');");
+    shouldBeTrue("internals.isPreloaded('resources/preload-test.jpg?72');");
+    shouldBeTrue("internals.isPreloaded('resources/preload-test.jpg?8');");
+</script>
+<!-- Control group -->
+<img src="resources/preload-test.jpg?0">
+<picture>
+<source srcset="resources/image2.png">
+<img></picture>
+<!-- nested element tests  - In these we're doing the right thing -->
+<picture>
+    <picture>
+        <source sizes="400px" srcset="resources/base-image1.png?1 200w, resources/base-image3.png?1 400w, resources/base-image2.png?1 800w">
+        <img src="resources/preload-test.jpg?1">
+    </picture>
+</picture>
+<picture>
+    <div>
+        <picture>
+            <source sizes="400px" srcset="resources/base-image1.png?2 200w, resources/base-image3.png?2 400w, resources/base-image2.png?2 800w">
+            <img src="resources/preload-test.jpg?2">
+        </picture>
+    </div>
+</picture>
+<picture>
+    <source sizes="400px" srcset="resources/base-image1.png?3 200w, resources/base-image3.png?3 400w, resources/base-image2.png?3 800w">
+    <div>
+        <picture>
+            <source sizes="400px" srcset="resources/base-image1.png?4 200w, resources/base-image3.png?4 400w, resources/base-image2.png?4 800w">
+            <img src="resources/preload-test.jpg?4">
+        </picture>
+    </div>
+    <img src="resources/preload-test.jpg?3">
+</picture>
+<picture>
+    <source sizes="400px" srcset="resources/base-image1.png?5 200w, resources/base-image3.png?5 400w, resources/base-image2.png?5 800w">
+    <div />
+        <picture>
+            <source sizes="400px" srcset="resources/base-image1.png?6 200w, resources/base-image3.png?6 400w, resources/base-image2.png?6 800w">
+            <!-- We're getting this one right -->
+            <img src="resources/preload-test.jpg?6">
+        </picture>
+    </div>
+    <img src="resources/preload-test.jpg?5">
+</picture>
+<picture>
+    <picture>
+        <source sizes="400px" srcset="resources/base-image1.png?7 200w, resources/base-image3.png?7 400w, resources/base-image2.png?7 800w">
+        <img src="resources/preload-test.jpg?7">
+        <img src="resources/preload-test.jpg?71">
+    </picture>
+    <img src="resources/preload-test.jpg?72">
+</picture>
+<picture>
+    <img src="resources/preload-test.jpg?8">
+</picture>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/loading/preload-picture-sizes-expected.txt b/LayoutTests/http/tests/loading/preload-picture-sizes-expected.txt
new file mode 100644 (file)
index 0000000..e37c03f
--- /dev/null
@@ -0,0 +1,62 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+main frame - didHandleOnloadEventsForFrame
+main frame - didFinishLoadForFrame
+PASS internals.isPreloaded('resources/image2.png'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?1'); is false
+PASS internals.isPreloaded('resources/base-image1.png?1'); is false
+PASS internals.isPreloaded('resources/base-image2.png?1'); is false
+PASS internals.isPreloaded('resources/base-image3.png?1'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?2'); is false
+PASS internals.isPreloaded('resources/base-image1.png?2'); is false
+PASS internals.isPreloaded('resources/base-image2.png?2'); is false
+PASS internals.isPreloaded('resources/base-image3.png?2'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?3'); is false
+PASS internals.isPreloaded('resources/base-image1.png?3'); is false
+PASS internals.isPreloaded('resources/base-image2.png?3'); is false
+PASS internals.isPreloaded('resources/base-image3.png?3'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?4'); is false
+PASS internals.isPreloaded('resources/base-image1.png?4'); is false
+PASS internals.isPreloaded('resources/base-image2.png?4'); is false
+PASS internals.isPreloaded('resources/base-image3.png?4'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?5'); is false
+PASS internals.isPreloaded('resources/base-image1.png?5'); is false
+PASS internals.isPreloaded('resources/base-image2.png?5'); is false
+PASS internals.isPreloaded('resources/base-image3.png?5'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?6'); is false
+PASS internals.isPreloaded('resources/base-image1.png?6'); is false
+PASS internals.isPreloaded('resources/base-image2.png?6'); is false
+PASS internals.isPreloaded('resources/base-image3.png?6'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?7'); is false
+PASS internals.isPreloaded('resources/base-image1.png?7'); is false
+PASS internals.isPreloaded('resources/base-image2.png?7'); is false
+PASS internals.isPreloaded('resources/base-image3.png?7'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?8'); is false
+PASS internals.isPreloaded('resources/base-image1.png?8'); is false
+PASS internals.isPreloaded('resources/base-image2.png?8'); is false
+PASS internals.isPreloaded('resources/base-image3.png?8'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?9'); is false
+PASS internals.isPreloaded('resources/base-image1.png?9'); is false
+PASS internals.isPreloaded('resources/base-image2.png?9'); is false
+PASS internals.isPreloaded('resources/base-image3.png?9'); is true
+PASS internals.isPreloaded('resources/preload-test.jpg?10'); is false
+PASS internals.isPreloaded('resources/base-image1.png?10'); is false
+PASS internals.isPreloaded('resources/base-image2.png?10'); is false
+PASS internals.isPreloaded('resources/base-image3.png?10'); is true
+PASS internals.isPreloaded('resources/dup-image1.png?7'); is false
+PASS internals.isPreloaded('resources/dup-image1.png?8'); is false
+PASS internals.isPreloaded('resources/dup-image2.png?8'); is false
+PASS internals.isPreloaded('resources/dup-image3.png?8'); is false
+PASS internals.isPreloaded('resources/base-image1.png?101'); is false
+PASS internals.isPreloaded('resources/base-image2.png?101'); is false
+PASS internals.isPreloaded('resources/base-image3.png?101'); is false
+PASS internals.isPreloaded('resources/preload-test.jpg?10'); is false
+PASS internals.isPreloaded('resources/preload-test.jpg?11'); is true
+PASS internals.isPreloaded('resources/base-image1.png?11'); is false
+PASS internals.isPreloaded('resources/base-image2.png?11'); is false
+PASS internals.isPreloaded('resources/base-image3.png?11'); is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+             
diff --git a/LayoutTests/http/tests/loading/preload-picture-sizes.html b/LayoutTests/http/tests/loading/preload-picture-sizes.html
new file mode 100644 (file)
index 0000000..905fee6
--- /dev/null
@@ -0,0 +1,85 @@
+<html>
+<head>
+<script src="/js-test-resources/js-test.js"></script>
+<script src="http://127.0.0.1:8000/resources/slow-script.pl?delay=100"></script>
+<script src="resources/picture-preload-helper.js"></script>
+</head>
+<body>
+<script>
+    if (window.testRunner)
+        testRunner.dumpAsText();
+    shouldBeTrue("internals.isPreloaded('resources/image2.png');");
+    for (var i = 1; i <= 10; ++i) {
+        loadFromSource(i);
+    }
+    shouldBeFalse("internals.isPreloaded('resources/dup-image1.png?7');");
+    shouldBeFalse("internals.isPreloaded('resources/dup-image1.png?8');");
+    shouldBeFalse("internals.isPreloaded('resources/dup-image2.png?8');");
+    shouldBeFalse("internals.isPreloaded('resources/dup-image3.png?8');");
+    shouldBeFalse("internals.isPreloaded('resources/base-image1.png?101');");
+    shouldBeFalse("internals.isPreloaded('resources/base-image2.png?101');");
+    shouldBeFalse("internals.isPreloaded('resources/base-image3.png?101');");
+    shouldBeFalse("internals.isPreloaded('resources/preload-test.jpg?10');");
+    loadFromImg(11);
+</script>
+<!-- Control group -->
+<picture>
+    <source srcset="resources/image2.png">
+    <img src="preload-test.jpg?1">
+</picture>
+<!-- All permutations of src, srcset and sizes -->
+<picture>
+    <source sizes="400px" srcset="resources/base-image1.png?1 200w, resources/base-image3.png?1 400w, resources/base-image2.png?1 800w">
+    <img src="preload-test.jpg?1">
+</picture>
+<picture>
+    <source srcset="resources/base-image1.png?2 200w, resources/base-image3.png?2 400w, resources/base-image2.png?2 800w" sizes="400px">
+    <img src="preload-test.jpg?2">
+</picture>
+<picture>
+    <source sizes="400px" srcset="resources/base-image1.png?3 200w, resources/base-image3.png?3 400w, resources/base-image2.png?3 800w">
+    <img src="preload-test.jpg?3">
+</picture>
+<picture>
+    <source sizes="400px" srcset="resources/base-image1.png?4 200w, resources/base-image3.png?4 400w, resources/base-image2.png?4 800w">
+    <img src="preload-test.jpg?4">
+</picture>
+<picture>
+    <source srcset="resources/base-image1.png?5 200w, resources/base-image3.png?5 400w, resources/base-image2.png?5 800w" sizes="400px">
+    <img src="preload-test.jpg?5">
+</picture>
+<picture>
+    <source srcset="resources/base-image1.png?6 200w, resources/base-image3.png?6 400w, resources/base-image2.png?6 800w" sizes="400px">
+    <img src="preload-test.jpg?6">
+</picture>
+<!-- Duplicate attributes -->
+<picture>
+    <source srcset="resources/base-image1.png?7 200w, resources/base-image3.png?7 400w, resources/base-image2.png?7 800w" sizes="400px"
+     src="resources/dup-image1.png?7">
+    <img src="preload-test.jpg?7">
+</picture>
+<picture>
+    <source srcset="resources/base-image1.png?8 200w, resources/base-image3.png?8 400w, resources/base-image2.png?8 800w" sizes="400px"
+     srcset="resources/dup-image1.png?8 200w, resources/dup-image3.png?8 400w, resources/dup-image2.png?8 800w">
+    <img src="preload-test.jpg?8">
+</picture>
+<picture>
+    <source srcset="resources/base-image1.png?9 200w, resources/base-image3.png?9 400w, resources/base-image2.png?9 800w" sizes="400px"
+     sizes="800px">
+    <img src="preload-test.jpg?9">
+</picture>
+<!-- Multiple sources -->
+<picture>
+    <source media="(max-width: 500px)" srcset="resources/base-image1.png?101 200w, resources/base-image3.png?101 400w,
+    resources/base-image2.png?101 10100w" sizes="400px">
+    <source media="(min-width: 501px)" srcset="resources/base-image1.png?10 200w, resources/base-image3.png?10 400w,
+    resources/base-image2.png?10 1000w" sizes="400px">
+    <img src="preload-test.jpg?10">
+</picture>
+<!-- Sizes with 'x' descriptors -->
+<picture>
+    <source srcset="resources/preload-test.jpg?11, resources/base-image1.png?11 2x, resources/base-image3.png?11 4x, resources/base-image2.png?11 8x" sizes="400px">
+    <img src="preload-test.jpg?11">
+</picture>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/loading/resources/base-image1.png b/LayoutTests/http/tests/loading/resources/base-image1.png
new file mode 100644 (file)
index 0000000..c8aea6f
Binary files /dev/null and b/LayoutTests/http/tests/loading/resources/base-image1.png differ
diff --git a/LayoutTests/http/tests/loading/resources/base-image2.png b/LayoutTests/http/tests/loading/resources/base-image2.png
new file mode 100644 (file)
index 0000000..c8aea6f
Binary files /dev/null and b/LayoutTests/http/tests/loading/resources/base-image2.png differ
diff --git a/LayoutTests/http/tests/loading/resources/base-image3.png b/LayoutTests/http/tests/loading/resources/base-image3.png
new file mode 100644 (file)
index 0000000..c8aea6f
Binary files /dev/null and b/LayoutTests/http/tests/loading/resources/base-image3.png differ
diff --git a/LayoutTests/http/tests/loading/resources/dup-image1.png b/LayoutTests/http/tests/loading/resources/dup-image1.png
new file mode 100644 (file)
index 0000000..c8aea6f
Binary files /dev/null and b/LayoutTests/http/tests/loading/resources/dup-image1.png differ
diff --git a/LayoutTests/http/tests/loading/resources/dup-image2.png b/LayoutTests/http/tests/loading/resources/dup-image2.png
new file mode 100644 (file)
index 0000000..c8aea6f
Binary files /dev/null and b/LayoutTests/http/tests/loading/resources/dup-image2.png differ
diff --git a/LayoutTests/http/tests/loading/resources/dup-image3.png b/LayoutTests/http/tests/loading/resources/dup-image3.png
new file mode 100644 (file)
index 0000000..c8aea6f
Binary files /dev/null and b/LayoutTests/http/tests/loading/resources/dup-image3.png differ
diff --git a/LayoutTests/http/tests/loading/resources/image1.png b/LayoutTests/http/tests/loading/resources/image1.png
new file mode 100644 (file)
index 0000000..c8aea6f
Binary files /dev/null and b/LayoutTests/http/tests/loading/resources/image1.png differ
diff --git a/LayoutTests/http/tests/loading/resources/image2.png b/LayoutTests/http/tests/loading/resources/image2.png
new file mode 100644 (file)
index 0000000..c8aea6f
Binary files /dev/null and b/LayoutTests/http/tests/loading/resources/image2.png differ
diff --git a/LayoutTests/http/tests/loading/resources/picture-preload-helper.js b/LayoutTests/http/tests/loading/resources/picture-preload-helper.js
new file mode 100644 (file)
index 0000000..4d62f39
--- /dev/null
@@ -0,0 +1,18 @@
+function loadFromSource(i) {
+    shouldBeFalse("internals.isPreloaded('resources/preload-test.jpg?" + i + "');");
+    shouldBeFalse("internals.isPreloaded('resources/base-image1.png?" + i + "');");
+    shouldBeFalse("internals.isPreloaded('resources/base-image2.png?" + i + "');");
+    shouldBeTrue("internals.isPreloaded('resources/base-image3.png?" + i + "');");
+}
+function loadFromSource2x(i) {
+    shouldBeFalse("internals.isPreloaded('resources/preload-test.jpg?" + i + "');");
+    shouldBeFalse("internals.isPreloaded('resources/base-image1.png?" + i + "');");
+    shouldBeTrue("internals.isPreloaded('resources/base-image2.png?" + i + "');");
+    shouldBeFalse("internals.isPreloaded('resources/base-image3.png?" + i + "');");
+}
+function loadFromImg(i) {
+    shouldBeTrue("internals.isPreloaded('resources/preload-test.jpg?" + i + "');");
+    shouldBeFalse("internals.isPreloaded('resources/base-image1.png?" + i + "');");
+    shouldBeFalse("internals.isPreloaded('resources/base-image2.png?" + i + "');");
+    shouldBeFalse("internals.isPreloaded('resources/base-image3.png?" + i + "');");
+}
index 44a83a1..54ff8ba 100644 (file)
@@ -1,3 +1,26 @@
+2016-01-11  Dave Hyatt  <hyatt@apple.com>
+
+        Picture element needs to work with the preload scanner and select the correct
+        source element instead of loading the image.
+        https://bugs.webkit.org/show_bug.cgi?id=152983
+
+        Reviewed by Dean Jackson.
+
+        Added new tests in http/tests/loading.
+
+        * html/parser/HTMLPreloadScanner.cpp:
+        (WebCore::TokenPreloadScanner::tagIdFor):
+        (WebCore::TokenPreloadScanner::initiatorFor):
+        (WebCore::TokenPreloadScanner::StartTagScanner::StartTagScanner):
+        (WebCore::TokenPreloadScanner::StartTagScanner::processAttributes):
+        (WebCore::TokenPreloadScanner::StartTagScanner::processImageAndScriptAttribute):
+        (WebCore::TokenPreloadScanner::StartTagScanner::processAttribute):
+        (WebCore::TokenPreloadScanner::StartTagScanner::resourceType):
+        (WebCore::TokenPreloadScanner::scan):
+        * html/parser/HTMLPreloadScanner.h:
+        (WebCore::TokenPreloadScanner::setPredictedBaseElementURL):
+        (WebCore::TokenPreloadScanner::inPicture):
+
 2016-01-11  Brady Eidson  <beidson@apple.com>
 
         Modern IDB: storage/indexeddb/key-generator.html fails.
index 4f15ef9..d8304dc 100644 (file)
@@ -34,6 +34,8 @@
 #include "HTMLTokenizer.h"
 #include "InputTypeNames.h"
 #include "LinkRelAttribute.h"
+#include "MediaList.h"
+#include "MediaQueryEvaluator.h"
 #include "SourceSizeList.h"
 #include <wtf/MainThread.h>
 
@@ -62,6 +64,10 @@ TokenPreloadScanner::TagId TokenPreloadScanner::tagIdFor(const HTMLToken::DataVe
         return TagId::Template;
     if (tagName == metaTag)
         return TagId::Meta;
+    if (tagName == pictureTag)
+        return TagId::Picture;
+    if (tagName == sourceTag)
+        return TagId::Source;
     return TagId::Unknown;
 }
 
@@ -70,6 +76,7 @@ String TokenPreloadScanner::initiatorFor(TagId tagId)
     switch (tagId) {
     case TagId::Iframe:
         return "iframe";
+    case TagId::Source:
     case TagId::Img:
         return "img";
     case TagId::Input:
@@ -83,6 +90,7 @@ String TokenPreloadScanner::initiatorFor(TagId tagId)
     case TagId::Base:
     case TagId::Template:
     case TagId::Meta:
+    case TagId::Picture:
         ASSERT_NOT_REACHED();
         return "unknown";
     }
@@ -101,22 +109,30 @@ public:
     {
     }
 
-    void processAttributes(const HTMLToken::AttributeList& attributes, Document& document)
+    void processAttributes(const HTMLToken::AttributeList& attributes, Document& document, Vector<bool>& pictureState)
     {
         ASSERT(isMainThread());
         if (m_tagId >= TagId::Unknown)
             return;
-
+        
         for (auto& attribute : attributes) {
             AtomicString attributeName(attribute.name);
             String attributeValue = StringImpl::create8BitIfPossible(attribute.value);
-            processAttribute(attributeName, attributeValue);
+            processAttribute(attributeName, attributeValue, document, pictureState);
         }
-
+        
+        if (m_tagId == TagId::Source && !pictureState.isEmpty() && !pictureState.last() && m_mediaMatched && !m_srcSetAttribute.isEmpty()) {
+            float sourceSize = parseSizesAttribute(m_sizesAttribute, document.renderView(), document.frame());
+            ImageCandidate imageCandidate = bestFitSourceForImageAttributes(m_deviceScaleFactor, m_urlToLoad, m_srcSetAttribute, sourceSize);
+            if (!imageCandidate.isEmpty()) {
+                pictureState.last() = true;
+                setUrlToLoad(imageCandidate.string.toString(), true);
+            }
+        }
+        
         // Resolve between src and srcSet if we have them and the tag is img.
         if (m_tagId == TagId::Img && !m_srcSetAttribute.isEmpty()) {
-            float sourceSize = 0;
-            sourceSize = parseSizesAttribute(m_sizesAttribute, document.renderView(), document.frame());
+            float sourceSize = parseSizesAttribute(m_sizesAttribute, document.renderView(), document.frame());
             ImageCandidate imageCandidate = bestFitSourceForImageAttributes(m_deviceScaleFactor, m_urlToLoad, m_srcSetAttribute, sourceSize);
             setUrlToLoad(imageCandidate.string.toString(), true);
         }
@@ -154,14 +170,19 @@ private:
             m_charset = attributeValue;
     }
 
-    void processAttribute(const AtomicString& attributeName, const String& attributeValue)
+    void processAttribute(const AtomicString& attributeName, const String& attributeValue, Document& document, const Vector<bool>& pictureState)
     {
+        bool inPicture = !pictureState.isEmpty();
+        bool alreadyMatchedSource = inPicture && pictureState.last();
+
         switch (m_tagId) {
         case TagId::Iframe:
             if (match(attributeName, srcAttr))
                 setUrlToLoad(attributeValue);
             break;
         case TagId::Img:
+            if (inPicture && alreadyMatchedSource)
+                break;
             if (match(attributeName, srcsetAttr) && m_srcSetAttribute.isNull()) {
                 m_srcSetAttribute = attributeValue;
                 break;
@@ -172,6 +193,25 @@ private:
             }
             processImageAndScriptAttribute(attributeName, attributeValue);
             break;
+        case TagId::Source:
+            if (inPicture && alreadyMatchedSource)
+                break;
+            if (match(attributeName, srcsetAttr) && m_srcSetAttribute.isNull()) {
+                m_srcSetAttribute = attributeValue;
+                break;
+            }
+            if (match(attributeName, sizesAttr) && m_sizesAttribute.isNull()) {
+                m_sizesAttribute = attributeValue;
+                break;
+            }
+            if (match(attributeName, mediaAttr) && m_mediaAttribute.isNull()) {
+                m_mediaAttribute = attributeValue;
+                Ref<MediaQuerySet> mediaSet = MediaQuerySet::createAllowingDescriptionSyntax(attributeValue);
+                Vector<std::unique_ptr<MediaQueryResult>> viewportDependentMediaQueryResults;
+                MediaQueryEvaluator evaluator(document.printing() ? "print" : "screen", document.frame(), document.documentElement()->computedStyle());
+                m_mediaMatched = evaluator.evalCheckingViewportDependentResults(mediaSet.ptr(), viewportDependentMediaQueryResults);
+            }
+            break;
         case TagId::Script:
             processImageAndScriptAttribute(attributeName, attributeValue);
             break;
@@ -200,6 +240,7 @@ private:
         case TagId::Base:
         case TagId::Style:
         case TagId::Template:
+        case TagId::Picture:
         case TagId::Unknown:
             break;
         }
@@ -237,6 +278,7 @@ private:
             return CachedResource::Script;
         case TagId::Img:
         case TagId::Input:
+        case TagId::Source:
             ASSERT(m_tagId != TagId::Input || m_inputIsImage);
             return CachedResource::ImageResource;
         case TagId::Link:
@@ -247,6 +289,7 @@ private:
         case TagId::Style:
         case TagId::Base:
         case TagId::Template:
+        case TagId::Picture:
             break;
         }
         ASSERT_NOT_REACHED();
@@ -279,6 +322,7 @@ private:
     String m_urlToLoad;
     String m_srcSetAttribute;
     String m_sizesAttribute;
+    bool m_mediaMatched { true };
     String m_charset;
     String m_crossOriginMode;
     bool m_linkIsStyleSheet;
@@ -317,7 +361,9 @@ void TokenPreloadScanner::scan(const HTMLToken& token, Vector<std::unique_ptr<Pr
             if (m_inStyle)
                 m_cssScanner.reset();
             m_inStyle = false;
-        }
+        } else if (tagId == TagId::Picture && !m_pictureSourceState.isEmpty())
+            m_pictureSourceState.removeLast();
+
         return;
     }
 
@@ -344,9 +390,13 @@ void TokenPreloadScanner::scan(const HTMLToken& token, Vector<std::unique_ptr<Pr
             updatePredictedBaseURL(token);
             return;
         }
+        if (tagId == TagId::Picture) {
+            m_pictureSourceState.append(false);
+            return;
+        }
 
         StartTagScanner scanner(tagId, m_deviceScaleFactor);
-        scanner.processAttributes(token.attributes(), document);
+        scanner.processAttributes(token.attributes(), document, m_pictureSourceState);
         if (auto request = scanner.createPreloadRequest(m_predictedBaseElementURL))
             requests.append(WTFMove(request));
         return;
index c93db6e..4ea760d 100644 (file)
@@ -41,6 +41,8 @@ public:
     void scan(const HTMLToken&, PreloadRequestStream&, Document&);
 
     void setPredictedBaseElementURL(const URL& url) { m_predictedBaseElementURL = url; }
+    
+    bool inPicture() { return !m_pictureSourceState.isEmpty(); }
 
 private:
     enum class TagId {
@@ -51,12 +53,14 @@ private:
         Link,
         Script,
         Meta,
+        Source,
 
         // These tags are not scanned by the StartTagScanner.
         Unknown,
         Style,
         Base,
         Template,
+        Picture
     };
 
     class StartTagScanner;
@@ -73,6 +77,9 @@ private:
 
     URL m_predictedBaseElementURL;
     bool m_inStyle { false };
+    
+    Vector<bool> m_pictureSourceState;
+
 #if ENABLE(TEMPLATE_ELEMENT)
     unsigned m_templateCount { 0 };
 #endif