| <!DOCTYPE html> |
| <meta charset="utf-8"> |
| <title>Cross-realm [[Set]] to window.location and location.href throws an error of correct realm</title> |
| <link rel="help" href="https://html.spec.whatwg.org/multipage/#window"> |
| <link rel="help" href="https://webidl.spec.whatwg.org/#Unforgeable"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="/common/get-host-info.sub.js"></script> |
| <body> |
| <script> |
| const URL_SAME_ORIGIN = get_host_info().ORIGINAL_HOST; |
| const URL_CROSS_ORIGIN = get_host_info().HTTP_REMOTE_ORIGIN; |
| const URL_VALID = "#foo"; |
| const URL_INVALID = "http://#"; |
| |
| const { get: locationGet, set: locationSet } = Object.getOwnPropertyDescriptor(window, "location"); |
| const { get: hrefGet, set: hrefSet } = Object.getOwnPropertyDescriptor(location, "href"); |
| |
| |
| promise_test(async t => { |
| const sameOriginWindow = await makeWindow(t, URL_SAME_ORIGIN); |
| assert_throws_js(sameOriginWindow.TypeError, () => { Object.create(sameOriginWindow).location; }); |
| assert_throws_js(sameOriginWindow.TypeError, () => { Reflect.get(sameOriginWindow, "location", {}); }); |
| assert_throws_js(TypeError, () => { locationGet.call({}); }); |
| }, "Same-origin window.location getter throws TypeError in holder's realm on invalid |this| value"); |
| |
| promise_test(async t => { |
| const sameOriginWindow = await makeWindow(t, URL_SAME_ORIGIN); |
| assert_throws_js(sameOriginWindow.TypeError, () => { Object.create(sameOriginWindow.location).href; }); |
| assert_throws_js(sameOriginWindow.TypeError, () => { Reflect.get(sameOriginWindow.location, "href", {}); }); |
| assert_throws_js(TypeError, () => { hrefGet(); }); |
| }, "Same-origin location.href getter throws TypeError in holder's realm on invalid |this| value"); |
| |
| promise_test(async t => { |
| const crossOriginWindow = await makeWindow(t, URL_CROSS_ORIGIN); |
| assert_throws_dom("SECURITY_ERR", () => { crossOriginWindow.location.href; }); |
| assert_throws_dom("SECURITY_ERR", () => { hrefGet.call(crossOriginWindow.location); }); |
| assert_equals(Object.getOwnPropertyDescriptor(crossOriginWindow.location, "href").get, undefined); |
| }, "Cross-origin location.href getter throws SecurityError in lexical realm"); |
| |
| |
| promise_test(async t => { |
| const sameOriginWindow = await makeWindow(t, URL_SAME_ORIGIN); |
| assert_throws_js(sameOriginWindow.TypeError, () => { Object.create(sameOriginWindow).location = URL_VALID; }); |
| assert_throws_js(sameOriginWindow.TypeError, () => { Reflect.set(sameOriginWindow, "location", URL_VALID, {}); }); |
| assert_throws_js(TypeError, () => { locationSet.call(() => {}, URL_VALID); }); |
| }, "Same-origin window.location setter throws TypeError in holder's realm on invalid |this| value"); |
| |
| promise_test(async t => { |
| const sameOriginWindow = await makeWindow(t, URL_SAME_ORIGIN); |
| assert_throws_js(sameOriginWindow.TypeError, () => { Object.create(sameOriginWindow.location).href = URL_VALID; }); |
| assert_throws_js(sameOriginWindow.TypeError, () => { Reflect.set(sameOriginWindow.location, "href", URL_VALID, {}); }); |
| assert_throws_js(TypeError, () => { hrefSet.call(undefined, URL_VALID); }); |
| }, "Same-origin location.href setter throws TypeError in holder's realm on invalid |this| value"); |
| |
| promise_test(async t => { |
| const crossOriginWindow = await makeWindow(t, URL_CROSS_ORIGIN); |
| assert_throws_js(TypeError, () => { Object.create(crossOriginWindow).location = URL_VALID; }); |
| assert_throws_js(TypeError, () => { Reflect.set(crossOriginWindow, "location", URL_VALID, {}); }); |
| assert_throws_js(TypeError, () => { locationSet.call([], URL_VALID); }); |
| }, "Cross-origin window.location setter throws TypeError in lexical realm on invalid |this| value"); |
| |
| promise_test(async t => { |
| const crossOriginWindow = await makeWindow(t, URL_CROSS_ORIGIN); |
| assert_throws_js(TypeError, () => { Object.create(crossOriginWindow.location).href = URL_VALID; }); |
| assert_throws_js(TypeError, () => { Reflect.set(crossOriginWindow.location, "href", URL_VALID, {}); }); |
| assert_throws_js(TypeError, () => { hrefSet.call(null, URL_VALID); }); |
| }, "Cross-origin location.href setter throws TypeError in lexical realm on invalid |this| value"); |
| |
| |
| promise_test(async t => { |
| const sameOriginWindow = await makeWindow(t, URL_SAME_ORIGIN); |
| assert_throws_js(sameOriginWindow.TypeError, () => { sameOriginWindow.location = Symbol(); }); |
| |
| // The error originates in sameOriginWindow.location.href setter, hence it's not in realm of locationSet. |
| assert_throws_js(sameOriginWindow.TypeError, () => { locationSet.call(sameOriginWindow, Symbol()); }); |
| }, "Same-origin window.location` setter throws TypeError in holder's realm on non-coercible URL argument"); |
| |
| promise_test(async t => { |
| const sameOriginWindow = await makeWindow(t, URL_SAME_ORIGIN); |
| assert_throws_js(sameOriginWindow.TypeError, () => { sameOriginWindow.location.href = Symbol(); }); |
| assert_throws_js(TypeError, () => { hrefSet.call(sameOriginWindow.location, Symbol()); }); |
| }, "Same-origin location.href setter throws TypeError in holder's realm on non-coercible URL argument"); |
| |
| promise_test(async t => { |
| const crossOriginWindow = await makeWindow(t, URL_CROSS_ORIGIN); |
| assert_throws_js(TypeError, () => { crossOriginWindow.location = Symbol(); }); |
| assert_throws_js(TypeError, () => { locationSet.call(crossOriginWindow, Symbol()); }); |
| }, "Cross-origin window.location setter throws TypeError in lexical realm on non-coercible URL argument"); |
| |
| promise_test(async t => { |
| const crossOriginWindow = await makeWindow(t, URL_CROSS_ORIGIN); |
| assert_throws_js(TypeError, () => { crossOriginWindow.location.href = Symbol(); }); |
| assert_throws_js(TypeError, () => { hrefSet.call(crossOriginWindow.location, Symbol()); }); |
| }, "Cross-origin location.href setter throws TypeError in lexical realm on non-coercible URL argument"); |
| |
| function makeWindow(t, src) { |
| return new Promise(resolve => { |
| const iframe = document.createElement("iframe"); |
| t.add_cleanup(() => { iframe.remove(); }); |
| iframe.onload = () => { resolve(iframe.contentWindow); }; |
| iframe.src = src; |
| document.body.append(iframe); |
| }); |
| } |
| </script> |