common.js (7206B)
1 "use strict"; 2 3 const HTML5_ELEMENTS = [ 4 'a', 'abbr', 'address', 'area', 'article', 'aside', 5 'audio', 'b', 'base', 'bdi', 'bdo', 'blockquote', 6 'body', 'br', 'button', 'canvas', 'caption', 'cite', 7 'code', 'col', 'colgroup', 'data', 'datalist', 'dd', 8 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 9 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 10 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 11 'h5', 'h6', 'head', 'header', 'hr', 'html', 12 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 13 'label', 'legend', 'li', 'link', 'main', 'map', 14 'mark', 'menu', 'meta', 'meter', 'nav', 'noscript', 15 'object', 'ol', 'optgroup', 'option', 'output', 'p', 16 'param', 'pre', 'progress', 'q', 'rp', 'rt', 17 'ruby', 's', 'samp', 'script', 'section', 'select', 18 'slot', 'small', 'source', 'span', 'strong', 'style', 19 'sub', 'sup', 'summary', 'table', 'tbody', 'td', 20 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 21 'title', 'tr', 'track', 'u', 'ul', 'var', 22 'video', 'wbr' 23 ]; 24 25 // only void (without end tag) HTML5 elements 26 var HTML5_VOID_ELEMENTS = [ 27 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 28 'param', 'source', 'track', 'wbr' 29 ]; 30 31 // https://html.spec.whatwg.org/multipage/multipage/forms.html#form-associated-element 32 var HTML5_FORM_ASSOCIATED_ELEMENTS = [ 'button', 'fieldset', 'input', 33 'object', 'output', 'select', 'textarea' ]; 34 35 // https://html.spec.whatwg.org/#category-label 36 const HTML5_LABELABLE_ELEMENTS = [ 37 'button', 'input', 'meter', 'output', 'progress', 'select', 'textarea' 38 ]; 39 40 const HTML5_SHADOW_ALLOWED_ELEMENTS = [ 41 'article', 'aside', 'blockquote', 'body', 'div', 'footer', 'h1', 'h2', 'h3', 42 'h4', 'h5', 'h6', 'header', 'main', 'nav', 'p', 'section', 'span' 43 ]; 44 45 const HTML5_SHADOW_DISALLOWED_ELEMENTS = 46 HTML5_ELEMENTS.filter(el => !HTML5_SHADOW_ALLOWED_ELEMENTS.includes(el)); 47 48 // These are *deprecated/removed* HTML5 element names. 49 const HTML5_DEPRECATED_ELEMENTS = [ 50 'acronym', 'applet', 'basefont', 'bgsound', 'big', 'blink', 51 'center', 'command', 'content', 'dir', 'font', 'frame', 52 'frameset', 'hgroup', 'image', 'isindex', 'keygen', 'marquee', 53 'menuitem', 'nobr', 'noembed', 'noframes', 'plaintext', 'rb', 54 'rtc', 'shadow', 'spacer', 'strike', 'tt', 'xmp' 55 ]; 56 57 const HTML5_INPUT_TYPES = [ 58 'hidden', 'text', 'search', 'tel', 'url', 'email', 'password', 'date', 59 'time', 'datetime-local', 'number', 'range', 'color', 'checkbox', 'radio', 60 'file', 'submit', 'image', 'reset', 'button' 61 ]; 62 63 function newDocument() { 64 var d = document.implementation.createDocument(); 65 return d; 66 } 67 68 function newHTMLDocument() { 69 var d = document.implementation.createHTMLDocument('Test Document'); 70 return d; 71 } 72 73 function newXHTMLDocument() { 74 var doctype = document.implementation.createDocumentType('html', 75 '-//W3C//DTD XHTML 1.0 Transitional//EN', 76 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'); 77 78 var d = document.implementation.createDocument( 79 'http://www.w3.org/1999/xhtml', 'html', doctype); 80 return d; 81 } 82 83 function newIFrame(context, src) { 84 if (typeof (context) === 'undefined' 85 || typeof (context.iframes) !== 'object') { 86 assert_unreached('Illegal context object in newIFrame'); 87 } 88 89 var iframe = document.createElement('iframe'); 90 91 if (typeof (src) != 'undefined') { 92 iframe.src = src; 93 } 94 document.body.appendChild(iframe); 95 context.iframes.push(iframe); 96 97 assert_true(typeof (iframe.contentWindow) != 'undefined' 98 && typeof (iframe.contentWindow.document) != 'undefined' 99 && iframe.contentWindow.document != document, 100 'Failed to create new rendered document'); 101 return iframe; 102 } 103 104 function newRenderedHTMLDocument(context) { 105 var frame = newIFrame(context); 106 var d = frame.contentWindow.document; 107 return d; 108 } 109 110 function newContext() { 111 return { 112 iframes : [] 113 }; 114 } 115 116 function cleanContext(context) { 117 context.iframes.forEach(function(e) { 118 e.parentNode.removeChild(e); 119 }); 120 } 121 122 // run given test function in context 123 // the context is cleaned up after test completes. 124 function inContext(f) { 125 return function() { 126 var context = newContext(); 127 try { 128 f(context); 129 } finally { 130 cleanContext(context); 131 } 132 }; 133 } 134 135 // new context and iframe are created and url (if supplied) is asigned to 136 // iframe.src 137 // function f is bound to the iframe onload event or executed directly after 138 // iframe creation 139 // the context is passed to function as argument 140 function testInIFrame(url, f, testName, testProps) { 141 if (url) { 142 var t = async_test(testName); 143 t.step(function() { 144 var context = newContext(); 145 var iframe = newIFrame(context, url); 146 iframe.onload = t.step_func(function() { 147 try { 148 f(context); 149 t.done(); 150 } finally { 151 cleanContext(context); 152 } 153 }); 154 }); 155 } else { 156 test(inContext(function(context) { 157 newRenderedHTMLDocument(context); 158 f(context); 159 }), testName); 160 } 161 } 162 163 function assert_nodelist_contents_equal_noorder(actual, expected, message) { 164 assert_equals(actual.length, expected.length, message); 165 var used = []; 166 for ( var i = 0; i < expected.length; i++) { 167 used.push(false); 168 } 169 for (i = 0; i < expected.length; i++) { 170 var found = false; 171 for ( var j = 0; j < actual.length; j++) { 172 if (used[j] == false && expected[i] == actual[j]) { 173 used[j] = true; 174 found = true; 175 break; 176 } 177 } 178 if (!found) { 179 assert_unreached(message + ". Fail reason: element not found: " 180 + expected[i]); 181 } 182 } 183 } 184 185 function isVoidElement(elementName) { 186 return HTML5_VOID_ELEMENTS.indexOf(elementName) >= 0; 187 } 188 189 function checkTemplateContent(d, obj, html, id, nodeName) { 190 191 obj.innerHTML = '<template id="tmpl">' + html + '</template>'; 192 193 var t = d.querySelector('#tmpl'); 194 195 if (id != null) { 196 assert_equals(t.content.childNodes.length, 1, 'Element ' + nodeName 197 + ' should present among template nodes'); 198 assert_equals(t.content.firstChild.id, id, 'Wrong element ID'); 199 } 200 if (nodeName != null) { 201 assert_equals(t.content.firstChild.nodeName, nodeName.toUpperCase(), 202 'Wrong node name'); 203 } 204 } 205 206 function checkBodyTemplateContent(d, html, id, nodeName) { 207 checkTemplateContent(d, d.body, html, id, nodeName); 208 } 209 210 function checkHeadTemplateContent(d, html, id, nodeName) { 211 checkTemplateContent(d, d.head, html, id, nodeName); 212 }