Skip to content

Commit

Permalink
Test more precisely setting window/location's [[Prototype]]
Browse files Browse the repository at this point in the history
This expands the existing tests for Location to also cover WindowProxy, and to test the newly-introduced logic of allowing [[SetPrototypeOf]] if the value is the same as before: see whatwg/html#2400. It also expands coverage to include cross origin versions of the tests.

The cross-origin tests here are slightly redundant with those under the name "cross-origin-objects", but their additional test coverage of all the vagaries of prototype-setting and different cross-origin situations argues for keeping them as well.
  • Loading branch information
domenic authored Mar 15, 2017
1 parent d43ffe4 commit 259511e
Show file tree
Hide file tree
Showing 13 changed files with 343 additions and 18 deletions.
8 changes: 8 additions & 0 deletions common/domain-setter.sub.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>A page that will likely be same-origin-domain but not same-origin</title>

<script>
"use strict";
document.domain = "{{host}}";
</script>
40 changes: 40 additions & 0 deletions common/test-setting-immutable-prototype.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
self.testSettingImmutablePrototypeToNewValueOnly = (prefix, target, newValue, newValueString) => {
test(() => {
assert_throws(new TypeError, () => {
Object.setPrototypeOf(target, newValue);
});
}, `${prefix}: setting the prototype to ${newValueString} via Object.setPrototypeOf should throw a TypeError`);

test(() => {
assert_throws(new TypeError, function() {
target.__proto__ = newValue;
});
}, `${prefix}: setting the prototype to ${newValueString} via __proto__ should throw a TypeError`);

test(() => {
assert_false(Reflect.setPrototypeOf(target, newValue));
}, `${prefix}: setting the prototype to ${newValueString} via Reflect.setPrototypeOf should return false`);
};

self.testSettingImmutablePrototype =
(prefix, target, originalValue, newValue = {}, newValueString = "an empty object") => {
testSettingImmutablePrototypeToNewValueOnly(prefix, target, newValue, newValueString);

const originalValueString = originalValue === null ? "null" : "its original value";

test(() => {
assert_equals(Object.getPrototypeOf(target), originalValue);
}, `${prefix}: the prototype must still be ${originalValueString}`);

test(() => {
Object.setPrototypeOf(target, originalValue);
}, `${prefix}: setting the prototype to ${originalValueString} via Object.setPrototypeOf should not throw`);

test(() => {
target.__proto__ = originalValue;
}, `${prefix}: setting the prototype to ${originalValueString} via __proto__ should not throw`);

test(() => {
assert_true(Reflect.setPrototypeOf(target, originalValue));
}, `${prefix}: setting the prototype to ${originalValueString} via Reflect.setPrototypeOf should return true`);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>[[SetPrototypeOf]] on a Location object should not allow changing its value: cross-origin via document.domain</title>
<link rel="help" href="http://html.spec.whatwg.org/multipage/#location-setprototypeof">
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/test-setting-immutable-prototype.js"></script>

<iframe src="/common/domain-setter.sub.html"></iframe>

<script>
"use strict";
// This page does *not* set document.domain, so it's cross-origin with the iframe
setup({ explicit_done: true });

window.onload = () => {
const targetLocation = frames[0].location;
const origProto = Object.getPrototypeOf(targetLocation);

test(() => {
assert_equals(Object.getPrototypeOf(targetLocation), null);
}, "Cross-origin via document.domain: the prototype is null");

testSettingImmutablePrototype("Cross-origin via document.domain", targetLocation, origProto);

done();
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>[[SetPrototypeOf]] on a Location object should not allow changing its value: cross-origin</title>
<link rel="help" href="http://html.spec.whatwg.org/multipage/#location-setprototypeof">
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/test-setting-immutable-prototype.js"></script>

<iframe src="//{{domains[www]}}:{{ports[http][1]}}/common/blank.html"></iframe>

<script>
"use strict";
setup({ explicit_done: true });

window.onload = () => {
const targetLocation = frames[0].location;

test(() => {
assert_equals(Object.getPrototypeOf(targetLocation), null);
}, "Cross-origin: the prototype is null");

testSettingImmutablePrototype("Cross-origin", targetLocation, null);

done();
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>[[SetPrototypeOf]] on a Location object should not allow changing its value: cross-origin via document.domain after initially getting the object</title>
<link rel="help" href="http://html.spec.whatwg.org/multipage/#location-setprototypeof">
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/test-setting-immutable-prototype.js"></script>

<iframe src="/common/blank.html"></iframe>

<script>
"use strict";
setup({ explicit_done: true });

window.onload = () => {
const targetLocation = frames[0].location;
const origProto = Object.getPrototypeOf(targetLocation);

test(() => {
assert_not_equals(origProto, null);
}, "Same-origin (for now): the prototype is accessible");

document.domain = "{{host}}";

test(() => {
assert_equals(Object.getPrototypeOf(targetLocation), null);
}, "Became cross-origin via document.domain: the prototype is now null");

testSettingImmutablePrototype("Became cross-origin via document.domain", targetLocation, null);

testSettingImmutablePrototypeToNewValueOnly(
"Became cross-origin via document.domain", targetLocation, origProto,
"the original value from before going cross-origin");

done();
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>[[SetPrototypeOf]] on a Location object should not allow changing its value: cross-origin, but same-origin-domain</title>
<link rel="help" href="http://html.spec.whatwg.org/multipage/#location-setprototypeof">
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/test-setting-immutable-prototype.js"></script>

<iframe src="//{{domains[www]}}:{{ports[http][1]}}/common/domain-setter.sub.html"></iframe>

<script>
"use strict";
document.domain = "{{host}}";
setup({ explicit_done: true });

window.onload = () => {
const targetLocation = frames[0].location;
const origProto = Object.getPrototypeOf(targetLocation);

test(() => {
assert_not_equals(origProto, null);
}, "Same-origin-domain prerequisite check: the original prototype is accessible");

testSettingImmutablePrototype("Same-origin-domain", targetLocation, origProto);

done();
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>[[SetPrototypeOf]] on a location object should not allow changing its value: same-origin</title>
<link rel="help" href="http://html.spec.whatwg.org/multipage/#location-setprototypeof">
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">

<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/common/test-setting-immutable-prototype.js"></script>

<script>
"use strict";

const origProto = Object.getPrototypeOf(location);

test(() => {
assert_not_equals(origProto, null);
}, "Same-origin prerequisite check: the original prototype is accessible");

testSettingImmutablePrototype("Same-origin", location, origProto);
</script>

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>[[SetPrototypeOf]] on a WindowProxy object should not allow changing its value: cross-origin via document.domain</title>
<link rel="help" href="http://html.spec.whatwg.org/multipage/#windowproxy-setprototypeof">
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/test-setting-immutable-prototype.js"></script>

<iframe src="/common/domain-setter.sub.html"></iframe>

<script>
"use strict";
// This page does *not* set document.domain, so it's cross-origin with the iframe
setup({ explicit_done: true });

window.onload = () => {
const target = frames[0];

test(() => {
assert_equals(Object.getPrototypeOf(target), null);
}, "Cross-origin: the prototype is null");

testSettingImmutablePrototype("Cross-origin", target, null);

done();
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>[[SetPrototypeOf]] on a WindowProxy object should not allow changing its value: cross-origin</title>
<link rel="help" href="http://html.spec.whatwg.org/multipage/#windowproxy-setprototypeof">
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/test-setting-immutable-prototype.js"></script>

<iframe src="//{{domains[www]}}:{{ports[http][1]}}/common/blank.html"></iframe>

<script>
"use strict";
setup({ explicit_done: true });

window.onload = () => {
const target = frames[0];

test(() => {
assert_equals(Object.getPrototypeOf(target), null);
}, "Cross-origin: the prototype is null");

testSettingImmutablePrototype("Cross-origin", target, null);

done();
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>[[SetPrototypeOf]] on a WindowProxy object should not allow changing its value: cross-origin via document.domain after initially getting the object</title>
<link rel="help" href="http://html.spec.whatwg.org/multipage/#windowproxy-setprototypeof">
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/test-setting-immutable-prototype.js"></script>

<iframe src="/common/blank.html"></iframe>

<script>
"use strict";
setup({ explicit_done: true });

window.onload = () => {
const target = frames[0];
const origProto = Object.getPrototypeOf(target);

test(() => {
assert_not_equals(origProto, null);
}, "Same-origin (for now): the prototype is accessible");

document.domain = "{{host}}";

test(() => {
assert_equals(Object.getPrototypeOf(target), null);
}, "Became cross-origin via document.domain: the prototype is now null");

testSettingImmutablePrototype("Became cross-origin via document.domain", target, null);

testSettingImmutablePrototypeToNewValueOnly(
"Became cross-origin via document.domain", target, origProto,
"the original value from before going cross-origin");

done();
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>[[SetPrototypeOf]] on a WindowProxy object should not allow changing its value: cross-origin, but same-origin-domain</title>
<link rel="help" href="http://html.spec.whatwg.org/multipage/#windowproxy-setprototypeof">
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/test-setting-immutable-prototype.js"></script>

<iframe src="//{{domains[www]}}:{{ports[http][1]}}/common/domain-setter.sub.html"></iframe>

<script>
"use strict";
document.domain = "{{host}}";
setup({ explicit_done: true });

window.onload = () => {
const target = frames[0];
const origProto = Object.getPrototypeOf(target);

test(() => {
assert_not_equals(origProto, null);
}, "Same-origin-domain prerequisite check: the original prototype is accessible");

testSettingImmutablePrototype("Same-origin-domain", target, origProto);

done();
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>[[SetPrototypeOf]] on a WindowProxy object should not allow changing its value: same-origin</title>
<link rel="help" href="http://html.spec.whatwg.org/multipage/#windowproxy-setprototypeof">
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/test-setting-immutable-prototype.js"></script>

<script>
"use strict";

const origProto = Object.getPrototypeOf(window);

test(() => {
assert_not_equals(origProto, null);
}, "Same-origin prerequisite check: the original prototype is accessible");

testSettingImmutablePrototype("Same-origin", window, origProto);
</script>

0 comments on commit 259511e

Please sign in to comment.