| <!DOCTYPE html> |
| <title>Custom Elements: CustomElementsRegistry.whenDefined</title> |
| <script src="../../../resources/testharness.js"></script> |
| <script src="../../../resources/testharnessreport.js"></script> |
| <script src="../resources/custom-elements-helpers.js"></script> |
| <body> |
| <div id="log"></div> |
| <script> |
| 'use strict'; |
| (() => { |
| // https://html.spec.whatwg.org/multipage/scripting.html#dom-customelementsregistry-whendefined |
| // Use window from iframe to isolate the test. |
| function setup() { |
| const iframe = document.createElement('iframe'); |
| document.body.appendChild(iframe); |
| const testWindow = iframe.contentWindow; |
| const customElements = testWindow.customElements; |
| if (!customElements) |
| return Promise.reject('This test requires window.customElements'); |
| if (!('whenDefined' in customElements)) |
| return Promise.reject('This test requires window.customElements.whenDefined'); |
| return Promise.resolve(customElements); |
| } |
| |
| const kNameToBeDefined = 'x-foo'; |
| const kNameNotDefined = 'x-bar'; |
| let beforeDefined = false; |
| let notDefined = true; |
| let afterDefined = false; |
| promise_test(() => setup() |
| .then(customElements => { |
| // 4. If map does not contain an entry with key name, create an entry in |
| // map with key name and whose value is a new promise. |
| const promiseBeforeDefined = customElements.whenDefined(kNameToBeDefined); |
| promiseBeforeDefined.then(() => beforeDefined = true); |
| // 5. Let promise be the value of the entry in map with key name. |
| // 6. Return promise |
| assert_equals(promiseBeforeDefined, |
| customElements.whenDefined(kNameToBeDefined), |
| 'There is only one promise defined before.'); |
| const promiseNotDefined = customElements.whenDefined(kNameNotDefined); |
| promiseNotDefined.then(() => notDefined = false); |
| assert_not_equals(promiseBeforeDefined, promiseNotDefined, |
| 'whenDefined() returns different promises for different names.'); |
| customElements.define(kNameToBeDefined, class {}); |
| // 3. If this CustomElementsRegistry contains an entry with name name, |
| // then return a new promise resolved with undefined and abort these |
| // steps. |
| const promiseAfterDefined = customElements.whenDefined(kNameToBeDefined); |
| promiseAfterDefined.then(() => afterDefined = true); |
| assert_not_equals(promiseBeforeDefined, promiseAfterDefined, |
| 'When name is defined, we should have a new promise.'); |
| assert_not_equals(promiseAfterDefined, |
| customElements.whenDefined(kNameToBeDefined), |
| 'Once name is defined, whenDefined() always returns a new promise.'); |
| return customElements; |
| }).then(customElements => { |
| assert_true(beforeDefined, 'promise before defined should be resolved.'); |
| assert_true(afterDefined, 'promise after defined should be resolved.'); |
| assert_true(notDefined, 'promise for not defined name should not be resolved.'); |
| }).catch(reason => { throw reason })); |
| |
| // Calling whenDefined() with invalid names should throw "SyntaxError"DOMException |
| // https://html.spec.whatwg.org/multipage/scripting.html#valid-custom-element-name |
| let invalid_names = [ |
| 'annotation-xml', |
| 'color-profile', |
| 'font-face', |
| 'font-face-src', |
| 'font-face-uri', |
| 'font-face-format', |
| 'font-face-name', |
| 'missing-glyph', |
| 'div', 'p', |
| 'nothtmlbutnohyphen', |
| '-not-initial-a-z', '0not-initial-a-z', 'Not-initial-a-z', |
| 'intermediate-UPPERCASE-letters', |
| 'bad-\u00b6', 'bad-\u00b8', 'bad-\u00bf', 'bad-\u00d7', 'bad-\u00f7', |
| 'bad-\u037e', 'bad-\u037e', 'bad-\u2000', 'bad-\u200e', 'bad-\u203e', |
| 'bad-\u2041', 'bad-\u206f', 'bad-\u2190', 'bad-\u2bff', 'bad-\u2ff0', |
| 'bad-\u3000', 'bad-\ud800', 'bad-\uf8ff', 'bad-\ufdd0', 'bad-\ufdef', |
| 'bad-\ufffe', 'bad-\uffff', 'bad-' + String.fromCodePoint(0xf0000) |
| ]; |
| |
| invalid_names.forEach((name) => { |
| promise_test((t) => { |
| return create_window_in_test(t) |
| .then((w) => { |
| return promise_rejects_with_dom_exception_syntax_error(w, t, w.customElements.whenDefined(name)); |
| }); |
| }, 'whenDefined() called with invalid name ' + name + ' should throw "SyntaxError"DOMException'); |
| }); |
| |
| function promise_rejects_with_dom_exception_syntax_error(global_context, test, promise, description) { |
| return promise.then(test.unreached_func("Should have rejected: " + description)).catch(function(e) { |
| assert_throws_dom_exception(global_context, 'SYNTAX_ERR', function () { throw e; }) |
| }); |
| } |
| })(); |
| </script> |
| </body> |