Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!DOCTYPE html>
<meta charset="utf-8">
<title>Cross-realm getter / setter / operation doesn't use lexical global object if |this| value is incompatible object / null / undefined</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support/create-realm.js"></script>
<body>
<script>
promise_test(async t => {
const other = await createRealm(t);
const notWindow = Object.create(Object.getPrototypeOf(other));
assert_throws_js(other.TypeError, () => { Object.create(other).window; });
assert_throws_js(other.TypeError, () => { Object.getOwnPropertyDescriptor(other, "history").get.call(notWindow); });
assert_throws_js(other.TypeError, () => { Reflect.get(other, "screen", notWindow); });
assert_throws_js(other.TypeError, () => { new Proxy(other, {}).onclick; });
}, "Cross-realm global object's getter throws when called on incompatible object");
promise_test(async t => {
const other = await createRealm(t);
const notWindow = Object.create(Object.getPrototypeOf(other));
assert_throws_js(other.TypeError, () => { Object.create(other).name = "dummy"; });
assert_throws_js(other.TypeError, () => { Object.getOwnPropertyDescriptor(other, "status").set.call(notWindow, other.status); });
// parent is [Replaceable]
assert_throws_js(other.TypeError, () => { Reflect.set(other, "parent", window, notWindow); });
assert_throws_js(other.TypeError, () => { new Proxy(other, {}).location = location; });
}, "Cross-realm global object's setter throws when called on incompatible object");
promise_test(async t => {
const other = await createRealm(t);
const notWindow = Object.create(Object.getPrototypeOf(other));
assert_throws_js(other.TypeError, () => { Object.create(other).focus(); });
assert_throws_js(other.TypeError, () => { other.clearInterval.call(notWindow, 0); });
assert_throws_js(other.TypeError, () => { Reflect.apply(other.blur, notWindow, []); });
assert_throws_js(other.TypeError, () => { new Proxy(other, {}).removeEventListener("foo", () => {}); });
}, "Cross-realm global object's operation throws when called on incompatible object");
promise_test(async t => {
const other = await createRealm(t);
const otherNameGetter = Object.getOwnPropertyDescriptor(other, "name").get;
assert_equals(Reflect.get(other, "self", null), other);
assert_equals(Reflect.get(other, "document", undefined), other.document);
assert_equals(otherNameGetter.call(null), "dummy");
// 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
assert_equals((() => otherNameGetter())(), "dummy");
}, "Cross-realm global object's getter called on null / undefined");
promise_test(async t => {
const other = await createRealm(t);
const otherLocationSetter = Object.getOwnPropertyDescriptor(other, "location").set;
const otherHref = other.location.href;
const newSelf = {};
// self is [Replaceable]
assert_true(Reflect.set(other, "self", newSelf, null));
assert_true(Reflect.set(other, "name", "newName", undefined));
otherLocationSetter.call(null, `${otherHref}#foo`);
assert_equals(other.location.hash, "#foo");
// 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
(() => { otherLocationSetter(`${otherHref}#bar`); })();
assert_equals(other.location.hash, "#bar");
// Check these after calling "location" setter make sure no navigation has occurred
assert_equals(other.self, newSelf);
assert_equals(other.name, "newName");
}, "Cross-realm global object's setter called on null / undefined");
promise_test(async t => {
const other = await createRealm(t);
const otherFocus = other.focus;
const otherDispatchEvent = other.dispatchEvent;
assert_equals(document.activeElement, document.body);
// 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
(() => { otherFocus(); })();
assert_equals(document.activeElement.contentWindow, other);
let caughtEvent;
other.addEventListener.call(null, "foo", event => { caughtEvent = event; });
const dispatchedEvent = new other.Event("foo");
assert_true(otherDispatchEvent(dispatchedEvent));
assert_equals(caughtEvent, dispatchedEvent);
const messagePromise = new EventWatcher(t, other, "message").wait_for("message");
other.postMessage.call(null, "foo");
assert_equals((await messagePromise).data, "foo");
}, "Cross-realm global object's operation called on null / undefined");
</script>