|
@@ -146,6 +146,7 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContext(
|
|
|
v8::Local<v8::Value> value,
|
|
|
context_bridge::RenderFrameFunctionStore* store,
|
|
|
context_bridge::ObjectCache* object_cache,
|
|
|
+ bool support_dynamic_properties,
|
|
|
int recursion_depth) {
|
|
|
if (recursion_depth >= kMaxRecursion) {
|
|
|
v8::Context::Scope source_scope(source_context);
|
|
@@ -179,7 +180,8 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContext(
|
|
|
{
|
|
|
v8::Local<v8::Value> proxy_func = gin_helper::CallbackToV8Leaked(
|
|
|
destination_context->GetIsolate(),
|
|
|
- base::BindRepeating(&ProxyFunctionWrapper, store, func_id));
|
|
|
+ base::BindRepeating(&ProxyFunctionWrapper, store, func_id,
|
|
|
+ support_dynamic_properties));
|
|
|
FunctionLifeMonitor::BindTo(destination_context->GetIsolate(),
|
|
|
v8::Local<v8::Object>::Cast(proxy_func),
|
|
|
store->GetWeakPtr(), func_id);
|
|
@@ -209,7 +211,7 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContext(
|
|
|
auto val =
|
|
|
PassValueToOtherContext(global_source_context.Get(isolate),
|
|
|
global_destination_context.Get(isolate),
|
|
|
- result, store, &object_cache, 0);
|
|
|
+ result, store, &object_cache, false, 0);
|
|
|
if (!val.IsEmpty())
|
|
|
proxied_promise->Resolve(val.ToLocalChecked());
|
|
|
delete proxied_promise;
|
|
@@ -230,7 +232,7 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContext(
|
|
|
auto val =
|
|
|
PassValueToOtherContext(global_source_context.Get(isolate),
|
|
|
global_destination_context.Get(isolate),
|
|
|
- result, store, &object_cache, 0);
|
|
|
+ result, store, &object_cache, false, 0);
|
|
|
if (!val.IsEmpty())
|
|
|
proxied_promise->Reject(val.ToLocalChecked());
|
|
|
delete proxied_promise;
|
|
@@ -276,7 +278,7 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContext(
|
|
|
auto value_for_array = PassValueToOtherContext(
|
|
|
source_context, destination_context,
|
|
|
arr->Get(source_context, i).ToLocalChecked(), store, object_cache,
|
|
|
- recursion_depth + 1);
|
|
|
+ support_dynamic_properties, recursion_depth + 1);
|
|
|
if (value_for_array.IsEmpty())
|
|
|
return v8::MaybeLocal<v8::Value>();
|
|
|
|
|
@@ -293,9 +295,9 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContext(
|
|
|
// Proxy all objects
|
|
|
if (IsPlainObject(value)) {
|
|
|
auto object_value = v8::Local<v8::Object>::Cast(value);
|
|
|
- auto passed_value =
|
|
|
- CreateProxyForAPI(object_value, source_context, destination_context,
|
|
|
- store, object_cache, recursion_depth + 1);
|
|
|
+ auto passed_value = CreateProxyForAPI(
|
|
|
+ object_value, source_context, destination_context, store, object_cache,
|
|
|
+ support_dynamic_properties, recursion_depth + 1);
|
|
|
if (passed_value.IsEmpty())
|
|
|
return v8::MaybeLocal<v8::Value>();
|
|
|
return v8::MaybeLocal<v8::Value>(passed_value.ToLocalChecked());
|
|
@@ -324,6 +326,7 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContext(
|
|
|
v8::Local<v8::Value> ProxyFunctionWrapper(
|
|
|
context_bridge::RenderFrameFunctionStore* store,
|
|
|
size_t func_id,
|
|
|
+ bool support_dynamic_properties,
|
|
|
gin_helper::Arguments* args) {
|
|
|
// Context the proxy function was called from
|
|
|
v8::Local<v8::Context> calling_context = args->isolate()->GetCurrentContext();
|
|
@@ -343,7 +346,8 @@ v8::Local<v8::Value> ProxyFunctionWrapper(
|
|
|
|
|
|
for (auto value : original_args) {
|
|
|
auto arg = PassValueToOtherContext(calling_context, func_owning_context,
|
|
|
- value, store, &object_cache, 0);
|
|
|
+ value, store, &object_cache,
|
|
|
+ support_dynamic_properties, 0);
|
|
|
if (arg.IsEmpty())
|
|
|
return v8::Undefined(args->isolate());
|
|
|
proxied_args.push_back(arg.ToLocalChecked());
|
|
@@ -381,9 +385,10 @@ v8::Local<v8::Value> ProxyFunctionWrapper(
|
|
|
if (maybe_return_value.IsEmpty())
|
|
|
return v8::Undefined(args->isolate());
|
|
|
|
|
|
- auto ret = PassValueToOtherContext(func_owning_context, calling_context,
|
|
|
- maybe_return_value.ToLocalChecked(),
|
|
|
- store, &object_cache, 0);
|
|
|
+ auto ret =
|
|
|
+ PassValueToOtherContext(func_owning_context, calling_context,
|
|
|
+ maybe_return_value.ToLocalChecked(), store,
|
|
|
+ &object_cache, support_dynamic_properties, 0);
|
|
|
if (ret.IsEmpty())
|
|
|
return v8::Undefined(args->isolate());
|
|
|
return ret.ToLocalChecked();
|
|
@@ -396,6 +401,7 @@ v8::MaybeLocal<v8::Object> CreateProxyForAPI(
|
|
|
const v8::Local<v8::Context>& destination_context,
|
|
|
context_bridge::RenderFrameFunctionStore* store,
|
|
|
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);
|
|
@@ -420,13 +426,54 @@ v8::MaybeLocal<v8::Object> CreateProxyForAPI(
|
|
|
if (!gin::ConvertFromV8(api.isolate(), key, &key_str)) {
|
|
|
continue;
|
|
|
}
|
|
|
+ if (support_dynamic_properties) {
|
|
|
+ v8::Context::Scope source_context_scope(source_context);
|
|
|
+ auto maybe_desc = api.GetHandle()->GetOwnPropertyDescriptor(
|
|
|
+ source_context, v8::Local<v8::Name>::Cast(key));
|
|
|
+ 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, store, object_cache, false,
|
|
|
+ 1)
|
|
|
+ .ToLocal(&getter_proxy))
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (!setter.IsEmpty()) {
|
|
|
+ if (!PassValueToOtherContext(source_context, destination_context,
|
|
|
+ setter, store, object_cache, false,
|
|
|
+ 1)
|
|
|
+ .ToLocal(&setter_proxy))
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ v8::PropertyDescriptor desc(getter_proxy, setter_proxy);
|
|
|
+ ignore_result(proxy.GetHandle()->DefineProperty(
|
|
|
+ destination_context, gin::StringToV8(api.isolate(), key_str),
|
|
|
+ desc));
|
|
|
+ }
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
v8::Local<v8::Value> value;
|
|
|
if (!api.Get(key_str, &value))
|
|
|
continue;
|
|
|
|
|
|
- auto passed_value =
|
|
|
- PassValueToOtherContext(source_context, destination_context, value,
|
|
|
- store, object_cache, recursion_depth + 1);
|
|
|
+ auto passed_value = PassValueToOtherContext(
|
|
|
+ source_context, destination_context, value, store, object_cache,
|
|
|
+ support_dynamic_properties, recursion_depth + 1);
|
|
|
if (passed_value.IsEmpty())
|
|
|
return v8::MaybeLocal<v8::Object>();
|
|
|
proxy.Set(key_str, passed_value.ToLocalChecked());
|
|
@@ -472,8 +519,9 @@ void ExposeAPIInMainWorld(const std::string& key,
|
|
|
context_bridge::ObjectCache object_cache;
|
|
|
v8::Context::Scope main_context_scope(main_context);
|
|
|
{
|
|
|
- v8::MaybeLocal<v8::Object> maybe_proxy = CreateProxyForAPI(
|
|
|
- api_object, isolated_context, main_context, store, &object_cache, 0);
|
|
|
+ v8::MaybeLocal<v8::Object> maybe_proxy =
|
|
|
+ CreateProxyForAPI(api_object, isolated_context, main_context, store,
|
|
|
+ &object_cache, false, 0);
|
|
|
if (maybe_proxy.IsEmpty())
|
|
|
return;
|
|
|
auto proxy = maybe_proxy.ToLocalChecked();
|
|
@@ -493,13 +541,14 @@ gin_helper::Dictionary TraceKeyPath(const gin_helper::Dictionary& start,
|
|
|
return current;
|
|
|
}
|
|
|
|
|
|
-void OverrideGlobalMethodFromIsolatedWorld(
|
|
|
+void OverrideGlobalValueFromIsolatedWorld(
|
|
|
const std::vector<std::string>& key_path,
|
|
|
- v8::Local<v8::Function> method) {
|
|
|
+ v8::Local<v8::Object> value,
|
|
|
+ bool support_dynamic_properties) {
|
|
|
if (key_path.size() == 0)
|
|
|
return;
|
|
|
|
|
|
- auto* render_frame = GetRenderFrame(method);
|
|
|
+ auto* render_frame = GetRenderFrame(value);
|
|
|
CHECK(render_frame);
|
|
|
context_bridge::RenderFrameFunctionStore* store =
|
|
|
GetOrCreateStore(render_frame);
|
|
@@ -515,9 +564,9 @@ void OverrideGlobalMethodFromIsolatedWorld(
|
|
|
{
|
|
|
v8::Context::Scope main_context_scope(main_context);
|
|
|
context_bridge::ObjectCache object_cache;
|
|
|
- v8::MaybeLocal<v8::Value> maybe_proxy =
|
|
|
- PassValueToOtherContext(method->CreationContext(), main_context, method,
|
|
|
- store, &object_cache, 1);
|
|
|
+ v8::MaybeLocal<v8::Value> maybe_proxy = PassValueToOtherContext(
|
|
|
+ value->CreationContext(), main_context, value, store, &object_cache,
|
|
|
+ support_dynamic_properties, 1);
|
|
|
DCHECK(!maybe_proxy.IsEmpty());
|
|
|
auto proxy = maybe_proxy.ToLocalChecked();
|
|
|
|
|
@@ -555,14 +604,14 @@ bool OverrideGlobalPropertyFromIsolatedWorld(
|
|
|
if (!getter->IsNullOrUndefined()) {
|
|
|
v8::MaybeLocal<v8::Value> maybe_getter_proxy =
|
|
|
PassValueToOtherContext(getter->CreationContext(), main_context,
|
|
|
- getter, store, &object_cache, 1);
|
|
|
+ getter, store, &object_cache, false, 1);
|
|
|
DCHECK(!maybe_getter_proxy.IsEmpty());
|
|
|
getter_proxy = maybe_getter_proxy.ToLocalChecked();
|
|
|
}
|
|
|
if (!setter->IsNullOrUndefined() && setter->IsObject()) {
|
|
|
v8::MaybeLocal<v8::Value> maybe_setter_proxy =
|
|
|
PassValueToOtherContext(getter->CreationContext(), main_context,
|
|
|
- setter, store, &object_cache, 1);
|
|
|
+ setter, store, &object_cache, false, 1);
|
|
|
DCHECK(!maybe_setter_proxy.IsEmpty());
|
|
|
setter_proxy = maybe_setter_proxy.ToLocalChecked();
|
|
|
}
|
|
@@ -597,8 +646,8 @@ void Initialize(v8::Local<v8::Object> exports,
|
|
|
v8::Isolate* isolate = context->GetIsolate();
|
|
|
gin_helper::Dictionary dict(isolate, exports);
|
|
|
dict.SetMethod("exposeAPIInMainWorld", &electron::api::ExposeAPIInMainWorld);
|
|
|
- dict.SetMethod("_overrideGlobalMethodFromIsolatedWorld",
|
|
|
- &electron::api::OverrideGlobalMethodFromIsolatedWorld);
|
|
|
+ dict.SetMethod("_overrideGlobalValueFromIsolatedWorld",
|
|
|
+ &electron::api::OverrideGlobalValueFromIsolatedWorld);
|
|
|
dict.SetMethod("_overrideGlobalPropertyFromIsolatedWorld",
|
|
|
&electron::api::OverrideGlobalPropertyFromIsolatedWorld);
|
|
|
dict.SetMethod("_isCalledFromMainWorld",
|