gecko-dev/testing/web-platform/tests/custom-elements/CustomElementRegistry.html
James Graham cf6ec8d839 Bug 1309931 - Update web-platform-tests to revision 1d8e28e2c762b51c06670a373b23af6bd7a8aed7, a=testonly
MozReview-Commit-ID: 17dwWFxkprQ


--HG--
rename : testing/web-platform/tests/conformance-checkers/html-svg/animate-dom-01-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/animate-dom-01-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/animate-dom-02-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/animate-dom-02-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/animate-elem-40-t-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/animate-elem-40-t-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/animate-script-elem-01-b-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/animate-script-elem-01-b-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/animate-struct-dom-01-b-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/animate-struct-dom-01-b-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/conform-viewers-02-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/conform-viewers-02-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/coords-dom-03-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/coords-dom-03-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/interact-events-02-b-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/interact-events-02-b-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/interact-pevents-01-b-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/interact-pevents-01-b-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/interact-pevents-03-b-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/interact-pevents-03-b-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/interact-pevents-05-b-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/interact-pevents-05-b-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/interact-pevents-07-t-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/interact-pevents-07-t-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/interact-pevents-08-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/interact-pevents-08-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/interact-pevents-09-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/interact-pevents-09-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/interact-pointer-01-t-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/interact-pointer-01-t-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/interact-pointer-03-t-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/interact-pointer-03-t-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/masking-path-09-b-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/masking-path-09-b-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/paths-dom-01-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/paths-dom-01-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/paths-dom-02-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/paths-dom-02-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/struct-cond-02-t-isvalid.html => testing/web-platform/tests/conformance-checkers/html-svg/struct-cond-02-t-haswarn.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/struct-dom-07-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/struct-dom-07-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/struct-dom-08-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/struct-dom-08-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/struct-dom-11-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/struct-dom-11-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/struct-dom-13-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/struct-dom-13-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/struct-dom-14-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/struct-dom-14-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/struct-dom-15-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/struct-dom-15-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/struct-dom-20-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/struct-dom-20-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/struct-use-13-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/struct-use-13-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/text-dom-02-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/text-dom-02-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/text-dom-05-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/text-dom-05-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/text-tselect-02-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/text-tselect-02-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/text-tselect-03-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/text-tselect-03-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/types-dom-02-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/types-dom-02-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/types-dom-03-b-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/types-dom-03-b-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/types-dom-05-b-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/types-dom-05-b-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/types-dom-07-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/types-dom-07-f-isvalid.html
rename : testing/web-platform/tests/conformance-checkers/html-svg/types-dom-08-f-novalid.html => testing/web-platform/tests/conformance-checkers/html-svg/types-dom-08-f-isvalid.html
rename : testing/web-platform/tests/encrypted-media/Google/encrypted-media-utils.js => testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-utils.js
rename : testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_session_history_unload_prompt_1.html => testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_session_history_unload_prompt_1-manual.html
rename : testing/web-platform/tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-scrollamount-effect.html => testing/web-platform/tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-scrollamount-effect-manual.html
rename : testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_000.htm => testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_000-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_001.htm => testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_001-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_002.htm => testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_002-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_003.htm => testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_003-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_004.htm => testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_004-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_005.htm => testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_005-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_006.htm => testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_006-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_007.htm => testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_007-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_008.htm => testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_008-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_009.htm => testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_009-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_010.htm => testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_010-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_011.htm => testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_011-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_012.htm => testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_012-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_013.htm => testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_013-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_014.htm => testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_014-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_015.htm => testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_015-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_016.htm => testing/web-platform/tests/old-tests/submission/Microsoft/dragdrop/dragdrop_016-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_003.htm => testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_003-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_004.htm => testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_004-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_006.htm => testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_006-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_007.htm => testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_007-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_008.htm => testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_008-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_009.htm => testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_009-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_010.htm => testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_010-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_020.htm => testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_020-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_021.htm => testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_021-manual.htm
rename : testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_022.htm => testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_022-manual.htm
rename : testing/web-platform/tests/pointerevents/pointerevent_pointermove-on-chorded-mouse-button.html => testing/web-platform/tests/pointerevents/pointerevent_pointermove_on_chorded_mouse_button-manual.html
rename : testing/web-platform/tests/pointerevents/pointerevent_suppress_compat_events_on_click.html => testing/web-platform/tests/pointerevents/pointerevent_suppress_compat_events_on_click-manual.html
rename : testing/web-platform/tests/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse.html => testing/web-platform/tests/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse-manual.html
2016-10-25 18:10:30 +01:00

581 lines
31 KiB
HTML

<!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>