Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(822)

Unified Diff: third_party/WebKit/LayoutTests/custom-elements/spec/parsing.html

Issue 2200613002: The HTML parser synchronously creates custom elements (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/LayoutTests/custom-elements/spec/parsing.html
diff --git a/third_party/WebKit/LayoutTests/custom-elements/spec/parsing.html b/third_party/WebKit/LayoutTests/custom-elements/spec/parsing.html
new file mode 100644
index 0000000000000000000000000000000000000000..5491e838e65487c642295fc209200c1dc6c73a82
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/custom-elements/spec/parsing.html
@@ -0,0 +1,268 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="resources/custom-elements-helpers.js"></script>
+<body>
+<script>
+'use strict';
+
+// Looks up the preceeding element (which should be a template
+// element) and creates a Promise test. The test name is taken from
+// the template's data-test attribute.
+//
+// The content of the template is loaded into an iframe. On load, f
+// is passed the frame's content window to run assertions.
+function test_with_content(f) {
+ let t = document.currentScript.previousElementSibling;
+ test_with_window(f, t.dataset.test, t.innerHTML);
+}
+
+// Searches the document for an iframe with the specified content window.
+function findFrameWithWindow(w) {
+ return Array.prototype.find.call(document.querySelectorAll('iframe'), (f) => {
+ return f.contentWindow === w;
+ });
+}
+
+test_with_window((w) => {
+ assert_equals(findFrameWithWindow(w).contentWindow, w,
+ 'should find the frame with this window');
+ assert_equals(findFrameWithWindow(window), undefined,
+ 'should return undefined if there is no such frame');
+}, 'sanity check the findFrameWithWindow function');
+</script>
+
+<template data-test="the parser synchronously creates elements">
+ <script>
+ 'use strict';
+
+ window.invocations = [];
+ customElements.define('a-a', class extends HTMLElement {
+ constructor() {
+ super();
+ invocations.push('constructor');
+ }
+ static get observedAttributes() { return ['x']; }
+ attributeChangedCallback(name, oldValue, newValue, nsuri) {
+ invocations.push(`${name}="${newValue}"`);
+ }
+ connectedCallback() {
+ invocations.push('connected');
+ }
+ });
+ </script>
+ <a-a x="y">
+ <script>
+ 'use strict';
kouhei (in TOK) 2016/08/15 02:10:31 Nit: indent
+
+ invocations.push('script');
+ </script>
+ </a-a>
+</template>
+<script>
+'use strict';
+
+test_with_content((w) => {
+ assert_array_equals(w.invocations,
+ ['constructor', 'x="y"', 'connected', 'script']);
+});
+</script>
+
+<template data-test="element creation failure produces unknown element">
+ <script>
+ 'use strict';
+
+ customElements.define('a-a', class extends HTMLElement {
+ constructor() {
+ super();
+ return document.documentElement;
kouhei (in TOK) 2016/08/15 02:10:31 add a comment why we are returning a documentEleme
+ }
+ });
+ </script>
+ <a-a>
+</template>
+<script>
+'use strict';
+
+test_with_content((w) => {
+ let e = w.document.querySelector('a-a');
+ assert_true(e.matches(':not(:defined)'));
+ assert_equals(Object.getPrototypeOf(e), w.HTMLUnknownElement.prototype);
+});
+</script>
+
+<template data-test="modify tree during creation">
+ <script>
+ 'use strict';
+
+ customElements.define('a-a', class extends HTMLElement {
+ constructor() {
+ super();
+ document.querySelector('b').remove();
+ }
+ });
+ </script>
+ <b>
+ <a-a>
+ </b>
+</template>
+<script>
+'use strict';
+
+test_with_content((w) => {
+ assert_equals(w.document.querySelectorAll('b').length, 0);
+});
+</script>
+
+<template data-test="destructive writes are blocked during construction">
+ <script>
+ 'use strict';
+
+ window.invocations = [];
+ customElements.define('a-a', class extends HTMLElement {
+ constructor() {
+ super();
+ invocations.push('constructor');
+ document.write(
+ `<script>'use strict'; invocations.push('written');</scr${'i'}pt>`);
+ }
+ connectedCallback() {
+ invocations.push('connected');
+ }
+ });
+ </script>
+ <a-a>
+ <script>
+ 'use strict';
+ invocations.push('parsed');
+ </script>
+</template>
+<script>
+'use strict';
+
+test_with_content((w) => {
+ assert_array_equals(
+ w.invocations,
+ ['constructor', 'connected', 'parsed'],
+ 'the destructive document.write content should have been ignored');
+});
+</script>
+
+<template data-test="non-destructive writes are not blocked">
kouhei (in TOK) 2016/08/15 02:10:31 maybe document why? "Parser pause flag (https://ht
+ <script>
+ 'use strict';
+
+ window.invocations = [];
+ customElements.define('a-a', class extends HTMLElement {
+ constructor() {
+ super();
+ invocations.push('constructor');
+ document.write(
+ `<script>'use strict'; invocations.push('written');</scr${'i'}pt>`);
+ }
+ connectedCallback() {
+ invocations.push('connected');
+ }
+ });
+ document.write('<a-a>');
+ invocations.push('post write');
+ </script>
+ <script>
+ 'use strict';
+ invocations.push('parsed');
+ </script>
+</template>
+<script>
+'use strict';
+
+test_with_content((w) => {
+ assert_array_equals(
+ w.invocations,
+ ['constructor', 'connected', 'post write', 'written', 'parsed'],
+ 'the non-destructive document.write content should have been inserted');
+});
+</script>
+
+<template data-test="innerHTML is not blocked by custom element constructors">
+ <script>
+ 'use strict';
+
+ window.invocations = [];
+ customElements.define('a-a', class extends HTMLElement {
+ constructor() {
+ super();
+ invocations.push(`construct ${this.id}`);
+ if (!this.id) {
+ // If the ID attribute is not set, this was created
+ // synchronously by the parser. Adding children at this point
+ // would cause creation to fail, so embiggen the previous
+ // element instead.
+ document.querySelector('span').innerHTML = `<a-a id="r">`;
+ }
+ }
+ connectedCallback() {
+ invocations.push(`connected ${this.parentNode.localName}/${this.id}`);
+ }
+ });
+ </script>
+ <span></span>
+ <a-a id="q"></a-a>
+ <script>
+ 'use strict';
+ invocations.push('parsed');
+ </script>
+</template>
+<script>
+'use strict';
+
+test_with_content((w) => {
+ assert_array_equals(
+ w.invocations,
+ ['construct ', 'construct r', 'connected span/r', 'connected body/q',
+ 'parsed'],
+ 'custom element constructors should not block innerHTML');
+});
+</script>
+
+
+<template data-test="parsing without a browsing context should not create custom elements">
+ <body>
+ <script>
+ 'use strict';
+
+ let f = parent.findFrameWithWindow(window);
+ f.invocations = [];
+
+ customElements.define('a-a', class extends HTMLElement {
+ constructor() {
+ super();
+ f.invocations.push(this);
+ }
+ });
+ </script>
+ <a-a></a-a>
+ <script>
+ f.detached = document.implementation.createHTMLDocument();
+ f.detached.documentElement.appendChild(document.body);
+ </script>
+ <a-a></a-a>
+</template>
+<script>
+'use strict';
+
+test_with_content((w) => {
+ let f = findFrameWithWindow(w);
+ assert_array_equals(f.invocations,
+ [f.detached.querySelector('a-a:first-of-type')],
+ 'one element should have been constructed');
+ assert_true(f.invocations[0].matches(':defined'),
+ 'the element should have been created successfully');
+
+ let elements = f.detached.querySelectorAll('a-a');
+ console.log(f.invocations[0].parentNode);
+ assert_equals(elements.length, 2,
+ 'two elements should have been created');
+ assert_equals(Object.getPrototypeOf(elements[1]), w.HTMLElement.prototype,
+ 'the second element should be un-upgraded, not failed');
+});
+</script>

Powered by Google App Engine
This is Rietveld 408576698