diff --git a/lib/browser/remote/server.ts b/lib/browser/remote/server.ts index 41d3c2a9cfaf..3fea88c25adb 100644 --- a/lib/browser/remote/server.ts +++ b/lib/browser/remote/server.ts @@ -8,7 +8,6 @@ import type { MetaTypeFromRenderer, ObjectMember, MetaType, ObjProtoDescriptor } const v8Util = process._linkedBinding('electron_common_v8_util'); const eventBinding = process._linkedBinding('electron_browser_event'); const features = process._linkedBinding('electron_common_features'); -const { NativeImage } = process._linkedBinding('electron_common_native_image'); if (!features.isRemoteModuleEnabled()) { throw new Error('remote module is disabled'); @@ -102,7 +101,7 @@ const valueToMeta = function (sender: electron.WebContents, contextId: string, v // Recognize certain types of objects. if (value instanceof Buffer) { type = 'buffer'; - } else if (value instanceof NativeImage) { + } else if (value && value.constructor && value.constructor.name === 'NativeImage') { type = 'nativeimage'; } else if (Array.isArray(value)) { type = 'array'; diff --git a/lib/common/type-utils.ts b/lib/common/type-utils.ts index 9500e838d12a..2fd2fdb2f2aa 100644 --- a/lib/common/type-utils.ts +++ b/lib/common/type-utils.ts @@ -1,4 +1,4 @@ -const { nativeImage, NativeImage } = process._linkedBinding('electron_common_native_image'); +const { nativeImage } = process._linkedBinding('electron_common_native_image'); export function isPromise (val: any) { return ( @@ -80,7 +80,7 @@ function deserializeNativeImage (value: any) { } export function serialize (value: any): any { - if (value instanceof NativeImage) { + if (value && value.constructor && value.constructor.name === 'NativeImage') { return serializeNativeImage(value); } if (Array.isArray(value)) { return value.map(serialize); diff --git a/lib/renderer/api/remote.ts b/lib/renderer/api/remote.ts index b4ec0db3539b..b30fe3202b02 100644 --- a/lib/renderer/api/remote.ts +++ b/lib/renderer/api/remote.ts @@ -8,7 +8,6 @@ import { commonModuleList } from '@electron/internal/common/api/module-list'; const v8Util = process._linkedBinding('electron_common_v8_util'); const { hasSwitch } = process._linkedBinding('electron_common_command_line'); -const { NativeImage } = process._linkedBinding('electron_common_native_image'); const callbacksRegistry = new CallbacksRegistry(); const remoteObjectCache = new Map(); @@ -59,7 +58,7 @@ function wrapArgs (args: any[], visited = new Set()): any { }; } - if (value instanceof NativeImage) { + if (value && value.constructor && value.constructor.name === 'NativeImage') { return { type: 'nativeimage', value: serialize(value) }; } else if (Array.isArray(value)) { visited.add(value); diff --git a/shell/common/api/electron_api_native_image.cc b/shell/common/api/electron_api_native_image.cc index 255f6a533d6e..a51274ea3651 100644 --- a/shell/common/api/electron_api_native_image.cc +++ b/shell/common/api/electron_api_native_image.cc @@ -14,6 +14,9 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_restrictions.h" +#include "gin/arguments.h" +#include "gin/object_template_builder.h" +#include "gin/per_isolate_data.h" #include "net/base/data_url.h" #include "shell/common/asar/asar_util.h" #include "shell/common/gin_converters/file_path_converter.h" @@ -21,6 +24,7 @@ #include "shell/common/gin_converters/gurl_converter.h" #include "shell/common/gin_converters/value_converter.h" #include "shell/common/gin_helper/dictionary.h" +#include "shell/common/gin_helper/function_template_extensions.h" #include "shell/common/gin_helper/object_template_builder.h" #include "shell/common/node_includes.h" #include "shell/common/skia_util.h" @@ -104,24 +108,22 @@ void Noop(char*, void*) {} } // namespace NativeImage::NativeImage(v8::Isolate* isolate, const gfx::Image& image) - : image_(image) { - Init(isolate); + : image_(image), isolate_(isolate) { if (image_.HasRepresentation(gfx::Image::kImageRepSkia)) { - isolate->AdjustAmountOfExternalAllocatedMemory( + isolate_->AdjustAmountOfExternalAllocatedMemory( image_.ToImageSkia()->bitmap()->computeByteSize()); } } #if defined(OS_WIN) NativeImage::NativeImage(v8::Isolate* isolate, const base::FilePath& hicon_path) - : hicon_path_(hicon_path) { + : hicon_path_(hicon_path), isolate_(isolate) { // Use the 256x256 icon as fallback icon. gfx::ImageSkia image_skia; electron::util::ReadImageSkiaFromICO(&image_skia, GetHICON(256)); image_ = gfx::Image(image_skia); - Init(isolate); if (image_.HasRepresentation(gfx::Image::kImageRepSkia)) { - isolate->AdjustAmountOfExternalAllocatedMemory( + isolate_->AdjustAmountOfExternalAllocatedMemory( image_.ToImageSkia()->bitmap()->computeByteSize()); } } @@ -129,7 +131,7 @@ NativeImage::NativeImage(v8::Isolate* isolate, const base::FilePath& hicon_path) NativeImage::~NativeImage() { if (image_.HasRepresentation(gfx::Image::kImageRepSkia)) { - isolate()->AdjustAmountOfExternalAllocatedMemory(-static_cast( + isolate_->AdjustAmountOfExternalAllocatedMemory(-static_cast( image_.ToImageSkia()->bitmap()->computeByteSize())); } } @@ -510,10 +512,19 @@ gin::Handle NativeImage::CreateFromNamedImage(gin::Arguments* args, #endif // static -void NativeImage::BuildPrototype(v8::Isolate* isolate, - v8::Local prototype) { - prototype->SetClassName(gin::StringToV8(isolate, "NativeImage")); - gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) +gin::ObjectTemplateBuilder NativeImage::GetObjectTemplateBuilder( + v8::Isolate* isolate) { + gin::PerIsolateData* data = gin::PerIsolateData::From(isolate); + auto* wrapper_info = &kWrapperInfo; + v8::Local constructor = + data->GetFunctionTemplate(wrapper_info); + if (constructor.IsEmpty()) { + constructor = v8::FunctionTemplate::New(isolate); + constructor->SetClassName(gin::StringToV8(isolate, GetTypeName())); + data->SetFunctionTemplate(wrapper_info, constructor); + } + return gin::ObjectTemplateBuilder(isolate, GetTypeName(), + constructor->InstanceTemplate()) .SetMethod("toPNG", &NativeImage::ToPNG) .SetMethod("toJPEG", &NativeImage::ToJPEG) .SetMethod("toBitmap", &NativeImage::ToBitmap) @@ -533,6 +544,13 @@ void NativeImage::BuildPrototype(v8::Isolate* isolate, .SetMethod("addRepresentation", &NativeImage::AddRepresentation); } +const char* NativeImage::GetTypeName() { + return "NativeImage"; +} + +// static +gin::WrapperInfo NativeImage::kWrapperInfo = {gin::kEmbedderNativeGin}; + } // namespace api } // namespace electron @@ -542,8 +560,9 @@ namespace gin { v8::Local Converter::ToV8( v8::Isolate* isolate, electron::api::NativeImage* val) { - if (val) - return val->GetWrapper(); + v8::Local ret; + if (val && val->GetWrapper(isolate).ToLocal(&ret)) + return ret; else return v8::Null(isolate); } @@ -570,9 +589,11 @@ bool Converter::FromV8( return true; } + // reinterpret_cast is safe here because NativeImage is the only subclass of + // gin::Wrappable. *out = static_cast( - static_cast( - gin_helper::internal::FromV8Impl(isolate, val))); + static_cast(gin::internal::FromV8Impl( + isolate, val, &electron::api::NativeImage::kWrapperInfo))); return *out != nullptr; } @@ -588,9 +609,6 @@ void Initialize(v8::Local exports, void* priv) { v8::Isolate* isolate = context->GetIsolate(); gin_helper::Dictionary dict(isolate, exports); - dict.Set("NativeImage", NativeImage::GetConstructor(isolate) - ->GetFunction(context) - .ToLocalChecked()); gin_helper::Dictionary native_image = gin::Dictionary::CreateEmpty(isolate); dict.Set("nativeImage", native_image); diff --git a/shell/common/api/electron_api_native_image.h b/shell/common/api/electron_api_native_image.h index 4b9ced24602f..09da8faf79b6 100644 --- a/shell/common/api/electron_api_native_image.h +++ b/shell/common/api/electron_api_native_image.h @@ -11,8 +11,8 @@ #include "base/values.h" #include "gin/handle.h" +#include "gin/wrappable.h" #include "shell/common/gin_helper/error_thrower.h" -#include "shell/common/gin_helper/wrappable.h" #include "ui/gfx/image/image.h" #if defined(OS_WIN) @@ -35,11 +35,15 @@ namespace gin_helper { class Dictionary; } +namespace gin { +class Arguments; +} + namespace electron { namespace api { -class NativeImage : public gin_helper::Wrappable { +class NativeImage : public gin::Wrappable { public: static gin::Handle CreateEmpty(v8::Isolate* isolate); static gin::Handle Create(v8::Isolate* isolate, @@ -65,8 +69,13 @@ class NativeImage : public gin_helper::Wrappable { static gin::Handle CreateFromNamedImage(gin::Arguments* args, std::string name); - static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + static v8::Local GetConstructor(v8::Isolate* isolate); + + // gin::Wrappable + static gin::WrapperInfo kWrapperInfo; + gin::ObjectTemplateBuilder GetObjectTemplateBuilder( + v8::Isolate* isolate) override; + const char* GetTypeName() override; #if defined(OS_WIN) HICON GetHICON(int size); @@ -109,6 +118,8 @@ class NativeImage : public gin_helper::Wrappable { gfx::Image image_; + v8::Isolate* isolate_; + DISALLOW_COPY_AND_ASSIGN(NativeImage); }; diff --git a/shell/common/api/electron_api_native_image_mac.mm b/shell/common/api/electron_api_native_image_mac.mm index 607f24b7575f..8124f5a9d4cd 100644 --- a/shell/common/api/electron_api_native_image_mac.mm +++ b/shell/common/api/electron_api_native_image_mac.mm @@ -10,6 +10,7 @@ #import #include "base/strings/sys_string_conversions.h" +#include "gin/arguments.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h"