зеркало из https://github.com/mozilla/gecko-dev.git
Bug 837723: Implement Debugger.Object.prototype.unsafeDereference. r=jorendorff
This commit is contained in:
Родитель
70218ceedf
Коммит
689e14416b
|
@ -0,0 +1,10 @@
|
||||||
|
// Debugger.Object.prototype.unsafeDereference returns the referent directly.
|
||||||
|
|
||||||
|
var g = newGlobal();
|
||||||
|
var dbg = new Debugger();
|
||||||
|
var gw = dbg.addDebuggee(g);
|
||||||
|
|
||||||
|
assertEq(gw.getOwnPropertyDescriptor('Math').value.unsafeDereference(), g.Math);
|
||||||
|
|
||||||
|
g.eval('var obj = {}');
|
||||||
|
assertEq(gw.getOwnPropertyDescriptor('obj').value.unsafeDereference(), g.obj);
|
|
@ -4779,6 +4779,14 @@ DebuggerObject_unwrap(JSContext *cx, unsigned argc, Value *vp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
DebuggerObject_unsafeDereference(JSContext *cx, unsigned argc, Value *vp)
|
||||||
|
{
|
||||||
|
THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, "unsafeDereference", args, referent);
|
||||||
|
args.rval().setObject(*referent);
|
||||||
|
return cx->compartment->wrap(cx, args.rval());
|
||||||
|
}
|
||||||
|
|
||||||
static JSPropertySpec DebuggerObject_properties[] = {
|
static JSPropertySpec DebuggerObject_properties[] = {
|
||||||
JS_PSG("proto", DebuggerObject_getProto, 0),
|
JS_PSG("proto", DebuggerObject_getProto, 0),
|
||||||
JS_PSG("class", DebuggerObject_getClass, 0),
|
JS_PSG("class", DebuggerObject_getClass, 0),
|
||||||
|
@ -4810,6 +4818,7 @@ static JSFunctionSpec DebuggerObject_methods[] = {
|
||||||
JS_FN("evalInGlobal", DebuggerObject_evalInGlobal, 1, 0),
|
JS_FN("evalInGlobal", DebuggerObject_evalInGlobal, 1, 0),
|
||||||
JS_FN("evalInGlobalWithBindings", DebuggerObject_evalInGlobalWithBindings, 2, 0),
|
JS_FN("evalInGlobalWithBindings", DebuggerObject_evalInGlobalWithBindings, 2, 0),
|
||||||
JS_FN("unwrap", DebuggerObject_unwrap, 0, 0),
|
JS_FN("unwrap", DebuggerObject_unwrap, 0, 0),
|
||||||
|
JS_FN("unsafeDereference", DebuggerObject_unsafeDereference, 0, 0),
|
||||||
JS_FS_END
|
JS_FS_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
DEPTH = @DEPTH@
|
||||||
|
topsrcdir = @top_srcdir@
|
||||||
|
srcdir = @srcdir@
|
||||||
|
VPATH = @srcdir@
|
||||||
|
relativesrcdir = @relativesrcdir@
|
||||||
|
|
||||||
|
include $(DEPTH)/config/autoconf.mk
|
||||||
|
|
||||||
|
MOCHITEST_CHROME_FILES = \
|
||||||
|
test_unsafeDereference.html \
|
||||||
|
nonchrome_unsafeDereference.html \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,5 @@
|
||||||
|
# vim: set filetype=python:
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<script>
|
||||||
|
var xhr = new XMLHttpRequest;
|
||||||
|
xhr.timeout = 1742;
|
||||||
|
xhr.expando = 'Expando!';
|
||||||
|
</script>
|
||||||
|
</html>
|
|
@ -0,0 +1,52 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=837723
|
||||||
|
|
||||||
|
When we use Debugger.Object.prototype.unsafeDereference to get a non-D.O
|
||||||
|
reference to a content object in chrome, that reference should be via an
|
||||||
|
xray wrapper.
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Mozilla Bug 837723</title>
|
||||||
|
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script>
|
||||||
|
|
||||||
|
Components.utils.import("resource://gre/modules/jsdebugger.jsm");
|
||||||
|
addDebuggerToGlobal(this);
|
||||||
|
|
||||||
|
window.onload = function () {
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
var iframe = document.createElement("iframe");
|
||||||
|
iframe.src = "http://mochi.test:8888/chrome/toolkit/devtools/debugger/tests/mochitest/nonchrome_unsafeDereference.html";
|
||||||
|
|
||||||
|
iframe.onload = function () {
|
||||||
|
var dbg = new Debugger;
|
||||||
|
var contentDO = dbg.addDebuggee(iframe.contentWindow);
|
||||||
|
var xhrDesc = contentDO.getOwnPropertyDescriptor('xhr');
|
||||||
|
|
||||||
|
isnot(xhrDesc, undefined, "xhr should be visible as property of content global");
|
||||||
|
isnot(xhrDesc.value, undefined, "xhr should have a value");
|
||||||
|
|
||||||
|
var xhr = xhrDesc.value.unsafeDereference();
|
||||||
|
|
||||||
|
is(typeof xhr, "object", "we should be able to deference xhr's value's D.O");
|
||||||
|
is(xhr.timeout, 1742, "chrome should see the xhr's 'timeout' property");
|
||||||
|
is(xhr.expando, undefined, "chrome should not see the xhr's 'expando' property");
|
||||||
|
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
document.body.appendChild(iframe);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -4,5 +4,6 @@
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
MODULE = 'test_debugger'
|
DIRS += ['mochitest']
|
||||||
|
|
||||||
|
MODULE = 'test_debugger'
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
// Any copyright is dedicated to the Public Domain.
|
||||||
|
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
|
||||||
|
// Test Debugger.Object.prototype.unsafeDereference in the presence of
|
||||||
|
// interesting cross-compartment wrappers.
|
||||||
|
//
|
||||||
|
// This is not really a debugger server test; it's more of a Debugger test.
|
||||||
|
// But we need xpcshell and Components.utils.Sandbox to get
|
||||||
|
// cross-compartment wrappers with interesting properties, and this is the
|
||||||
|
// xpcshell test directory most closely related to the JS Debugger API.
|
||||||
|
|
||||||
|
Components.utils.import("resource://gre/modules/jsdebugger.jsm");
|
||||||
|
addDebuggerToGlobal(this);
|
||||||
|
|
||||||
|
// Add a method to Debugger.Object for fetching value properties
|
||||||
|
// conveniently.
|
||||||
|
Debugger.Object.prototype.getProperty = function (aName) {
|
||||||
|
let desc = this.getOwnPropertyDescriptor(aName);
|
||||||
|
if (!desc)
|
||||||
|
return undefined;
|
||||||
|
if (!desc.value) {
|
||||||
|
throw Error("Debugger.Object.prototype.getProperty: " +
|
||||||
|
"not a value property: " + aName);
|
||||||
|
}
|
||||||
|
return desc.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
function run_test() {
|
||||||
|
// Create a low-privilege sandbox, and a chrome-privilege sandbox.
|
||||||
|
let contentBox = Components.utils.Sandbox('http://www.example.com');
|
||||||
|
let chromeBox = Components.utils.Sandbox(this);
|
||||||
|
|
||||||
|
// Create an objects in this compartment, and one in each sandbox. We'll
|
||||||
|
// refer to the objects as "mainObj", "contentObj", and "chromeObj", in
|
||||||
|
// variable and property names.
|
||||||
|
var mainObj = { name: "mainObj" };
|
||||||
|
Components.utils.evalInSandbox('var contentObj = { name: "contentObj" };',
|
||||||
|
contentBox);
|
||||||
|
Components.utils.evalInSandbox('var chromeObj = { name: "chromeObj" };',
|
||||||
|
chromeBox);
|
||||||
|
|
||||||
|
// Give each global a pointer to all the other globals' objects.
|
||||||
|
contentBox.mainObj = chromeBox.mainObj = mainObj;
|
||||||
|
var contentObj = chromeBox.contentObj = contentBox.contentObj;
|
||||||
|
var chromeObj = contentBox.chromeObj = chromeBox.chromeObj;
|
||||||
|
|
||||||
|
// First, a whole bunch of basic sanity checks, to ensure that JavaScript
|
||||||
|
// evaluated in various scopes really does see the world the way this
|
||||||
|
// test expects it to.
|
||||||
|
|
||||||
|
// The objects appear as global variables in the sandbox, and as
|
||||||
|
// the sandbox object's properties in chrome.
|
||||||
|
do_check_true(Components.utils.evalInSandbox('mainObj', contentBox)
|
||||||
|
=== contentBox.mainObj);
|
||||||
|
do_check_true(Components.utils.evalInSandbox('contentObj', contentBox)
|
||||||
|
=== contentBox.contentObj);
|
||||||
|
do_check_true(Components.utils.evalInSandbox('chromeObj', contentBox)
|
||||||
|
=== contentBox.chromeObj);
|
||||||
|
do_check_true(Components.utils.evalInSandbox('mainObj', chromeBox)
|
||||||
|
=== chromeBox.mainObj);
|
||||||
|
do_check_true(Components.utils.evalInSandbox('contentObj', chromeBox)
|
||||||
|
=== chromeBox.contentObj);
|
||||||
|
do_check_true(Components.utils.evalInSandbox('chromeObj', chromeBox)
|
||||||
|
=== chromeBox.chromeObj);
|
||||||
|
|
||||||
|
// We (the main global) can see properties of all objects in all globals.
|
||||||
|
do_check_true(contentBox.mainObj.name === "mainObj");
|
||||||
|
do_check_true(contentBox.contentObj.name === "contentObj");
|
||||||
|
do_check_true(contentBox.chromeObj.name === "chromeObj");
|
||||||
|
|
||||||
|
// chromeBox can see properties of all objects in all globals.
|
||||||
|
do_check_eq(Components.utils.evalInSandbox('mainObj.name', chromeBox),
|
||||||
|
'mainObj');
|
||||||
|
do_check_eq(Components.utils.evalInSandbox('contentObj.name', chromeBox),
|
||||||
|
'contentObj');
|
||||||
|
do_check_eq(Components.utils.evalInSandbox('chromeObj.name', chromeBox),
|
||||||
|
'chromeObj');
|
||||||
|
|
||||||
|
// contentBox can see properties of the content object, but not of either
|
||||||
|
// chrome object, because by default, content -> chrome wrappers hide all
|
||||||
|
// object properties.
|
||||||
|
do_check_eq(Components.utils.evalInSandbox('mainObj.name', contentBox),
|
||||||
|
undefined);
|
||||||
|
do_check_eq(Components.utils.evalInSandbox('contentObj.name', contentBox),
|
||||||
|
'contentObj');
|
||||||
|
do_check_eq(Components.utils.evalInSandbox('chromeObj.name', contentBox),
|
||||||
|
undefined);
|
||||||
|
|
||||||
|
// When viewing an object in compartment A from the vantage point of
|
||||||
|
// compartment B, Debugger should give the same results as debuggee code
|
||||||
|
// would.
|
||||||
|
|
||||||
|
// Create a debugger, debugging our two sandboxes.
|
||||||
|
let dbg = new Debugger;
|
||||||
|
|
||||||
|
// Create Debugger.Object instances referring to the two sandboxes, as
|
||||||
|
// seen from their own compartments.
|
||||||
|
let contentBoxDO = dbg.addDebuggee(contentBox);
|
||||||
|
let chromeBoxDO = dbg.addDebuggee(chromeBox);
|
||||||
|
|
||||||
|
// Use Debugger to view the objects from contentBox. We should get the
|
||||||
|
// same D.O instance from both getProperty and makeDebuggeeValue, and the
|
||||||
|
// same property visibility we checked for above.
|
||||||
|
let mainFromContentDO = contentBoxDO.getProperty('mainObj');
|
||||||
|
do_check_eq(mainFromContentDO, contentBoxDO.makeDebuggeeValue(mainObj));
|
||||||
|
do_check_eq(mainFromContentDO.getProperty('name'), undefined);
|
||||||
|
do_check_eq(mainFromContentDO.unsafeDereference(), mainObj);
|
||||||
|
|
||||||
|
let contentFromContentDO = contentBoxDO.getProperty('contentObj');
|
||||||
|
do_check_eq(contentFromContentDO, contentBoxDO.makeDebuggeeValue(contentObj));
|
||||||
|
do_check_eq(contentFromContentDO.getProperty('name'), 'contentObj');
|
||||||
|
do_check_eq(contentFromContentDO.unsafeDereference(), contentObj);
|
||||||
|
|
||||||
|
let chromeFromContentDO = contentBoxDO.getProperty('chromeObj');
|
||||||
|
do_check_eq(chromeFromContentDO, contentBoxDO.makeDebuggeeValue(chromeObj));
|
||||||
|
do_check_eq(chromeFromContentDO.getProperty('name'), undefined);
|
||||||
|
do_check_eq(chromeFromContentDO.unsafeDereference(), chromeObj);
|
||||||
|
|
||||||
|
// Similarly, viewing from chromeBox.
|
||||||
|
let mainFromChromeDO = chromeBoxDO.getProperty('mainObj');
|
||||||
|
do_check_eq(mainFromChromeDO, chromeBoxDO.makeDebuggeeValue(mainObj));
|
||||||
|
do_check_eq(mainFromChromeDO.getProperty('name'), 'mainObj');
|
||||||
|
do_check_eq(mainFromChromeDO.unsafeDereference(), mainObj);
|
||||||
|
|
||||||
|
let contentFromChromeDO = chromeBoxDO.getProperty('contentObj');
|
||||||
|
do_check_eq(contentFromChromeDO, chromeBoxDO.makeDebuggeeValue(contentObj));
|
||||||
|
do_check_eq(contentFromChromeDO.getProperty('name'), 'contentObj');
|
||||||
|
do_check_eq(contentFromChromeDO.unsafeDereference(), contentObj);
|
||||||
|
|
||||||
|
let chromeFromChromeDO = chromeBoxDO.getProperty('chromeObj');
|
||||||
|
do_check_eq(chromeFromChromeDO, chromeBoxDO.makeDebuggeeValue(chromeObj));
|
||||||
|
do_check_eq(chromeFromChromeDO.getProperty('name'), 'chromeObj');
|
||||||
|
do_check_eq(chromeFromChromeDO.unsafeDereference(), chromeObj);
|
||||||
|
}
|
|
@ -109,3 +109,4 @@ reason = bug 820380
|
||||||
[test_profiler_actor.js]
|
[test_profiler_actor.js]
|
||||||
skip-if = toolkit == "gonk"
|
skip-if = toolkit == "gonk"
|
||||||
reason = bug 820380
|
reason = bug 820380
|
||||||
|
[test_unsafeDereference.js]
|
||||||
|
|
Загрузка…
Ссылка в новой задаче