Browse Source

refactor: ginify Screen (#24677)

Jeremy Rose 4 years ago
parent
commit
e6cf5906f6

+ 0 - 1
filenames.auto.gni

@@ -238,7 +238,6 @@ auto_filenames = {
     "lib/browser/remote/objects-registry.ts",
     "lib/browser/remote/server.ts",
     "lib/browser/rpc-server.ts",
-    "lib/browser/utils.ts",
     "lib/common/api/clipboard.ts",
     "lib/common/api/deprecate.ts",
     "lib/common/api/module-list.ts",

+ 18 - 8
lib/browser/api/screen.ts

@@ -1,10 +1,20 @@
-'use strict';
+const { createScreen } = process._linkedBinding('electron_common_screen');
 
-import { createLazyInstance } from '@electron/internal/browser/utils';
-const { EventEmitter } = require('events');
-const { Screen, createScreen } = process._linkedBinding('electron_common_screen');
+let _screen: Electron.Screen;
 
-// Screen is an EventEmitter.
-Object.setPrototypeOf(Screen.prototype, EventEmitter.prototype);
-
-module.exports = createLazyInstance(createScreen, Screen, true);
+// We can't call createScreen until after app.on('ready'), but this module
+// exposes an instance created by createScreen. In order to avoid
+// side-effecting and calling createScreen upon import of this module, instead
+// we export a proxy which lazily calls createScreen on first access.
+export default new Proxy({}, {
+  get: (target, prop) => {
+    if (_screen === undefined) {
+      _screen = createScreen();
+    }
+    const v = (_screen as any)[prop];
+    if (typeof v === 'function') {
+      return v.bind(_screen);
+    }
+    return v;
+  }
+});

+ 0 - 38
lib/browser/utils.ts

@@ -1,38 +0,0 @@
-import { EventEmitter } from 'events';
-
-/**
-* Creates a lazy instance of modules that can't be required before the
-* app 'ready' event by returning a proxy object to mitigate side effects
-* on 'require'
-*
-* @param {Function} creator - Function that creates a new module instance
-* @param {Object} holder - the object holding the module prototype
-* @param {Boolean} isEventEmitter - whether or not the module is an EventEmitter
-* @returns {Object} - a proxy object for the
-*/
-
-export function createLazyInstance (
-  creator: Function,
-  holder: Object,
-  isEventEmitter: Boolean
-) {
-  let lazyModule: Object;
-  const module: any = {};
-  for (const method in (holder as any).prototype) { // eslint-disable-line guard-for-in
-    module[method] = (...args: any) => {
-      // create new instance of module at runtime if none exists
-      if (!lazyModule) {
-        lazyModule = creator();
-        if (isEventEmitter) EventEmitter.call(lazyModule as any);
-      }
-
-      // check for properties on the prototype chain that aren't functions
-      if (typeof (lazyModule as any)[method] !== 'function') {
-        return (lazyModule as any)[method];
-      }
-
-      return (lazyModule as any)[method](...args);
-    };
-  }
-  return module;
-}

+ 10 - 9
shell/browser/api/electron_api_screen.cc

@@ -29,6 +29,8 @@ namespace electron {
 
 namespace api {
 
+gin::WrapperInfo Screen::kWrapperInfo = {gin::kEmbedderNativeGin};
+
 namespace {
 
 // Find an item in container according to its ID.
@@ -72,7 +74,6 @@ void DelayEmitWithMetrics(Screen* screen,
 Screen::Screen(v8::Isolate* isolate, display::Screen* screen)
     : screen_(screen) {
   screen_->AddObserver(this);
-  Init(isolate);
 }
 
 Screen::~Screen() {
@@ -154,11 +155,10 @@ v8::Local<v8::Value> Screen::Create(gin_helper::ErrorThrower error_thrower) {
       .ToV8();
 }
 
-// static
-void Screen::BuildPrototype(v8::Isolate* isolate,
-                            v8::Local<v8::FunctionTemplate> prototype) {
-  prototype->SetClassName(gin::StringToV8(isolate, "Screen"));
-  gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
+gin::ObjectTemplateBuilder Screen::GetObjectTemplateBuilder(
+    v8::Isolate* isolate) {
+  return gin_helper::EventEmitterMixin<Screen>::GetObjectTemplateBuilder(
+             isolate)
       .SetMethod("getCursorScreenPoint", &Screen::GetCursorScreenPoint)
       .SetMethod("getPrimaryDisplay", &Screen::GetPrimaryDisplay)
       .SetMethod("getAllDisplays", &Screen::GetAllDisplays)
@@ -172,6 +172,10 @@ void Screen::BuildPrototype(v8::Isolate* isolate,
       .SetMethod("getDisplayMatching", &Screen::GetDisplayMatching);
 }
 
+const char* Screen::GetTypeName() {
+  return "Screen";
+}
+
 }  // namespace api
 
 }  // namespace electron
@@ -187,9 +191,6 @@ void Initialize(v8::Local<v8::Object> exports,
   v8::Isolate* isolate = context->GetIsolate();
   gin_helper::Dictionary dict(isolate, exports);
   dict.SetMethod("createScreen", base::BindRepeating(&Screen::Create));
-  dict.Set(
-      "Screen",
-      Screen::GetConstructor(isolate)->GetFunction(context).ToLocalChecked());
 }
 
 }  // namespace

+ 8 - 4
shell/browser/api/electron_api_screen.h

@@ -7,8 +7,9 @@
 
 #include <vector>
 
+#include "gin/wrappable.h"
+#include "shell/browser/event_emitter_mixin.h"
 #include "shell/common/gin_helper/error_thrower.h"
-#include "shell/common/gin_helper/event_emitter.h"
 #include "ui/display/display_observer.h"
 #include "ui/display/screen.h"
 
@@ -22,13 +23,16 @@ namespace electron {
 
 namespace api {
 
-class Screen : public gin_helper::EventEmitter<Screen>,
+class Screen : public gin::Wrappable<Screen>,
+               public gin_helper::EventEmitterMixin<Screen>,
                public display::DisplayObserver {
  public:
   static v8::Local<v8::Value> Create(gin_helper::ErrorThrower error_thrower);
 
-  static void BuildPrototype(v8::Isolate* isolate,
-                             v8::Local<v8::FunctionTemplate> prototype);
+  static gin::WrapperInfo kWrapperInfo;
+  gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
+      v8::Isolate* isolate) override;
+  const char* GetTypeName() override;
 
  protected:
   Screen(v8::Isolate* isolate, display::Screen* screen);