resolve-url.js (26783B)
1 // NOTE: this file needs to be split up rather than expanded. See ../location.sub.html for some 2 // extracted tests. Tracked by https://github.com/web-platform-tests/wpt/issues/4934. 3 4 /* 5 * help: 6 * https://html.spec.whatwg.org/multipage/#the-link-element 7 * https://html.spec.whatwg.org/multipage/#styling 8 * https://html.spec.whatwg.org/multipage/#prepare-a-script 9 * https://html.spec.whatwg.org/multipage/#concept-media-load-algorithm 10 * https://html.spec.whatwg.org/multipage/#track-url 11 * https://html.spec.whatwg.org/multipage/#concept-form-submit 12 * https://html.spec.whatwg.org/multipage/#set-the-frozen-base-url 13 * https://dom.spec.whatwg.org/#dom-node-baseuri 14 * https://html.spec.whatwg.org/multipage/#the-a-element 15 * https://html.spec.whatwg.org/multipage/#dom-worker 16 * https://html.spec.whatwg.org/multipage/#dom-sharedworker 17 * https://html.spec.whatwg.org/multipage/#dom-eventsource 18 * https://html.spec.whatwg.org/multipage/#dom-xmldocument-load 19 * https://html.spec.whatwg.org/multipage/#dom-open 20 * http://url.spec.whatwg.org/#dom-url-search 21 * https://www.w3.org/Bugs/Public/show_bug.cgi?id=24148 22 * https://xhr.spec.whatwg.org/#the-open()-method 23 * https://html.spec.whatwg.org/multipage/#set-up-a-worker-script-settings-object 24 * https://html.spec.whatwg.org/multipage/#dom-workerglobalscope-importscripts 25 * https://html.spec.whatwg.org/multipage/#parse-a-websocket-url's-components 26 * https://html.spec.whatwg.org/multipage/#dom-websocket-url 27 * https://www.w3.org/Bugs/Public/show_bug.cgi?id=23968 28 * http://dev.w3.org/csswg/cssom/#requirements-on-user-agents-implementing-the-xml-stylesheet-processing-instruction 29 * http://url.spec.whatwg.org/#dom-url 30 */ 31 setup({explicit_done:true}); 32 onload = function() { 33 var encoding = '{{GET[encoding]}}'; 34 var input_url = 'resources/resource.py?q=\u00E5&encoding=' + encoding + '&type='; 35 ('html css js worker sharedworker worker_importScripts sharedworker_importScripts worker_worker worker_sharedworker sharedworker_worker '+ 36 'sharedworker_sharedworker eventstream png svg xmlstylesheet_css video webvtt').split(' ').forEach(function(str) { 37 window['input_url_'+str] = input_url + str; 38 }); 39 var blank = 'resources/blank.py?encoding=' + encoding; 40 var stash_put = 'resources/stash.py?q=\u00E5&action=put&id='; 41 var stash_take = 'resources/stash.py?action=take&id='; 42 var expected_obj = { 43 'utf-8':'%C3%A5', 44 'utf-16be':'%C3%A5', 45 'utf-16le':'%C3%A5', 46 'windows-1252':'%E5', 47 'windows-1251':'%26%23229%3B' 48 }; 49 var expected_current = expected_obj[encoding]; 50 var expected_utf8 = expected_obj['utf-8']; 51 52 function msg(expected, got) { 53 return 'expected substring '+expected+' got '+got; 54 } 55 56 function poll_for_stash(test_obj, uuid, expected) { 57 var start = new Date(); 58 var poll = test_obj.step_func(function () { 59 var xhr = new XMLHttpRequest(); 60 xhr.open('GET', stash_take + uuid); 61 xhr.onload = test_obj.step_func(function(e) { 62 if (xhr.response == "") { 63 if (new Date() - start > 10000) { 64 // If we set the status to TIMEOUT here we avoid a race between the 65 // page and the test timing out 66 test_obj.force_timeout(); 67 } 68 test_obj.step_timeout(poll, 200); 69 } else { 70 assert_equals(xhr.response, expected); 71 test_obj.done(); 72 } 73 }); 74 xhr.send(); 75 }) 76 test_obj.step_timeout(poll, 200); 77 } 78 79 // loading html (or actually svg to support <embed>) 80 function test_load_nested_browsing_context(tag, attr, spec_url) { 81 subsetTestByKey('nested-browsing', async_test, function() { 82 var id = 'test_load_nested_browsing_context_'+tag; 83 var elm = document.createElement(tag); 84 elm.setAttribute(attr, input_url_svg); 85 elm.name = id; 86 document.body.appendChild(elm); 87 this.add_cleanup(function() { 88 document.body.removeChild(elm); 89 }); 90 elm.onload = this.step_func_done(function() { 91 assert_equals(window[id].document.documentElement.textContent, expected_current); 92 }); 93 94 }, 'load nested browsing context <'+tag+' '+attr+'>'); 95 } 96 97 spec_url_load_nested_browsing_context = { 98 frame:'https://html.spec.whatwg.org/multipage/#process-the-frame-attributes', 99 iframe:'https://html.spec.whatwg.org/multipage/#process-the-iframe-attributes', 100 object:'https://html.spec.whatwg.org/multipage/#the-object-element', 101 embed:'https://html.spec.whatwg.org/multipage/#the-embed-element-setup-steps' 102 }; 103 104 'frame src, iframe src, object data, embed src'.split(', ').forEach(function(str) { 105 var arr = str.split(' '); 106 test_load_nested_browsing_context(arr[0], arr[1], spec_url_load_nested_browsing_context[arr[0]]); 107 }); 108 109 // loading css with <link> 110 subsetTestByKey('loading', async_test, function() { 111 var elm = document.createElement('link'); 112 elm.href = input_url_css; 113 elm.rel = 'stylesheet'; 114 document.head.appendChild(elm); 115 this.add_cleanup(function() { 116 document.head.removeChild(elm); 117 }); 118 elm.onload = this.step_func_done(function() { 119 var got = elm.sheet.href; 120 assert_true(elm.sheet.href.indexOf(expected_current) > -1, 'sheet.href ' + msg(expected_current, got)); 121 assert_equals(elm.sheet.cssRules[0].style.content, '"'+expected_current+'"', 'sheet.cssRules[0].style.content'); 122 }); 123 }, 'loading css <link>'); 124 125 // loading js 126 subsetTestByKey('loading-css', async_test, function() { 127 var elm = document.createElement('script'); 128 elm.src = input_url_js + '&var=test_load_js_got'; 129 document.head.appendChild(elm); // no cleanup 130 elm.onload = this.step_func_done(function() { 131 assert_equals(window.test_load_js_got, expected_current); 132 }); 133 }, 'loading js <script>'); 134 135 // loading image 136 function test_load_image(tag, attr, spec_url) { 137 subsetTestByKey('loading', async_test, function() { 138 var elm = document.createElement(tag); 139 if (tag == 'input') { 140 elm.type = 'image'; 141 } 142 elm.setAttribute(attr, input_url_png); 143 document.body.appendChild(elm); 144 this.add_cleanup(function() { 145 document.body.removeChild(elm); 146 }); 147 elm.onload = this.step_func_done(function() { 148 var got = elm.offsetWidth; 149 assert_equals(got, query_to_image_width[expected_current], msg(expected_current, image_width_to_query[got])); 150 }); 151 // <video poster> doesn't notify when the image is loaded so we need to poll :-( 152 var interval; 153 var check_video_width = function() { 154 var width = elm.offsetWidth; 155 if (width != 300 && width != 0) { 156 clearInterval(interval); 157 elm.onload(); 158 } 159 } 160 if (tag == 'video') { 161 interval = setInterval(check_video_width, 10); 162 } 163 }, 'loading image <'+tag+' '+attr+'>'); 164 } 165 166 var query_to_image_width = { 167 '%E5':1, 168 '%26%23229%3B':1, 169 '%C3%A5':2, 170 '%3F':16, 171 'unknown query':256, 172 'default intrinsic width':300 173 }; 174 175 var image_width_to_query = {}; 176 (function() { 177 for (var x in query_to_image_width) { 178 image_width_to_query[query_to_image_width[x]] = x; 179 } 180 })(); 181 182 var spec_url_load_image = { 183 img:'https://html.spec.whatwg.org/multipage/#update-the-image-data', 184 embed:'https://html.spec.whatwg.org/multipage/#the-embed-element-setup-steps', 185 object:'https://html.spec.whatwg.org/multipage/#the-object-element', 186 input:'https://html.spec.whatwg.org/multipage/#image-button-state-(type=image)', 187 video:'https://html.spec.whatwg.org/multipage/#poster-frame' 188 }; 189 190 'img src, embed src, object data, input src, video poster'.split(', ').forEach(function(str) { 191 var arr = str.split(' '); 192 test_load_image(arr[0], arr[1], spec_url_load_image[arr[0]]); 193 }); 194 195 // XXX test <img srcset> or its successor 196 197 // loading video 198 function test_load_video(tag, use_source_element) { 199 subsetTestByKey('loading', async_test, function() { 200 var elm = document.createElement(tag); 201 var video_ext = ''; 202 if (elm.canPlayType('video/webm; codecs="vp9,opus"')) { 203 video_ext = 'webm'; 204 } else if (elm.canPlayType('video/mp4; codecs="avc1.42E01E,mp4a.40.2"')) { 205 video_ext = 'mp4'; 206 } 207 assert_not_equals(video_ext, '', 'no supported video format'); 208 var source; 209 if (use_source_element) { 210 source = document.createElement('source'); 211 elm.appendChild(source); 212 } else { 213 source = elm; 214 } 215 source.src = input_url_video + '&ext=' + video_ext; 216 elm.preload = 'auto'; 217 elm.load(); 218 this.add_cleanup(function() { 219 elm.removeAttribute('src'); 220 if (elm.firstChild) { 221 elm.removeChild(elm.firstChild); 222 } 223 elm.load(); 224 }); 225 elm.onloadedmetadata = this.step_func_done(function() { 226 var got = Math.round(elm.duration); 227 assert_equals(got, query_to_video_duration[expected_current], msg(expected_current, video_duration_to_query[got])); 228 }); 229 }, 'loading video <'+tag+'>' + (use_source_element ? '<source>' : '')); 230 } 231 232 var query_to_video_duration = { 233 '%E5':3, 234 '%26%23229%3B':3, 235 '%C3%A5':5, 236 '%3F':30, 237 'unknown query':300, 238 'Infinity':Infinity, 239 'NaN':NaN 240 }; 241 242 var video_duration_to_query = {}; 243 (function() { 244 for (var x in query_to_video_duration) { 245 video_duration_to_query[query_to_video_duration[x]] = x; 246 } 247 })(); 248 249 'video, audio'.split(', ').forEach(function(str) { 250 test_load_video(str); 251 test_load_video(str, true); 252 }); 253 254 // loading webvtt 255 subsetTestByKey('loading', async_test, function() { 256 var video = document.createElement('video'); 257 var track = document.createElement('track'); 258 video.appendChild(track); 259 track.src = input_url_webvtt; 260 track.track.mode = 'showing'; 261 track.onload = this.step_func_done(function() { 262 var got = track.track.cues[0].text; 263 assert_equals(got, expected_current); 264 }); 265 }, 'loading webvtt <track>'); 266 267 // XXX downloading seems hard to automate 268 // <a href download> 269 // <area href download> 270 271 // submit forms 272 function test_submit_form(tag, attr) { 273 subsetTestByKey('submit', async_test, function(){ 274 var elm = document.createElement(tag); 275 elm.setAttribute(attr, input_url_html); 276 var form; 277 var button; 278 if (tag == 'form') { 279 form = elm; 280 button = document.createElement('button'); 281 } else { 282 form = document.createElement('form'); 283 button = elm; 284 } 285 form.method = 'post'; 286 form.appendChild(button); 287 var iframe = document.createElement('iframe'); 288 var id = 'test_submit_form_' + tag; 289 iframe.name = id; 290 form.target = id; 291 button.type = 'submit'; 292 document.body.appendChild(form); 293 document.body.appendChild(iframe); 294 this.add_cleanup(function() { 295 document.body.removeChild(form); 296 document.body.removeChild(iframe); 297 }); 298 button.click(); 299 iframe.onload = this.step_func_done(function() { 300 var got = iframe.contentDocument.body.textContent; 301 if (got == '') { 302 return; 303 } 304 assert_equals(got, expected_current); 305 }); 306 }, 'submit form <'+tag+' '+attr+'>'); 307 } 308 309 'form action, input formaction, button formaction'.split(', ').forEach(function(str) { 310 var arr = str.split(' '); 311 test_submit_form(arr[0], arr[1]); 312 }); 313 314 // <base href> 315 subsetTestByKey('base-href', async_test, function() { 316 var iframe = document.createElement('iframe'); 317 iframe.src = blank; 318 document.body.appendChild(iframe); 319 this.add_cleanup(function() { 320 document.body.removeChild(iframe); 321 }); 322 iframe.onload = this.step_func_done(function() { 323 var doc = iframe.contentDocument; 324 doc.write('<!doctype html><base href="'+input_url+'"><a href></a>'); 325 doc.close(); 326 var got_baseURI = doc.baseURI; 327 assert_true(got_baseURI.indexOf(expected_current) > -1, msg(expected_current, got_baseURI), 'doc.baseURI'); 328 var got_a_href = doc.links[0].href; 329 assert_true(got_a_href.indexOf(expected_current) > -1, msg(expected_current, got_a_href), 'a.href'); 330 }); 331 }, '<base href>'); 332 333 // XXX drag and drop (<a href> or <img src>) seems hard to automate 334 335 // Worker() 336 subsetTestByKey('workers', async_test, function() { 337 var worker = new Worker(input_url_worker); 338 worker.onmessage = this.step_func_done(function(e) { 339 assert_equals(e.data, expected_current); 340 }); 341 }, 'Worker constructor'); 342 343 // SharedWorker() 344 subsetTestByKey('workers', async_test, function() { 345 var worker = new SharedWorker(input_url_sharedworker); 346 worker.port.onmessage = this.step_func_done(function(e) { 347 assert_equals(e.data, expected_current); 348 }); 349 }, 'SharedWorker constructor'); 350 351 // EventSource() 352 subsetTestByKey('eventsource', async_test, function() { 353 var source = new EventSource(input_url_eventstream); 354 this.add_cleanup(function() { 355 source.close(); 356 }); 357 source.onmessage = this.step_func_done(function(e) { 358 assert_equals(e.data, expected_current); 359 }); 360 }, 'EventSource constructor'); 361 362 // EventSource#url 363 subsetTestByKey('eventsource', test, function() { 364 var source = new EventSource(input_url_eventstream); 365 source.close(); 366 var got = source.url; 367 assert_true(source.url.indexOf(expected_current) > -1, msg(expected_current, got)); 368 }, 'EventSource#url'); 369 370 // window.open 371 subsetTestByKey('window-open', async_test, function() { 372 var id = 'test_window_open'; 373 var iframe = document.createElement('iframe'); 374 iframe.name = id; 375 document.body.appendChild(iframe); 376 this.add_cleanup(function() { 377 document.body.removeChild(iframe); 378 }); 379 window.open(input_url_html, id); 380 iframe.onload = this.step_func(function() { 381 var got = iframe.contentDocument.body.textContent; 382 if (got != "") { 383 assert_equals(got, expected_current); 384 this.done(); 385 } 386 }); 387 }, 'window.open()'); 388 389 // a.search, area.search 390 function test_hyperlink_search(tag) { 391 subsetTestByKey('hyperlink-search', test, function() { 392 var elm = document.createElement(tag); 393 var input_arr = input_url_html.split('?'); 394 elm.href = input_arr[0]; 395 elm.search = '?' + input_arr[1]; 396 var got_href = elm.getAttribute('href'); 397 assert_true(got_href.indexOf(expected_utf8) > -1, 'href content attribute ' + msg(expected_utf8, got_href)); 398 var got_search = elm.search; 399 assert_true(got_search.indexOf(expected_utf8) > -1, 'getting .search '+msg(expected_utf8, got_search)); 400 }, '<'+tag+'>.search'); 401 } 402 'a, area'.split(', ').forEach(function(str) { 403 test_hyperlink_search(str); 404 }); 405 406 // history.pushState 407 // history.replaceState 408 function test_history(prop) { 409 subsetTestByKey('history', async_test, function() { 410 var url = input_url_html.replace('resources/', ''); 411 var iframe = document.createElement('iframe'); 412 iframe.src = blank; 413 document.body.appendChild(iframe); 414 this.add_cleanup(function() { 415 document.body.removeChild(iframe); 416 }); 417 iframe.onload = this.step_func_done(function() { 418 // this should resolve against the iframe's URL 419 // "Parse url, relative to the relevant settings object of history." 420 // https://html.spec.whatwg.org/multipage/nav-history-apis.html#shared-history-push%2Freplace-state-steps 421 iframe.contentWindow.history[prop](null, null, url); 422 var got = iframe.contentWindow.location.href; 423 assert_true(got.indexOf(expected_current) > -1, msg(expected_current, got)); 424 assert_not_equals(got.indexOf('/resources/'), -1, 'url was resolved against the test\'s URL'); 425 }); 426 }, 'history.'+prop); 427 } 428 429 'pushState, replaceState'.split(', ').forEach(function(str) { 430 test_history(str); 431 }); 432 433 // SVG 434 var ns = {svg:'http://www.w3.org/2000/svg', xlink:'http://www.w3.org/1999/xlink'}; 435 // a 436 subsetTestByKey('svg', async_test, function() { 437 SVGAElement; // check support 438 var iframe = document.createElement('iframe'); 439 var id = 'test_svg_a'; 440 iframe.name = id; 441 var svg = document.createElementNS(ns.svg, 'svg'); 442 var a = document.createElementNS(ns.svg, 'a'); 443 a.setAttributeNS(ns.xlink, 'xlink:href', input_url_html); 444 a.setAttribute('target', id); 445 var span = document.createElement('span'); 446 a.appendChild(span); 447 svg.appendChild(a); 448 document.body.appendChild(iframe); 449 document.body.appendChild(svg); 450 this.add_cleanup(function() { 451 document.body.removeChild(iframe); 452 document.body.removeChild(svg); 453 }); 454 span.click(); 455 iframe.onload = this.step_func_done(function() { 456 var got = iframe.contentDocument.body.textContent; 457 if (got != '') { 458 assert_equals(got, expected_current); 459 } 460 }); 461 }, 'SVG <a>'); 462 463 // feImage, image, use 464 function test_svg(func, tag) { 465 subsetTestByKey('svg', async_test, function() { 466 var uuid = token(); 467 var id = 'test_svg_'+tag; 468 var svg = document.createElementNS(ns.svg, 'svg'); 469 var parent = func(svg, id); 470 var elm = document.createElementNS(ns.svg, tag); 471 elm.setAttributeNS(ns.xlink, 'xlink:href', stash_put + uuid + '#foo'); 472 parent.appendChild(elm); 473 document.body.appendChild(svg); 474 this.add_cleanup(function() { 475 document.body.removeChild(svg); 476 }); 477 poll_for_stash(this, uuid, expected_current); 478 }, 'SVG <' + tag + '>'); 479 } 480 481 [[function(svg, id) { 482 SVGFEImageElement; // check support 483 var filter = document.createElementNS(ns.svg, 'filter'); 484 filter.setAttribute('id', id); 485 svg.appendChild(filter); 486 var rect = document.createElementNS(ns.svg, 'rect'); 487 rect.setAttribute('filter', 'url(#'+id+')'); 488 svg.appendChild(rect); 489 return filter; 490 }, 'feImage'], 491 [function(svg, id) { SVGImageElement; return svg; }, 'image'], 492 [function(svg, id) { SVGUseElement; return svg; }, 'use']].forEach(function(arr) { 493 test_svg(arr[0], arr[1]); 494 }); 495 496 // UTF-8: 497 // XHR 498 subsetTestByKey('xhr', async_test, function() { 499 var xhr = new XMLHttpRequest(); 500 xhr.open('GET', input_url_html); 501 xhr.onload = this.step_func_done(function() { 502 assert_equals(xhr.response, expected_current); 503 }); 504 xhr.send(); 505 }, 'XMLHttpRequest#open()'); 506 507 // in a worker 508 subsetTestByKey('workers', async_test, function() { 509 var worker = new Worker(input_url_worker_importScripts); 510 worker.onmessage = this.step_func_done(function(e) { 511 assert_equals(e.data, expected_utf8); 512 }); 513 }, 'importScripts() in a dedicated worker'); 514 515 subsetTestByKey('workers', async_test, function() { 516 var worker = new Worker(input_url_worker_worker); 517 worker.onmessage = this.step_func_done(function(e) { 518 assert_equals(e.data, expected_utf8); 519 }); 520 }, 'Worker() in a dedicated worker'); 521 522 subsetTestByKey('workers', async_test, function() { 523 var worker = new SharedWorker(input_url_sharedworker_importScripts); 524 worker.port.onmessage = this.step_func_done(function(e) { 525 assert_equals(e.data, expected_utf8); 526 }); 527 }, 'importScripts() in a shared worker'); 528 529 subsetTestByKey('workers', async_test, function() { 530 var worker = new SharedWorker(input_url_sharedworker_worker); 531 worker.port.onmessage = this.step_func_done(function(e) { 532 assert_equals(e.data, expected_utf8); 533 }); 534 }, 'Worker() in a shared worker'); 535 536 // WebSocket() 537 subsetTestByKey('websocket', async_test, function() { 538 var ws = new WebSocket('ws://{{host}}:{{ports[ws][0]}}/echo-query?\u00E5'); 539 this.add_cleanup(function() { 540 ws.close(); 541 }); 542 ws.onmessage = this.step_func_done(function(e) { 543 assert_equals(e.data, expected_utf8); 544 }); 545 }, 'WebSocket constructor'); 546 547 // WebSocket#url 548 subsetTestByKey('websocket', test, function() { 549 var ws = new WebSocket('ws://{{host}}:{{ports[ws][0]}}/echo-query?\u00E5'); 550 ws.close(); 551 var got = ws.url; 552 assert_true(ws.url.indexOf(expected_utf8) > -1, msg(expected_utf8, got)); 553 }, 'WebSocket#url'); 554 555 // CSS 556 function test_css(tmpl, expected_cssom, encoding, use_style_element) { 557 var desc = ['CSS', (use_style_element ? '<style>' : '<link> (' + encoding + ')'), tmpl].join(' '); 558 subsetTestByKey('css', async_test, function(){ 559 css_is_supported(tmpl, expected_cssom, this); 560 var uuid = token(); 561 var id = 'test_css_' + uuid; 562 var url = 'url(stash.py?q=%s&action=put&id=' + uuid + ')'; 563 tmpl = tmpl.replace(/<id>/g, id).replace(/<url>/g, url); 564 var link; 565 if (use_style_element) { 566 link = document.createElement('style'); 567 link.textContent = tmpl.replace(/%s/g, '\u00E5').replace(/stash\.py/g, 'resources/stash.py'); 568 } else { 569 link = document.createElement('link'); 570 link.rel = 'stylesheet'; 571 link.href = 'resources/css-tmpl.py?encoding='+encoding+'&tmpl='+encodeURIComponent(tmpl); 572 } 573 var div = document.createElement('div'); 574 div.id = id; 575 div.textContent='x'; 576 document.head.appendChild(link); 577 document.body.appendChild(div); 578 this.add_cleanup(function() { 579 document.head.removeChild(link); 580 document.body.removeChild(div); 581 }); 582 poll_for_stash(this, uuid, expected_utf8); 583 }, desc); 584 } 585 586 // fail fast if the input doesn't parse into the expected cssom 587 function css_is_supported(tmpl, expected_cssom, test_obj) { 588 if (expected_cssom === null) { 589 return; 590 } 591 var style = document.createElement('style'); 592 style.textContent = tmpl.replace(/<id>/g, 'x').replace(/<url>/g, 'url(data:,)'); 593 document.head.appendChild(style); 594 test_obj.add_cleanup(function() { 595 document.head.removeChild(style); 596 }); 597 assert_equals(style.sheet.cssRules.length, expected_cssom.length, 'number of style rules'); 598 for (var i = 0; i < expected_cssom.length; ++i) { 599 if (expected_cssom[i] === null) { 600 continue; 601 } 602 assert_equals(style.sheet.cssRules[i].style.length, expected_cssom[i], 'number of declarations in style rule #'+i); 603 } 604 } 605 606 [['#<id> { background-image:<url> }', [1] ], 607 ['#<id> { border-image-source:<url> }', [1] ], 608 ['#<id>::before { content:<url> }', [1] ], 609 ['@font-face { font-family:<id>; src:<url> } #<id> { font-family:<id> }', [null, 1] ], 610 ['#<id> { display:list-item; list-style-image:<url> }', [2] ], 611 ['@import <url>;', null ], 612 // XXX maybe cursor isn't suitable for automation here if browsers delay fetching it 613 ['#<id> { cursor:<url>, pointer }', [1] ]].forEach(function(arr) { 614 var input = arr[0]; 615 var expected_cssom = arr[1]; 616 var other_encoding = encoding == 'utf-8' ? 'windows-1252' : 'utf-8'; 617 test_css(input, expected_cssom, encoding); 618 test_css(input, expected_cssom, other_encoding); 619 test_css(input, expected_cssom, null, true); 620 }); 621 622 // XXX maybe test if they become relevant: 623 // binding (obsolete?) 624 // aural: cue-after, cue-before, play-during (not implemented?) 625 // hyphenate-resource (not implemented?) 626 // image() (not implemented?) 627 628 // <?xml-stylesheet?> 629 subsetTestByKey('xml', async_test, function() { 630 var iframe = document.createElement('iframe'); 631 iframe.src = input_url_xmlstylesheet_css; 632 document.body.appendChild(iframe); 633 this.add_cleanup(function() { 634 document.body.removeChild(iframe); 635 }); 636 iframe.onload = this.step_func_done(function() { 637 assert_equals(iframe.contentDocument.firstChild.sheet.cssRules[0].style.content, '"' + expected_utf8 + '"'); 638 }); 639 }, '<?xml-stylesheet?> (CSS)'); 640 641 // new URL() 642 subsetTestByKey('url', test, function() { 643 var url = new URL('http://example.org/'+input_url); 644 var expected = expected_utf8; 645 assert_true(url.href.indexOf(expected) > -1, 'url.href '+msg(expected, url.href)); 646 assert_true(url.search.indexOf(expected) > -1, 'url.search '+msg(expected, url.search)); 647 }, 'URL constructor, url'); 648 649 subsetTestByKey('url', test, function() { 650 var url = new URL('', 'http://example.org/'+input_url); 651 var expected = expected_utf8; 652 assert_true(url.href.indexOf(expected) > -1, 'url.href '+msg(expected, url.href)); 653 assert_true(url.search.indexOf(expected) > -1, 'url.search '+msg(expected, url.search)); 654 }, 'URL constructor, base'); 655 656 // Test different schemes 657 function test_scheme(url, utf8) { 658 subsetTestByKey('scheme', test, function() { 659 var a = document.createElement('a'); 660 a.setAttribute('href', url); 661 var got = a.href; 662 var expected = utf8 ? expected_utf8 : expected_current; 663 assert_true(got.indexOf(expected) != -1, msg(expected, got)); 664 }, 'Scheme ' + url.split(':')[0] + ' (getting <a>.href)'); 665 } 666 667 var test_scheme_urls = ['ftp://example.invalid/?x=\u00E5', 668 'file:///?x=\u00E5', 669 'http://example.invalid/?x=\u00E5', 670 'https://example.invalid/?x=\u00E5', 671 ]; 672 673 var test_scheme_urls_utf8 = ['ws://example.invalid/?x=\u00E5', 674 'wss://example.invalid/?x=\u00E5', 675 'gopher://example.invalid/?x=\u00E5', 676 'mailto:example@invalid?x=\u00E5', 677 'data:text/plain;charset='+encoding+',?x=\u00E5', 678 'javascript:"?x=\u00E5"', 679 'ftps://example.invalid/?x=\u00E5', 680 'httpbogus://example.invalid/?x=\u00E5', 681 'bitcoin:foo?x=\u00E5', 682 'geo:foo?x=\u00E5', 683 'im:foo?x=\u00E5', 684 'irc:foo?x=\u00E5', 685 'ircs:foo?x=\u00E5', 686 'magnet:foo?x=\u00E5', 687 'mms:foo?x=\u00E5', 688 'news:foo?x=\u00E5', 689 'nntp:foo?x=\u00E5', 690 'sip:foo?x=\u00E5', 691 'sms:foo?x=\u00E5', 692 'smsto:foo?x=\u00E5', 693 'ssh:foo?x=\u00E5', 694 'tel:foo?x=\u00E5', 695 'urn:foo?x=\u00E5', 696 'webcal:foo?x=\u00E5', 697 'wtai:foo?x=\u00E5', 698 'xmpp:foo?x=\u00E5', 699 'web+http:foo?x=\u00E5', 700 ]; 701 702 test_scheme_urls.forEach(function(url) { 703 test_scheme(url); 704 }); 705 706 test_scheme_urls_utf8.forEach(function(url) { 707 test_scheme(url, true); 708 }); 709 710 done(); 711 };