Diff
Modified: trunk/LayoutTests/ChangeLog (197527 => 197528)
--- trunk/LayoutTests/ChangeLog 2016-03-04 00:26:23 UTC (rev 197527)
+++ trunk/LayoutTests/ChangeLog 2016-03-04 00:28:44 UTC (rev 197528)
@@ -1,3 +1,25 @@
+2016-03-02 Ryosuke Niwa <[email protected]>
+
+ Disallow custom elements inside template elements and share the registry for windowless documents
+ https://bugs.webkit.org/show_bug.cgi?id=154944
+ <rdar://problem/24944875>
+
+ Reviewed by Antti Koivisto.
+
+ Added various tests to ensure the custom elements registry is not shared between documents with
+ distinct browsing context (e.g. iframes) but shared among the ones that share a single browsing context
+ (e.g. documents created by DOMImplementation).
+
+ Also added a test case for defineCustomElement to ensure it throws NotSupportedError when it's called on
+ a template element's inert owner document as well as a basic test case for document.write.
+
+ * fast/custom-elements/Document-defineCustomElement-expected.txt:
+ * fast/custom-elements/Document-defineCustomElement.html: Added a new test case.
+ * fast/custom-elements/parser/parser-constructs-custom-element-in-document-write-expected.txt: Added.
+ * fast/custom-elements/parser/parser-constructs-custom-element-in-document-write.html: Added.
+ * fast/custom-elements/parser/parser-uses-registry-of-owner-document-expected.txt: Added.
+ * fast/custom-elements/parser/parser-uses-registry-of-owner-document.html: Added.
+
2016-03-03 Zalan Bujtas <[email protected]>
Subpixel rendering: Make collapsed borders painting subpixel aware.
Modified: trunk/LayoutTests/fast/custom-elements/Document-defineCustomElement-expected.txt (197527 => 197528)
--- trunk/LayoutTests/fast/custom-elements/Document-defineCustomElement-expected.txt 2016-03-04 00:26:23 UTC (rev 197527)
+++ trunk/LayoutTests/fast/custom-elements/Document-defineCustomElement-expected.txt 2016-03-04 00:28:44 UTC (rev 197528)
@@ -2,6 +2,9 @@
PASS Check the existence of defineCustomElement on Document interface
PASS document.defineCustomElement should throw with an invalid name
PASS document.defineCustomElement should throw with a duplicate name
+PASS document.defineCustomElement must throw a NotSupportedError when the context object is an associated inert template document
+PASS document.defineCustomElement must throw a NotSupportedError when the context object is created by DOMImplementation.createHTMLDocument
+PASS document.defineCustomElement must throw a NotSupportedError when the context object is created by DOMImplementation.createDocument
PASS document.defineCustomElement should throw when the element interface is not a constructor
PASS document.defineCustomElement should define an instantiatable custom element
Modified: trunk/LayoutTests/fast/custom-elements/Document-defineCustomElement.html (197527 => 197528)
--- trunk/LayoutTests/fast/custom-elements/Document-defineCustomElement.html 2016-03-04 00:26:23 UTC (rev 197527)
+++ trunk/LayoutTests/fast/custom-elements/Document-defineCustomElement.html 2016-03-04 00:28:44 UTC (rev 197528)
@@ -58,6 +58,36 @@
}, 'document.defineCustomElement should throw with a duplicate name');
test(function () {
+ class SomeCustomElement extends HTMLElement {};
+
+ var templateContentOwnerDocument = document.createElement('template').content.ownerDocument;
+ assert_throws({'name': 'NotSupportedError'}, function () {
+ templateContentOwnerDocument.defineCustomElement('some-custom-element', SomeCustomElement);
+ });
+
+}, 'document.defineCustomElement must throw a NotSupportedError when the context object is an associated inert template document');
+
+test(function () {
+ class SomeCustomElement extends HTMLElement {};
+
+ var windowlessDocument = document.implementation.createHTMLDocument();
+ assert_throws({'name': 'NotSupportedError'}, function () {
+ windowlessDocument.defineCustomElement('some-custom-element', SomeCustomElement);
+ });
+
+}, 'document.defineCustomElement must throw a NotSupportedError when the context object is created by DOMImplementation.createHTMLDocument');
+
+test(function () {
+ class SomeCustomElement extends HTMLElement {};
+
+ var windowlessDocument = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null)
+ assert_throws({'name': 'NotSupportedError'}, function () {
+ windowlessDocument.defineCustomElement('some-custom-element', SomeCustomElement);
+ });
+
+}, 'document.defineCustomElement must throw a NotSupportedError when the context object is created by DOMImplementation.createDocument');
+
+test(function () {
assert_throws({'name': 'TypeError'}, function () { document.defineCustomElement('invalid-element', 1); },
'document.defineCustomElement must throw a TypeError when the element interface is a number');
assert_throws({'name': 'TypeError'}, function () { document.defineCustomElement('invalid-element', '123'); },
Added: trunk/LayoutTests/fast/custom-elements/parser/parser-constructs-custom-element-in-document-write-expected.txt (0 => 197528)
--- trunk/LayoutTests/fast/custom-elements/parser/parser-constructs-custom-element-in-document-write-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/parser/parser-constructs-custom-element-in-document-write-expected.txt 2016-03-04 00:28:44 UTC (rev 197528)
@@ -0,0 +1,3 @@
+
+PASS HTML parser must instantiate custom elements inside document.write
+
Added: trunk/LayoutTests/fast/custom-elements/parser/parser-constructs-custom-element-in-document-write.html (0 => 197528)
--- trunk/LayoutTests/fast/custom-elements/parser/parser-constructs-custom-element-in-document-write.html (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/parser/parser-constructs-custom-element-in-document-write.html 2016-03-04 00:28:44 UTC (rev 197528)
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: Changes to the HTML parser</title>
+<meta name="author" title="Ryosuke Niwa" href=""
+<meta name="assert" content="HTML parser must construct custom elements inside document.write">
+<script src=""
+<script src=""
+<link rel='stylesheet' href=''>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+class MyCustomElement extends HTMLElement { }
+document.defineCustomElement('my-custom-element', MyCustomElement);
+
+document.write('<my-custom-element></my-custom-element>');
+
+test(function () {
+ var instance = document.querySelector('my-custom-element');
+
+ assert_true(instance instanceof HTMLElement);
+ assert_true(instance instanceof MyCustomElement);
+
+}, 'HTML parser must instantiate custom elements inside document.write');
+
+</script>
+</body>
+</html>
Added: trunk/LayoutTests/fast/custom-elements/parser/parser-uses-registry-of-owner-document-expected.txt (0 => 197528)
--- trunk/LayoutTests/fast/custom-elements/parser/parser-uses-registry-of-owner-document-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/parser/parser-uses-registry-of-owner-document-expected.txt 2016-03-04 00:28:44 UTC (rev 197528)
@@ -0,0 +1,8 @@
+
+PASS HTML parser must not instantiate custom elements inside template elements
+PASS HTML parser must not use the registry of the owner element's document inside an iframe
+PASS HTML parser must use the registry of the content document inside an iframe
+PASS HTML parser must not instantiate a custom element defined inside an frame in frame element's owner document
+PASS HTML parser must use the registry of window.document in a document created by document.implementation.createHTMLDocument()
+PASS HTML parser must use the registry of window.document in a document created by document.implementation.createXHTMLDocument()
+
Added: trunk/LayoutTests/fast/custom-elements/parser/parser-uses-registry-of-owner-document.html (0 => 197528)
--- trunk/LayoutTests/fast/custom-elements/parser/parser-uses-registry-of-owner-document.html (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/parser/parser-uses-registry-of-owner-document.html 2016-03-04 00:28:44 UTC (rev 197528)
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: Changes to the HTML parser</title>
+<meta name="author" title="Ryosuke Niwa" href=""
+<meta name="assert" content="HTML parser must use the owner document's custom element registry">
+<script src=""
+<script src=""
+<link rel='stylesheet' href=''>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+class MyCustomElement extends HTMLElement { };
+document.defineCustomElement('my-custom-element', MyCustomElement);
+
+document.write('<template><my-custom-element></my-custom-element></template>');
+
+test(function () {
+ var template = document.querySelector('template');
+ var instance = template.content.firstChild;
+
+ assert_true(instance instanceof HTMLElement,
+ 'A custom element inside a template element must be an instance of HTMLElement');
+ assert_false(instance instanceof MyCustomElement,
+ 'A custom element must not be instantiated inside a template element using the registry of the template element\'s owner document');
+ assert_equals(instance.ownerDocument, template.content.ownerDocument,
+ 'Custom elements inside a template must use the appropriate template contents owner document as the owner document');
+
+}, 'HTML parser must not instantiate custom elements inside template elements');
+
+var iframe = document.createElement('iframe');
+document.body.appendChild(iframe);
+iframe.contentDocument.body.innerHTML = '<my-custom-element></my-custom-element>';
+
+test(function () {
+ var instance = iframe.contentDocument.querySelector('my-custom-element');
+
+ assert_true(instance instanceof iframe.contentWindow.HTMLElement);
+ assert_false(instance instanceof MyCustomElement);
+
+}, 'HTML parser must not use the registry of the owner element\'s document inside an iframe');
+
+class ElementInIFrame extends iframe.contentWindow.HTMLElement { };
+iframe.contentDocument.defineCustomElement('element-in-iframe', ElementInIFrame);
+iframe.contentDocument.body.innerHTML = '<element-in-iframe></element-in-iframe>';
+
+test(function () {
+ var instance = iframe.contentDocument.querySelector('element-in-iframe');
+
+ assert_true(instance instanceof iframe.contentWindow.HTMLElement, 'A custom element inside an iframe must be an instance of HTMLElement');
+ assert_true(instance instanceof ElementInIFrame,
+ 'A custom element must be instantiated inside an iframe using the registry of the content document');
+ assert_equals(instance.ownerDocument, iframe.contentDocument,
+ 'The owner document of custom elements inside an iframe must be the content document of the iframe');
+
+}, 'HTML parser must use the registry of the content document inside an iframe');
+
+document.write('<element-in-iframe></element-in-iframe>');
+
+test(function () {
+ var instance = document.querySelector('element-in-iframe');
+
+ assert_true(instance instanceof HTMLElement);
+ assert_false(instance instanceof ElementInIFrame);
+
+}, 'HTML parser must not instantiate a custom element defined inside an frame in frame element\'s owner document');
+
+document.body.removeChild(iframe);
+
+var windowlessDocument = document.implementation.createHTMLDocument();
+windowlessDocument.open();
+windowlessDocument.write('<my-custom-element></my-custom-element>');
+windowlessDocument.close();
+
+test(function () {
+ var instance = windowlessDocument.querySelector('my-custom-element');
+
+ assert_true(instance instanceof HTMLElement);
+ assert_false(instance instanceof MyCustomElement);
+
+}, 'HTML parser must use the registry of window.document in a document created by document.implementation.createHTMLDocument()');
+
+windowlessDocument = document.implementation.createDocument ('http://www.w3.org/1999/xhtml', 'html', null);
+windowlessDocument.documentElement.innerHTML = '<my-custom-element></my-custom-element>';
+
+test(function () {
+ var instance = windowlessDocument.querySelector('my-custom-element');
+
+ assert_true(instance instanceof HTMLElement);
+ assert_false(instance instanceof MyCustomElement);
+
+}, 'HTML parser must use the registry of window.document in a document created by document.implementation.createXHTMLDocument()');
+
+</script>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (197527 => 197528)
--- trunk/Source/WebCore/ChangeLog 2016-03-04 00:26:23 UTC (rev 197527)
+++ trunk/Source/WebCore/ChangeLog 2016-03-04 00:28:44 UTC (rev 197528)
@@ -1,3 +1,30 @@
+2016-03-03 Ryosuke Niwa <[email protected]>
+
+ Disallow custom elements inside a window-less documents
+ https://bugs.webkit.org/show_bug.cgi?id=154944
+ <rdar://problem/24944875>
+
+ Reviewed by Antti Koivisto.
+
+ Disallow custom elements inside a window-less documents such as the shared inert document of template elements
+ and the ones created by DOMImplementation.createDocument and DOMImplementation.createHTMLDocument.
+
+ Throw NotSupportedError in defineCustomElement when it's called in such a document as discussed in:
+ https://github.com/w3c/webcomponents/issues/369
+
+ Tests: fast/custom-elements/parser/parser-constructs-custom-element-in-document-write.html
+ fast/custom-elements/parser/parser-uses-registry-of-owner-document.html
+
+ * bindings/js/JSDOMBinding.cpp:
+ (WebCore::throwNotSupportedError): Added.
+ * bindings/js/JSDOMBinding.h:
+ * bindings/js/JSDocumentCustom.cpp:
+ (WebCore::JSDocument::defineCustomElement): Throw NotSupportedError when the context object's document doesn't
+ have a browsing context (i.e. window-less).
+ * html/parser/HTMLDocumentParser.cpp:
+ (WebCore::HTMLDocumentParser::runScriptsForPausedTreeBuilder): Replaced a FIXME with an assertion now that we
+ disallow instantiation of custom elements inside a template element.
+
2016-03-03 Alex Christensen <[email protected]>
Move SPI to CFNetworkSPI.h
Modified: trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp (197527 => 197528)
--- trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp 2016-03-04 00:26:23 UTC (rev 197527)
+++ trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp 2016-03-04 00:28:44 UTC (rev 197528)
@@ -635,6 +635,13 @@
context.addConsoleMessage(MessageSource::JS, MessageLevel::Error, makeString("Deprecated attempt to set property '", attributeName, "' on a non-", interfaceName, " object."));
}
+void throwNotSupportedError(JSC::ExecState& state, const char* message)
+{
+ ASSERT(!state.hadException());
+ String messageString(message);
+ state.vm().throwException(&state, createDOMException(&state, NOT_SUPPORTED_ERR, &messageString));
+}
+
JSC::EncodedJSValue throwArgumentMustBeEnumError(JSC::ExecState& state, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedValues)
{
StringBuilder builder;
Modified: trunk/Source/WebCore/bindings/js/JSDOMBinding.h (197527 => 197528)
--- trunk/Source/WebCore/bindings/js/JSDOMBinding.h 2016-03-04 00:26:23 UTC (rev 197527)
+++ trunk/Source/WebCore/bindings/js/JSDOMBinding.h 2016-03-04 00:28:44 UTC (rev 197528)
@@ -84,6 +84,7 @@
WEBCORE_EXPORT JSC::EncodedJSValue reportDeprecatedGetterError(JSC::ExecState&, const char* interfaceName, const char* attributeName);
WEBCORE_EXPORT void reportDeprecatedSetterError(JSC::ExecState&, const char* interfaceName, const char* attributeName);
+void throwNotSupportedError(JSC::ExecState&, const char* message);
void throwArrayElementTypeError(JSC::ExecState&);
void throwAttributeTypeError(JSC::ExecState&, const char* interfaceName, const char* attributeName, const char* expectedType);
WEBCORE_EXPORT void throwSequenceTypeError(JSC::ExecState&);
Modified: trunk/Source/WebCore/bindings/js/JSDocumentCustom.cpp (197527 => 197528)
--- trunk/Source/WebCore/bindings/js/JSDocumentCustom.cpp 2016-03-04 00:26:23 UTC (rev 197527)
+++ trunk/Source/WebCore/bindings/js/JSDocumentCustom.cpp 2016-03-04 00:28:44 UTC (rev 197528)
@@ -147,6 +147,11 @@
return throwTypeError(&state, "The second argument must be a constructor");
Document& document = wrapped();
+ if (!document.domWindow()) {
+ throwNotSupportedError(state, "Cannot define a custom element in a docuemnt without a browsing context");
+ return jsUndefined();
+ }
+
switch (CustomElementDefinitions::checkName(tagName)) {
case CustomElementDefinitions::NameStatus::Valid:
break;
@@ -161,10 +166,7 @@
QualifiedName name(nullAtom, tagName, HTMLNames::xhtmlNamespaceURI);
auto& definitions = document.ensureCustomElementDefinitions();
if (definitions.findInterface(tagName)) {
- ExceptionCodeWithMessage ec;
- ec.code = NOT_SUPPORTED_ERR;
- ec.message = "Cannot define multiple custom elements with the same tag name";
- setDOMException(&state, ec);
+ throwNotSupportedError(state, "Cannot define multiple custom elements with the same tag name");
return jsUndefined();
}
definitions.defineElement(name, JSCustomElementInterface::create(object, globalObject()));
Modified: trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp (197527 => 197528)
--- trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp 2016-03-04 00:26:23 UTC (rev 197527)
+++ trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp 2016-03-04 00:28:44 UTC (rev 197528)
@@ -196,7 +196,7 @@
RefPtr<Element> newElement = constructionData->interface->constructElement(constructionData->name, JSCustomElementInterface::ShouldClearException::Clear);
if (!newElement) {
- // FIXME: This call to docuemnt() is wrong for elements inside a template element.
+ ASSERT(!m_treeBuilder->isParsingTemplateContents());
newElement = HTMLUnknownElement::create(QualifiedName(nullAtom, constructionData->name, xhtmlNamespaceURI), *document());
}
Modified: trunk/Source/WebCore/html/parser/HTMLTreeBuilder.h (197527 => 197528)
--- trunk/Source/WebCore/html/parser/HTMLTreeBuilder.h 2016-03-04 00:26:23 UTC (rev 197527)
+++ trunk/Source/WebCore/html/parser/HTMLTreeBuilder.h 2016-03-04 00:28:44 UTC (rev 197528)
@@ -61,6 +61,7 @@
void constructTree(AtomicHTMLToken&);
+ bool isParsingTemplateContents() const;
bool hasParserBlockingScriptWork() const;
// Must be called to take the parser-blocking script before calling the parser again.
@@ -107,7 +108,6 @@
AfterAfterFrameset,
};
- bool isParsingTemplateContents() const;
bool isParsingFragmentOrTemplateContents() const;
#if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS)