|
@@ -44,6 +44,8 @@ namespace api {
|
|
|
namespace context_bridge {
|
|
|
|
|
|
const char kProxyFunctionPrivateKey[] = "electron_contextBridge_proxy_fn";
|
|
|
+const char kProxyFunctionReceiverPrivateKey[] =
|
|
|
+ "electron_contextBridge_proxy_fn_receiver";
|
|
|
const char kSupportsDynamicPropertiesPrivateKey[] =
|
|
|
"electron_contextBridge_supportsDynamicProperties";
|
|
|
const char kOriginalFunctionPrivateKey[] = "electron_contextBridge_original_fn";
|
|
@@ -138,6 +140,7 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContext(
|
|
|
v8::Local<v8::Context> source_context,
|
|
|
v8::Local<v8::Context> destination_context,
|
|
|
v8::Local<v8::Value> value,
|
|
|
+ v8::Local<v8::Value> parent_value,
|
|
|
context_bridge::ObjectCache* object_cache,
|
|
|
bool support_dynamic_properties,
|
|
|
int recursion_depth,
|
|
@@ -199,6 +202,9 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContext(
|
|
|
v8::Object::New(destination_context->GetIsolate());
|
|
|
SetPrivate(destination_context, state,
|
|
|
context_bridge::kProxyFunctionPrivateKey, func);
|
|
|
+ SetPrivate(destination_context, state,
|
|
|
+ context_bridge::kProxyFunctionReceiverPrivateKey,
|
|
|
+ parent_value);
|
|
|
SetPrivate(destination_context, state,
|
|
|
context_bridge::kSupportsDynamicPropertiesPrivateKey,
|
|
|
gin::ConvertToV8(destination_context->GetIsolate(),
|
|
@@ -246,10 +252,12 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContext(
|
|
|
v8::MaybeLocal<v8::Value> val;
|
|
|
{
|
|
|
v8::TryCatch try_catch(isolate);
|
|
|
+ v8::Local<v8::Context> source_context =
|
|
|
+ global_source_context.Get(isolate);
|
|
|
val = PassValueToOtherContext(
|
|
|
- global_source_context.Get(isolate),
|
|
|
- global_destination_context.Get(isolate), result, &object_cache,
|
|
|
- false, 0, BridgeErrorTarget::kDestination);
|
|
|
+ source_context, global_destination_context.Get(isolate), result,
|
|
|
+ source_context->Global(), &object_cache, false, 0,
|
|
|
+ BridgeErrorTarget::kDestination);
|
|
|
if (try_catch.HasCaught()) {
|
|
|
if (try_catch.Message().IsEmpty()) {
|
|
|
proxied_promise->RejectWithErrorMessage(
|
|
@@ -292,10 +300,12 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContext(
|
|
|
v8::MaybeLocal<v8::Value> val;
|
|
|
{
|
|
|
v8::TryCatch try_catch(isolate);
|
|
|
+ v8::Local<v8::Context> source_context =
|
|
|
+ global_source_context.Get(isolate);
|
|
|
val = PassValueToOtherContext(
|
|
|
- global_source_context.Get(isolate),
|
|
|
- global_destination_context.Get(isolate), result, &object_cache,
|
|
|
- false, 0, BridgeErrorTarget::kDestination);
|
|
|
+ source_context, global_destination_context.Get(isolate), result,
|
|
|
+ source_context->Global(), &object_cache, false, 0,
|
|
|
+ BridgeErrorTarget::kDestination);
|
|
|
if (try_catch.HasCaught()) {
|
|
|
if (try_catch.Message().IsEmpty()) {
|
|
|
proxied_promise->RejectWithErrorMessage(
|
|
@@ -362,7 +372,7 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContext(
|
|
|
for (size_t i = 0; i < length; i++) {
|
|
|
auto value_for_array = PassValueToOtherContext(
|
|
|
source_context, destination_context,
|
|
|
- arr->Get(source_context, i).ToLocalChecked(), object_cache,
|
|
|
+ arr->Get(source_context, i).ToLocalChecked(), value, object_cache,
|
|
|
support_dynamic_properties, recursion_depth + 1, error_target);
|
|
|
if (value_for_array.IsEmpty())
|
|
|
return v8::MaybeLocal<v8::Value>();
|
|
@@ -440,8 +450,10 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo<v8::Value>& info) {
|
|
|
context_bridge::kSupportsDynamicPropertiesPrivateKey);
|
|
|
v8::MaybeLocal<v8::Value> maybe_func = GetPrivate(
|
|
|
calling_context, data, context_bridge::kProxyFunctionPrivateKey);
|
|
|
+ v8::MaybeLocal<v8::Value> maybe_recv = GetPrivate(
|
|
|
+ calling_context, data, context_bridge::kProxyFunctionReceiverPrivateKey);
|
|
|
v8::Local<v8::Value> func_value;
|
|
|
- if (sdp_value.IsEmpty() || maybe_func.IsEmpty() ||
|
|
|
+ if (sdp_value.IsEmpty() || maybe_func.IsEmpty() || maybe_recv.IsEmpty() ||
|
|
|
!gin::ConvertFromV8(args.isolate(), sdp_value.ToLocalChecked(),
|
|
|
&support_dynamic_properties) ||
|
|
|
!maybe_func.ToLocal(&func_value))
|
|
@@ -461,8 +473,9 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo<v8::Value>& info) {
|
|
|
|
|
|
for (auto value : original_args) {
|
|
|
auto arg = PassValueToOtherContext(
|
|
|
- calling_context, func_owning_context, value, &object_cache,
|
|
|
- support_dynamic_properties, 0, BridgeErrorTarget::kSource);
|
|
|
+ calling_context, func_owning_context, value,
|
|
|
+ calling_context->Global(), &object_cache, support_dynamic_properties,
|
|
|
+ 0, BridgeErrorTarget::kSource);
|
|
|
if (arg.IsEmpty())
|
|
|
return;
|
|
|
proxied_args.push_back(arg.ToLocalChecked());
|
|
@@ -473,8 +486,9 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo<v8::Value>& info) {
|
|
|
v8::Local<v8::Value> error_message;
|
|
|
{
|
|
|
v8::TryCatch try_catch(args.isolate());
|
|
|
- maybe_return_value = func->Call(func_owning_context, func,
|
|
|
- proxied_args.size(), proxied_args.data());
|
|
|
+ maybe_return_value =
|
|
|
+ func->Call(func_owning_context, maybe_recv.ToLocalChecked(),
|
|
|
+ proxied_args.size(), proxied_args.data());
|
|
|
if (try_catch.HasCaught()) {
|
|
|
did_error = true;
|
|
|
v8::Local<v8::Value> exception = try_catch.Exception();
|
|
@@ -529,6 +543,7 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo<v8::Value>& info) {
|
|
|
v8::TryCatch try_catch(args.isolate());
|
|
|
ret = PassValueToOtherContext(func_owning_context, calling_context,
|
|
|
maybe_return_value.ToLocalChecked(),
|
|
|
+ func_owning_context->Global(),
|
|
|
&object_cache, support_dynamic_properties,
|
|
|
0, BridgeErrorTarget::kDestination);
|
|
|
if (try_catch.HasCaught()) {
|
|
@@ -605,18 +620,18 @@ v8::MaybeLocal<v8::Object> CreateProxyForAPI(
|
|
|
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,
|
|
|
- error_target)
|
|
|
+ if (!PassValueToOtherContext(
|
|
|
+ source_context, destination_context, getter,
|
|
|
+ api.GetHandle(), object_cache,
|
|
|
+ support_dynamic_properties, 1, error_target)
|
|
|
.ToLocal(&getter_proxy))
|
|
|
continue;
|
|
|
}
|
|
|
if (!setter.IsEmpty()) {
|
|
|
- if (!PassValueToOtherContext(source_context, destination_context,
|
|
|
- setter, object_cache,
|
|
|
- support_dynamic_properties, 1,
|
|
|
- error_target)
|
|
|
+ if (!PassValueToOtherContext(
|
|
|
+ source_context, destination_context, setter,
|
|
|
+ api.GetHandle(), object_cache,
|
|
|
+ support_dynamic_properties, 1, error_target)
|
|
|
.ToLocal(&setter_proxy))
|
|
|
continue;
|
|
|
}
|
|
@@ -633,8 +648,9 @@ v8::MaybeLocal<v8::Object> CreateProxyForAPI(
|
|
|
continue;
|
|
|
|
|
|
auto passed_value = PassValueToOtherContext(
|
|
|
- source_context, destination_context, value, object_cache,
|
|
|
- support_dynamic_properties, recursion_depth + 1, error_target);
|
|
|
+ source_context, destination_context, value, api.GetHandle(),
|
|
|
+ object_cache, support_dynamic_properties, recursion_depth + 1,
|
|
|
+ error_target);
|
|
|
if (passed_value.IsEmpty())
|
|
|
return v8::MaybeLocal<v8::Object>();
|
|
|
proxy.Set(key, passed_value.ToLocalChecked());
|
|
@@ -681,7 +697,8 @@ void ExposeAPIInWorld(v8::Isolate* isolate,
|
|
|
v8::Context::Scope target_context_scope(target_context);
|
|
|
|
|
|
v8::MaybeLocal<v8::Value> maybe_proxy = PassValueToOtherContext(
|
|
|
- electron_isolated_context, target_context, api, &object_cache, false, 0,
|
|
|
+ electron_isolated_context, target_context, api,
|
|
|
+ electron_isolated_context->Global(), &object_cache, false, 0,
|
|
|
BridgeErrorTarget::kSource);
|
|
|
if (maybe_proxy.IsEmpty())
|
|
|
return;
|
|
@@ -730,9 +747,11 @@ void OverrideGlobalValueFromIsolatedWorld(
|
|
|
{
|
|
|
v8::Context::Scope main_context_scope(main_context);
|
|
|
context_bridge::ObjectCache object_cache;
|
|
|
+ v8::Local<v8::Context> source_context = value->GetCreationContextChecked();
|
|
|
v8::MaybeLocal<v8::Value> maybe_proxy = PassValueToOtherContext(
|
|
|
- value->GetCreationContextChecked(), main_context, value, &object_cache,
|
|
|
- support_dynamic_properties, 1, BridgeErrorTarget::kSource);
|
|
|
+ source_context, main_context, value, source_context->Global(),
|
|
|
+ &object_cache, support_dynamic_properties, 1,
|
|
|
+ BridgeErrorTarget::kSource);
|
|
|
DCHECK(!maybe_proxy.IsEmpty());
|
|
|
auto proxy = maybe_proxy.ToLocalChecked();
|
|
|
|
|
@@ -766,15 +785,19 @@ bool OverrideGlobalPropertyFromIsolatedWorld(
|
|
|
v8::Local<v8::Value> getter_proxy;
|
|
|
v8::Local<v8::Value> setter_proxy;
|
|
|
if (!getter->IsNullOrUndefined()) {
|
|
|
+ v8::Local<v8::Context> source_context =
|
|
|
+ getter->GetCreationContextChecked();
|
|
|
v8::MaybeLocal<v8::Value> maybe_getter_proxy = PassValueToOtherContext(
|
|
|
- getter->GetCreationContextChecked(), main_context, getter,
|
|
|
+ source_context, main_context, getter, source_context->Global(),
|
|
|
&object_cache, false, 1, BridgeErrorTarget::kSource);
|
|
|
DCHECK(!maybe_getter_proxy.IsEmpty());
|
|
|
getter_proxy = maybe_getter_proxy.ToLocalChecked();
|
|
|
}
|
|
|
if (!setter->IsNullOrUndefined() && setter->IsObject()) {
|
|
|
+ v8::Local<v8::Context> source_context =
|
|
|
+ getter->GetCreationContextChecked();
|
|
|
v8::MaybeLocal<v8::Value> maybe_setter_proxy = PassValueToOtherContext(
|
|
|
- getter->GetCreationContextChecked(), main_context, setter,
|
|
|
+ source_context, main_context, setter, source_context->Global(),
|
|
|
&object_cache, false, 1, BridgeErrorTarget::kSource);
|
|
|
DCHECK(!maybe_setter_proxy.IsEmpty());
|
|
|
setter_proxy = maybe_setter_proxy.ToLocalChecked();
|