window-location-and-location-href-cross-realm-set.html (6213B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>Cross-realm [[Set]] to window.location and location.href throws an error of correct realm</title> 4 <link rel="help" href="https://html.spec.whatwg.org/multipage/#window"> 5 <link rel="help" href="https://webidl.spec.whatwg.org/#Unforgeable"> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="/common/get-host-info.sub.js"></script> 9 <body> 10 <script> 11 const URL_SAME_ORIGIN = get_host_info().ORIGINAL_HOST; 12 const URL_CROSS_ORIGIN = get_host_info().HTTP_REMOTE_ORIGIN; 13 const URL_VALID = "#foo"; 14 const URL_INVALID = "http://#"; 15 16 const { get: locationGet, set: locationSet } = Object.getOwnPropertyDescriptor(window, "location"); 17 const { get: hrefGet, set: hrefSet } = Object.getOwnPropertyDescriptor(location, "href"); 18 19 20 promise_test(async t => { 21 const sameOriginWindow = await makeWindow(t, URL_SAME_ORIGIN); 22 assert_throws_js(sameOriginWindow.TypeError, () => { Object.create(sameOriginWindow).location; }); 23 assert_throws_js(sameOriginWindow.TypeError, () => { Reflect.get(sameOriginWindow, "location", {}); }); 24 assert_throws_js(TypeError, () => { locationGet.call({}); }); 25 }, "Same-origin window.location getter throws TypeError in holder's realm on invalid |this| value"); 26 27 promise_test(async t => { 28 const sameOriginWindow = await makeWindow(t, URL_SAME_ORIGIN); 29 assert_throws_js(sameOriginWindow.TypeError, () => { Object.create(sameOriginWindow.location).href; }); 30 assert_throws_js(sameOriginWindow.TypeError, () => { Reflect.get(sameOriginWindow.location, "href", {}); }); 31 assert_throws_js(TypeError, () => { hrefGet(); }); 32 }, "Same-origin location.href getter throws TypeError in holder's realm on invalid |this| value"); 33 34 promise_test(async t => { 35 const crossOriginWindow = await makeWindow(t, URL_CROSS_ORIGIN); 36 assert_throws_dom("SECURITY_ERR", () => { crossOriginWindow.location.href; }); 37 assert_throws_dom("SECURITY_ERR", () => { hrefGet.call(crossOriginWindow.location); }); 38 assert_equals(Object.getOwnPropertyDescriptor(crossOriginWindow.location, "href").get, undefined); 39 }, "Cross-origin location.href getter throws SecurityError in lexical realm"); 40 41 42 promise_test(async t => { 43 const sameOriginWindow = await makeWindow(t, URL_SAME_ORIGIN); 44 assert_throws_js(sameOriginWindow.TypeError, () => { Object.create(sameOriginWindow).location = URL_VALID; }); 45 assert_throws_js(sameOriginWindow.TypeError, () => { Reflect.set(sameOriginWindow, "location", URL_VALID, {}); }); 46 assert_throws_js(TypeError, () => { locationSet.call(() => {}, URL_VALID); }); 47 }, "Same-origin window.location setter throws TypeError in holder's realm on invalid |this| value"); 48 49 promise_test(async t => { 50 const sameOriginWindow = await makeWindow(t, URL_SAME_ORIGIN); 51 assert_throws_js(sameOriginWindow.TypeError, () => { Object.create(sameOriginWindow.location).href = URL_VALID; }); 52 assert_throws_js(sameOriginWindow.TypeError, () => { Reflect.set(sameOriginWindow.location, "href", URL_VALID, {}); }); 53 assert_throws_js(TypeError, () => { hrefSet.call(undefined, URL_VALID); }); 54 }, "Same-origin location.href setter throws TypeError in holder's realm on invalid |this| value"); 55 56 promise_test(async t => { 57 const crossOriginWindow = await makeWindow(t, URL_CROSS_ORIGIN); 58 assert_throws_js(TypeError, () => { Object.create(crossOriginWindow).location = URL_VALID; }); 59 assert_throws_js(TypeError, () => { Reflect.set(crossOriginWindow, "location", URL_VALID, {}); }); 60 assert_throws_js(TypeError, () => { locationSet.call([], URL_VALID); }); 61 }, "Cross-origin window.location setter throws TypeError in lexical realm on invalid |this| value"); 62 63 promise_test(async t => { 64 const crossOriginWindow = await makeWindow(t, URL_CROSS_ORIGIN); 65 assert_throws_js(TypeError, () => { Object.create(crossOriginWindow.location).href = URL_VALID; }); 66 assert_throws_js(TypeError, () => { Reflect.set(crossOriginWindow.location, "href", URL_VALID, {}); }); 67 assert_throws_js(TypeError, () => { hrefSet.call(null, URL_VALID); }); 68 }, "Cross-origin location.href setter throws TypeError in lexical realm on invalid |this| value"); 69 70 71 promise_test(async t => { 72 const sameOriginWindow = await makeWindow(t, URL_SAME_ORIGIN); 73 assert_throws_js(sameOriginWindow.TypeError, () => { sameOriginWindow.location = Symbol(); }); 74 75 // The error originates in sameOriginWindow.location.href setter, hence it's not in realm of locationSet. 76 assert_throws_js(sameOriginWindow.TypeError, () => { locationSet.call(sameOriginWindow, Symbol()); }); 77 }, "Same-origin window.location` setter throws TypeError in holder's realm on non-coercible URL argument"); 78 79 promise_test(async t => { 80 const sameOriginWindow = await makeWindow(t, URL_SAME_ORIGIN); 81 assert_throws_js(sameOriginWindow.TypeError, () => { sameOriginWindow.location.href = Symbol(); }); 82 assert_throws_js(TypeError, () => { hrefSet.call(sameOriginWindow.location, Symbol()); }); 83 }, "Same-origin location.href setter throws TypeError in holder's realm on non-coercible URL argument"); 84 85 promise_test(async t => { 86 const crossOriginWindow = await makeWindow(t, URL_CROSS_ORIGIN); 87 assert_throws_js(TypeError, () => { crossOriginWindow.location = Symbol(); }); 88 assert_throws_js(TypeError, () => { locationSet.call(crossOriginWindow, Symbol()); }); 89 }, "Cross-origin window.location setter throws TypeError in lexical realm on non-coercible URL argument"); 90 91 promise_test(async t => { 92 const crossOriginWindow = await makeWindow(t, URL_CROSS_ORIGIN); 93 assert_throws_js(TypeError, () => { crossOriginWindow.location.href = Symbol(); }); 94 assert_throws_js(TypeError, () => { hrefSet.call(crossOriginWindow.location, Symbol()); }); 95 }, "Cross-origin location.href setter throws TypeError in lexical realm on non-coercible URL argument"); 96 97 function makeWindow(t, src) { 98 return new Promise(resolve => { 99 const iframe = document.createElement("iframe"); 100 t.add_cleanup(() => { iframe.remove(); }); 101 iframe.onload = () => { resolve(iframe.contentWindow); }; 102 iframe.src = src; 103 document.body.append(iframe); 104 }); 105 } 106 </script>