local_ref<jstring> ReadableNativeMap::getStringKey(const std::string& key) {
  const folly::dynamic& val = getMapValue(key);
  if (val.isNull()) {
    return local_ref<jstring>(nullptr);
  }
  return make_jstring(val.getString().c_str());
}
void throwNewJavaException(const char* throwableName, const char* msg) {
  // If anything of the fbjni calls fail, an exception of a suitable
  // form will be thrown, which is what we want.
  auto throwableClass = findClassLocal(throwableName);
  auto throwable = throwableClass->newObject(
    throwableClass->getConstructor<jthrowable(jstring)>(),
    make_jstring(msg).release());
  throwNewJavaException(throwable.get());
}
local_ref<jstring> ReadableNativeMapKeySetIterator::nextKey() {
  if (!hasNextKey()) {
    throwNewJavaException("com/facebook/react/bridge/InvalidIteratorException",
                          "No such element exists");
  }
  auto ret = make_jstring(iter_->first.c_str());
  ++iter_;
  return ret;
}
Size TextLayoutManager::measure(
    AttributedString attributedString,
    ParagraphAttributes paragraphAttributes,
    LayoutConstraints layoutConstraints) const {
  const jni::global_ref<jobject> &fabricUIManager =
      contextContainer_->getInstance<jni::global_ref<jobject>>(
          "FabricUIManager");

  static auto measure =
      jni::findClassStatic("com/facebook/react/fabric/FabricUIManager")
          ->getMethod<jlong(
              jstring,
              ReadableMap::javaobject,
              ReadableMap::javaobject,
              jint,
              jint,
              jint,
              jint)>("measure");

  auto minimumSize = layoutConstraints.minimumSize;
  auto maximumSize = layoutConstraints.maximumSize;
  int minWidth = (int)minimumSize.width;
  int minHeight = (int)minimumSize.height;
  int maxWidth = (int)maximumSize.width;
  int maxHeight = (int)maximumSize.height;

  local_ref<JString> componentName = make_jstring("RCTText");
  local_ref<ReadableNativeMap::javaobject> attributedStringRNM =
      ReadableNativeMap::newObjectCxxArgs(toDynamic(attributedString));
  local_ref<ReadableNativeMap::javaobject> paragraphAttributesRNM =
      ReadableNativeMap::newObjectCxxArgs(toDynamic(paragraphAttributes));

  local_ref<ReadableMap::javaobject> attributedStringRM = make_local(
      reinterpret_cast<ReadableMap::javaobject>(attributedStringRNM.get()));
  local_ref<ReadableMap::javaobject> paragraphAttributesRM = make_local(
      reinterpret_cast<ReadableMap::javaobject>(paragraphAttributesRNM.get()));
  return yogaMeassureToSize(measure(
      fabricUIManager,
      componentName.get(),
      attributedStringRM.get(),
      paragraphAttributesRM.get(),
      minWidth,
      maxWidth,
      minHeight,
      maxHeight));
}
local_ref<jstring> NativeArray::toString() {
  exceptions::throwIfObjectAlreadyConsumed(this, "Array already consumed");
  return make_jstring(folly::toJson(array).c_str());
}