Add support for DOMTokenList.supports()
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 28 Sep 2016 23:49:50 +0000 (23:49 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 28 Sep 2016 23:49:50 +0000 (23:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=162659

Reviewed by Ryosuke Niwa.

LayoutTests/imported/w3c:

Rebaseline W3C tests now that more checks are passing.

* web-platform-tests/dom/interfaces-expected.txt:
* web-platform-tests/html/semantics/document-metadata/the-link-element/link-rellist-expected.txt:

Source/WebCore:

Add support for DOMTokenList.supports():
- https://dom.spec.whatwg.org/#dom-domtokenlist-supports

Firefox and Chrome already recently implemented it (Chrome since
version 50 and Firefox since version 49).

Test: fast/dom/DOMTokenList-supports.html

* dom/SecurityContext.cpp:
(WebCore::SecurityContext::isSupportedSandboxPolicy):
(WebCore::SecurityContext::enforceSandboxFlags): Deleted.
* dom/SecurityContext.h:
* html/DOMTokenList.cpp:
(WebCore::DOMTokenList::DOMTokenList):
(WebCore::DOMTokenList::supports):
(WebCore::DOMTokenList::replace): Deleted.
* html/DOMTokenList.h:
(WebCore::DOMTokenList::DOMTokenList):
* html/DOMTokenList.idl:
* html/HTMLAnchorElement.cpp:
(WebCore::HTMLAnchorElement::parseAttribute):
(WebCore::HTMLAnchorElement::relList):
* html/HTMLAnchorElement.idl:
* html/HTMLAreaElement.idl:
* html/HTMLIFrameElement.cpp:
(WebCore::HTMLIFrameElement::sandbox):
* html/HTMLLinkElement.cpp:
(WebCore::HTMLLinkElement::relList):
* html/HTMLTableCellElement.idl:
* html/LinkRelAttribute.cpp:
(WebCore::LinkRelAttribute::isSupported):
(WebCore::LinkRelAttribute::LinkRelAttribute): Deleted.
* html/LinkRelAttribute.h:

LayoutTests:

Add layout test coverage. Our pass rate is identical to Firefox 49,
everything passes except HTMLElement.dropzone. Chrome 53's pass rate
is lower because relList is not a DOMTokenList on anchor / area,
they do not support HTMLElement.dropzone and their
DOMTokenList.supports() is case-sensitive.

* fast/dom/DOMTokenList-supports-expected.txt: Added.
* fast/dom/DOMTokenList-supports.html: Added.

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

20 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/dom/DOMTokenList-supports-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/DOMTokenList-supports.html [new file with mode: 0644]
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/dom/interfaces-expected.txt
LayoutTests/imported/w3c/web-platform-tests/html/semantics/document-metadata/the-link-element/link-rellist-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/dom/SecurityContext.cpp
Source/WebCore/dom/SecurityContext.h
Source/WebCore/html/DOMTokenList.cpp
Source/WebCore/html/DOMTokenList.h
Source/WebCore/html/DOMTokenList.idl
Source/WebCore/html/HTMLAnchorElement.cpp
Source/WebCore/html/HTMLAnchorElement.idl
Source/WebCore/html/HTMLAreaElement.idl
Source/WebCore/html/HTMLIFrameElement.cpp
Source/WebCore/html/HTMLLinkElement.cpp
Source/WebCore/html/HTMLTableCellElement.idl
Source/WebCore/html/LinkRelAttribute.cpp
Source/WebCore/html/LinkRelAttribute.h

index 1e0d988..2afc11e 100644 (file)
@@ -1,3 +1,19 @@
+2016-09-28  Chris Dumez  <cdumez@apple.com>
+
+        Add support for DOMTokenList.supports()
+        https://bugs.webkit.org/show_bug.cgi?id=162659
+
+        Reviewed by Ryosuke Niwa.
+
+        Add layout test coverage. Our pass rate is identical to Firefox 49,
+        everything passes except HTMLElement.dropzone. Chrome 53's pass rate
+        is lower because relList is not a DOMTokenList on anchor / area,
+        they do not support HTMLElement.dropzone and their
+        DOMTokenList.supports() is case-sensitive.
+
+        * fast/dom/DOMTokenList-supports-expected.txt: Added.
+        * fast/dom/DOMTokenList-supports.html: Added.
+
 2016-09-28  Ryosuke Niwa  <rniwa@webkit.org>
 
         DOMTokenList’s value and stringifier should not return parsed tokens
diff --git a/LayoutTests/fast/dom/DOMTokenList-supports-expected.txt b/LayoutTests/fast/dom/DOMTokenList-supports-expected.txt
new file mode 100644 (file)
index 0000000..823204d
--- /dev/null
@@ -0,0 +1,62 @@
+Test support for DOMTokenList.supports()
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS DOMTokenList.prototype.supports is an instance of Function
+
+* HTMLLinkElement.relList
+PASS link.relList.__proto__ is DOMTokenList.prototype
+PASS link.relList.supports(linkRelSupportedValues[i]) is true
+PASS link.relList.supports(linkRelSupportedValues[i].toUpperCase()) is true
+PASS link.relList.supports(linkRelSupportedValues[i]) is true
+PASS link.relList.supports(linkRelSupportedValues[i].toUpperCase()) is true
+PASS link.relList.supports(linkRelSupportedValues[i]) is true
+PASS link.relList.supports(linkRelSupportedValues[i].toUpperCase()) is true
+PASS link.relList.supports(linkRelSupportedValues[i]) is true
+PASS link.relList.supports(linkRelSupportedValues[i].toUpperCase()) is true
+PASS link.relList.supports('unsupported') is false
+
+* HTMLAnchorElement.relList
+PASS anchor.relList.__proto__ is DOMTokenList.prototype
+PASS anchor.relList.supports(anchorRelSupportedValues[i]) is true
+PASS anchor.relList.supports(anchorRelSupportedValues[i].toUpperCase()) is true
+PASS anchor.relList.supports('unsupported') is false
+
+* HTMLAreaElement.relList
+PASS area.relList.__proto__ is DOMTokenList.prototype
+PASS area.relList.supports(areaRelSupportedValues[i]) is true
+PASS area.relList.supports(areaRelSupportedValues[i].toUpperCase()) is true
+PASS area.relList.supports('unsupported') is false
+
+* HTMLIFrameElement.sandbox
+PASS iframe.sandbox.__proto__ is DOMTokenList.prototype
+PASS iframe.sandbox.supports(iframeSandboxSupportedValues[i]) is true
+PASS iframe.sandbox.supports(iframeSandboxSupportedValues[i].toUpperCase()) is true
+PASS iframe.sandbox.supports(iframeSandboxSupportedValues[i]) is true
+PASS iframe.sandbox.supports(iframeSandboxSupportedValues[i].toUpperCase()) is true
+PASS iframe.sandbox.supports(iframeSandboxSupportedValues[i]) is true
+PASS iframe.sandbox.supports(iframeSandboxSupportedValues[i].toUpperCase()) is true
+PASS iframe.sandbox.supports(iframeSandboxSupportedValues[i]) is true
+PASS iframe.sandbox.supports(iframeSandboxSupportedValues[i].toUpperCase()) is true
+PASS iframe.sandbox.supports(iframeSandboxSupportedValues[i]) is true
+PASS iframe.sandbox.supports(iframeSandboxSupportedValues[i].toUpperCase()) is true
+PASS iframe.sandbox.supports(iframeSandboxSupportedValues[i]) is true
+PASS iframe.sandbox.supports(iframeSandboxSupportedValues[i].toUpperCase()) is true
+PASS iframe.sandbox.supports('unsupported') is false
+
+* HTMLLinkElement.sizes
+PASS link.sizes.__proto__ is DOMTokenList.prototype
+PASS link.sizes.supports('token') threw exception TypeError: Type error.
+
+* HTMLOutputElement.htmlFor
+PASS output.htmlFor.__proto__ is DOMTokenList.prototype
+PASS output.htmlFor.supports('token') threw exception TypeError: Type error.
+
+* HTMLElement.dropzone
+FAIL HTMLElement.dropzone is not supported.
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/dom/DOMTokenList-supports.html b/LayoutTests/fast/dom/DOMTokenList-supports.html
new file mode 100644 (file)
index 0000000..0956535
--- /dev/null
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src="../../resources/js-test-pre.js"></script>
+<script>
+description("Test support for DOMTokenList.supports()");
+
+shouldBeType("DOMTokenList.prototype.supports", "Function");
+
+debug("");
+debug("* HTMLLinkElement.relList");
+var link = document.createElement("link");
+shouldBe("link.relList.__proto__", "DOMTokenList.prototype");
+var linkRelSupportedValues = ["alternate", "dns-prefetch", "icon", "stylesheet"];
+for (var i = 0; i < linkRelSupportedValues.length; i++) {
+    shouldBeTrue("link.relList.supports(linkRelSupportedValues[i])");
+    shouldBeTrue("link.relList.supports(linkRelSupportedValues[i].toUpperCase())");
+}
+shouldBeFalse("link.relList.supports('unsupported')");
+
+debug("");
+debug("* HTMLAnchorElement.relList");
+var anchor = document.createElement("a");
+shouldBe("anchor.relList.__proto__", "DOMTokenList.prototype");
+var anchorRelSupportedValues = ["noreferrer"];
+for (var i = 0; i < anchorRelSupportedValues.length; i++) {
+    shouldBeTrue("anchor.relList.supports(anchorRelSupportedValues[i])");
+    shouldBeTrue("anchor.relList.supports(anchorRelSupportedValues[i].toUpperCase())");
+}
+shouldBeFalse("anchor.relList.supports('unsupported')");
+
+debug("");
+debug("* HTMLAreaElement.relList");
+var area = document.createElement("area");
+shouldBe("area.relList.__proto__", "DOMTokenList.prototype");
+var areaRelSupportedValues = ["noreferrer"];
+for (var i = 0; i < areaRelSupportedValues.length; i++) {
+    shouldBeTrue("area.relList.supports(areaRelSupportedValues[i])");
+    shouldBeTrue("area.relList.supports(areaRelSupportedValues[i].toUpperCase())");
+}
+shouldBeFalse("area.relList.supports('unsupported')");
+
+debug("");
+debug("* HTMLIFrameElement.sandbox");
+var iframe = document.createElement("iframe");
+shouldBe("iframe.sandbox.__proto__", "DOMTokenList.prototype");
+var iframeSandboxSupportedValues = ["allow-forms", "allow-same-origin", "allow-scripts", "allow-top-navigation", "allow-pointer-lock", "allow-popups"];
+for (var i = 0; i < iframeSandboxSupportedValues.length; i++) {
+    shouldBeTrue("iframe.sandbox.supports(iframeSandboxSupportedValues[i])");
+    shouldBeTrue("iframe.sandbox.supports(iframeSandboxSupportedValues[i].toUpperCase())");
+}
+shouldBeFalse("iframe.sandbox.supports('unsupported')");
+
+debug("");
+debug("* HTMLLinkElement.sizes");
+shouldBe("link.sizes.__proto__", "DOMTokenList.prototype");
+shouldThrowErrorName("link.sizes.supports('token')", "TypeError");
+
+debug("");
+debug("* HTMLOutputElement.htmlFor");
+var output = document.createElement("output");
+shouldBe("output.htmlFor.__proto__", "DOMTokenList.prototype");
+shouldThrowErrorName("output.htmlFor.supports('token')", "TypeError");
+
+debug("");
+debug("* HTMLElement.dropzone");
+if (link.dropzone) {
+    shouldBe("link.dropzone.__proto__", "DOMTokenList.prototype");
+    var dropzoneSupportedValues = ["copy", "move", "link"];
+    for (var i = 0; i < dropzoneSupportedValues.length; i++) {
+        shouldBeTrue("link.dropzone.supports(dropzoneSupportedValues[i])");
+        shouldBeTrue("link.dropzone.supports(dropzoneSupportedValues[i].toUpperCase())");
+    }
+    shouldBeFalse("link.dropzone.supports('unsupported')");
+} else
+    testFailed("HTMLElement.dropzone is not supported.");
+
+debug("");
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
index 378df29..d52be6d 100644 (file)
@@ -1,3 +1,15 @@
+2016-09-28  Chris Dumez  <cdumez@apple.com>
+
+        Add support for DOMTokenList.supports()
+        https://bugs.webkit.org/show_bug.cgi?id=162659
+
+        Reviewed by Ryosuke Niwa.
+
+        Rebaseline W3C tests now that more checks are passing.
+
+        * web-platform-tests/dom/interfaces-expected.txt:
+        * web-platform-tests/html/semantics/document-metadata/the-link-element/link-rellist-expected.txt:
+
 2016-09-28  Ryosuke Niwa  <rniwa@webkit.org>
 
         DOMTokenList’s value and stringifier should not return parsed tokens
index 5053e9c..fdbd51b 100644 (file)
@@ -1590,7 +1590,7 @@ PASS DOMTokenList interface: operation add(DOMString)
 PASS DOMTokenList interface: operation remove(DOMString) 
 PASS DOMTokenList interface: operation toggle(DOMString,boolean) 
 PASS DOMTokenList interface: operation replace(DOMString,DOMString) 
-FAIL DOMTokenList interface: operation supports(DOMString) assert_own_property: interface prototype object missing non-static operation expected property "supports" missing
+PASS DOMTokenList interface: operation supports(DOMString) 
 PASS DOMTokenList interface: attribute value 
 PASS DOMTokenList interface: stringifier 
 PASS DOMTokenList must be primary interface of document.body.classList 
@@ -1608,7 +1608,7 @@ PASS DOMTokenList interface: document.body.classList must inherit property "togg
 PASS DOMTokenList interface: calling toggle(DOMString,boolean) on document.body.classList with too few arguments must throw TypeError 
 PASS DOMTokenList interface: document.body.classList must inherit property "replace" with the proper type (6) 
 PASS DOMTokenList interface: calling replace(DOMString,DOMString) on document.body.classList with too few arguments must throw TypeError 
-FAIL DOMTokenList interface: document.body.classList must inherit property "supports" with the proper type (7) assert_inherits: property "supports" not found in prototype chain
-FAIL DOMTokenList interface: calling supports(DOMString) on document.body.classList with too few arguments must throw TypeError assert_inherits: property "supports" not found in prototype chain
+PASS DOMTokenList interface: document.body.classList must inherit property "supports" with the proper type (7) 
+PASS DOMTokenList interface: calling supports(DOMString) on document.body.classList with too few arguments must throw TypeError 
 PASS DOMTokenList interface: document.body.classList must inherit property "value" with the proper type (8) 
 
index 14e73c7..fef095d 100644 (file)
@@ -1,3 +1,44 @@
+2016-09-28  Chris Dumez  <cdumez@apple.com>
+
+        Add support for DOMTokenList.supports()
+        https://bugs.webkit.org/show_bug.cgi?id=162659
+
+        Reviewed by Ryosuke Niwa.
+
+        Add support for DOMTokenList.supports():
+        - https://dom.spec.whatwg.org/#dom-domtokenlist-supports
+
+        Firefox and Chrome already recently implemented it (Chrome since
+        version 50 and Firefox since version 49).
+
+        Test: fast/dom/DOMTokenList-supports.html
+
+        * dom/SecurityContext.cpp:
+        (WebCore::SecurityContext::isSupportedSandboxPolicy):
+        (WebCore::SecurityContext::enforceSandboxFlags): Deleted.
+        * dom/SecurityContext.h:
+        * html/DOMTokenList.cpp:
+        (WebCore::DOMTokenList::DOMTokenList):
+        (WebCore::DOMTokenList::supports):
+        (WebCore::DOMTokenList::replace): Deleted.
+        * html/DOMTokenList.h:
+        (WebCore::DOMTokenList::DOMTokenList):
+        * html/DOMTokenList.idl:
+        * html/HTMLAnchorElement.cpp:
+        (WebCore::HTMLAnchorElement::parseAttribute):
+        (WebCore::HTMLAnchorElement::relList):
+        * html/HTMLAnchorElement.idl:
+        * html/HTMLAreaElement.idl:
+        * html/HTMLIFrameElement.cpp:
+        (WebCore::HTMLIFrameElement::sandbox):
+        * html/HTMLLinkElement.cpp:
+        (WebCore::HTMLLinkElement::relList):
+        * html/HTMLTableCellElement.idl:
+        * html/LinkRelAttribute.cpp:
+        (WebCore::LinkRelAttribute::isSupported):
+        (WebCore::LinkRelAttribute::LinkRelAttribute): Deleted.
+        * html/LinkRelAttribute.h:
+
 2016-09-28  Ryosuke Niwa  <rniwa@webkit.org>
 
         DOMTokenList’s value and stringifier should not return parsed tokens
index 03ef40c..15ffe7e 100644 (file)
@@ -31,6 +31,7 @@
 #include "HTMLParserIdioms.h"
 #include "SecurityOrigin.h"
 #include "SecurityOriginPolicy.h"
+#include <wtf/NeverDestroyed.h>
 #include <wtf/text/StringBuilder.h>
 
 namespace WebCore {
@@ -84,6 +85,20 @@ void SecurityContext::enforceSandboxFlags(SandboxFlags mask)
         setSecurityOriginPolicy(SecurityOriginPolicy::create(SecurityOrigin::createUnique()));
 }
 
+bool SecurityContext::isSupportedSandboxPolicy(const String& policy)
+{
+    static const char* supportedPolicies[] = {
+        "allow-forms", "allow-same-origin", "allow-scripts", "allow-top-navigation", "allow-pointer-lock", "allow-popups"
+    };
+
+    for (auto* supportedPolicy : supportedPolicies) {
+        if (equalIgnoringASCIICase(policy, supportedPolicy))
+            return true;
+    }
+    return false;
+}
+
+// Keep SecurityContext::isSupportedSandboxPolicy() in sync when updating this function.
 SandboxFlags SecurityContext::parseSandboxPolicy(const String& policy, String& invalidTokensErrorMessage)
 {
     // http://www.w3.org/TR/html5/the-iframe-element.html#attr-iframe-sandbox
index 6920388..069d31b 100644 (file)
@@ -75,6 +75,8 @@ public:
     WEBCORE_EXPORT SecurityOrigin* securityOrigin() const;
 
     static SandboxFlags parseSandboxPolicy(const String& policy, String& invalidTokensErrorMessage);
+    static bool isSupportedSandboxPolicy(const String&);
+
     bool foundMixedContent() const { return m_foundMixedContent; }
     void setFoundMixedContent() { m_foundMixedContent = true; }
     bool geolocationAccessed() const { return m_geolocationAccessed; }
index 37affcf..ed373a0 100644 (file)
 
 namespace WebCore {
 
-DOMTokenList::DOMTokenList(Element& element, const QualifiedName& attributeName)
+DOMTokenList::DOMTokenList(Element& element, const QualifiedName& attributeName, WTF::Function<bool(const String&)>&& isSupportedToken)
     : m_element(element)
     , m_attributeName(attributeName)
+    , m_isSupportedToken(WTFMove(isSupportedToken))
 {
 }
 
@@ -177,6 +178,16 @@ void DOMTokenList::replace(const AtomicString& token, const AtomicString& newTok
     updateAssociatedAttributeFromTokens();
 }
 
+// https://dom.spec.whatwg.org/#concept-domtokenlist-validation
+bool DOMTokenList::supports(const String& token, ExceptionCode& ec)
+{
+    if (!m_isSupportedToken) {
+        ec = TypeError;
+        return false;
+    }
+    return m_isSupportedToken(token);
+}
+
 // https://dom.spec.whatwg.org/#dom-domtokenlist-value
 const AtomicString& DOMTokenList::value() const
 {
index 477765c..c8318a3 100644 (file)
@@ -32,7 +32,7 @@ namespace WebCore {
 class DOMTokenList {
     WTF_MAKE_NONCOPYABLE(DOMTokenList); WTF_MAKE_FAST_ALLOCATED;
 public:
-    DOMTokenList(Element&, const QualifiedName& attributeName);
+    DOMTokenList(Element&, const QualifiedName& attributeName, WTF::Function<bool(const String&)>&& isSupportedToken = { });
 
     void associatedAttributeValueChanged(const AtomicString&);
 
@@ -49,6 +49,7 @@ public:
     void remove(const AtomicString&, ExceptionCode&);
     WEBCORE_EXPORT bool toggle(const AtomicString&, Optional<bool> force, ExceptionCode&);
     void replace(const AtomicString& token, const AtomicString& newToken, ExceptionCode&);
+    bool supports(const String& token, ExceptionCode&);
 
     Element& element() const { return m_element; }
 
@@ -72,6 +73,7 @@ private:
     bool m_inUpdateAssociatedAttributeFromTokens { false };
     bool m_tokensNeedUpdating { true };
     Vector<AtomicString> m_tokens;
+    WTF::Function<bool(const String&)> m_isSupportedToken;
 };
 
 inline unsigned DOMTokenList::length() const
index e66cc23..bac81a8 100644 (file)
@@ -34,6 +34,7 @@
     [RaisesException] void remove(DOMString... tokens);
     [RaisesException] boolean toggle(DOMString token, optional boolean force);
     [RaisesException] void replace(DOMString token, DOMString newToken);
+    [RaisesException] boolean supports(DOMString token);
 
     iterable<DOMString>;
 
index ce4d248..6abf9b6 100644 (file)
@@ -248,6 +248,7 @@ void HTMLAnchorElement::parseAttribute(const QualifiedName& name, const AtomicSt
     } else if (name == nameAttr || name == titleAttr) {
         // Do nothing.
     } else if (name == relAttr) {
+        // Update HTMLAnchorElement::relList() if more rel attributes values are supported.
         if (SpaceSplitString::spaceSplitStringContainsValue(value, "noreferrer", true))
             m_linkRelations |= RelationNoReferrer;
         if (m_relList)
@@ -302,7 +303,9 @@ bool HTMLAnchorElement::hasRel(uint32_t relation) const
 DOMTokenList& HTMLAnchorElement::relList()
 {
     if (!m_relList) 
-        m_relList = std::make_unique<DOMTokenList>(*this, HTMLNames::relAttr);
+        m_relList = std::make_unique<DOMTokenList>(*this, HTMLNames::relAttr, [](const String& token) {
+            return equalIgnoringASCIICase(token, "noreferrer");
+        });
     return *m_relList;
 }
 
index 1a158bc..f7cede1 100644 (file)
@@ -24,10 +24,7 @@ interface HTMLAnchorElement : HTMLElement {
     [Conditional=DOWNLOAD_ATTRIBUTE, EnabledAtRuntime=DownloadAttribute, Reflect] attribute DOMString download;
     [Reflect] attribute DOMString hreflang;
     [Reflect] attribute DOMString name;
-
-    // FIXME: This is supposed to be: [PutForwards=value] readonly attribute DOMTokenList ping;
     [Reflect] attribute USVString ping;
-
     [Reflect] attribute DOMString rel;
     [Reflect] attribute DOMString rev;
     [Reflect] attribute DOMString shape;
index 3afca4c..35b127a 100644 (file)
@@ -22,11 +22,7 @@ interface HTMLAreaElement : HTMLElement {
     [Reflect] attribute DOMString alt;
     [Reflect] attribute DOMString coords;
     [Reflect] attribute boolean noHref;
-
-    // FIXME: This is supposed to be:
-    // [PutForwards=value] readonly attribute DOMTokenList ping;
     [Reflect] attribute USVString ping;
-
     [Reflect] attribute DOMString rel;
     [Reflect] attribute DOMString shape;
     [Reflect] attribute DOMString target;
index 31368ae..4aa0151 100644 (file)
@@ -51,7 +51,9 @@ Ref<HTMLIFrameElement> HTMLIFrameElement::create(const QualifiedName& tagName, D
 DOMTokenList& HTMLIFrameElement::sandbox()
 {
     if (!m_sandbox)
-        m_sandbox = std::make_unique<DOMTokenList>(*this, sandboxAttr);
+        m_sandbox = std::make_unique<DOMTokenList>(*this, sandboxAttr, [](const String& token) {
+            return SecurityContext::isSupportedSandboxPolicy(token);
+        });
     return *m_sandbox;
 }
 
index aee458f..eeabc29 100644 (file)
@@ -444,7 +444,9 @@ void HTMLLinkElement::dispatchPendingEvent(LinkEventSender* eventSender)
 DOMTokenList& HTMLLinkElement::relList()
 {
     if (!m_relList) 
-        m_relList = std::make_unique<DOMTokenList>(*this, HTMLNames::relAttr);
+        m_relList = std::make_unique<DOMTokenList>(*this, HTMLNames::relAttr, [](const String& token) {
+            return LinkRelAttribute::isSupported(token);
+        });
     return *m_relList;
 }
 
index 6a90dd9..6220021 100644 (file)
@@ -29,8 +29,6 @@ interface HTMLTableCellElement : HTMLElement {
     [ImplementedAs=colSpanForBindings] attribute unsigned long colSpan;
     [ImplementedAs=rowSpanForBindings] attribute unsigned long rowSpan;
 
-    // FIXME: This is supposed to be:
-    // [PutForwards=value] readonly attribute DOMTokenList headers;
     [Reflect] attribute DOMString headers;
 
     [Reflect] attribute DOMString height;
index 6e50b18..a7d4775 100644 (file)
@@ -42,6 +42,7 @@ LinkRelAttribute::LinkRelAttribute()
 {
 }
 
+// Keep LinkRelAttribute::isSupported() in sync when updating this constructor.
 LinkRelAttribute::LinkRelAttribute(const String& rel)
 {
     if (equalLettersIgnoringASCIICase(rel, "stylesheet"))
@@ -86,4 +87,25 @@ LinkRelAttribute::LinkRelAttribute(const String& rel)
     }
 }
 
+// https://html.spec.whatwg.org/#linkTypes
+bool LinkRelAttribute::isSupported(const String& attribute)
+{
+    static const char* supportedAttributes[] = {
+        "alternate", "dns-prefetch", "icon", "stylesheet", "apple-touch-icon", "apple-touch-icon-precomposed",
+#if ENABLE(LINK_PREFETCH)
+        "prefetch", "subresource",
+#endif
+    };
+
+    for (auto* supportedAttribute : supportedAttributes) {
+        if (equalIgnoringASCIICase(attribute, supportedAttribute))
+            return true;
+    }
+
+    if (RuntimeEnabledFeatures::sharedFeatures().linkPreloadEnabled() && equalIgnoringASCIICase(attribute, "preload"))
+        return true;
+
+    return false;
+}
+
 }
index 2009575..fc28a99 100644 (file)
@@ -52,6 +52,8 @@ struct LinkRelAttribute {
 
     LinkRelAttribute();
     explicit LinkRelAttribute(const String&);
+
+    static bool isSupported(const String&);
 };
 
 }