Browse Source

refactor: ginify NativeImage (#24486)

Jeremy Rose 4 years ago
parent
commit
36bd940bc3

+ 1 - 2
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';

+ 2 - 2
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);

+ 1 - 2
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);

+ 36 - 18
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<int64_t>(
+    isolate_->AdjustAmountOfExternalAllocatedMemory(-static_cast<int64_t>(
         image_.ToImageSkia()->bitmap()->computeByteSize()));
   }
 }
@@ -510,10 +512,19 @@ gin::Handle<NativeImage> NativeImage::CreateFromNamedImage(gin::Arguments* args,
 #endif
 
 // static
-void NativeImage::BuildPrototype(v8::Isolate* isolate,
-                                 v8::Local<v8::FunctionTemplate> 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<v8::FunctionTemplate> 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<v8::Value> Converter<electron::api::NativeImage*>::ToV8(
     v8::Isolate* isolate,
     electron::api::NativeImage* val) {
-  if (val)
-    return val->GetWrapper();
+  v8::Local<v8::Object> ret;
+  if (val && val->GetWrapper(isolate).ToLocal(&ret))
+    return ret;
   else
     return v8::Null(isolate);
 }
@@ -570,9 +589,11 @@ bool Converter<electron::api::NativeImage*>::FromV8(
     return true;
   }
 
+  // reinterpret_cast is safe here because NativeImage is the only subclass of
+  // gin::Wrappable<NativeImage>.
   *out = static_cast<electron::api::NativeImage*>(
-      static_cast<gin_helper::WrappableBase*>(
-          gin_helper::internal::FromV8Impl(isolate, val)));
+      static_cast<gin::WrappableBase*>(gin::internal::FromV8Impl(
+          isolate, val, &electron::api::NativeImage::kWrapperInfo)));
   return *out != nullptr;
 }
 
@@ -588,9 +609,6 @@ void Initialize(v8::Local<v8::Object> 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);
 

+ 15 - 4
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<NativeImage> {
+class NativeImage : public gin::Wrappable<NativeImage> {
  public:
   static gin::Handle<NativeImage> CreateEmpty(v8::Isolate* isolate);
   static gin::Handle<NativeImage> Create(v8::Isolate* isolate,
@@ -65,8 +69,13 @@ class NativeImage : public gin_helper::Wrappable<NativeImage> {
   static gin::Handle<NativeImage> CreateFromNamedImage(gin::Arguments* args,
                                                        std::string name);
 
-  static void BuildPrototype(v8::Isolate* isolate,
-                             v8::Local<v8::FunctionTemplate> prototype);
+  static v8::Local<v8::FunctionTemplate> 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<NativeImage> {
 
   gfx::Image image_;
 
+  v8::Isolate* isolate_;
+
   DISALLOW_COPY_AND_ASSIGN(NativeImage);
 };
 

+ 1 - 0
shell/common/api/electron_api_native_image_mac.mm

@@ -10,6 +10,7 @@
 #import <Cocoa/Cocoa.h>
 
 #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"