WebKit Bugzilla
Attachment 346728 Details for
Bug 188336
: HTML parser should execute custom element reactions for setting attributes immediately after creating a custom element
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for landing
bug-188336-20180807140259.patch (text/plain), 35.99 KB, created by
Ryosuke Niwa
on 2018-08-07 14:03:00 PDT
(
hide
)
Description:
Patch for landing
Filename:
MIME Type:
Creator:
Ryosuke Niwa
Created:
2018-08-07 14:03:00 PDT
Size:
35.99 KB
patch
obsolete
>Subversion Revision: 234583 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 3d89b3c517f5a554b3365a0b0beb63834827d535..ff45baf271da79acc75d45e98768fe4b25fc3974 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,54 @@ >+2018-08-06 Ryosuke Niwa <rniwa@webkit.org> >+ >+ document.open and document.write must throw while the HTML parser is synchronously constructing a custom element >+ https://bugs.webkit.org/show_bug.cgi?id=187319 >+ <rdar://problem/42843012> >+ >+ Reviewed by Frédéric Wang. >+ >+ Make document.open, document.write, document.writeln, and document.close throw InvalidStateError during >+ a synchronous custom element construction as specified: >+ https://html.spec.whatwg.org/multipage/parsing.html#create-an-element-for-the-token >+ https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#throw-on-dynamic-markup-insertion-counter >+ >+ Tests: fast/custom-elements/throw-on-dynamic-markup-insertion-counter-construct.html >+ fast/custom-elements/throw-on-dynamic-markup-insertion-counter-reactions.html >+ >+ * WebCore.xcodeproj/project.pbxproj: >+ * dom/Document.cpp: >+ (WebCore::Document::openForBindings): Throw InvalidStateError when m_throwOnDynamicMarkupInsertionCount is non-zero. >+ (WebCore::Document::closeForBindings): Ditto. >+ (WebCore::Document::write): Ditto. >+ (WebCore::Document::writeln): Ditto. >+ * dom/Document.h: Re-ordered the related instance variables in the order they appear in the spec, and updated spec URLs. >+ * dom/ThrowOnDynamicMarkupInsertionCountIncrementer.h: Added. >+ (WebCore::ThrowOnDynamicMarkupInsertionCountIncrementer): Added. >+ (WebCore::ThrowOnDynamicMarkupInsertionCountIncrementer::ThrowOnDynamicMarkupInsertionCountIncrementer): >+ (WebCore::ThrowOnDynamicMarkupInsertionCountIncrementer::~ThrowOnDynamicMarkupInsertionCountIncrementer): >+ * html/parser/HTMLDocumentParser.cpp: >+ (WebCore::HTMLDocumentParser::runScriptsForPausedTreeBuilder): Instantiate ThrowOnDynamicMarkupInsertionCountIncrementer. >+ >+2018-08-05 Ryosuke Niwa <rniwa@webkit.org> >+ >+ HTML parser should execute custom element reactions for setting attributes immediately after creating a custom element >+ https://bugs.webkit.org/show_bug.cgi?id=188336 >+ >+ Reviewed by Frédéric Wang. >+ >+ Push and pop an element queue from the custom element reactions stack when constructing a custom element: >+ https://html.spec.whatwg.org/multipage/parsing.html#create-an-element-for-the-token >+ >+ To do this, we instantiate CustomElementReactionStack in HTMLDocumentParser::runScriptsForPausedTreeBuilder >+ where we synchronously construct a custom element. We don't have to worry about whether *will execute script* >+ is set or not since the precense of an element queue should not be observable in the case where we're constructing >+ a fallback element (since it would not enqueue any new custom element reaction). >+ >+ Tests: imported/w3c/web-platform-tests/custom-elements/parser/parser-sets-attributes-and-children.html >+ >+ * html/parser/HTMLDocumentParser.cpp: >+ (WebCore::HTMLDocumentParser::runScriptsForPausedTreeBuilder): Instantiate CustomElementReactionStack. Note that we >+ don't insert the custom element into the parser until we finish processing the custom element reactions. >+ > 2018-08-05 Ms2ger <Ms2ger@igalia.com> > > [GStreamer] Remove unsound assertions in MediaPlayerPrivateGStreamerBase. >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index cee8d7ef7c336e25564e9a217cda002841999849..1994510339d270995d5167942f1f94a83c6fb1dd 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -10851,6 +10851,7 @@ > 9B32CDA813DF7FA900F34D13 /* RenderedPosition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderedPosition.cpp; sourceTree = "<group>"; }; > 9B417062125662B3006B28FC /* ApplyBlockElementCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ApplyBlockElementCommand.h; sourceTree = "<group>"; }; > 9B417063125662B3006B28FC /* ApplyBlockElementCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ApplyBlockElementCommand.cpp; sourceTree = "<group>"; }; >+ 9B4376EF2117E872009D03A0 /* ThrowOnDynamicMarkupInsertionCountIncrementer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ThrowOnDynamicMarkupInsertionCountIncrementer.h; sourceTree = "<group>"; }; > 9B50B1DC17CD4C0F0087F63C /* FormNamedItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormNamedItem.h; sourceTree = "<group>"; }; > 9B532EA11BA928570038A827 /* SlotAssignment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SlotAssignment.cpp; sourceTree = "<group>"; }; > 9B532EA21BA928570038A827 /* SlotAssignment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SlotAssignment.h; sourceTree = "<group>"; }; >@@ -26563,6 +26564,7 @@ > A77B419F12E675A90054343D /* TextEventInputType.h */, > E4D988B517BFEB210084FB88 /* TextNodeTraversal.cpp */, > E4D988B317BFD1F60084FB88 /* TextNodeTraversal.h */, >+ 9B4376EF2117E872009D03A0 /* ThrowOnDynamicMarkupInsertionCountIncrementer.h */, > 0F54DD051881D5F5003EEDBB /* Touch.h */, > 0F54DD061881D5F5003EEDBB /* TouchEvent.h */, > 0F54DD071881D5F5003EEDBB /* TouchList.h */, >diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp >index d0ebe6ff7f984e723772fe14f3c5144084fbe46b..5203257ab64762f995ee586c8580247f471b8a1a 100644 >--- a/Source/WebCore/dom/Document.cpp >+++ b/Source/WebCore/dom/Document.cpp >@@ -2609,7 +2609,7 @@ ExceptionOr<RefPtr<WindowProxy>> Document::openForBindings(DOMWindow& activeWind > // FIXME: Add support for the 'type' and 'replace' parameters. > ExceptionOr<Document&> Document::openForBindings(Document* responsibleDocument, const String&, const String&) > { >- if (!isHTMLDocument()) >+ if (!isHTMLDocument() || m_throwOnDynamicMarkupInsertionCount) > return Exception { InvalidStateError }; > > // FIXME: This should also throw if "document's throw-on-dynamic-markup-insertion counter is greater than 0". >@@ -2753,7 +2753,7 @@ ExceptionOr<void> Document::closeForBindings() > // FIXME: We should follow the specification more closely: > // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-close > >- if (!isHTMLDocument()) >+ if (!isHTMLDocument() || m_throwOnDynamicMarkupInsertionCount) > return Exception { InvalidStateError }; > > // FIXME: This should also throw if "document's throw-on-dynamic-markup-insertion counter is greater than 0". >@@ -2984,7 +2984,7 @@ void Document::write(Document* responsibleDocument, SegmentedString&& text) > > ExceptionOr<void> Document::write(Document* responsibleDocument, Vector<String>&& strings) > { >- if (!isHTMLDocument()) >+ if (!isHTMLDocument() || m_throwOnDynamicMarkupInsertionCount) > return Exception { InvalidStateError }; > > // FIXME: This should also throw if "document's throw-on-dynamic-markup-insertion counter is greater than 0". >@@ -3001,7 +3001,7 @@ ExceptionOr<void> Document::write(Document* responsibleDocument, Vector<String>& > > ExceptionOr<void> Document::writeln(Document* responsibleDocument, Vector<String>&& strings) > { >- if (!isHTMLDocument()) >+ if (!isHTMLDocument() || m_throwOnDynamicMarkupInsertionCount) > return Exception { InvalidStateError }; > > // FIXME: This should also throw if "document's throw-on-dynamic-markup-insertion counter is greater than 0". >diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h >index 83b0889c09984984fa268354a8f47145be7c282b..f0de01a42d2a58a7377dcd5eb98fe222e80daca6 100644 >--- a/Source/WebCore/dom/Document.h >+++ b/Source/WebCore/dom/Document.h >@@ -1480,8 +1480,9 @@ protected: > private: > friend class DocumentParserYieldToken; > friend class Node; >- friend class IgnoreDestructiveWriteCountIncrementer; >+ friend class ThrowOnDynamicMarkupInsertionCountIncrementer; > friend class IgnoreOpensDuringUnloadCountIncrementer; >+ friend class IgnoreDestructiveWriteCountIncrementer; > > bool shouldInheritContentSecurityPolicyFromOwner() const; > >@@ -1854,12 +1855,15 @@ private: > int m_loadEventDelayCount { 0 }; > unsigned m_lastStyleUpdateSizeForTesting { 0 }; > >- // https://html.spec.whatwg.org/multipage/webappapis.html#ignore-destructive-writes-counter >- unsigned m_ignoreDestructiveWriteCount { 0 }; >+ // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#throw-on-dynamic-markup-insertion-counter >+ unsigned m_throwOnDynamicMarkupInsertionCount { 0 }; > >- // https://html.spec.whatwg.org/multipage/webappapis.html#ignore-opens-during-unload-counter >+ // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#ignore-opens-during-unload-counter > unsigned m_ignoreOpensDuringUnloadCount { 0 }; > >+ // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#ignore-destructive-writes-counter >+ unsigned m_ignoreDestructiveWriteCount { 0 }; >+ > unsigned m_activeParserCount { 0 }; > unsigned m_styleRecalcCount { 0 }; > >diff --git a/Source/WebCore/dom/ThrowOnDynamicMarkupInsertionCountIncrementer.h b/Source/WebCore/dom/ThrowOnDynamicMarkupInsertionCountIncrementer.h >new file mode 100644 >index 0000000000000000000000000000000000000000..83e71fa371f1a6f30fb4a5faf85f8b774b8a1df8 >--- /dev/null >+++ b/Source/WebCore/dom/ThrowOnDynamicMarkupInsertionCountIncrementer.h >@@ -0,0 +1,51 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#include "Document.h" >+ >+namespace WebCore { >+ >+class ThrowOnDynamicMarkupInsertionCountIncrementer { >+ WTF_MAKE_NONCOPYABLE(ThrowOnDynamicMarkupInsertionCountIncrementer); >+public: >+ explicit ThrowOnDynamicMarkupInsertionCountIncrementer(Document& document) >+ : m_document(document) >+ { >+ ++document.m_throwOnDynamicMarkupInsertionCount; >+ } >+ >+ ~ThrowOnDynamicMarkupInsertionCountIncrementer() >+ { >+ ASSERT(m_document->m_throwOnDynamicMarkupInsertionCount); >+ --m_document->m_throwOnDynamicMarkupInsertionCount; >+ } >+ >+private: >+ Ref<Document> m_document; >+}; >+ >+} // namespace WebCore >diff --git a/Source/WebCore/html/parser/HTMLDocumentParser.cpp b/Source/WebCore/html/parser/HTMLDocumentParser.cpp >index c9cc3ac91e081fc4ab276c1aacefff40c72f3d90..ad2ab6cdb974b270d53e66466e945419c7007244 100644 >--- a/Source/WebCore/html/parser/HTMLDocumentParser.cpp >+++ b/Source/WebCore/html/parser/HTMLDocumentParser.cpp >@@ -27,6 +27,7 @@ > #include "config.h" > #include "HTMLDocumentParser.h" > >+#include "CustomElementReactionQueue.h" > #include "DocumentFragment.h" > #include "DocumentLoader.h" > #include "Frame.h" >@@ -40,6 +41,7 @@ > #include "LinkLoader.h" > #include "NavigationScheduler.h" > #include "ScriptElement.h" >+#include "ThrowOnDynamicMarkupInsertionCountIncrementer.h" > > namespace WebCore { > >@@ -208,9 +210,14 @@ void HTMLDocumentParser::runScriptsForPausedTreeBuilder() > ASSERT(!m_treeBuilder->hasParserBlockingScriptWork()); > > // https://html.spec.whatwg.org/#create-an-element-for-the-token >- auto& elementInterface = constructionData->elementInterface.get(); >- auto newElement = elementInterface.constructElementWithFallback(*document(), constructionData->name); >- m_treeBuilder->didCreateCustomOrFallbackElement(WTFMove(newElement), *constructionData); >+ { >+ // Prevent document.open/write during reactions by allocating the incrementer before the reactions stack. >+ ThrowOnDynamicMarkupInsertionCountIncrementer incrementer(*document()); >+ CustomElementReactionStack reactionStack(document()->execState()); >+ auto& elementInterface = constructionData->elementInterface.get(); >+ auto newElement = elementInterface.constructElementWithFallback(*document(), constructionData->name); >+ m_treeBuilder->didCreateCustomOrFallbackElement(WTFMove(newElement), *constructionData); >+ } > return; > } > >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 981ca45e34127ae6ce1eb8b79996a64b25f4a0a0..af3b4263647b52c4c7e853f2a5df8b972d169dce 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,20 @@ >+2018-08-06 Ryosuke Niwa <rniwa@webkit.org> >+ >+ document.open and document.write must throw while the HTML parser is synchronously constructing a custom element >+ https://bugs.webkit.org/show_bug.cgi?id=187319 >+ <rdar://problem/42843012> >+ >+ Reviewed by Frédéric Wang. >+ >+ Added W3C style testharness.js tests. The WPT test added by https://github.com/web-platform-tests/wpt/pull/12037 >+ doesn't test nearly as many edge cases. >+ >+ * fast/custom-elements/resources/navigation-destination.html: Added. >+ * fast/custom-elements/throw-on-dynamic-markup-insertion-counter-construct-expected.txt: Added. >+ * fast/custom-elements/throw-on-dynamic-markup-insertion-counter-construct.html: Added. >+ * fast/custom-elements/throw-on-dynamic-markup-insertion-counter-reactions-expected.txt: Added. >+ * fast/custom-elements/throw-on-dynamic-markup-insertion-counter-reactions.html: Added. >+ > 2018-08-05 Philippe Normand <pnormand@igalia.com> > > [MediaCapabilities] Platform integration >diff --git a/LayoutTests/imported/w3c/ChangeLog b/LayoutTests/imported/w3c/ChangeLog >index 1bc0aa31b1d9d3860758a3bde32a660191c48d1c..81b8ba869281de044ef3b2d2f04beb16dc39137f 100644 >--- a/LayoutTests/imported/w3c/ChangeLog >+++ b/LayoutTests/imported/w3c/ChangeLog >@@ -1,3 +1,14 @@ >+2018-08-05 Ryosuke Niwa <rniwa@webkit.org> >+ >+ HTML parser should execute custom element reactions for setting attributes immediately after creating a custom element >+ https://bugs.webkit.org/show_bug.cgi?id=188336 >+ >+ Reviewed by Frédéric Wang. >+ >+ Rebaseline the test now that the relevant test case is passing. >+ >+ * web-platform-tests/custom-elements/parser/parser-sets-attributes-and-children-expected.txt: >+ > 2018-08-03 Ryosuke Niwa <rniwa@webkit.org> > > innerHTML should not synchronously create a custom element >diff --git a/LayoutTests/fast/custom-elements/resources/navigation-destination.html b/LayoutTests/fast/custom-elements/resources/navigation-destination.html >new file mode 100644 >index 0000000000000000000000000000000000000000..ede8d2c6eb13ea0d8b633780160811559e283950 >--- /dev/null >+++ b/LayoutTests/fast/custom-elements/resources/navigation-destination.html >@@ -0,0 +1,9 @@ >+<!DOCTYPE html> >+<html> >+<body> >+<p>Navigated!</p> >+<script> >+parent.postMessage('didNavigate', '*'); >+</script> >+</body> >+</html> >diff --git a/LayoutTests/fast/custom-elements/throw-on-dynamic-markup-insertion-counter-construct-expected.txt b/LayoutTests/fast/custom-elements/throw-on-dynamic-markup-insertion-counter-construct-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..d976fe770479edebc867449bfe18960a7c31839a >--- /dev/null >+++ b/LayoutTests/fast/custom-elements/throw-on-dynamic-markup-insertion-counter-construct-expected.txt >@@ -0,0 +1,13 @@ >+ >+PASS document.open() must throw an InvalidStateError when synchronously constructing a custom element >+PASS document.open("text/html") must throw an InvalidStateError when synchronously constructing a custom element >+PASS document.open(URL) must NOT throw an InvalidStateError when synchronously constructing a custom element >+PASS document.close() must throw an InvalidStateError when synchronously constructing a custom element >+PASS document.write must throw an InvalidStateError when synchronously constructing a custom element >+PASS document.writeln must throw an InvalidStateError when synchronously constructing a custom element >+PASS document.open() of another document must not throw an InvalidStateError when synchronously constructing a custom element >+PASS document.open("text/html") of another document must not throw an InvalidStateError when synchronously constructing a custom element >+PASS document.close() of another document must not throw an InvalidStateError when synchronously constructing a custom element >+PASS document.write of another document must not throw an InvalidStateError when synchronously constructing a custom element >+PASS document.writeln of another document must not throw an InvalidStateError when synchronously constructing a custom element >+ >diff --git a/LayoutTests/fast/custom-elements/throw-on-dynamic-markup-insertion-counter-construct.html b/LayoutTests/fast/custom-elements/throw-on-dynamic-markup-insertion-counter-construct.html >new file mode 100644 >index 0000000000000000000000000000000000000000..aa4c7b0dbfe6d13e4f03449862c174147776033c >--- /dev/null >+++ b/LayoutTests/fast/custom-elements/throw-on-dynamic-markup-insertion-counter-construct.html >@@ -0,0 +1,117 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<title>Custom Elements: create an element for a token must increment and decrement document's throw-on-dynamic-markup-insertion counter</title> >+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> >+<meta name="assert" content="Invoking document.open, document.write, document.writeln, and document.write must throw an exception when the HTML parser is creating a custom element for a token"> >+<meta name="help" content="https://html.spec.whatwg.org/multipage/parsing.html#create-an-element-for-the-token"> >+<meta name="help" content="https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#throw-on-dynamic-markup-insertion-counter"> >+<script src="../../resources/testharness.js"></script> >+<script src="../../resources/testharnessreport.js"></script> >+<script src="../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js"></script> >+</head> >+<body> >+<div id="log"></div> >+<script> >+ >+async function construct_custom_element_in_parser(test, call_function) >+{ >+ const window = await create_window_in_test(test); >+ const document = window.document; >+ >+ document.open(); >+ >+ let executed = false; >+ let exception = null; >+ class CustomElement extends window.HTMLElement { >+ constructor() { >+ super(); >+ try { >+ call_function(document, window); >+ } catch (error) { >+ exception = error; >+ } >+ executed = true; >+ } >+ } >+ window.customElements.define('some-element', CustomElement); >+ >+ document.write('<!DOCTYPE html><html><body><some-element></some-element></body></html>'); >+ document.close(); >+ >+ assert_true(executed, 'Must synchronously instantiate a custom element'); >+ return {window, document, exception}; >+} >+ >+promise_test(async function () { >+ const result = await construct_custom_element_in_parser(this, (document) => document.open()); >+ assert_throws({name: 'InvalidStateError'}, () => { throw result.exception; }, 'Must throw an InvalidStateError'); >+}, 'document.open() must throw an InvalidStateError when synchronously constructing a custom element'); >+ >+promise_test(async function () { >+ const result = await construct_custom_element_in_parser(this, (document) => document.open('text/html')); >+ assert_throws({name: 'InvalidStateError'}, () => { throw result.exception; }, 'Must throw an InvalidStateError'); >+}, 'document.open("text/html") must throw an InvalidStateError when synchronously constructing a custom element'); >+ >+// https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-document-open-window >+promise_test(async function () { >+ let load_promise = new Promise((resolve) => window.onmessage = (event) => resolve(event.data)); >+ const result = await construct_custom_element_in_parser(this, (document, window) => document.open('resources/navigation-destination.html', '_self', '')); >+ assert_equals(result.exception, null); >+ assert_equals(await load_promise, 'didNavigate'); >+}, 'document.open(URL) must NOT throw an InvalidStateError when synchronously constructing a custom element'); >+ >+promise_test(async function () { >+ const result = await construct_custom_element_in_parser(this, (document) => document.close()); >+ assert_throws({name: 'InvalidStateError'}, () => { throw result.exception; }, 'Must throw an InvalidStateError'); >+}, 'document.close() must throw an InvalidStateError when synchronously constructing a custom element'); >+ >+promise_test(async function () { >+ const result = await construct_custom_element_in_parser(this, (document) => document.write('<b>some text</b>')); >+ assert_throws({name: 'InvalidStateError'}, () => { throw result.exception; }, 'Must throw an InvalidStateError'); >+ assert_equals(result.document.querySelector('b'), null, 'Must not insert new content'); >+ assert_false(result.document.documentElement.innerHTML.includes('some text'), 'Must not insert new content'); >+}, 'document.write must throw an InvalidStateError when synchronously constructing a custom element'); >+ >+promise_test(async function () { >+ const result = await construct_custom_element_in_parser(this, (document) => document.writeln('<b>some text</b>')); >+ assert_throws({name: 'InvalidStateError'}, () => { throw result.exception; }, 'Must throw an InvalidStateError'); >+ assert_equals(result.document.querySelector('b'), null, 'Must not insert new content'); >+ assert_false(result.document.documentElement.innerHTML.includes('some text'), 'Must not insert new content'); >+}, 'document.writeln must throw an InvalidStateError when synchronously constructing a custom element'); >+ >+promise_test(async function () { >+ const another_window = await create_window_in_test(this); >+ const result = await construct_custom_element_in_parser(this, (document) => another_window.document.open()); >+ assert_equals(result.exception, null); >+}, 'document.open() of another document must not throw an InvalidStateError when synchronously constructing a custom element'); >+ >+promise_test(async function () { >+ const another_window = await create_window_in_test(this); >+ const result = await construct_custom_element_in_parser(this, (document) => another_window.document.open('text/html')); >+ assert_equals(result.exception, null); >+}, 'document.open("text/html") of another document must not throw an InvalidStateError when synchronously constructing a custom element'); >+ >+promise_test(async function () { >+ const another_window = await create_window_in_test(this); >+ const result = await construct_custom_element_in_parser(this, (document) => another_window.document.close()); >+ assert_equals(result.exception, null); >+}, 'document.close() of another document must not throw an InvalidStateError when synchronously constructing a custom element'); >+ >+promise_test(async function () { >+ const another_window = await create_window_in_test(this); >+ const result = await construct_custom_element_in_parser(this, (document) => another_window.document.write('<b>some text</b>')); >+ assert_equals(result.exception, null); >+ assert_equals(another_window.document.querySelector('b').outerHTML, '<b>some text</b>'); >+}, 'document.write of another document must not throw an InvalidStateError when synchronously constructing a custom element'); >+ >+promise_test(async function () { >+ const another_window = await create_window_in_test(this); >+ const result = await construct_custom_element_in_parser(this, (document) => another_window.document.writeln('<b>some text</b>')); >+ assert_equals(result.exception, null); >+ assert_equals(another_window.document.querySelector('b').outerHTML, '<b>some text</b>'); >+}, 'document.writeln of another document must not throw an InvalidStateError when synchronously constructing a custom element'); >+ >+</script> >+</body> >+</html> >diff --git a/LayoutTests/fast/custom-elements/throw-on-dynamic-markup-insertion-counter-reactions-expected.txt b/LayoutTests/fast/custom-elements/throw-on-dynamic-markup-insertion-counter-reactions-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..e19ed11945bd69013c74aa5b09bfe2fdb2634cf8 >--- /dev/null >+++ b/LayoutTests/fast/custom-elements/throw-on-dynamic-markup-insertion-counter-reactions-expected.txt >@@ -0,0 +1,13 @@ >+ >+PASS document.open() must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element >+PASS document.open("text/html") must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element >+PASS document.open(URL) must NOT throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element >+PASS document.close() must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element >+PASS document.write must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element >+PASS document.writeln must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element >+PASS document.open() of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element >+PASS document.open("text/html") of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element >+PASS document.close() of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element >+PASS document.write of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element >+PASS document.writeln of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element >+ >diff --git a/LayoutTests/fast/custom-elements/throw-on-dynamic-markup-insertion-counter-reactions.html b/LayoutTests/fast/custom-elements/throw-on-dynamic-markup-insertion-counter-reactions.html >new file mode 100644 >index 0000000000000000000000000000000000000000..c6cd7c60e70534b5aa4997b3f6ece557a4bcc818 >--- /dev/null >+++ b/LayoutTests/fast/custom-elements/throw-on-dynamic-markup-insertion-counter-reactions.html >@@ -0,0 +1,117 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<title>Custom Elements: create an element for a token must increment and decrement document's throw-on-dynamic-markup-insertion counter</title> >+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> >+<meta name="assert" content="Invoking document.open, document.write, document.writeln, and document.write must throw an exception when the HTML parser is creating a custom element for a token"> >+<meta name="help" content="https://html.spec.whatwg.org/multipage/parsing.html#create-an-element-for-the-token"> >+<meta name="help" content="https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#throw-on-dynamic-markup-insertion-counter"> >+<script src="../../resources/testharness.js"></script> >+<script src="../../resources/testharnessreport.js"></script> >+<script src="../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js"></script> >+</head> >+<body> >+<div id="log"></div> >+<script> >+ >+async function custom_element_reactions_in_parser(test, call_function) >+{ >+ const window = await create_window_in_test(test); >+ const document = window.document; >+ >+ document.open(); >+ >+ let executed = false; >+ let exception = null; >+ class CustomElement extends window.HTMLElement { >+ attributeChangedCallback(name, oldValue, newValue) { >+ try { >+ call_function(document, window); >+ } catch (error) { >+ exception = error; >+ } >+ executed = true; >+ } >+ } >+ CustomElement.observedAttributes = ['title']; >+ window.customElements.define('some-element', CustomElement); >+ >+ document.write('<!DOCTYPE html><html><body><some-element title="some title"></some-element></body></html>'); >+ document.close(); >+ >+ assert_true(executed, 'Must immediately process custom element reactions for setting attributes'); >+ return {frameElement, window, document, exception}; >+} >+ >+promise_test(async function () { >+ const result = await custom_element_reactions_in_parser(this, (document) => document.open()); >+ assert_throws({name: 'InvalidStateError'}, () => { throw result.exception; }, 'Must throw an InvalidStateError'); >+}, 'document.open() must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); >+ >+promise_test(async function () { >+ const result = await custom_element_reactions_in_parser(this, (document) => document.open('text/html')); >+ assert_throws({name: 'InvalidStateError'}, () => { throw result.exception; }, 'Must throw an InvalidStateError'); >+}, 'document.open("text/html") must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); >+ >+// https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-document-open-window >+promise_test(async function () { >+ let load_promise = new Promise((resolve) => window.onmessage = (event) => resolve(event.data)); >+ const result = await custom_element_reactions_in_parser(this, (document, window) => document.open('resources/navigation-destination.html', '_self', '')); >+ assert_equals(result.exception, null); >+ assert_equals(await load_promise, 'didNavigate'); >+}, 'document.open(URL) must NOT throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); >+ >+promise_test(async function () { >+ const result = await custom_element_reactions_in_parser(this, (document) => document.close()); >+ assert_throws({name: 'InvalidStateError'}, () => { throw result.exception; }, 'Must throw an InvalidStateError'); >+}, 'document.close() must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); >+ >+promise_test(async function () { >+ const result = await custom_element_reactions_in_parser(this, (document) => document.write('<b>some text</b>')); >+ assert_throws({name: 'InvalidStateError'}, () => { throw result.exception; }, 'Must throw an InvalidStateError'); >+ assert_equals(result.document.querySelector('b'), null, 'Must not insert new content'); >+ assert_false(result.document.documentElement.innerHTML.includes('some text'), 'Must not insert new content'); >+}, 'document.write must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); >+ >+promise_test(async function () { >+ const result = await custom_element_reactions_in_parser(this, (document) => document.writeln('<b>some text</b>')); >+ assert_throws({name: 'InvalidStateError'}, () => { throw result.exception; }, 'Must throw an InvalidStateError'); >+ assert_equals(result.document.querySelector('b'), null, 'Must not insert new content'); >+ assert_false(result.document.documentElement.innerHTML.includes('some text'), 'Must not insert new content'); >+}, 'document.writeln must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); >+ >+promise_test(async function () { >+ const another_window = await create_window_in_test(this); >+ const result = await custom_element_reactions_in_parser(this, (document) => another_window.document.open()); >+ assert_equals(result.exception, null); >+}, 'document.open() of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); >+ >+promise_test(async function () { >+ const another_window = await create_window_in_test(this); >+ const result = await custom_element_reactions_in_parser(this, (document) => another_window.document.open('text/html')); >+ assert_equals(result.exception, null); >+}, 'document.open("text/html") of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); >+ >+promise_test(async function () { >+ const another_window = await create_window_in_test(this); >+ const result = await custom_element_reactions_in_parser(this, (document) => another_window.document.close()); >+ assert_equals(result.exception, null); >+}, 'document.close() of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); >+ >+promise_test(async function () { >+ const another_window = await create_window_in_test(this); >+ const result = await custom_element_reactions_in_parser(this, (document) => another_window.document.write('<b>some text</b>')); >+ assert_equals(result.exception, null); >+ assert_equals(another_window.document.querySelector('b').outerHTML, '<b>some text</b>'); >+}, 'document.write of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); >+ >+promise_test(async function () { >+ const another_window = await create_window_in_test(this); >+ const result = await custom_element_reactions_in_parser(this, (document) => another_window.document.writeln('<b>some text</b>')); >+ assert_equals(result.exception, null); >+ assert_equals(another_window.document.querySelector('b').outerHTML, '<b>some text</b>'); >+}, 'document.writeln of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); >+ >+</script> >+</body> >+</html> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/custom-elements/parser/parser-sets-attributes-and-children-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/custom-elements/parser/parser-sets-attributes-and-children-expected.txt >index e2317aa63f7dcc560e2038f1dfae5d698ac89f42..bc0c300e768f5efc4b5aa6080097dfbf41b8e0ec 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/custom-elements/parser/parser-sets-attributes-and-children-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/custom-elements/parser/parser-sets-attributes-and-children-expected.txt >@@ -3,5 +3,5 @@ PASS HTML parser must set the attributes > PASS HTML parser must append child nodes > PASS HTML parser must set the attributes or append children before calling constructor > FAIL HTML parser should call connectedCallback before appending child nodes. assert_equals: expected 0 but got 2 >-FAIL HTML parser must enqueue attributeChanged reactions assert_equals: attributeChangedCallback should be called before appending a child expected 0 but got 2 >+PASS HTML parser must enqueue attributeChanged reactions > hello world
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 188336
:
346607
|
346608
|
346728
|
346730
|
346731