Browse Source

Merge pull request #5280 from electron/better-wrappable

Clean up the Wrappable class
Cheng Zhao 9 years ago
parent
commit
60b9ff3948
52 changed files with 368 additions and 391 deletions
  1. 11 9
      atom/browser/api/atom_api_app.cc
  2. 6 7
      atom/browser/api/atom_api_app.h
  3. 12 10
      atom/browser/api/atom_api_auto_updater.cc
  4. 6 7
      atom/browser/api/atom_api_auto_updater.h
  5. 5 3
      atom/browser/api/atom_api_cookies.cc
  6. 2 2
      atom/browser/api/atom_api_cookies.h
  7. 4 10
      atom/browser/api/atom_api_debugger.cc
  8. 2 2
      atom/browser/api/atom_api_debugger.h
  9. 9 7
      atom/browser/api/atom_api_desktop_capturer.cc
  10. 6 7
      atom/browser/api/atom_api_desktop_capturer.h
  11. 4 10
      atom/browser/api/atom_api_download_item.cc
  12. 1 2
      atom/browser/api/atom_api_download_item.h
  13. 11 9
      atom/browser/api/atom_api_global_shortcut.cc
  14. 4 5
      atom/browser/api/atom_api_global_shortcut.h
  15. 2 2
      atom/browser/api/atom_api_menu.cc
  16. 2 2
      atom/browser/api/atom_api_menu.h
  17. 1 1
      atom/browser/api/atom_api_menu_mac.h
  18. 3 3
      atom/browser/api/atom_api_menu_mac.mm
  19. 3 3
      atom/browser/api/atom_api_menu_views.cc
  20. 1 1
      atom/browser/api/atom_api_menu_views.h
  21. 8 2
      atom/browser/api/atom_api_power_monitor.cc
  22. 4 1
      atom/browser/api/atom_api_power_monitor.h
  23. 12 10
      atom/browser/api/atom_api_power_save_blocker.cc
  24. 4 5
      atom/browser/api/atom_api_power_save_blocker.h
  25. 31 29
      atom/browser/api/atom_api_protocol.cc
  26. 5 6
      atom/browser/api/atom_api_protocol.h
  27. 15 12
      atom/browser/api/atom_api_screen.cc
  28. 6 7
      atom/browser/api/atom_api_screen.h
  29. 9 12
      atom/browser/api/atom_api_session.cc
  30. 1 1
      atom/browser/api/atom_api_session.h
  31. 3 3
      atom/browser/api/atom_api_tray.cc
  32. 3 2
      atom/browser/api/atom_api_tray.h
  33. 10 12
      atom/browser/api/atom_api_web_contents.cc
  34. 4 5
      atom/browser/api/atom_api_web_contents.h
  35. 4 2
      atom/browser/api/atom_api_web_request.cc
  36. 2 3
      atom/browser/api/atom_api_web_request.h
  37. 3 3
      atom/browser/api/atom_api_window.cc
  38. 2 2
      atom/browser/api/atom_api_window.h
  39. 12 20
      atom/browser/api/event.cc
  40. 6 6
      atom/browser/api/event.h
  41. 14 8
      atom/browser/api/event_emitter.cc
  42. 27 11
      atom/browser/api/event_emitter.h
  43. 0 9
      atom/browser/api/trackable_object.cc
  44. 13 35
      atom/browser/api/trackable_object.h
  45. 24 24
      atom/common/api/atom_api_asar.cc
  46. 3 3
      atom/common/api/atom_api_id_weak_map.cc
  47. 3 3
      atom/common/api/atom_api_id_weak_map.h
  48. 21 26
      atom/common/api/atom_api_native_image.cc
  49. 5 9
      atom/common/api/atom_api_native_image.h
  50. 12 10
      atom/renderer/api/atom_api_web_frame.cc
  51. 6 7
      atom/renderer/api/atom_api_web_frame.h
  52. 1 1
      vendor/native_mate

+ 11 - 9
atom/browser/api/atom_api_app.cc

@@ -194,10 +194,11 @@ int ImportIntoCertStore(
 
 }  // namespace
 
-App::App() {
+App::App(v8::Isolate* isolate) {
   static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(this);
   Browser::Get()->AddObserver(this);
   content::GpuDataManager::GetInstance()->AddObserver(this);
+  Init(isolate);
 }
 
 App::~App() {
@@ -439,10 +440,16 @@ void App::OnCertificateManagerModelCreated(
 }
 #endif
 
-mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
-    v8::Isolate* isolate) {
+// static
+mate::Handle<App> App::Create(v8::Isolate* isolate) {
+  return mate::CreateHandle(isolate, new App(isolate));
+}
+
+// static
+void App::BuildPrototype(
+    v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) {
   auto browser = base::Unretained(Browser::Get());
-  return mate::ObjectTemplateBuilder(isolate)
+  mate::ObjectTemplateBuilder(isolate, prototype)
       .SetMethod("quit", base::Bind(&Browser::Quit, browser))
       .SetMethod("exit", base::Bind(&Browser::Exit, browser))
       .SetMethod("focus", base::Bind(&Browser::Focus, browser))
@@ -484,11 +491,6 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
       .SetMethod("makeSingleInstance", &App::MakeSingleInstance);
 }
 
-// static
-mate::Handle<App> App::Create(v8::Isolate* isolate) {
-  return CreateHandle(isolate, new App);
-}
-
 }  // namespace api
 
 }  // namespace atom

+ 6 - 7
atom/browser/api/atom_api_app.h

@@ -33,12 +33,15 @@ namespace atom {
 namespace api {
 
 class App : public AtomBrowserClient::Delegate,
-            public mate::EventEmitter,
+            public mate::EventEmitter<App>,
             public BrowserObserver,
             public content::GpuDataManagerObserver {
  public:
   static mate::Handle<App> Create(v8::Isolate* isolate);
 
+  static void BuildPrototype(v8::Isolate* isolate,
+                             v8::Local<v8::ObjectTemplate> prototype);
+
   // Called when window with disposition needs to be created.
   void OnCreateWindow(const GURL& target_url,
                       const std::string& frame_name,
@@ -54,8 +57,8 @@ class App : public AtomBrowserClient::Delegate,
 #endif
 
  protected:
-  App();
-  virtual ~App();
+  explicit App(v8::Isolate* isolate);
+  ~App() override;
 
   // BrowserObserver:
   void OnBeforeQuit(bool* prevent_default) override;
@@ -93,10 +96,6 @@ class App : public AtomBrowserClient::Delegate,
   void OnPlatformThemeChanged() override;
 #endif
 
-  // mate::Wrappable:
-  mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
-      v8::Isolate* isolate) override;
-
  private:
   // Get/Set the pre-defined path in PathService.
   base::FilePath GetPath(mate::Arguments* args, const std::string& name);

+ 12 - 10
atom/browser/api/atom_api_auto_updater.cc

@@ -34,8 +34,9 @@ namespace atom {
 
 namespace api {
 
-AutoUpdater::AutoUpdater() {
+AutoUpdater::AutoUpdater(v8::Isolate* isolate) {
   auto_updater::AutoUpdater::SetDelegate(this);
+  Init(isolate);
 }
 
 AutoUpdater::~AutoUpdater() {
@@ -78,14 +79,6 @@ void AutoUpdater::OnWindowAllClosed() {
   QuitAndInstall();
 }
 
-mate::ObjectTemplateBuilder AutoUpdater::GetObjectTemplateBuilder(
-    v8::Isolate* isolate) {
-  return mate::ObjectTemplateBuilder(isolate)
-      .SetMethod("setFeedURL", &auto_updater::AutoUpdater::SetFeedURL)
-      .SetMethod("checkForUpdates", &auto_updater::AutoUpdater::CheckForUpdates)
-      .SetMethod("quitAndInstall", &AutoUpdater::QuitAndInstall);
-}
-
 void AutoUpdater::QuitAndInstall() {
   // If we don't have any window then quitAndInstall immediately.
   WindowList* window_list = WindowList::GetInstance();
@@ -102,7 +95,16 @@ void AutoUpdater::QuitAndInstall() {
 
 // static
 mate::Handle<AutoUpdater> AutoUpdater::Create(v8::Isolate* isolate) {
-  return CreateHandle(isolate, new AutoUpdater);
+  return mate::CreateHandle(isolate, new AutoUpdater(isolate));
+}
+
+// static
+void AutoUpdater::BuildPrototype(
+    v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) {
+  mate::ObjectTemplateBuilder(isolate, prototype)
+      .SetMethod("setFeedURL", &auto_updater::AutoUpdater::SetFeedURL)
+      .SetMethod("checkForUpdates", &auto_updater::AutoUpdater::CheckForUpdates)
+      .SetMethod("quitAndInstall", &AutoUpdater::QuitAndInstall);
 }
 
 }  // namespace api

+ 6 - 7
atom/browser/api/atom_api_auto_updater.h

@@ -16,15 +16,18 @@ namespace atom {
 
 namespace api {
 
-class AutoUpdater : public mate::EventEmitter,
+class AutoUpdater : public mate::EventEmitter<AutoUpdater>,
                     public auto_updater::Delegate,
                     public WindowListObserver {
  public:
   static mate::Handle<AutoUpdater> Create(v8::Isolate* isolate);
 
+  static void BuildPrototype(v8::Isolate* isolate,
+                             v8::Local<v8::ObjectTemplate> prototype);
+
  protected:
-  AutoUpdater();
-  virtual ~AutoUpdater();
+  explicit AutoUpdater(v8::Isolate* isolate);
+  ~AutoUpdater() override;
 
   // Delegate implementations.
   void OnError(const std::string& error) override;
@@ -39,10 +42,6 @@ class AutoUpdater : public mate::EventEmitter,
   // WindowListObserver:
   void OnWindowAllClosed() override;
 
-  // mate::Wrappable implementations:
-  mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
-      v8::Isolate* isolate) override;
-
  private:
   void QuitAndInstall();
 

+ 5 - 3
atom/browser/api/atom_api_cookies.cc

@@ -186,8 +186,10 @@ void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
 
 }  // namespace
 
-Cookies::Cookies(content::BrowserContext* browser_context)
-    : request_context_getter_(browser_context->GetRequestContext()) {
+Cookies::Cookies(v8::Isolate* isolate,
+                 content::BrowserContext* browser_context)
+      : request_context_getter_(browser_context->GetRequestContext()) {
+  Init(isolate);
 }
 
 Cookies::~Cookies() {
@@ -223,7 +225,7 @@ void Cookies::Set(const base::DictionaryValue& details,
 mate::Handle<Cookies> Cookies::Create(
     v8::Isolate* isolate,
     content::BrowserContext* browser_context) {
-  return mate::CreateHandle(isolate, new Cookies(browser_context));
+  return mate::CreateHandle(isolate, new Cookies(isolate, browser_context));
 }
 
 // static

+ 2 - 2
atom/browser/api/atom_api_cookies.h

@@ -46,8 +46,8 @@ class Cookies : public mate::TrackableObject<Cookies> {
                              v8::Local<v8::ObjectTemplate> prototype);
 
  protected:
-  explicit Cookies(content::BrowserContext* browser_context);
-  ~Cookies();
+  Cookies(v8::Isolate* isolate, content::BrowserContext* browser_context);
+  ~Cookies() override;
 
   void Get(const base::DictionaryValue& filter, const GetCallback& callback);
   void Remove(const GURL& url, const std::string& name,

+ 4 - 10
atom/browser/api/atom_api_debugger.cc

@@ -31,9 +31,10 @@ WrapDebuggerCallback g_wrap_debugger;
 
 }  // namespace
 
-Debugger::Debugger(content::WebContents* web_contents)
+Debugger::Debugger(v8::Isolate* isolate, content::WebContents* web_contents)
     : web_contents_(web_contents),
       previous_request_id_(0) {
+  Init(isolate);
 }
 
 Debugger::~Debugger() {
@@ -150,7 +151,8 @@ void Debugger::SendCommand(mate::Arguments* args) {
 mate::Handle<Debugger> Debugger::Create(
     v8::Isolate* isolate,
     content::WebContents* web_contents) {
-  auto handle = mate::CreateHandle(isolate, new Debugger(web_contents));
+  auto handle = mate::CreateHandle(
+      isolate, new Debugger(isolate, web_contents));
   g_wrap_debugger.Run(handle.ToV8());
   return handle;
 }
@@ -165,16 +167,8 @@ void Debugger::BuildPrototype(v8::Isolate* isolate,
       .SetMethod("sendCommand", &Debugger::SendCommand);
 }
 
-void ClearWrapDebugger() {
-  g_wrap_debugger.Reset();
-}
-
 void SetWrapDebugger(const WrapDebuggerCallback& callback) {
   g_wrap_debugger = callback;
-
-  // Cleanup the wrapper on exit.
-  atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(
-      base::Bind(ClearWrapDebugger));
 }
 
 }  // namespace api

+ 2 - 2
atom/browser/api/atom_api_debugger.h

@@ -42,8 +42,8 @@ class Debugger: public mate::TrackableObject<Debugger>,
                              v8::Local<v8::ObjectTemplate> prototype);
 
  protected:
-  explicit Debugger(content::WebContents* web_contents);
-  ~Debugger();
+  Debugger(v8::Isolate* isolate, content::WebContents* web_contents);
+  ~Debugger() override;
 
   // content::DevToolsAgentHostClient:
   void AgentHostClosed(content::DevToolsAgentHost* agent_host,

+ 9 - 7
atom/browser/api/atom_api_desktop_capturer.cc

@@ -38,7 +38,8 @@ namespace atom {
 
 namespace api {
 
-DesktopCapturer::DesktopCapturer() {
+DesktopCapturer::DesktopCapturer(v8::Isolate* isolate) {
+  Init(isolate);
 }
 
 DesktopCapturer::~DesktopCapturer() {
@@ -92,15 +93,16 @@ bool DesktopCapturer::OnRefreshFinished() {
   return false;
 }
 
-mate::ObjectTemplateBuilder DesktopCapturer::GetObjectTemplateBuilder(
-      v8::Isolate* isolate) {
-  return mate::ObjectTemplateBuilder(isolate)
-      .SetMethod("startHandling", &DesktopCapturer::StartHandling);
+// static
+mate::Handle<DesktopCapturer> DesktopCapturer::Create(v8::Isolate* isolate) {
+  return mate::CreateHandle(isolate, new DesktopCapturer(isolate));
 }
 
 // static
-mate::Handle<DesktopCapturer> DesktopCapturer::Create(v8::Isolate* isolate) {
-  return mate::CreateHandle(isolate, new DesktopCapturer);
+void DesktopCapturer::BuildPrototype(
+    v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) {
+  mate::ObjectTemplateBuilder(isolate, prototype)
+      .SetMethod("startHandling", &DesktopCapturer::StartHandling);
 }
 
 }  // namespace api

+ 6 - 7
atom/browser/api/atom_api_desktop_capturer.h

@@ -14,18 +14,21 @@ namespace atom {
 
 namespace api {
 
-class DesktopCapturer: public mate::EventEmitter,
+class DesktopCapturer: public mate::EventEmitter<DesktopCapturer>,
                        public DesktopMediaListObserver {
  public:
   static mate::Handle<DesktopCapturer> Create(v8::Isolate* isolate);
 
+  static void BuildPrototype(v8::Isolate* isolate,
+                             v8::Local<v8::ObjectTemplate> prototype);
+
   void StartHandling(bool capture_window,
                      bool capture_screen,
                      const gfx::Size& thumbnail_size);
 
  protected:
-  DesktopCapturer();
-  ~DesktopCapturer();
+  explicit DesktopCapturer(v8::Isolate* isolate);
+  ~DesktopCapturer() override;
 
   // DesktopMediaListObserver overrides.
   void OnSourceAdded(int index) override;
@@ -36,10 +39,6 @@ class DesktopCapturer: public mate::EventEmitter,
   bool OnRefreshFinished() override;
 
  private:
-  // mate::Wrappable:
-  mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
-      v8::Isolate* isolate) override;
-
   scoped_ptr<DesktopMediaList> media_list_;
 
   DISALLOW_COPY_AND_ASSIGN(DesktopCapturer);

+ 4 - 10
atom/browser/api/atom_api_download_item.cc

@@ -57,9 +57,11 @@ std::map<uint32_t, linked_ptr<v8::Global<v8::Value>>> g_download_item_objects;
 
 }  // namespace
 
-DownloadItem::DownloadItem(content::DownloadItem* download_item)
+DownloadItem::DownloadItem(v8::Isolate* isolate,
+                           content::DownloadItem* download_item)
     : download_item_(download_item) {
   download_item_->AddObserver(this);
+  Init(isolate);
   AttachAsUserData(download_item);
 }
 
@@ -173,7 +175,7 @@ mate::Handle<DownloadItem> DownloadItem::Create(
   if (existing)
     return mate::CreateHandle(isolate, static_cast<DownloadItem*>(existing));
 
-  auto handle = mate::CreateHandle(isolate, new DownloadItem(item));
+  auto handle = mate::CreateHandle(isolate, new DownloadItem(isolate, item));
   g_wrap_download_item.Run(handle.ToV8());
 
   // Reference this object in case it got garbage collected.
@@ -182,16 +184,8 @@ mate::Handle<DownloadItem> DownloadItem::Create(
   return handle;
 }
 
-void ClearWrapDownloadItem() {
-  g_wrap_download_item.Reset();
-}
-
 void SetWrapDownloadItem(const WrapDownloadItemCallback& callback) {
   g_wrap_download_item = callback;
-
-  // Cleanup the wrapper on exit.
-  atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(
-      base::Bind(ClearWrapDownloadItem));
 }
 
 }  // namespace api

+ 1 - 2
atom/browser/api/atom_api_download_item.h

@@ -23,7 +23,6 @@ class DownloadItem : public mate::TrackableObject<DownloadItem>,
   static mate::Handle<DownloadItem> Create(v8::Isolate* isolate,
                                            content::DownloadItem* item);
 
-  // mate::TrackableObject:
   static void BuildPrototype(v8::Isolate* isolate,
                              v8::Local<v8::ObjectTemplate> prototype);
 
@@ -41,7 +40,7 @@ class DownloadItem : public mate::TrackableObject<DownloadItem>,
   base::FilePath GetSavePath() const;
 
  protected:
-  explicit DownloadItem(content::DownloadItem* download_item);
+  DownloadItem(v8::Isolate* isolate, content::DownloadItem* download_item);
   ~DownloadItem();
 
   // Override content::DownloadItem::Observer methods

+ 11 - 9
atom/browser/api/atom_api_global_shortcut.cc

@@ -19,7 +19,8 @@ namespace atom {
 
 namespace api {
 
-GlobalShortcut::GlobalShortcut() {
+GlobalShortcut::GlobalShortcut(v8::Isolate* isolate) {
+  Init(isolate);
 }
 
 GlobalShortcut::~GlobalShortcut() {
@@ -66,20 +67,21 @@ void GlobalShortcut::UnregisterAll() {
   GlobalShortcutListener::GetInstance()->UnregisterAccelerators(this);
 }
 
-mate::ObjectTemplateBuilder GlobalShortcut::GetObjectTemplateBuilder(
-    v8::Isolate* isolate) {
-  return mate::ObjectTemplateBuilder(isolate)
+// static
+mate::Handle<GlobalShortcut> GlobalShortcut::Create(v8::Isolate* isolate) {
+  return mate::CreateHandle(isolate, new GlobalShortcut(isolate));
+}
+
+// static
+void GlobalShortcut::BuildPrototype(
+    v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) {
+  mate::ObjectTemplateBuilder(isolate, prototype)
       .SetMethod("register", &GlobalShortcut::Register)
       .SetMethod("isRegistered", &GlobalShortcut::IsRegistered)
       .SetMethod("unregister", &GlobalShortcut::Unregister)
       .SetMethod("unregisterAll", &GlobalShortcut::UnregisterAll);
 }
 
-// static
-mate::Handle<GlobalShortcut> GlobalShortcut::Create(v8::Isolate* isolate) {
-  return CreateHandle(isolate, new GlobalShortcut);
-}
-
 }  // namespace api
 
 }  // namespace atom

+ 4 - 5
atom/browser/api/atom_api_global_shortcut.h

@@ -23,14 +23,13 @@ class GlobalShortcut : public extensions::GlobalShortcutListener::Observer,
  public:
   static mate::Handle<GlobalShortcut> Create(v8::Isolate* isolate);
 
+  static void BuildPrototype(v8::Isolate* isolate,
+                             v8::Local<v8::ObjectTemplate> prototype);
+
  protected:
-  GlobalShortcut();
+  explicit GlobalShortcut(v8::Isolate* isolate);
   ~GlobalShortcut() override;
 
-  // mate::Wrappable implementations:
-  mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
-      v8::Isolate* isolate) override;
-
  private:
   typedef std::map<ui::Accelerator, base::Closure> AcceleratorCallbackMap;
 

+ 2 - 2
atom/browser/api/atom_api_menu.cc

@@ -19,7 +19,7 @@ namespace atom {
 
 namespace api {
 
-Menu::Menu()
+Menu::Menu(v8::Isolate* isolate)
     : model_(new AtomMenuModel(this)),
       parent_(NULL) {
 }
@@ -28,7 +28,7 @@ Menu::~Menu() {
 }
 
 void Menu::AfterInit(v8::Isolate* isolate) {
-  mate::Dictionary wrappable(isolate, GetWrapper(isolate));
+  mate::Dictionary wrappable(isolate, GetWrapper());
   mate::Dictionary delegate;
   if (!wrappable.Get("delegate", &delegate))
     return;

+ 2 - 2
atom/browser/api/atom_api_menu.h

@@ -20,7 +20,7 @@ namespace api {
 class Menu : public mate::TrackableObject<Menu>,
              public AtomMenuModel::Delegate {
  public:
-  static mate::Wrappable* Create();
+  static mate::WrappableBase* Create(v8::Isolate* isolate);
 
   static void BuildPrototype(v8::Isolate* isolate,
                              v8::Local<v8::ObjectTemplate> prototype);
@@ -36,7 +36,7 @@ class Menu : public mate::TrackableObject<Menu>,
   AtomMenuModel* model() const { return model_.get(); }
 
  protected:
-  Menu();
+  explicit Menu(v8::Isolate* isolate);
   ~Menu() override;
 
   // mate::Wrappable:

+ 1 - 1
atom/browser/api/atom_api_menu_mac.h

@@ -17,7 +17,7 @@ namespace api {
 
 class MenuMac : public Menu {
  protected:
-  MenuMac();
+  explicit MenuMac(v8::Isolate* isolate);
 
   void PopupAt(Window* window, int x, int y, int positioning_item = 0) override;
 

+ 3 - 3
atom/browser/api/atom_api_menu_mac.mm

@@ -15,7 +15,7 @@ namespace atom {
 
 namespace api {
 
-MenuMac::MenuMac() {
+MenuMac::MenuMac(v8::Isolate* isolate) : Menu(isolate) {
 }
 
 void MenuMac::PopupAt(Window* window, int x, int y, int positioning_item) {
@@ -68,8 +68,8 @@ void Menu::SendActionToFirstResponder(const std::string& action) {
 }
 
 // static
-mate::Wrappable* Menu::Create() {
-  return new MenuMac();
+mate::WrappableBase* Menu::Create(v8::Isolate* isolate) {
+  return new MenuMac(isolate);
 }
 
 }  // namespace api

+ 3 - 3
atom/browser/api/atom_api_menu_views.cc

@@ -13,7 +13,7 @@ namespace atom {
 
 namespace api {
 
-MenuViews::MenuViews() {
+MenuViews::MenuViews(v8::Isolate* isolate) : Menu(isolate) {
 }
 
 void MenuViews::PopupAt(Window* window, int x, int y, int positioning_item) {
@@ -49,8 +49,8 @@ void MenuViews::PopupAt(Window* window, int x, int y, int positioning_item) {
 }
 
 // static
-mate::Wrappable* Menu::Create() {
-  return new MenuViews();
+mate::WrappableBase* Menu::Create(v8::Isolate* isolate) {
+  return new MenuViews(isolate);
 }
 
 }  // namespace api

+ 1 - 1
atom/browser/api/atom_api_menu_views.h

@@ -14,7 +14,7 @@ namespace api {
 
 class MenuViews : public Menu {
  public:
-  MenuViews();
+  explicit MenuViews(v8::Isolate* isolate);
 
  protected:
   void PopupAt(Window* window, int x, int y, int positioning_item = 0) override;

+ 8 - 2
atom/browser/api/atom_api_power_monitor.cc

@@ -14,8 +14,9 @@ namespace atom {
 
 namespace api {
 
-PowerMonitor::PowerMonitor() {
+PowerMonitor::PowerMonitor(v8::Isolate* isolate) {
   base::PowerMonitor::Get()->AddObserver(this);
+  Init(isolate);
 }
 
 PowerMonitor::~PowerMonitor() {
@@ -46,7 +47,12 @@ v8::Local<v8::Value> PowerMonitor::Create(v8::Isolate* isolate) {
     return v8::Null(isolate);
   }
 
-  return CreateHandle(isolate, new PowerMonitor).ToV8();
+  return mate::CreateHandle(isolate, new PowerMonitor(isolate)).ToV8();
+}
+
+// static
+void PowerMonitor::BuildPrototype(
+    v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) {
 }
 
 }  // namespace api

+ 4 - 1
atom/browser/api/atom_api_power_monitor.h

@@ -19,8 +19,11 @@ class PowerMonitor : public mate::TrackableObject<PowerMonitor>,
  public:
   static v8::Local<v8::Value> Create(v8::Isolate* isolate);
 
+  static void BuildPrototype(v8::Isolate* isolate,
+                             v8::Local<v8::ObjectTemplate> prototype);
+
  protected:
-  PowerMonitor();
+  explicit PowerMonitor(v8::Isolate* isolate);
   ~PowerMonitor() override;
 
   // base::PowerObserver implementations:

+ 12 - 10
atom/browser/api/atom_api_power_save_blocker.cc

@@ -37,9 +37,10 @@ namespace atom {
 
 namespace api {
 
-PowerSaveBlocker::PowerSaveBlocker()
+PowerSaveBlocker::PowerSaveBlocker(v8::Isolate* isolate)
     : current_blocker_type_(
-        content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension) {
+          content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension) {
+  Init(isolate);
 }
 
 PowerSaveBlocker::~PowerSaveBlocker() {
@@ -97,17 +98,18 @@ bool PowerSaveBlocker::IsStarted(int id) {
   return power_save_blocker_types_.find(id) != power_save_blocker_types_.end();
 }
 
-mate::ObjectTemplateBuilder PowerSaveBlocker::GetObjectTemplateBuilder(
-    v8::Isolate* isolate) {
-  return mate::ObjectTemplateBuilder(isolate)
-      .SetMethod("start", &PowerSaveBlocker::Start)
-      .SetMethod("stop", &PowerSaveBlocker::Stop)
-      .SetMethod("isStarted", &PowerSaveBlocker::IsStarted);
+// static
+mate::Handle<PowerSaveBlocker> PowerSaveBlocker::Create(v8::Isolate* isolate) {
+  return mate::CreateHandle(isolate, new PowerSaveBlocker(isolate));
 }
 
 // static
-mate::Handle<PowerSaveBlocker> PowerSaveBlocker::Create(v8::Isolate* isolate) {
-  return CreateHandle(isolate, new PowerSaveBlocker);
+void PowerSaveBlocker::BuildPrototype(
+    v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) {
+  mate::ObjectTemplateBuilder(isolate, prototype)
+      .SetMethod("start", &PowerSaveBlocker::Start)
+      .SetMethod("stop", &PowerSaveBlocker::Stop)
+      .SetMethod("isStarted", &PowerSaveBlocker::IsStarted);
 }
 
 }  // namespace api

+ 4 - 5
atom/browser/api/atom_api_power_save_blocker.h

@@ -24,14 +24,13 @@ class PowerSaveBlocker : public mate::TrackableObject<PowerSaveBlocker> {
  public:
   static mate::Handle<PowerSaveBlocker> Create(v8::Isolate* isolate);
 
+  static void BuildPrototype(v8::Isolate* isolate,
+                             v8::Local<v8::ObjectTemplate> prototype);
+
  protected:
-  PowerSaveBlocker();
+  explicit PowerSaveBlocker(v8::Isolate* isolate);
   ~PowerSaveBlocker() override;
 
-  // mate::Wrappable implementations:
-  mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
-      v8::Isolate* isolate) override;
-
  private:
   void UpdatePowerSaveBlocker();
   int Start(content::PowerSaveBlocker::PowerSaveBlockerType type);

+ 31 - 29
atom/browser/api/atom_api_protocol.cc

@@ -22,37 +22,11 @@ namespace atom {
 
 namespace api {
 
-Protocol::Protocol(AtomBrowserContext* browser_context)
+Protocol::Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context)
     : request_context_getter_(browser_context->GetRequestContext()),
       job_factory_(browser_context->job_factory()) {
   CHECK(job_factory_);
-}
-
-mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder(
-    v8::Isolate* isolate) {
-  return mate::ObjectTemplateBuilder(isolate)
-      .SetMethod("registerStandardSchemes", &Protocol::RegisterStandardSchemes)
-      .SetMethod("registerServiceWorkerSchemes",
-                 &Protocol::RegisterServiceWorkerSchemes)
-      .SetMethod("registerStringProtocol",
-                 &Protocol::RegisterProtocol<URLRequestStringJob>)
-      .SetMethod("registerBufferProtocol",
-                 &Protocol::RegisterProtocol<URLRequestBufferJob>)
-      .SetMethod("registerFileProtocol",
-                 &Protocol::RegisterProtocol<URLRequestAsyncAsarJob>)
-      .SetMethod("registerHttpProtocol",
-                 &Protocol::RegisterProtocol<URLRequestFetchJob>)
-      .SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol)
-      .SetMethod("isProtocolHandled", &Protocol::IsProtocolHandled)
-      .SetMethod("interceptStringProtocol",
-                 &Protocol::InterceptProtocol<URLRequestStringJob>)
-      .SetMethod("interceptBufferProtocol",
-                 &Protocol::InterceptProtocol<URLRequestBufferJob>)
-      .SetMethod("interceptFileProtocol",
-                 &Protocol::InterceptProtocol<URLRequestAsyncAsarJob>)
-      .SetMethod("interceptHttpProtocol",
-                 &Protocol::InterceptProtocol<URLRequestFetchJob>)
-      .SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol);
+  Init(isolate);
 }
 
 void Protocol::RegisterStandardSchemes(
@@ -150,7 +124,35 @@ std::string Protocol::ErrorCodeToString(ProtocolError error) {
 // static
 mate::Handle<Protocol> Protocol::Create(
     v8::Isolate* isolate, AtomBrowserContext* browser_context) {
-  return mate::CreateHandle(isolate, new Protocol(browser_context));
+  return mate::CreateHandle(isolate, new Protocol(isolate, browser_context));
+}
+
+// static
+void Protocol::BuildPrototype(
+    v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) {
+  mate::ObjectTemplateBuilder(isolate, prototype)
+      .SetMethod("registerStandardSchemes", &Protocol::RegisterStandardSchemes)
+      .SetMethod("registerServiceWorkerSchemes",
+                 &Protocol::RegisterServiceWorkerSchemes)
+      .SetMethod("registerStringProtocol",
+                 &Protocol::RegisterProtocol<URLRequestStringJob>)
+      .SetMethod("registerBufferProtocol",
+                 &Protocol::RegisterProtocol<URLRequestBufferJob>)
+      .SetMethod("registerFileProtocol",
+                 &Protocol::RegisterProtocol<URLRequestAsyncAsarJob>)
+      .SetMethod("registerHttpProtocol",
+                 &Protocol::RegisterProtocol<URLRequestFetchJob>)
+      .SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol)
+      .SetMethod("isProtocolHandled", &Protocol::IsProtocolHandled)
+      .SetMethod("interceptStringProtocol",
+                 &Protocol::InterceptProtocol<URLRequestStringJob>)
+      .SetMethod("interceptBufferProtocol",
+                 &Protocol::InterceptProtocol<URLRequestBufferJob>)
+      .SetMethod("interceptFileProtocol",
+                 &Protocol::InterceptProtocol<URLRequestAsyncAsarJob>)
+      .SetMethod("interceptHttpProtocol",
+                 &Protocol::InterceptProtocol<URLRequestFetchJob>)
+      .SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol);
 }
 
 }  // namespace api

+ 5 - 6
atom/browser/api/atom_api_protocol.h

@@ -30,7 +30,7 @@ class AtomURLRequestJobFactory;
 
 namespace api {
 
-class Protocol : public mate::Wrappable {
+class Protocol : public mate::Wrappable<Protocol> {
  public:
   using Handler =
       base::Callback<void(const net::URLRequest*, v8::Local<v8::Value>)>;
@@ -40,12 +40,11 @@ class Protocol : public mate::Wrappable {
   static mate::Handle<Protocol> Create(
       v8::Isolate* isolate, AtomBrowserContext* browser_context);
 
- protected:
-  explicit Protocol(AtomBrowserContext* browser_context);
+  static void BuildPrototype(v8::Isolate* isolate,
+                             v8::Local<v8::ObjectTemplate> prototype);
 
-  // mate::Wrappable implementations:
-  virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
-      v8::Isolate* isolate);
+ protected:
+  Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context);
 
  private:
   // Possible errors.

+ 15 - 12
atom/browser/api/atom_api_screen.cc

@@ -47,9 +47,11 @@ std::vector<std::string> MetricsToArray(uint32_t metrics) {
 
 }  // namespace
 
-Screen::Screen(gfx::Screen* screen) : screen_(screen) {
+Screen::Screen(v8::Isolate* isolate, gfx::Screen* screen)
+    : screen_(screen) {
   displays_ = screen_->GetAllDisplays();
   screen_->AddObserver(this);
+  Init(isolate);
 }
 
 Screen::~Screen() {
@@ -100,16 +102,6 @@ void Screen::OnDisplayMetricsChanged(const gfx::Display& display,
   Emit("display-metrics-changed", display, MetricsToArray(changed_metrics));
 }
 
-mate::ObjectTemplateBuilder Screen::GetObjectTemplateBuilder(
-    v8::Isolate* isolate) {
-  return mate::ObjectTemplateBuilder(isolate)
-      .SetMethod("getCursorScreenPoint", &Screen::GetCursorScreenPoint)
-      .SetMethod("getPrimaryDisplay", &Screen::GetPrimaryDisplay)
-      .SetMethod("getAllDisplays", &Screen::GetAllDisplays)
-      .SetMethod("getDisplayNearestPoint", &Screen::GetDisplayNearestPoint)
-      .SetMethod("getDisplayMatching", &Screen::GetDisplayMatching);
-}
-
 // static
 v8::Local<v8::Value> Screen::Create(v8::Isolate* isolate) {
   if (!Browser::Get()->is_ready()) {
@@ -126,7 +118,18 @@ v8::Local<v8::Value> Screen::Create(v8::Isolate* isolate) {
     return v8::Null(isolate);
   }
 
-  return mate::CreateHandle(isolate, new Screen(screen)).ToV8();
+  return mate::CreateHandle(isolate, new Screen(isolate, screen)).ToV8();
+}
+
+// static
+void Screen::BuildPrototype(
+    v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) {
+  mate::ObjectTemplateBuilder(isolate, prototype)
+      .SetMethod("getCursorScreenPoint", &Screen::GetCursorScreenPoint)
+      .SetMethod("getPrimaryDisplay", &Screen::GetPrimaryDisplay)
+      .SetMethod("getAllDisplays", &Screen::GetAllDisplays)
+      .SetMethod("getDisplayNearestPoint", &Screen::GetDisplayNearestPoint)
+      .SetMethod("getDisplayMatching", &Screen::GetDisplayMatching);
 }
 
 }  // namespace api

+ 6 - 7
atom/browser/api/atom_api_screen.h

@@ -21,14 +21,17 @@ namespace atom {
 
 namespace api {
 
-class Screen : public mate::EventEmitter,
+class Screen : public mate::EventEmitter<Screen>,
                public gfx::DisplayObserver {
  public:
   static v8::Local<v8::Value> Create(v8::Isolate* isolate);
 
+  static void BuildPrototype(v8::Isolate* isolate,
+                             v8::Local<v8::ObjectTemplate> prototype);
+
  protected:
-  explicit Screen(gfx::Screen* screen);
-  virtual ~Screen();
+  Screen(v8::Isolate* isolate, gfx::Screen* screen);
+  ~Screen() override;
 
   gfx::Point GetCursorScreenPoint();
   gfx::Display GetPrimaryDisplay();
@@ -42,10 +45,6 @@ class Screen : public mate::EventEmitter,
   void OnDisplayMetricsChanged(const gfx::Display& display,
                                uint32_t changed_metrics) override;
 
-  // mate::Wrappable:
-  mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
-      v8::Isolate* isolate) override;
-
  private:
   gfx::Screen* screen_;
   std::vector<gfx::Display> displays_;

+ 9 - 12
atom/browser/api/atom_api_session.cc

@@ -288,14 +288,15 @@ void ClearHostResolverCacheInIO(
 
 }  // namespace
 
-Session::Session(AtomBrowserContext* browser_context)
+Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context)
     : devtools_network_emulation_client_id_(base::GenerateGUID()),
       browser_context_(browser_context) {
-  AttachAsUserData(browser_context);
-
   // Observe DownloadManger to get download notifications.
   content::BrowserContext::GetDownloadManager(browser_context)->
       AddObserver(this);
+
+  Init(isolate);
+  AttachAsUserData(browser_context);
 }
 
 Session::~Session() {
@@ -308,6 +309,9 @@ void Session::OnDownloadCreated(content::DownloadManager* manager,
   auto web_contents = item->GetWebContents();
   if (SavePageHandler::IsSavePageTypes(item->GetMimeType()))
     return;
+
+  v8::Locker locker(isolate());
+  v8::HandleScope handle_scope(isolate());
   bool prevent_default = Emit(
       "will-download",
       DownloadItem::Create(isolate(), item),
@@ -454,7 +458,8 @@ mate::Handle<Session> Session::CreateFrom(
   if (existing)
     return mate::CreateHandle(isolate, static_cast<Session*>(existing));
 
-  auto handle = mate::CreateHandle(isolate, new Session(browser_context));
+  auto handle = mate::CreateHandle(
+      isolate, new Session(isolate, browser_context));
   g_wrap_session.Run(handle.ToV8());
   return handle;
 }
@@ -489,16 +494,8 @@ void Session::BuildPrototype(v8::Isolate* isolate,
       .SetProperty("webRequest", &Session::WebRequest);
 }
 
-void ClearWrapSession() {
-  g_wrap_session.Reset();
-}
-
 void SetWrapSession(const WrapSessionCallback& callback) {
   g_wrap_session = callback;
-
-  // Cleanup the wrapper on exit.
-  atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(
-      base::Bind(ClearWrapSession));
 }
 
 }  // namespace api

+ 1 - 1
atom/browser/api/atom_api_session.h

@@ -58,7 +58,7 @@ class Session: public mate::TrackableObject<Session>,
                              v8::Local<v8::ObjectTemplate> prototype);
 
  protected:
-  explicit Session(AtomBrowserContext* browser_context);
+  Session(v8::Isolate* isolate, AtomBrowserContext* browser_context);
   ~Session();
 
   // content::DownloadManager::Observer:

+ 3 - 3
atom/browser/api/atom_api_tray.cc

@@ -22,7 +22,7 @@ namespace atom {
 
 namespace api {
 
-Tray::Tray(const gfx::Image& image)
+Tray::Tray(v8::Isolate* isolate, const gfx::Image& image)
     : tray_icon_(TrayIcon::Create()) {
   tray_icon_->SetImage(image);
   tray_icon_->AddObserver(this);
@@ -32,13 +32,13 @@ Tray::~Tray() {
 }
 
 // static
-mate::Wrappable* Tray::New(v8::Isolate* isolate, const gfx::Image& image) {
+mate::WrappableBase* Tray::New(v8::Isolate* isolate, const gfx::Image& image) {
   if (!Browser::Get()->is_ready()) {
     isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
         isolate, "Cannot create Tray before app is ready")));
     return nullptr;
   }
-  return new Tray(image);
+  return new Tray(isolate, image);
 }
 
 void Tray::OnClicked(const gfx::Rect& bounds, int modifiers) {

+ 3 - 2
atom/browser/api/atom_api_tray.h

@@ -32,13 +32,14 @@ class Menu;
 class Tray : public mate::TrackableObject<Tray>,
              public TrayIconObserver {
  public:
-  static mate::Wrappable* New(v8::Isolate* isolate, const gfx::Image& image);
+  static mate::WrappableBase* New(
+      v8::Isolate* isolate, const gfx::Image& image);
 
   static void BuildPrototype(v8::Isolate* isolate,
                              v8::Local<v8::ObjectTemplate> prototype);
 
  protected:
-  explicit Tray(const gfx::Image& image);
+  Tray(v8::Isolate* isolate, const gfx::Image& image);
   ~Tray() override;
 
   // TrayIconObserver:

+ 10 - 12
atom/browser/api/atom_api_web_contents.cc

@@ -215,14 +215,17 @@ content::ServiceWorkerContext* GetServiceWorkerContext(
 
 }  // namespace
 
-WebContents::WebContents(content::WebContents* web_contents)
+WebContents::WebContents(v8::Isolate* isolate,
+                         content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents),
       embedder_(nullptr),
       type_(REMOTE),
       request_id_(0),
       background_throttling_(true) {
-  AttachAsUserData(web_contents);
   web_contents->SetUserAgentOverride(GetBrowserContext()->GetUserAgent());
+
+  Init(isolate);
+  AttachAsUserData(web_contents);
 }
 
 WebContents::WebContents(v8::Isolate* isolate,
@@ -270,7 +273,6 @@ WebContents::WebContents(v8::Isolate* isolate,
   }
 
   Observe(web_contents);
-  AttachAsUserData(web_contents);
   InitWithWebContents(web_contents);
 
   managed_web_contents()->GetView()->SetDelegate(this);
@@ -299,6 +301,9 @@ WebContents::WebContents(v8::Isolate* isolate,
     if (owner_window)
       SetOwnerWindow(owner_window);
   }
+
+  Init(isolate);
+  AttachAsUserData(web_contents);
 }
 
 WebContents::~WebContents() {
@@ -1290,7 +1295,8 @@ mate::Handle<WebContents> WebContents::CreateFrom(
     return mate::CreateHandle(isolate, static_cast<WebContents*>(existing));
 
   // Otherwise create a new WebContents wrapper object.
-  auto handle = mate::CreateHandle(isolate, new WebContents(web_contents));
+  auto handle = mate::CreateHandle(
+      isolate, new WebContents(isolate, web_contents));
   g_wrap_web_contents.Run(handle.ToV8());
   return handle;
 }
@@ -1303,16 +1309,8 @@ mate::Handle<WebContents> WebContents::Create(
   return handle;
 }
 
-void ClearWrapWebContents() {
-  g_wrap_web_contents.Reset();
-}
-
 void SetWrapWebContents(const WrapWebContentsCallback& callback) {
   g_wrap_web_contents = callback;
-
-  // Cleanup the wrapper on exit.
-  atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(
-      base::Bind(ClearWrapWebContents));
 }
 
 }  // namespace api

+ 4 - 5
atom/browser/api/atom_api_web_contents.h

@@ -55,6 +55,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
   static mate::Handle<WebContents> Create(
       v8::Isolate* isolate, const mate::Dictionary& options);
 
+  static void BuildPrototype(v8::Isolate* isolate,
+                             v8::Local<v8::ObjectTemplate> prototype);
+
   int GetID() const;
   bool Equal(const WebContents* web_contents) const;
   void LoadURL(const GURL& url, const mate::Dictionary& options);
@@ -156,12 +159,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
   v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
   v8::Local<v8::Value> Debugger(v8::Isolate* isolate);
 
-  // mate::TrackableObject:
-  static void BuildPrototype(v8::Isolate* isolate,
-                             v8::Local<v8::ObjectTemplate> prototype);
-
  protected:
-  explicit WebContents(content::WebContents* web_contents);
+  WebContents(v8::Isolate* isolate, content::WebContents* web_contents);
   WebContents(v8::Isolate* isolate, const mate::Dictionary& options);
   ~WebContents();
 

+ 4 - 2
atom/browser/api/atom_api_web_request.cc

@@ -36,8 +36,10 @@ namespace atom {
 
 namespace api {
 
-WebRequest::WebRequest(AtomBrowserContext* browser_context)
+WebRequest::WebRequest(v8::Isolate* isolate,
+                       AtomBrowserContext* browser_context)
     : browser_context_(browser_context) {
+  Init(isolate);
 }
 
 WebRequest::~WebRequest() {
@@ -81,7 +83,7 @@ void WebRequest::SetListener(Method method, Event type, mate::Arguments* args) {
 mate::Handle<WebRequest> WebRequest::Create(
     v8::Isolate* isolate,
     AtomBrowserContext* browser_context) {
-  return mate::CreateHandle(isolate, new WebRequest(browser_context));
+  return mate::CreateHandle(isolate, new WebRequest(isolate, browser_context));
 }
 
 // static

+ 2 - 3
atom/browser/api/atom_api_web_request.h

@@ -21,13 +21,12 @@ class WebRequest : public mate::TrackableObject<WebRequest> {
   static mate::Handle<WebRequest> Create(v8::Isolate* isolate,
                                          AtomBrowserContext* browser_context);
 
-  // mate::TrackableObject:
   static void BuildPrototype(v8::Isolate* isolate,
                              v8::Local<v8::ObjectTemplate> prototype);
 
  protected:
-  explicit WebRequest(AtomBrowserContext* browser_context);
-  ~WebRequest();
+  WebRequest(v8::Isolate* isolate, AtomBrowserContext* browser_context);
+  ~WebRequest() override;
 
   // C++ can not distinguish overloaded member function.
   template<AtomNetworkDelegate::SimpleEvent type>

+ 3 - 3
atom/browser/api/atom_api_window.cc

@@ -151,7 +151,7 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) {
   api_web_contents_ = web_contents.get();
 
   // Keep a copy of the options for later use.
-  mate::Dictionary(isolate, web_contents->GetWrapper(isolate)).Set(
+  mate::Dictionary(isolate, web_contents->GetWrapper()).Set(
       "browserWindowOptions", options);
 
   // Creates BrowserWindow.
@@ -287,7 +287,7 @@ void Window::OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) {
 #endif
 
 // static
-mate::Wrappable* Window::New(v8::Isolate* isolate, mate::Arguments* args) {
+mate::WrappableBase* Window::New(v8::Isolate* isolate, mate::Arguments* args) {
   if (!Browser::Get()->is_ready()) {
     isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
         isolate, "Cannot create BrowserWindow before app is ready")));
@@ -817,7 +817,7 @@ v8::Local<v8::Value> Window::From(v8::Isolate* isolate,
                                   NativeWindow* native_window) {
   auto existing = TrackableObject::FromWrappedClass(isolate, native_window);
   if (existing)
-    return existing->GetWrapper(isolate);
+    return existing->GetWrapper();
   else
     return v8::Null(isolate);
 }

+ 2 - 2
atom/browser/api/atom_api_window.h

@@ -38,7 +38,7 @@ class WebContents;
 class Window : public mate::TrackableObject<Window>,
                public NativeWindowObserver {
  public:
-  static mate::Wrappable* New(v8::Isolate* isolate, mate::Arguments* args);
+  static mate::WrappableBase* New(v8::Isolate* isolate, mate::Arguments* args);
 
   static void BuildPrototype(v8::Isolate* isolate,
                              v8::Local<v8::ObjectTemplate> prototype);
@@ -51,7 +51,7 @@ class Window : public mate::TrackableObject<Window>,
 
  protected:
   Window(v8::Isolate* isolate, const mate::Dictionary& options);
-  virtual ~Window();
+  ~Window() override;
 
   // NativeWindowObserver:
   void WillCloseWindow(bool* prevent_default) override;

+ 12 - 20
atom/browser/api/event.cc

@@ -11,31 +11,15 @@
 
 namespace mate {
 
-namespace {
-
-v8::Persistent<v8::ObjectTemplate> template_;
-
-}  // namespace
-
-Event::Event()
+Event::Event(v8::Isolate* isolate)
     : sender_(NULL),
       message_(NULL) {
+  Init(isolate);
 }
 
 Event::~Event() {
 }
 
-ObjectTemplateBuilder Event::GetObjectTemplateBuilder(v8::Isolate* isolate) {
-  if (template_.IsEmpty())
-    template_.Reset(isolate, ObjectTemplateBuilder(isolate)
-        .SetMethod("preventDefault", &Event::PreventDefault)
-        .SetMethod("sendReply", &Event::SendReply)
-        .Build());
-
-  return ObjectTemplateBuilder(
-      isolate, v8::Local<v8::ObjectTemplate>::New(isolate, template_));
-}
-
 void Event::SetSenderAndMessage(content::WebContents* sender,
                                 IPC::Message* message) {
   DCHECK(!sender_);
@@ -52,7 +36,7 @@ void Event::WebContentsDestroyed() {
 }
 
 void Event::PreventDefault(v8::Isolate* isolate) {
-  GetWrapper(isolate)->Set(StringToV8(isolate, "defaultPrevented"),
+  GetWrapper()->Set(StringToV8(isolate, "defaultPrevented"),
                            v8::True(isolate));
 }
 
@@ -66,7 +50,15 @@ bool Event::SendReply(const base::string16& json) {
 
 // static
 Handle<Event> Event::Create(v8::Isolate* isolate) {
-  return CreateHandle(isolate, new Event);
+  return mate::CreateHandle(isolate, new Event(isolate));
+}
+
+// static
+void Event::BuildPrototype(
+    v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) {
+  mate::ObjectTemplateBuilder(isolate, prototype)
+      .SetMethod("preventDefault", &Event::PreventDefault)
+      .SetMethod("sendReply", &Event::SendReply);
 }
 
 }  // namespace mate

+ 6 - 6
atom/browser/api/event.h

@@ -15,11 +15,14 @@ class Message;
 
 namespace mate {
 
-class Event : public Wrappable,
+class Event : public Wrappable<Event>,
               public content::WebContentsObserver {
  public:
   static Handle<Event> Create(v8::Isolate* isolate);
 
+  static void BuildPrototype(v8::Isolate* isolate,
+                             v8::Local<v8::ObjectTemplate> prototype);
+
   // Pass the sender and message to be replied.
   void SetSenderAndMessage(content::WebContents* sender, IPC::Message* message);
 
@@ -30,11 +33,8 @@ class Event : public Wrappable,
   bool SendReply(const base::string16& json);
 
  protected:
-  Event();
-  virtual ~Event();
-
-  // Wrappable implementations:
-  ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate) override;
+  explicit Event(v8::Isolate* isolate);
+  ~Event() override;
 
   // content::WebContentsObserver implementations:
   void WebContentsDestroyed() override;

+ 14 - 8
atom/browser/api/event_emitter.cc

@@ -34,11 +34,13 @@ v8::Local<v8::Object> CreateEventObject(v8::Isolate* isolate) {
 
 }  // namespace
 
-EventEmitter::EventEmitter() {
-}
+namespace internal {
 
-v8::Local<v8::Object> EventEmitter::CreateJSEvent(
-    v8::Isolate* isolate, content::WebContents* sender, IPC::Message* message) {
+v8::Local<v8::Object> CreateJSEvent(
+    v8::Isolate* isolate,
+    v8::Local<v8::Object> object,
+    content::WebContents* sender,
+    IPC::Message* message) {
   v8::Local<v8::Object> event;
   bool use_native_event = sender && message;
 
@@ -49,16 +51,20 @@ v8::Local<v8::Object> EventEmitter::CreateJSEvent(
   } else {
     event = CreateEventObject(isolate);
   }
-  mate::Dictionary(isolate, event).Set("sender", GetWrapper(isolate));
+  mate::Dictionary(isolate, event).Set("sender", object);
   return event;
 }
 
-v8::Local<v8::Object> EventEmitter::CreateCustomEvent(
-    v8::Isolate* isolate, v8::Local<v8::Object> custom_event) {
+v8::Local<v8::Object> CreateCustomEvent(
+    v8::Isolate* isolate,
+    v8::Local<v8::Object> object,
+    v8::Local<v8::Object> custom_event) {
   v8::Local<v8::Object> event = CreateEventObject(isolate);
   (void)event->SetPrototype(custom_event->CreationContext(), custom_event);
-  mate::Dictionary(isolate, event).Set("sender", GetWrapper(isolate));
+  mate::Dictionary(isolate, event).Set("sender", object);
   return event;
 }
 
+}  // namespace internal
+
 }  // namespace mate

+ 27 - 11
atom/browser/api/event_emitter.h

@@ -20,17 +20,38 @@ class Message;
 
 namespace mate {
 
+namespace internal {
+
+v8::Local<v8::Object> CreateJSEvent(v8::Isolate* isolate,
+                                    v8::Local<v8::Object> object,
+                                    content::WebContents* sender,
+                                    IPC::Message* message);
+v8::Local<v8::Object> CreateCustomEvent(
+    v8::Isolate* isolate,
+    v8::Local<v8::Object> object,
+    v8::Local<v8::Object> event);
+
+}  // namespace internal
+
 // Provide helperers to emit event in JavaScript.
-class EventEmitter : public Wrappable {
+template<typename T>
+class EventEmitter : public Wrappable<T> {
  public:
   typedef std::vector<v8::Local<v8::Value>> ValueArray;
 
+  // Make the convinient methods visible:
+  // https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-members
+  v8::Local<v8::Object> GetWrapper() { return Wrappable<T>::GetWrapper(); }
+  v8::Isolate* isolate() const { return Wrappable<T>::isolate(); }
+
   // this.emit(name, event, args...);
   template<typename... Args>
   bool EmitCustomEvent(const base::StringPiece& name,
                        v8::Local<v8::Object> event,
                        const Args&... args) {
-    return EmitWithEvent(name, CreateCustomEvent(isolate(), event), args...);
+    return EmitWithEvent(
+        name,
+        internal::CreateCustomEvent(isolate(), GetWrapper(), event), args...);
   }
 
   // this.emit(name, new Event(), args...);
@@ -47,12 +68,13 @@ class EventEmitter : public Wrappable {
                       const Args&... args) {
     v8::Locker locker(isolate());
     v8::HandleScope handle_scope(isolate());
-    v8::Local<v8::Object> event = CreateJSEvent(isolate(), sender, message);
+    v8::Local<v8::Object> event = internal::CreateJSEvent(
+        isolate(), GetWrapper(), sender, message);
     return EmitWithEvent(name, event, args...);
   }
 
  protected:
-  EventEmitter();
+  EventEmitter() {}
 
  private:
   // this.emit(name, event, args...);
@@ -62,17 +84,11 @@ class EventEmitter : public Wrappable {
                      const Args&... args) {
     v8::Locker locker(isolate());
     v8::HandleScope handle_scope(isolate());
-    EmitEvent(isolate(), GetWrapper(isolate()), name, event, args...);
+    EmitEvent(isolate(), GetWrapper(), name, event, args...);
     return event->Get(
         StringToV8(isolate(), "defaultPrevented"))->BooleanValue();
   }
 
-  v8::Local<v8::Object> CreateJSEvent(v8::Isolate* isolate,
-                                      content::WebContents* sender,
-                                      IPC::Message* message);
-  v8::Local<v8::Object> CreateCustomEvent(
-      v8::Isolate* isolate, v8::Local<v8::Object> event);
-
   DISALLOW_COPY_AND_ASSIGN(EventEmitter);
 };
 

+ 0 - 9
atom/browser/api/trackable_object.cc

@@ -37,15 +37,6 @@ TrackableObjectBase::~TrackableObjectBase() {
   cleanup_.Run();
 }
 
-void TrackableObjectBase::AfterInit(v8::Isolate* isolate) {
-  if (wrapped_)
-    AttachAsUserData(wrapped_);
-}
-
-void TrackableObjectBase::MarkDestroyed() {
-  GetWrapper(isolate())->SetAlignedPointerInInternalField(0, nullptr);
-}
-
 base::Closure TrackableObjectBase::GetDestroyClosure() {
   return base::Bind(&TrackableObjectBase::Destroy, weak_factory_.GetWeakPtr());
 }

+ 13 - 35
atom/browser/api/trackable_object.h

@@ -21,7 +21,7 @@ class SupportsUserData;
 namespace mate {
 
 // Users should use TrackableObject instead.
-class TrackableObjectBase : public mate::EventEmitter {
+class TrackableObjectBase {
  public:
   TrackableObjectBase();
 
@@ -32,13 +32,7 @@ class TrackableObjectBase : public mate::EventEmitter {
   void AttachAsUserData(base::SupportsUserData* wrapped);
 
  protected:
-  ~TrackableObjectBase() override;
-
-  // mate::Wrappable:
-  void AfterInit(v8::Isolate* isolate) override;
-
-  // Mark the JS object as destroyed.
-  void MarkDestroyed();
+  virtual ~TrackableObjectBase();
 
   // Returns a closure that can destroy the native class.
   base::Closure GetDestroyClosure();
@@ -65,8 +59,14 @@ class TrackableObjectBase : public mate::EventEmitter {
 // All instances of TrackableObject will be kept in a weak map and can be got
 // from its ID.
 template<typename T>
-class TrackableObject : public TrackableObjectBase {
+class TrackableObject : public TrackableObjectBase,
+                        public mate::EventEmitter<T> {
  public:
+  // Mark the JS object as destroyed.
+  void MarkDestroyed() {
+    Wrappable<T>::GetWrapper()->SetAlignedPointerInInternalField(0, nullptr);
+  }
+
   // Finds out the TrackableObject from its ID in weak map.
   static T* FromWeakMapID(v8::Isolate* isolate, int32_t id) {
     if (!weak_map_)
@@ -106,6 +106,7 @@ class TrackableObject : public TrackableObjectBase {
 
  protected:
   TrackableObject() {}
+
   ~TrackableObject() override {
     RemoveFromWeakMap();
   }
@@ -113,41 +114,18 @@ class TrackableObject : public TrackableObjectBase {
   void AfterInit(v8::Isolate* isolate) override {
     if (!weak_map_) {
       weak_map_.reset(new atom::IDWeakMap);
-      RegisterDestructionCallback(
-          base::Bind(&TrackableObject<T>::ReleaseAllWeakReferences));
     }
-    weak_map_id_ = weak_map_->Add(isolate, GetWrapper(isolate));
-    TrackableObjectBase::AfterInit(isolate);
+    weak_map_id_ = weak_map_->Add(isolate, Wrappable<T>::GetWrapper());
+    if (wrapped_)
+      AttachAsUserData(wrapped_);
   }
 
  private:
-  // mate::Wrappable:
-  mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
-      v8::Isolate* isolate) override {
-    if (template_.IsEmpty()) {
-      auto templ = v8::ObjectTemplate::New(isolate);
-      T::BuildPrototype(isolate, templ);
-      template_.Reset(isolate, templ);
-    }
-
-    return ObjectTemplateBuilder(
-        isolate, v8::Local<v8::ObjectTemplate>::New(isolate, template_));
-  }
-
-  // Releases all weak references in weak map, called when app is terminating.
-  static void ReleaseAllWeakReferences() {
-    weak_map_.reset();
-  }
-
-  static v8::Persistent<v8::ObjectTemplate> template_;
   static scoped_ptr<atom::IDWeakMap> weak_map_;
 
   DISALLOW_COPY_AND_ASSIGN(TrackableObject);
 };
 
-template<typename T>
-v8::Persistent<v8::ObjectTemplate> TrackableObject<T>::template_;
-
 template<typename T>
 scoped_ptr<atom::IDWeakMap> TrackableObject<T>::weak_map_;
 

+ 24 - 24
atom/common/api/atom_api_asar.cc

@@ -18,21 +18,39 @@
 
 namespace {
 
-v8::Persistent<v8::ObjectTemplate> template_;
-
-class Archive : public mate::Wrappable {
+class Archive : public mate::Wrappable<Archive> {
  public:
   static v8::Local<v8::Value> Create(v8::Isolate* isolate,
                                       const base::FilePath& path) {
     scoped_ptr<asar::Archive> archive(new asar::Archive(path));
     if (!archive->Init())
       return v8::False(isolate);
-    return (new Archive(std::move(archive)))->GetWrapper(isolate);
+    return (new Archive(isolate, std::move(archive)))->GetWrapper();
+  }
+
+  static void BuildPrototype(
+      v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) {
+    mate::ObjectTemplateBuilder(isolate, prototype)
+        .SetProperty("path", &Archive::GetPath)
+        .SetMethod("getFileInfo", &Archive::GetFileInfo)
+        .SetMethod("stat", &Archive::Stat)
+        .SetMethod("readdir", &Archive::Readdir)
+        .SetMethod("realpath", &Archive::Realpath)
+        .SetMethod("copyFileOut", &Archive::CopyFileOut)
+        .SetMethod("getFd", &Archive::GetFD)
+        .SetMethod("destroy", &Archive::Destroy);
   }
 
  protected:
-  explicit Archive(scoped_ptr<asar::Archive> archive)
-      : archive_(std::move(archive)) {}
+  Archive(v8::Isolate* isolate, scoped_ptr<asar::Archive> archive)
+      : archive_(std::move(archive)) {
+    Init(isolate);
+  }
+
+  // Returns the path of the file.
+  base::FilePath GetPath() {
+    return archive_->path();
+  }
 
   // Reads the offset and size of file.
   v8::Local<v8::Value> GetFileInfo(v8::Isolate* isolate,
@@ -101,24 +119,6 @@ class Archive : public mate::Wrappable {
     archive_.reset();
   }
 
-  // mate::Wrappable:
-  mate::ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate) {
-    if (template_.IsEmpty())
-      template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate)
-          .SetValue("path", archive_->path())
-          .SetMethod("getFileInfo", &Archive::GetFileInfo)
-          .SetMethod("stat", &Archive::Stat)
-          .SetMethod("readdir", &Archive::Readdir)
-          .SetMethod("realpath", &Archive::Realpath)
-          .SetMethod("copyFileOut", &Archive::CopyFileOut)
-          .SetMethod("getFd", &Archive::GetFD)
-          .SetMethod("destroy", &Archive::Destroy)
-          .Build());
-
-    return mate::ObjectTemplateBuilder(
-        isolate, v8::Local<v8::ObjectTemplate>::New(isolate, template_));
-  }
-
  private:
   scoped_ptr<asar::Archive> archive_;
 

+ 3 - 3
atom/common/api/atom_api_id_weak_map.cc

@@ -12,7 +12,7 @@ namespace atom {
 
 namespace api {
 
-IDWeakMap::IDWeakMap() {
+IDWeakMap::IDWeakMap(v8::Isolate* isolate) {
 }
 
 IDWeakMap::~IDWeakMap() {
@@ -52,8 +52,8 @@ void IDWeakMap::BuildPrototype(v8::Isolate* isolate,
 }
 
 // static
-mate::Wrappable* IDWeakMap::Create(v8::Isolate* isolate) {
-  return new IDWeakMap;
+mate::WrappableBase* IDWeakMap::Create(v8::Isolate* isolate) {
+  return new IDWeakMap(isolate);
 }
 
 }  // namespace api

+ 3 - 3
atom/common/api/atom_api_id_weak_map.h

@@ -13,15 +13,15 @@ namespace atom {
 
 namespace api {
 
-class IDWeakMap : public mate::Wrappable {
+class IDWeakMap : public mate::Wrappable<IDWeakMap> {
  public:
-  static mate::Wrappable* Create(v8::Isolate* isolate);
+  static mate::WrappableBase* Create(v8::Isolate* isolate);
 
   static void BuildPrototype(v8::Isolate* isolate,
                              v8::Local<v8::ObjectTemplate> prototype);
 
  protected:
-  IDWeakMap();
+  explicit IDWeakMap(v8::Isolate* isolate);
   ~IDWeakMap();
 
  private:

+ 21 - 26
atom/common/api/atom_api_native_image.cc

@@ -168,35 +168,15 @@ bool ReadImageSkiaFromICO(gfx::ImageSkia* image, const base::FilePath& path) {
 }
 #endif
 
-v8::Persistent<v8::ObjectTemplate> template_;
-
 }  // namespace
 
-NativeImage::NativeImage() {}
-
-NativeImage::NativeImage(const gfx::Image& image) : image_(image) {}
+NativeImage::NativeImage(v8::Isolate* isolate, const gfx::Image& image)
+    : image_(image) {
+  Init(isolate);
+}
 
 NativeImage::~NativeImage() {}
 
-mate::ObjectTemplateBuilder NativeImage::GetObjectTemplateBuilder(
-    v8::Isolate* isolate) {
-  if (template_.IsEmpty())
-    template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate)
-        .SetMethod("toPng", &NativeImage::ToPNG)
-        .SetMethod("toJpeg", &NativeImage::ToJPEG)
-        .SetMethod("getNativeHandle", &NativeImage::GetNativeHandle)
-        .SetMethod("toDataURL", &NativeImage::ToDataURL)
-        .SetMethod("toDataUrl", &NativeImage::ToDataURL)  // deprecated.
-        .SetMethod("isEmpty", &NativeImage::IsEmpty)
-        .SetMethod("getSize", &NativeImage::GetSize)
-        .SetMethod("setTemplateImage", &NativeImage::SetTemplateImage)
-        .SetMethod("isTemplateImage", &NativeImage::IsTemplateImage)
-        .Build());
-
-  return mate::ObjectTemplateBuilder(
-      isolate, v8::Local<v8::ObjectTemplate>::New(isolate, template_));
-}
-
 v8::Local<v8::Value> NativeImage::ToPNG(v8::Isolate* isolate) {
   scoped_refptr<base::RefCountedMemory> png = image_.As1xPNGBytes();
   return node::Buffer::Copy(isolate,
@@ -255,13 +235,13 @@ bool NativeImage::IsTemplateImage() {
 
 // static
 mate::Handle<NativeImage> NativeImage::CreateEmpty(v8::Isolate* isolate) {
-  return mate::CreateHandle(isolate, new NativeImage);
+  return mate::CreateHandle(isolate, new NativeImage(isolate, gfx::Image()));
 }
 
 // static
 mate::Handle<NativeImage> NativeImage::Create(
     v8::Isolate* isolate, const gfx::Image& image) {
-  return mate::CreateHandle(isolate, new NativeImage(image));
+  return mate::CreateHandle(isolate, new NativeImage(isolate, image));
 }
 
 // static
@@ -330,6 +310,21 @@ mate::Handle<NativeImage> NativeImage::CreateFromDataURL(
   return CreateEmpty(isolate);
 }
 
+// static
+void NativeImage::BuildPrototype(
+    v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) {
+  mate::ObjectTemplateBuilder(isolate, prototype)
+      .SetMethod("toPng", &NativeImage::ToPNG)
+      .SetMethod("toJpeg", &NativeImage::ToJPEG)
+      .SetMethod("getNativeHandle", &NativeImage::GetNativeHandle)
+      .SetMethod("toDataURL", &NativeImage::ToDataURL)
+      .SetMethod("toDataUrl", &NativeImage::ToDataURL)  // deprecated.
+      .SetMethod("isEmpty", &NativeImage::IsEmpty)
+      .SetMethod("getSize", &NativeImage::GetSize)
+      .SetMethod("setTemplateImage", &NativeImage::SetTemplateImage)
+      .SetMethod("isTemplateImage", &NativeImage::IsTemplateImage);
+}
+
 }  // namespace api
 
 }  // namespace atom

+ 5 - 9
atom/common/api/atom_api_native_image.h

@@ -29,7 +29,7 @@ namespace atom {
 
 namespace api {
 
-class NativeImage : public mate::Wrappable {
+class NativeImage : public mate::Wrappable<NativeImage> {
  public:
   static mate::Handle<NativeImage> CreateEmpty(v8::Isolate* isolate);
   static mate::Handle<NativeImage> Create(
@@ -45,18 +45,14 @@ class NativeImage : public mate::Wrappable {
   static mate::Handle<NativeImage> CreateFromDataURL(
       v8::Isolate* isolate, const GURL& url);
 
-  // The default constructor should only be used by image_converter.cc.
-  NativeImage();
+  static void BuildPrototype(v8::Isolate* isolate,
+                             v8::Local<v8::ObjectTemplate> prototype);
 
   const gfx::Image& image() const { return image_; }
 
  protected:
-  explicit NativeImage(const gfx::Image& image);
-  virtual ~NativeImage();
-
-  // mate::Wrappable:
-  mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
-      v8::Isolate* isolate) override;
+  NativeImage(v8::Isolate* isolate, const gfx::Image& image);
+  ~NativeImage() override;
 
  private:
   v8::Local<v8::Value> ToPNG(v8::Isolate* isolate);

+ 12 - 10
atom/renderer/api/atom_api_web_frame.cc

@@ -54,8 +54,9 @@ class ScriptExecutionCallback : public blink::WebScriptExecutionCallback {
 
 }  // namespace
 
-WebFrame::WebFrame()
+WebFrame::WebFrame(v8::Isolate* isolate)
     : web_frame_(blink::WebLocalFrame::frameForCurrentContext()) {
+  Init(isolate);
 }
 
 WebFrame::~WebFrame() {
@@ -67,7 +68,7 @@ void WebFrame::SetName(const std::string& name) {
 
 double WebFrame::SetZoomLevel(double level) {
   double ret = web_frame_->view()->setZoomLevel(level);
-  mate::EmitEvent(isolate(), GetWrapper(isolate()), "zoom-level-changed", ret);
+  mate::EmitEvent(isolate(), GetWrapper(), "zoom-level-changed", ret);
   return ret;
 }
 
@@ -162,9 +163,15 @@ void WebFrame::ExecuteJavaScript(const base::string16& code,
       callback.release());
 }
 
-mate::ObjectTemplateBuilder WebFrame::GetObjectTemplateBuilder(
-    v8::Isolate* isolate) {
-  return mate::ObjectTemplateBuilder(isolate)
+// static
+mate::Handle<WebFrame> WebFrame::Create(v8::Isolate* isolate) {
+  return mate::CreateHandle(isolate, new WebFrame(isolate));
+}
+
+// static
+void WebFrame::BuildPrototype(
+    v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) {
+  mate::ObjectTemplateBuilder(isolate, prototype)
       .SetMethod("setName", &WebFrame::SetName)
       .SetMethod("setZoomLevel", &WebFrame::SetZoomLevel)
       .SetMethod("getZoomLevel", &WebFrame::GetZoomLevel)
@@ -187,11 +194,6 @@ mate::ObjectTemplateBuilder WebFrame::GetObjectTemplateBuilder(
       .SetMethod("executeJavaScript", &WebFrame::ExecuteJavaScript);
 }
 
-// static
-mate::Handle<WebFrame> WebFrame::Create(v8::Isolate* isolate) {
-  return CreateHandle(isolate, new WebFrame);
-}
-
 }  // namespace api
 
 }  // namespace atom

+ 6 - 7
atom/renderer/api/atom_api_web_frame.h

@@ -26,13 +26,16 @@ namespace api {
 
 class SpellCheckClient;
 
-class WebFrame : public mate::Wrappable {
+class WebFrame : public mate::Wrappable<WebFrame> {
  public:
   static mate::Handle<WebFrame> Create(v8::Isolate* isolate);
 
+  static void BuildPrototype(v8::Isolate* isolate,
+                             v8::Local<v8::ObjectTemplate> prototype);
+
  private:
-  WebFrame();
-  virtual ~WebFrame();
+  explicit WebFrame(v8::Isolate* isolate);
+  ~WebFrame() override;
 
   void SetName(const std::string& name);
 
@@ -66,10 +69,6 @@ class WebFrame : public mate::Wrappable {
   // Excecuting scripts.
   void ExecuteJavaScript(const base::string16& code, mate::Arguments* args);
 
-  // mate::Wrappable:
-  virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
-      v8::Isolate* isolate);
-
   scoped_ptr<SpellCheckClient> spell_check_client_;
 
   blink::WebLocalFrame* web_frame_;

+ 1 - 1
vendor/native_mate

@@ -1 +1 @@
-Subproject commit 553326b00696fcda106a8866872a8f2ad6caff0d
+Subproject commit 0df2d882ea2286e6335f206b7002037fce66c4a5