v8::MaybeLocal CreateProxyForAPI()

in shell/renderer/api/electron_api_context_bridge.cc [482:561]


v8::MaybeLocal<v8::Object> CreateProxyForAPI(
    const v8::Local<v8::Object>& api_object,
    const v8::Local<v8::Context>& source_context,
    const v8::Local<v8::Context>& destination_context,
    context_bridge::ObjectCache* object_cache,
    bool support_dynamic_properties,
    int recursion_depth) {
  gin_helper::Dictionary api(source_context->GetIsolate(), api_object);

  {
    v8::Context::Scope destination_context_scope(destination_context);
    gin_helper::Dictionary proxy =
        gin::Dictionary::CreateEmpty(destination_context->GetIsolate());
    object_cache->CacheProxiedObject(api.GetHandle(), proxy.GetHandle());
    auto maybe_keys = api.GetHandle()->GetOwnPropertyNames(
        source_context, static_cast<v8::PropertyFilter>(v8::ONLY_ENUMERABLE));
    if (maybe_keys.IsEmpty())
      return v8::MaybeLocal<v8::Object>(proxy.GetHandle());
    auto keys = maybe_keys.ToLocalChecked();

    uint32_t length = keys->Length();
    for (uint32_t i = 0; i < length; i++) {
      v8::Local<v8::Value> key =
          keys->Get(destination_context, i).ToLocalChecked();

      if (support_dynamic_properties) {
        v8::Context::Scope source_context_scope(source_context);
        auto maybe_desc = api.GetHandle()->GetOwnPropertyDescriptor(
            source_context, key.As<v8::Name>());
        v8::Local<v8::Value> desc_value;
        if (!maybe_desc.ToLocal(&desc_value) || !desc_value->IsObject())
          continue;
        gin_helper::Dictionary desc(api.isolate(), desc_value.As<v8::Object>());
        if (desc.Has("get") || desc.Has("set")) {
          v8::Local<v8::Value> getter;
          v8::Local<v8::Value> setter;
          desc.Get("get", &getter);
          desc.Get("set", &setter);

          {
            v8::Context::Scope destination_context_scope(destination_context);
            v8::Local<v8::Value> getter_proxy;
            v8::Local<v8::Value> setter_proxy;
            if (!getter.IsEmpty()) {
              if (!PassValueToOtherContext(source_context, destination_context,
                                           getter, object_cache,
                                           support_dynamic_properties, 1)
                       .ToLocal(&getter_proxy))
                continue;
            }
            if (!setter.IsEmpty()) {
              if (!PassValueToOtherContext(source_context, destination_context,
                                           setter, object_cache,
                                           support_dynamic_properties, 1)
                       .ToLocal(&setter_proxy))
                continue;
            }

            v8::PropertyDescriptor desc(getter_proxy, setter_proxy);
            ignore_result(proxy.GetHandle()->DefineProperty(
                destination_context, key.As<v8::Name>(), desc));
          }
          continue;
        }
      }
      v8::Local<v8::Value> value;
      if (!api.Get(key, &value))
        continue;

      auto passed_value = PassValueToOtherContext(
          source_context, destination_context, value, object_cache,
          support_dynamic_properties, recursion_depth + 1);
      if (passed_value.IsEmpty())
        return v8::MaybeLocal<v8::Object>();
      proxy.Set(key, passed_value.ToLocalChecked());
    }

    return proxy.GetHandle();
  }
}