コード例 #1
0
ファイル: IDBCursor.cpp プロジェクト: LordJZ/gecko-dev
void
IDBCursor::GetKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
                  ErrorResult& aRv)
{
  AssertIsOnOwningThread();

  MOZ_ASSERT(!mKey.IsUnset() || !mHaveValue);

  if (!mHaveValue) {
    aResult.setUndefined();
    return;
  }

  if (!mHaveCachedKey) {
    if (!mRooted) {
      mozilla::HoldJSObjects(this);
      mRooted = true;
    }

    aRv = mKey.ToJSVal(aCx, mCachedKey);
    if (NS_WARN_IF(aRv.Failed())) {
      return;
    }

    mHaveCachedKey = true;
  }

  JS::ExposeValueToActiveJS(mCachedKey);
  aResult.set(mCachedKey);
}
コード例 #2
0
ファイル: IDBCursor.cpp プロジェクト: LordJZ/gecko-dev
void
IDBCursor::GetPrimaryKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
                         ErrorResult& aRv)
{
  AssertIsOnOwningThread();

  if (!mHaveValue) {
    aResult.setUndefined();
    return;
  }

  if (!mHaveCachedPrimaryKey) {
    if (!mRooted) {
      mozilla::HoldJSObjects(this);
      mRooted = true;
    }

    const Key& key =
      (mType == Type_ObjectStore || mType == Type_ObjectStoreKey) ?
      mKey :
      mPrimaryKey;

    MOZ_ASSERT(!key.IsUnset());

    aRv = key.ToJSVal(aCx, mCachedPrimaryKey);
    if (NS_WARN_IF(aRv.Failed())) {
      return;
    }

    mHaveCachedPrimaryKey = true;
  }

  JS::ExposeValueToActiveJS(mCachedPrimaryKey);
  aResult.set(mCachedPrimaryKey);
}
コード例 #3
0
bool
ChromeObjectWrapper::get(JSContext *cx, JS::Handle<JSObject*> wrapper,
                         JS::Handle<JSObject*> receiver, JS::Handle<jsid> id,
                         JS::MutableHandle<JS::Value> vp)
{
    assertEnteredPolicy(cx, wrapper, id);
    vp.setUndefined();
    JSPropertyDescriptor desc;
    // Only call through to the get trap on the underlying object if we're
    // allowed to see the property, and if what we'll find is not on a standard
    // prototype.
    if (AllowedByBase(cx, wrapper, id, js::Wrapper::GET) &&
        !PropIsFromStandardPrototype(cx, wrapper, id))
    {
        // Call the get trap.
        if (!ChromeObjectWrapperBase::get(cx, wrapper, receiver, id, vp))
            return false;
        // If we found something, we're done.
        if (!vp.isUndefined())
            return true;
    }

    // If we have no proto, we're done.
    JSObject *wrapperProto;
    if (!JS_GetPrototype(cx, wrapper, &wrapperProto))
        return false;
    if (!wrapperProto)
        return true;

    // Try the prototype.
    MOZ_ASSERT(js::IsObjectInContextCompartment(wrapper, cx));
    return js::GetGeneric(cx, wrapperProto, receiver, id, vp.address());
}
コード例 #4
0
ファイル: IDBCursor.cpp プロジェクト: LordJZ/gecko-dev
void
IDBCursor::GetValue(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
                    ErrorResult& aRv)
{
  AssertIsOnOwningThread();
  MOZ_ASSERT(mType == Type_ObjectStore || mType == Type_Index);

  if (!mHaveValue) {
    aResult.setUndefined();
    return;
  }

  if (!mHaveCachedValue) {
    if (!mRooted) {
      mozilla::HoldJSObjects(this);
      mRooted = true;
    }

    JS::Rooted<JS::Value> val(aCx);
    if (NS_WARN_IF(!IDBObjectStore::DeserializeValue(aCx, mCloneInfo, &val))) {
      aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
      return;
    }

    IDBObjectStore::ClearCloneReadInfo(mCloneInfo);

    mCachedValue = val;
    mHaveCachedValue = true;
  }

  JS::ExposeValueToActiveJS(mCachedValue);
  aResult.set(mCachedValue);
}
コード例 #5
0
  bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue) override
  {
    aValue.setUndefined();

    mServer->mServices.RemoveElement(mService);

    return true;
  }
コード例 #6
0
ファイル: FileHelper.cpp プロジェクト: Wrichik1999/gecko-dev
nsresult
FileHelper::GetSuccessResult(JSContext* aCx,
                             JS::MutableHandle<JS::Value> aVal)
{
  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");

  aVal.setUndefined();
  return NS_OK;
}
コード例 #7
0
ファイル: BluetoothGatt.cpp プロジェクト: Mardak/tiles-dev
  bool
  ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
  {
    aValue.setUndefined();

    const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
    NS_ENSURE_TRUE(v.type() == BluetoothValue::Tuint32_t, false);

    aValue.setInt32(static_cast<int32_t>(v.get_uint32_t()));
    return true;
  }
コード例 #8
0
  virtual bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
  {
    aValue.setUndefined();

    const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
    if (v.type() != BluetoothValue::Tbool) {
      BT_WARNING("Not a boolean!");
      SetError(NS_LITERAL_STRING("BluetoothReplyTypeError"));
      return false;
    }

    aValue.setBoolean(v.get_bool());
    return true;
  }
コード例 #9
0
  virtual bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
  {
    aValue.setUndefined();

    const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
    if (v.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
      BT_WARNING("Not a BluetoothNamedValue array!");
      SetError(NS_LITERAL_STRING("BluetoothReplyTypeError"));
      return false;
    }

    const InfallibleTArray<BluetoothNamedValue>& values =
      v.get_ArrayOfBluetoothNamedValue();

    nsTArray<nsRefPtr<BluetoothDevice> > devices;
    for (uint32_t i = 0; i < values.Length(); i++) {
      const BluetoothValue properties = values[i].value();
      if (properties.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
        BT_WARNING("Not a BluetoothNamedValue array!");
        SetError(NS_LITERAL_STRING("BluetoothReplyTypeError"));
        return false;
      }
      nsRefPtr<BluetoothDevice> d =
        BluetoothDevice::Create(mAdapterPtr->GetOwner(),
                                mAdapterPtr->GetPath(),
                                properties);
      devices.AppendElement(d);
    }

    nsresult rv;
    nsIScriptContext* sc = mAdapterPtr->GetContextForEventHandlers(&rv);
    if (!sc) {
      BT_WARNING("Cannot create script context!");
      SetError(NS_LITERAL_STRING("BluetoothScriptContextError"));
      return false;
    }

    AutoPushJSContext cx(sc->GetNativeContext());
    JSObject* JsDevices = nullptr;
    rv = nsTArrayToJSArray(cx, devices, &JsDevices);
    if (!JsDevices) {
      BT_WARNING("Cannot create JS array!");
      SetError(NS_LITERAL_STRING("BluetoothError"));
      return false;
    }

    aValue.setObject(*JsDevices);
    return true;
  }
コード例 #10
0
ファイル: BluetoothManager.cpp プロジェクト: jedp/gecko-dev
  bool
  ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
  {
    aValue.setUndefined();

    const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
    if (v.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
      BT_WARNING("Not a BluetoothNamedValue array!");
      SetError(NS_LITERAL_STRING("BluetoothReplyTypeError"));
      return false;
    }

    if (!mManagerPtr->GetOwner()) {
      BT_WARNING("Bluetooth manager was disconnected from owner window.");

      // Stop to create adapter since owner window of Bluetooth manager was
      // gone. These is no need to create a DOMEvent target which has no owner
      // to reply to.
      return false;
    }

    const InfallibleTArray<BluetoothNamedValue>& values =
      v.get_ArrayOfBluetoothNamedValue();
    nsRefPtr<BluetoothAdapter> adapter =
      BluetoothAdapter::Create(mManagerPtr->GetOwner(), values);

    nsresult rv;
    nsIScriptContext* sc = mManagerPtr->GetContextForEventHandlers(&rv);
    if (!sc) {
      BT_WARNING("Cannot create script context!");
      SetError(NS_LITERAL_STRING("BluetoothScriptContextError"));
      return false;
    }

    AutoPushJSContext cx(sc->GetNativeContext());

    JS::Rooted<JSObject*> scope(cx, sc->GetWindowProxy());
    JSAutoCompartment ac(cx, scope);
    rv = nsContentUtils::WrapNative(cx, adapter, aValue);
    if (NS_FAILED(rv)) {
      BT_WARNING("Cannot create native object!");
      SetError(NS_LITERAL_STRING("BluetoothNativeObjectError"));
      return false;
    }

    return true;
  }
コード例 #11
0
ファイル: BluetoothAdapter.cpp プロジェクト: dadaa/gecko-dev
    virtual bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
    {
        aValue.setUndefined();

        const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
        if (v.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
            BT_WARNING("Not a BluetoothNamedValue array!");
            SetError(NS_LITERAL_STRING("BluetoothReplyTypeError"));
            return false;
        }

        const InfallibleTArray<BluetoothNamedValue>& values =
            v.get_ArrayOfBluetoothNamedValue();

        nsTArray<nsRefPtr<BluetoothDevice> > devices;
        for (uint32_t i = 0; i < values.Length(); i++) {
            const BluetoothValue properties = values[i].value();
            if (properties.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
                BT_WARNING("Not a BluetoothNamedValue array!");
                SetError(NS_LITERAL_STRING("BluetoothReplyTypeError"));
                return false;
            }
            nsRefPtr<BluetoothDevice> d =
                BluetoothDevice::Create(mAdapterPtr->GetOwner(),
                                        mAdapterPtr->GetPath(),
                                        properties);
            devices.AppendElement(d);
        }

        AutoJSAPI jsapi;
        if (!jsapi.Init(mAdapterPtr->GetOwner())) {
            BT_WARNING("Failed to initialise AutoJSAPI!");
            SetError(NS_LITERAL_STRING("BluetoothAutoJSAPIInitError"));
            return false;
        }
        JSContext* cx = jsapi.cx();
        JS::Rooted<JSObject*> JsDevices(cx);
        if (NS_FAILED(nsTArrayToJSArray(cx, devices, &JsDevices))) {
            BT_WARNING("Cannot create JS array!");
            SetError(NS_LITERAL_STRING("BluetoothError"));
            return false;
        }

        aValue.setObject(*JsDevices);
        return true;
    }
コード例 #12
0
  bool
  ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
  {
    aValue.setUndefined();

    const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
    NS_ENSURE_TRUE(v.type() == BluetoothValue::TArrayOfuint8_t, false);

    AutoJSAPI jsapi;
    NS_ENSURE_TRUE(jsapi.Init(mCharacteristic->GetParentObject()), false);

    JSContext* cx = jsapi.cx();
    if (!ToJSValue(cx, v.get_ArrayOfuint8_t(), aValue)) {
      JS_ClearPendingException(cx);
      return false;
    }

    return true;
  }
コード例 #13
0
/* static */ void
ThreadSafeChromeUtils::NondeterministicGetWeakSetKeys(GlobalObject& aGlobal,
                                                      JS::Handle<JS::Value> aSet,
                                                      JS::MutableHandle<JS::Value> aRetval,
                                                      ErrorResult& aRv)
{
  if (!aSet.isObject()) {
    aRetval.setUndefined();
  } else {
    JSContext* cx = aGlobal.Context();
    JS::Rooted<JSObject*> objRet(cx);
    JS::Rooted<JSObject*> setObj(cx, &aSet.toObject());
    if (!JS_NondeterministicGetWeakSetKeys(cx, setObj, &objRet)) {
      aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    } else {
      aRetval.set(objRet ? JS::ObjectValue(*objRet) : JS::UndefinedValue());
    }
  }
}
コード例 #14
0
ファイル: BluetoothDevice.cpp プロジェクト: arroway/gecko-dev
  bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
  {
    aValue.setUndefined();

    const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
    NS_ENSURE_TRUE(v.type() == BluetoothValue::TArrayOfnsString, false);
    const InfallibleTArray<nsString>& uuids = v.get_ArrayOfnsString();

    AutoJSAPI jsapi;
    NS_ENSURE_TRUE(jsapi.Init(mDevice->GetParentObject()), false);

    JSContext* cx = jsapi.cx();
    if (!ToJSValue(cx, uuids, aValue)) {
      BT_WARNING("Cannot create JS array!");
      JS_ClearPendingException(cx);
      return false;
    }

    return true;
  }
コード例 #15
0
  bool
  ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
  {
    /**
     * Unwrap BluetoothReply.BluetoothReplySuccess.BluetoothValue =
     *   BluetoothNamedValue[]
     *     |
     *     |__ BluetoothNamedValue =
     *     |     {"Adapter", BluetoothValue = BluetoothNamedValue[]}
     *     |
     *     |__ BluetoothNamedValue =
     *     |     {"Adapter", BluetoothValue = BluetoothNamedValue[]}
     *     ...
     */

    // Extract the array of all adapters' properties
    const BluetoothValue& adaptersProperties =
      mReply->get_BluetoothReplySuccess().value();
    NS_ENSURE_TRUE(adaptersProperties.type() ==
                   BluetoothValue::TArrayOfBluetoothNamedValue, false);

    const InfallibleTArray<BluetoothNamedValue>& adaptersPropertiesArray =
      adaptersProperties.get_ArrayOfBluetoothNamedValue();
    BT_API2_LOGR("GetAdaptersTask: len[%d]", adaptersPropertiesArray.Length());

    // Append a BluetoothAdapter into adapters array for each properties array
    uint32_t numAdapters = adaptersPropertiesArray.Length();
    for (uint32_t i = 0; i < numAdapters; i++) {
      MOZ_ASSERT(adaptersPropertiesArray[i].name().EqualsLiteral("Adapter"));

      const BluetoothValue& properties = adaptersPropertiesArray[i].value();
      mManager->AppendAdapter(properties);
    }

    aValue.setUndefined();
    return true;
  }
コード例 #16
0
ファイル: BluetoothAdapter.cpp プロジェクト: LordJZ/gecko-dev
  bool
  ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
  {
    aValue.setUndefined();

    AutoJSAPI jsapi;
    NS_ENSURE_TRUE(jsapi.Init(mAdapter->GetParentObject()), false);
    JSContext* cx = jsapi.cx();

    /**
     * Create a new discovery handle and wrap it to return. Each
     * discovery handle is one-time-use only.
     */
    nsRefPtr<BluetoothDiscoveryHandle> discoveryHandle =
      BluetoothDiscoveryHandle::Create(mAdapter->GetParentObject());
    if (!ToJSValue(cx, discoveryHandle, aValue)) {
      JS_ClearPendingException(cx);
      return false;
    }

    // Set the created discovery handle as the one in use.
    mAdapter->SetDiscoveryHandleInUse(discoveryHandle);
    return true;
  }
コード例 #17
0
ファイル: nsJSUtils.cpp プロジェクト: bebef1987/gecko-dev
nsresult
nsJSUtils::EvaluateString(JSContext* aCx,
                          JS::SourceBufferHolder& aSrcBuf,
                          JS::Handle<JSObject*> aScopeObject,
                          JS::CompileOptions& aCompileOptions,
                          const EvaluateOptions& aEvaluateOptions,
                          JS::MutableHandle<JS::Value> aRetValue,
                          void **aOffThreadToken)
{
  PROFILER_LABEL("nsJSUtils", "EvaluateString",
    js::ProfileEntry::Category::JS);

  MOZ_ASSERT_IF(aCompileOptions.versionSet,
                aCompileOptions.version != JSVERSION_UNKNOWN);
  MOZ_ASSERT_IF(aEvaluateOptions.coerceToString, aEvaluateOptions.needResult);
  MOZ_ASSERT_IF(!aEvaluateOptions.reportUncaught, aEvaluateOptions.needResult);
  MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
  MOZ_ASSERT(aSrcBuf.get());

  // Unfortunately, the JS engine actually compiles scripts with a return value
  // in a different, less efficient way.  Furthermore, it can't JIT them in many
  // cases.  So we need to be explicitly told whether the caller cares about the
  // return value.  Callers can do this by calling the other overload of
  // EvaluateString() which calls this function with aEvaluateOptions.needResult
  // set to false.
  aRetValue.setUndefined();

  JS::ExposeObjectToActiveJS(aScopeObject);
  nsAutoMicroTask mt;
  nsresult rv = NS_OK;

  bool ok = false;
  nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
  NS_ENSURE_TRUE(ssm->ScriptAllowed(js::GetGlobalForObjectCrossCompartment(aScopeObject)), NS_OK);

  mozilla::Maybe<AutoDontReportUncaught> dontReport;
  if (!aEvaluateOptions.reportUncaught) {
    // We need to prevent AutoLastFrameCheck from reporting and clearing
    // any pending exceptions.
    dontReport.emplace(aCx);
  }

  // Scope the JSAutoCompartment so that we can later wrap the return value
  // into the caller's cx.
  {
    JSAutoCompartment ac(aCx, aScopeObject);

    JS::Rooted<JSObject*> rootedScope(aCx, aScopeObject);
    if (aOffThreadToken) {
      JS::Rooted<JSScript*>
        script(aCx, JS::FinishOffThreadScript(aCx, JS_GetRuntime(aCx), *aOffThreadToken));
      *aOffThreadToken = nullptr; // Mark the token as having been finished.
      if (script) {
        if (aEvaluateOptions.needResult) {
          ok = JS_ExecuteScript(aCx, rootedScope, script, aRetValue);
        } else {
          ok = JS_ExecuteScript(aCx, rootedScope, script);
        }
      } else {
        ok = false;
      }
    } else {
      if (aEvaluateOptions.needResult) {
        ok = JS::Evaluate(aCx, rootedScope, aCompileOptions,
                          aSrcBuf, aRetValue);
      } else {
        ok = JS::Evaluate(aCx, rootedScope, aCompileOptions,
                          aSrcBuf);
      }
    }

    if (ok && aEvaluateOptions.coerceToString && !aRetValue.isUndefined()) {
      JS::Rooted<JS::Value> value(aCx, aRetValue);
      JSString* str = JS::ToString(aCx, value);
      ok = !!str;
      aRetValue.set(ok ? JS::StringValue(str) : JS::UndefinedValue());
    }
  }

  if (!ok) {
    if (aEvaluateOptions.reportUncaught) {
      ReportPendingException(aCx);
      if (aEvaluateOptions.needResult) {
        aRetValue.setUndefined();
      }
    } else {
      rv = JS_IsExceptionPending(aCx) ? NS_ERROR_FAILURE
                                      : NS_ERROR_OUT_OF_MEMORY;
      JS::Rooted<JS::Value> exn(aCx);
      JS_GetPendingException(aCx, &exn);
      if (aEvaluateOptions.needResult) {
        aRetValue.set(exn);
      }
      JS_ClearPendingException(aCx);
    }
  }

  // Wrap the return value into whatever compartment aCx was in.
  if (aEvaluateOptions.needResult) {
    JS::Rooted<JS::Value> v(aCx, aRetValue);
    if (!JS_WrapValue(aCx, &v)) {
      return NS_ERROR_OUT_OF_MEMORY;
    }
    aRetValue.set(v);
  }
  return rv;
}
コード例 #18
0
nsresult
nsJSUtils::EvaluateString(JSContext* aCx,
                          JS::SourceBufferHolder& aSrcBuf,
                          JS::Handle<JSObject*> aEvaluationGlobal,
                          JS::CompileOptions& aCompileOptions,
                          const EvaluateOptions& aEvaluateOptions,
                          JS::MutableHandle<JS::Value> aRetValue,
                          void **aOffThreadToken)
{
  PROFILER_LABEL("nsJSUtils", "EvaluateString",
    js::ProfileEntry::Category::JS);

  MOZ_ASSERT(JS::ContextOptionsRef(aCx).autoJSAPIOwnsErrorReporting(),
             "Caller must own error reporting");
  MOZ_ASSERT_IF(aCompileOptions.versionSet,
                aCompileOptions.version != JSVERSION_UNKNOWN);
  MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
  MOZ_ASSERT(aSrcBuf.get());
  MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(aEvaluationGlobal) ==
             aEvaluationGlobal);
  MOZ_ASSERT_IF(aOffThreadToken, aCompileOptions.noScriptRval);
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(nsContentUtils::IsInMicroTask());

  // Unfortunately, the JS engine actually compiles scripts with a return value
  // in a different, less efficient way.  Furthermore, it can't JIT them in many
  // cases.  So we need to be explicitly told whether the caller cares about the
  // return value.  Callers can do this by calling the other overload of
  // EvaluateString() which calls this function with
  // aCompileOptions.noScriptRval set to true.
  aRetValue.setUndefined();

  nsresult rv = NS_OK;

  nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
  NS_ENSURE_TRUE(ssm->ScriptAllowed(aEvaluationGlobal), NS_OK);

  bool ok = true;
  // Scope the JSAutoCompartment so that we can later wrap the return value
  // into the caller's cx.
  {
    JSAutoCompartment ac(aCx, aEvaluationGlobal);

    // Now make sure to wrap the scope chain into the right compartment.
    JS::AutoObjectVector scopeChain(aCx);
    if (!scopeChain.reserve(aEvaluateOptions.scopeChain.length())) {
      return NS_ERROR_OUT_OF_MEMORY;
    }

    for (size_t i = 0; i < aEvaluateOptions.scopeChain.length(); ++i) {
      JS::ExposeObjectToActiveJS(aEvaluateOptions.scopeChain[i]);
      scopeChain.infallibleAppend(aEvaluateOptions.scopeChain[i]);
      if (!JS_WrapObject(aCx, scopeChain[i])) {
        ok = false;
        break;
      }
    }

    if (ok && aOffThreadToken) {
      JS::Rooted<JSScript*>
        script(aCx, JS::FinishOffThreadScript(aCx, JS_GetRuntime(aCx), *aOffThreadToken));
      *aOffThreadToken = nullptr; // Mark the token as having been finished.
      if (script) {
        ok = JS_ExecuteScript(aCx, scopeChain, script);
      } else {
        ok = false;
      }
    } else if (ok) {
      ok = JS::Evaluate(aCx, scopeChain, aCompileOptions, aSrcBuf, aRetValue);
    }
  }

  if (!ok) {
    if (JS_IsExceptionPending(aCx)) {
      rv = NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW;
    } else {
      rv = NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE;
    }

    if (!aCompileOptions.noScriptRval) {
      aRetValue.setUndefined();
    }
  }

  // Wrap the return value into whatever compartment aCx was in.
  if (ok && !aCompileOptions.noScriptRval) {
    if (!JS_WrapValue(aCx, aRetValue)) {
      return NS_ERROR_OUT_OF_MEMORY;
    }
  }
  return rv;
}