Index: third_party/WebKit/LayoutTests/imported/wpt/custom-elements/CustomElementRegistry.html |
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/custom-elements/CustomElementRegistry.html b/third_party/WebKit/LayoutTests/imported/wpt/custom-elements/CustomElementRegistry.html |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ecc7810e8df8acfb251cf93bd992a3e1266d51dd |
--- /dev/null |
+++ b/third_party/WebKit/LayoutTests/imported/wpt/custom-elements/CustomElementRegistry.html |
@@ -0,0 +1,580 @@ |
+<!DOCTYPE html> |
+<html> |
+<head> |
+<title>Custom Elements: CustomElementRegistry interface</title> |
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> |
+<meta name="assert" content="CustomElementRegistry interface must exist"> |
+<script src="/resources/testharness.js"></script> |
+<script src="/resources/testharnessreport.js"></script> |
+</head> |
+<body> |
+<div id="log"></div> |
+<script> |
+ |
+test(function () { |
+ assert_true('define' in CustomElementRegistry.prototype, '"define" exists on CustomElementRegistry.prototype'); |
+ assert_true('define' in customElements, '"define" exists on window.customElements'); |
+}, 'CustomElementRegistry interface must have define as a method'); |
+ |
+test(function () { |
+ assert_throws({'name': 'TypeError'}, function () { customElements.define('badname', 1); }, |
+ 'customElements.define must throw a TypeError when the element interface is a number'); |
+ assert_throws({'name': 'TypeError'}, function () { customElements.define('badname', '123'); }, |
+ 'customElements.define must throw a TypeError when the element interface is a string'); |
+ assert_throws({'name': 'TypeError'}, function () { customElements.define('badname', {}); }, |
+ 'customElements.define must throw a TypeError when the element interface is an object'); |
+ assert_throws({'name': 'TypeError'}, function () { customElements.define('badname', []); }, |
+ 'customElements.define must throw a TypeError when the element interface is an array'); |
+}, 'customElements.define must throw when the element interface is not a constructor'); |
+ |
+test(function () { |
+ customElements.define('custom-html-element', HTMLElement); |
+}, 'customElements.define must not throw the constructor is HTMLElement'); |
+ |
+test(function () { |
+ class MyCustomElement extends HTMLElement {}; |
+ |
+ assert_throws({'name': 'SyntaxError'}, function () { customElements.define(null, MyCustomElement); }, |
+ 'customElements.define must throw a SyntaxError if the tag name is null'); |
+ assert_throws({'name': 'SyntaxError'}, function () { customElements.define('', MyCustomElement); }, |
+ 'customElements.define must throw a SyntaxError if the tag name is empty'); |
+ assert_throws({'name': 'SyntaxError'}, function () { customElements.define('abc', MyCustomElement); }, |
+ 'customElements.define must throw a SyntaxError if the tag name does not contain "-"'); |
+ assert_throws({'name': 'SyntaxError'}, function () { customElements.define('a-Bc', MyCustomElement); }, |
+ 'customElements.define must throw a SyntaxError if the tag name contains an upper case letter'); |
+ |
+ var builtinTagNames = [ |
+ 'annotation-xml', |
+ 'color-profile', |
+ 'font-face', |
+ 'font-face-src', |
+ 'font-face-uri', |
+ 'font-face-format', |
+ 'font-face-name', |
+ 'missing-glyph' |
+ ]; |
+ |
+ for (var tagName of builtinTagNames) { |
+ assert_throws({'name': 'SyntaxError'}, function () { customElements.define(tagName, MyCustomElement); }, |
+ 'customElements.define must throw a SyntaxError if the tag name is "' + tagName + '"'); |
+ } |
+ |
+}, 'customElements.define must throw with an invalid name'); |
+ |
+test(function () { |
+ class SomeCustomElement extends HTMLElement {}; |
+ |
+ var calls = []; |
+ var OtherCustomElement = new Proxy(class extends HTMLElement {}, { |
+ get: function (target, name) { |
+ calls.push(name); |
+ return target[name]; |
+ } |
+ }) |
+ |
+ customElements.define('some-custom-element', SomeCustomElement); |
+ assert_throws({'name': 'NotSupportedError'}, function () { customElements.define('some-custom-element', OtherCustomElement); }, |
+ 'customElements.define must throw a NotSupportedError if the specified tag name is already used'); |
+ assert_array_equals(calls, [], 'customElements.define must validate the custom element name before getting the prototype of the constructor'); |
+ |
+}, 'customElements.define must throw when there is already a custom element of the same name'); |
+ |
+test(function () { |
+ class AnotherCustomElement extends HTMLElement {}; |
+ |
+ customElements.define('another-custom-element', AnotherCustomElement); |
+ assert_throws({'name': 'NotSupportedError'}, function () { customElements.define('some-other-element', AnotherCustomElement); }, |
+ 'customElements.define must throw a NotSupportedError if the specified class already defines an element'); |
+ |
+}, 'customElements.define must throw a NotSupportedError when there is already a custom element with the same class'); |
+ |
+test(function () { |
+ var outerCalls = []; |
+ var OuterCustomElement = new Proxy(class extends HTMLElement { }, { |
+ get: function (target, name) { |
+ outerCalls.push(name); |
+ customElements.define('inner-custom-element', InnerCustomElement); |
+ return target[name]; |
+ } |
+ }); |
+ var innerCalls = []; |
+ var InnerCustomElement = new Proxy(class extends HTMLElement { }, { |
+ get: function (target, name) { |
+ outerCalls.push(name); |
+ return target[name]; |
+ } |
+ }); |
+ |
+ assert_throws({'name': 'NotSupportedError'}, function () { customElements.define('outer-custom-element', OuterCustomElement); }, |
+ 'customElements.define must throw a NotSupportedError if the specified class already defines an element'); |
+ assert_array_equals(outerCalls, ['prototype'], 'customElements.define must get "prototype"'); |
+ assert_array_equals(innerCalls, [], |
+ 'customElements.define must throw a NotSupportedError when element definition is running flag is set' |
+ + ' before getting the prototype of the constructor'); |
+ |
+}, 'customElements.define must throw a NotSupportedError when element definition is running flag is set'); |
+ |
+test(function () { |
+ var calls = []; |
+ var ElementWithBadInnerConstructor = new Proxy(class extends HTMLElement { }, { |
+ get: function (target, name) { |
+ calls.push(name); |
+ customElements.define('inner-custom-element', 1); |
+ return target[name]; |
+ } |
+ }); |
+ |
+ assert_throws({'name': 'TypeError'}, function () { |
+ customElements.define('element-with-bad-inner-constructor', ElementWithBadInnerConstructor); |
+ }, 'customElements.define must throw a NotSupportedError if IsConstructor(constructor) is false'); |
+ |
+ assert_array_equals(calls, ['prototype'], 'customElements.define must get "prototype"'); |
+}, 'customElements.define must check IsConstructor on the constructor before checking the element definition is running flag'); |
+ |
+test(function () { |
+ var calls = []; |
+ var ElementWithBadInnerName = new Proxy(class extends HTMLElement { }, { |
+ get: function (target, name) { |
+ calls.push(name); |
+ customElements.define('badname', class extends HTMLElement {}); |
+ return target[name]; |
+ } |
+ }); |
+ |
+ assert_throws({'name': 'SyntaxError'}, function () { |
+ customElements.define('element-with-bad-inner-name', ElementWithBadInnerName); |
+ }, 'customElements.define must throw a SyntaxError if the specified name is not a valid custom element name'); |
+ |
+ assert_array_equals(calls, ['prototype'], 'customElements.define must get "prototype"'); |
+}, 'customElements.define must validate the custom element name before checking the element definition is running flag'); |
+ |
+test(function () { |
+ var unresolvedElement = document.createElement('constructor-calls-define'); |
+ document.body.appendChild(unresolvedElement); |
+ var elementUpgradedDuringUpgrade = document.createElement('defined-during-upgrade'); |
+ document.body.appendChild(elementUpgradedDuringUpgrade); |
+ |
+ var DefinedDuringUpgrade = class extends HTMLElement { }; |
+ |
+ class ConstructorCallsDefine extends HTMLElement { |
+ constructor() { |
+ customElements.define('defined-during-upgrade', DefinedDuringUpgrade); |
+ assert_false(unresolvedElement instanceof ConstructorCallsDefine); |
+ assert_true(elementUpgradedDuringUpgrade instanceof DefinedDuringUpgrade); |
+ super(); |
+ assert_true(unresolvedElement instanceof ConstructorCallsDefine); |
+ assert_true(elementUpgradedDuringUpgrade instanceof DefinedDuringUpgrade); |
+ } |
+ } |
+ |
+ assert_false(unresolvedElement instanceof ConstructorCallsDefine); |
+ assert_false(elementUpgradedDuringUpgrade instanceof DefinedDuringUpgrade); |
+ |
+ customElements.define('constructor-calls-define', ConstructorCallsDefine); |
+}, 'customElements.define unset the element definition is running flag before upgrading custom elements'); |
+ |
+(function () { |
+ var testCase = async_test('customElements.define must not throw' |
+ +' when defining another custom element in a different global object during Get(constructor, "prototype")', {timeout: 100}); |
+ |
+ var iframe = document.createElement('iframe'); |
+ iframe.onload = function () { |
+ testCase.step(function () { |
+ var InnerCustomElement = class extends iframe.contentWindow.HTMLElement {}; |
+ var calls = []; |
+ var proxy = new Proxy(class extends HTMLElement { }, { |
+ get: function (target, name) { |
+ calls.push(name); |
+ iframe.contentWindow.customElements.define('another-custom-element', InnerCustomElement); |
+ return target[name]; |
+ } |
+ }) |
+ customElements.define('element-with-inner-element-define', proxy); |
+ assert_array_equals(calls, ['prototype'], 'customElements.define must get "prototype"'); |
+ assert_true(iframe.contentDocument.createElement('another-custom-element') instanceof InnerCustomElement); |
+ }); |
+ document.body.removeChild(iframe); |
+ testCase.done(); |
+ } |
+ |
+ document.body.appendChild(iframe); |
+})(); |
+ |
+test(function () { |
+ var calls = []; |
+ var ElementWithBadInnerName = new Proxy(class extends HTMLElement { }, { |
+ get: function (target, name) { |
+ calls.push(name); |
+ customElements.define('badname', class extends HTMLElement {}); |
+ return target[name]; |
+ } |
+ }); |
+ |
+ assert_throws({'name': 'SyntaxError'}, function () { |
+ customElements.define('element-with-bad-inner-name', ElementWithBadInnerName); |
+ }, 'customElements.define must throw a SyntaxError if the specified name is not a valid custom element name'); |
+ |
+ assert_array_equals(calls, ['prototype'], 'customElements.define must get "prototype"'); |
+}, ''); |
+ |
+test(function () { |
+ var calls = []; |
+ var proxy = new Proxy(class extends HTMLElement { }, { |
+ get: function (target, name) { |
+ calls.push(name); |
+ return target[name]; |
+ } |
+ }); |
+ customElements.define('proxy-element', proxy); |
+ assert_array_equals(calls, ['prototype']); |
+}, 'customElements.define must get "prototype" property of the constructor'); |
+ |
+test(function () { |
+ var proxy = new Proxy(class extends HTMLElement { }, { |
+ get: function (target, name) { |
+ throw {name: 'expectedError'}; |
+ } |
+ }); |
+ assert_throws({'name': 'expectedError'}, function () { customElements.define('element-with-string-prototype', proxy); }); |
+}, 'customElements.define must rethrow an exception thrown while getting "prototype" property of the constructor'); |
+ |
+test(function () { |
+ var returnedValue; |
+ var proxy = new Proxy(class extends HTMLElement { }, { |
+ get: function (target, name) { return returnedValue; } |
+ }); |
+ |
+ returnedValue = null; |
+ assert_throws({'name': 'TypeError'}, function () { customElements.define('element-with-string-prototype', proxy); }, |
+ 'customElements.define must throw when "prototype" property of the constructor is null'); |
+ returnedValue = undefined; |
+ assert_throws({'name': 'TypeError'}, function () { customElements.define('element-with-string-prototype', proxy); }, |
+ 'customElements.define must throw when "prototype" property of the constructor is undefined'); |
+ returnedValue = 'hello'; |
+ assert_throws({'name': 'TypeError'}, function () { customElements.define('element-with-string-prototype', proxy); }, |
+ 'customElements.define must throw when "prototype" property of the constructor is a string'); |
+ returnedValue = 1; |
+ assert_throws({'name': 'TypeError'}, function () { customElements.define('element-with-string-prototype', proxy); }, |
+ 'customElements.define must throw when "prototype" property of the constructor is a number'); |
+ |
+}, 'customElements.define must throw when "prototype" property of the constructor is not an object'); |
+ |
+test(function () { |
+ var constructor = function () {} |
+ var calls = []; |
+ constructor.prototype = new Proxy(constructor.prototype, { |
+ get: function (target, name) { |
+ calls.push(name); |
+ return target[name]; |
+ } |
+ }); |
+ customElements.define('element-with-proxy-prototype', constructor); |
+ assert_array_equals(calls, ['connectedCallback', 'disconnectedCallback', 'adoptedCallback', 'attributeChangedCallback']); |
+}, 'customElements.define must get callbacks of the constructor prototype'); |
+ |
+test(function () { |
+ var constructor = function () {} |
+ var calls = []; |
+ constructor.prototype = new Proxy(constructor.prototype, { |
+ get: function (target, name) { |
+ calls.push(name); |
+ if (name == 'disconnectedCallback') |
+ throw {name: 'expectedError'}; |
+ return target[name]; |
+ } |
+ }); |
+ assert_throws({'name': 'expectedError'}, function () { customElements.define('element-with-throwing-callback', constructor); }); |
+ assert_array_equals(calls, ['connectedCallback', 'disconnectedCallback'], |
+ 'customElements.define must not get callbacks after one of the get throws'); |
+}, 'customElements.define must rethrow an exception thrown while getting callbacks on the constructor prototype'); |
+ |
+test(function () { |
+ var constructor = function () {} |
+ var calls = []; |
+ constructor.prototype = new Proxy(constructor.prototype, { |
+ get: function (target, name) { |
+ calls.push(name); |
+ if (name == 'adoptedCallback') |
+ return 1; |
+ return target[name]; |
+ } |
+ }); |
+ assert_throws({'name': 'TypeError'}, function () { customElements.define('element-with-throwing-callback', constructor); }); |
+ assert_array_equals(calls, ['connectedCallback', 'disconnectedCallback', 'adoptedCallback'], |
+ 'customElements.define must not get callbacks after one of the conversion throws'); |
+}, 'customElements.define must rethrow an exception thrown while converting a callback value to Function callback type'); |
+ |
+test(function () { |
+ var constructor = function () {} |
+ constructor.prototype.attributeChangedCallback = function () { }; |
+ var prototypeCalls = []; |
+ var callOrder = 0; |
+ constructor.prototype = new Proxy(constructor.prototype, { |
+ get: function (target, name) { |
+ if (name == 'prototype' || name == 'observedAttributes') |
+ throw 'Unexpected access to observedAttributes'; |
+ prototypeCalls.push(callOrder++); |
+ prototypeCalls.push(name); |
+ return target[name]; |
+ } |
+ }); |
+ var constructorCalls = []; |
+ var proxy = new Proxy(constructor, { |
+ get: function (target, name) { |
+ constructorCalls.push(callOrder++); |
+ constructorCalls.push(name); |
+ return target[name]; |
+ } |
+ }); |
+ customElements.define('element-with-attribute-changed-callback', proxy); |
+ assert_array_equals(prototypeCalls, [1, 'connectedCallback', 2, 'disconnectedCallback', 3, 'adoptedCallback', 4, 'attributeChangedCallback']); |
+ assert_array_equals(constructorCalls, [0, 'prototype', 5, 'observedAttributes']); |
+}, 'customElements.define must get "observedAttributes" property on the constructor prototype when "attributeChangedCallback" is present'); |
+ |
+test(function () { |
+ var constructor = function () {} |
+ constructor.prototype.attributeChangedCallback = function () { }; |
+ var calls = []; |
+ var proxy = new Proxy(constructor, { |
+ get: function (target, name) { |
+ calls.push(name); |
+ if (name == 'observedAttributes') |
+ throw {name: 'expectedError'}; |
+ return target[name]; |
+ } |
+ }); |
+ assert_throws({'name': 'expectedError'}, function () { customElements.define('element-with-throwing-observed-attributes', proxy); }); |
+ assert_array_equals(calls, ['prototype', 'observedAttributes'], |
+ 'customElements.define must get "prototype" and "observedAttributes" on the constructor'); |
+}, 'customElements.define must rethrow an exception thrown while getting observedAttributes on the constructor prototype'); |
+ |
+test(function () { |
+ var constructor = function () {} |
+ constructor.prototype.attributeChangedCallback = function () { }; |
+ var calls = []; |
+ var proxy = new Proxy(constructor, { |
+ get: function (target, name) { |
+ calls.push(name); |
+ if (name == 'observedAttributes') |
+ return 1; |
+ return target[name]; |
+ } |
+ }); |
+ assert_throws({'name': 'TypeError'}, function () { customElements.define('element-with-invalid-observed-attributes', proxy); }); |
+ assert_array_equals(calls, ['prototype', 'observedAttributes'], |
+ 'customElements.define must get "prototype" and "observedAttributes" on the constructor'); |
+}, 'customElements.define must rethrow an exception thrown while converting the value of observedAttributes to sequence<DOMString>'); |
+ |
+test(function () { |
+ var constructor = function () {} |
+ constructor.prototype.attributeChangedCallback = function () { }; |
+ constructor.observedAttributes = {[Symbol.iterator]: function *() { |
+ yield 'foo'; |
+ throw {name: 'SomeError'}; |
+ }}; |
+ assert_throws({'name': 'SomeError'}, function () { customElements.define('element-with-generator-observed-attributes', constructor); }); |
+}, 'customElements.define must rethrow an exception thrown while iterating over observedAttributes to sequence<DOMString>'); |
+ |
+test(function () { |
+ var constructor = function () {} |
+ constructor.prototype.attributeChangedCallback = function () { }; |
+ constructor.observedAttributes = {[Symbol.iterator]: 1}; |
+ assert_throws({'name': 'TypeError'}, function () { customElements.define('element-with-observed-attributes-with-uncallable-iterator', constructor); }); |
+}, 'customElements.define must rethrow an exception thrown while retrieving Symbol.iterator on observedAttributes'); |
+ |
+test(function () { |
+ var constructor = function () {} |
+ constructor.observedAttributes = 1; |
+ customElements.define('element-without-callback-with-invalid-observed-attributes', constructor); |
+}, 'customElements.define must not throw even if "observedAttributes" fails to convert if "attributeChangedCallback" is not defined'); |
+ |
+test(function () { |
+ class MyCustomElement extends HTMLElement {}; |
+ customElements.define('my-custom-element', MyCustomElement); |
+ |
+ var instance = new MyCustomElement; |
+ assert_true(instance instanceof MyCustomElement, |
+ 'An instance of a custom HTML element be an instance of the associated interface'); |
+ |
+ assert_true(instance instanceof HTMLElement, |
+ 'An instance of a custom HTML element must inherit from HTMLElement'); |
+ |
+ assert_equals(instance.localName, 'my-custom-element', |
+ 'An instance of a custom element must use the associated tag name'); |
+ |
+ assert_equals(instance.namespaceURI, 'http://www.w3.org/1999/xhtml', |
+ 'A custom element HTML must use HTML namespace'); |
+ |
+}, 'customElements.define must define an instantiatable custom element'); |
+ |
+test(function () { |
+ var disconnectedElement = document.createElement('some-custom'); |
+ var connectedElementBeforeShadowHost = document.createElement('some-custom'); |
+ var connectedElementAfterShadowHost = document.createElement('some-custom'); |
+ var elementInShadowTree = document.createElement('some-custom'); |
+ var childElementOfShadowHost = document.createElement('some-custom'); |
+ var customShadowHost = document.createElement('some-custom'); |
+ var elementInNestedShadowTree = document.createElement('some-custom'); |
+ |
+ var container = document.createElement('div'); |
+ var shadowHost = document.createElement('div'); |
+ var shadowRoot = shadowHost.attachShadow({mode: 'closed'}); |
+ container.appendChild(connectedElementBeforeShadowHost); |
+ container.appendChild(shadowHost); |
+ container.appendChild(connectedElementAfterShadowHost); |
+ shadowHost.appendChild(childElementOfShadowHost); |
+ shadowRoot.appendChild(elementInShadowTree); |
+ shadowRoot.appendChild(customShadowHost); |
+ |
+ var innerShadowRoot = customShadowHost.attachShadow({mode: 'closed'}); |
+ innerShadowRoot.appendChild(elementInNestedShadowTree); |
+ |
+ var calls = []; |
+ class SomeCustomElement extends HTMLElement { |
+ constructor() { |
+ super(); |
+ calls.push(this); |
+ } |
+ }; |
+ |
+ document.body.appendChild(container); |
+ customElements.define('some-custom', SomeCustomElement); |
+ assert_array_equals(calls, [connectedElementBeforeShadowHost, elementInShadowTree, customShadowHost, elementInNestedShadowTree, childElementOfShadowHost, connectedElementAfterShadowHost]); |
+}, 'customElements.define must upgrade elements in the shadow-including tree order'); |
+ |
+test(function () { |
+ assert_true('get' in CustomElementRegistry.prototype, '"get" exists on CustomElementRegistry.prototype'); |
+ assert_true('get' in customElements, '"get" exists on window.customElements'); |
+}, 'CustomElementRegistry interface must have get as a method'); |
+ |
+test(function () { |
+ assert_equals(customElements.get('a-b'), undefined); |
+}, 'customElements.get must return undefined when the registry does not contain an entry with the given name'); |
+ |
+test(function () { |
+ assert_equals(customElements.get('html'), undefined); |
+ assert_equals(customElements.get('span'), undefined); |
+ assert_equals(customElements.get('div'), undefined); |
+ assert_equals(customElements.get('g'), undefined); |
+ assert_equals(customElements.get('ab'), undefined); |
+}, 'customElements.get must return undefined when the registry does not contain an entry with the given name even if the name was not a valid custom element name'); |
+ |
+test(function () { |
+ assert_equals(customElements.get('existing-custom-element'), undefined); |
+ class ExistingCustomElement extends HTMLElement {}; |
+ customElements.define('existing-custom-element', ExistingCustomElement); |
+ assert_equals(customElements.get('existing-custom-element'), ExistingCustomElement); |
+}, 'customElements.get return the constructor of the entry with the given name when there is a matching entry.'); |
+ |
+test(function () { |
+ assert_true(customElements.whenDefined('some-name') instanceof Promise); |
+}, 'customElements.whenDefined must return a promise for a valid custom element name'); |
+ |
+test(function () { |
+ assert_equals(customElements.whenDefined('some-name'), customElements.whenDefined('some-name')); |
+}, 'customElements.whenDefined must return the same promise each time invoked for a valid custom element name which has not been defined'); |
+ |
+promise_test(function () { |
+ var resolved = false; |
+ var rejected = false; |
+ customElements.whenDefined('a-b').then(function () { resolved = true; }, function () { rejected = true; }); |
+ return Promise.resolve().then(function () { |
+ assert_false(resolved, 'The promise returned by "whenDefined" must not be resolved until a custom element is defined'); |
+ assert_false(rejected, 'The promise returned by "whenDefined" must not be rejected until a custom element is defined'); |
+ }); |
+}, 'customElements.whenDefined must return an unresolved promise when the registry does not contain the entry with the given name') |
+ |
+promise_test(function () { |
+ var promise = customElements.whenDefined('badname'); |
+ promise.then(function (value) { promise.resolved = value; }, function (value) { promise.rejected = value; }); |
+ |
+ assert_false('resolved' in promise, 'The promise returned by "whenDefined" must not be resolved until the end of the next microtask'); |
+ assert_false('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected until the end of the next microtask'); |
+ |
+ return Promise.resolve().then(function () { |
+ assert_false('resolved' in promise, 'The promise returned by "whenDefined" must be resolved when a custom element is defined'); |
+ assert_true('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined'); |
+ }); |
+}, 'customElements.whenDefined must return a rejected promise when the given name is not a valid custom element name'); |
+ |
+promise_test(function () { |
+ customElements.define('preexisting-custom-element', class extends HTMLElement { }); |
+ |
+ var promise = customElements.whenDefined('preexisting-custom-element'); |
+ promise.then(function (value) { promise.resolved = value; }, function (value) { promise.rejected = value; }); |
+ |
+ assert_false('resolved' in promise, 'The promise returned by "whenDefined" must not be resolved until the end of the next microtask'); |
+ assert_false('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected until the end of the next microtask'); |
+ |
+ return Promise.resolve().then(function () { |
+ assert_true('resolved' in promise, 'The promise returned by "whenDefined" must be resolved when a custom element is defined'); |
+ assert_equals(promise.resolved, undefined, |
+ 'The promise returned by "whenDefined" must be resolved with "undefined" when a custom element is defined'); |
+ assert_false('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined'); |
+ }); |
+}, 'customElements.whenDefined must return a resolved promise when the registry contains the entry with the given name'); |
+ |
+promise_test(function () { |
+ class AnotherExistingCustomElement extends HTMLElement {}; |
+ customElements.define('another-existing-custom-element', AnotherExistingCustomElement); |
+ |
+ var promise1 = customElements.whenDefined('another-existing-custom-element'); |
+ var promise2 = customElements.whenDefined('another-existing-custom-element'); |
+ promise1.then(function (value) { promise1.resolved = value; }, function (value) { promise1.rejected = value; }); |
+ promise2.then(function (value) { promise2.resolved = value; }, function (value) { promise2.rejected = value; }); |
+ |
+ assert_not_equals(promise1, promise2); |
+ assert_false('resolved' in promise1, 'The promise returned by "whenDefined" must not be resolved until the end of the next microtask'); |
+ assert_false('resolved' in promise2, 'The promise returned by "whenDefined" must not be resolved until the end of the next microtask'); |
+ assert_false('rejected' in promise1, 'The promise returned by "whenDefined" must not be rejected until the end of the next microtask'); |
+ assert_false('rejected' in promise2, 'The promise returned by "whenDefined" must not be rejected until the end of the next microtask'); |
+ |
+ return Promise.resolve().then(function () { |
+ assert_true('resolved' in promise1, 'The promise returned by "whenDefined" must be resolved when a custom element is defined'); |
+ assert_equals(promise1.resolved, undefined, 'The promise returned by "whenDefined" must be resolved with "undefined" when a custom element is defined'); |
+ assert_false('rejected' in promise1, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined'); |
+ |
+ assert_true('resolved' in promise2, 'The promise returned by "whenDefined" must be resolved when a custom element is defined'); |
+ assert_equals(promise2.resolved, undefined, 'The promise returned by "whenDefined" must be resolved with "undefined" when a custom element is defined'); |
+ assert_false('rejected' in promise2, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined'); |
+ }); |
+}, 'customElements.whenDefined must return a new resolved promise each time invoked when the registry contains the entry with the given name'); |
+ |
+promise_test(function () { |
+ var promise = customElements.whenDefined('element-defined-after-whendefined'); |
+ promise.then(function (value) { promise.resolved = value; }, function (value) { promise.rejected = value; }); |
+ |
+ assert_false('resolved' in promise, 'The promise returned by "whenDefined" must not be resolved until the end of the next microtask'); |
+ assert_false('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected until the end of the next microtask'); |
+ |
+ var promiseAfterDefine; |
+ return Promise.resolve().then(function () { |
+ assert_false('resolved' in promise, 'The promise returned by "whenDefined" must not be resolved until the element is defined'); |
+ assert_false('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected until the element is defined'); |
+ assert_equals(customElements.whenDefined('element-defined-after-whendefined'), promise, |
+ '"whenDefined" must return the same unresolved promise before the custom element is defined'); |
+ customElements.define('element-defined-after-whendefined', class extends HTMLElement { }); |
+ assert_false('resolved' in promise, 'The promise returned by "whenDefined" must not be resolved until the end of the next microtask'); |
+ assert_false('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected until the end of the next microtask'); |
+ |
+ promiseAfterDefine = customElements.whenDefined('element-defined-after-whendefined'); |
+ promiseAfterDefine.then(function (value) { promiseAfterDefine.resolved = value; }, function (value) { promiseAfterDefine.rejected = value; }); |
+ assert_not_equals(promiseAfterDefine, promise, '"whenDefined" must return a resolved promise once the custom element is defined'); |
+ assert_false('resolved' in promiseAfterDefine, 'The promise returned by "whenDefined" must not be resolved until the end of the next microtask'); |
+ assert_false('rejected' in promiseAfterDefine, 'The promise returned by "whenDefined" must not be rejected until the end of the next microtask'); |
+ }).then(function () { |
+ assert_true('resolved' in promise, 'The promise returned by "whenDefined" must be resolved when a custom element is defined'); |
+ assert_equals(promise.resolved, undefined, |
+ 'The promise returned by "whenDefined" must be resolved with "undefined" when a custom element is defined'); |
+ assert_false('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined'); |
+ |
+ assert_true('resolved' in promiseAfterDefine, 'The promise returned by "whenDefined" must be resolved when a custom element is defined'); |
+ assert_equals(promiseAfterDefine.resolved, undefined, |
+ 'The promise returned by "whenDefined" must be resolved with "undefined" when a custom element is defined'); |
+ assert_false('rejected' in promiseAfterDefine, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined'); |
+ }); |
+}, 'A promise returned by customElements.whenDefined must be resolved by "define"'); |
+ |
+</script> |
+</body> |
+</html> |