tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

global-object-implicit-this-value-cross-realm.html (5056B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <title>Cross-realm getter / setter / operation doesn't use lexical global object if |this| value is incompatible object / null / undefined</title>
      4 <link rel="help" href="https://webidl.spec.whatwg.org/#dfn-attribute-getter">
      5 <link rel="help" href="https://webidl.spec.whatwg.org/#dfn-attribute-setter">
      6 <link rel="help" href="https://webidl.spec.whatwg.org/#dfn-create-operation-function">
      7 
      8 <script src="/resources/testharness.js"></script>
      9 <script src="/resources/testharnessreport.js"></script>
     10 <script src="support/create-realm.js"></script>
     11 
     12 <body>
     13 <script>
     14 promise_test(async t => {
     15    const other = await createRealm(t);
     16    const notWindow = Object.create(Object.getPrototypeOf(other));
     17 
     18    assert_throws_js(other.TypeError, () => { Object.create(other).window; });
     19    assert_throws_js(other.TypeError, () => { Object.getOwnPropertyDescriptor(other, "history").get.call(notWindow); });
     20    assert_throws_js(other.TypeError, () => { Reflect.get(other, "screen", notWindow); });
     21    assert_throws_js(other.TypeError, () => { new Proxy(other, {}).onclick; });
     22 }, "Cross-realm global object's getter throws when called on incompatible object");
     23 
     24 promise_test(async t => {
     25    const other = await createRealm(t);
     26    const notWindow = Object.create(Object.getPrototypeOf(other));
     27 
     28    assert_throws_js(other.TypeError, () => { Object.create(other).name = "dummy"; });
     29    assert_throws_js(other.TypeError, () => { Object.getOwnPropertyDescriptor(other, "status").set.call(notWindow, other.status); });
     30    // parent is [Replaceable]
     31    assert_throws_js(other.TypeError, () => { Reflect.set(other, "parent", window, notWindow); });
     32    assert_throws_js(other.TypeError, () => { new Proxy(other, {}).location = location; });
     33 }, "Cross-realm global object's setter throws when called on incompatible object");
     34 
     35 promise_test(async t => {
     36    const other = await createRealm(t);
     37    const notWindow = Object.create(Object.getPrototypeOf(other));
     38 
     39    assert_throws_js(other.TypeError, () => { Object.create(other).focus(); });
     40    assert_throws_js(other.TypeError, () => { other.clearInterval.call(notWindow, 0); });
     41    assert_throws_js(other.TypeError, () => { Reflect.apply(other.blur, notWindow, []); });
     42    assert_throws_js(other.TypeError, () => { new Proxy(other, {}).removeEventListener("foo", () => {}); });
     43 }, "Cross-realm global object's operation throws when called on incompatible object");
     44 
     45 promise_test(async t => {
     46    const other = await createRealm(t);
     47    const otherNameGetter = Object.getOwnPropertyDescriptor(other, "name").get;
     48 
     49    assert_equals(Reflect.get(other, "self", null), other);
     50    assert_equals(Reflect.get(other, "document", undefined), other.document);
     51    assert_equals(otherNameGetter.call(null), "dummy");
     52    // An engine might have different code path for calling a function from outer scope to implement step 1.b.iii of https://tc39.es/ecma262/#sec-evaluatecall
     53    assert_equals((() => otherNameGetter())(), "dummy");
     54 }, "Cross-realm global object's getter called on null / undefined");
     55 
     56 promise_test(async t => {
     57    const other = await createRealm(t);
     58    const otherLocationSetter = Object.getOwnPropertyDescriptor(other, "location").set;
     59    const otherHref = other.location.href;
     60    const newSelf = {};
     61 
     62    // self is [Replaceable]
     63    assert_true(Reflect.set(other, "self", newSelf, null));
     64    assert_true(Reflect.set(other, "name", "newName", undefined));
     65 
     66    otherLocationSetter.call(null, `${otherHref}#foo`);
     67    assert_equals(other.location.hash, "#foo");
     68    // An engine might have different code path for calling a function from outer scope to implement step 1.b.iii of https://tc39.es/ecma262/#sec-evaluatecall
     69    (() => { otherLocationSetter(`${otherHref}#bar`); })();
     70    assert_equals(other.location.hash, "#bar");
     71 
     72    // Check these after calling "location" setter make sure no navigation has occurred
     73    assert_equals(other.self, newSelf);
     74    assert_equals(other.name, "newName");
     75 }, "Cross-realm global object's setter called on null / undefined");
     76 
     77 promise_test(async t => {
     78    const other = await createRealm(t);
     79    const otherFocus = other.focus;
     80    const otherDispatchEvent = other.dispatchEvent;
     81 
     82    assert_equals(document.activeElement, document.body);
     83    // An engine might have different code path for calling a function from outer scope to implement step 1.b.iii of https://tc39.es/ecma262/#sec-evaluatecall
     84    (() => { otherFocus(); })();
     85    assert_equals(document.activeElement.contentWindow, other);
     86 
     87    let caughtEvent;
     88    other.addEventListener.call(null, "foo", event => { caughtEvent = event; });
     89    const dispatchedEvent = new other.Event("foo");
     90    assert_true(otherDispatchEvent(dispatchedEvent));
     91    assert_equals(caughtEvent, dispatchedEvent);
     92 
     93    const messagePromise = new EventWatcher(t, other, "message").wait_for("message");
     94    other.postMessage.call(null, "foo");
     95    assert_equals((await messagePromise).data, "foo");
     96 }, "Cross-realm global object's operation called on null / undefined");
     97 </script>