Example #1
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_IF(aEvaluateOptions.coerceToString, !aCompileOptions.noScriptRval);
  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 && 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 (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;
}
// Define a shadowing property on |this| for the XBL field defined by the
// contents of the callee's reserved slots.  If the property was defined,
// *installed will be true, and idp will be set to the property name that was
// defined.
static JSBool
InstallXBLField(JSContext* cx,
                JS::Handle<JSObject*> callee, JS::Handle<JSObject*> thisObj,
                JS::MutableHandle<jsid> idp, bool* installed)
{
  *installed = false;

  // First ensure |this| is a reasonable XBL bound node.
  //
  // FieldAccessorGuard already determined whether |thisObj| was acceptable as
  // |this| in terms of not throwing a TypeError.  Assert this for good measure.
  MOZ_ASSERT(ValueHasISupportsPrivate(JS::ObjectValue(*thisObj)));

  // But there are some cases where we must accept |thisObj| but not install a
  // property on it, or otherwise touch it.  Hence this split of |this|-vetting
  // duties.
  nsISupports* native =
    nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, thisObj);
  if (!native) {
    // Looks like whatever |thisObj| is it's not our nsIContent.  It might well
    // be the proto our binding installed, however, where the private is the
    // nsXBLDocumentInfo, so just baul out quietly.  Do NOT throw an exception
    // here.
    //
    // We could make this stricter by checking the class maybe, but whatever.
    return true;
  }

  nsCOMPtr<nsIContent> xblNode = do_QueryInterface(native);
  if (!xblNode) {
    xpc::Throw(cx, NS_ERROR_UNEXPECTED);
    return false;
  }

  // Now that |this| is okay, actually install the field.

  // Because of the possibility (due to XBL binding inheritance, because each
  // XBL binding lives in its own global object) that |this| might be in a
  // different compartment from the callee (not to mention that this method can
  // be called with an arbitrary |this| regardless of how insane XBL is), and
  // because in this method we've entered |this|'s compartment (see in
  // Field[GS]etter where we attempt a cross-compartment call), we must enter
  // the callee's compartment to access its reserved slots.
  nsXBLPrototypeBinding* protoBinding;
  nsDependentJSString fieldName;
  {
    JSAutoCompartment ac(cx, callee);

    JS::Rooted<JSObject*> xblProto(cx);
    xblProto = &js::GetFunctionNativeReserved(callee, XBLPROTO_SLOT).toObject();

    JS::Rooted<JS::Value> name(cx, js::GetFunctionNativeReserved(callee, FIELD_SLOT));
    JSFlatString* fieldStr = JS_ASSERT_STRING_IS_FLAT(name.toString());
    fieldName.init(fieldStr);

    MOZ_ALWAYS_TRUE(JS_ValueToId(cx, name, idp.address()));

    // If a separate XBL scope is being used, the callee is not same-compartment
    // with the xbl prototype, and the object is a cross-compartment wrapper.
    xblProto = js::UncheckedUnwrap(xblProto);
    JSAutoCompartment ac2(cx, xblProto);
    JS::Value slotVal = ::JS_GetReservedSlot(xblProto, 0);
    protoBinding = static_cast<nsXBLPrototypeBinding*>(slotVal.toPrivate());
    MOZ_ASSERT(protoBinding);
  }

  nsXBLProtoImplField* field = protoBinding->FindField(fieldName);
  MOZ_ASSERT(field);

  // This mirrors code in nsXBLProtoImpl::InstallImplementation
  nsIScriptGlobalObject* global = xblNode->OwnerDoc()->GetScriptGlobalObject();
  if (!global) {
    return true;
  }

  nsCOMPtr<nsIScriptContext> context = global->GetContext();
  if (!context) {
    return true;
  }

  nsresult rv = field->InstallField(context, thisObj, protoBinding->DocURI(),
                                    installed);
  if (NS_SUCCEEDED(rv)) {
    return true;
  }

  if (!::JS_IsExceptionPending(cx)) {
    xpc::Throw(cx, rv);
  }
  return false;
}
NS_IMETHODIMP
MobileMessageManager::Send(JS::Handle<JS::Value> aNumber,
                           const nsAString& aMessage,
                           JS::Handle<JS::Value> aSendParams,
                           JSContext* aCx,
                           uint8_t aArgc,
                           JS::MutableHandle<JS::Value> aReturn)
{
  if (!aNumber.isString() && !JS_IsArrayObject(aCx, aNumber)) {
    return NS_ERROR_INVALID_ARG;
  }

  nsresult rv;
  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
  NS_ENSURE_SUCCESS(rv, rv);
  NS_ENSURE_STATE(sc);

  JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));

  mozilla::Maybe<JSAutoCompartment> ac;
  if (!global) {
    global = sc->GetWindowProxy();
    ac.construct(aCx, global);
  }

  nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
  NS_ENSURE_TRUE(smsService, NS_ERROR_FAILURE);

  // Use the default one unless |aSendParams.serviceId| is available.
  uint32_t serviceId;
  rv = smsService->GetSmsDefaultServiceId(&serviceId);
  NS_ENSURE_SUCCESS(rv, rv);

  if (aArgc == 1) {
    JS::Rooted<JS::Value> param(aCx, aSendParams);
    RootedDictionary<SmsSendParameters> sendParams(aCx);
    if (!sendParams.Init(aCx, param)) {
      return NS_ERROR_TYPE_ERR;
    }
    if (sendParams.mServiceId.WasPassed()) {
      serviceId = sendParams.mServiceId.Value();
    }
  }

  if (aNumber.isString()) {
    JS::Rooted<JSString*> str(aCx, aNumber.toString());
    return Send(aCx, global, serviceId, str, aMessage, aReturn.address());
  }

  // Must be an array then.
  JS::Rooted<JSObject*> numbers(aCx, &aNumber.toObject());

  uint32_t size;
  if (!JS_GetArrayLength(aCx, numbers, &size)) {
    return NS_ERROR_FAILURE;
  }

  JS::AutoValueVector requests(aCx);
  if (!requests.resize(size)) {
    return NS_ERROR_FAILURE;
  }

  JS::Rooted<JS::Value> number(aCx);
  JS::Rooted<JSString*> str(aCx);
  for (uint32_t i = 0; i < size; ++i) {
    if (!JS_GetElement(aCx, numbers, i, &number)) {
      return NS_ERROR_INVALID_ARG;
    }

    str = JS::ToString(aCx, number);
    if (!str) {
      return NS_ERROR_FAILURE;
    }

    nsresult rv = Send(aCx, global, serviceId, str, aMessage, &requests[i]);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  JS::Rooted<JSObject*> obj(aCx);
  obj = JS_NewArrayObject(aCx, requests);
  if (!obj) {
    return NS_ERROR_FAILURE;
  }

  aReturn.setObject(*obj);
  return NS_OK;
}
bool
WindowNamedPropertiesHandler::getOwnPropertyDescriptor(JSContext* aCx,
                                                       JS::Handle<JSObject*> aProxy,
                                                       JS::Handle<jsid> aId,
                                                       JS::MutableHandle<JSPropertyDescriptor> aDesc,
                                                       unsigned aFlags)
{
  if (!JSID_IS_STRING(aId)) {
    // Nothing to do if we're resolving a non-string property.
    return true;
  }

  JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, aProxy));
  if (HasPropertyOnPrototype(aCx, aProxy, aId)) {
    return true;
  }

  nsDependentJSString str(aId);

  // Grab the DOM window.
  XPCWrappedNative* wrapper = XPCWrappedNative::Get(global);
  nsCOMPtr<nsPIDOMWindow> piWin = do_QueryWrappedNative(wrapper);
  MOZ_ASSERT(piWin);
  nsGlobalWindow* win = static_cast<nsGlobalWindow*>(piWin.get());
  if (win->GetLength() > 0) {
    nsCOMPtr<nsIDOMWindow> childWin = win->GetChildWindow(str);
    if (childWin && ShouldExposeChildWindow(str, childWin)) {
      // We found a subframe of the right name. Shadowing via |var foo| in
      // global scope is still allowed, since |var| only looks up |own|
      // properties. But unqualified shadowing will fail, per-spec.
      JS::Rooted<JS::Value> v(aCx);
      if (!WrapObject(aCx, aProxy, childWin, &v)) {
        return false;
      }
      aDesc.object().set(aProxy);
      aDesc.value().set(v);
      aDesc.setAttributes(JSPROP_ENUMERATE);
      return true;
    }
  }

  // The rest of this function is for HTML documents only.
  nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(win->GetExtantDoc());
  if (!htmlDoc) {
    return true;
  }
  nsHTMLDocument* document = static_cast<nsHTMLDocument*>(htmlDoc.get());

  Element* element = document->GetElementById(str);
  if (element) {
    JS::Rooted<JS::Value> v(aCx);
    if (!WrapObject(aCx, aProxy, element, &v)) {
      return false;
    }
    aDesc.object().set(aProxy);
    aDesc.value().set(v);
    aDesc.setAttributes(JSPROP_ENUMERATE);
    return true;
  }

  nsWrapperCache* cache;
  nsISupports* result = document->ResolveName(str, &cache);
  if (!result) {
    return true;
  }

  JS::Rooted<JS::Value> v(aCx);
  if (!WrapObject(aCx, aProxy, result, cache, nullptr, &v)) {
    return false;
  }
  aDesc.object().set(aProxy);
  aDesc.value().set(v);
  aDesc.setAttributes(JSPROP_ENUMERATE);
  return true;
}
Example #5
0
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;
}
NS_IMETHODIMP
MmsMessage::GetAttachments(JSContext* aCx, JS::MutableHandle<JS::Value> aAttachments)
{
  uint32_t length = mAttachments.Length();

  JS::Rooted<JSObject*> attachments(
    aCx, JS_NewArrayObject(aCx, length));
  NS_ENSURE_TRUE(attachments, NS_ERROR_OUT_OF_MEMORY);

  for (uint32_t i = 0; i < length; ++i) {
    const Attachment &attachment = mAttachments[i];

    JS::Rooted<JSObject*> attachmentObj(aCx, JS_NewPlainObject(aCx));
    NS_ENSURE_TRUE(attachmentObj, NS_ERROR_OUT_OF_MEMORY);

    JS::Rooted<JSString*> tmpJsStr(aCx);

    // Get |attachment.mId|.
    tmpJsStr = JS_NewUCStringCopyN(aCx,
                                   attachment.id.get(),
                                   attachment.id.Length());
    NS_ENSURE_TRUE(tmpJsStr, NS_ERROR_OUT_OF_MEMORY);

    if (!JS_DefineProperty(aCx, attachmentObj, "id", tmpJsStr, JSPROP_ENUMERATE)) {
      return NS_ERROR_FAILURE;
    }

    // Get |attachment.mLocation|.
    tmpJsStr = JS_NewUCStringCopyN(aCx,
                                   attachment.location.get(),
                                   attachment.location.Length());
    NS_ENSURE_TRUE(tmpJsStr, NS_ERROR_OUT_OF_MEMORY);

    if (!JS_DefineProperty(aCx, attachmentObj, "location", tmpJsStr, JSPROP_ENUMERATE)) {
      return NS_ERROR_FAILURE;
    }

    // Get |attachment.mContent|.

    // Duplicating the File with the correct parent object.
    nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
    MOZ_ASSERT(global);
    nsRefPtr<File> newBlob = new File(global, attachment.content->Impl());

    JS::Rooted<JS::Value> val(aCx);
    if (!GetOrCreateDOMReflector(aCx, newBlob, &val)) {
      return NS_ERROR_FAILURE;
    }

    if (!JS_DefineProperty(aCx, attachmentObj, "content", val, JSPROP_ENUMERATE)) {
      return NS_ERROR_FAILURE;
    }

    if (!JS_DefineElement(aCx, attachments, i, attachmentObj, JSPROP_ENUMERATE)) {
      return NS_ERROR_FAILURE;
    }
  }

  aAttachments.setObject(*attachments);
  return NS_OK;
}
nsresult
nsXBLPrototypeHandler::EnsureEventHandler(AutoJSAPI& jsapi, nsIAtom* aName,
                                          JS::MutableHandle<JSObject*> aHandler)
{
  JSContext* cx = jsapi.cx();

  // Check to see if we've already compiled this
  JS::Rooted<JSObject*> globalObject(cx, JS::CurrentGlobalOrNull(cx));
  nsCOMPtr<nsPIDOMWindowInner> pWindow = xpc::WindowOrNull(globalObject)->AsInner();
  if (pWindow) {
    JS::Rooted<JSObject*> cachedHandler(cx, pWindow->GetCachedXBLPrototypeHandler(this));
    if (cachedHandler) {
      JS::ExposeObjectToActiveJS(cachedHandler);
      aHandler.set(cachedHandler);
      NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE);
      return NS_OK;
    }
  }

  // Ensure that we have something to compile
  nsDependentString handlerText(mHandlerText);
  NS_ENSURE_TRUE(!handlerText.IsEmpty(), NS_ERROR_FAILURE);

  JSAddonId* addonId = MapURIToAddonID(mPrototypeBinding->DocURI());

  JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, globalObject, addonId));
  NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);

  nsAutoCString bindingURI;
  mPrototypeBinding->DocURI()->GetSpec(bindingURI);

  uint32_t argCount;
  const char **argNames;
  nsContentUtils::GetEventArgNames(kNameSpaceID_XBL, aName, false, &argCount,
                                   &argNames);

  // Compile the event handler in the xbl scope.
  JSAutoCompartment ac(cx, scopeObject);
  JS::CompileOptions options(cx);
  options.setFileAndLine(bindingURI.get(), mLineNumber)
         .setVersion(JSVERSION_LATEST);

  JS::Rooted<JSObject*> handlerFun(cx);
  JS::AutoObjectVector emptyVector(cx);
  nsresult rv = nsJSUtils::CompileFunction(jsapi, emptyVector, options,
                                           nsAtomCString(aName), argCount,
                                           argNames, handlerText,
                                           handlerFun.address());
  NS_ENSURE_SUCCESS(rv, rv);
  NS_ENSURE_TRUE(handlerFun, NS_ERROR_FAILURE);

  // Wrap the handler into the content scope, since we're about to stash it
  // on the DOM window and such.
  JSAutoCompartment ac2(cx, globalObject);
  bool ok = JS_WrapObject(cx, &handlerFun);
  NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
  aHandler.set(handlerFun);
  NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE);

  if (pWindow) {
    pWindow->CacheXBLPrototypeHandler(this, aHandler);
  }

  return NS_OK;
}
Example #8
0
// static
nsresult
Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd,
                         JSContext* aCx, uint8_t aTypeOffset, JS::MutableHandle<JS::Value> aVal,
                         uint16_t aRecursionDepth)
{
  NS_ENSURE_TRUE(aRecursionDepth < MaxRecursionDepth, NS_ERROR_DOM_INDEXEDDB_DATA_ERR);

  if (*aPos - aTypeOffset >= eArray) {
    JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0, nullptr));
    if (!array) {
      NS_WARNING("Failed to make array!");
      return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
    }

    aTypeOffset += eMaxType;

    if (aTypeOffset == eMaxType * MaxArrayCollapse) {
      ++aPos;
      aTypeOffset = 0;
    }

    uint32_t index = 0;
    JS::Rooted<JS::Value> val(aCx);
    while (aPos < aEnd && *aPos - aTypeOffset != eTerminator) {
      nsresult rv = DecodeJSValInternal(aPos, aEnd, aCx, aTypeOffset,
                                        &val, aRecursionDepth + 1);
      NS_ENSURE_SUCCESS(rv, rv);

      aTypeOffset = 0;

      if (!JS_SetElement(aCx, array, index++, &val)) {
        NS_WARNING("Failed to set array element!");
        return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
      }
    }

    NS_ASSERTION(aPos >= aEnd || (*aPos % eMaxType) == eTerminator,
                 "Should have found end-of-array marker");
    ++aPos;

    aVal.setObject(*array);
  }
  else if (*aPos - aTypeOffset == eString) {
    nsString key;
    DecodeString(aPos, aEnd, key);
    if (!xpc::StringToJsval(aCx, key, aVal)) {
      return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
    }
  }
  else if (*aPos - aTypeOffset == eDate) {
    double msec = static_cast<double>(DecodeNumber(aPos, aEnd));
    JSObject* date = JS_NewDateObjectMsec(aCx, msec);
    if (!date) {
      NS_WARNING("Failed to make date!");
      return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
    }

    aVal.setObject(*date);
  }
  else if (*aPos - aTypeOffset == eFloat) {
    aVal.setDouble(DecodeNumber(aPos, aEnd));
  }
  else {
    NS_NOTREACHED("Unknown key type!");
  }

  return NS_OK;
}
Example #9
0
JSBool JavaObject::setPropertyWrapper(JSContext* ctx, JS::Handle<JSObject*> obj,
    JS::Handle<jsid> id, JSBool strict, JS::MutableHandle<JS::Value> vp) {
  jsval rval = vp.get();
  return JavaObject::setProperty(ctx, obj, id, strict, &rval);
}
nsresult
nsXBLPrototypeHandler::EnsureEventHandler(nsIScriptGlobalObject* aGlobal,
                                          nsIScriptContext *aBoundContext,
                                          nsIAtom *aName,
                                          JS::MutableHandle<JSObject*> aHandler)
{
  AutoPushJSContext cx(aBoundContext->GetNativeContext());

  // Check to see if we've already compiled this
  nsCOMPtr<nsPIDOMWindow> pWindow = do_QueryInterface(aGlobal);
  if (pWindow) {
    JS::Rooted<JSObject*> cachedHandler(cx, pWindow->GetCachedXBLPrototypeHandler(this));
    if (cachedHandler) {
      JS::ExposeObjectToActiveJS(cachedHandler);
      aHandler.set(cachedHandler);
      NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE);
      return NS_OK;
    }
  }

  // Ensure that we have something to compile
  nsDependentString handlerText(mHandlerText);
  NS_ENSURE_TRUE(!handlerText.IsEmpty(), NS_ERROR_FAILURE);

  JS::Rooted<JSObject*> globalObject(cx, aGlobal->GetGlobalJSObject());
  JS::Rooted<JSObject*> scopeObject(cx, xpc::GetXBLScope(cx, globalObject));
  NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);

  nsAutoCString bindingURI;
  mPrototypeBinding->DocURI()->GetSpec(bindingURI);

  uint32_t argCount;
  const char **argNames;
  nsContentUtils::GetEventArgNames(kNameSpaceID_XBL, aName, &argCount,
                                   &argNames);

  // Compile the event handler in the xbl scope.
  JSAutoCompartment ac(cx, scopeObject);
  JS::CompileOptions options(cx);
  options.setFileAndLine(bindingURI.get(), mLineNumber)
         .setVersion(JSVERSION_LATEST);

  JS::Rooted<JSObject*> rootedNull(cx); // See bug 781070.
  JS::Rooted<JSObject*> handlerFun(cx);
  nsresult rv = nsJSUtils::CompileFunction(cx, rootedNull, options,
                                           nsAtomCString(aName), argCount,
                                           argNames, handlerText, handlerFun.address());
  NS_ENSURE_SUCCESS(rv, rv);
  NS_ENSURE_TRUE(handlerFun, NS_ERROR_FAILURE);

  // Wrap the handler into the content scope, since we're about to stash it
  // on the DOM window and such.
  JSAutoCompartment ac2(cx, globalObject);
  bool ok = JS_WrapObject(cx, handlerFun.address());
  NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
  aHandler.set(handlerFun);
  NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE);

  if (pWindow) {
    pWindow->CacheXBLPrototypeHandler(this, aHandler);
  }

  return NS_OK;
}
Example #11
0
void
WorkerDebuggerGlobalScope::GetGlobal(JSContext* aCx,
                                     JS::MutableHandle<JSObject*> aGlobal)
{
  aGlobal.set(mWorkerPrivate->GetOrCreateGlobalScope(aCx)->GetWrapper());
}