mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 943357 - Name argument of exportFunction should be optional. r=bholley
This commit is contained in:
parent
90193750e8
commit
a4dc9c6eea
@ -120,7 +120,7 @@ interface ScheduledGCCallback : nsISupports
|
||||
/**
|
||||
* interface of Components.utils
|
||||
*/
|
||||
[scriptable, uuid(ef621cac-c818-464a-9fb1-9a35731a7f32)]
|
||||
[scriptable, uuid(8dd4680f-4f06-4760-a147-292cb307662f)]
|
||||
interface nsIXPCComponents_Utils : nsISupports
|
||||
{
|
||||
|
||||
@ -338,12 +338,13 @@ interface nsIXPCComponents_Utils : nsISupports
|
||||
* algorithm.
|
||||
* The return value is the new forwarder function, wrapped into
|
||||
* the caller's compartment.
|
||||
* The 3rd argument is the name of the property that will
|
||||
* be set on the target scope, with the forwarder function as
|
||||
* the value.
|
||||
* The 3rd argument is an optional options object:
|
||||
* - defineAs: the name of the property that will
|
||||
* be set on the target scope, with
|
||||
* the forwarder function as the value.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
jsval exportFunction(in jsval vfunction, in jsval vscope, in jsval vname);
|
||||
jsval exportFunction(in jsval vfunction, in jsval vscope, [optional] in jsval voptions);
|
||||
|
||||
/*
|
||||
* To be called from JS only.
|
||||
|
@ -243,17 +243,20 @@ IsProxy(JSContext *cx, unsigned argc, jsval *vp)
|
||||
namespace xpc {
|
||||
|
||||
bool
|
||||
ExportFunction(JSContext *cx, HandleValue vfunction, HandleValue vscope, HandleValue vname,
|
||||
ExportFunction(JSContext *cx, HandleValue vfunction, HandleValue vscope, HandleValue voptions,
|
||||
MutableHandleValue rval)
|
||||
{
|
||||
if (!vscope.isObject() || !vfunction.isObject() || !vname.isString()) {
|
||||
bool hasOptions = !voptions.isUndefined();
|
||||
if (!vscope.isObject() || !vfunction.isObject() || (hasOptions && !voptions.isObject())) {
|
||||
JS_ReportError(cx, "Invalid argument");
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedObject funObj(cx, &vfunction.toObject());
|
||||
RootedObject targetScope(cx, &vscope.toObject());
|
||||
RootedString funName(cx, vname.toString());
|
||||
ExportOptions options(cx, hasOptions ? &voptions.toObject() : nullptr);
|
||||
if (hasOptions && !options.Parse())
|
||||
return false;
|
||||
|
||||
// We can only export functions to scopes those are transparent for us,
|
||||
// so if there is a security wrapper around targetScope we must throw.
|
||||
@ -268,11 +271,6 @@ ExportFunction(JSContext *cx, HandleValue vfunction, HandleValue vscope, HandleV
|
||||
return false;
|
||||
}
|
||||
|
||||
if (JS_GetStringLength(funName) == 0) {
|
||||
JS_ReportError(cx, "3rd argument should be a non-empty string");
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
// We need to operate in the target scope from here on, let's enter
|
||||
// its compartment.
|
||||
@ -285,16 +283,28 @@ ExportFunction(JSContext *cx, HandleValue vfunction, HandleValue vscope, HandleV
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedId id(cx, options.defineAs);
|
||||
if (JSID_IS_VOID(id)) {
|
||||
// If there wasn't any function name specified,
|
||||
// copy the name from the function being imported.
|
||||
JSFunction *fun = JS_GetObjectFunction(funObj);
|
||||
RootedString funName(cx, JS_GetFunctionId(fun));
|
||||
if (!funName)
|
||||
funName = JS_InternString(cx, "");
|
||||
|
||||
RootedValue vname(cx);
|
||||
vname.setString(funName);
|
||||
if (!JS_ValueToId(cx, vname, id.address()))
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(JSID_IS_STRING(id));
|
||||
|
||||
// The function forwarder will live in the target compartment. Since
|
||||
// this function will be referenced from its private slot, to avoid a
|
||||
// GC hazard, we must wrap it to the same compartment.
|
||||
if (!JS_WrapObject(cx, &funObj))
|
||||
return false;
|
||||
|
||||
RootedId id(cx);
|
||||
if (!JS_ValueToId(cx, vname, id.address()))
|
||||
return false;
|
||||
|
||||
// And now, let's create the forwarder function in the target compartment
|
||||
// for the function the be exported.
|
||||
if (!NewFunctionForwarder(cx, id, funObj, /* doclone = */ true, rval)) {
|
||||
@ -302,12 +312,16 @@ ExportFunction(JSContext *cx, HandleValue vfunction, HandleValue vscope, HandleV
|
||||
return false;
|
||||
}
|
||||
|
||||
// We have the forwarder function in the target compartment, now
|
||||
// we have to add it to the target scope as a property.
|
||||
if (!JS_DefinePropertyById(cx, targetScope, id, rval,
|
||||
JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JSPROP_ENUMERATE))
|
||||
return false;
|
||||
// We have the forwarder function in the target compartment. If
|
||||
// defineAs was set, we also need to define it as a property on
|
||||
// the target.
|
||||
if (!JSID_IS_VOID(options.defineAs)) {
|
||||
if (!JS_DefinePropertyById(cx, targetScope, id, rval,
|
||||
JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JSPROP_ENUMERATE)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally we have to re-wrap the exported function back to the caller compartment.
|
||||
@ -321,19 +335,19 @@ ExportFunction(JSContext *cx, HandleValue vfunction, HandleValue vscope, HandleV
|
||||
* Expected type of the arguments and the return value:
|
||||
* function exportFunction(function funToExport,
|
||||
* object targetScope,
|
||||
* string name)
|
||||
* [optional] object options)
|
||||
*/
|
||||
static bool
|
||||
ExportFunction(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.length() < 3) {
|
||||
JS_ReportError(cx, "Function requires at least 3 arguments");
|
||||
if (args.length() < 2) {
|
||||
JS_ReportError(cx, "Function requires at least 2 arguments");
|
||||
return false;
|
||||
}
|
||||
|
||||
return ExportFunction(cx, args[0], args[1],
|
||||
args[2], args.rval());
|
||||
RootedValue options(cx, args.length() > 2 ? args[2] : UndefinedValue());
|
||||
return ExportFunction(cx, args[0], args[1], options, args.rval());
|
||||
}
|
||||
} /* namespace xpc */
|
||||
|
||||
|
@ -3094,13 +3094,13 @@ nsXPCComponents_Utils::EvalInWindow(const nsAString &source, const Value &window
|
||||
/* jsval exportFunction(in jsval vfunction, in jsval vscope, in jsval vname); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::ExportFunction(const Value &vfunction, const Value &vscope,
|
||||
const Value &vname, JSContext *cx, Value *rval)
|
||||
const Value &voptions, JSContext *cx, Value *rval)
|
||||
{
|
||||
RootedValue rfunction(cx, vfunction);
|
||||
RootedValue rscope(cx, vscope);
|
||||
RootedValue rname(cx, vname);
|
||||
RootedValue roptions(cx, voptions);
|
||||
RootedValue res(cx);
|
||||
if (!xpc::ExportFunction(cx, rfunction, rscope, rname, &res))
|
||||
if (!xpc::ExportFunction(cx, rfunction, rscope, roptions, &res))
|
||||
return NS_ERROR_FAILURE;
|
||||
*rval = res;
|
||||
return NS_OK;
|
||||
|
@ -3461,6 +3461,19 @@ public:
|
||||
JS::RootedId defineAs;
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS ExportOptions : public OptionsBase {
|
||||
public:
|
||||
ExportOptions(JSContext *cx = xpc_GetSafeJSContext(),
|
||||
JSObject* options = nullptr)
|
||||
: OptionsBase(cx, options)
|
||||
, defineAs(cx, JSID_VOID)
|
||||
{ }
|
||||
|
||||
virtual bool Parse() { return ParseId("defineAs", &defineAs); };
|
||||
|
||||
JS::RootedId defineAs;
|
||||
};
|
||||
|
||||
JSObject *
|
||||
CreateGlobalObject(JSContext *cx, const JSClass *clasp, nsIPrincipal *principal,
|
||||
JS::CompartmentOptions& aOptions);
|
||||
|
@ -1,9 +1,9 @@
|
||||
function run_test() {
|
||||
var Cu = Components.utils;
|
||||
var epsb = new Cu.Sandbox(["http://example.com", "http://example.org"], { wantExportHelpers: true });
|
||||
subsb = new Cu.Sandbox("http://example.com", { wantGlobalProperties: ["XMLHttpRequest"] });
|
||||
subsb2 = new Cu.Sandbox("http://example.com", { wantGlobalProperties: ["XMLHttpRequest"] });
|
||||
xorigsb = new Cu.Sandbox("http://test.com");
|
||||
var subsb = new Cu.Sandbox("http://example.com", { wantGlobalProperties: ["XMLHttpRequest"] });
|
||||
var subsb2 = new Cu.Sandbox("http://example.com", { wantGlobalProperties: ["XMLHttpRequest"] });
|
||||
var xorigsb = new Cu.Sandbox("http://test.com");
|
||||
|
||||
epsb.subsb = subsb;
|
||||
epsb.xorigsb = xorigsb;
|
||||
@ -32,7 +32,7 @@ function run_test() {
|
||||
do_check_true(wasCalled);
|
||||
wasCalled = false;
|
||||
}
|
||||
exportFunction(funToExport, subsb, "imported");
|
||||
exportFunction(funToExport, subsb, { defineAs: "imported" });
|
||||
}.toSource() + ")()", epsb);
|
||||
|
||||
subsb.xrayed = Cu.evalInSandbox("(" + function () {
|
||||
@ -64,7 +64,7 @@ function run_test() {
|
||||
// not subsume the principal of the target.
|
||||
Cu.evalInSandbox("(" + function() {
|
||||
try{
|
||||
exportFunction(function(){}, this.xorigsb, "denied");
|
||||
exportFunction(function() {}, this.xorigsb, { defineAs: "denied" });
|
||||
do_check_true(false);
|
||||
} catch (e) {
|
||||
do_check_true(e.toString().indexOf('Permission denied') > -1);
|
||||
@ -74,8 +74,8 @@ function run_test() {
|
||||
// Let's create an object in the target scope and add privileged
|
||||
// function to it as a property.
|
||||
Cu.evalInSandbox("(" + function() {
|
||||
var newContentObject = createObjectIn(subsb, {defineAs:"importedObject"});
|
||||
exportFunction(funToExport, newContentObject, "privMethod");
|
||||
var newContentObject = createObjectIn(subsb, { defineAs: "importedObject" });
|
||||
exportFunction(funToExport, newContentObject, { defineAs: "privMethod" });
|
||||
}.toSource() + ")()", epsb);
|
||||
|
||||
Cu.evalInSandbox("(" + function () {
|
||||
@ -87,13 +87,27 @@ function run_test() {
|
||||
}.toSource() + ")()", epsb);
|
||||
|
||||
// exportFunction and createObjectIn should be available from Cu too.
|
||||
var newContentObject = Cu.createObjectIn(subsb, {defineAs:"importedObject2"});
|
||||
var newContentObject = Cu.createObjectIn(subsb, { defineAs: "importedObject2" });
|
||||
var wasCalled = false;
|
||||
Cu.exportFunction(function(arg){wasCalled = arg.wasCalled;}, newContentObject, "privMethod");
|
||||
Cu.exportFunction(function(arg) { wasCalled = arg.wasCalled; },
|
||||
newContentObject, { defineAs: "privMethod" });
|
||||
|
||||
Cu.evalInSandbox("(" + function () {
|
||||
importedObject2.privMethod({wasCalled: true});
|
||||
}.toSource() + ")()", subsb);
|
||||
|
||||
// 3rd argument of exportFunction should be optional.
|
||||
Cu.evalInSandbox("(" + function() {
|
||||
subsb.imported2 = exportFunction(funToExport, subsb);
|
||||
}.toSource() + ")()", epsb);
|
||||
|
||||
Cu.evalInSandbox("(" + function () {
|
||||
imported2(42, tobecloned, native, mixed);
|
||||
}.toSource() + ")()", subsb);
|
||||
|
||||
Cu.evalInSandbox("(" + function() {
|
||||
checkIfCalled();
|
||||
}.toSource() + ")()", epsb);
|
||||
|
||||
do_check_true(wasCalled, true);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user