Exemple #1
0
void
Promise::AppendNativeHandler(PromiseNativeHandler* aRunnable)
{
  NS_ASSERT_OWNINGTHREAD(Promise);

  AutoJSAPI jsapi;
  if (NS_WARN_IF(!jsapi.Init(mGlobal))) {
    // Our API doesn't allow us to return a useful error.  Not like this should
    // happen anyway.
    return;
  }

  // The self-hosted promise js may keep the object we pass to it alive
  // for quite a while depending on when GC runs.  Therefore, pass a shim
  // object instead.  The shim will free its inner PromiseNativeHandler
  // after the promise has settled just like our previous c++ promises did.
  RefPtr<PromiseNativeHandlerShim> shim =
    new PromiseNativeHandlerShim(aRunnable);

  JSContext* cx = jsapi.cx();
  JS::Rooted<JSObject*> handlerWrapper(cx);
  // Note: PromiseNativeHandler is NOT wrappercached.  So we can't use
  // ToJSValue here, because it will try to do XPConnect wrapping on it, sadly.
  if (NS_WARN_IF(!shim->WrapObject(cx, nullptr, &handlerWrapper))) {
    // Again, no way to report errors.
    jsapi.ClearException();
    return;
  }

  JS::Rooted<JSObject*> resolveFunc(cx);
  resolveFunc =
    CreateNativeHandlerFunction(cx, handlerWrapper, NativeHandlerTask::Resolve);
  if (NS_WARN_IF(!resolveFunc)) {
    jsapi.ClearException();
    return;
  }

  JS::Rooted<JSObject*> rejectFunc(cx);
  rejectFunc =
    CreateNativeHandlerFunction(cx, handlerWrapper, NativeHandlerTask::Reject);
  if (NS_WARN_IF(!rejectFunc)) {
    jsapi.ClearException();
    return;
  }

  JS::Rooted<JSObject*> promiseObj(cx, PromiseObj());
  if (NS_WARN_IF(!JS::AddPromiseReactions(cx, promiseObj, resolveFunc,
                                          rejectFunc))) {
    jsapi.ClearException();
    return;
  }
}
nsresult TranslateChoices(
    JS::HandleValue aChoices,
    const nsTArray<PermissionRequest>& aPermissionRequests,
    nsTArray<PermissionChoice>& aTranslatedChoices) {
  if (aChoices.isNullOrUndefined()) {
    // No choice is specified.
  } else if (aChoices.isObject()) {
    // Iterate through all permission types.
    for (uint32_t i = 0; i < aPermissionRequests.Length(); ++i) {
      nsCString type = aPermissionRequests[i].type();

      JS::Rooted<JSObject*> obj(RootingCx(), &aChoices.toObject());
      // People really shouldn't be passing WindowProxy or Location
      // objects for the choices here.
      obj = js::CheckedUnwrapStatic(obj);
      if (!obj) {
        return NS_ERROR_FAILURE;
      }

      AutoJSAPI jsapi;
      jsapi.Init();

      JSContext* cx = jsapi.cx();
      JSAutoRealm ar(cx, obj);

      JS::Rooted<JS::Value> val(cx);

      if (!JS_GetProperty(cx, obj, type.BeginReading(), &val) ||
          !val.isString()) {
        // no setting for the permission type, clear exception and skip it
        jsapi.ClearException();
      } else {
        nsAutoJSString choice;
        if (!choice.init(cx, val)) {
          jsapi.ClearException();
          return NS_ERROR_FAILURE;
        }
        aTranslatedChoices.AppendElement(PermissionChoice(type, choice));
      }
    }
  } else {
    MOZ_ASSERT(false, "SelectedChoices should be undefined or an JS object");
    return NS_ERROR_FAILURE;
  }

  return NS_OK;
}
NS_IMETHODIMP
MobileConnectionCallback::NotifyGetCallForwardingSuccess(uint32_t aCount,
                                                         nsIMobileCallForwardingOptions** aResults)
{
  nsTArray<MozCallForwardingOptions> results;
  for (uint32_t i = 0; i < aCount; i++)
  {
    MozCallForwardingOptions result;
    int16_t pShort;
    nsString pString;
    bool pBool;

    aResults[i]->GetActive(&pBool);
    result.mActive.Construct(pBool);

    aResults[i]->GetAction(&pShort);
    if (pShort != nsIMobileConnection::CALL_FORWARD_ACTION_UNKNOWN) {
      result.mAction.Construct(pShort);
    }

    aResults[i]->GetReason(&pShort);
    if (pShort != nsIMobileConnection::CALL_FORWARD_REASON_UNKNOWN) {
      result.mReason.Construct(pShort);
    }

    aResults[i]->GetNumber(pString);
    result.mNumber.Construct(pString.get());

    aResults[i]->GetTimeSeconds(&pShort);
    if (pShort >= 0) {
      result.mTimeSeconds.Construct(pShort);
    }

    aResults[i]->GetServiceClass(&pShort);
    if (pShort != nsIMobileConnection::ICC_SERVICE_CLASS_NONE) {
      result.mServiceClass.Construct(pShort);
    }

    results.AppendElement(result);
  }

  AutoJSAPI jsapi;
  if (NS_WARN_IF(!jsapi.Init(mWindow))) {
    return NS_ERROR_FAILURE;
  }

  JSContext* cx = jsapi.cx();
  JS::Rooted<JS::Value> jsResult(cx);

  if (!ToJSValue(cx, results, &jsResult)) {
    jsapi.ClearException();
    return NS_ERROR_TYPE_ERR;
  }

  return NotifySuccess(jsResult);
}
void
ProfileGatherer::Finish()
{
  MOZ_ASSERT(NS_IsMainThread());

  if (!mTicker) {
    // We somehow got called after we were cancelled! This shouldn't
    // be possible, but doing a belt-and-suspenders check to be sure.
    return;
  }

  UniquePtr<char[]> buf = mTicker->ToJSON(mSinceTime);

  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
  if (os) {
    DebugOnly<nsresult> rv = os->RemoveObserver(this, "profiler-subprocess");
    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "RemoveObserver failed");
  }

  AutoJSAPI jsapi;
  if (NS_WARN_IF(!jsapi.Init(mPromise->GlobalJSObject()))) {
    // We're really hosed if we can't get a JS context for some reason.
    Reset();
    return;
  }

  JSContext* cx = jsapi.cx();

  // Now parse the JSON so that we resolve with a JS Object.
  JS::RootedValue val(cx);
  {
    NS_ConvertUTF8toUTF16 js_string(nsDependentCString(buf.get()));
    if (!JS_ParseJSON(cx, static_cast<const char16_t*>(js_string.get()),
                      js_string.Length(), &val)) {
      if (!jsapi.HasException()) {
        mPromise->MaybeReject(NS_ERROR_DOM_UNKNOWN_ERR);
      } else {
        JS::RootedValue exn(cx);
        DebugOnly<bool> gotException = jsapi.StealException(&exn);
        MOZ_ASSERT(gotException);

        jsapi.ClearException();
        mPromise->MaybeReject(cx, exn);
      }
    } else {
      mPromise->MaybeResolve(val);
    }
  }

  Reset();
}
  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(mDescriptor->GetParentObject()), false);

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

    return true;
  }
NS_IMETHODIMP
MobileConnectionCallback::NotifyGetClirStatusSuccess(uint16_t aN, uint16_t aM)
{
  MozClirStatus result;
  result.mN.Construct(aN);
  result.mM.Construct(aM);

  AutoJSAPI jsapi;
  if (NS_WARN_IF(!jsapi.Init(mWindow))) {
    return NS_ERROR_FAILURE;
  }

  JSContext* cx = jsapi.cx();
  JS::Rooted<JS::Value> jsResult(cx);
  if (!ToJSValue(cx, result, &jsResult)) {
    jsapi.ClearException();
    return NS_ERROR_TYPE_ERR;
  }

  return NotifySuccess(jsResult);
};
NS_IMETHODIMP
MobileConnectionCallback::NotifyGetCallBarringSuccess(uint16_t aProgram,
                                                      bool aEnabled,
                                                      uint16_t aServiceClass)
{
  MozCallBarringOptions result;
  result.mProgram.Construct().SetValue(aProgram);
  result.mEnabled.Construct().SetValue(aEnabled);
  result.mServiceClass.Construct().SetValue(aServiceClass);

  AutoJSAPI jsapi;
  if (NS_WARN_IF(!jsapi.Init(mWindow))) {
    return NS_ERROR_FAILURE;
  }

  JSContext* cx = jsapi.cx();
  JS::Rooted<JS::Value> jsResult(cx);
  if (!ToJSValue(cx, result, &jsResult)) {
    jsapi.ClearException();
    return NS_ERROR_TYPE_ERR;
  }

  return NotifySuccess(jsResult);
}
Exemple #8
0
// static
JSObject*
SimpleGlobalObject::Create(GlobalType globalType, JS::Handle<JS::Value> proto)
{
    // We can't root our return value with our AutoJSAPI because the rooting
    // analysis thinks ~AutoJSAPI can GC.  So we need to root in a scope outside
    // the lifetime of the AutoJSAPI.
    JS::Rooted<JSObject*> global(RootingCx());

    {   // Scope to ensure the AutoJSAPI destructor runs before we end up returning
        AutoJSAPI jsapi;
        jsapi.Init();
        JSContext* cx = jsapi.cx();

        JS::CompartmentOptions options;
        options.creationOptions()
        .setInvisibleToDebugger(true)
        // Put our SimpleGlobalObjects in the system zone, so we won't create
        // lots of zones for what are probably very short-lived
        // compartments.  This should help them be GCed quicker and take up
        // less memory before they're GCed.
        .setZone(JS::SystemZone);

        if (NS_IsMainThread()) {
            nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create();
            options.creationOptions().setTrace(xpc::TraceXPCGlobal);
            global = xpc::CreateGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass),
                                             nsJSPrincipals::get(principal),
                                             options);
        } else {
            global = JS_NewGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass),
                                        nullptr,
                                        JS::DontFireOnNewGlobalHook, options);
        }

        if (!global) {
            jsapi.ClearException();
            return nullptr;
        }

        JSAutoCompartment ac(cx, global);

        // It's important to create the nsIGlobalObject for our new global before we
        // start trying to wrap things like the prototype into its compartment,
        // because the wrap operation relies on the global having its
        // nsIGlobalObject already.
        RefPtr<SimpleGlobalObject> globalObject =
            new SimpleGlobalObject(global, globalType);

        // Pass on ownership of globalObject to |global|.
        JS_SetPrivate(global, globalObject.forget().take());

        if (proto.isObjectOrNull()) {
            JS::Rooted<JSObject*> protoObj(cx, proto.toObjectOrNull());
            if (!JS_WrapObject(cx, &protoObj)) {
                jsapi.ClearException();
                return nullptr;
            }

            if (!JS_SplicePrototype(cx, global, protoObj)) {
                jsapi.ClearException();
                return nullptr;
            }
        } else if (!proto.isUndefined()) {
            // Bogus proto.
            return nullptr;
        }

        JS_FireOnNewGlobalObject(cx, global);
    }

    return global;
}
Exemple #9
0
static bool
ProcessFile(AutoJSAPI& jsapi, const char* filename, FILE* file, bool forceTTY)
{
    JSContext* cx = jsapi.cx();
    JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
    MOZ_ASSERT(global);

    if (forceTTY) {
        file = stdin;
    } else if (!isatty(fileno(file))) {
        /*
         * It's not interactive - just execute it.
         *
         * Support the UNIX #! shell hack; gobble the first line if it starts
         * with '#'.  TODO - this isn't quite compatible with sharp variables,
         * as a legal js program (using sharp variables) might start with '#'.
         * But that would require multi-character lookahead.
         */
        int ch = fgetc(file);
        if (ch == '#') {
            while ((ch = fgetc(file)) != EOF) {
                if (ch == '\n' || ch == '\r')
                    break;
            }
        }
        ungetc(ch, file);

        JS::RootedScript script(cx);
        JS::RootedValue unused(cx);
        JS::CompileOptions options(cx);
        options.setUTF8(true)
               .setFileAndLine(filename, 1)
               .setIsRunOnce(true)
               .setNoScriptRval(true);
        if (!JS::Compile(cx, options, file, &script))
            return false;
        return compileOnly || JS_ExecuteScript(cx, script, &unused);
    }

    /* It's an interactive filehandle; drop into read-eval-print loop. */
    int lineno = 1;
    bool hitEOF = false;
    do {
        char buffer[4096];
        char* bufp = buffer;
        *bufp = '\0';

        /*
         * Accumulate lines until we get a 'compilable unit' - one that either
         * generates an error (before running out of source) or that compiles
         * cleanly.  This should be whenever we get a complete statement that
         * coincides with the end of a line.
         */
        int startline = lineno;
        do {
            if (!GetLine(cx, bufp, file, startline == lineno ? "js> " : "")) {
                hitEOF = true;
                break;
            }
            bufp += strlen(bufp);
            lineno++;
        } while (!JS_BufferIsCompilableUnit(cx, global, buffer, strlen(buffer)));

        if (!ProcessLine(jsapi, buffer, startline))
            jsapi.ClearException(); // Errors from interactive processing are squelched.
    } while (!hitEOF && !gQuitting);

    fprintf(gOutFile, "\n");
    return true;
}