Bug 927765 - Options for createObjectIn. r=bholley
authorGabor Krizsanits <gkrizsanits@mozilla.com>
Tue, 22 Oct 2013 14:23:41 +0200
changeset 151674 595c7dc7a02a0645322728e980dc539f05bacc69
parent 151673 7f3af7b5ab295dddbfb103a305d878d61e987623
child 151675 9916cc731d15ebfdaf2714c51c40a402294044f1
push id25504
push userphilringnalda@gmail.com
push dateWed, 23 Oct 2013 02:50:41 +0000
treeherdermozilla-central@21d97baadc05 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs927765
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 927765 - Options for createObjectIn. r=bholley
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/xpcprivate.h
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -1248,23 +1248,26 @@ GetExpandedPrincipal(JSContext *cx, Hand
   result.forget(out);
   return true;
 }
 
 /*
  * Helper that tries to get a property form the options object.
  */
 bool
-OptionsBase::ParseValue(const char *name, MutableHandleValue prop, bool *found)
+OptionsBase::ParseValue(const char *name, MutableHandleValue prop, bool *aFound)
 {
-    MOZ_ASSERT(found);
-    bool ok = JS_HasProperty(mCx, mObject, name, found);
+    bool found;
+    bool ok = JS_HasProperty(mCx, mObject, name, &found);
     NS_ENSURE_TRUE(ok, false);
 
-    if (!*found)
+    if (aFound)
+        *aFound = found;
+
+    if (!found)
         return true;
 
     return JS_GetProperty(mCx, mObject, name, prop);
 }
 
 /*
  * Helper that tries to get a boolean property form the options object.
  */
@@ -1332,16 +1335,33 @@ OptionsBase::ParseString(const char *nam
 
     char *tmp = JS_EncodeString(mCx, value.toString());
     NS_ENSURE_TRUE(tmp, false);
     prop.Adopt(tmp, strlen(tmp));
     return true;
 }
 
 /*
+ * Helper that tries to get jsid property form the options object.
+ */
+bool
+OptionsBase::ParseId(const char *name, MutableHandleId prop)
+{
+    RootedValue value(mCx);
+    bool found;
+    bool ok = ParseValue(name, &value, &found);
+    NS_ENSURE_TRUE(ok, false);
+
+    if (!found)
+        return true;
+
+    return JS_ValueToId(mCx, value, prop.address());
+}
+
+/*
  * Helper that tries to get a list of DOM constructors and other helpers from the options object.
  */
 bool
 SandboxOptions::ParseGlobalProperties()
 {
     RootedValue value(mCx);
     bool found;
     bool ok = ParseValue("wantGlobalProperties", &value, &found);
@@ -1364,25 +1384,24 @@ SandboxOptions::ParseGlobalProperties()
 }
 
 /*
  * Helper that parsing the sandbox options object (from) and sets the fields of the incoming options struct (options).
  */
 bool
 SandboxOptions::Parse()
 {
-    bool found;
     return ParseObject("sandboxPrototype", &proto) &&
            ParseBoolean("wantXrays", &wantXrays) &&
            ParseBoolean("wantComponents", &wantComponents) &&
            ParseBoolean("wantExportHelpers", &wantExportHelpers) &&
            ParseString("sandboxName", sandboxName) &&
            ParseObject("sameZoneAs", &sameZoneAs) &&
            ParseGlobalProperties() &&
-           ParseValue("metadata", &metadata, &found);
+           ParseValue("metadata", &metadata);
 }
 
 static nsresult
 AssembleSandboxMemoryReporterName(JSContext *cx, nsCString &sandboxName)
 {
     // Use a default name when the caller did not provide a sandboxName.
     if (sandboxName.IsEmpty())
         sandboxName = NS_LITERAL_CSTRING("[anonymous sandbox]");
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -3006,39 +3006,62 @@ nsXPCComponents_Utils::GetGlobalForObjec
     // Outerize if necessary.
     if (JSObjectOp outerize = js::GetObjectClass(obj)->ext.outerObject)
       *retval = OBJECT_TO_JSVAL(outerize(cx, obj));
 
     return NS_OK;
 }
 
 /* jsval createObjectIn(in jsval vobj); */
-NS_IMETHODIMP
-nsXPCComponents_Utils::CreateObjectIn(const Value &vobj, JSContext *cx, Value *rval)
+bool
+xpc::CreateObjectIn(JSContext *cx, HandleValue vobj, CreateObjectOptions &options,
+                    MutableHandleValue rval)
 {
-    if (!cx)
-        return NS_ERROR_FAILURE;
-
-    // first argument must be an object
-    if (vobj.isPrimitive())
-        return NS_ERROR_XPC_BAD_CONVERT_JS;
-
-    RootedObject scope(cx, js::UncheckedUnwrap(&vobj.toObject()));
+    if (!vobj.isObject()) {
+        JS_ReportError(cx, "Expected an object as the target scope");
+        return false;
+    }
+
+    RootedObject scope(cx, js::CheckedUnwrap(&vobj.toObject()));
+    if (!scope) {
+        JS_ReportError(cx, "Permission denied to create object in the target scope");
+        return false;
+    }
     RootedObject obj(cx);
     {
         JSAutoCompartment ac(cx, scope);
         obj = JS_NewObject(cx, nullptr, nullptr, scope);
         if (!obj)
-            return NS_ERROR_FAILURE;
+            return false;
+
+        if (!JSID_IS_VOID(options.defineAs) &&
+            !JS_DefinePropertyById(cx, scope, options.defineAs, ObjectValue(*obj),
+                                       JS_PropertyStub, JS_StrictPropertyStub,
+                                       JSPROP_ENUMERATE))
+            return false;
     }
 
     if (!JS_WrapObject(cx, &obj))
+        return false;
+
+    rval.setObject(*obj);
+    return true;
+}
+
+/* jsval createObjectIn(in jsval vobj); */
+NS_IMETHODIMP
+nsXPCComponents_Utils::CreateObjectIn(const Value &vobj, JSContext *cx, Value *rval)
+{
+    CreateObjectOptions options;
+    RootedValue rvobj(cx, vobj);
+    RootedValue res(cx);
+    if (!xpc::CreateObjectIn(cx, rvobj, options, &res))
         return NS_ERROR_FAILURE;
 
-    *rval = ObjectValue(*obj);
+    *rval = res;
     return NS_OK;
 }
 
 /* jsval createObjectIn(in jsval vobj); */
 NS_IMETHODIMP
 nsXPCComponents_Utils::CreateArrayIn(const Value &vobj, JSContext *cx, Value *rval)
 {
     if (!cx)
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -3622,20 +3622,21 @@ public:
                 JS::HandleObject options = JS::NullPtr())
         : mCx(cx)
         , mObject(cx, options)
     { }
 
     virtual bool Parse() = 0;
 
 protected:
-    bool ParseValue(const char *name, JS::MutableHandleValue prop, bool *found);
+    bool ParseValue(const char *name, JS::MutableHandleValue prop, bool *found = nullptr);
     bool ParseBoolean(const char *name, bool *prop);
     bool ParseObject(const char *name, JS::MutableHandleObject prop);
     bool ParseString(const char *name, nsCString &prop);
+    bool ParseId(const char* name, JS::MutableHandleId id);
 
     JSContext *mCx;
     JS::RootedObject mObject;
 };
 
 class MOZ_STACK_CLASS SandboxOptions : public OptionsBase {
 public:
     SandboxOptions(JSContext *cx = xpc_GetSafeJSContext(),
@@ -3659,16 +3660,29 @@ public:
     JS::RootedObject sameZoneAs;
     GlobalProperties globalProperties;
     JS::RootedValue metadata;
 
 protected:
     bool ParseGlobalProperties();
 };
 
+class MOZ_STACK_CLASS CreateObjectOptions : public OptionsBase {
+public:
+    CreateObjectOptions(JSContext *cx = xpc_GetSafeJSContext(),
+                        JS::HandleObject options = JS::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);
 
 // Helper for creating a sandbox object to use for evaluating
 // untrusted code completely separated from all other code in the
 // system using EvalInSandbox(). Takes the JSContext on which to
 // do setup etc on, puts the sandbox object in *vp (which must be
@@ -3701,16 +3715,20 @@ EvalInSandbox(JSContext *cx, JS::HandleO
 nsresult
 GetSandboxMetadata(JSContext *cx, JS::HandleObject sandboxArg,
                    JS::MutableHandleValue rval);
 
 nsresult
 SetSandboxMetadata(JSContext *cx, JS::HandleObject sandboxArg,
                    JS::HandleValue metadata);
 
+bool
+CreateObjectIn(JSContext *cx, JS::HandleValue vobj, CreateObjectOptions &options,
+               JS::MutableHandleValue rval);
+
 } /* namespace xpc */
 
 
 /***************************************************************************/
 // Inlined utilities.
 
 inline bool
 xpc_ForcePropertyResolve(JSContext* cx, JSObject* obj, jsid id);