| <!DOCTYPE html> |
| <html is="my-html"> |
| <head> |
| <meta charset="utf-8"> |
| <meta name="help" content="https://html.spec.whatwg.org/multipage/custom-elements.html#element-definition"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| </head> |
| <body is="my-body"> |
| <div id="container"></div> |
| <script> |
| class MyA extends HTMLAnchorElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyAbbr extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyAddress extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyArea extends HTMLAreaElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyArticle extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyAside extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyAudio extends HTMLAudioElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyB extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyBase extends HTMLBaseElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyBdi extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyBdo extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyBlockquote extends HTMLQuoteElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyBody extends HTMLBodyElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyBr extends HTMLBRElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyButton extends HTMLButtonElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyCanvas extends HTMLCanvasElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyCaption extends HTMLTableCaptionElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyCite extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyCode extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyCol extends HTMLTableColElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyColgroup extends HTMLTableColElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyData extends HTMLDataElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyDd extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyDel extends HTMLModElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyDetails extends HTMLDetailsElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyDfn extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyDiv extends HTMLDivElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyDl extends HTMLDListElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyDt extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyEm extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyEmbed extends HTMLEmbedElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyFieldset extends HTMLFieldSetElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyFigcaption extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyFigure extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyFooter extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyForm extends HTMLFormElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyH1 extends HTMLHeadingElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyH2 extends HTMLHeadingElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyH3 extends HTMLHeadingElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyH4 extends HTMLHeadingElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyH5 extends HTMLHeadingElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyH6 extends HTMLHeadingElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyHeader extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyHgroup extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyHr extends HTMLHRElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyHtml extends HTMLHtmlElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyI extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyIframe extends HTMLIFrameElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyImg extends HTMLImageElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyInput extends HTMLInputElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyIns extends HTMLModElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyKbd extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyLabel extends HTMLLabelElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyLegend extends HTMLLegendElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyLi extends HTMLLIElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyLink extends HTMLLinkElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyMain extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyMap extends HTMLMapElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyMark extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyMenu extends HTMLMenuElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyMeta extends HTMLMetaElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyMeter extends HTMLMeterElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyNav extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyNoscript extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyObject extends HTMLObjectElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyOl extends HTMLOListElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyOptgroup extends HTMLOptGroupElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyOption extends HTMLOptionElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyOutput extends HTMLOutputElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyP extends HTMLParagraphElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyParam extends HTMLParamElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyPicture extends HTMLPictureElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyPre extends HTMLPreElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyProgress extends HTMLProgressElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyQ extends HTMLQuoteElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyRp extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyRt extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyRuby extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyS extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MySamp extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyScript extends HTMLScriptElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MySection extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MySelect extends HTMLSelectElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MySmall extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MySource extends HTMLSourceElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MySpan extends HTMLSpanElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyStrong extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyStyle extends HTMLStyleElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MySub extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MySummary extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MySup extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyTable extends HTMLTableElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyTbody extends HTMLTableSectionElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyTd extends HTMLTableCellElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyTemplate extends HTMLTemplateElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyTextarea extends HTMLTextAreaElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyTfoot extends HTMLTableSectionElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyTh extends HTMLTableCellElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyThead extends HTMLTableSectionElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyTime extends HTMLTimeElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyTitle extends HTMLTitleElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyTr extends HTMLTableRowElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyTrack extends HTMLTrackElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyU extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyUl extends HTMLUListElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyVar extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyVideo extends HTMLVideoElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| class MyWbr extends HTMLElement { |
| constructor() { |
| super(); |
| } |
| } |
| |
| let testData = [ |
| {tag: 'a', klass: MyA}, |
| {tag: 'abbr', klass: MyAbbr}, |
| {tag: 'address', klass: MyAddress}, |
| {tag: 'area', klass: MyArea}, |
| {tag: 'article', klass: MyArticle}, |
| {tag: 'aside', klass: MyAside}, |
| {tag: 'audio', klass: MyAudio}, |
| {tag: 'b', klass: MyB}, |
| {tag: 'base', klass: MyBase}, |
| {tag: 'bdi', klass: MyBdi}, |
| {tag: 'bdo', klass: MyBdo}, |
| {tag: 'blockquote', klass: MyBlockquote}, |
| {tag: 'body', klass: MyBody, parsing: 'document'}, |
| {tag: 'br', klass: MyBr}, |
| {tag: 'button', klass: MyButton}, |
| {tag: 'canvas', klass: MyCanvas}, |
| {tag: 'caption', klass: MyCaption, parsing: 'table'}, |
| {tag: 'cite', klass: MyCite}, |
| {tag: 'code', klass: MyCode}, |
| {tag: 'col', klass: MyCol, parsing: 'table'}, |
| {tag: 'colgroup', klass: MyColgroup, parsing: 'table'}, |
| {tag: 'data', klass: MyData}, |
| {tag: 'dd', klass: MyDd}, |
| {tag: 'del', klass: MyDel}, |
| {tag: 'details', klass: MyDetails}, |
| {tag: 'dfn', klass: MyDfn}, |
| {tag: 'div', klass: MyDiv}, |
| {tag: 'dl', klass: MyDl}, |
| {tag: 'dt', klass: MyDt}, |
| {tag: 'em', klass: MyEm}, |
| {tag: 'embed', klass: MyEmbed}, |
| {tag: 'fieldset', klass: MyFieldset}, |
| {tag: 'figcaption', klass: MyFigcaption}, |
| {tag: 'figure', klass: MyFigure}, |
| {tag: 'footer', klass: MyFooter}, |
| {tag: 'form', klass: MyForm}, |
| {tag: 'h1', klass: MyH1}, |
| {tag: 'h2', klass: MyH2}, |
| {tag: 'h3', klass: MyH3}, |
| {tag: 'h4', klass: MyH4}, |
| {tag: 'h5', klass: MyH5}, |
| {tag: 'h6', klass: MyH6}, |
| {tag: 'header', klass: MyHeader}, |
| {tag: 'hgroup', klass: MyHgroup}, |
| {tag: 'hr', klass: MyHr}, |
| {tag: 'html', klass: MyHtml, parsing: 'document'}, |
| {tag: 'i', klass: MyI}, |
| {tag: 'iframe', klass: MyIframe}, |
| {tag: 'img', klass: MyImg}, |
| {tag: 'input', klass: MyInput}, |
| {tag: 'ins', klass: MyIns}, |
| {tag: 'kbd', klass: MyKbd}, |
| {tag: 'label', klass: MyLabel}, |
| {tag: 'legend', klass: MyLegend}, |
| {tag: 'li', klass: MyLi}, |
| {tag: 'link', klass: MyLink}, |
| {tag: 'main', klass: MyMain}, |
| {tag: 'map', klass: MyMap}, |
| {tag: 'mark', klass: MyMark}, |
| {tag: 'menu', klass: MyMenu}, |
| {tag: 'meta', klass: MyMeta}, |
| {tag: 'meter', klass: MyMeter}, |
| {tag: 'nav', klass: MyNav}, |
| {tag: 'noscript', klass: MyNoscript}, |
| {tag: 'object', klass: MyObject}, |
| {tag: 'ol', klass: MyOl}, |
| {tag: 'optgroup', klass: MyOptgroup}, |
| {tag: 'option', klass: MyOption}, |
| {tag: 'output', klass: MyOutput}, |
| {tag: 'p', klass: MyP}, |
| {tag: 'param', klass: MyParam}, |
| {tag: 'picture', klass: MyPicture}, |
| {tag: 'pre', klass: MyPre}, |
| {tag: 'progress', klass: MyProgress}, |
| {tag: 'q', klass: MyQ}, |
| {tag: 'rp', klass: MyRp}, |
| {tag: 'rt', klass: MyRt}, |
| {tag: 'ruby', klass: MyRuby}, |
| {tag: 's', klass: MyS}, |
| {tag: 'samp', klass: MySamp}, |
| {tag: 'script', klass: MyScript}, |
| {tag: 'section', klass: MySection}, |
| {tag: 'select', klass: MySelect}, |
| {tag: 'small', klass: MySmall}, |
| {tag: 'source', klass: MySource}, |
| {tag: 'span', klass: MySpan}, |
| {tag: 'strong', klass: MyStrong}, |
| {tag: 'style', klass: MyStyle}, |
| {tag: 'sub', klass: MySub}, |
| {tag: 'summary', klass: MySummary}, |
| {tag: 'sup', klass: MySup}, |
| {tag: 'table', klass: MyTable}, |
| {tag: 'tbody', klass: MyTbody, parsing: 'table'}, |
| {tag: 'td', klass: MyTd, parsing: 'table'}, |
| {tag: 'template', klass: MyTemplate}, |
| {tag: 'textarea', klass: MyTextarea}, |
| {tag: 'tfoot', klass: MyTfoot, parsing: 'table'}, |
| {tag: 'th', klass: MyTh, parsing: 'table'}, |
| {tag: 'thead', klass: MyThead, parsing: 'table'}, |
| {tag: 'time', klass: MyTime}, |
| {tag: 'title', klass: MyTitle}, |
| {tag: 'tr', klass: MyTr, parsing: 'table'}, |
| {tag: 'track', klass: MyTrack}, |
| {tag: 'u', klass: MyU}, |
| {tag: 'ul', klass: MyUl}, |
| {tag: 'var', klass: MyVar}, |
| {tag: 'video', klass: MyVideo}, |
| {tag: 'wbr', klass: MyWbr}, |
| ]; |
| // HTMLDataListElement isn't implemented by all major browsers yet. |
| if (window.HTMLDataListElement) { |
| testData.push({tag: 'datalist', klass: class extends HTMLDataListElement { |
| constructor() { |
| super(); |
| } |
| }}); |
| } |
| // HTMLDialogElement isn't implemented by all major browsers yet. |
| if (window.HTMLDialogElement) { |
| testData.push({tag: 'dialog', klass: class MyDialog extends HTMLDialogElement { |
| constructor() { |
| super(); |
| } |
| }}); |
| } |
| // HTMLSlotElement isn't implemented by all major browsers yet. |
| if (window.HTMLSlotElement) { |
| testData.push({tag: 'slot', klass: class extends HTMLSlotElement { |
| constructor() { |
| super(); |
| } |
| }}); |
| } |
| |
| for (const t of testData) { |
| test(() => { |
| let name = 'my-' + t.tag; |
| customElements.define(name, t.klass, { extends: t.tag }); |
| |
| test(() => { |
| let customized = new t.klass(); |
| assert_equals(customized.constructor, t.klass); |
| // cloneNode() won't create a customized built-in element due to no |
| // 'is' attribute. https://github.com/whatwg/html/issues/3402 |
| assert_not_equals(customized.cloneNode().constructor, t.klass, |
| 'Cloning a customized built-in element should NOT succeed.'); |
| }, `${t.tag}: Operator 'new' should instantiate a customized built-in element`); |
| |
| test(() => { |
| let customized = document.createElement(t.tag, { is: name }); |
| assert_equals(customized.constructor, t.klass); |
| assert_equals(customized.cloneNode().constructor, t.klass, |
| 'Cloning a customized built-in element should succeed.'); |
| }, `${t.tag}: document.createElement() should instantiate a customized built-in element`); |
| |
| if (t.parsing == 'document') { |
| let test = async_test(`${t.tag}: document parser should instantiate a customized built-in element`); |
| window.addEventListener('load', test.step_func_done(() => { |
| let customized = document.querySelector(t.tag); |
| assert_equals(customized.constructor, t.klass); |
| assert_equals(customized.cloneNode().constructor, t.klass, |
| 'Cloning a customized built-in element should succeed.'); |
| })); |
| return; |
| } |
| test(() => { |
| let container = document.getElementById('container'); |
| if (t.parsing == 'table') { |
| container.innerHTML = `<table><${t.tag} is="${name}" id="${name}">`; |
| } else { |
| container.innerHTML = `<${t.tag} is="${name}" id="${name}">`; |
| } |
| let customized = document.getElementById(name); |
| assert_equals(customized.constructor, t.klass); |
| assert_equals(customized.cloneNode().constructor, t.klass, |
| 'Cloning a customized built-in element should succeed.'); |
| }, `${t.tag}: innerHTML should instantiate a customized built-in element`); |
| |
| }, `${t.tag}: Define a customized built-in element`); |
| } |
| </script> |
| </body> |
| </html> |