bool
JavaScriptShared::toValue(JSContext *cx, const JSVariant &from, MutableHandleValue to)
{
    switch (from.type()) {
        case JSVariant::Tvoid_t:
          to.set(UndefinedValue());
          return true;

        case JSVariant::Tuint64_t:
        {
          ObjectId id = from.get_uint64_t();
          if (id) {
              JSObject *obj = unwrap(cx, id);
              if (!obj)
                  return false;
              to.set(ObjectValue(*obj));
          } else {
              to.set(JSVAL_NULL);
          }
          return true;
        }

        case JSVariant::Tdouble:
          to.set(JS_NumberValue(from.get_double()));
          return true;

        case JSVariant::Tbool:
          to.set(BOOLEAN_TO_JSVAL(from.get_bool()));
          return true;

        case JSVariant::TnsString:
        {
          const nsString &old = from.get_nsString();
          JSString *str = JS_NewUCStringCopyN(cx, old.BeginReading(), old.Length());
          if (!str)
              return false;
          to.set(StringValue(str));
          return true;
        }

        case JSVariant::TJSIID:
        {
          nsID iid;
          const JSIID &id = from.get_JSIID();
          ConvertID(id, &iid);

          JSCompartment *compartment = GetContextCompartment(cx);
          RootedObject global(cx, JS_GetGlobalForCompartmentOrNull(cx, compartment));
          JSObject *obj = xpc_NewIDObject(cx, global, iid);
          if (!obj)
              return false;
          to.set(ObjectValue(*obj));
          return true;
        }

        default:
          return false;
    }
}
bool
JavaScriptShared::fromVariant(JSContext* cx, const JSVariant& from, MutableHandleValue to)
{
    switch (from.type()) {
        case JSVariant::TUndefinedVariant:
          to.set(UndefinedValue());
          return true;

        case JSVariant::TNullVariant:
          to.set(NullValue());
          return true;

        case JSVariant::TObjectVariant:
        {
          JSObject* obj = fromObjectVariant(cx, from.get_ObjectVariant());
          if (!obj)
              return false;
          to.set(ObjectValue(*obj));
          return true;
        }

        case JSVariant::TSymbolVariant:
        {
          Symbol* sym = fromSymbolVariant(cx, from.get_SymbolVariant());
          if (!sym)
              return false;
          to.setSymbol(sym);
          return true;
        }

        case JSVariant::Tdouble:
          to.set(JS_NumberValue(from.get_double()));
          return true;

        case JSVariant::Tbool:
          to.set(BOOLEAN_TO_JSVAL(from.get_bool()));
          return true;

        case JSVariant::TnsString:
        {
          const nsString& old = from.get_nsString();
          JSString* str = JS_NewUCStringCopyN(cx, old.BeginReading(), old.Length());
          if (!str)
              return false;
          to.set(StringValue(str));
          return true;
        }

        case JSVariant::TJSIID:
        {
          nsID iid;
          const JSIID& id = from.get_JSIID();
          ConvertID(id, &iid);

          JSCompartment* compartment = GetContextCompartment(cx);
          RootedObject global(cx, JS_GetGlobalForCompartmentOrNull(cx, compartment));
          JSObject* obj = xpc_NewIDObject(cx, global, iid);
          if (!obj)
              return false;
          to.set(ObjectValue(*obj));
          return true;
        }

        default:
          MOZ_CRASH("NYI");
          return false;
    }
}