зеркало из https://github.com/mozilla/gecko-dev.git
340 строки
12 KiB
Plaintext
340 строки
12 KiB
Plaintext
|
<?xml version="1.0"?>
|
||
|
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||
|
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||
|
type="text/css"?>
|
||
|
<window title="MessageManager CPOW tests"
|
||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||
|
onload="start()">
|
||
|
|
||
|
<!-- test results are displayed in the html:body -->
|
||
|
<label value="CPOWs"/>
|
||
|
|
||
|
<script type="application/javascript"><![CDATA[
|
||
|
var test_state = "remote";
|
||
|
var test_node = null;
|
||
|
var reentered = false;
|
||
|
var savedMM = null;
|
||
|
const Cu = Components.utils;
|
||
|
|
||
|
function info(message) {
|
||
|
return opener.wrappedJSObject.info(message);
|
||
|
}
|
||
|
|
||
|
function ok(condition, message) {
|
||
|
return opener.wrappedJSObject.ok(condition, message);
|
||
|
}
|
||
|
|
||
|
function is(v1, v2, message) {
|
||
|
return opener.wrappedJSObject.is(v1, v2, message);
|
||
|
}
|
||
|
|
||
|
function todo_is(v1, v2, message) {
|
||
|
return opener.wrappedJSObject.todo_is(v1, v2, message);
|
||
|
}
|
||
|
|
||
|
// Make sure that an error in this file actually causes the test to fail.
|
||
|
var gReceivedErrorProbe = false;
|
||
|
window.onerror = function (msg, url, line) {
|
||
|
if (/Test Error Probe/.test(msg)) {
|
||
|
gReceivedErrorProbe = true;
|
||
|
return;
|
||
|
}
|
||
|
ok(false, "Error while executing: \n" + msg + "\n" + url + ":" + line);
|
||
|
};
|
||
|
|
||
|
function testCpowMessage(message) {
|
||
|
ok(message.json.check == "ok", "correct json");
|
||
|
|
||
|
ok(!Components.utils.isCrossProcessWrapper(message.json), "not everything is a CPOW");
|
||
|
|
||
|
let data = message.objects.data;
|
||
|
let document = message.objects.document;
|
||
|
if (test_state == "remote") {
|
||
|
ok(Components.utils.isCrossProcessWrapper(data), "got a CPOW");
|
||
|
ok(Components.utils.isCrossProcessWrapper(document), "got a CPOW");
|
||
|
}
|
||
|
ok(data.i === 5, "integer property");
|
||
|
ok(data.b === true, "boolean property");
|
||
|
ok(data.s === "hello", "string property");
|
||
|
ok(data.x.i === 10, "nested property");
|
||
|
ok(data.f() === 99, "function call");
|
||
|
let obj = new data.ctor();
|
||
|
ok(obj.a === 3, "constructor call");
|
||
|
ok(document.title === "Hello, Kitty", "document node");
|
||
|
|
||
|
data.i = 6;
|
||
|
data.b = false;
|
||
|
data.s = "bye";
|
||
|
data.x = null;
|
||
|
ok(data.i === 6, "integer property");
|
||
|
ok(data.b === false, "boolean property");
|
||
|
ok(data.s === "bye", "string property");
|
||
|
ok(data.x === null, "nested property");
|
||
|
|
||
|
let throwing = message.objects.throwing;
|
||
|
// Based on the table on:
|
||
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
|
||
|
let tests = [
|
||
|
() => Object.getOwnPropertyDescriptor(throwing, 'test'),
|
||
|
() => Object.getOwnPropertyNames(throwing),
|
||
|
() => Object.defineProperty(throwing, 'test', {value: 1}),
|
||
|
() => delete throwing.test,
|
||
|
() => "test" in throwing,
|
||
|
() => Object.prototype.hasOwnProperty.call(throwing, 'test'),
|
||
|
() => throwing.test,
|
||
|
() => { throwing.test = 1 },
|
||
|
// () => { for (let prop in throwing) {} }, Bug 783829
|
||
|
() => { for (let prop of throwing) {} },
|
||
|
() => Object.keys(throwing),
|
||
|
() => Function.prototype.call.call(throwing),
|
||
|
() => new throwing,
|
||
|
() => Object.preventExtensions(throwing),
|
||
|
() => Object.freeze(throwing),
|
||
|
() => Object.seal(throwing),
|
||
|
]
|
||
|
|
||
|
for (let test of tests) {
|
||
|
let threw = false;
|
||
|
try {
|
||
|
test()
|
||
|
} catch (e) {
|
||
|
threw = true;
|
||
|
}
|
||
|
ok(threw, "proxy operation threw exception");
|
||
|
}
|
||
|
|
||
|
let array = message.objects.array;
|
||
|
let i = 1;
|
||
|
for (let elt of array) {
|
||
|
ok(elt === i, "correct element found");
|
||
|
i++;
|
||
|
}
|
||
|
ok(i === 4, "array has correct length");
|
||
|
|
||
|
let j = message.objects.for_json;
|
||
|
let str = JSON.stringify(j);
|
||
|
let j2 = JSON.parse(str);
|
||
|
ok(j2.n === 3, "JSON integer property");
|
||
|
ok(j2.a[0] === 1, "JSON array index");
|
||
|
ok(j2.a[1] === 2, "JSON array index");
|
||
|
ok(j2.a[2] === 3, "JSON array index");
|
||
|
ok(j2.s === "hello", "JSON string property");
|
||
|
ok(j2.o.x === 10, "JSON object property");
|
||
|
}
|
||
|
|
||
|
function recvAsyncMessage(message) {
|
||
|
testCpowMessage(message);
|
||
|
}
|
||
|
|
||
|
function recvSyncMessage(message) {
|
||
|
testCpowMessage(message);
|
||
|
}
|
||
|
|
||
|
function recvRpcMessage(message) {
|
||
|
ok(message.json.check == "ok", "correct json");
|
||
|
|
||
|
let data = message.objects.data;
|
||
|
|
||
|
// Sanity check.
|
||
|
ok(data.i === 5, "integer property");
|
||
|
|
||
|
// Check that we re-enter.
|
||
|
reentered = false;
|
||
|
let result = data.reenter();
|
||
|
ok(reentered, "re-entered rpc");
|
||
|
ok(result == "ok", "got correct result");
|
||
|
}
|
||
|
|
||
|
function recvReenterMessage(message) {
|
||
|
ok(message.objects.data.valid === true, "cpows work");
|
||
|
reentered = true;
|
||
|
}
|
||
|
|
||
|
function recvNestedSyncMessage(message) {
|
||
|
message.objects.data.reenter();
|
||
|
}
|
||
|
|
||
|
function recvReenterSyncMessage(message) {
|
||
|
ok(false, "should not have received re-entered sync message");
|
||
|
}
|
||
|
|
||
|
function recvFailMessage(message) {
|
||
|
ok(false, message.json.message);
|
||
|
}
|
||
|
|
||
|
function recvDoneMessage(message) {
|
||
|
if (test_state == "remote") {
|
||
|
test_node.parentNode.removeChild(test_node);
|
||
|
run_tests("inprocess");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
finish();
|
||
|
}
|
||
|
|
||
|
function recvParentTest(message) {
|
||
|
let func = message.objects.func;
|
||
|
let result = func(n => 2*n);
|
||
|
ok(result == 20, "result == 20");
|
||
|
let obj = {a:1, __exposedProps__: {"a": "r"}};
|
||
|
savedMM.sendAsyncMessage("cpows:from_parent", {}, {obj: obj});
|
||
|
}
|
||
|
|
||
|
// Make sure errors in this file actually hit window.onerror.
|
||
|
function recvErrorReportingTest(message) {
|
||
|
throw "Test Error Probe";
|
||
|
}
|
||
|
|
||
|
let savedElement = null;
|
||
|
function recvDomTest(message) {
|
||
|
savedElement = message.objects.element;
|
||
|
}
|
||
|
|
||
|
function recvDomTestAfterGC(message) {
|
||
|
let id;
|
||
|
try {
|
||
|
id = savedElement.id;
|
||
|
} catch (e) {
|
||
|
ok(false, "Got exception using DOM element");
|
||
|
}
|
||
|
is(id, "it_works", "DOM element has expected ID");
|
||
|
}
|
||
|
|
||
|
function recvXrayTest(message) {
|
||
|
let element = message.objects.element;
|
||
|
is(element.foo, undefined, "DOM element does not expose content properties");
|
||
|
}
|
||
|
|
||
|
function recvSymbolTest(message) {
|
||
|
let object = message.objects.object;
|
||
|
is(object[Symbol.iterator], Symbol.iterator, "Should use Symbol.iterator");
|
||
|
is(Symbol.keyFor(object[Symbol.for("cpow-test")]), "cpow-test", "Symbols aren't registered correctly");
|
||
|
let symbols = Object.getOwnPropertySymbols(object);
|
||
|
is(symbols.length, 2, "Object should have two symbol keys");
|
||
|
let test = undefined;
|
||
|
for (let x of message.objects.test) {
|
||
|
test = x;
|
||
|
}
|
||
|
is(test, "a", "for .. of iteration should work");
|
||
|
}
|
||
|
|
||
|
let systemGlobal = this;
|
||
|
function recvCompartmentTest(message) {
|
||
|
let getUnprivilegedObject = message.objects.getUnprivilegedObject;
|
||
|
let testParentObject = message.objects.testParentObject;
|
||
|
|
||
|
// Make sure that parent->child CPOWs live in the parent's privileged junk scope.
|
||
|
let unprivilegedObject = getUnprivilegedObject();
|
||
|
is(Cu.getGlobalForObject(getUnprivilegedObject),
|
||
|
Cu.getGlobalForObject(unprivilegedObject),
|
||
|
"all parent->child CPOWs should live in the same scope");
|
||
|
let cpowLocation = Cu.getCompartmentLocation(getUnprivilegedObject);
|
||
|
ok(/Privileged Junk/.test(cpowLocation),
|
||
|
"parent->child CPOWs should live in the privileged junk scope: " + cpowLocation);
|
||
|
|
||
|
// Make sure that parent->child CPOWs point through a privileged scope in the child
|
||
|
// (the privileged junk scope, but we don't have a good way to test for that
|
||
|
// specifically).
|
||
|
is(unprivilegedObject.expando, undefined, "parent->child references should get Xrays");
|
||
|
is(unprivilegedObject.wrappedJSObject.expando, 42, "parent->child references should get waivable Xrays");
|
||
|
|
||
|
// Send an object to the child to let it verify invariants in the other direction.
|
||
|
function passMe() { return 42; };
|
||
|
passMe.expando = 42;
|
||
|
let results = testParentObject(passMe);
|
||
|
ok(results.length > 0, "Need results");
|
||
|
results.forEach((x) => is(x.result, "PASS", x.message));
|
||
|
}
|
||
|
|
||
|
function recvRegExpTest(message) {
|
||
|
let regexp = message.objects.regexp;
|
||
|
|
||
|
// These work generically.
|
||
|
is(regexp.toString(), "/myRegExp/g", "toString works right");
|
||
|
ok(regexp.test("I like myRegExp to match"), "No false positives");
|
||
|
ok(!regexp.test("asdfsdf"), "No false positives");
|
||
|
|
||
|
// These go over regexp_toShared.
|
||
|
is("filler myRegExp filler".search(regexp), 7, "String.prototype.match works right");
|
||
|
var shell = /x/;
|
||
|
shell.compile(regexp);
|
||
|
is(regexp.toString(), shell.toString(), ".compile works right");
|
||
|
}
|
||
|
|
||
|
let savedWilldieObj;
|
||
|
let wontDie = {f:2, __exposedProps__: {"f": "r"}};
|
||
|
function recvLifetimeTest1(message) {
|
||
|
let obj = message.objects.obj;
|
||
|
savedWilldieObj = obj.will_die;
|
||
|
ok(savedWilldieObj.f == 1, "limited-lifetime CPOW works at first");
|
||
|
obj.wont_die = wontDie;
|
||
|
obj = null;
|
||
|
return 10;
|
||
|
}
|
||
|
function recvLifetimeTest2(message) {
|
||
|
let threw = false;
|
||
|
try {
|
||
|
savedWilldieObj.f;
|
||
|
} catch (e) {
|
||
|
threw = true;
|
||
|
}
|
||
|
ok(threw, "limited-lifetime CPOW stopped working");
|
||
|
wontDie = null;
|
||
|
Components.utils.schedulePreciseGC(function() {
|
||
|
savedMM.sendAsyncMessage("cpows:lifetime_test_3");
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function run_tests(type) {
|
||
|
info("Running tests: " + type);
|
||
|
var node = document.getElementById('cpowbrowser_' + type);
|
||
|
|
||
|
test_state = type;
|
||
|
test_node = node;
|
||
|
|
||
|
function recvIsRemote(message) {
|
||
|
return type == "remote";
|
||
|
}
|
||
|
|
||
|
var mm = node.messageManager;
|
||
|
savedMM = mm;
|
||
|
mm.addMessageListener("cpows:is_remote", recvIsRemote);
|
||
|
mm.addMessageListener("cpows:async", recvAsyncMessage);
|
||
|
mm.addMessageListener("cpows:sync", recvSyncMessage);
|
||
|
mm.addMessageListener("cpows:rpc", recvRpcMessage);
|
||
|
mm.addMessageListener("cpows:reenter", recvReenterMessage);
|
||
|
mm.addMessageListener("cpows:reenter", recvReenterMessage);
|
||
|
mm.addMessageListener("cpows:nested_sync", recvNestedSyncMessage);
|
||
|
mm.addMessageListener("cpows:reenter_sync", recvReenterSyncMessage);
|
||
|
mm.addMessageListener("cpows:done", recvDoneMessage);
|
||
|
mm.addMessageListener("cpows:fail", recvFailMessage);
|
||
|
mm.addMessageListener("cpows:parent_test", recvParentTest);
|
||
|
mm.addMessageListener("cpows:error_reporting_test", recvErrorReportingTest);
|
||
|
mm.addMessageListener("cpows:dom_test", recvDomTest);
|
||
|
mm.addMessageListener("cpows:dom_test_after_gc", recvDomTestAfterGC);
|
||
|
mm.addMessageListener("cpows:xray_test", recvXrayTest);
|
||
|
if (typeof Symbol === "function") {
|
||
|
mm.addMessageListener("cpows:symbol_test", recvSymbolTest);
|
||
|
}
|
||
|
mm.addMessageListener("cpows:compartment_test", recvCompartmentTest);
|
||
|
mm.addMessageListener("cpows:regexp_test", recvRegExpTest);
|
||
|
mm.addMessageListener("cpows:lifetime_test_1", recvLifetimeTest1);
|
||
|
mm.addMessageListener("cpows:lifetime_test_2", recvLifetimeTest2);
|
||
|
mm.loadFrameScript("chrome://mochitests/content/chrome/dom/base/test/chrome/cpows_child.js", true);
|
||
|
}
|
||
|
|
||
|
function start() {
|
||
|
run_tests('remote');
|
||
|
}
|
||
|
|
||
|
function finish() {
|
||
|
ok(gReceivedErrorProbe, "Should have reported error probe");
|
||
|
opener.setTimeout("done()", 0);
|
||
|
window.close();
|
||
|
}
|
||
|
]]></script>
|
||
|
|
||
|
<browser type="content" src="about:blank" id="cpowbrowser_remote" remote="true"/>
|
||
|
<browser type="content" src="about:blank" id="cpowbrowser_inprocess"/>
|
||
|
</window>
|