  v8::Local<v8::Promise> ExecuteJavaScriptInIsolatedWorld(
      gin::Arguments* gin_args,
      int world_id,
      const std::vector<gin_helper::Dictionary>& scripts) {
    gin_helper::Arguments* args = static_cast<gin_helper::Arguments*>(gin_args);

    v8::Isolate* isolate = args->isolate();
    gin_helper::Promise<v8::Local<v8::Value>> promise(isolate);
    v8::Local<v8::Promise> handle = promise.GetHandle();

    content::RenderFrame* render_frame;
    std::string error_msg;
    if (!MaybeGetRenderFrame(&error_msg, "executeJavaScriptInIsolatedWorld",
                             &render_frame)) {
      promise.RejectWithErrorMessage(error_msg);
      return handle;
    }

    bool has_user_gesture = false;
    args->GetNext(&has_user_gesture);

    blink::WebLocalFrame::ScriptExecutionType scriptExecutionType =
        blink::WebLocalFrame::kSynchronous;
    args->GetNext(&scriptExecutionType);

    ScriptExecutionCallback::CompletionCallback completion_callback;
    args->GetNext(&completion_callback);

    std::vector<blink::WebScriptSource> sources;
    sources.reserve(scripts.size());

    for (const auto& script : scripts) {
      std::u16string code;
      std::u16string url;
      script.Get("url", &url);

      if (!script.Get("code", &code)) {
        const char error_message[] = "Invalid 'code'";
        if (!completion_callback.is_null()) {
          std::move(completion_callback)
              .Run(v8::Undefined(isolate),
                   v8::Exception::Error(
                       v8::String::NewFromUtf8(isolate, error_message)
                           .ToLocalChecked()));
        }
        promise.RejectWithErrorMessage(error_message);
        return handle;
      }

      sources.emplace_back(blink::WebString::FromUTF16(code),
                           blink::WebURL(GURL(url)));
    }

    render_frame->GetWebFrame()->RequestExecuteScript(
        world_id, base::make_span(sources), has_user_gesture,
        scriptExecutionType,
        new ScriptExecutionCallback(std::move(promise),
                                    std::move(completion_callback)),
        blink::BackForwardCacheAware::kPossiblyDisallow,
        blink::WebLocalFrame::PromiseBehavior::kDontWait);

    return handle;
  }
  v8::Local<v8::Promise> ExecuteJavaScriptInIsolatedWorld(
      gin::Arguments* gin_args,
      int world_id,
      const std::vector<gin_helper::Dictionary>& scripts) {
    gin_helper::Arguments* args = static_cast<gin_helper::Arguments*>(gin_args);

    v8::Isolate* isolate = args->isolate();
    gin_helper::Promise<v8::Local<v8::Value>> promise(isolate);
    v8::Local<v8::Promise> handle = promise.GetHandle();

    content::RenderFrame* render_frame;
    std::string error_msg;
    if (!MaybeGetRenderFrame(&error_msg, "executeJavaScriptInIsolatedWorld",
                             &render_frame)) {
      promise.RejectWithErrorMessage(error_msg);
      return handle;
    }

    bool has_user_gesture = false;
    args->GetNext(&has_user_gesture);

    blink::WebLocalFrame::ScriptExecutionType scriptExecutionType =
        blink::WebLocalFrame::kSynchronous;
    args->GetNext(&scriptExecutionType);

    ScriptExecutionCallback::CompletionCallback completion_callback;
    args->GetNext(&completion_callback);

    std::vector<blink::WebScriptSource> sources;
    sources.reserve(scripts.size());

    for (const auto& script : scripts) {
      std::u16string code;
      std::u16string url;
      script.Get("url", &url);

      if (!script.Get("code", &code)) {
        const char error_message[] = "Invalid 'code'";
        if (!completion_callback.is_null()) {
          std::move(completion_callback)
              .Run(v8::Undefined(isolate),
                   v8::Exception::Error(
                       v8::String::NewFromUtf8(isolate, error_message)
                           .ToLocalChecked()));
        }
        promise.RejectWithErrorMessage(error_message);
        return handle;
      }

      sources.emplace_back(blink::WebString::FromUTF16(code),
                           blink::WebURL(GURL(url)));
    }

    render_frame->GetWebFrame()->RequestExecuteScript(
        world_id, base::make_span(sources), has_user_gesture,
        scriptExecutionType,
        new ScriptExecutionCallback(std::move(promise),
                                    std::move(completion_callback)),
        blink::BackForwardCacheAware::kPossiblyDisallow,
        blink::WebLocalFrame::PromiseBehavior::kDontWait);

    return handle;
  }