Bug 1599630 [wpt PR 20465] - Disallow recursive custom element constructions, a=testonly

Automatic update from web-platform-tests
Disallow recursive custom element constructions

With this CL, recursive custom element constructions are no
longer allowed. I.e. this will now only run the constructor once:
  class extends HTMLElement {
    constructor() {
      super();
      customElements.upgrade(this);
    }
  }

Previously, the code and spec had a bug which caused the above
code snippet to infinitely recurse. In [1] the spec has changed,
to set the custom element state to "failed" before the constructor
is called. With this change in place, recursive calls will
early-out at step #2 (of [2]), and avoid the recursion.

[1] https://github.com/whatwg/html/pull/5126
[2] https://html.spec.whatwg.org/multipage/custom-elements.html#upgrades

Bug: 966472
Change-Id: I76e88c0b70132eee2482c304ef9e727ae1fe8fc7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1931644
Reviewed-by: Kent Tamura <tkent@chromium.org>
Commit-Queue: Mason Freed <masonfreed@chromium.org>
Auto-Submit: Mason Freed <masonfreed@chromium.org>
Cr-Commit-Position: refs/heads/master@{#727841}

--

wpt-commits: 4f24cabbe1f503f3daf8cf0834f4fb1a032f31bc
wpt-pr: 20465
This commit is contained in:
Mason Freed 2020-01-02 10:54:19 +00:00 коммит произвёл moz-wptsync-bot
Родитель 3f1f90850c
Коммит 100fe4df0b
2 изменённых файлов: 68 добавлений и 0 удалений

Просмотреть файл

@ -90,4 +90,22 @@ function test_defined(expected, element, description) {
assert_equals(style.color, expected ? defined : not_defined, 'getComputedStyle');
}, `${description} should ${expected ? 'be' : 'not be'} :defined`);
}
test(function () {
var log = [];
var instance = document.createElement('my-custom-element-2');
document.body.appendChild(instance);
customElements.define('my-custom-element-2',class extends HTMLElement {
constructor() {
super();
log.push([this, 'begin']);
assert_false(this.matches(":defined"), "During construction, this should not match :defined");
log.push([this, 'end']);
}
});
assert_equals(log.length, 2);
assert_array_equals(log[0], [instance, 'begin']);
assert_array_equals(log[1], [instance, 'end']);
}, 'this.matches(:defined) should not match during an upgrade');
</script>

Просмотреть файл

@ -12,6 +12,9 @@
<script src="resources/custom-elements-helpers.js"></script>
</head>
<body>
<infinite-cloning-element-1></infinite-cloning-element-1>
<infinite-cloning-element-2 id="a"></infinite-cloning-element-2>
<infinite-cloning-element-2 id="b"></infinite-cloning-element-2>
<div id="log"></div>
<script>
setup({allow_uncaught_exception:true});
@ -203,6 +206,53 @@ test(() => {
}, 'If definition\'s disable shadow is true and element\'s shadow root is ' +
'non-null, then throw a "NotSupportedError" DOMException.');
test(() => {
var log = [];
customElements.define('infinite-cloning-element-1',class extends HTMLElement {
constructor() {
super();
log.push([this, 'begin']);
// Potential infinite recursion:
customElements.upgrade(this);
log.push([this, 'end']);
}
});
assert_equals(log.length, 2);
const instance = document.querySelector("infinite-cloning-element-1");
assert_array_equals(log[0], [instance, 'begin']);
assert_array_equals(log[1], [instance, 'end']);
}, 'Infinite constructor recursion with upgrade(this) should not be possible');
test(() => {
var log = [];
customElements.define('infinite-cloning-element-2',class extends HTMLElement {
constructor() {
super();
log.push([this, 'begin']);
const b = document.querySelector("#b");
b.remove();
// While this constructor is running for "a", "b" is still
// undefined, and so inserting it into the document will enqueue a
// second upgrade reaction for "b" in addition to the one enqueued
// by defining x-foo.
document.body.appendChild(b);
log.push([this, 'end']);
}
});
assert_equals(log.length, 4);
const instanceA = document.querySelector("#a");
const instanceB = document.querySelector("#b");
assert_array_equals(log[0], [instanceA, 'begin']);
assert_array_equals(log[1], [instanceB, 'begin']);
assert_array_equals(log[2], [instanceB, 'end']);
assert_array_equals(log[3], [instanceA, 'end']);
}, 'Infinite constructor recursion with appendChild should not be possible');
</script>
</body>
</html>