Browse Source

Merge pull request #4065 from atom/coffee-to-js

[WIP] Convert from CoffeeScript to JavaScript
Cheng Zhao 9 years ago
parent
commit
d9d821cea5
100 changed files with 5105 additions and 3087 deletions
  1. 12 12
      atom.gyp
  2. 0 72
      atom/browser/api/lib/app.coffee
  3. 131 0
      atom/browser/api/lib/app.js
  4. 0 12
      atom/browser/api/lib/auto-updater.coffee
  5. 14 0
      atom/browser/api/lib/auto-updater.js
  6. 0 6
      atom/browser/api/lib/auto-updater/auto-updater-native.coffee
  7. 9 0
      atom/browser/api/lib/auto-updater/auto-updater-native.js
  8. 0 42
      atom/browser/api/lib/auto-updater/auto-updater-win.coffee
  9. 78 0
      atom/browser/api/lib/auto-updater/auto-updater-win.js
  10. 0 67
      atom/browser/api/lib/auto-updater/squirrel-update-win.coffee
  11. 118 0
      atom/browser/api/lib/auto-updater/squirrel-update-win.js
  12. 0 114
      atom/browser/api/lib/browser-window.coffee
  13. 250 0
      atom/browser/api/lib/browser-window.js
  14. 0 1
      atom/browser/api/lib/content-tracing.coffee
  15. 1 0
      atom/browser/api/lib/content-tracing.js
  16. 0 127
      atom/browser/api/lib/dialog.coffee
  17. 175 0
      atom/browser/api/lib/dialog.js
  18. 0 57
      atom/browser/api/lib/exports/electron.coffee
  19. 115 0
      atom/browser/api/lib/exports/electron.js
  20. 0 3
      atom/browser/api/lib/global-shortcut.coffee
  21. 5 0
      atom/browser/api/lib/global-shortcut.js
  22. 0 3
      atom/browser/api/lib/ipc-main.coffee
  23. 5 0
      atom/browser/api/lib/ipc-main.js
  24. 0 6
      atom/browser/api/lib/ipc.coffee
  25. 10 0
      atom/browser/api/lib/ipc.js
  26. 0 73
      atom/browser/api/lib/menu-item.coffee
  27. 108 0
      atom/browser/api/lib/menu-item.js
  28. 0 178
      atom/browser/api/lib/menu.coffee
  29. 350 0
      atom/browser/api/lib/menu.js
  30. 0 122
      atom/browser/api/lib/navigation-controller.coffee
  31. 195 0
      atom/browser/api/lib/navigation-controller.js
  32. 0 7
      atom/browser/api/lib/power-monitor.coffee
  33. 9 0
      atom/browser/api/lib/power-monitor.js
  34. 0 3
      atom/browser/api/lib/power-save-blocker.coffee
  35. 5 0
      atom/browser/api/lib/power-save-blocker.js
  36. 0 25
      atom/browser/api/lib/protocol.coffee
  37. 35 0
      atom/browser/api/lib/protocol.js
  38. 0 6
      atom/browser/api/lib/screen.coffee
  39. 9 0
      atom/browser/api/lib/screen.js
  40. 0 24
      atom/browser/api/lib/session.coffee
  41. 42 0
      atom/browser/api/lib/session.js
  42. 0 19
      atom/browser/api/lib/tray.coffee
  43. 28 0
      atom/browser/api/lib/tray.js
  44. 0 137
      atom/browser/api/lib/web-contents.coffee
  45. 210 0
      atom/browser/api/lib/web-contents.js
  46. 0 96
      atom/browser/lib/chrome-extension.coffee
  47. 163 0
      atom/browser/lib/chrome-extension.js
  48. 0 37
      atom/browser/lib/desktop-capturer.coffee
  49. 85 0
      atom/browser/lib/desktop-capturer.js
  50. 0 174
      atom/browser/lib/guest-view-manager.coffee
  51. 238 0
      atom/browser/lib/guest-view-manager.js
  52. 0 86
      atom/browser/lib/guest-window-manager.coffee
  53. 137 0
      atom/browser/lib/guest-window-manager.js
  54. 0 118
      atom/browser/lib/init.coffee
  55. 201 0
      atom/browser/lib/init.js
  56. 0 67
      atom/browser/lib/objects-registry.coffee
  57. 133 0
      atom/browser/lib/objects-registry.js
  58. 0 231
      atom/browser/lib/rpc-server.coffee
  59. 389 0
      atom/browser/lib/rpc-server.js
  60. 0 43
      atom/common/api/lib/callbacks-registry.coffee
  61. 68 0
      atom/common/api/lib/callbacks-registry.js
  62. 0 5
      atom/common/api/lib/clipboard.coffee
  63. 7 0
      atom/common/api/lib/clipboard.js
  64. 0 69
      atom/common/api/lib/crash-reporter.coffee
  65. 104 0
      atom/common/api/lib/crash-reporter.js
  66. 0 68
      atom/common/api/lib/deprecate.coffee
  67. 115 0
      atom/common/api/lib/deprecate.js
  68. 0 29
      atom/common/api/lib/exports/electron.coffee
  69. 59 0
      atom/common/api/lib/exports/electron.js
  70. 0 7
      atom/common/api/lib/native-image.coffee
  71. 12 0
      atom/common/api/lib/native-image.js
  72. 0 1
      atom/common/api/lib/shell.coffee
  73. 1 0
      atom/common/api/lib/shell.js
  74. 0 386
      atom/common/lib/asar.coffee
  75. 610 0
      atom/common/lib/asar.js
  76. 0 22
      atom/common/lib/asar_init.coffee
  77. 17 0
      atom/common/lib/asar_init.js
  78. 0 36
      atom/common/lib/init.coffee
  79. 62 0
      atom/common/lib/init.js
  80. 0 29
      atom/common/lib/reset-search-paths.coffee
  81. 45 0
      atom/common/lib/reset-search-paths.js
  82. 0 20
      atom/renderer/api/lib/desktop-capturer.coffee
  83. 50 0
      atom/renderer/api/lib/desktop-capturer.js
  84. 0 22
      atom/renderer/api/lib/exports/electron.coffee
  85. 43 0
      atom/renderer/api/lib/exports/electron.js
  86. 0 18
      atom/renderer/api/lib/ipc-renderer.coffee
  87. 33 0
      atom/renderer/api/lib/ipc-renderer.js
  88. 0 19
      atom/renderer/api/lib/ipc.coffee
  89. 38 0
      atom/renderer/api/lib/ipc.js
  90. 0 199
      atom/renderer/api/lib/remote.coffee
  91. 394 0
      atom/renderer/api/lib/remote.js
  92. 0 1
      atom/renderer/api/lib/screen.coffee
  93. 1 0
      atom/renderer/api/lib/screen.js
  94. 0 9
      atom/renderer/api/lib/web-frame.coffee
  95. 16 0
      atom/renderer/api/lib/web-frame.js
  96. 0 10
      atom/renderer/lib/chrome-api.coffee
  97. 16 0
      atom/renderer/lib/chrome-api.js
  98. 0 109
      atom/renderer/lib/init.coffee
  99. 154 0
      atom/renderer/lib/init.js
  100. 0 60
      atom/renderer/lib/inspector.coffee

+ 12 - 12
atom.gyp

@@ -28,7 +28,7 @@
       'target_name': '<(project_name)',
       'type': 'executable',
       'dependencies': [
-        'compile_coffee',
+        'js2asar',
         '<(project_name)_lib',
       ],
       'sources': [
@@ -221,7 +221,7 @@
       'target_name': '<(project_name)_lib',
       'type': 'static_library',
       'dependencies': [
-        'atom_coffee2c',
+        'atom_js2c',
         'vendor/brightray/brightray.gyp:brightray',
         'vendor/node/node.gyp:node',
       ],
@@ -351,11 +351,11 @@
       ],
     },  # target <(product_name)_lib
     {
-      'target_name': 'compile_coffee',
+      'target_name': 'js2asar',
       'type': 'none',
       'actions': [
         {
-          'action_name': 'compile_coffee',
+          'action_name': 'js2asar',
           'variables': {
             'conditions': [
               ['OS=="mac"', {
@@ -366,41 +366,41 @@
             ],
           },
           'inputs': [
-            '<@(coffee_sources)',
+            '<@(js_sources)',
           ],
           'outputs': [
             '<(resources_path)/atom.asar',
           ],
           'action': [
             'python',
-            'tools/coffee2asar.py',
+            'tools/js2asar.py',
             '<@(_outputs)',
             '<@(_inputs)',
           ],
         }
       ],
-    },  # target compile_coffee
+    },  # target js2asar
     {
-      'target_name': 'atom_coffee2c',
+      'target_name': 'atom_js2c',
       'type': 'none',
       'actions': [
         {
-          'action_name': 'atom_coffee2c',
+          'action_name': 'atom_js2c',
           'inputs': [
-            '<@(coffee2c_sources)',
+            '<@(js2c_sources)',
           ],
           'outputs': [
             '<(SHARED_INTERMEDIATE_DIR)/atom_natives.h',
           ],
           'action': [
             'python',
-            'tools/coffee2c.py',
+            'tools/js2c.py',
             '<@(_outputs)',
             '<@(_inputs)',
           ],
         }
       ],
-    },  # target atom_coffee2c
+    },  # target atom_js2c
   ],
   'conditions': [
     ['OS=="mac"', {

+ 0 - 72
atom/browser/api/lib/app.coffee

@@ -1,72 +0,0 @@
-{deprecate, session, Menu} = require 'electron'
-{EventEmitter} = require 'events'
-
-bindings = process.atomBinding 'app'
-downloadItemBindings = process.atomBinding 'download_item'
-
-app = bindings.app
-app.__proto__ = EventEmitter.prototype
-
-app.setApplicationMenu = (menu) ->
-  Menu.setApplicationMenu menu
-
-app.getApplicationMenu = ->
-  Menu.getApplicationMenu()
-
-app.commandLine =
-  appendSwitch: bindings.appendSwitch,
-  appendArgument: bindings.appendArgument
-
-if process.platform is 'darwin'
-  app.dock =
-    bounce: (type='informational') -> bindings.dockBounce type
-    cancelBounce: bindings.dockCancelBounce
-    setBadge: bindings.dockSetBadgeText
-    getBadge: bindings.dockGetBadgeText
-    hide: bindings.dockHide
-    show: bindings.dockShow
-    setMenu: bindings.dockSetMenu
-
-appPath = null
-app.setAppPath = (path) ->
-  appPath = path
-
-app.getAppPath = ->
-  appPath
-
-# Routes the events to webContents.
-for name in ['login', 'certificate-error', 'select-client-certificate']
-  do (name) ->
-    app.on name, (event, webContents, args...) ->
-      webContents.emit name, event, args...
-
-# Deprecated.
-app.getHomeDir = deprecate 'app.getHomeDir', 'app.getPath', ->
-  @getPath 'home'
-app.getDataPath = deprecate 'app.getDataPath', 'app.getPath', ->
-  @getPath 'userData'
-app.setDataPath = deprecate 'app.setDataPath', 'app.setPath', (path) ->
-  @setPath 'userData', path
-app.resolveProxy = deprecate 'app.resolveProxy', 'session.defaultSession.resolveProxy', (url, callback) ->
-  session.defaultSession.resolveProxy url, callback
-deprecate.rename app, 'terminate', 'quit'
-deprecate.event app, 'finish-launching', 'ready', ->
-  setImmediate => # give default app a chance to setup default menu.
-    @emit 'finish-launching'
-deprecate.event app, 'activate-with-no-open-windows', 'activate', (event, hasVisibleWindows) ->
-  @emit 'activate-with-no-open-windows', event if not hasVisibleWindows
-deprecate.event app, 'select-certificate', 'select-client-certificate'
-
-# Wrappers for native classes.
-wrapDownloadItem = (downloadItem) ->
-  # downloadItem is an EventEmitter.
-  downloadItem.__proto__ = EventEmitter.prototype
-  # Deprecated.
-  deprecate.property downloadItem, 'url', 'getURL'
-  deprecate.property downloadItem, 'filename', 'getFilename'
-  deprecate.property downloadItem, 'mimeType', 'getMimeType'
-  deprecate.rename downloadItem, 'getUrl', 'getURL'
-downloadItemBindings._setWrapDownloadItem wrapDownloadItem
-
-# Only one App object pemitted.
-module.exports = app

+ 131 - 0
atom/browser/api/lib/app.js

@@ -0,0 +1,131 @@
+var EventEmitter, Menu, app, appPath, bindings, deprecate, downloadItemBindings, fn, i, len, name, ref, ref1, session, wrapDownloadItem,
+  slice = [].slice;
+
+ref = require('electron'), deprecate = ref.deprecate, session = ref.session, Menu = ref.Menu;
+
+EventEmitter = require('events').EventEmitter;
+
+bindings = process.atomBinding('app');
+
+downloadItemBindings = process.atomBinding('download_item');
+
+app = bindings.app;
+
+app.__proto__ = EventEmitter.prototype;
+
+app.setApplicationMenu = function(menu) {
+  return Menu.setApplicationMenu(menu);
+};
+
+app.getApplicationMenu = function() {
+  return Menu.getApplicationMenu();
+};
+
+app.commandLine = {
+  appendSwitch: bindings.appendSwitch,
+  appendArgument: bindings.appendArgument
+};
+
+if (process.platform === 'darwin') {
+  app.dock = {
+    bounce: function(type) {
+      if (type == null) {
+        type = 'informational';
+      }
+      return bindings.dockBounce(type);
+    },
+    cancelBounce: bindings.dockCancelBounce,
+    setBadge: bindings.dockSetBadgeText,
+    getBadge: bindings.dockGetBadgeText,
+    hide: bindings.dockHide,
+    show: bindings.dockShow,
+    setMenu: bindings.dockSetMenu
+  };
+}
+
+appPath = null;
+
+app.setAppPath = function(path) {
+  return appPath = path;
+};
+
+app.getAppPath = function() {
+  return appPath;
+};
+
+
+/* Routes the events to webContents. */
+
+ref1 = ['login', 'certificate-error', 'select-client-certificate'];
+fn = function(name) {
+  return app.on(name, function() {
+    var args, event, webContents;
+    event = arguments[0], webContents = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : [];
+    return webContents.emit.apply(webContents, [name, event].concat(slice.call(args)));
+  });
+};
+for (i = 0, len = ref1.length; i < len; i++) {
+  name = ref1[i];
+  fn(name);
+}
+
+
+/* Deprecated. */
+
+app.getHomeDir = deprecate('app.getHomeDir', 'app.getPath', function() {
+  return this.getPath('home');
+});
+
+app.getDataPath = deprecate('app.getDataPath', 'app.getPath', function() {
+  return this.getPath('userData');
+});
+
+app.setDataPath = deprecate('app.setDataPath', 'app.setPath', function(path) {
+  return this.setPath('userData', path);
+});
+
+app.resolveProxy = deprecate('app.resolveProxy', 'session.defaultSession.resolveProxy', function(url, callback) {
+  return session.defaultSession.resolveProxy(url, callback);
+});
+
+deprecate.rename(app, 'terminate', 'quit');
+
+deprecate.event(app, 'finish-launching', 'ready', function() {
+
+  /* give default app a chance to setup default menu. */
+  return setImmediate((function(_this) {
+    return function() {
+      return _this.emit('finish-launching');
+    };
+  })(this));
+});
+
+deprecate.event(app, 'activate-with-no-open-windows', 'activate', function(event, hasVisibleWindows) {
+  if (!hasVisibleWindows) {
+    return this.emit('activate-with-no-open-windows', event);
+  }
+});
+
+deprecate.event(app, 'select-certificate', 'select-client-certificate');
+
+
+/* Wrappers for native classes. */
+
+wrapDownloadItem = function(downloadItem) {
+
+  /* downloadItem is an EventEmitter. */
+  downloadItem.__proto__ = EventEmitter.prototype;
+
+  /* Deprecated. */
+  deprecate.property(downloadItem, 'url', 'getURL');
+  deprecate.property(downloadItem, 'filename', 'getFilename');
+  deprecate.property(downloadItem, 'mimeType', 'getMimeType');
+  return deprecate.rename(downloadItem, 'getUrl', 'getURL');
+};
+
+downloadItemBindings._setWrapDownloadItem(wrapDownloadItem);
+
+
+/* Only one App object pemitted. */
+
+module.exports = app;

+ 0 - 12
atom/browser/api/lib/auto-updater.coffee

@@ -1,12 +0,0 @@
-{deprecate} = require 'electron'
-
-autoUpdater =
-  if process.platform is 'win32'
-    require './auto-updater/auto-updater-win'
-  else
-    require './auto-updater/auto-updater-native'
-
-# Deprecated.
-deprecate.rename autoUpdater, 'setFeedUrl', 'setFeedURL'
-
-module.exports = autoUpdater

+ 14 - 0
atom/browser/api/lib/auto-updater.js

@@ -0,0 +1,14 @@
+var autoUpdater, deprecate;
+
+deprecate = require('electron').deprecate;
+
+autoUpdater = process.platform === 'win32' ? require('./auto-updater/auto-updater-win') : require('./auto-updater/auto-updater-native');
+
+
+/* Deprecated. */
+
+deprecate.rename(autoUpdater, 'setFeedUrl', 'setFeedURL');
+
+
+
+module.exports = autoUpdater;

+ 0 - 6
atom/browser/api/lib/auto-updater/auto-updater-native.coffee

@@ -1,6 +0,0 @@
-{EventEmitter} = require 'events'
-{autoUpdater} = process.atomBinding 'auto_updater'
-
-autoUpdater.__proto__ = EventEmitter.prototype
-
-module.exports = autoUpdater

+ 9 - 0
atom/browser/api/lib/auto-updater/auto-updater-native.js

@@ -0,0 +1,9 @@
+var EventEmitter, autoUpdater;
+
+EventEmitter = require('events').EventEmitter;
+
+autoUpdater = process.atomBinding('auto_updater').autoUpdater;
+
+autoUpdater.__proto__ = EventEmitter.prototype;
+
+module.exports = autoUpdater;

+ 0 - 42
atom/browser/api/lib/auto-updater/auto-updater-win.coffee

@@ -1,42 +0,0 @@
-{app} = require 'electron'
-{EventEmitter} = require 'events'
-url = require 'url'
-
-squirrelUpdate = require './squirrel-update-win'
-
-class AutoUpdater extends EventEmitter
-  quitAndInstall: ->
-    squirrelUpdate.processStart()
-    app.quit()
-
-  setFeedURL: (updateURL) ->
-    @updateURL = updateURL
-
-  checkForUpdates: ->
-    return @emitError 'Update URL is not set' unless @updateURL
-    return @emitError 'Can not find Squirrel' unless squirrelUpdate.supported()
-
-    @emit 'checking-for-update'
-
-    squirrelUpdate.download @updateURL, (error, update) =>
-      return @emitError error if error?
-      return @emit 'update-not-available' unless update?
-
-      @emit 'update-available'
-
-      squirrelUpdate.update @updateURL, (error) =>
-        return @emitError error if error?
-
-        {releaseNotes, version} = update
-        # Following information is not available on Windows, so fake them.
-        date = new Date
-        url = @updateURL
-
-        @emit 'update-downloaded', {}, releaseNotes, version, date, url, => @quitAndInstall()
-
-  # Private: Emit both error object and message, this is to keep compatibility
-  # with Old APIs.
-  emitError: (message) ->
-    @emit 'error', new Error(message), message
-
-module.exports = new AutoUpdater

+ 78 - 0
atom/browser/api/lib/auto-updater/auto-updater-win.js

@@ -0,0 +1,78 @@
+var AutoUpdater, EventEmitter, app, squirrelUpdate, url,
+  extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+  hasProp = {}.hasOwnProperty;
+
+app = require('electron').app;
+
+EventEmitter = require('events').EventEmitter;
+
+url = require('url');
+
+squirrelUpdate = require('./squirrel-update-win');
+
+AutoUpdater = (function(superClass) {
+  extend(AutoUpdater, superClass);
+
+  function AutoUpdater() {
+    return AutoUpdater.__super__.constructor.apply(this, arguments);
+  }
+
+  AutoUpdater.prototype.quitAndInstall = function() {
+    squirrelUpdate.processStart();
+    return app.quit();
+  };
+
+  AutoUpdater.prototype.setFeedURL = function(updateURL) {
+    return this.updateURL = updateURL;
+  };
+
+  AutoUpdater.prototype.checkForUpdates = function() {
+    if (!this.updateURL) {
+      return this.emitError('Update URL is not set');
+    }
+    if (!squirrelUpdate.supported()) {
+      return this.emitError('Can not find Squirrel');
+    }
+    this.emit('checking-for-update');
+    return squirrelUpdate.download(this.updateURL, (function(_this) {
+      return function(error, update) {
+        if (error != null) {
+          return _this.emitError(error);
+        }
+        if (update == null) {
+          return _this.emit('update-not-available');
+        }
+        _this.emit('update-available');
+        return squirrelUpdate.update(_this.updateURL, function(error) {
+          var date, releaseNotes, version;
+          if (error != null) {
+            return _this.emitError(error);
+          }
+          releaseNotes = update.releaseNotes, version = update.version;
+
+          /* Following information is not available on Windows, so fake them. */
+          date = new Date;
+          url = _this.updateURL;
+          return _this.emit('update-downloaded', {}, releaseNotes, version, date, url, function() {
+            return _this.quitAndInstall();
+          });
+        });
+      };
+    })(this));
+  };
+
+
+  /*
+    Private: Emit both error object and message, this is to keep compatibility
+    with Old APIs.
+   */
+
+  AutoUpdater.prototype.emitError = function(message) {
+    return this.emit('error', new Error(message), message);
+  };
+
+  return AutoUpdater;
+
+})(EventEmitter);
+
+module.exports = new AutoUpdater;

+ 0 - 67
atom/browser/api/lib/auto-updater/squirrel-update-win.coffee

@@ -1,67 +0,0 @@
-fs      = require 'fs'
-path    = require 'path'
-{spawn} = require 'child_process'
-
-appFolder = path.dirname process.execPath # i.e. my-app/app-0.1.13/
-updateExe = path.resolve appFolder, '..', 'Update.exe' # i.e. my-app/Update.exe
-exeName   = path.basename process.execPath
-
-# Spawn a command and invoke the callback when it completes with an error
-# and the output from standard out.
-spawnUpdate = (args, detached, callback) ->
-  try
-    spawnedProcess = spawn updateExe, args, {detached}
-  catch error
-    # Shouldn't happen, but still guard it.
-    process.nextTick -> callback error
-    return
-
-  stdout = ''
-  stderr = ''
-  spawnedProcess.stdout.on 'data', (data) -> stdout += data
-  spawnedProcess.stderr.on 'data', (data) -> stderr += data
-
-  errorEmitted = false
-  spawnedProcess.on 'error', (error) ->
-    errorEmitted = true
-    callback error
-  spawnedProcess.on 'exit', (code, signal) ->
-    # We may have already emitted an error.
-    return if errorEmitted
-
-    # Process terminated with error.
-    if code isnt 0
-      return callback "Command failed: #{signal ? code}\n#{stderr}"
-
-    # Success.
-    callback null, stdout
-
-# Start an instance of the installed app.
-exports.processStart = (callback) ->
-  spawnUpdate ['--processStart', exeName], true, ->
-
-# Download the releases specified by the URL and write new results to stdout.
-exports.download = (updateURL, callback) ->
-  spawnUpdate ['--download', updateURL], false, (error, stdout) ->
-    return callback(error) if error?
-
-    try
-      # Last line of output is the JSON details about the releases
-      json = stdout.trim().split('\n').pop()
-      update = JSON.parse(json)?.releasesToApply?.pop?()
-    catch
-      return callback "Invalid result:\n#{stdout}"
-
-    callback null, update
-
-# Update the application to the latest remote version specified by URL.
-exports.update = (updateURL, callback) ->
-  spawnUpdate ['--update', updateURL], false, callback
-
-# Is the Update.exe installed with the current application?
-exports.supported = ->
-  try
-    fs.accessSync updateExe, fs.R_OK
-    return true
-  catch
-    return false

+ 118 - 0
atom/browser/api/lib/auto-updater/squirrel-update-win.js

@@ -0,0 +1,118 @@
+var appFolder, exeName, fs, path, spawn, spawnUpdate, updateExe;
+
+fs = require('fs');
+
+path = require('path');
+
+spawn = require('child_process').spawn;
+
+
+/* i.e. my-app/app-0.1.13/ */
+
+appFolder = path.dirname(process.execPath);
+
+
+/* i.e. my-app/Update.exe */
+
+updateExe = path.resolve(appFolder, '..', 'Update.exe');
+
+exeName = path.basename(process.execPath);
+
+
+/*
+  Spawn a command and invoke the callback when it completes with an error
+  and the output from standard out.
+ */
+
+spawnUpdate = function(args, detached, callback) {
+  var error, error1, errorEmitted, spawnedProcess, stderr, stdout;
+  try {
+    spawnedProcess = spawn(updateExe, args, {
+      detached: detached
+    });
+  } catch (error1) {
+    error = error1;
+
+    /* Shouldn't happen, but still guard it. */
+    process.nextTick(function() {
+      return callback(error);
+    });
+    return;
+  }
+  stdout = '';
+  stderr = '';
+  spawnedProcess.stdout.on('data', function(data) {
+    return stdout += data;
+  });
+  spawnedProcess.stderr.on('data', function(data) {
+    return stderr += data;
+  });
+  errorEmitted = false;
+  spawnedProcess.on('error', function(error) {
+    errorEmitted = true;
+    return callback(error);
+  });
+  return spawnedProcess.on('exit', function(code, signal) {
+
+    /* We may have already emitted an error. */
+    if (errorEmitted) {
+      return;
+    }
+
+    /* Process terminated with error. */
+    if (code !== 0) {
+      return callback("Command failed: " + (signal != null ? signal : code) + "\n" + stderr);
+    }
+
+    /* Success. */
+    return callback(null, stdout);
+  });
+};
+
+
+/* Start an instance of the installed app. */
+
+exports.processStart = function(callback) {
+  return spawnUpdate(['--processStart', exeName], true, function() {});
+};
+
+
+/* Download the releases specified by the URL and write new results to stdout. */
+
+exports.download = function(updateURL, callback) {
+  return spawnUpdate(['--download', updateURL], false, function(error, stdout) {
+    var error1, json, ref, ref1, update;
+    if (error != null) {
+      return callback(error);
+    }
+    try {
+
+      /* Last line of output is the JSON details about the releases */
+      json = stdout.trim().split('\n').pop();
+      update = (ref = JSON.parse(json)) != null ? (ref1 = ref.releasesToApply) != null ? typeof ref1.pop === "function" ? ref1.pop() : void 0 : void 0 : void 0;
+    } catch (error1) {
+      return callback("Invalid result:\n" + stdout);
+    }
+    return callback(null, update);
+  });
+};
+
+
+/* Update the application to the latest remote version specified by URL. */
+
+exports.update = function(updateURL, callback) {
+  return spawnUpdate(['--update', updateURL], false, callback);
+};
+
+
+/* Is the Update.exe installed with the current application? */
+
+exports.supported = function() {
+  var error1;
+  try {
+    fs.accessSync(updateExe, fs.R_OK);
+    return true;
+  } catch (error1) {
+    return false;
+  }
+};

+ 0 - 114
atom/browser/api/lib/browser-window.coffee

@@ -1,114 +0,0 @@
-{ipcMain, deprecate} = require 'electron'
-{EventEmitter} = require 'events'
-
-{BrowserWindow} = process.atomBinding 'window'
-BrowserWindow::__proto__ = EventEmitter.prototype
-
-BrowserWindow::_init = ->
-  {app} = require 'electron'  # avoid recursive require.
-
-  # Simulate the application menu on platforms other than OS X.
-  if process.platform isnt 'darwin'
-    menu = app.getApplicationMenu()
-    @setMenu menu if menu?
-
-  # Make new windows requested by links behave like "window.open"
-  @webContents.on '-new-window', (event, url, frameName) ->
-    options = show: true, width: 800, height: 600
-    ipcMain.emit 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', event, url, frameName, options
-
-  # window.resizeTo(...)
-  # window.moveTo(...)
-  @webContents.on 'move', (event, size) =>
-    @setBounds size
-
-  # Hide the auto-hide menu when webContents is focused.
-  @webContents.on 'activate', =>
-    if process.platform isnt 'darwin' and @isMenuBarAutoHide() and @isMenuBarVisible()
-      @setMenuBarVisibility false
-
-  # Forward the crashed event.
-  @webContents.on 'crashed', =>
-    @emit 'crashed'
-
-  # Change window title to page title.
-  @webContents.on 'page-title-updated', (event, title, explicitSet) =>
-    @emit 'page-title-updated', event, title
-    @setTitle title unless event.defaultPrevented
-
-  # Sometimes the webContents doesn't get focus when window is shown, so we have
-  # to force focusing on webContents in this case. The safest way is to focus it
-  # when we first start to load URL, if we do it earlier it won't have effect,
-  # if we do it later we might move focus in the page.
-  # Though this hack is only needed on OS X when the app is launched from
-  # Finder, we still do it on all platforms in case of other bugs we don't know.
-  @webContents.once 'load-url', ->
-    @focus()
-
-  # Redirect focus/blur event to app instance too.
-  @on 'blur', (event) =>
-    app.emit 'browser-window-blur', event, this
-  @on 'focus', (event) =>
-    app.emit 'browser-window-focus', event, this
-
-  # Notify the creation of the window.
-  app.emit 'browser-window-created', {}, this
-
-  # Be compatible with old APIs.
-  @webContents.on 'devtools-focused', => @emit 'devtools-focused'
-  @webContents.on 'devtools-opened', => @emit 'devtools-opened'
-  @webContents.on 'devtools-closed', => @emit 'devtools-closed'
-  Object.defineProperty this, 'devToolsWebContents',
-    enumerable: true,
-    configurable: false,
-    get: -> @webContents.devToolsWebContents
-
-BrowserWindow.getFocusedWindow = ->
-  windows = BrowserWindow.getAllWindows()
-  return window for window in windows when window.isFocused()
-  null
-
-BrowserWindow.fromWebContents = (webContents) ->
-  windows = BrowserWindow.getAllWindows()
-  return window for window in windows when window.webContents?.equal webContents
-
-BrowserWindow.fromDevToolsWebContents = (webContents) ->
-  windows = BrowserWindow.getAllWindows()
-  return window for window in windows when window.devToolsWebContents?.equal webContents
-
-# Helpers.
-BrowserWindow::loadURL = -> @webContents.loadURL.apply @webContents, arguments
-BrowserWindow::getURL = -> @webContents.getURL()
-BrowserWindow::reload = -> @webContents.reload.apply @webContents, arguments
-BrowserWindow::send = -> @webContents.send.apply @webContents, arguments
-BrowserWindow::openDevTools = -> @webContents.openDevTools.apply @webContents, arguments
-BrowserWindow::closeDevTools = -> @webContents.closeDevTools()
-BrowserWindow::isDevToolsOpened = -> @webContents.isDevToolsOpened()
-BrowserWindow::isDevToolsFocused = -> @webContents.isDevToolsFocused()
-BrowserWindow::toggleDevTools = -> @webContents.toggleDevTools()
-BrowserWindow::inspectElement = -> @webContents.inspectElement.apply @webContents, arguments
-BrowserWindow::inspectServiceWorker = -> @webContents.inspectServiceWorker()
-
-# Deprecated.
-deprecate.member BrowserWindow, 'undo', 'webContents'
-deprecate.member BrowserWindow, 'redo', 'webContents'
-deprecate.member BrowserWindow, 'cut', 'webContents'
-deprecate.member BrowserWindow, 'copy', 'webContents'
-deprecate.member BrowserWindow, 'paste', 'webContents'
-deprecate.member BrowserWindow, 'selectAll', 'webContents'
-deprecate.member BrowserWindow, 'reloadIgnoringCache', 'webContents'
-deprecate.member BrowserWindow, 'isLoading', 'webContents'
-deprecate.member BrowserWindow, 'isWaitingForResponse', 'webContents'
-deprecate.member BrowserWindow, 'stop', 'webContents'
-deprecate.member BrowserWindow, 'isCrashed', 'webContents'
-deprecate.member BrowserWindow, 'print', 'webContents'
-deprecate.member BrowserWindow, 'printToPDF', 'webContents'
-deprecate.rename BrowserWindow, 'restart', 'reload'
-deprecate.rename BrowserWindow, 'loadUrl', 'loadURL'
-deprecate.rename BrowserWindow, 'getUrl', 'getURL'
-BrowserWindow::executeJavaScriptInDevTools = deprecate 'executeJavaScriptInDevTools', 'devToolsWebContents.executeJavaScript', (code) ->
-  @devToolsWebContents?.executeJavaScript code
-BrowserWindow::getPageTitle = deprecate 'getPageTitle', 'webContents.getTitle', ->
-  @webContents?.getTitle()
-
-module.exports = BrowserWindow

+ 250 - 0
atom/browser/api/lib/browser-window.js

@@ -0,0 +1,250 @@
+var BrowserWindow, EventEmitter, deprecate, ipcMain, ref;
+
+ref = require('electron'), ipcMain = ref.ipcMain, deprecate = ref.deprecate;
+
+EventEmitter = require('events').EventEmitter;
+
+BrowserWindow = process.atomBinding('window').BrowserWindow;
+
+BrowserWindow.prototype.__proto__ = EventEmitter.prototype;
+
+BrowserWindow.prototype._init = function() {
+
+  /* avoid recursive require. */
+  var app, menu;
+  app = require('electron').app;
+
+  /* Simulate the application menu on platforms other than OS X. */
+  if (process.platform !== 'darwin') {
+    menu = app.getApplicationMenu();
+    if (menu != null) {
+      this.setMenu(menu);
+    }
+  }
+
+  /* Make new windows requested by links behave like "window.open" */
+  this.webContents.on('-new-window', function(event, url, frameName) {
+    var options;
+    options = {
+      show: true,
+      width: 800,
+      height: 600
+    };
+    return ipcMain.emit('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', event, url, frameName, options);
+  });
+
+  /*
+    window.resizeTo(...)
+    window.moveTo(...)
+   */
+  this.webContents.on('move', (function(_this) {
+    return function(event, size) {
+      return _this.setBounds(size);
+    };
+  })(this));
+
+  /* Hide the auto-hide menu when webContents is focused. */
+  this.webContents.on('activate', (function(_this) {
+    return function() {
+      if (process.platform !== 'darwin' && _this.isMenuBarAutoHide() && _this.isMenuBarVisible()) {
+        return _this.setMenuBarVisibility(false);
+      }
+    };
+  })(this));
+
+  /* Forward the crashed event. */
+  this.webContents.on('crashed', (function(_this) {
+    return function() {
+      return _this.emit('crashed');
+    };
+  })(this));
+
+  /* Change window title to page title. */
+  this.webContents.on('page-title-updated', (function(_this) {
+    return function(event, title, explicitSet) {
+      _this.emit('page-title-updated', event, title);
+      if (!event.defaultPrevented) {
+        return _this.setTitle(title);
+      }
+    };
+  })(this));
+
+  /*
+    Sometimes the webContents doesn't get focus when window is shown, so we have
+    to force focusing on webContents in this case. The safest way is to focus it
+    when we first start to load URL, if we do it earlier it won't have effect,
+    if we do it later we might move focus in the page.
+    Though this hack is only needed on OS X when the app is launched from
+    Finder, we still do it on all platforms in case of other bugs we don't know.
+   */
+  this.webContents.once('load-url', function() {
+    return this.focus();
+  });
+
+  /* Redirect focus/blur event to app instance too. */
+  this.on('blur', (function(_this) {
+    return function(event) {
+      return app.emit('browser-window-blur', event, _this);
+    };
+  })(this));
+  this.on('focus', (function(_this) {
+    return function(event) {
+      return app.emit('browser-window-focus', event, _this);
+    };
+  })(this));
+
+  /* Notify the creation of the window. */
+  app.emit('browser-window-created', {}, this);
+
+  /* Be compatible with old APIs. */
+  this.webContents.on('devtools-focused', (function(_this) {
+    return function() {
+      return _this.emit('devtools-focused');
+    };
+  })(this));
+  this.webContents.on('devtools-opened', (function(_this) {
+    return function() {
+      return _this.emit('devtools-opened');
+    };
+  })(this));
+  this.webContents.on('devtools-closed', (function(_this) {
+    return function() {
+      return _this.emit('devtools-closed');
+    };
+  })(this));
+  return Object.defineProperty(this, 'devToolsWebContents', {
+    enumerable: true,
+    configurable: false,
+    get: function() {
+      return this.webContents.devToolsWebContents;
+    }
+  });
+};
+
+BrowserWindow.getFocusedWindow = function() {
+  var i, len, window, windows;
+  windows = BrowserWindow.getAllWindows();
+  for (i = 0, len = windows.length; i < len; i++) {
+    window = windows[i];
+    if (window.isFocused()) {
+      return window;
+    }
+  }
+  return null;
+};
+
+BrowserWindow.fromWebContents = function(webContents) {
+  var i, len, ref1, window, windows;
+  windows = BrowserWindow.getAllWindows();
+  for (i = 0, len = windows.length; i < len; i++) {
+    window = windows[i];
+    if ((ref1 = window.webContents) != null ? ref1.equal(webContents) : void 0) {
+      return window;
+    }
+  }
+};
+
+BrowserWindow.fromDevToolsWebContents = function(webContents) {
+  var i, len, ref1, window, windows;
+  windows = BrowserWindow.getAllWindows();
+  for (i = 0, len = windows.length; i < len; i++) {
+    window = windows[i];
+    if ((ref1 = window.devToolsWebContents) != null ? ref1.equal(webContents) : void 0) {
+      return window;
+    }
+  }
+};
+
+
+/* Helpers. */
+
+BrowserWindow.prototype.loadURL = function() {
+  return this.webContents.loadURL.apply(this.webContents, arguments);
+};
+
+BrowserWindow.prototype.getURL = function() {
+  return this.webContents.getURL();
+};
+
+BrowserWindow.prototype.reload = function() {
+  return this.webContents.reload.apply(this.webContents, arguments);
+};
+
+BrowserWindow.prototype.send = function() {
+  return this.webContents.send.apply(this.webContents, arguments);
+};
+
+BrowserWindow.prototype.openDevTools = function() {
+  return this.webContents.openDevTools.apply(this.webContents, arguments);
+};
+
+BrowserWindow.prototype.closeDevTools = function() {
+  return this.webContents.closeDevTools();
+};
+
+BrowserWindow.prototype.isDevToolsOpened = function() {
+  return this.webContents.isDevToolsOpened();
+};
+
+BrowserWindow.prototype.isDevToolsFocused = function() {
+  return this.webContents.isDevToolsFocused();
+};
+
+BrowserWindow.prototype.toggleDevTools = function() {
+  return this.webContents.toggleDevTools();
+};
+
+BrowserWindow.prototype.inspectElement = function() {
+  return this.webContents.inspectElement.apply(this.webContents, arguments);
+};
+
+BrowserWindow.prototype.inspectServiceWorker = function() {
+  return this.webContents.inspectServiceWorker();
+};
+
+
+/* Deprecated. */
+
+deprecate.member(BrowserWindow, 'undo', 'webContents');
+
+deprecate.member(BrowserWindow, 'redo', 'webContents');
+
+deprecate.member(BrowserWindow, 'cut', 'webContents');
+
+deprecate.member(BrowserWindow, 'copy', 'webContents');
+
+deprecate.member(BrowserWindow, 'paste', 'webContents');
+
+deprecate.member(BrowserWindow, 'selectAll', 'webContents');
+
+deprecate.member(BrowserWindow, 'reloadIgnoringCache', 'webContents');
+
+deprecate.member(BrowserWindow, 'isLoading', 'webContents');
+
+deprecate.member(BrowserWindow, 'isWaitingForResponse', 'webContents');
+
+deprecate.member(BrowserWindow, 'stop', 'webContents');
+
+deprecate.member(BrowserWindow, 'isCrashed', 'webContents');
+
+deprecate.member(BrowserWindow, 'print', 'webContents');
+
+deprecate.member(BrowserWindow, 'printToPDF', 'webContents');
+
+deprecate.rename(BrowserWindow, 'restart', 'reload');
+
+deprecate.rename(BrowserWindow, 'loadUrl', 'loadURL');
+
+deprecate.rename(BrowserWindow, 'getUrl', 'getURL');
+
+BrowserWindow.prototype.executeJavaScriptInDevTools = deprecate('executeJavaScriptInDevTools', 'devToolsWebContents.executeJavaScript', function(code) {
+  var ref1;
+  return (ref1 = this.devToolsWebContents) != null ? ref1.executeJavaScript(code) : void 0;
+});
+
+BrowserWindow.prototype.getPageTitle = deprecate('getPageTitle', 'webContents.getTitle', function() {
+  var ref1;
+  return (ref1 = this.webContents) != null ? ref1.getTitle() : void 0;
+});
+
+module.exports = BrowserWindow;

+ 0 - 1
atom/browser/api/lib/content-tracing.coffee

@@ -1 +0,0 @@
-module.exports = process.atomBinding 'content_tracing'

+ 1 - 0
atom/browser/api/lib/content-tracing.js

@@ -0,0 +1 @@
+module.exports = process.atomBinding('content_tracing');

+ 0 - 127
atom/browser/api/lib/dialog.coffee

@@ -1,127 +0,0 @@
-{app, BrowserWindow} = require 'electron'
-
-binding = process.atomBinding 'dialog'
-v8Util = process.atomBinding 'v8_util'
-
-fileDialogProperties =
-  openFile:        1 << 0
-  openDirectory:   1 << 1
-  multiSelections: 1 << 2
-  createDirectory: 1 << 3
-
-messageBoxTypes = ['none', 'info', 'warning', 'error', 'question']
-
-messageBoxOptions =
-  noLink: 1 << 0
-
-parseArgs = (window, options, callback) ->
-  unless window is null or window?.constructor is BrowserWindow
-    # Shift.
-    callback = options
-    options = window
-    window = null
-  if not callback? and typeof options is 'function'
-    # Shift.
-    callback = options
-    options = null
-  [window, options, callback]
-
-checkAppInitialized = ->
-  throw new Error('dialog module can only be used after app is ready') unless app.isReady()
-
-module.exports =
-  showOpenDialog: (args...) ->
-    checkAppInitialized()
-    [window, options, callback] = parseArgs args...
-
-    options ?= title: 'Open', properties: ['openFile']
-    options.properties ?= ['openFile']
-    throw new TypeError('Properties need to be array') unless Array.isArray options.properties
-
-    properties = 0
-    for prop, value of fileDialogProperties
-      properties |= value if prop in options.properties
-
-    options.title ?= ''
-    options.defaultPath ?= ''
-    options.filters ?= []
-
-    wrappedCallback =
-      if typeof callback is 'function'
-        (success, result) -> callback(if success then result)
-      else
-        null
-
-    binding.showOpenDialog String(options.title),
-                           String(options.defaultPath),
-                           options.filters
-                           properties,
-                           window,
-                           wrappedCallback
-
-  showSaveDialog: (args...) ->
-    checkAppInitialized()
-    [window, options, callback] = parseArgs args...
-
-    options ?= title: 'Save'
-    options.title ?= ''
-    options.defaultPath ?= ''
-    options.filters ?= []
-
-    wrappedCallback =
-      if typeof callback is 'function'
-        (success, result) -> callback(if success then result)
-      else
-        null
-
-    binding.showSaveDialog String(options.title),
-                           String(options.defaultPath),
-                           options.filters
-                           window,
-                           wrappedCallback
-
-  showMessageBox: (args...) ->
-    checkAppInitialized()
-    [window, options, callback] = parseArgs args...
-
-    options ?= type: 'none'
-    options.type ?= 'none'
-    messageBoxType = messageBoxTypes.indexOf options.type
-    throw new TypeError('Invalid message box type') unless messageBoxType > -1
-
-    throw new TypeError('Buttons need to be array') unless Array.isArray options.buttons
-
-    options.title ?= ''
-    options.message ?= ''
-    options.detail ?= ''
-    options.icon ?= null
-    options.defaultId ?= -1
-
-    # Choose a default button to get selected when dialog is cancelled.
-    unless options.cancelId?
-      options.cancelId = 0
-      for text, i in options.buttons
-        if text.toLowerCase() in ['cancel', 'no']
-          options.cancelId = i
-          break
-
-    flags = if options.noLink then messageBoxOptions.noLink else 0
-
-    binding.showMessageBox messageBoxType,
-                           options.buttons,
-                           options.defaultId,
-                           options.cancelId,
-                           flags,
-                           options.title,
-                           options.message,
-                           options.detail,
-                           options.icon,
-                           window,
-                           callback
-
-  showErrorBox: (args...) ->
-    binding.showErrorBox args...
-
-# Mark standard asynchronous functions.
-for api in ['showMessageBox', 'showOpenDialog', 'showSaveDialog']
-  v8Util.setHiddenValue module.exports[api], 'asynchronous', true

+ 175 - 0
atom/browser/api/lib/dialog.js

@@ -0,0 +1,175 @@
+var BrowserWindow, api, app, binding, checkAppInitialized, fileDialogProperties, j, len, messageBoxOptions, messageBoxTypes, parseArgs, ref, ref1, v8Util,
+  slice = [].slice,
+  indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+ref = require('electron'), app = ref.app, BrowserWindow = ref.BrowserWindow;
+
+binding = process.atomBinding('dialog');
+
+v8Util = process.atomBinding('v8_util');
+
+fileDialogProperties = {
+  openFile: 1 << 0,
+  openDirectory: 1 << 1,
+  multiSelections: 1 << 2,
+  createDirectory: 1 << 3
+};
+
+messageBoxTypes = ['none', 'info', 'warning', 'error', 'question'];
+
+messageBoxOptions = {
+  noLink: 1 << 0
+};
+
+parseArgs = function(window, options, callback) {
+  if (!(window === null || (window != null ? window.constructor : void 0) === BrowserWindow)) {
+
+    /* Shift. */
+    callback = options;
+    options = window;
+    window = null;
+  }
+  if ((callback == null) && typeof options === 'function') {
+
+    /* Shift. */
+    callback = options;
+    options = null;
+  }
+  return [window, options, callback];
+};
+
+checkAppInitialized = function() {
+  if (!app.isReady()) {
+    throw new Error('dialog module can only be used after app is ready');
+  }
+};
+
+module.exports = {
+  showOpenDialog: function() {
+    var args, callback, options, prop, properties, ref1, value, window, wrappedCallback;
+    args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+    checkAppInitialized();
+    ref1 = parseArgs.apply(null, args), window = ref1[0], options = ref1[1], callback = ref1[2];
+    if (options == null) {
+      options = {
+        title: 'Open',
+        properties: ['openFile']
+      };
+    }
+    if (options.properties == null) {
+      options.properties = ['openFile'];
+    }
+    if (!Array.isArray(options.properties)) {
+      throw new TypeError('Properties need to be array');
+    }
+    properties = 0;
+    for (prop in fileDialogProperties) {
+      value = fileDialogProperties[prop];
+      if (indexOf.call(options.properties, prop) >= 0) {
+        properties |= value;
+      }
+    }
+    if (options.title == null) {
+      options.title = '';
+    }
+    if (options.defaultPath == null) {
+      options.defaultPath = '';
+    }
+    if (options.filters == null) {
+      options.filters = [];
+    }
+    wrappedCallback = typeof callback === 'function' ? function(success, result) {
+      return callback(success ? result : void 0);
+    } : null;
+    return binding.showOpenDialog(String(options.title), String(options.defaultPath), options.filters, properties, window, wrappedCallback);
+  },
+  showSaveDialog: function() {
+    var args, callback, options, ref1, window, wrappedCallback;
+    args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+    checkAppInitialized();
+    ref1 = parseArgs.apply(null, args), window = ref1[0], options = ref1[1], callback = ref1[2];
+    if (options == null) {
+      options = {
+        title: 'Save'
+      };
+    }
+    if (options.title == null) {
+      options.title = '';
+    }
+    if (options.defaultPath == null) {
+      options.defaultPath = '';
+    }
+    if (options.filters == null) {
+      options.filters = [];
+    }
+    wrappedCallback = typeof callback === 'function' ? function(success, result) {
+      return callback(success ? result : void 0);
+    } : null;
+    return binding.showSaveDialog(String(options.title), String(options.defaultPath), options.filters, window, wrappedCallback);
+  },
+  showMessageBox: function() {
+    var args, callback, flags, i, j, len, messageBoxType, options, ref1, ref2, ref3, text, window;
+    args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+    checkAppInitialized();
+    ref1 = parseArgs.apply(null, args), window = ref1[0], options = ref1[1], callback = ref1[2];
+    if (options == null) {
+      options = {
+        type: 'none'
+      };
+    }
+    if (options.type == null) {
+      options.type = 'none';
+    }
+    messageBoxType = messageBoxTypes.indexOf(options.type);
+    if (!(messageBoxType > -1)) {
+      throw new TypeError('Invalid message box type');
+    }
+    if (!Array.isArray(options.buttons)) {
+      throw new TypeError('Buttons need to be array');
+    }
+    if (options.title == null) {
+      options.title = '';
+    }
+    if (options.message == null) {
+      options.message = '';
+    }
+    if (options.detail == null) {
+      options.detail = '';
+    }
+    if (options.icon == null) {
+      options.icon = null;
+    }
+    if (options.defaultId == null) {
+      options.defaultId = -1;
+    }
+
+    /* Choose a default button to get selected when dialog is cancelled. */
+    if (options.cancelId == null) {
+      options.cancelId = 0;
+      ref2 = options.buttons;
+      for (i = j = 0, len = ref2.length; j < len; i = ++j) {
+        text = ref2[i];
+        if ((ref3 = text.toLowerCase()) === 'cancel' || ref3 === 'no') {
+          options.cancelId = i;
+          break;
+        }
+      }
+    }
+    flags = options.noLink ? messageBoxOptions.noLink : 0;
+    return binding.showMessageBox(messageBoxType, options.buttons, options.defaultId, options.cancelId, flags, options.title, options.message, options.detail, options.icon, window, callback);
+  },
+  showErrorBox: function() {
+    var args;
+    args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+    return binding.showErrorBox.apply(binding, args);
+  }
+};
+
+
+/* Mark standard asynchronous functions. */
+
+ref1 = ['showMessageBox', 'showOpenDialog', 'showSaveDialog'];
+for (j = 0, len = ref1.length; j < len; j++) {
+  api = ref1[j];
+  v8Util.setHiddenValue(module.exports[api], 'asynchronous', true);
+}

+ 0 - 57
atom/browser/api/lib/exports/electron.coffee

@@ -1,57 +0,0 @@
-common = require '../../../../common/api/lib/exports/electron'
-
-# Import common modules.
-common.defineProperties exports
-
-Object.defineProperties exports,
-  # Browser side modules, please sort with alphabet order.
-  app:
-    enumerable: true
-    get: -> require '../app'
-  autoUpdater:
-    enumerable: true
-    get: -> require '../auto-updater'
-  BrowserWindow:
-    enumerable: true
-    get: -> require '../browser-window'
-  contentTracing:
-    enumerable: true
-    get: -> require '../content-tracing'
-  dialog:
-    enumerable: true
-    get: -> require '../dialog'
-  ipcMain:
-    enumerable: true
-    get: -> require '../ipc-main'
-  globalShortcut:
-    enumerable: true
-    get: -> require '../global-shortcut'
-  Menu:
-    enumerable: true
-    get: -> require '../menu'
-  MenuItem:
-    enumerable: true
-    get: -> require '../menu-item'
-  powerMonitor:
-    enumerable: true
-    get: -> require '../power-monitor'
-  powerSaveBlocker:
-    enumerable: true
-    get: -> require '../power-save-blocker'
-  protocol:
-    enumerable: true
-    get: -> require '../protocol'
-  screen:
-    enumerable: true
-    get: -> require '../screen'
-  session:
-    enumerable: true
-    get: -> require '../session'
-  Tray:
-    enumerable: true
-    get: -> require '../tray'
-  # The internal modules, invisible unless you know their names.
-  NavigationController:
-    get: -> require '../navigation-controller'
-  webContents:
-    get: -> require '../web-contents'

+ 115 - 0
atom/browser/api/lib/exports/electron.js

@@ -0,0 +1,115 @@
+var common;
+
+common = require('../../../../common/api/lib/exports/electron');
+
+
+/* Import common modules. */
+
+common.defineProperties(exports);
+
+Object.defineProperties(exports, {
+
+  /* Browser side modules, please sort with alphabet order. */
+  app: {
+    enumerable: true,
+    get: function() {
+      return require('../app');
+    }
+  },
+  autoUpdater: {
+    enumerable: true,
+    get: function() {
+      return require('../auto-updater');
+    }
+  },
+  BrowserWindow: {
+    enumerable: true,
+    get: function() {
+      return require('../browser-window');
+    }
+  },
+  contentTracing: {
+    enumerable: true,
+    get: function() {
+      return require('../content-tracing');
+    }
+  },
+  dialog: {
+    enumerable: true,
+    get: function() {
+      return require('../dialog');
+    }
+  },
+  ipcMain: {
+    enumerable: true,
+    get: function() {
+      return require('../ipc-main');
+    }
+  },
+  globalShortcut: {
+    enumerable: true,
+    get: function() {
+      return require('../global-shortcut');
+    }
+  },
+  Menu: {
+    enumerable: true,
+    get: function() {
+      return require('../menu');
+    }
+  },
+  MenuItem: {
+    enumerable: true,
+    get: function() {
+      return require('../menu-item');
+    }
+  },
+  powerMonitor: {
+    enumerable: true,
+    get: function() {
+      return require('../power-monitor');
+    }
+  },
+  powerSaveBlocker: {
+    enumerable: true,
+    get: function() {
+      return require('../power-save-blocker');
+    }
+  },
+  protocol: {
+    enumerable: true,
+    get: function() {
+      return require('../protocol');
+    }
+  },
+  screen: {
+    enumerable: true,
+    get: function() {
+      return require('../screen');
+    }
+  },
+  session: {
+    enumerable: true,
+    get: function() {
+      return require('../session');
+    }
+  },
+  Tray: {
+    enumerable: true,
+    get: function() {
+      return require('../tray');
+    }
+  },
+
+  /* The internal modules, invisible unless you know their names. */
+  NavigationController: {
+    get: function() {
+      return require('../navigation-controller');
+    }
+  },
+  webContents: {
+    get: function() {
+      return require('../web-contents');
+    }
+  }
+});

+ 0 - 3
atom/browser/api/lib/global-shortcut.coffee

@@ -1,3 +0,0 @@
-{globalShortcut} = process.atomBinding 'global_shortcut'
-
-module.exports = globalShortcut

+ 5 - 0
atom/browser/api/lib/global-shortcut.js

@@ -0,0 +1,5 @@
+var globalShortcut;
+
+globalShortcut = process.atomBinding('global_shortcut').globalShortcut;
+
+module.exports = globalShortcut;

+ 0 - 3
atom/browser/api/lib/ipc-main.coffee

@@ -1,3 +0,0 @@
-{EventEmitter} = require 'events'
-
-module.exports = new EventEmitter

+ 5 - 0
atom/browser/api/lib/ipc-main.js

@@ -0,0 +1,5 @@
+var EventEmitter;
+
+EventEmitter = require('events').EventEmitter;
+
+module.exports = new EventEmitter;

+ 0 - 6
atom/browser/api/lib/ipc.coffee

@@ -1,6 +0,0 @@
-{deprecate, ipcMain} = require 'electron'
-
-# This module is deprecated, we mirror everything from ipcMain.
-deprecate.warn 'ipc module', 'require("electron").ipcMain'
-
-module.exports = ipcMain

+ 10 - 0
atom/browser/api/lib/ipc.js

@@ -0,0 +1,10 @@
+var deprecate, ipcMain, ref;
+
+ref = require('electron'), deprecate = ref.deprecate, ipcMain = ref.ipcMain;
+
+
+/* This module is deprecated, we mirror everything from ipcMain. */
+
+deprecate.warn('ipc module', 'require("electron").ipcMain');
+
+module.exports = ipcMain;

+ 0 - 73
atom/browser/api/lib/menu-item.coffee

@@ -1,73 +0,0 @@
-v8Util = process.atomBinding 'v8_util'
-
-nextCommandId = 0
-
-# Maps role to methods of webContents
-rolesMap =
-  undo: 'undo'
-  redo: 'redo'
-  cut: 'cut'
-  copy: 'copy'
-  paste: 'paste'
-  selectall: 'selectAll'
-  minimize: 'minimize'
-  close: 'close'
-
-# Maps methods that should be called directly on the BrowserWindow instance
-methodInBrowserWindow =
-  minimize: true
-  close: true
-
-class MenuItem
-  @types = ['normal', 'separator', 'submenu', 'checkbox', 'radio']
-
-  constructor: (options) ->
-    {Menu} = require 'electron'
-
-    {click, @selector, @type, @role, @label, @sublabel, @accelerator, @icon, @enabled, @visible, @checked, @submenu} = options
-
-    if @submenu? and @submenu.constructor isnt Menu
-      @submenu = Menu.buildFromTemplate @submenu
-    @type = 'submenu' if not @type? and @submenu?
-    throw new Error('Invalid submenu') if @type is 'submenu' and @submenu?.constructor isnt Menu
-
-    @overrideReadOnlyProperty 'type', 'normal'
-    @overrideReadOnlyProperty 'role'
-    @overrideReadOnlyProperty 'accelerator'
-    @overrideReadOnlyProperty 'icon'
-    @overrideReadOnlyProperty 'submenu'
-    @overrideProperty 'label', ''
-    @overrideProperty 'sublabel', ''
-    @overrideProperty 'enabled', true
-    @overrideProperty 'visible', true
-    @overrideProperty 'checked', false
-
-    throw new Error("Unknown menu type #{@type}") if MenuItem.types.indexOf(@type) is -1
-
-    @commandId = ++nextCommandId
-    @click = (focusedWindow) =>
-      # Manually flip the checked flags when clicked.
-      @checked = !@checked if @type in ['checkbox', 'radio']
-
-      if @role and rolesMap[@role] and process.platform isnt 'darwin' and focusedWindow?
-        methodName = rolesMap[@role]
-        if methodInBrowserWindow[methodName]
-          focusedWindow[methodName]()
-        else
-          focusedWindow.webContents?[methodName]()
-      else if typeof click is 'function'
-        click this, focusedWindow
-      else if typeof @selector is 'string'
-        Menu.sendActionToFirstResponder @selector
-
-  overrideProperty: (name, defaultValue=null) ->
-    this[name] ?= defaultValue
-
-  overrideReadOnlyProperty: (name, defaultValue=null) ->
-    this[name] ?= defaultValue
-    Object.defineProperty this, name,
-      enumerable: true
-      writable: false
-      value: this[name]
-
-module.exports = MenuItem

+ 108 - 0
atom/browser/api/lib/menu-item.js

@@ -0,0 +1,108 @@
+var MenuItem, methodInBrowserWindow, nextCommandId, rolesMap, v8Util;
+
+v8Util = process.atomBinding('v8_util');
+
+nextCommandId = 0;
+
+
+/* Maps role to methods of webContents */
+
+rolesMap = {
+  undo: 'undo',
+  redo: 'redo',
+  cut: 'cut',
+  copy: 'copy',
+  paste: 'paste',
+  selectall: 'selectAll',
+  minimize: 'minimize',
+  close: 'close'
+};
+
+
+/* Maps methods that should be called directly on the BrowserWindow instance */
+
+methodInBrowserWindow = {
+  minimize: true,
+  close: true
+};
+
+MenuItem = (function() {
+  MenuItem.types = ['normal', 'separator', 'submenu', 'checkbox', 'radio'];
+
+  function MenuItem(options) {
+    var Menu, click, ref;
+    Menu = require('electron').Menu;
+    click = options.click, this.selector = options.selector, this.type = options.type, this.role = options.role, this.label = options.label, this.sublabel = options.sublabel, this.accelerator = options.accelerator, this.icon = options.icon, this.enabled = options.enabled, this.visible = options.visible, this.checked = options.checked, this.submenu = options.submenu;
+    if ((this.submenu != null) && this.submenu.constructor !== Menu) {
+      this.submenu = Menu.buildFromTemplate(this.submenu);
+    }
+    if ((this.type == null) && (this.submenu != null)) {
+      this.type = 'submenu';
+    }
+    if (this.type === 'submenu' && ((ref = this.submenu) != null ? ref.constructor : void 0) !== Menu) {
+      throw new Error('Invalid submenu');
+    }
+    this.overrideReadOnlyProperty('type', 'normal');
+    this.overrideReadOnlyProperty('role');
+    this.overrideReadOnlyProperty('accelerator');
+    this.overrideReadOnlyProperty('icon');
+    this.overrideReadOnlyProperty('submenu');
+    this.overrideProperty('label', '');
+    this.overrideProperty('sublabel', '');
+    this.overrideProperty('enabled', true);
+    this.overrideProperty('visible', true);
+    this.overrideProperty('checked', false);
+    if (MenuItem.types.indexOf(this.type) === -1) {
+      throw new Error("Unknown menu type " + this.type);
+    }
+    this.commandId = ++nextCommandId;
+    this.click = (function(_this) {
+      return function(focusedWindow) {
+
+        /* Manually flip the checked flags when clicked. */
+        var methodName, ref1, ref2;
+        if ((ref1 = _this.type) === 'checkbox' || ref1 === 'radio') {
+          _this.checked = !_this.checked;
+        }
+        if (_this.role && rolesMap[_this.role] && process.platform !== 'darwin' && (focusedWindow != null)) {
+          methodName = rolesMap[_this.role];
+          if (methodInBrowserWindow[methodName]) {
+            return focusedWindow[methodName]();
+          } else {
+            return (ref2 = focusedWindow.webContents) != null ? ref2[methodName]() : void 0;
+          }
+        } else if (typeof click === 'function') {
+          return click(_this, focusedWindow);
+        } else if (typeof _this.selector === 'string') {
+          return Menu.sendActionToFirstResponder(_this.selector);
+        }
+      };
+    })(this);
+  }
+
+  MenuItem.prototype.overrideProperty = function(name, defaultValue) {
+    if (defaultValue == null) {
+      defaultValue = null;
+    }
+    return this[name] != null ? this[name] : this[name] = defaultValue;
+  };
+
+  MenuItem.prototype.overrideReadOnlyProperty = function(name, defaultValue) {
+    if (defaultValue == null) {
+      defaultValue = null;
+    }
+    if (this[name] == null) {
+      this[name] = defaultValue;
+    }
+    return Object.defineProperty(this, name, {
+      enumerable: true,
+      writable: false,
+      value: this[name]
+    });
+  };
+
+  return MenuItem;
+
+})();
+
+module.exports = MenuItem;

+ 0 - 178
atom/browser/api/lib/menu.coffee

@@ -1,178 +0,0 @@
-{BrowserWindow, MenuItem} = require 'electron'
-{EventEmitter} = require 'events'
-
-v8Util = process.atomBinding 'v8_util'
-bindings = process.atomBinding 'menu'
-
-# Automatically generated radio menu item's group id.
-nextGroupId = 0
-
-# Search between seperators to find a radio menu item and return its group id,
-# otherwise generate a group id.
-generateGroupId = (items, pos) ->
-  if pos > 0
-    for i in [pos - 1..0]
-      item = items[i]
-      return item.groupId if item.type is 'radio'
-      break if item.type is 'separator'
-  else if pos < items.length
-    for i in [pos..items.length - 1]
-      item = items[i]
-      return item.groupId if item.type is 'radio'
-      break if item.type is 'separator'
-  ++nextGroupId
-
-# Returns the index of item according to |id|.
-indexOfItemById = (items, id) ->
-  return i for item, i in items when item.id is id
-  -1
-
-# Returns the index of where to insert the item according to |position|.
-indexToInsertByPosition = (items, position) ->
-  return items.length unless position
-
-  [query, id] = position.split '='
-  insertIndex = indexOfItemById items, id
-  if insertIndex is -1 and query isnt 'endof'
-    console.warn "Item with id '#{id}' is not found"
-    return items.length
-
-  switch query
-    when 'after'
-      insertIndex++
-    when 'endof'
-      # If the |id| doesn't exist, then create a new group with the |id|.
-      if insertIndex is -1
-        items.push id: id, type: 'separator'
-        insertIndex = items.length - 1
-
-      # Find the end of the group.
-      insertIndex++
-      while insertIndex < items.length and items[insertIndex].type isnt 'separator'
-        insertIndex++
-
-  insertIndex
-
-Menu = bindings.Menu
-Menu::__proto__ = EventEmitter.prototype
-
-Menu::_init = ->
-  @commandsMap = {}
-  @groupsMap = {}
-  @items = []
-  @delegate =
-    isCommandIdChecked: (commandId) => @commandsMap[commandId]?.checked
-    isCommandIdEnabled: (commandId) => @commandsMap[commandId]?.enabled
-    isCommandIdVisible: (commandId) => @commandsMap[commandId]?.visible
-    getAcceleratorForCommandId: (commandId) => @commandsMap[commandId]?.accelerator
-    getIconForCommandId: (commandId) => @commandsMap[commandId]?.icon
-    executeCommand: (commandId) =>
-      @commandsMap[commandId]?.click BrowserWindow.getFocusedWindow()
-    menuWillShow: =>
-      # Make sure radio groups have at least one menu item seleted.
-      for id, group of @groupsMap
-        checked = false
-        for radioItem in group when radioItem.checked
-          checked = true
-          break
-        v8Util.setHiddenValue group[0], 'checked', true unless checked
-
-Menu::popup = (window, x, y) ->
-  unless window?.constructor is BrowserWindow
-    # Shift.
-    y = x
-    x = window
-    window = BrowserWindow.getFocusedWindow()
-  if x? and y?
-    @_popupAt(window, x, y)
-  else
-    @_popup window
-
-Menu::append = (item) ->
-  @insert @getItemCount(), item
-
-Menu::insert = (pos, item) ->
-  throw new TypeError('Invalid item') unless item?.constructor is MenuItem
-
-  switch item.type
-    when 'normal' then @insertItem pos, item.commandId, item.label
-    when 'checkbox' then @insertCheckItem pos, item.commandId, item.label
-    when 'separator' then @insertSeparator pos
-    when 'submenu' then @insertSubMenu pos, item.commandId, item.label, item.submenu
-    when 'radio'
-      # Grouping radio menu items.
-      item.overrideReadOnlyProperty 'groupId', generateGroupId(@items, pos)
-      @groupsMap[item.groupId] ?= []
-      @groupsMap[item.groupId].push item
-
-      # Setting a radio menu item should flip other items in the group.
-      v8Util.setHiddenValue item, 'checked', item.checked
-      Object.defineProperty item, 'checked',
-        enumerable: true
-        get: -> v8Util.getHiddenValue item, 'checked'
-        set: (val) =>
-          for otherItem in @groupsMap[item.groupId] when otherItem isnt item
-            v8Util.setHiddenValue otherItem, 'checked', false
-          v8Util.setHiddenValue item, 'checked', true
-
-      @insertRadioItem pos, item.commandId, item.label, item.groupId
-
-  @setSublabel pos, item.sublabel if item.sublabel?
-  @setIcon pos, item.icon if item.icon?
-  @setRole pos, item.role if item.role?
-
-  # Make menu accessable to items.
-  item.overrideReadOnlyProperty 'menu', this
-
-  # Remember the items.
-  @items.splice pos, 0, item
-  @commandsMap[item.commandId] = item
-
-# Force menuWillShow to be called
-Menu::_callMenuWillShow = ->
-  @delegate?.menuWillShow()
-  item.submenu._callMenuWillShow() for item in @items when item.submenu?
-
-applicationMenu = null
-Menu.setApplicationMenu = (menu) ->
-  throw new TypeError('Invalid menu') unless menu is null or menu.constructor is Menu
-  applicationMenu = menu  # Keep a reference.
-
-  if process.platform is 'darwin'
-    return if menu is null
-    menu._callMenuWillShow()
-    bindings.setApplicationMenu menu
-  else
-    windows = BrowserWindow.getAllWindows()
-    w.setMenu menu for w in windows
-
-Menu.getApplicationMenu = -> applicationMenu
-
-Menu.sendActionToFirstResponder = bindings.sendActionToFirstResponder
-
-Menu.buildFromTemplate = (template) ->
-  throw new TypeError('Invalid template for Menu') unless Array.isArray template
-
-  positionedTemplate = []
-  insertIndex = 0
-
-  for item in template
-    if item.position
-      insertIndex = indexToInsertByPosition positionedTemplate, item.position
-    else
-      # If no |position| is specified, insert after last item.
-      insertIndex++
-    positionedTemplate.splice insertIndex, 0, item
-
-  menu = new Menu
-
-  for item in positionedTemplate
-    throw new TypeError('Invalid template for MenuItem') unless typeof item is 'object'
-
-    menuItem = new MenuItem(item)
-    menuItem[key] ?= value for key, value of item
-    menu.append menuItem
-
-  menu
-
-module.exports = Menu

+ 350 - 0
atom/browser/api/lib/menu.js

@@ -0,0 +1,350 @@
+var BrowserWindow, EventEmitter, Menu, MenuItem, applicationMenu, bindings, generateGroupId, indexOfItemById, indexToInsertByPosition, nextGroupId, ref, v8Util;
+
+ref = require('electron'), BrowserWindow = ref.BrowserWindow, MenuItem = ref.MenuItem;
+
+EventEmitter = require('events').EventEmitter;
+
+v8Util = process.atomBinding('v8_util');
+
+bindings = process.atomBinding('menu');
+
+
+/* Automatically generated radio menu item's group id. */
+
+nextGroupId = 0;
+
+
+/* Search between seperators to find a radio menu item and return its group id, */
+
+
+/* otherwise generate a group id. */
+
+generateGroupId = function(items, pos) {
+  var i, item, j, k, ref1, ref2, ref3;
+  if (pos > 0) {
+    for (i = j = ref1 = pos - 1; ref1 <= 0 ? j <= 0 : j >= 0; i = ref1 <= 0 ? ++j : --j) {
+      item = items[i];
+      if (item.type === 'radio') {
+        return item.groupId;
+      }
+      if (item.type === 'separator') {
+        break;
+      }
+    }
+  } else if (pos < items.length) {
+    for (i = k = ref2 = pos, ref3 = items.length - 1; ref2 <= ref3 ? k <= ref3 : k >= ref3; i = ref2 <= ref3 ? ++k : --k) {
+      item = items[i];
+      if (item.type === 'radio') {
+        return item.groupId;
+      }
+      if (item.type === 'separator') {
+        break;
+      }
+    }
+  }
+  return ++nextGroupId;
+};
+
+
+/* Returns the index of item according to |id|. */
+
+indexOfItemById = function(items, id) {
+  var i, item, j, len;
+  for (i = j = 0, len = items.length; j < len; i = ++j) {
+    item = items[i];
+    if (item.id === id) {
+      return i;
+    }
+  }
+  return -1;
+};
+
+
+/* Returns the index of where to insert the item according to |position|. */
+
+indexToInsertByPosition = function(items, position) {
+  var id, insertIndex, query, ref1;
+  if (!position) {
+    return items.length;
+  }
+  ref1 = position.split('='), query = ref1[0], id = ref1[1];
+  insertIndex = indexOfItemById(items, id);
+  if (insertIndex === -1 && query !== 'endof') {
+    console.warn("Item with id '" + id + "' is not found");
+    return items.length;
+  }
+  switch (query) {
+    case 'after':
+      insertIndex++;
+      break;
+    case 'endof':
+
+      /* If the |id| doesn't exist, then create a new group with the |id|. */
+      if (insertIndex === -1) {
+        items.push({
+          id: id,
+          type: 'separator'
+        });
+        insertIndex = items.length - 1;
+      }
+
+      /* Find the end of the group. */
+      insertIndex++;
+      while (insertIndex < items.length && items[insertIndex].type !== 'separator') {
+        insertIndex++;
+      }
+  }
+  return insertIndex;
+};
+
+Menu = bindings.Menu;
+
+Menu.prototype.__proto__ = EventEmitter.prototype;
+
+Menu.prototype._init = function() {
+  this.commandsMap = {};
+  this.groupsMap = {};
+  this.items = [];
+  return this.delegate = {
+    isCommandIdChecked: (function(_this) {
+      return function(commandId) {
+        var ref1;
+        return (ref1 = _this.commandsMap[commandId]) != null ? ref1.checked : void 0;
+      };
+    })(this),
+    isCommandIdEnabled: (function(_this) {
+      return function(commandId) {
+        var ref1;
+        return (ref1 = _this.commandsMap[commandId]) != null ? ref1.enabled : void 0;
+      };
+    })(this),
+    isCommandIdVisible: (function(_this) {
+      return function(commandId) {
+        var ref1;
+        return (ref1 = _this.commandsMap[commandId]) != null ? ref1.visible : void 0;
+      };
+    })(this),
+    getAcceleratorForCommandId: (function(_this) {
+      return function(commandId) {
+        var ref1;
+        return (ref1 = _this.commandsMap[commandId]) != null ? ref1.accelerator : void 0;
+      };
+    })(this),
+    getIconForCommandId: (function(_this) {
+      return function(commandId) {
+        var ref1;
+        return (ref1 = _this.commandsMap[commandId]) != null ? ref1.icon : void 0;
+      };
+    })(this),
+    executeCommand: (function(_this) {
+      return function(commandId) {
+        var ref1;
+        return (ref1 = _this.commandsMap[commandId]) != null ? ref1.click(BrowserWindow.getFocusedWindow()) : void 0;
+      };
+    })(this),
+    menuWillShow: (function(_this) {
+      return function() {
+
+        /* Make sure radio groups have at least one menu item seleted. */
+        var checked, group, id, j, len, radioItem, ref1, results;
+        ref1 = _this.groupsMap;
+        results = [];
+        for (id in ref1) {
+          group = ref1[id];
+          checked = false;
+          for (j = 0, len = group.length; j < len; j++) {
+            radioItem = group[j];
+            if (!radioItem.checked) {
+              continue;
+            }
+            checked = true;
+            break;
+          }
+          if (!checked) {
+            results.push(v8Util.setHiddenValue(group[0], 'checked', true));
+          } else {
+            results.push(void 0);
+          }
+        }
+        return results;
+      };
+    })(this)
+  };
+};
+
+Menu.prototype.popup = function(window, x, y) {
+  if ((window != null ? window.constructor : void 0) !== BrowserWindow) {
+
+    /* Shift. */
+    y = x;
+    x = window;
+    window = BrowserWindow.getFocusedWindow();
+  }
+  if ((x != null) && (y != null)) {
+    return this._popupAt(window, x, y);
+  } else {
+    return this._popup(window);
+  }
+};
+
+Menu.prototype.append = function(item) {
+  return this.insert(this.getItemCount(), item);
+};
+
+Menu.prototype.insert = function(pos, item) {
+  var base, name;
+  if ((item != null ? item.constructor : void 0) !== MenuItem) {
+    throw new TypeError('Invalid item');
+  }
+  switch (item.type) {
+    case 'normal':
+      this.insertItem(pos, item.commandId, item.label);
+      break;
+    case 'checkbox':
+      this.insertCheckItem(pos, item.commandId, item.label);
+      break;
+    case 'separator':
+      this.insertSeparator(pos);
+      break;
+    case 'submenu':
+      this.insertSubMenu(pos, item.commandId, item.label, item.submenu);
+      break;
+    case 'radio':
+
+      /* Grouping radio menu items. */
+      item.overrideReadOnlyProperty('groupId', generateGroupId(this.items, pos));
+      if ((base = this.groupsMap)[name = item.groupId] == null) {
+        base[name] = [];
+      }
+      this.groupsMap[item.groupId].push(item);
+
+      /* Setting a radio menu item should flip other items in the group. */
+      v8Util.setHiddenValue(item, 'checked', item.checked);
+      Object.defineProperty(item, 'checked', {
+        enumerable: true,
+        get: function() {
+          return v8Util.getHiddenValue(item, 'checked');
+        },
+        set: (function(_this) {
+          return function(val) {
+            var j, len, otherItem, ref1;
+            ref1 = _this.groupsMap[item.groupId];
+            for (j = 0, len = ref1.length; j < len; j++) {
+              otherItem = ref1[j];
+              if (otherItem !== item) {
+                v8Util.setHiddenValue(otherItem, 'checked', false);
+              }
+            }
+            return v8Util.setHiddenValue(item, 'checked', true);
+          };
+        })(this)
+      });
+      this.insertRadioItem(pos, item.commandId, item.label, item.groupId);
+  }
+  if (item.sublabel != null) {
+    this.setSublabel(pos, item.sublabel);
+  }
+  if (item.icon != null) {
+    this.setIcon(pos, item.icon);
+  }
+  if (item.role != null) {
+    this.setRole(pos, item.role);
+  }
+
+  /* Make menu accessable to items. */
+  item.overrideReadOnlyProperty('menu', this);
+
+  /* Remember the items. */
+  this.items.splice(pos, 0, item);
+  return this.commandsMap[item.commandId] = item;
+};
+
+
+/* Force menuWillShow to be called */
+
+Menu.prototype._callMenuWillShow = function() {
+  var item, j, len, ref1, ref2, results;
+  if ((ref1 = this.delegate) != null) {
+    ref1.menuWillShow();
+  }
+  ref2 = this.items;
+  results = [];
+  for (j = 0, len = ref2.length; j < len; j++) {
+    item = ref2[j];
+    if (item.submenu != null) {
+      results.push(item.submenu._callMenuWillShow());
+    }
+  }
+  return results;
+};
+
+applicationMenu = null;
+
+Menu.setApplicationMenu = function(menu) {
+  var j, len, results, w, windows;
+  if (!(menu === null || menu.constructor === Menu)) {
+    throw new TypeError('Invalid menu');
+  }
+
+  /* Keep a reference. */
+  applicationMenu = menu;
+  if (process.platform === 'darwin') {
+    if (menu === null) {
+      return;
+    }
+    menu._callMenuWillShow();
+    return bindings.setApplicationMenu(menu);
+  } else {
+    windows = BrowserWindow.getAllWindows();
+    results = [];
+    for (j = 0, len = windows.length; j < len; j++) {
+      w = windows[j];
+      results.push(w.setMenu(menu));
+    }
+    return results;
+  }
+};
+
+Menu.getApplicationMenu = function() {
+  return applicationMenu;
+};
+
+Menu.sendActionToFirstResponder = bindings.sendActionToFirstResponder;
+
+Menu.buildFromTemplate = function(template) {
+  var insertIndex, item, j, k, key, len, len1, menu, menuItem, positionedTemplate, value;
+  if (!Array.isArray(template)) {
+    throw new TypeError('Invalid template for Menu');
+  }
+  positionedTemplate = [];
+  insertIndex = 0;
+  for (j = 0, len = template.length; j < len; j++) {
+    item = template[j];
+    if (item.position) {
+      insertIndex = indexToInsertByPosition(positionedTemplate, item.position);
+    } else {
+
+      /* If no |position| is specified, insert after last item. */
+      insertIndex++;
+    }
+    positionedTemplate.splice(insertIndex, 0, item);
+  }
+  menu = new Menu;
+  for (k = 0, len1 = positionedTemplate.length; k < len1; k++) {
+    item = positionedTemplate[k];
+    if (typeof item !== 'object') {
+      throw new TypeError('Invalid template for MenuItem');
+    }
+    menuItem = new MenuItem(item);
+    for (key in item) {
+      value = item[key];
+      if (menuItem[key] == null) {
+        menuItem[key] = value;
+      }
+    }
+    menu.append(menuItem);
+  }
+  return menu;
+};
+
+module.exports = Menu;

+ 0 - 122
atom/browser/api/lib/navigation-controller.coffee

@@ -1,122 +0,0 @@
-{ipcMain} = require 'electron'
-
-# The history operation in renderer is redirected to browser.
-ipcMain.on 'ATOM_SHELL_NAVIGATION_CONTROLLER', (event, method, args...) ->
-  event.sender[method] args...
-
-ipcMain.on 'ATOM_SHELL_SYNC_NAVIGATION_CONTROLLER', (event, method, args...) ->
-  event.returnValue = event.sender[method] args...
-
-# JavaScript implementation of Chromium's NavigationController.
-# Instead of relying on Chromium for history control, we compeletely do history
-# control on user land, and only rely on WebContents.loadURL for navigation.
-# This helps us avoid Chromium's various optimizations so we can ensure renderer
-# process is restarted everytime.
-class NavigationController
-  constructor: (@webContents) ->
-    @clearHistory()
-
-    # webContents may have already navigated to a page.
-    if @webContents._getURL()
-      @currentIndex++
-      @history.push @webContents._getURL()
-
-    @webContents.on 'navigation-entry-commited', (event, url, inPage, replaceEntry) =>
-      if @inPageIndex > -1 and not inPage
-        # Navigated to a new page, clear in-page mark.
-        @inPageIndex = -1
-      else if @inPageIndex is -1 and inPage
-        # Started in-page navigations.
-        @inPageIndex = @currentIndex
-
-      if @pendingIndex >= 0 # Go to index.
-        @currentIndex = @pendingIndex
-        @pendingIndex = -1
-        @history[@currentIndex] = url
-      else if replaceEntry # Non-user initialized navigation.
-        @history[@currentIndex] = url
-      else  # Normal navigation.
-        @history = @history.slice 0, @currentIndex + 1  # Clear history.
-        currentEntry = @history[@currentIndex]
-        if currentEntry?.url isnt url
-          @currentIndex++
-          @history.push url
-
-  loadURL: (url, options={}) ->
-    @pendingIndex = -1
-    @webContents._loadURL url, options
-    @webContents.emit 'load-url', url, options
-
-  getURL: ->
-    if @currentIndex is -1
-      ''
-    else
-      @history[@currentIndex]
-
-  stop: ->
-    @pendingIndex = -1
-    @webContents._stop()
-
-  reload: ->
-    @pendingIndex = @currentIndex
-    @webContents._loadURL @getURL(), {}
-
-  reloadIgnoringCache: ->
-    @pendingIndex = @currentIndex
-    @webContents._loadURL @getURL(), {extraHeaders: "pragma: no-cache\n"}
-
-  canGoBack: ->
-    @getActiveIndex() > 0
-
-  canGoForward: ->
-    @getActiveIndex() < @history.length - 1
-
-  canGoToIndex: (index) ->
-    index >=0 and index < @history.length
-
-  canGoToOffset: (offset) ->
-    @canGoToIndex @currentIndex + offset
-
-  clearHistory: ->
-    @history = []
-    @currentIndex = -1
-    @pendingIndex = -1
-    @inPageIndex = -1
-
-  goBack: ->
-    return unless @canGoBack()
-    @pendingIndex = @getActiveIndex() - 1
-    if @inPageIndex > -1 and @pendingIndex >= @inPageIndex
-      @webContents._goBack()
-    else
-      @webContents._loadURL @history[@pendingIndex], {}
-
-  goForward: ->
-    return unless @canGoForward()
-    @pendingIndex = @getActiveIndex() + 1
-    if @inPageIndex > -1 and @pendingIndex >= @inPageIndex
-      @webContents._goForward()
-    else
-      @webContents._loadURL @history[@pendingIndex], {}
-
-  goToIndex: (index) ->
-    return unless @canGoToIndex index
-    @pendingIndex = index
-    @webContents._loadURL @history[@pendingIndex], {}
-
-  goToOffset: (offset) ->
-    return unless @canGoToOffset offset
-    pendingIndex = @currentIndex + offset
-    if @inPageIndex > -1 and pendingIndex >= @inPageIndex
-      @pendingIndex = pendingIndex
-      @webContents._goToOffset offset
-    else
-      @goToIndex pendingIndex
-
-  getActiveIndex: ->
-    if @pendingIndex is -1 then @currentIndex else @pendingIndex
-
-  length: ->
-    @history.length
-
-module.exports = NavigationController

+ 195 - 0
atom/browser/api/lib/navigation-controller.js

@@ -0,0 +1,195 @@
+var NavigationController, ipcMain,
+  slice = [].slice;
+
+ipcMain = require('electron').ipcMain;
+
+
+/* The history operation in renderer is redirected to browser. */
+
+ipcMain.on('ATOM_SHELL_NAVIGATION_CONTROLLER', function() {
+  var args, event, method, ref;
+  event = arguments[0], method = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : [];
+  return (ref = event.sender)[method].apply(ref, args);
+});
+
+ipcMain.on('ATOM_SHELL_SYNC_NAVIGATION_CONTROLLER', function() {
+  var args, event, method, ref;
+  event = arguments[0], method = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : [];
+  return event.returnValue = (ref = event.sender)[method].apply(ref, args);
+});
+
+
+/*
+  JavaScript implementation of Chromium's NavigationController.
+  Instead of relying on Chromium for history control, we compeletely do history
+  control on user land, and only rely on WebContents.loadURL for navigation.
+  This helps us avoid Chromium's various optimizations so we can ensure renderer
+  process is restarted everytime.
+ */
+
+NavigationController = (function() {
+  function NavigationController(webContents) {
+    this.webContents = webContents;
+    this.clearHistory();
+
+    /* webContents may have already navigated to a page. */
+    if (this.webContents._getURL()) {
+      this.currentIndex++;
+      this.history.push(this.webContents._getURL());
+    }
+    this.webContents.on('navigation-entry-commited', (function(_this) {
+      return function(event, url, inPage, replaceEntry) {
+        var currentEntry;
+        if (_this.inPageIndex > -1 && !inPage) {
+
+          /* Navigated to a new page, clear in-page mark. */
+          _this.inPageIndex = -1;
+        } else if (_this.inPageIndex === -1 && inPage) {
+
+          /* Started in-page navigations. */
+          _this.inPageIndex = _this.currentIndex;
+        }
+        if (_this.pendingIndex >= 0) {
+
+          /* Go to index. */
+          _this.currentIndex = _this.pendingIndex;
+          _this.pendingIndex = -1;
+          return _this.history[_this.currentIndex] = url;
+        } else if (replaceEntry) {
+
+          /* Non-user initialized navigation. */
+          return _this.history[_this.currentIndex] = url;
+        } else {
+
+          /* Normal navigation. Clear history. */
+          _this.history = _this.history.slice(0, _this.currentIndex + 1);
+          currentEntry = _this.history[_this.currentIndex];
+          if ((currentEntry != null ? currentEntry.url : void 0) !== url) {
+            _this.currentIndex++;
+            return _this.history.push(url);
+          }
+        }
+      };
+    })(this));
+  }
+
+  NavigationController.prototype.loadURL = function(url, options) {
+    if (options == null) {
+      options = {};
+    }
+    this.pendingIndex = -1;
+    this.webContents._loadURL(url, options);
+    return this.webContents.emit('load-url', url, options);
+  };
+
+  NavigationController.prototype.getURL = function() {
+    if (this.currentIndex === -1) {
+      return '';
+    } else {
+      return this.history[this.currentIndex];
+    }
+  };
+
+  NavigationController.prototype.stop = function() {
+    this.pendingIndex = -1;
+    return this.webContents._stop();
+  };
+
+  NavigationController.prototype.reload = function() {
+    this.pendingIndex = this.currentIndex;
+    return this.webContents._loadURL(this.getURL(), {});
+  };
+
+  NavigationController.prototype.reloadIgnoringCache = function() {
+    this.pendingIndex = this.currentIndex;
+    return this.webContents._loadURL(this.getURL(), {
+      extraHeaders: "pragma: no-cache\n"
+    });
+  };
+
+  NavigationController.prototype.canGoBack = function() {
+    return this.getActiveIndex() > 0;
+  };
+
+  NavigationController.prototype.canGoForward = function() {
+    return this.getActiveIndex() < this.history.length - 1;
+  };
+
+  NavigationController.prototype.canGoToIndex = function(index) {
+    return index >= 0 && index < this.history.length;
+  };
+
+  NavigationController.prototype.canGoToOffset = function(offset) {
+    return this.canGoToIndex(this.currentIndex + offset);
+  };
+
+  NavigationController.prototype.clearHistory = function() {
+    this.history = [];
+    this.currentIndex = -1;
+    this.pendingIndex = -1;
+    return this.inPageIndex = -1;
+  };
+
+  NavigationController.prototype.goBack = function() {
+    if (!this.canGoBack()) {
+      return;
+    }
+    this.pendingIndex = this.getActiveIndex() - 1;
+    if (this.inPageIndex > -1 && this.pendingIndex >= this.inPageIndex) {
+      return this.webContents._goBack();
+    } else {
+      return this.webContents._loadURL(this.history[this.pendingIndex], {});
+    }
+  };
+
+  NavigationController.prototype.goForward = function() {
+    if (!this.canGoForward()) {
+      return;
+    }
+    this.pendingIndex = this.getActiveIndex() + 1;
+    if (this.inPageIndex > -1 && this.pendingIndex >= this.inPageIndex) {
+      return this.webContents._goForward();
+    } else {
+      return this.webContents._loadURL(this.history[this.pendingIndex], {});
+    }
+  };
+
+  NavigationController.prototype.goToIndex = function(index) {
+    if (!this.canGoToIndex(index)) {
+      return;
+    }
+    this.pendingIndex = index;
+    return this.webContents._loadURL(this.history[this.pendingIndex], {});
+  };
+
+  NavigationController.prototype.goToOffset = function(offset) {
+    var pendingIndex;
+    if (!this.canGoToOffset(offset)) {
+      return;
+    }
+    pendingIndex = this.currentIndex + offset;
+    if (this.inPageIndex > -1 && pendingIndex >= this.inPageIndex) {
+      this.pendingIndex = pendingIndex;
+      return this.webContents._goToOffset(offset);
+    } else {
+      return this.goToIndex(pendingIndex);
+    }
+  };
+
+  NavigationController.prototype.getActiveIndex = function() {
+    if (this.pendingIndex === -1) {
+      return this.currentIndex;
+    } else {
+      return this.pendingIndex;
+    }
+  };
+
+  NavigationController.prototype.length = function() {
+    return this.history.length;
+  };
+
+  return NavigationController;
+
+})();
+
+module.exports = NavigationController;

+ 0 - 7
atom/browser/api/lib/power-monitor.coffee

@@ -1,7 +0,0 @@
-{EventEmitter} = require 'events'
-
-{powerMonitor} = process.atomBinding 'power_monitor'
-
-powerMonitor.__proto__ = EventEmitter.prototype
-
-module.exports = powerMonitor

+ 9 - 0
atom/browser/api/lib/power-monitor.js

@@ -0,0 +1,9 @@
+var EventEmitter, powerMonitor;
+
+EventEmitter = require('events').EventEmitter;
+
+powerMonitor = process.atomBinding('power_monitor').powerMonitor;
+
+powerMonitor.__proto__ = EventEmitter.prototype;
+
+module.exports = powerMonitor;

+ 0 - 3
atom/browser/api/lib/power-save-blocker.coffee

@@ -1,3 +0,0 @@
-{powerSaveBlocker} = process.atomBinding 'power_save_blocker'
-
-module.exports = powerSaveBlocker

+ 5 - 0
atom/browser/api/lib/power-save-blocker.js

@@ -0,0 +1,5 @@
+var powerSaveBlocker;
+
+powerSaveBlocker = process.atomBinding('power_save_blocker').powerSaveBlocker;
+
+module.exports = powerSaveBlocker;

+ 0 - 25
atom/browser/api/lib/protocol.coffee

@@ -1,25 +0,0 @@
-{app} = require 'electron'
-
-throw new Error('Can not initialize protocol module before app is ready') unless app.isReady()
-
-{protocol} = process.atomBinding 'protocol'
-
-# Warn about removed APIs.
-logAndThrow = (callback, message) ->
-  console.error message
-  if callback then callback(new Error(message)) else throw new Error(message)
-protocol.registerProtocol = (scheme, handler, callback) ->
-  logAndThrow callback,
-              'registerProtocol API has been replaced by the
-               register[File/Http/Buffer/String]Protocol API family, please
-               switch to the new APIs.'
-protocol.isHandledProtocol = (scheme, callback) ->
-  logAndThrow callback,
-              'isHandledProtocol API has been replaced by isProtocolHandled.'
-protocol.interceptProtocol = (scheme, handler, callback) ->
-  logAndThrow callback,
-              'interceptProtocol API has been replaced by the
-               intercept[File/Http/Buffer/String]Protocol API family, please
-               switch to the new APIs.'
-
-module.exports = protocol

+ 35 - 0
atom/browser/api/lib/protocol.js

@@ -0,0 +1,35 @@
+var app, logAndThrow, protocol;
+
+app = require('electron').app;
+
+if (!app.isReady()) {
+  throw new Error('Can not initialize protocol module before app is ready');
+}
+
+protocol = process.atomBinding('protocol').protocol;
+
+
+/* Warn about removed APIs. */
+
+logAndThrow = function(callback, message) {
+  console.error(message);
+  if (callback) {
+    return callback(new Error(message));
+  } else {
+    throw new Error(message);
+  }
+};
+
+protocol.registerProtocol = function(scheme, handler, callback) {
+  return logAndThrow(callback, 'registerProtocol API has been replaced by the register[File/Http/Buffer/String]Protocol API family, please switch to the new APIs.');
+};
+
+protocol.isHandledProtocol = function(scheme, callback) {
+  return logAndThrow(callback, 'isHandledProtocol API has been replaced by isProtocolHandled.');
+};
+
+protocol.interceptProtocol = function(scheme, handler, callback) {
+  return logAndThrow(callback, 'interceptProtocol API has been replaced by the intercept[File/Http/Buffer/String]Protocol API family, please switch to the new APIs.');
+};
+
+module.exports = protocol;

+ 0 - 6
atom/browser/api/lib/screen.coffee

@@ -1,6 +0,0 @@
-{EventEmitter} = require 'events'
-{screen} = process.atomBinding 'screen'
-
-screen.__proto__ = EventEmitter.prototype
-
-module.exports = screen

+ 9 - 0
atom/browser/api/lib/screen.js

@@ -0,0 +1,9 @@
+var EventEmitter, screen;
+
+EventEmitter = require('events').EventEmitter;
+
+screen = process.atomBinding('screen').screen;
+
+screen.__proto__ = EventEmitter.prototype;
+
+module.exports = screen;

+ 0 - 24
atom/browser/api/lib/session.coffee

@@ -1,24 +0,0 @@
-{EventEmitter} = require 'events'
-
-bindings = process.atomBinding 'session'
-
-PERSIST_PERFIX = 'persist:'
-
-# Returns the Session from |partition| string.
-exports.fromPartition = (partition='') ->
-  return exports.defaultSession if partition is ''
-  if partition.startsWith PERSIST_PERFIX
-    bindings.fromPartition partition.substr(PERSIST_PERFIX.length), false
-  else
-    bindings.fromPartition partition, true
-
-# Returns the default session.
-Object.defineProperty exports, 'defaultSession',
-  enumerable: true
-  get: -> bindings.fromPartition '', false
-
-wrapSession = (session) ->
-  # session is an EventEmitter.
-  session.__proto__ = EventEmitter.prototype
-
-bindings._setWrapSession wrapSession

+ 42 - 0
atom/browser/api/lib/session.js

@@ -0,0 +1,42 @@
+var EventEmitter, PERSIST_PERFIX, bindings, wrapSession;
+
+EventEmitter = require('events').EventEmitter;
+
+bindings = process.atomBinding('session');
+
+PERSIST_PERFIX = 'persist:';
+
+
+/* Returns the Session from |partition| string. */
+
+exports.fromPartition = function(partition) {
+  if (partition == null) {
+    partition = '';
+  }
+  if (partition === '') {
+    return exports.defaultSession;
+  }
+  if (partition.startsWith(PERSIST_PERFIX)) {
+    return bindings.fromPartition(partition.substr(PERSIST_PERFIX.length), false);
+  } else {
+    return bindings.fromPartition(partition, true);
+  }
+};
+
+
+/* Returns the default session. */
+
+Object.defineProperty(exports, 'defaultSession', {
+  enumerable: true,
+  get: function() {
+    return bindings.fromPartition('', false);
+  }
+});
+
+wrapSession = function(session) {
+
+  /* session is an EventEmitter. */
+  return session.__proto__ = EventEmitter.prototype;
+};
+
+bindings._setWrapSession(wrapSession);

+ 0 - 19
atom/browser/api/lib/tray.coffee

@@ -1,19 +0,0 @@
-{deprecate} = require 'electron'
-{EventEmitter} = require 'events'
-
-{Tray} = process.atomBinding 'tray'
-Tray::__proto__ = EventEmitter.prototype
-
-Tray::_init = ->
-  # Deprecated.
-  deprecate.rename this, 'popContextMenu', 'popUpContextMenu'
-  deprecate.event this, 'clicked', 'click'
-  deprecate.event this, 'double-clicked', 'double-click'
-  deprecate.event this, 'right-clicked', 'right-click'
-  deprecate.event this, 'balloon-clicked', 'balloon-click'
-
-Tray::setContextMenu = (menu) ->
-  @_setContextMenu menu
-  @menu = menu  # Keep a strong reference of menu.
-
-module.exports = Tray

+ 28 - 0
atom/browser/api/lib/tray.js

@@ -0,0 +1,28 @@
+var EventEmitter, Tray, deprecate;
+
+deprecate = require('electron').deprecate;
+
+EventEmitter = require('events').EventEmitter;
+
+Tray = process.atomBinding('tray').Tray;
+
+Tray.prototype.__proto__ = EventEmitter.prototype;
+
+Tray.prototype._init = function() {
+
+  /* Deprecated. */
+  deprecate.rename(this, 'popContextMenu', 'popUpContextMenu');
+  deprecate.event(this, 'clicked', 'click');
+  deprecate.event(this, 'double-clicked', 'double-click');
+  deprecate.event(this, 'right-clicked', 'right-click');
+  return deprecate.event(this, 'balloon-clicked', 'balloon-click');
+};
+
+Tray.prototype.setContextMenu = function(menu) {
+  this._setContextMenu(menu);
+
+  /* Keep a strong reference of menu. */
+  return this.menu = menu;
+};
+
+module.exports = Tray;

+ 0 - 137
atom/browser/api/lib/web-contents.coffee

@@ -1,137 +0,0 @@
-{EventEmitter} = require 'events'
-{deprecate, ipcMain, session, NavigationController, Menu} = require 'electron'
-
-binding = process.atomBinding 'web_contents'
-
-nextId = 0
-getNextId = -> ++nextId
-
-PDFPageSize =
-  A5:
-    custom_display_name: "A5"
-    height_microns: 210000
-    name: "ISO_A5"
-    width_microns: 148000
-  A4:
-    custom_display_name: "A4"
-    height_microns: 297000
-    name: "ISO_A4"
-    is_default: "true"
-    width_microns: 210000
-  A3:
-    custom_display_name: "A3"
-    height_microns: 420000
-    name: "ISO_A3"
-    width_microns: 297000
-  Legal:
-    custom_display_name: "Legal"
-    height_microns: 355600
-    name: "NA_LEGAL"
-    width_microns: 215900
-  Letter:
-    custom_display_name: "Letter"
-    height_microns: 279400
-    name: "NA_LETTER"
-    width_microns: 215900
-  Tabloid:
-    height_microns: 431800
-    name: "NA_LEDGER"
-    width_microns: 279400
-    custom_display_name: "Tabloid"
-
-wrapWebContents = (webContents) ->
-  # webContents is an EventEmitter.
-  webContents.__proto__ = EventEmitter.prototype
-
-  # WebContents::send(channel, args..)
-  webContents.send = (channel, args...) ->
-    @_send channel, [args...]
-
-  # Make sure webContents.executeJavaScript would run the code only when the
-  # web contents has been loaded.
-  webContents.executeJavaScript = (code, hasUserGesture=false) ->
-    if @getURL() and not @isLoading()
-      @_executeJavaScript code, hasUserGesture
-    else
-      webContents.once 'did-finish-load', @_executeJavaScript.bind(this, code, hasUserGesture)
-
-  # The navigation controller.
-  controller = new NavigationController(webContents)
-  for name, method of NavigationController.prototype when method instanceof Function
-    do (name, method) ->
-      webContents[name] = -> method.apply controller, arguments
-
-  # Dispatch IPC messages to the ipc module.
-  webContents.on 'ipc-message', (event, packed) ->
-    [channel, args...] = packed
-    ipcMain.emit channel, event, args...
-  webContents.on 'ipc-message-sync', (event, packed) ->
-    [channel, args...] = packed
-    Object.defineProperty event, 'returnValue', set: (value) -> event.sendReply JSON.stringify(value)
-    ipcMain.emit channel, event, args...
-
-  # Handle context menu action request from pepper plugin.
-  webContents.on 'pepper-context-menu', (event, params) ->
-    menu = Menu.buildFromTemplate params.menu
-    menu.popup params.x, params.y
-
-  # This error occurs when host could not be found.
-  webContents.on 'did-fail-provisional-load', (args...) ->
-    # Calling loadURL during this event might cause crash, so delay the event
-    # until next tick.
-    setImmediate => @emit 'did-fail-load', args...
-
-  # Delays the page-title-updated event to next tick.
-  webContents.on '-page-title-updated', (args...) ->
-    setImmediate => @emit 'page-title-updated', args...
-
-  # Deprecated.
-  deprecate.rename webContents, 'loadUrl', 'loadURL'
-  deprecate.rename webContents, 'getUrl', 'getURL'
-  deprecate.event webContents, 'page-title-set', 'page-title-updated', (args...) ->
-    @emit 'page-title-set', args...
-
-  webContents.printToPDF = (options, callback) ->
-    printingSetting =
-      pageRage: []
-      mediaSize: {}
-      landscape: false
-      color: 2
-      headerFooterEnabled: false
-      marginsType: 0
-      isFirstRequest: false
-      requestID: getNextId()
-      previewModifiable: true
-      printToPDF: true
-      printWithCloudPrint: false
-      printWithPrivet: false
-      printWithExtension: false
-      deviceName: "Save as PDF"
-      generateDraftData: true
-      fitToPageEnabled: false
-      duplex: 0
-      copies: 1
-      collate: true
-      shouldPrintBackgrounds: false
-      shouldPrintSelectionOnly: false
-
-    if options.landscape
-      printingSetting.landscape = options.landscape
-    if options.marginsType
-      printingSetting.marginsType = options.marginsType
-    if options.printSelectionOnly
-      printingSetting.shouldPrintSelectionOnly = options.printSelectionOnly
-    if options.printBackground
-      printingSetting.shouldPrintBackgrounds = options.printBackground
-
-    if options.pageSize and PDFPageSize[options.pageSize]
-      printingSetting.mediaSize = PDFPageSize[options.pageSize]
-    else
-      printingSetting.mediaSize = PDFPageSize['A4']
-
-    @_printToPDF printingSetting, callback
-
-binding._setWrapWebContents wrapWebContents
-
-module.exports.create = (options={}) ->
-  binding.create(options)

+ 210 - 0
atom/browser/api/lib/web-contents.js

@@ -0,0 +1,210 @@
+var EventEmitter, Menu, NavigationController, PDFPageSize, binding, deprecate, getNextId, ipcMain, nextId, ref, session, wrapWebContents,
+  slice = [].slice;
+
+EventEmitter = require('events').EventEmitter;
+
+ref = require('electron'), deprecate = ref.deprecate, ipcMain = ref.ipcMain, session = ref.session, NavigationController = ref.NavigationController, Menu = ref.Menu;
+
+binding = process.atomBinding('web_contents');
+
+nextId = 0;
+
+getNextId = function() {
+  return ++nextId;
+};
+
+PDFPageSize = {
+  A5: {
+    custom_display_name: "A5",
+    height_microns: 210000,
+    name: "ISO_A5",
+    width_microns: 148000
+  },
+  A4: {
+    custom_display_name: "A4",
+    height_microns: 297000,
+    name: "ISO_A4",
+    is_default: "true",
+    width_microns: 210000
+  },
+  A3: {
+    custom_display_name: "A3",
+    height_microns: 420000,
+    name: "ISO_A3",
+    width_microns: 297000
+  },
+  Legal: {
+    custom_display_name: "Legal",
+    height_microns: 355600,
+    name: "NA_LEGAL",
+    width_microns: 215900
+  },
+  Letter: {
+    custom_display_name: "Letter",
+    height_microns: 279400,
+    name: "NA_LETTER",
+    width_microns: 215900
+  },
+  Tabloid: {
+    height_microns: 431800,
+    name: "NA_LEDGER",
+    width_microns: 279400,
+    custom_display_name: "Tabloid"
+  }
+};
+
+wrapWebContents = function(webContents) {
+
+  /* webContents is an EventEmitter. */
+  var controller, method, name, ref1;
+  webContents.__proto__ = EventEmitter.prototype;
+
+  /* WebContents::send(channel, args..) */
+  webContents.send = function() {
+    var args, channel;
+    channel = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+    return this._send(channel, slice.call(args));
+  };
+
+  /*
+    Make sure webContents.executeJavaScript would run the code only when the
+    web contents has been loaded.
+   */
+  webContents.executeJavaScript = function(code, hasUserGesture) {
+    if (hasUserGesture == null) {
+      hasUserGesture = false;
+    }
+    if (this.getURL() && !this.isLoading()) {
+      return this._executeJavaScript(code, hasUserGesture);
+    } else {
+      return webContents.once('did-finish-load', this._executeJavaScript.bind(this, code, hasUserGesture));
+    }
+  };
+
+  /* The navigation controller. */
+  controller = new NavigationController(webContents);
+  ref1 = NavigationController.prototype;
+  for (name in ref1) {
+    method = ref1[name];
+    if (method instanceof Function) {
+      (function(name, method) {
+        return webContents[name] = function() {
+          return method.apply(controller, arguments);
+        };
+      })(name, method);
+    }
+  }
+
+  /* Dispatch IPC messages to the ipc module. */
+  webContents.on('ipc-message', function(event, packed) {
+    var args, channel;
+    channel = packed[0], args = 2 <= packed.length ? slice.call(packed, 1) : [];
+    return ipcMain.emit.apply(ipcMain, [channel, event].concat(slice.call(args)));
+  });
+  webContents.on('ipc-message-sync', function(event, packed) {
+    var args, channel;
+    channel = packed[0], args = 2 <= packed.length ? slice.call(packed, 1) : [];
+    Object.defineProperty(event, 'returnValue', {
+      set: function(value) {
+        return event.sendReply(JSON.stringify(value));
+      }
+    });
+    return ipcMain.emit.apply(ipcMain, [channel, event].concat(slice.call(args)));
+  });
+
+  /* Handle context menu action request from pepper plugin. */
+  webContents.on('pepper-context-menu', function(event, params) {
+    var menu;
+    menu = Menu.buildFromTemplate(params.menu);
+    return menu.popup(params.x, params.y);
+  });
+
+  /* This error occurs when host could not be found. */
+  webContents.on('did-fail-provisional-load', function() {
+    var args;
+    args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+
+    /*
+      Calling loadURL during this event might cause crash, so delay the event
+      until next tick.
+     */
+    return setImmediate((function(_this) {
+      return function() {
+        return _this.emit.apply(_this, ['did-fail-load'].concat(slice.call(args)));
+      };
+    })(this));
+  });
+
+  /* Delays the page-title-updated event to next tick. */
+  webContents.on('-page-title-updated', function() {
+    var args;
+    args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+    return setImmediate((function(_this) {
+      return function() {
+        return _this.emit.apply(_this, ['page-title-updated'].concat(slice.call(args)));
+      };
+    })(this));
+  });
+
+  /* Deprecated. */
+  deprecate.rename(webContents, 'loadUrl', 'loadURL');
+  deprecate.rename(webContents, 'getUrl', 'getURL');
+  deprecate.event(webContents, 'page-title-set', 'page-title-updated', function() {
+    var args;
+    args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+    return this.emit.apply(this, ['page-title-set'].concat(slice.call(args)));
+  });
+  return webContents.printToPDF = function(options, callback) {
+    var printingSetting;
+    printingSetting = {
+      pageRage: [],
+      mediaSize: {},
+      landscape: false,
+      color: 2,
+      headerFooterEnabled: false,
+      marginsType: 0,
+      isFirstRequest: false,
+      requestID: getNextId(),
+      previewModifiable: true,
+      printToPDF: true,
+      printWithCloudPrint: false,
+      printWithPrivet: false,
+      printWithExtension: false,
+      deviceName: "Save as PDF",
+      generateDraftData: true,
+      fitToPageEnabled: false,
+      duplex: 0,
+      copies: 1,
+      collate: true,
+      shouldPrintBackgrounds: false,
+      shouldPrintSelectionOnly: false
+    };
+    if (options.landscape) {
+      printingSetting.landscape = options.landscape;
+    }
+    if (options.marginsType) {
+      printingSetting.marginsType = options.marginsType;
+    }
+    if (options.printSelectionOnly) {
+      printingSetting.shouldPrintSelectionOnly = options.printSelectionOnly;
+    }
+    if (options.printBackground) {
+      printingSetting.shouldPrintBackgrounds = options.printBackground;
+    }
+    if (options.pageSize && PDFPageSize[options.pageSize]) {
+      printingSetting.mediaSize = PDFPageSize[options.pageSize];
+    } else {
+      printingSetting.mediaSize = PDFPageSize['A4'];
+    }
+    return this._printToPDF(printingSetting, callback);
+  };
+};
+
+binding._setWrapWebContents(wrapWebContents);
+
+module.exports.create = function(options) {
+  if (options == null) {
+    options = {};
+  }
+  return binding.create(options);
+};

+ 0 - 96
atom/browser/lib/chrome-extension.coffee

@@ -1,96 +0,0 @@
-electron = require 'electron'
-fs   = require 'fs'
-path = require 'path'
-url  = require 'url'
-
-# Mapping between hostname and file path.
-hostPathMap = {}
-hostPathMapNextKey = 0
-
-getHostForPath = (path) ->
-  key = "extension-#{++hostPathMapNextKey}"
-  hostPathMap[key] = path
-  key
-
-getPathForHost = (host) ->
-  hostPathMap[host]
-
-# Cache extensionInfo.
-extensionInfoMap = {}
-
-getExtensionInfoFromPath = (srcDirectory) ->
-  manifest = JSON.parse fs.readFileSync(path.join(srcDirectory, 'manifest.json'))
-  unless extensionInfoMap[manifest.name]?
-    # We can not use 'file://' directly because all resources in the extension
-    # will be treated as relative to the root in Chrome.
-    page = url.format
-      protocol: 'chrome-extension'
-      slashes: true
-      hostname: getHostForPath srcDirectory
-      pathname: manifest.devtools_page
-    extensionInfoMap[manifest.name] =
-      startPage: page
-      name: manifest.name
-      srcDirectory: srcDirectory
-      exposeExperimentalAPIs: true
-    extensionInfoMap[manifest.name]
-
-# The loaded extensions cache and its persistent path.
-loadedExtensions = null
-loadedExtensionsPath = null
-
-# Persistent loaded extensions.
-{app} = electron
-app.on 'will-quit', ->
-  try
-    loadedExtensions = Object.keys(extensionInfoMap).map (key) -> extensionInfoMap[key].srcDirectory
-    try
-      fs.mkdirSync path.dirname(loadedExtensionsPath)
-    catch e
-    fs.writeFileSync loadedExtensionsPath, JSON.stringify(loadedExtensions)
-  catch e
-
-# We can not use protocol or BrowserWindow until app is ready.
-app.once 'ready', ->
-  {protocol, BrowserWindow} = electron
-
-  # Load persistented extensions.
-  loadedExtensionsPath = path.join app.getPath('userData'), 'DevTools Extensions'
-
-  try
-    loadedExtensions = JSON.parse fs.readFileSync(loadedExtensionsPath)
-    loadedExtensions = [] unless Array.isArray loadedExtensions
-    # Preheat the extensionInfo cache.
-    getExtensionInfoFromPath srcDirectory for srcDirectory in loadedExtensions
-  catch e
-
-  # The chrome-extension: can map a extension URL request to real file path.
-  chromeExtensionHandler = (request, callback) ->
-    parsed = url.parse request.url
-    return callback() unless parsed.hostname and parsed.path?
-    return callback() unless /extension-\d+/.test parsed.hostname
-
-    directory = getPathForHost parsed.hostname
-    return callback() unless directory?
-    callback path.join(directory, parsed.path)
-  protocol.registerFileProtocol 'chrome-extension', chromeExtensionHandler, (error) ->
-    console.error 'Unable to register chrome-extension protocol' if error
-
-  BrowserWindow::_loadDevToolsExtensions = (extensionInfoArray) ->
-    @devToolsWebContents?.executeJavaScript "DevToolsAPI.addExtensions(#{JSON.stringify(extensionInfoArray)});"
-
-  BrowserWindow.addDevToolsExtension = (srcDirectory) ->
-    extensionInfo = getExtensionInfoFromPath srcDirectory
-    if extensionInfo
-      window._loadDevToolsExtensions [extensionInfo] for window in BrowserWindow.getAllWindows()
-      extensionInfo.name
-
-  BrowserWindow.removeDevToolsExtension = (name) ->
-    delete extensionInfoMap[name]
-
-  # Load persistented extensions when devtools is opened.
-  init = BrowserWindow::_init
-  BrowserWindow::_init = ->
-    init.call this
-    @on 'devtools-opened', ->
-      @_loadDevToolsExtensions Object.keys(extensionInfoMap).map (key) -> extensionInfoMap[key]

+ 163 - 0
atom/browser/lib/chrome-extension.js

@@ -0,0 +1,163 @@
+var app, electron, extensionInfoMap, fs, getExtensionInfoFromPath, getHostForPath, getPathForHost, hostPathMap, hostPathMapNextKey, loadedExtensions, loadedExtensionsPath, path, url;
+
+electron = require('electron');
+
+fs = require('fs');
+
+path = require('path');
+
+url = require('url');
+
+
+/* Mapping between hostname and file path. */
+
+hostPathMap = {};
+
+hostPathMapNextKey = 0;
+
+getHostForPath = function(path) {
+  var key;
+  key = "extension-" + (++hostPathMapNextKey);
+  hostPathMap[key] = path;
+  return key;
+};
+
+getPathForHost = function(host) {
+  return hostPathMap[host];
+};
+
+
+/* Cache extensionInfo. */
+
+extensionInfoMap = {};
+
+getExtensionInfoFromPath = function(srcDirectory) {
+  var manifest, page;
+  manifest = JSON.parse(fs.readFileSync(path.join(srcDirectory, 'manifest.json')));
+  if (extensionInfoMap[manifest.name] == null) {
+
+    /*
+      We can not use 'file://' directly because all resources in the extension
+      will be treated as relative to the root in Chrome.
+     */
+    page = url.format({
+      protocol: 'chrome-extension',
+      slashes: true,
+      hostname: getHostForPath(srcDirectory),
+      pathname: manifest.devtools_page
+    });
+    extensionInfoMap[manifest.name] = {
+      startPage: page,
+      name: manifest.name,
+      srcDirectory: srcDirectory,
+      exposeExperimentalAPIs: true
+    };
+    return extensionInfoMap[manifest.name];
+  }
+};
+
+
+/* The loaded extensions cache and its persistent path. */
+
+loadedExtensions = null;
+
+loadedExtensionsPath = null;
+
+
+/* Persistent loaded extensions. */
+
+app = electron.app;
+
+app.on('will-quit', function() {
+  var e, error1, error2;
+  try {
+    loadedExtensions = Object.keys(extensionInfoMap).map(function(key) {
+      return extensionInfoMap[key].srcDirectory;
+    });
+    try {
+      fs.mkdirSync(path.dirname(loadedExtensionsPath));
+    } catch (error1) {
+      e = error1;
+    }
+    return fs.writeFileSync(loadedExtensionsPath, JSON.stringify(loadedExtensions));
+  } catch (error2) {
+    e = error2;
+  }
+});
+
+
+/* We can not use protocol or BrowserWindow until app is ready. */
+
+app.once('ready', function() {
+  var BrowserWindow, chromeExtensionHandler, e, error1, i, init, len, protocol, srcDirectory;
+  protocol = electron.protocol, BrowserWindow = electron.BrowserWindow;
+
+  /* Load persistented extensions. */
+  loadedExtensionsPath = path.join(app.getPath('userData'), 'DevTools Extensions');
+  try {
+    loadedExtensions = JSON.parse(fs.readFileSync(loadedExtensionsPath));
+    if (!Array.isArray(loadedExtensions)) {
+      loadedExtensions = [];
+    }
+
+    /* Preheat the extensionInfo cache. */
+    for (i = 0, len = loadedExtensions.length; i < len; i++) {
+      srcDirectory = loadedExtensions[i];
+      getExtensionInfoFromPath(srcDirectory);
+    }
+  } catch (error1) {
+    e = error1;
+  }
+
+  /* The chrome-extension: can map a extension URL request to real file path. */
+  chromeExtensionHandler = function(request, callback) {
+    var directory, parsed;
+    parsed = url.parse(request.url);
+    if (!(parsed.hostname && (parsed.path != null))) {
+      return callback();
+    }
+    if (!/extension-\d+/.test(parsed.hostname)) {
+      return callback();
+    }
+    directory = getPathForHost(parsed.hostname);
+    if (directory == null) {
+      return callback();
+    }
+    return callback(path.join(directory, parsed.path));
+  };
+  protocol.registerFileProtocol('chrome-extension', chromeExtensionHandler, function(error) {
+    if (error) {
+      return console.error('Unable to register chrome-extension protocol');
+    }
+  });
+  BrowserWindow.prototype._loadDevToolsExtensions = function(extensionInfoArray) {
+    var ref;
+    return (ref = this.devToolsWebContents) != null ? ref.executeJavaScript("DevToolsAPI.addExtensions(" + (JSON.stringify(extensionInfoArray)) + ");") : void 0;
+  };
+  BrowserWindow.addDevToolsExtension = function(srcDirectory) {
+    var extensionInfo, j, len1, ref, window;
+    extensionInfo = getExtensionInfoFromPath(srcDirectory);
+    if (extensionInfo) {
+      ref = BrowserWindow.getAllWindows();
+      for (j = 0, len1 = ref.length; j < len1; j++) {
+        window = ref[j];
+        window._loadDevToolsExtensions([extensionInfo]);
+      }
+      return extensionInfo.name;
+    }
+  };
+  BrowserWindow.removeDevToolsExtension = function(name) {
+    return delete extensionInfoMap[name];
+  };
+
+  /* Load persistented extensions when devtools is opened. */
+  init = BrowserWindow.prototype._init;
+  return BrowserWindow.prototype._init = function() {
+    init.call(this);
+    return this.on('devtools-opened', function() {
+      return this._loadDevToolsExtensions(Object.keys(extensionInfoMap).map(function(key) {
+        return extensionInfoMap[key];
+      }));
+    });
+  };
+});

+ 0 - 37
atom/browser/lib/desktop-capturer.coffee

@@ -1,37 +0,0 @@
-{ipcMain} = require 'electron'
-{desktopCapturer} = process.atomBinding 'desktop_capturer'
-
-deepEqual = (opt1, opt2) ->
-  return JSON.stringify(opt1) is JSON.stringify(opt2)
-
-# A queue for holding all requests from renderer process.
-requestsQueue = []
-
-ipcMain.on 'ATOM_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', (event, captureWindow, captureScreen, thumbnailSize, id) ->
-  request = id: id, options: {captureWindow, captureScreen, thumbnailSize}, webContents: event.sender
-  requestsQueue.push request
-  desktopCapturer.startHandling captureWindow, captureScreen, thumbnailSize if requestsQueue.length is 1
-  # If the WebContents is destroyed before receiving result, just remove the
-  # reference from requestsQueue to make the module not send the result to it.
-  event.sender.once 'destroyed', ->
-    request.webContents = null
-
-desktopCapturer.emit = (event, name, sources) ->
-  # Receiving sources result from main process, now send them back to renderer.
-  handledRequest = requestsQueue.shift 0
-  result = ({ id: source.id, name: source.name, thumbnail: source.thumbnail.toDataUrl() } for source in sources)
-  handledRequest.webContents?.send "ATOM_RENDERER_DESKTOP_CAPTURER_RESULT_#{handledRequest.id}", result
-
-  # Check the queue to see whether there is other same request. If has, handle
-  # it for reducing redunplicated `desktopCaptuer.startHandling` calls.
-  unhandledRequestsQueue = []
-  for request in requestsQueue
-    if deepEqual handledRequest.options, request.options
-      request.webContents?.send "ATOM_RENDERER_DESKTOP_CAPTURER_RESULT_#{request.id}", errorMessage, result
-    else
-      unhandledRequestsQueue.push request
-  requestsQueue = unhandledRequestsQueue
-  # If the requestsQueue is not empty, start a new request handling.
-  if requestsQueue.length > 0
-    {captureWindow, captureScreen, thumbnailSize} = requestsQueue[0].options
-    desktopCapturer.startHandling captureWindow, captureScreen, thumbnailSize

+ 85 - 0
atom/browser/lib/desktop-capturer.js

@@ -0,0 +1,85 @@
+var deepEqual, desktopCapturer, ipcMain, requestsQueue;
+
+ipcMain = require('electron').ipcMain;
+
+desktopCapturer = process.atomBinding('desktop_capturer').desktopCapturer;
+
+deepEqual = function(opt1, opt2) {
+  return JSON.stringify(opt1) === JSON.stringify(opt2);
+};
+
+
+/* A queue for holding all requests from renderer process. */
+
+requestsQueue = [];
+
+ipcMain.on('ATOM_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', function(event, captureWindow, captureScreen, thumbnailSize, id) {
+  var request;
+  request = {
+    id: id,
+    options: {
+      captureWindow: captureWindow,
+      captureScreen: captureScreen,
+      thumbnailSize: thumbnailSize
+    },
+    webContents: event.sender
+  };
+  requestsQueue.push(request);
+  if (requestsQueue.length === 1) {
+    desktopCapturer.startHandling(captureWindow, captureScreen, thumbnailSize);
+  }
+
+  /*
+    If the WebContents is destroyed before receiving result, just remove the
+    reference from requestsQueue to make the module not send the result to it.
+   */
+  return event.sender.once('destroyed', function() {
+    return request.webContents = null;
+  });
+});
+
+desktopCapturer.emit = function(event, name, sources) {
+
+  /* Receiving sources result from main process, now send them back to renderer. */
+  var captureScreen, captureWindow, handledRequest, i, len, ref, ref1, ref2, request, result, source, thumbnailSize, unhandledRequestsQueue;
+  handledRequest = requestsQueue.shift(0);
+  result = (function() {
+    var i, len, results;
+    results = [];
+    for (i = 0, len = sources.length; i < len; i++) {
+      source = sources[i];
+      results.push({
+        id: source.id,
+        name: source.name,
+        thumbnail: source.thumbnail.toDataUrl()
+      });
+    }
+    return results;
+  })();
+  if ((ref = handledRequest.webContents) != null) {
+    ref.send("ATOM_RENDERER_DESKTOP_CAPTURER_RESULT_" + handledRequest.id, result);
+  }
+
+  /*
+    Check the queue to see whether there is other same request. If has, handle
+    it for reducing redunplicated `desktopCaptuer.startHandling` calls.
+   */
+  unhandledRequestsQueue = [];
+  for (i = 0, len = requestsQueue.length; i < len; i++) {
+    request = requestsQueue[i];
+    if (deepEqual(handledRequest.options, request.options)) {
+      if ((ref1 = request.webContents) != null) {
+        ref1.send("ATOM_RENDERER_DESKTOP_CAPTURER_RESULT_" + request.id, errorMessage, result);
+      }
+    } else {
+      unhandledRequestsQueue.push(request);
+    }
+  }
+  requestsQueue = unhandledRequestsQueue;
+
+  /* If the requestsQueue is not empty, start a new request handling. */
+  if (requestsQueue.length > 0) {
+    ref2 = requestsQueue[0].options, captureWindow = ref2.captureWindow, captureScreen = ref2.captureScreen, thumbnailSize = ref2.thumbnailSize;
+    return desktopCapturer.startHandling(captureWindow, captureScreen, thumbnailSize);
+  }
+};

+ 0 - 174
atom/browser/lib/guest-view-manager.coffee

@@ -1,174 +0,0 @@
-{ipcMain, webContents} = require 'electron'
-
-webViewManager = null  # Doesn't exist in early initialization.
-
-supportedWebViewEvents = [
-  'load-commit'
-  'did-finish-load'
-  'did-fail-load'
-  'did-frame-finish-load'
-  'did-start-loading'
-  'did-stop-loading'
-  'did-get-response-details'
-  'did-get-redirect-request'
-  'dom-ready'
-  'console-message'
-  'devtools-opened'
-  'devtools-closed'
-  'devtools-focused'
-  'new-window'
-  'will-navigate'
-  'did-navigate'
-  'did-navigate-in-page'
-  'close'
-  'crashed'
-  'gpu-crashed'
-  'plugin-crashed'
-  'destroyed'
-  'page-title-updated'
-  'page-favicon-updated'
-  'enter-html-full-screen'
-  'leave-html-full-screen'
-  'media-started-playing'
-  'media-paused'
-  'found-in-page'
-  'did-change-theme-color'
-]
-
-nextInstanceId = 0
-guestInstances = {}
-embedderElementsMap = {}
-reverseEmbedderElementsMap = {}
-
-# Moves the last element of array to the first one.
-moveLastToFirst = (list) ->
-  list.unshift list.pop()
-
-# Generate guestInstanceId.
-getNextInstanceId = (webContents) ->
-  ++nextInstanceId
-
-# Create a new guest instance.
-createGuest = (embedder, params) ->
-  webViewManager ?= process.atomBinding 'web_view_manager'
-
-  id = getNextInstanceId embedder
-  guest = webContents.create {isGuest: true, partition: params.partition, embedder}
-  guestInstances[id] = {guest, embedder}
-
-  # Destroy guest when the embedder is gone or navigated.
-  destroyEvents = ['destroyed', 'crashed', 'did-navigate']
-  destroy = ->
-    destroyGuest embedder, id if guestInstances[id]?
-  for event in destroyEvents
-    embedder.once event, destroy
-    # Users might also listen to the crashed event, so We must ensure the guest
-    # is destroyed before users' listener gets called. It is done by moving our
-    # listener to the first one in queue.
-    listeners = embedder._events[event]
-    moveLastToFirst listeners if Array.isArray listeners
-  guest.once 'destroyed', ->
-    embedder.removeListener event, destroy for event in destroyEvents
-
-  # Init guest web view after attached.
-  guest.once 'did-attach', ->
-    params = @attachParams
-    delete @attachParams
-
-    @viewInstanceId = params.instanceId
-    @setSize
-      normal:
-        width: params.elementWidth, height: params.elementHeight
-      enableAutoSize: params.autosize
-      min:
-        width: params.minwidth, height: params.minheight
-      max:
-        width: params.maxwidth, height: params.maxheight
-
-    if params.src
-      opts = {}
-      opts.httpReferrer = params.httpreferrer if params.httpreferrer
-      opts.userAgent = params.useragent if params.useragent
-      @loadURL params.src, opts
-
-    if params.allowtransparency?
-      @setAllowTransparency params.allowtransparency
-
-    guest.allowPopups = params.allowpopups
-
-  # Dispatch events to embedder.
-  for event in supportedWebViewEvents
-    do (event) ->
-      guest.on event, (_, args...) ->
-        embedder.send "ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-#{guest.viewInstanceId}", event, args...
-
-  # Dispatch guest's IPC messages to embedder.
-  guest.on 'ipc-message-host', (_, packed) ->
-    [channel, args...] = packed
-    embedder.send "ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-#{guest.viewInstanceId}", channel, args...
-
-  # Autosize.
-  guest.on 'size-changed', (_, args...) ->
-    embedder.send "ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-#{guest.viewInstanceId}", args...
-
-  id
-
-# Attach the guest to an element of embedder.
-attachGuest = (embedder, elementInstanceId, guestInstanceId, params) ->
-  guest = guestInstances[guestInstanceId].guest
-
-  # Destroy the old guest when attaching.
-  key = "#{embedder.getId()}-#{elementInstanceId}"
-  oldGuestInstanceId = embedderElementsMap[key]
-  if oldGuestInstanceId?
-    # Reattachment to the same guest is not currently supported.
-    return unless oldGuestInstanceId != guestInstanceId
-
-    return unless guestInstances[oldGuestInstanceId]?
-    destroyGuest embedder, oldGuestInstanceId
-
-  webPreferences =
-    guestInstanceId: guestInstanceId
-    nodeIntegration: params.nodeintegration ? false
-    plugins: params.plugins
-    webSecurity: !params.disablewebsecurity
-  webPreferences.preloadURL = params.preload if params.preload
-  webViewManager.addGuest guestInstanceId, elementInstanceId, embedder, guest, webPreferences
-
-  guest.attachParams = params
-  embedderElementsMap[key] = guestInstanceId
-  reverseEmbedderElementsMap[guestInstanceId] = key
-
-# Destroy an existing guest instance.
-destroyGuest = (embedder, id) ->
-  webViewManager.removeGuest embedder, id
-  guestInstances[id].guest.destroy()
-  delete guestInstances[id]
-
-  key = reverseEmbedderElementsMap[id]
-  if key?
-    delete reverseEmbedderElementsMap[id]
-    delete embedderElementsMap[key]
-
-ipcMain.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', (event, params, requestId) ->
-  event.sender.send "ATOM_SHELL_RESPONSE_#{requestId}", createGuest(event.sender, params)
-
-ipcMain.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', (event, elementInstanceId, guestInstanceId, params) ->
-  attachGuest event.sender, elementInstanceId, guestInstanceId, params
-
-ipcMain.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', (event, id) ->
-  destroyGuest event.sender, id
-
-ipcMain.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', (event, id, params) ->
-  guestInstances[id]?.guest.setSize params
-
-ipcMain.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_ALLOW_TRANSPARENCY', (event, id, allowtransparency) ->
-  guestInstances[id]?.guest.setAllowTransparency allowtransparency
-
-# Returns WebContents from its guest id.
-exports.getGuest = (id) ->
-  guestInstances[id]?.guest
-
-# Returns the embedder of the guest.
-exports.getEmbedder = (id) ->
-  guestInstances[id]?.embedder

+ 238 - 0
atom/browser/lib/guest-view-manager.js

@@ -0,0 +1,238 @@
+var attachGuest, createGuest, destroyGuest, embedderElementsMap, getNextInstanceId, guestInstances, ipcMain, moveLastToFirst, nextInstanceId, ref, reverseEmbedderElementsMap, supportedWebViewEvents, webContents, webViewManager,
+  slice = [].slice;
+
+ref = require('electron'), ipcMain = ref.ipcMain, webContents = ref.webContents;
+
+
+/* Doesn't exist in early initialization. */
+
+webViewManager = null;
+
+supportedWebViewEvents = ['load-commit', 'did-finish-load', 'did-fail-load', 'did-frame-finish-load', 'did-start-loading', 'did-stop-loading', 'did-get-response-details', 'did-get-redirect-request', 'dom-ready', 'console-message', 'devtools-opened', 'devtools-closed', 'devtools-focused', 'new-window', 'will-navigate', 'did-navigate', 'did-navigate-in-page', 'close', 'crashed', 'gpu-crashed', 'plugin-crashed', 'destroyed', 'page-title-updated', 'page-favicon-updated', 'enter-html-full-screen', 'leave-html-full-screen', 'media-started-playing', 'media-paused', 'found-in-page', 'did-change-theme-color'];
+
+nextInstanceId = 0;
+
+guestInstances = {};
+
+embedderElementsMap = {};
+
+reverseEmbedderElementsMap = {};
+
+
+/* Moves the last element of array to the first one. */
+
+moveLastToFirst = function(list) {
+  return list.unshift(list.pop());
+};
+
+
+/* Generate guestInstanceId. */
+
+getNextInstanceId = function(webContents) {
+  return ++nextInstanceId;
+};
+
+
+/* Create a new guest instance. */
+
+createGuest = function(embedder, params) {
+  var destroy, destroyEvents, event, fn, guest, i, id, j, len, len1, listeners;
+  if (webViewManager == null) {
+    webViewManager = process.atomBinding('web_view_manager');
+  }
+  id = getNextInstanceId(embedder);
+  guest = webContents.create({
+    isGuest: true,
+    partition: params.partition,
+    embedder: embedder
+  });
+  guestInstances[id] = {
+    guest: guest,
+    embedder: embedder
+  };
+
+  /* Destroy guest when the embedder is gone or navigated. */
+  destroyEvents = ['destroyed', 'crashed', 'did-navigate'];
+  destroy = function() {
+    if (guestInstances[id] != null) {
+      return destroyGuest(embedder, id);
+    }
+  };
+  for (i = 0, len = destroyEvents.length; i < len; i++) {
+    event = destroyEvents[i];
+    embedder.once(event, destroy);
+
+    /*
+      Users might also listen to the crashed event, so We must ensure the guest
+      is destroyed before users' listener gets called. It is done by moving our
+      listener to the first one in queue.
+     */
+    listeners = embedder._events[event];
+    if (Array.isArray(listeners)) {
+      moveLastToFirst(listeners);
+    }
+  }
+  guest.once('destroyed', function() {
+    var j, len1, results;
+    results = [];
+    for (j = 0, len1 = destroyEvents.length; j < len1; j++) {
+      event = destroyEvents[j];
+      results.push(embedder.removeListener(event, destroy));
+    }
+    return results;
+  });
+
+  /* Init guest web view after attached. */
+  guest.once('did-attach', function() {
+    var opts;
+    params = this.attachParams;
+    delete this.attachParams;
+    this.viewInstanceId = params.instanceId;
+    this.setSize({
+      normal: {
+        width: params.elementWidth,
+        height: params.elementHeight
+      },
+      enableAutoSize: params.autosize,
+      min: {
+        width: params.minwidth,
+        height: params.minheight
+      },
+      max: {
+        width: params.maxwidth,
+        height: params.maxheight
+      }
+    });
+    if (params.src) {
+      opts = {};
+      if (params.httpreferrer) {
+        opts.httpReferrer = params.httpreferrer;
+      }
+      if (params.useragent) {
+        opts.userAgent = params.useragent;
+      }
+      this.loadURL(params.src, opts);
+    }
+    if (params.allowtransparency != null) {
+      this.setAllowTransparency(params.allowtransparency);
+    }
+    return guest.allowPopups = params.allowpopups;
+  });
+
+  /* Dispatch events to embedder. */
+  fn = function(event) {
+    return guest.on(event, function() {
+      var _, args;
+      _ = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+      return embedder.send.apply(embedder, ["ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-" + guest.viewInstanceId, event].concat(slice.call(args)));
+    });
+  };
+  for (j = 0, len1 = supportedWebViewEvents.length; j < len1; j++) {
+    event = supportedWebViewEvents[j];
+    fn(event);
+  }
+
+  /* Dispatch guest's IPC messages to embedder. */
+  guest.on('ipc-message-host', function(_, packed) {
+    var args, channel;
+    channel = packed[0], args = 2 <= packed.length ? slice.call(packed, 1) : [];
+    return embedder.send.apply(embedder, ["ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-" + guest.viewInstanceId, channel].concat(slice.call(args)));
+  });
+
+  /* Autosize. */
+  guest.on('size-changed', function() {
+    var _, args;
+    _ = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+    return embedder.send.apply(embedder, ["ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-" + guest.viewInstanceId].concat(slice.call(args)));
+  });
+  return id;
+};
+
+
+/* Attach the guest to an element of embedder. */
+
+attachGuest = function(embedder, elementInstanceId, guestInstanceId, params) {
+  var guest, key, oldGuestInstanceId, ref1, webPreferences;
+  guest = guestInstances[guestInstanceId].guest;
+
+  /* Destroy the old guest when attaching. */
+  key = (embedder.getId()) + "-" + elementInstanceId;
+  oldGuestInstanceId = embedderElementsMap[key];
+  if (oldGuestInstanceId != null) {
+
+    /* Reattachment to the same guest is not currently supported. */
+    if (oldGuestInstanceId === guestInstanceId) {
+      return;
+    }
+    if (guestInstances[oldGuestInstanceId] == null) {
+      return;
+    }
+    destroyGuest(embedder, oldGuestInstanceId);
+  }
+  webPreferences = {
+    guestInstanceId: guestInstanceId,
+    nodeIntegration: (ref1 = params.nodeintegration) != null ? ref1 : false,
+    plugins: params.plugins,
+    webSecurity: !params.disablewebsecurity
+  };
+  if (params.preload) {
+    webPreferences.preloadURL = params.preload;
+  }
+  webViewManager.addGuest(guestInstanceId, elementInstanceId, embedder, guest, webPreferences);
+  guest.attachParams = params;
+  embedderElementsMap[key] = guestInstanceId;
+  return reverseEmbedderElementsMap[guestInstanceId] = key;
+};
+
+
+/* Destroy an existing guest instance. */
+
+destroyGuest = function(embedder, id) {
+  var key;
+  webViewManager.removeGuest(embedder, id);
+  guestInstances[id].guest.destroy();
+  delete guestInstances[id];
+  key = reverseEmbedderElementsMap[id];
+  if (key != null) {
+    delete reverseEmbedderElementsMap[id];
+    return delete embedderElementsMap[key];
+  }
+};
+
+ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', function(event, params, requestId) {
+  return event.sender.send("ATOM_SHELL_RESPONSE_" + requestId, createGuest(event.sender, params));
+});
+
+ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', function(event, elementInstanceId, guestInstanceId, params) {
+  return attachGuest(event.sender, elementInstanceId, guestInstanceId, params);
+});
+
+ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', function(event, id) {
+  return destroyGuest(event.sender, id);
+});
+
+ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', function(event, id, params) {
+  var ref1;
+  return (ref1 = guestInstances[id]) != null ? ref1.guest.setSize(params) : void 0;
+});
+
+ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_SET_ALLOW_TRANSPARENCY', function(event, id, allowtransparency) {
+  var ref1;
+  return (ref1 = guestInstances[id]) != null ? ref1.guest.setAllowTransparency(allowtransparency) : void 0;
+});
+
+
+/* Returns WebContents from its guest id. */
+
+exports.getGuest = function(id) {
+  var ref1;
+  return (ref1 = guestInstances[id]) != null ? ref1.guest : void 0;
+};
+
+
+/* Returns the embedder of the guest. */
+
+exports.getEmbedder = function(id) {
+  var ref1;
+  return (ref1 = guestInstances[id]) != null ? ref1.embedder : void 0;
+};

+ 0 - 86
atom/browser/lib/guest-window-manager.coffee

@@ -1,86 +0,0 @@
-{ipcMain, BrowserWindow} = require 'electron'
-v8Util = process.atomBinding 'v8_util'
-
-frameToGuest = {}
-
-# Copy attribute of |parent| to |child| if it is not defined in |child|.
-mergeOptions = (child, parent) ->
-  for own key, value of parent when key not of child
-    if typeof value is 'object'
-      child[key] = mergeOptions {}, value
-    else
-      child[key] = value
-  child
-
-# Merge |options| with the |embedder|'s window's options.
-mergeBrowserWindowOptions = (embedder, options) ->
-  if embedder.browserWindowOptions?
-    # Inherit the original options if it is a BrowserWindow.
-    mergeOptions options, embedder.browserWindowOptions
-  else
-    # Or only inherit web-preferences if it is a webview.
-    options.webPreferences ?= {}
-    mergeOptions options.webPreferences, embedder.getWebPreferences()
-  options
-
-# Create a new guest created by |embedder| with |options|.
-createGuest = (embedder, url, frameName, options) ->
-  guest = frameToGuest[frameName]
-  if frameName and guest?
-    guest.loadURL url
-    return guest.id
-
-  # Remember the embedder window's id.
-  options.webPreferences ?= {}
-  options.webPreferences.openerId = BrowserWindow.fromWebContents(embedder)?.id
-
-  guest = new BrowserWindow(options)
-  guest.loadURL url
-
-  # When |embedder| is destroyed we should also destroy attached guest, and if
-  # guest is closed by user then we should prevent |embedder| from double
-  # closing guest.
-  guestId = guest.id
-  closedByEmbedder = ->
-    guest.removeListener 'closed', closedByUser
-    guest.destroy()
-  closedByUser = ->
-    embedder.send "ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_#{guestId}"
-    embedder.removeListener 'render-view-deleted', closedByEmbedder
-  embedder.once 'render-view-deleted', closedByEmbedder
-  guest.once 'closed', closedByUser
-
-  if frameName
-    frameToGuest[frameName] = guest
-    guest.frameName = frameName
-    guest.once 'closed', ->
-      delete frameToGuest[frameName]
-
-  guest.id
-
-# Routed window.open messages.
-ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', (event, args...) ->
-  [url, frameName, options] = args
-  options = mergeBrowserWindowOptions event.sender, options
-  event.sender.emit 'new-window', event, url, frameName, 'new-window', options
-  if (event.sender.isGuest() and not event.sender.allowPopups) or event.defaultPrevented
-    event.returnValue = null
-  else
-    event.returnValue = createGuest event.sender, url, frameName, options
-
-ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', (event, guestId) ->
-  BrowserWindow.fromId(guestId)?.destroy()
-
-ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', (event, guestId, method, args...) ->
-  BrowserWindow.fromId(guestId)?[method] args...
-
-ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (event, guestId, message, targetOrigin, sourceOrigin) ->
-  sourceId = BrowserWindow.fromWebContents(event.sender)?.id
-  return unless sourceId?
-
-  guestContents = BrowserWindow.fromId(guestId)?.webContents
-  if guestContents?.getURL().indexOf(targetOrigin) is 0 or targetOrigin is '*'
-    guestContents?.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', sourceId, message, sourceOrigin
-
-ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', (event, guestId, method, args...) ->
-  BrowserWindow.fromId(guestId)?.webContents?[method] args...

+ 137 - 0
atom/browser/lib/guest-window-manager.js

@@ -0,0 +1,137 @@
+var BrowserWindow, createGuest, frameToGuest, ipcMain, mergeBrowserWindowOptions, mergeOptions, ref, v8Util,
+  hasProp = {}.hasOwnProperty,
+  slice = [].slice;
+
+ref = require('electron'), ipcMain = ref.ipcMain, BrowserWindow = ref.BrowserWindow;
+
+v8Util = process.atomBinding('v8_util');
+
+frameToGuest = {};
+
+
+/* Copy attribute of |parent| to |child| if it is not defined in |child|. */
+
+mergeOptions = function(child, parent) {
+  var key, value;
+  for (key in parent) {
+    if (!hasProp.call(parent, key)) continue;
+    value = parent[key];
+    if (!(key in child)) {
+      if (typeof value === 'object') {
+        child[key] = mergeOptions({}, value);
+      } else {
+        child[key] = value;
+      }
+    }
+  }
+  return child;
+};
+
+
+/* Merge |options| with the |embedder|'s window's options. */
+
+mergeBrowserWindowOptions = function(embedder, options) {
+  if (embedder.browserWindowOptions != null) {
+
+    /* Inherit the original options if it is a BrowserWindow. */
+    mergeOptions(options, embedder.browserWindowOptions);
+  } else {
+
+    /* Or only inherit web-preferences if it is a webview. */
+    if (options.webPreferences == null) {
+      options.webPreferences = {};
+    }
+    mergeOptions(options.webPreferences, embedder.getWebPreferences());
+  }
+  return options;
+};
+
+
+/* Create a new guest created by |embedder| with |options|. */
+
+createGuest = function(embedder, url, frameName, options) {
+  var closedByEmbedder, closedByUser, guest, guestId, ref1;
+  guest = frameToGuest[frameName];
+  if (frameName && (guest != null)) {
+    guest.loadURL(url);
+    return guest.id;
+  }
+
+  /* Remember the embedder window's id. */
+  if (options.webPreferences == null) {
+    options.webPreferences = {};
+  }
+  options.webPreferences.openerId = (ref1 = BrowserWindow.fromWebContents(embedder)) != null ? ref1.id : void 0;
+  guest = new BrowserWindow(options);
+  guest.loadURL(url);
+
+  /*
+    When |embedder| is destroyed we should also destroy attached guest, and if
+    guest is closed by user then we should prevent |embedder| from double
+    closing guest.
+   */
+  guestId = guest.id;
+  closedByEmbedder = function() {
+    guest.removeListener('closed', closedByUser);
+    return guest.destroy();
+  };
+  closedByUser = function() {
+    embedder.send("ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_" + guestId);
+    return embedder.removeListener('render-view-deleted', closedByEmbedder);
+  };
+  embedder.once('render-view-deleted', closedByEmbedder);
+  guest.once('closed', closedByUser);
+  if (frameName) {
+    frameToGuest[frameName] = guest;
+    guest.frameName = frameName;
+    guest.once('closed', function() {
+      return delete frameToGuest[frameName];
+    });
+  }
+  return guest.id;
+};
+
+
+/* Routed window.open messages. */
+
+ipcMain.on('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', function() {
+  var args, event, frameName, options, url;
+  event = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+  url = args[0], frameName = args[1], options = args[2];
+  options = mergeBrowserWindowOptions(event.sender, options);
+  event.sender.emit('new-window', event, url, frameName, 'new-window', options);
+  if ((event.sender.isGuest() && !event.sender.allowPopups) || event.defaultPrevented) {
+    return event.returnValue = null;
+  } else {
+    return event.returnValue = createGuest(event.sender, url, frameName, options);
+  }
+});
+
+ipcMain.on('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', function(event, guestId) {
+  var ref1;
+  return (ref1 = BrowserWindow.fromId(guestId)) != null ? ref1.destroy() : void 0;
+});
+
+ipcMain.on('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', function() {
+  var args, event, guestId, method, ref1;
+  event = arguments[0], guestId = arguments[1], method = arguments[2], args = 4 <= arguments.length ? slice.call(arguments, 3) : [];
+  return (ref1 = BrowserWindow.fromId(guestId)) != null ? ref1[method].apply(ref1, args) : void 0;
+});
+
+ipcMain.on('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', function(event, guestId, message, targetOrigin, sourceOrigin) {
+  var guestContents, ref1, ref2, sourceId;
+  sourceId = (ref1 = BrowserWindow.fromWebContents(event.sender)) != null ? ref1.id : void 0;
+  if (sourceId == null) {
+    return;
+  }
+  guestContents = (ref2 = BrowserWindow.fromId(guestId)) != null ? ref2.webContents : void 0;
+  if ((guestContents != null ? guestContents.getURL().indexOf(targetOrigin) : void 0) === 0 || targetOrigin === '*') {
+    return guestContents != null ? guestContents.send('ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', sourceId, message, sourceOrigin) : void 0;
+  }
+});
+
+ipcMain.on('ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', function() {
+  var args, event, guestId, method, ref1, ref2;
+  event = arguments[0], guestId = arguments[1], method = arguments[2], args = 4 <= arguments.length ? slice.call(arguments, 3) : [];
+  return (ref1 = BrowserWindow.fromId(guestId)) != null ? (ref2 = ref1.webContents) != null ? ref2[method].apply(ref2, args) : void 0 : void 0;
+});

+ 0 - 118
atom/browser/lib/init.coffee

@@ -1,118 +0,0 @@
-fs     = require 'fs'
-path   = require 'path'
-util   = require 'util'
-Module = require 'module'
-
-# We modified the original process.argv to let node.js load the atom.js,
-# we need to restore it here.
-process.argv.splice 1, 1
-
-# Clear search paths.
-require path.resolve(__dirname, '..', '..', 'common', 'lib', 'reset-search-paths')
-
-# Import common settings.
-require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init')
-
-globalPaths = Module.globalPaths
-unless process.env.ELECTRON_HIDE_INTERNAL_MODULES
-  globalPaths.push path.resolve(__dirname, '..', 'api', 'lib')
-
-# Expose public APIs.
-globalPaths.push path.resolve(__dirname, '..', 'api', 'lib', 'exports')
-
-if process.platform is 'win32'
-  # Redirect node's console to use our own implementations, since node can not
-  # handle console output when running as GUI program.
-  consoleLog = (args...) ->
-    process.log util.format(args...) + "\n"
-  streamWrite = (chunk, encoding, callback) ->
-    chunk = chunk.toString(encoding) if Buffer.isBuffer chunk
-    process.log chunk
-    callback() if callback
-    true
-  console.log = console.error = console.warn = consoleLog
-  process.stdout.write = process.stderr.write = streamWrite
-
-  # Always returns EOF for stdin stream.
-  Readable = require('stream').Readable
-  stdin = new Readable
-  stdin.push null
-  process.__defineGetter__ 'stdin', -> stdin
-
-# Don't quit on fatal error.
-process.on 'uncaughtException', (error) ->
-  # Do nothing if the user has a custom uncaught exception handler.
-  if process.listeners('uncaughtException').length > 1
-    return
-
-  # Show error in GUI.
-  {dialog} = require 'electron'
-  stack = error.stack ? "#{error.name}: #{error.message}"
-  message = "Uncaught Exception:\n#{stack}"
-  dialog.showErrorBox 'A JavaScript error occurred in the main process', message
-
-# Emit 'exit' event on quit.
-{app} = require 'electron'
-app.on 'quit', (event, exitCode) ->
-  process.emit 'exit', exitCode
-
-# Map process.exit to app.exit, which quits gracefully.
-process.exit = app.exit
-
-# Load the RPC server.
-require './rpc-server'
-
-# Load the guest view manager.
-require './guest-view-manager'
-require './guest-window-manager'
-
-# Now we try to load app's package.json.
-packageJson = null
-
-searchPaths = [ 'app', 'app.asar', 'default_app' ]
-for packagePath in searchPaths
-  try
-    packagePath = path.join process.resourcesPath, packagePath
-    packageJson = JSON.parse(fs.readFileSync(path.join(packagePath, 'package.json')))
-    break
-  catch e
-    continue
-
-unless packageJson?
-  process.nextTick -> process.exit 1
-  throw new Error("Unable to find a valid app")
-
-# Set application's version.
-app.setVersion packageJson.version if packageJson.version?
-
-# Set application's name.
-if packageJson.productName?
-  app.setName packageJson.productName
-else if packageJson.name?
-  app.setName packageJson.name
-
-# Set application's desktop name.
-if packageJson.desktopName?
-  app.setDesktopName packageJson.desktopName
-else
-  app.setDesktopName "#{app.getName()}.desktop"
-
-# Chrome 42 disables NPAPI plugins by default, reenable them here
-app.commandLine.appendSwitch 'enable-npapi'
-
-# Set the user path according to application's name.
-app.setPath 'userData', path.join(app.getPath('appData'), app.getName())
-app.setPath 'userCache', path.join(app.getPath('cache'), app.getName())
-app.setAppPath packagePath
-
-# Load the chrome extension support.
-require './chrome-extension'
-
-# Load internal desktop-capturer module.
-require './desktop-capturer'
-
-# Set main startup script of the app.
-mainStartupScript = packageJson.main or 'index.js'
-
-# Finally load app's main.js and transfer control to C++.
-Module._load path.join(packagePath, mainStartupScript), Module, true

+ 201 - 0
atom/browser/lib/init.js

@@ -0,0 +1,201 @@
+var Module, Readable, app, consoleLog, e, error1, fs, globalPaths, i, len, mainStartupScript, packageJson, packagePath, path, searchPaths, stdin, streamWrite, util,
+  slice = [].slice;
+
+fs = require('fs');
+
+path = require('path');
+
+util = require('util');
+
+Module = require('module');
+
+
+/* We modified the original process.argv to let node.js load the atom.js, */
+
+
+/* we need to restore it here. */
+
+process.argv.splice(1, 1);
+
+
+/* Clear search paths. */
+
+require(path.resolve(__dirname, '..', '..', 'common', 'lib', 'reset-search-paths'));
+
+
+/* Import common settings. */
+
+require(path.resolve(__dirname, '..', '..', 'common', 'lib', 'init'));
+
+globalPaths = Module.globalPaths;
+
+if (!process.env.ELECTRON_HIDE_INTERNAL_MODULES) {
+  globalPaths.push(path.resolve(__dirname, '..', 'api', 'lib'));
+}
+
+
+/* Expose public APIs. */
+
+globalPaths.push(path.resolve(__dirname, '..', 'api', 'lib', 'exports'));
+
+if (process.platform === 'win32') {
+
+  /*
+    Redirect node's console to use our own implementations, since node can not
+    handle console output when running as GUI program.
+   */
+  consoleLog = function() {
+    var args;
+    args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+    return process.log(util.format.apply(util, args) + "\n");
+  };
+  streamWrite = function(chunk, encoding, callback) {
+    if (Buffer.isBuffer(chunk)) {
+      chunk = chunk.toString(encoding);
+    }
+    process.log(chunk);
+    if (callback) {
+      callback();
+    }
+    return true;
+  };
+  console.log = console.error = console.warn = consoleLog;
+  process.stdout.write = process.stderr.write = streamWrite;
+
+  /* Always returns EOF for stdin stream. */
+  Readable = require('stream').Readable;
+  stdin = new Readable;
+  stdin.push(null);
+  process.__defineGetter__('stdin', function() {
+    return stdin;
+  });
+}
+
+
+/* Don't quit on fatal error. */
+
+process.on('uncaughtException', function(error) {
+
+  /* Do nothing if the user has a custom uncaught exception handler. */
+  var dialog, message, ref, stack;
+  if (process.listeners('uncaughtException').length > 1) {
+    return;
+  }
+
+  /* Show error in GUI. */
+  dialog = require('electron').dialog;
+  stack = (ref = error.stack) != null ? ref : error.name + ": " + error.message;
+  message = "Uncaught Exception:\n" + stack;
+  return dialog.showErrorBox('A JavaScript error occurred in the main process', message);
+});
+
+
+/* Emit 'exit' event on quit. */
+
+app = require('electron').app;
+
+app.on('quit', function(event, exitCode) {
+  return process.emit('exit', exitCode);
+});
+
+
+/* Map process.exit to app.exit, which quits gracefully. */
+
+process.exit = app.exit;
+
+
+/* Load the RPC server. */
+
+require('./rpc-server');
+
+
+/* Load the guest view manager. */
+
+require('./guest-view-manager');
+
+require('./guest-window-manager');
+
+
+/* Now we try to load app's package.json. */
+
+packageJson = null;
+
+searchPaths = ['app', 'app.asar', 'default_app'];
+
+for (i = 0, len = searchPaths.length; i < len; i++) {
+  packagePath = searchPaths[i];
+  try {
+    packagePath = path.join(process.resourcesPath, packagePath);
+    packageJson = JSON.parse(fs.readFileSync(path.join(packagePath, 'package.json')));
+    break;
+  } catch (error1) {
+    e = error1;
+    continue;
+  }
+}
+
+if (packageJson == null) {
+  process.nextTick(function() {
+    return process.exit(1);
+  });
+  throw new Error("Unable to find a valid app");
+}
+
+
+/* Set application's version. */
+
+if (packageJson.version != null) {
+  app.setVersion(packageJson.version);
+}
+
+
+/* Set application's name. */
+
+if (packageJson.productName != null) {
+  app.setName(packageJson.productName);
+} else if (packageJson.name != null) {
+  app.setName(packageJson.name);
+}
+
+
+/* Set application's desktop name. */
+
+if (packageJson.desktopName != null) {
+  app.setDesktopName(packageJson.desktopName);
+} else {
+  app.setDesktopName((app.getName()) + ".desktop");
+}
+
+
+/* Chrome 42 disables NPAPI plugins by default, reenable them here */
+
+app.commandLine.appendSwitch('enable-npapi');
+
+
+/* Set the user path according to application's name. */
+
+app.setPath('userData', path.join(app.getPath('appData'), app.getName()));
+
+app.setPath('userCache', path.join(app.getPath('cache'), app.getName()));
+
+app.setAppPath(packagePath);
+
+
+/* Load the chrome extension support. */
+
+require('./chrome-extension');
+
+
+/* Load internal desktop-capturer module. */
+
+require('./desktop-capturer');
+
+
+/* Set main startup script of the app. */
+
+mainStartupScript = packageJson.main || 'index.js';
+
+
+/* Finally load app's main.js and transfer control to C++. */
+
+Module._load(path.join(packagePath, mainStartupScript), Module, true);

+ 0 - 67
atom/browser/lib/objects-registry.coffee

@@ -1,67 +0,0 @@
-{EventEmitter} = require 'events'
-v8Util = process.atomBinding 'v8_util'
-
-class ObjectsRegistry extends EventEmitter
-  constructor: ->
-    @setMaxListeners Number.MAX_VALUE
-    @nextId = 0
-
-    # Stores all objects by ref-counting.
-    # (id) => {object, count}
-    @storage = {}
-
-    # Stores the IDs of objects referenced by WebContents.
-    # (webContentsId) => {(id) => (count)}
-    @owners = {}
-
-  # Register a new object, the object would be kept referenced until you release
-  # it explicitly.
-  add: (webContentsId, obj) ->
-    id = @saveToStorage obj
-    # Remember the owner.
-    @owners[webContentsId] ?= {}
-    @owners[webContentsId][id] ?= 0
-    @owners[webContentsId][id]++
-    # Returns object's id
-    id
-
-  # Get an object according to its ID.
-  get: (id) ->
-    @storage[id]?.object
-
-  # Dereference an object according to its ID.
-  remove: (webContentsId, id) ->
-    @dereference id, 1
-    # Also reduce the count in owner.
-    pointer = @owners[webContentsId]
-    return unless pointer?
-    --pointer[id]
-    delete pointer[id] if pointer[id] is 0
-
-  # Clear all references to objects refrenced by the WebContents.
-  clear: (webContentsId) ->
-    @emit "clear-#{webContentsId}"
-    return unless @owners[webContentsId]?
-    @dereference id, count for id, count of @owners[webContentsId]
-    delete @owners[webContentsId]
-
-  # Private: Saves the object into storage and assigns an ID for it.
-  saveToStorage: (object) ->
-    id = v8Util.getHiddenValue object, 'atomId'
-    unless id
-      id = ++@nextId
-      @storage[id] = {count: 0, object}
-      v8Util.setHiddenValue object, 'atomId', id
-    ++@storage[id].count
-    id
-
-  # Private: Dereference the object from store.
-  dereference: (id, count) ->
-    pointer = @storage[id]
-    return unless pointer?
-    pointer.count -= count
-    if pointer.count is 0
-      v8Util.deleteHiddenValue pointer.object, 'atomId'
-      delete @storage[id]
-
-module.exports = new ObjectsRegistry

+ 133 - 0
atom/browser/lib/objects-registry.js

@@ -0,0 +1,133 @@
+var EventEmitter, ObjectsRegistry, v8Util,
+  extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+  hasProp = {}.hasOwnProperty;
+
+EventEmitter = require('events').EventEmitter;
+
+v8Util = process.atomBinding('v8_util');
+
+ObjectsRegistry = (function(superClass) {
+  extend(ObjectsRegistry, superClass);
+
+  function ObjectsRegistry() {
+    this.setMaxListeners(Number.MAX_VALUE);
+    this.nextId = 0;
+
+    /*
+      Stores all objects by ref-counting.
+      (id) => {object, count}
+     */
+    this.storage = {};
+
+    /*
+      Stores the IDs of objects referenced by WebContents.
+      (webContentsId) => {(id) => (count)}
+     */
+    this.owners = {};
+  }
+
+
+  /*
+    Register a new object, the object would be kept referenced until you release
+    it explicitly.
+   */
+
+  ObjectsRegistry.prototype.add = function(webContentsId, obj) {
+    var base, base1, id;
+    id = this.saveToStorage(obj);
+
+    /* Remember the owner. */
+    if ((base = this.owners)[webContentsId] == null) {
+      base[webContentsId] = {};
+    }
+    if ((base1 = this.owners[webContentsId])[id] == null) {
+      base1[id] = 0;
+    }
+    this.owners[webContentsId][id]++;
+
+    /* Returns object's id */
+    return id;
+  };
+
+
+  /* Get an object according to its ID. */
+
+  ObjectsRegistry.prototype.get = function(id) {
+    var ref;
+    return (ref = this.storage[id]) != null ? ref.object : void 0;
+  };
+
+
+  /* Dereference an object according to its ID. */
+
+  ObjectsRegistry.prototype.remove = function(webContentsId, id) {
+    var pointer;
+    this.dereference(id, 1);
+
+    /* Also reduce the count in owner. */
+    pointer = this.owners[webContentsId];
+    if (pointer == null) {
+      return;
+    }
+    --pointer[id];
+    if (pointer[id] === 0) {
+      return delete pointer[id];
+    }
+  };
+
+
+  /* Clear all references to objects refrenced by the WebContents. */
+
+  ObjectsRegistry.prototype.clear = function(webContentsId) {
+    var count, id, ref;
+    this.emit("clear-" + webContentsId);
+    if (this.owners[webContentsId] == null) {
+      return;
+    }
+    ref = this.owners[webContentsId];
+    for (id in ref) {
+      count = ref[id];
+      this.dereference(id, count);
+    }
+    return delete this.owners[webContentsId];
+  };
+
+
+  /* Private: Saves the object into storage and assigns an ID for it. */
+
+  ObjectsRegistry.prototype.saveToStorage = function(object) {
+    var id;
+    id = v8Util.getHiddenValue(object, 'atomId');
+    if (!id) {
+      id = ++this.nextId;
+      this.storage[id] = {
+        count: 0,
+        object: object
+      };
+      v8Util.setHiddenValue(object, 'atomId', id);
+    }
+    ++this.storage[id].count;
+    return id;
+  };
+
+
+  /* Private: Dereference the object from store. */
+
+  ObjectsRegistry.prototype.dereference = function(id, count) {
+    var pointer;
+    pointer = this.storage[id];
+    if (pointer == null) {
+      return;
+    }
+    pointer.count -= count;
+    if (pointer.count === 0) {
+      v8Util.deleteHiddenValue(pointer.object, 'atomId');
+      return delete this.storage[id];
+    }
+  };
+
+  return ObjectsRegistry;
+
+})(EventEmitter);
+
+module.exports = new ObjectsRegistry;

+ 0 - 231
atom/browser/lib/rpc-server.coffee

@@ -1,231 +0,0 @@
-path = require 'path'
-
-electron = require 'electron'
-{ipcMain} = electron
-objectsRegistry = require './objects-registry'
-
-v8Util = process.atomBinding 'v8_util'
-{IDWeakMap} = process.atomBinding 'id_weak_map'
-
-# Convert a real value into meta data.
-valueToMeta = (sender, value, optimizeSimpleObject=false) ->
-  meta = type: typeof value
-
-  meta.type = 'buffer' if Buffer.isBuffer value
-  meta.type = 'value' if value is null
-  meta.type = 'array' if Array.isArray value
-  meta.type = 'error' if value instanceof Error
-  meta.type = 'date' if value instanceof Date
-  meta.type = 'promise' if value?.constructor.name is 'Promise'
-
-  # Treat simple objects as value.
-  if optimizeSimpleObject and meta.type is 'object' and v8Util.getHiddenValue value, 'simple'
-    meta.type = 'value'
-
-  # Treat the arguments object as array.
-  meta.type = 'array' if meta.type is 'object' and value.callee? and value.length?
-
-  if meta.type is 'array'
-    meta.members = []
-    meta.members.push valueToMeta(sender, el) for el in value
-  else if meta.type is 'object' or meta.type is 'function'
-    meta.name = value.constructor.name
-
-    # Reference the original value if it's an object, because when it's
-    # passed to renderer we would assume the renderer keeps a reference of
-    # it.
-    meta.id = objectsRegistry.add sender.getId(), value
-
-    meta.members = ({name, type: typeof field} for name, field of value)
-  else if meta.type is 'buffer'
-    meta.value = Array::slice.call value, 0
-  else if meta.type is 'promise'
-    meta.then = valueToMeta sender, value.then.bind(value)
-  else if meta.type is 'error'
-    meta.members = plainObjectToMeta value
-    # Error.name is not part of own properties.
-    meta.members.push {name: 'name', value: value.name}
-  else if meta.type is 'date'
-    meta.value = value.getTime()
-  else
-    meta.type = 'value'
-    meta.value = value
-
-  meta
-
-# Convert object to meta by value.
-plainObjectToMeta = (obj) ->
-  Object.getOwnPropertyNames(obj).map (name) -> {name, value: obj[name]}
-
-# Convert Error into meta data.
-exceptionToMeta = (error) ->
-  type: 'exception', message: error.message, stack: (error.stack || error)
-
-# Convert array of meta data from renderer into array of real values.
-unwrapArgs = (sender, args) ->
-  metaToValue = (meta) ->
-    switch meta.type
-      when 'value' then meta.value
-      when 'remote-object' then objectsRegistry.get meta.id
-      when 'array' then unwrapArgs sender, meta.value
-      when 'buffer' then new Buffer(meta.value)
-      when 'date' then new Date(meta.value)
-      when 'promise' then Promise.resolve(then: metaToValue(meta.then))
-      when 'object'
-        ret = v8Util.createObjectWithName meta.name
-        for member in meta.members
-          ret[member.name] = metaToValue(member.value)
-        ret
-      when 'function-with-return-value'
-        returnValue = metaToValue meta.value
-        -> returnValue
-      when 'function'
-        # Cache the callbacks in renderer.
-        unless sender.callbacks
-          sender.callbacks = new IDWeakMap
-          sender.on 'render-view-deleted', ->
-            sender.callbacks.clear()
-        return sender.callbacks.get meta.id if sender.callbacks.has meta.id
-
-        rendererReleased = false
-        objectsRegistry.once "clear-#{sender.getId()}", ->
-          rendererReleased = true
-
-        ret = ->
-          if rendererReleased
-            throw new Error("Attempting to call a function in a renderer window
-              that has been closed or released. Function provided here: #{meta.location}.")
-          sender.send 'ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, arguments)
-        v8Util.setDestructor ret, ->
-          return if rendererReleased
-          sender.callbacks.remove meta.id
-          sender.send 'ATOM_RENDERER_RELEASE_CALLBACK', meta.id
-        sender.callbacks.set meta.id, ret
-        ret
-      else throw new TypeError("Unknown type: #{meta.type}")
-
-  args.map metaToValue
-
-# Call a function and send reply asynchronously if it's a an asynchronous
-# style function and the caller didn't pass a callback.
-callFunction = (event, func, caller, args) ->
-  funcMarkedAsync = v8Util.getHiddenValue(func, 'asynchronous')
-  funcPassedCallback = typeof args[args.length - 1] is 'function'
-
-  try
-    if funcMarkedAsync and not funcPassedCallback
-      args.push (ret) ->
-        event.returnValue = valueToMeta event.sender, ret, true
-      func.apply caller, args
-    else
-      ret = func.apply caller, args
-      event.returnValue = valueToMeta event.sender, ret, true
-  catch e
-    # Catch functions thrown further down in function invocation and wrap
-    # them with the function name so it's easier to trace things like
-    # `Error processing argument -1.`
-    funcName = func.name ? "anonymous"
-    throw new Error("Could not call remote function `#{funcName}`.
-                     Check that the function signature is correct.
-                     Underlying error: #{e.message}")
-
-# Send by BrowserWindow when its render view is deleted.
-process.on 'ATOM_BROWSER_RELEASE_RENDER_VIEW', (id) ->
-  objectsRegistry.clear id
-
-ipcMain.on 'ATOM_BROWSER_REQUIRE', (event, module) ->
-  try
-    event.returnValue = valueToMeta event.sender, process.mainModule.require(module)
-  catch e
-    event.returnValue = exceptionToMeta e
-
-ipcMain.on 'ATOM_BROWSER_GET_BUILTIN', (event, module) ->
-  try
-    event.returnValue = valueToMeta event.sender, electron[module]
-  catch e
-    event.returnValue = exceptionToMeta e
-
-ipcMain.on 'ATOM_BROWSER_GLOBAL', (event, name) ->
-  try
-    event.returnValue = valueToMeta event.sender, global[name]
-  catch e
-    event.returnValue = exceptionToMeta e
-
-ipcMain.on 'ATOM_BROWSER_CURRENT_WINDOW', (event) ->
-  try
-    event.returnValue = valueToMeta event.sender, event.sender.getOwnerBrowserWindow()
-  catch e
-    event.returnValue = exceptionToMeta e
-
-ipcMain.on 'ATOM_BROWSER_CURRENT_WEB_CONTENTS', (event) ->
-  event.returnValue = valueToMeta event.sender, event.sender
-
-ipcMain.on 'ATOM_BROWSER_CONSTRUCTOR', (event, id, args) ->
-  try
-    args = unwrapArgs event.sender, args
-    constructor = objectsRegistry.get id
-    # Call new with array of arguments.
-    # http://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible
-    obj = new (Function::bind.apply(constructor, [null].concat(args)))
-    event.returnValue = valueToMeta event.sender, obj
-  catch e
-    event.returnValue = exceptionToMeta e
-
-ipcMain.on 'ATOM_BROWSER_FUNCTION_CALL', (event, id, args) ->
-  try
-    args = unwrapArgs event.sender, args
-    func = objectsRegistry.get id
-    callFunction event, func, global, args
-  catch e
-    event.returnValue = exceptionToMeta e
-
-ipcMain.on 'ATOM_BROWSER_MEMBER_CONSTRUCTOR', (event, id, method, args) ->
-  try
-    args = unwrapArgs event.sender, args
-    constructor = objectsRegistry.get(id)[method]
-    # Call new with array of arguments.
-    obj = new (Function::bind.apply(constructor, [null].concat(args)))
-    event.returnValue = valueToMeta event.sender, obj
-  catch e
-    event.returnValue = exceptionToMeta e
-
-ipcMain.on 'ATOM_BROWSER_MEMBER_CALL', (event, id, method, args) ->
-  try
-    args = unwrapArgs event.sender, args
-    obj = objectsRegistry.get id
-    callFunction event, obj[method], obj, args
-  catch e
-    event.returnValue = exceptionToMeta e
-
-ipcMain.on 'ATOM_BROWSER_MEMBER_SET', (event, id, name, value) ->
-  try
-    obj = objectsRegistry.get id
-    obj[name] = value
-    event.returnValue = null
-  catch e
-    event.returnValue = exceptionToMeta e
-
-ipcMain.on 'ATOM_BROWSER_MEMBER_GET', (event, id, name) ->
-  try
-    obj = objectsRegistry.get id
-    event.returnValue = valueToMeta event.sender, obj[name]
-  catch e
-    event.returnValue = exceptionToMeta e
-
-ipcMain.on 'ATOM_BROWSER_DEREFERENCE', (event, id) ->
-  objectsRegistry.remove event.sender.getId(), id
-
-ipcMain.on 'ATOM_BROWSER_GUEST_WEB_CONTENTS', (event, guestInstanceId) ->
-  try
-    guestViewManager = require './guest-view-manager'
-    event.returnValue = valueToMeta event.sender, guestViewManager.getGuest(guestInstanceId)
-  catch e
-    event.returnValue = exceptionToMeta e
-
-ipcMain.on 'ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', (event, guestInstanceId, method, args...) ->
-  try
-    guestViewManager = require './guest-view-manager'
-    guest = guestViewManager.getGuest(guestInstanceId)
-    guest[method].apply(guest, args)
-  catch e
-    event.returnValue = exceptionToMeta e

+ 389 - 0
atom/browser/lib/rpc-server.js

@@ -0,0 +1,389 @@
+var IDWeakMap, callFunction, electron, exceptionToMeta, ipcMain, objectsRegistry, path, plainObjectToMeta, unwrapArgs, v8Util, valueToMeta,
+  slice = [].slice;
+
+path = require('path');
+
+electron = require('electron');
+
+ipcMain = electron.ipcMain;
+
+objectsRegistry = require('./objects-registry');
+
+v8Util = process.atomBinding('v8_util');
+
+IDWeakMap = process.atomBinding('id_weak_map').IDWeakMap;
+
+
+/* Convert a real value into meta data. */
+
+valueToMeta = function(sender, value, optimizeSimpleObject) {
+  var el, field, i, len, meta, name;
+  if (optimizeSimpleObject == null) {
+    optimizeSimpleObject = false;
+  }
+  meta = {
+    type: typeof value
+  };
+  if (Buffer.isBuffer(value)) {
+    meta.type = 'buffer';
+  }
+  if (value === null) {
+    meta.type = 'value';
+  }
+  if (Array.isArray(value)) {
+    meta.type = 'array';
+  }
+  if (value instanceof Error) {
+    meta.type = 'error';
+  }
+  if (value instanceof Date) {
+    meta.type = 'date';
+  }
+  if ((value != null ? value.constructor.name : void 0) === 'Promise') {
+    meta.type = 'promise';
+  }
+
+  /* Treat simple objects as value. */
+  if (optimizeSimpleObject && meta.type === 'object' && v8Util.getHiddenValue(value, 'simple')) {
+    meta.type = 'value';
+  }
+
+  /* Treat the arguments object as array. */
+  if (meta.type === 'object' && (value.callee != null) && (value.length != null)) {
+    meta.type = 'array';
+  }
+  if (meta.type === 'array') {
+    meta.members = [];
+    for (i = 0, len = value.length; i < len; i++) {
+      el = value[i];
+      meta.members.push(valueToMeta(sender, el));
+    }
+  } else if (meta.type === 'object' || meta.type === 'function') {
+    meta.name = value.constructor.name;
+
+    /*
+      Reference the original value if it's an object, because when it's
+      passed to renderer we would assume the renderer keeps a reference of
+      it.
+     */
+    meta.id = objectsRegistry.add(sender.getId(), value);
+    meta.members = (function() {
+      var results;
+      results = [];
+      for (name in value) {
+        field = value[name];
+        results.push({
+          name: name,
+          type: typeof field
+        });
+      }
+      return results;
+    })();
+  } else if (meta.type === 'buffer') {
+    meta.value = Array.prototype.slice.call(value, 0);
+  } else if (meta.type === 'promise') {
+    meta.then = valueToMeta(sender, value.then.bind(value));
+  } else if (meta.type === 'error') {
+    meta.members = plainObjectToMeta(value);
+
+    /* Error.name is not part of own properties. */
+    meta.members.push({
+      name: 'name',
+      value: value.name
+    });
+  } else if (meta.type === 'date') {
+    meta.value = value.getTime();
+  } else {
+    meta.type = 'value';
+    meta.value = value;
+  }
+  return meta;
+};
+
+
+/* Convert object to meta by value. */
+
+plainObjectToMeta = function(obj) {
+  return Object.getOwnPropertyNames(obj).map(function(name) {
+    return {
+      name: name,
+      value: obj[name]
+    };
+  });
+};
+
+
+/* Convert Error into meta data. */
+
+exceptionToMeta = function(error) {
+  return {
+    type: 'exception',
+    message: error.message,
+    stack: error.stack || error
+  };
+};
+
+
+/* Convert array of meta data from renderer into array of real values. */
+
+unwrapArgs = function(sender, args) {
+  var metaToValue;
+  metaToValue = function(meta) {
+    var i, len, member, ref, rendererReleased, ret, returnValue;
+    switch (meta.type) {
+      case 'value':
+        return meta.value;
+      case 'remote-object':
+        return objectsRegistry.get(meta.id);
+      case 'array':
+        return unwrapArgs(sender, meta.value);
+      case 'buffer':
+        return new Buffer(meta.value);
+      case 'date':
+        return new Date(meta.value);
+      case 'promise':
+        return Promise.resolve({
+          then: metaToValue(meta.then)
+        });
+      case 'object':
+        ret = v8Util.createObjectWithName(meta.name);
+        ref = meta.members;
+        for (i = 0, len = ref.length; i < len; i++) {
+          member = ref[i];
+          ret[member.name] = metaToValue(member.value);
+        }
+        return ret;
+      case 'function-with-return-value':
+        returnValue = metaToValue(meta.value);
+        return function() {
+          return returnValue;
+        };
+      case 'function':
+
+        /* Cache the callbacks in renderer. */
+        if (!sender.callbacks) {
+          sender.callbacks = new IDWeakMap;
+          sender.on('render-view-deleted', function() {
+            return sender.callbacks.clear();
+          });
+        }
+        if (sender.callbacks.has(meta.id)) {
+          return sender.callbacks.get(meta.id);
+        }
+        rendererReleased = false;
+        objectsRegistry.once("clear-" + (sender.getId()), function() {
+          return rendererReleased = true;
+        });
+        ret = function() {
+          if (rendererReleased) {
+            throw new Error("Attempting to call a function in a renderer window that has been closed or released. Function provided here: " + meta.location + ".");
+          }
+          return sender.send('ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, arguments));
+        };
+        v8Util.setDestructor(ret, function() {
+          if (rendererReleased) {
+            return;
+          }
+          sender.callbacks.remove(meta.id);
+          return sender.send('ATOM_RENDERER_RELEASE_CALLBACK', meta.id);
+        });
+        sender.callbacks.set(meta.id, ret);
+        return ret;
+      default:
+        throw new TypeError("Unknown type: " + meta.type);
+    }
+  };
+  return args.map(metaToValue);
+};
+
+
+/*
+  Call a function and send reply asynchronously if it's a an asynchronous
+  style function and the caller didn't pass a callback.
+ */
+
+callFunction = function(event, func, caller, args) {
+  var e, error1, funcMarkedAsync, funcName, funcPassedCallback, ref, ret;
+  funcMarkedAsync = v8Util.getHiddenValue(func, 'asynchronous');
+  funcPassedCallback = typeof args[args.length - 1] === 'function';
+  try {
+    if (funcMarkedAsync && !funcPassedCallback) {
+      args.push(function(ret) {
+        return event.returnValue = valueToMeta(event.sender, ret, true);
+      });
+      return func.apply(caller, args);
+    } else {
+      ret = func.apply(caller, args);
+      return event.returnValue = valueToMeta(event.sender, ret, true);
+    }
+  } catch (error1) {
+    e = error1;
+
+    /*
+      Catch functions thrown further down in function invocation and wrap
+      them with the function name so it's easier to trace things like
+      `Error processing argument -1.`
+     */
+    funcName = (ref = func.name) != null ? ref : "anonymous";
+    throw new Error("Could not call remote function `" + funcName + "`. Check that the function signature is correct. Underlying error: " + e.message);
+  }
+};
+
+
+/* Send by BrowserWindow when its render view is deleted. */
+
+process.on('ATOM_BROWSER_RELEASE_RENDER_VIEW', function(id) {
+  return objectsRegistry.clear(id);
+});
+
+ipcMain.on('ATOM_BROWSER_REQUIRE', function(event, module) {
+  var e, error1;
+  try {
+    return event.returnValue = valueToMeta(event.sender, process.mainModule.require(module));
+  } catch (error1) {
+    e = error1;
+    return event.returnValue = exceptionToMeta(e);
+  }
+});
+
+ipcMain.on('ATOM_BROWSER_GET_BUILTIN', function(event, module) {
+  var e, error1;
+  try {
+    return event.returnValue = valueToMeta(event.sender, electron[module]);
+  } catch (error1) {
+    e = error1;
+    return event.returnValue = exceptionToMeta(e);
+  }
+});
+
+ipcMain.on('ATOM_BROWSER_GLOBAL', function(event, name) {
+  var e, error1;
+  try {
+    return event.returnValue = valueToMeta(event.sender, global[name]);
+  } catch (error1) {
+    e = error1;
+    return event.returnValue = exceptionToMeta(e);
+  }
+});
+
+ipcMain.on('ATOM_BROWSER_CURRENT_WINDOW', function(event) {
+  var e, error1;
+  try {
+    return event.returnValue = valueToMeta(event.sender, event.sender.getOwnerBrowserWindow());
+  } catch (error1) {
+    e = error1;
+    return event.returnValue = exceptionToMeta(e);
+  }
+});
+
+ipcMain.on('ATOM_BROWSER_CURRENT_WEB_CONTENTS', function(event) {
+  return event.returnValue = valueToMeta(event.sender, event.sender);
+});
+
+ipcMain.on('ATOM_BROWSER_CONSTRUCTOR', function(event, id, args) {
+  var constructor, e, error1, obj;
+  try {
+    args = unwrapArgs(event.sender, args);
+    constructor = objectsRegistry.get(id);
+
+    /*
+      Call new with array of arguments.
+      http://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible
+     */
+    obj = new (Function.prototype.bind.apply(constructor, [null].concat(args)));
+    return event.returnValue = valueToMeta(event.sender, obj);
+  } catch (error1) {
+    e = error1;
+    return event.returnValue = exceptionToMeta(e);
+  }
+});
+
+ipcMain.on('ATOM_BROWSER_FUNCTION_CALL', function(event, id, args) {
+  var e, error1, func;
+  try {
+    args = unwrapArgs(event.sender, args);
+    func = objectsRegistry.get(id);
+    return callFunction(event, func, global, args);
+  } catch (error1) {
+    e = error1;
+    return event.returnValue = exceptionToMeta(e);
+  }
+});
+
+ipcMain.on('ATOM_BROWSER_MEMBER_CONSTRUCTOR', function(event, id, method, args) {
+  var constructor, e, error1, obj;
+  try {
+    args = unwrapArgs(event.sender, args);
+    constructor = objectsRegistry.get(id)[method];
+
+    /* Call new with array of arguments. */
+    obj = new (Function.prototype.bind.apply(constructor, [null].concat(args)));
+    return event.returnValue = valueToMeta(event.sender, obj);
+  } catch (error1) {
+    e = error1;
+    return event.returnValue = exceptionToMeta(e);
+  }
+});
+
+ipcMain.on('ATOM_BROWSER_MEMBER_CALL', function(event, id, method, args) {
+  var e, error1, obj;
+  try {
+    args = unwrapArgs(event.sender, args);
+    obj = objectsRegistry.get(id);
+    return callFunction(event, obj[method], obj, args);
+  } catch (error1) {
+    e = error1;
+    return event.returnValue = exceptionToMeta(e);
+  }
+});
+
+ipcMain.on('ATOM_BROWSER_MEMBER_SET', function(event, id, name, value) {
+  var e, error1, obj;
+  try {
+    obj = objectsRegistry.get(id);
+    obj[name] = value;
+    return event.returnValue = null;
+  } catch (error1) {
+    e = error1;
+    return event.returnValue = exceptionToMeta(e);
+  }
+});
+
+ipcMain.on('ATOM_BROWSER_MEMBER_GET', function(event, id, name) {
+  var e, error1, obj;
+  try {
+    obj = objectsRegistry.get(id);
+    return event.returnValue = valueToMeta(event.sender, obj[name]);
+  } catch (error1) {
+    e = error1;
+    return event.returnValue = exceptionToMeta(e);
+  }
+});
+
+ipcMain.on('ATOM_BROWSER_DEREFERENCE', function(event, id) {
+  return objectsRegistry.remove(event.sender.getId(), id);
+});
+
+ipcMain.on('ATOM_BROWSER_GUEST_WEB_CONTENTS', function(event, guestInstanceId) {
+  var e, error1, guestViewManager;
+  try {
+    guestViewManager = require('./guest-view-manager');
+    return event.returnValue = valueToMeta(event.sender, guestViewManager.getGuest(guestInstanceId));
+  } catch (error1) {
+    e = error1;
+    return event.returnValue = exceptionToMeta(e);
+  }
+});
+
+ipcMain.on('ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', function() {
+  var args, e, error1, event, guest, guestInstanceId, guestViewManager, method;
+  event = arguments[0], guestInstanceId = arguments[1], method = arguments[2], args = 4 <= arguments.length ? slice.call(arguments, 3) : [];
+  try {
+    guestViewManager = require('./guest-view-manager');
+    guest = guestViewManager.getGuest(guestInstanceId);
+    return guest[method].apply(guest, args);
+  } catch (error1) {
+    e = error1;
+    return event.returnValue = exceptionToMeta(e);
+  }
+});

+ 0 - 43
atom/common/api/lib/callbacks-registry.coffee

@@ -1,43 +0,0 @@
-v8Util = process.atomBinding 'v8_util'
-
-module.exports =
-class CallbacksRegistry
-  constructor: ->
-    @nextId = 0
-    @callbacks = {}
-
-  add: (callback) ->
-    # The callback is already added.
-    id = v8Util.getHiddenValue callback, 'callbackId'
-    return id if id?
-
-    id = ++@nextId
-
-    # Capture the location of the function and put it in the ID string,
-    # so that release errors can be tracked down easily.
-    regexp = /at (.*)/gi
-    stackString = (new Error).stack
-
-    while (match = regexp.exec(stackString)) isnt null
-      [x, location] = match
-      continue if location.indexOf('(native)') isnt -1
-      continue if location.indexOf('atom.asar') isnt -1
-      [x, filenameAndLine] = /([^/^\)]*)\)?$/gi.exec(location)
-      break
-
-    @callbacks[id] = callback
-    v8Util.setHiddenValue callback, 'callbackId', id
-    v8Util.setHiddenValue callback, 'location', filenameAndLine
-    id
-
-  get: (id) ->
-    @callbacks[id] ? ->
-
-  call: (id, args...) ->
-    @get(id).call global, args...
-
-  apply: (id, args...) ->
-    @get(id).apply global, args...
-
-  remove: (id) ->
-    delete @callbacks[id]

+ 68 - 0
atom/common/api/lib/callbacks-registry.js

@@ -0,0 +1,68 @@
+var CallbacksRegistry, v8Util,
+  slice = [].slice;
+
+v8Util = process.atomBinding('v8_util');
+
+module.exports = CallbacksRegistry = (function() {
+  function CallbacksRegistry() {
+    this.nextId = 0;
+    this.callbacks = {};
+  }
+
+  CallbacksRegistry.prototype.add = function(callback) {
+
+    /* The callback is already added. */
+    var filenameAndLine, id, location, match, ref, regexp, stackString, x;
+    id = v8Util.getHiddenValue(callback, 'callbackId');
+    if (id != null) {
+      return id;
+    }
+    id = ++this.nextId;
+
+    /*
+      Capture the location of the function and put it in the ID string,
+      so that release errors can be tracked down easily.
+     */
+    regexp = /at (.*)/gi;
+    stackString = (new Error).stack;
+    while ((match = regexp.exec(stackString)) !== null) {
+      x = match[0], location = match[1];
+      if (location.indexOf('(native)') !== -1) {
+        continue;
+      }
+      if (location.indexOf('atom.asar') !== -1) {
+        continue;
+      }
+      ref = /([^\/^\)]*)\)?$/gi.exec(location), x = ref[0], filenameAndLine = ref[1];
+      break;
+    }
+    this.callbacks[id] = callback;
+    v8Util.setHiddenValue(callback, 'callbackId', id);
+    v8Util.setHiddenValue(callback, 'location', filenameAndLine);
+    return id;
+  };
+
+  CallbacksRegistry.prototype.get = function(id) {
+    var ref;
+    return (ref = this.callbacks[id]) != null ? ref : function() {};
+  };
+
+  CallbacksRegistry.prototype.call = function() {
+    var args, id, ref;
+    id = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+    return (ref = this.get(id)).call.apply(ref, [global].concat(slice.call(args)));
+  };
+
+  CallbacksRegistry.prototype.apply = function() {
+    var args, id, ref;
+    id = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+    return (ref = this.get(id)).apply.apply(ref, [global].concat(slice.call(args)));
+  };
+
+  CallbacksRegistry.prototype.remove = function(id) {
+    return delete this.callbacks[id];
+  };
+
+  return CallbacksRegistry;
+
+})();

+ 0 - 5
atom/common/api/lib/clipboard.coffee

@@ -1,5 +0,0 @@
-if process.platform is 'linux' and process.type is 'renderer'
-  # On Linux we could not access clipboard in renderer process.
-  module.exports = require('electron').remote.clipboard
-else
-  module.exports = process.atomBinding 'clipboard'

+ 7 - 0
atom/common/api/lib/clipboard.js

@@ -0,0 +1,7 @@
+if (process.platform === 'linux' && process.type === 'renderer') {
+
+  /* On Linux we could not access clipboard in renderer process. */
+  module.exports = require('electron').remote.clipboard;
+} else {
+  module.exports = process.atomBinding('clipboard');
+}

+ 0 - 69
atom/common/api/lib/crash-reporter.coffee

@@ -1,69 +0,0 @@
-fs      = require 'fs'
-os      = require 'os'
-path    = require 'path'
-{spawn} = require 'child_process'
-
-electron = require 'electron'
-binding = process.atomBinding 'crash_reporter'
-
-class CrashReporter
-  start: (options={}) ->
-    {@productName, companyName, submitURL, autoSubmit, ignoreSystemCrashHandler, extra} = options
-
-    # Deprecated.
-    {deprecate} = electron
-    if options.submitUrl
-      submitURL ?= options.submitUrl
-      deprecate.warn 'submitUrl', 'submitURL'
-
-    {app} = if process.type is 'browser' then electron else electron.remote
-
-    @productName ?= app.getName()
-    autoSubmit ?= true
-    ignoreSystemCrashHandler ?= false
-    extra ?= {}
-
-    extra._productName ?= @productName
-    extra._companyName ?= companyName
-    extra._version ?= app.getVersion()
-
-    unless companyName?
-      deprecate.log('companyName is now a required option to crashReporter.start')
-      return
-
-    unless submitURL?
-      deprecate.log('submitURL is now a required option to crashReporter.start')
-      return
-
-    start = => binding.start @productName, companyName, submitURL, autoSubmit, ignoreSystemCrashHandler, extra
-
-    if process.platform is 'win32'
-      args = [
-        "--reporter-url=#{submitURL}"
-        "--application-name=#{@productName}"
-        "--v=1"
-      ]
-      env = ATOM_SHELL_INTERNAL_CRASH_SERVICE: 1
-
-      spawn process.execPath, args, {env, detached: true}
-    start()
-
-  getLastCrashReport: ->
-    reports = this.getUploadedReports()
-    if reports.length > 0 then reports[0] else null
-
-  getUploadedReports: ->
-    tmpdir =
-      if process.platform is 'win32'
-        os.tmpdir()
-      else
-        '/tmp'
-    log =
-      if process.platform is 'darwin'
-        path.join tmpdir, "#{@productName} Crashes"
-      else
-        path.join tmpdir, "#{@productName} Crashes", 'uploads.log'
-    binding._getUploadedReports log
-
-crashRepoter = new CrashReporter
-module.exports = crashRepoter

+ 104 - 0
atom/common/api/lib/crash-reporter.js

@@ -0,0 +1,104 @@
+var CrashReporter, binding, crashRepoter, electron, fs, os, path, spawn;
+
+fs = require('fs');
+
+os = require('os');
+
+path = require('path');
+
+spawn = require('child_process').spawn;
+
+electron = require('electron');
+
+binding = process.atomBinding('crash_reporter');
+
+CrashReporter = (function() {
+  function CrashReporter() {}
+
+  CrashReporter.prototype.start = function(options) {
+    var app, args, autoSubmit, companyName, deprecate, env, extra, ignoreSystemCrashHandler, start, submitURL;
+    if (options == null) {
+      options = {};
+    }
+    this.productName = options.productName, companyName = options.companyName, submitURL = options.submitURL, autoSubmit = options.autoSubmit, ignoreSystemCrashHandler = options.ignoreSystemCrashHandler, extra = options.extra;
+
+    /* Deprecated. */
+    deprecate = electron.deprecate;
+    if (options.submitUrl) {
+      if (submitURL == null) {
+        submitURL = options.submitUrl;
+      }
+      deprecate.warn('submitUrl', 'submitURL');
+    }
+    app = (process.type === 'browser' ? electron : electron.remote).app;
+    if (this.productName == null) {
+      this.productName = app.getName();
+    }
+    if (autoSubmit == null) {
+      autoSubmit = true;
+    }
+    if (ignoreSystemCrashHandler == null) {
+      ignoreSystemCrashHandler = false;
+    }
+    if (extra == null) {
+      extra = {};
+    }
+    if (extra._productName == null) {
+      extra._productName = this.productName;
+    }
+    if (extra._companyName == null) {
+      extra._companyName = companyName;
+    }
+    if (extra._version == null) {
+      extra._version = app.getVersion();
+    }
+    if (companyName == null) {
+      deprecate.log('companyName is now a required option to crashReporter.start');
+      return;
+    }
+    if (submitURL == null) {
+      deprecate.log('submitURL is now a required option to crashReporter.start');
+      return;
+    }
+    start = (function(_this) {
+      return function() {
+        return binding.start(_this.productName, companyName, submitURL, autoSubmit, ignoreSystemCrashHandler, extra);
+      };
+    })(this);
+    if (process.platform === 'win32') {
+      args = ["--reporter-url=" + submitURL, "--application-name=" + this.productName, "--v=1"];
+      env = {
+        ATOM_SHELL_INTERNAL_CRASH_SERVICE: 1
+      };
+      spawn(process.execPath, args, {
+        env: env,
+        detached: true
+      });
+    }
+    return start();
+  };
+
+  CrashReporter.prototype.getLastCrashReport = function() {
+    var reports;
+    reports = this.getUploadedReports();
+    if (reports.length > 0) {
+      return reports[0];
+    } else {
+      return null;
+    }
+  };
+
+  CrashReporter.prototype.getUploadedReports = function() {
+    var log, tmpdir;
+    tmpdir = process.platform === 'win32' ? os.tmpdir() : '/tmp';
+    log = process.platform === 'darwin' ? path.join(tmpdir, this.productName + " Crashes") : path.join(tmpdir, this.productName + " Crashes", 'uploads.log');
+    return binding._getUploadedReports(log);
+  };
+
+  return CrashReporter;
+
+})();
+
+crashRepoter = new CrashReporter;
+
+module.exports = crashRepoter;

+ 0 - 68
atom/common/api/lib/deprecate.coffee

@@ -1,68 +0,0 @@
-# Deprecate a method.
-deprecate = (oldName, newName, fn) ->
-  warned = false
-  ->
-    unless warned or process.noDeprecation
-      warned = true
-      deprecate.warn oldName, newName
-    fn.apply this, arguments
-
-# The method is renamed.
-deprecate.rename = (object, oldName, newName) ->
-  warned = false
-  newMethod = ->
-    unless warned or process.noDeprecation
-      warned = true
-      deprecate.warn oldName, newName
-    this[newName].apply this, arguments
-  if typeof object is 'function'
-    object.prototype[oldName] = newMethod
-  else
-    object[oldName] = newMethod
-
-# Forward the method to member.
-deprecate.member = (object, method, member) ->
-  warned = false
-  object.prototype[method] = ->
-    unless warned or process.noDeprecation
-      warned = true
-      deprecate.warn method, "#{member}.#{method}"
-    this[member][method].apply this[member], arguments
-
-# Deprecate a property.
-deprecate.property = (object, property, method) ->
-  Object.defineProperty object, property,
-    get: ->
-      warned = false
-      unless warned or process.noDeprecation
-        warned = true
-        deprecate.warn "#{property} property", "#{method} method"
-      this[method]()
-
-# Deprecate an event.
-deprecate.event = (emitter, oldName, newName, fn) ->
-  warned = false
-  emitter.on newName, (args...) ->
-    if @listenerCount(oldName) > 0  # there is listeners for old API.
-      unless warned or process.noDeprecation
-        warned = true
-        deprecate.warn "'#{oldName}' event", "'#{newName}' event"
-      if fn?
-        fn.apply this, arguments
-      else
-        @emit oldName, args...
-
-# Print deprecation warning.
-deprecate.warn = (oldName, newName) ->
-  deprecate.log "#{oldName} is deprecated. Use #{newName} instead."
-
-# Print deprecation message.
-deprecate.log = (message) ->
-  if process.throwDeprecation
-    throw new Error(message)
-  else if process.traceDeprecation
-    console.trace message
-  else
-    console.warn "(electron) #{message}"
-
-module.exports = deprecate

+ 115 - 0
atom/common/api/lib/deprecate.js

@@ -0,0 +1,115 @@
+
+/* Deprecate a method. */
+var deprecate,
+  slice = [].slice;
+
+deprecate = function(oldName, newName, fn) {
+  var warned;
+  warned = false;
+  return function() {
+    if (!(warned || process.noDeprecation)) {
+      warned = true;
+      deprecate.warn(oldName, newName);
+    }
+    return fn.apply(this, arguments);
+  };
+};
+
+
+/* The method is renamed. */
+
+deprecate.rename = function(object, oldName, newName) {
+  var newMethod, warned;
+  warned = false;
+  newMethod = function() {
+    if (!(warned || process.noDeprecation)) {
+      warned = true;
+      deprecate.warn(oldName, newName);
+    }
+    return this[newName].apply(this, arguments);
+  };
+  if (typeof object === 'function') {
+    return object.prototype[oldName] = newMethod;
+  } else {
+    return object[oldName] = newMethod;
+  }
+};
+
+
+/* Forward the method to member. */
+
+deprecate.member = function(object, method, member) {
+  var warned;
+  warned = false;
+  return object.prototype[method] = function() {
+    if (!(warned || process.noDeprecation)) {
+      warned = true;
+      deprecate.warn(method, member + "." + method);
+    }
+    return this[member][method].apply(this[member], arguments);
+  };
+};
+
+
+/* Deprecate a property. */
+
+deprecate.property = function(object, property, method) {
+  return Object.defineProperty(object, property, {
+    get: function() {
+      var warned;
+      warned = false;
+      if (!(warned || process.noDeprecation)) {
+        warned = true;
+        deprecate.warn(property + " property", method + " method");
+      }
+      return this[method]();
+    }
+  });
+};
+
+
+/* Deprecate an event. */
+
+deprecate.event = function(emitter, oldName, newName, fn) {
+  var warned;
+  warned = false;
+  return emitter.on(newName, function() {
+    var args;
+    args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+
+    /* there is listeners for old API. */
+    if (this.listenerCount(oldName) > 0) {
+      if (!(warned || process.noDeprecation)) {
+        warned = true;
+        deprecate.warn("'" + oldName + "' event", "'" + newName + "' event");
+      }
+      if (fn != null) {
+        return fn.apply(this, arguments);
+      } else {
+        return this.emit.apply(this, [oldName].concat(slice.call(args)));
+      }
+    }
+  });
+};
+
+
+/* Print deprecation warning. */
+
+deprecate.warn = function(oldName, newName) {
+  return deprecate.log(oldName + " is deprecated. Use " + newName + " instead.");
+};
+
+
+/* Print deprecation message. */
+
+deprecate.log = function(message) {
+  if (process.throwDeprecation) {
+    throw new Error(message);
+  } else if (process.traceDeprecation) {
+    return console.trace(message);
+  } else {
+    return console.warn("(electron) " + message);
+  }
+};
+
+module.exports = deprecate;

+ 0 - 29
atom/common/api/lib/exports/electron.coffee

@@ -1,29 +0,0 @@
-# Do not expose the internal modules to `require`.
-exports.hideInternalModules = ->
-  {globalPaths} = require 'module'
-  if globalPaths.length is 3
-    # Remove the "common/api/lib" and "browser-or-renderer/api/lib".
-    globalPaths.splice 0, 2
-
-# Attaches properties to |exports|.
-exports.defineProperties = (exports) ->
-  Object.defineProperties exports,
-    # Common modules, please sort with alphabet order.
-    clipboard:
-      # Must be enumerable, otherwise it woulde be invisible to remote module.
-      enumerable: true
-      get: -> require '../clipboard'
-    crashReporter:
-      enumerable: true
-      get: -> require '../crash-reporter'
-    nativeImage:
-      enumerable: true
-      get: -> require '../native-image'
-    shell:
-      enumerable: true
-      get: -> require '../shell'
-    # The internal modules, invisible unless you know their names.
-    CallbacksRegistry:
-      get: -> require '../callbacks-registry'
-    deprecate:
-      get: -> require '../deprecate'

+ 59 - 0
atom/common/api/lib/exports/electron.js

@@ -0,0 +1,59 @@
+
+/* Do not expose the internal modules to `require`. */
+exports.hideInternalModules = function() {
+  var globalPaths;
+  globalPaths = require('module').globalPaths;
+  if (globalPaths.length === 3) {
+
+    /* Remove the "common/api/lib" and "browser-or-renderer/api/lib". */
+    return globalPaths.splice(0, 2);
+  }
+};
+
+
+/* Attaches properties to |exports|. */
+
+exports.defineProperties = function(exports) {
+  return Object.defineProperties(exports, {
+
+    /* Common modules, please sort with alphabet order. */
+    clipboard: {
+
+      /* Must be enumerable, otherwise it woulde be invisible to remote module. */
+      enumerable: true,
+      get: function() {
+        return require('../clipboard');
+      }
+    },
+    crashReporter: {
+      enumerable: true,
+      get: function() {
+        return require('../crash-reporter');
+      }
+    },
+    nativeImage: {
+      enumerable: true,
+      get: function() {
+        return require('../native-image');
+      }
+    },
+    shell: {
+      enumerable: true,
+      get: function() {
+        return require('../shell');
+      }
+    },
+
+    /* The internal modules, invisible unless you know their names. */
+    CallbacksRegistry: {
+      get: function() {
+        return require('../callbacks-registry');
+      }
+    },
+    deprecate: {
+      get: function() {
+        return require('../deprecate');
+      }
+    }
+  });
+};

+ 0 - 7
atom/common/api/lib/native-image.coffee

@@ -1,7 +0,0 @@
-{deprecate} = require 'electron'
-nativeImage = process.atomBinding 'native_image'
-
-# Deprecated.
-deprecate.rename nativeImage, 'createFromDataUrl', 'createFromDataURL'
-
-module.exports = nativeImage

+ 12 - 0
atom/common/api/lib/native-image.js

@@ -0,0 +1,12 @@
+var deprecate, nativeImage;
+
+deprecate = require('electron').deprecate;
+
+nativeImage = process.atomBinding('native_image');
+
+
+/* Deprecated. */
+
+deprecate.rename(nativeImage, 'createFromDataUrl', 'createFromDataURL');
+
+module.exports = nativeImage;

+ 0 - 1
atom/common/api/lib/shell.coffee

@@ -1 +0,0 @@
-module.exports = process.atomBinding 'shell'

+ 1 - 0
atom/common/api/lib/shell.js

@@ -0,0 +1 @@
+module.exports = process.atomBinding('shell');

+ 0 - 386
atom/common/lib/asar.coffee

@@ -1,386 +0,0 @@
-asar = process.binding 'atom_common_asar'
-child_process = require 'child_process'
-path = require 'path'
-util = require 'util'
-
-# Cache asar archive objects.
-cachedArchives = {}
-getOrCreateArchive = (p) ->
-  archive = cachedArchives[p]
-  return archive if archive?
-  archive = asar.createArchive p
-  return false unless archive
-  cachedArchives[p] = archive
-
-# Clean cache on quit.
-process.on 'exit', ->
-  archive.destroy() for own p, archive of cachedArchives
-
-# Separate asar package's path from full path.
-splitPath = (p) ->
-  return [false] if process.noAsar  # shortcut to disable asar.
-  return [false] if typeof p isnt 'string'
-  return [true, p, ''] if p.substr(-5) is '.asar'
-  p = path.normalize p
-  index = p.lastIndexOf ".asar#{path.sep}"
-  return [false] if index is -1
-  [true, p.substr(0, index + 5), p.substr(index + 6)]
-
-# Convert asar archive's Stats object to fs's Stats object.
-nextInode = 0
-uid = if process.getuid? then process.getuid() else 0
-gid = if process.getgid? then process.getgid() else 0
-fakeTime = new Date()
-asarStatsToFsStats = (stats) ->
-  {
-    dev: 1,
-    ino: ++nextInode,
-    mode: 33188,
-    nlink: 1,
-    uid: uid,
-    gid: gid,
-    rdev: 0,
-    atime: stats.atime || fakeTime,
-    birthtime: stats.birthtime || fakeTime,
-    mtime: stats.mtime || fakeTime,
-    ctime: stats.ctime || fakeTime,
-    size: stats.size,
-    isFile: -> stats.isFile
-    isDirectory: -> stats.isDirectory
-    isSymbolicLink: -> stats.isLink
-    isBlockDevice: -> false
-    isCharacterDevice: -> false
-    isFIFO: -> false
-    isSocket: -> false
-  }
-
-# Create a ENOENT error.
-notFoundError = (asarPath, filePath, callback) ->
-  error = new Error("ENOENT, #{filePath} not found in #{asarPath}")
-  error.code = "ENOENT"
-  error.errno = -2
-  unless typeof callback is 'function'
-    throw error
-  process.nextTick -> callback error
-
-# Create a ENOTDIR error.
-notDirError = (callback) ->
-  error = new Error('ENOTDIR, not a directory')
-  error.code = 'ENOTDIR'
-  error.errno = -20
-  unless typeof callback is 'function'
-    throw error
-  process.nextTick -> callback error
-
-# Create invalid archive error.
-invalidArchiveError = (asarPath, callback) ->
-  error = new Error("Invalid package #{asarPath}")
-  unless typeof callback is 'function'
-    throw error
-  process.nextTick -> callback error
-
-# Override APIs that rely on passing file path instead of content to C++.
-overrideAPISync = (module, name, arg = 0) ->
-  old = module[name]
-  module[name] = ->
-    p = arguments[arg]
-    [isAsar, asarPath, filePath] = splitPath p
-    return old.apply this, arguments unless isAsar
-
-    archive = getOrCreateArchive asarPath
-    invalidArchiveError asarPath unless archive
-
-    newPath = archive.copyFileOut filePath
-    notFoundError asarPath, filePath unless newPath
-
-    arguments[arg] = newPath
-    old.apply this, arguments
-
-overrideAPI = (module, name, arg = 0) ->
-  old = module[name]
-  module[name] = ->
-    p = arguments[arg]
-    [isAsar, asarPath, filePath] = splitPath p
-    return old.apply this, arguments unless isAsar
-
-    callback = arguments[arguments.length - 1]
-    return overrideAPISync module, name, arg unless typeof callback is 'function'
-
-    archive = getOrCreateArchive asarPath
-    return invalidArchiveError asarPath, callback unless archive
-
-    newPath = archive.copyFileOut filePath
-    return notFoundError asarPath, filePath, callback unless newPath
-
-    arguments[arg] = newPath
-    old.apply this, arguments
-
-# Override fs APIs.
-exports.wrapFsWithAsar = (fs) ->
-  lstatSync = fs.lstatSync
-  fs.lstatSync = (p) ->
-    [isAsar, asarPath, filePath] = splitPath p
-    return lstatSync p unless isAsar
-
-    archive = getOrCreateArchive asarPath
-    invalidArchiveError asarPath unless archive
-
-    stats = archive.stat filePath
-    notFoundError asarPath, filePath unless stats
-
-    asarStatsToFsStats stats
-
-  lstat = fs.lstat
-  fs.lstat = (p, callback) ->
-    [isAsar, asarPath, filePath] = splitPath p
-    return lstat p, callback unless isAsar
-
-    archive = getOrCreateArchive asarPath
-    return invalidArchiveError asarPath, callback unless archive
-
-    stats = getOrCreateArchive(asarPath).stat filePath
-    return notFoundError asarPath, filePath, callback unless stats
-
-    process.nextTick -> callback null, asarStatsToFsStats stats
-
-  statSync = fs.statSync
-  fs.statSync = (p) ->
-    [isAsar, asarPath, filePath] = splitPath p
-    return statSync p unless isAsar
-
-    # Do not distinguish links for now.
-    fs.lstatSync p
-
-  stat = fs.stat
-  fs.stat = (p, callback) ->
-    [isAsar, asarPath, filePath] = splitPath p
-    return stat p, callback unless isAsar
-
-    # Do not distinguish links for now.
-    process.nextTick -> fs.lstat p, callback
-
-  statSyncNoException = fs.statSyncNoException
-  fs.statSyncNoException = (p) ->
-    [isAsar, asarPath, filePath] = splitPath p
-    return statSyncNoException p unless isAsar
-
-    archive = getOrCreateArchive asarPath
-    return false unless archive
-    stats = archive.stat filePath
-    return false unless stats
-    asarStatsToFsStats stats
-
-  realpathSync = fs.realpathSync
-  fs.realpathSync = (p) ->
-    [isAsar, asarPath, filePath] = splitPath p
-    return realpathSync.apply this, arguments unless isAsar
-
-    archive = getOrCreateArchive asarPath
-    invalidArchiveError asarPath unless archive
-
-    real = archive.realpath filePath
-    notFoundError asarPath, filePath if real is false
-
-    path.join realpathSync(asarPath), real
-
-  realpath = fs.realpath
-  fs.realpath = (p, cache, callback) ->
-    [isAsar, asarPath, filePath] = splitPath p
-    return realpath.apply this, arguments unless isAsar
-
-    if typeof cache is 'function'
-      callback = cache
-      cache = undefined
-
-    archive = getOrCreateArchive asarPath
-    return invalidArchiveError asarPath, callback unless archive
-
-    real = archive.realpath filePath
-    if real is false
-      return notFoundError asarPath, filePath, callback
-
-    realpath asarPath, (err, p) ->
-      return callback err if err
-      callback null, path.join(p, real)
-
-  exists = fs.exists
-  fs.exists = (p, callback) ->
-    [isAsar, asarPath, filePath] = splitPath p
-    return exists p, callback unless isAsar
-
-    archive = getOrCreateArchive asarPath
-    return invalidArchiveError asarPath, callback unless archive
-
-    process.nextTick -> callback archive.stat(filePath) isnt false
-
-  existsSync = fs.existsSync
-  fs.existsSync = (p) ->
-    [isAsar, asarPath, filePath] = splitPath p
-    return existsSync p unless isAsar
-
-    archive = getOrCreateArchive asarPath
-    return false unless archive
-
-    archive.stat(filePath) isnt false
-
-  open = fs.open
-  readFile = fs.readFile
-  fs.readFile = (p, options, callback) ->
-    [isAsar, asarPath, filePath] = splitPath p
-    return readFile.apply this, arguments unless isAsar
-
-    if typeof options is 'function'
-      callback = options
-      options = undefined
-
-    archive = getOrCreateArchive asarPath
-    return invalidArchiveError asarPath, callback unless archive
-
-    info = archive.getFileInfo filePath
-    return notFoundError asarPath, filePath, callback unless info
-
-    if info.size is 0
-      return process.nextTick -> callback null, new Buffer(0)
-
-    if info.unpacked
-      realPath = archive.copyFileOut filePath
-      return fs.readFile realPath, options, callback
-
-    if not options
-      options = encoding: null
-    else if util.isString options
-      options = encoding: options
-    else if not util.isObject options
-      throw new TypeError('Bad arguments')
-
-    encoding = options.encoding
-
-    buffer = new Buffer(info.size)
-    fd = archive.getFd()
-    return notFoundError asarPath, filePath, callback unless fd >= 0
-
-    fs.read fd, buffer, 0, info.size, info.offset, (error) ->
-      callback error, if encoding then buffer.toString encoding else buffer
-
-  openSync = fs.openSync
-  readFileSync = fs.readFileSync
-  fs.readFileSync = (p, opts) ->
-    options = opts # this allows v8 to optimize this function
-    [isAsar, asarPath, filePath] = splitPath p
-    return readFileSync.apply this, arguments unless isAsar
-
-    archive = getOrCreateArchive asarPath
-    invalidArchiveError asarPath unless archive
-
-    info = archive.getFileInfo filePath
-    notFoundError asarPath, filePath unless info
-
-    if info.size is 0
-      return if options then '' else new Buffer(0)
-
-    if info.unpacked
-      realPath = archive.copyFileOut filePath
-      return fs.readFileSync realPath, options
-
-    if not options
-      options = encoding: null
-    else if util.isString options
-      options = encoding: options
-    else if not util.isObject options
-      throw new TypeError('Bad arguments')
-
-    encoding = options.encoding
-
-    buffer = new Buffer(info.size)
-    fd = archive.getFd()
-    notFoundError asarPath, filePath unless fd >= 0
-
-    fs.readSync fd, buffer, 0, info.size, info.offset
-    if encoding then buffer.toString encoding else buffer
-
-  readdir = fs.readdir
-  fs.readdir = (p, callback) ->
-    [isAsar, asarPath, filePath] = splitPath p
-    return readdir.apply this, arguments unless isAsar
-
-    archive = getOrCreateArchive asarPath
-    return invalidArchiveError asarPath, callback unless archive
-
-    files = archive.readdir filePath
-    return notFoundError asarPath, filePath, callback unless files
-
-    process.nextTick -> callback null, files
-
-  readdirSync = fs.readdirSync
-  fs.readdirSync = (p) ->
-    [isAsar, asarPath, filePath] = splitPath p
-    return readdirSync.apply this, arguments unless isAsar
-
-    archive = getOrCreateArchive asarPath
-    invalidArchiveError asarPath unless archive
-
-    files = archive.readdir filePath
-    notFoundError asarPath, filePath unless files
-
-    files
-
-  internalModuleReadFile = process.binding('fs').internalModuleReadFile
-  process.binding('fs').internalModuleReadFile = (p) ->
-    [isAsar, asarPath, filePath] = splitPath p
-    return internalModuleReadFile p unless isAsar
-
-    archive = getOrCreateArchive asarPath
-    return undefined unless archive
-
-    info = archive.getFileInfo filePath
-    return undefined unless info
-    return '' if info.size is 0
-
-    if info.unpacked
-      realPath = archive.copyFileOut filePath
-      return fs.readFileSync realPath, encoding: 'utf8'
-
-    buffer = new Buffer(info.size)
-    fd = archive.getFd()
-    return undefined unless fd >= 0
-
-    fs.readSync fd, buffer, 0, info.size, info.offset
-    buffer.toString 'utf8'
-
-  internalModuleStat = process.binding('fs').internalModuleStat
-  process.binding('fs').internalModuleStat = (p) ->
-    [isAsar, asarPath, filePath] = splitPath p
-    return internalModuleStat p unless isAsar
-
-    archive = getOrCreateArchive asarPath
-    return -34 unless archive  # -ENOENT
-
-    stats = archive.stat filePath
-    return -34 unless stats  # -ENOENT
-
-    if stats.isDirectory then return 1 else return 0
-
-  # Calling mkdir for directory inside asar archive should throw ENOTDIR
-  # error, but on Windows it throws ENOENT.
-  # This is to work around the recursive looping bug of mkdirp since it is
-  # widely used.
-  if process.platform is 'win32'
-    mkdir = fs.mkdir
-    fs.mkdir = (p, mode, callback) ->
-      callback = mode if typeof mode is 'function'
-      [isAsar, asarPath, filePath] = splitPath p
-      return notDirError callback if isAsar and filePath.length
-      mkdir p, mode, callback
-
-    mkdirSync = fs.mkdirSync
-    fs.mkdirSync = (p, mode) ->
-      [isAsar, asarPath, filePath] = splitPath p
-      notDirError() if isAsar and filePath.length
-      mkdirSync p, mode
-
-  overrideAPI fs, 'open'
-  overrideAPI child_process, 'execFile'
-  overrideAPISync process, 'dlopen', 1
-  overrideAPISync require('module')._extensions, '.node', 1
-  overrideAPISync fs, 'openSync'
-  overrideAPISync child_process, 'execFileSync'

+ 610 - 0
atom/common/lib/asar.js

@@ -0,0 +1,610 @@
+(function () {
+var asar, asarStatsToFsStats, cachedArchives, child_process, fakeTime, getOrCreateArchive, gid, invalidArchiveError, nextInode, notDirError, notFoundError, overrideAPI, overrideAPISync, path, splitPath, uid, util,
+  hasProp = {}.hasOwnProperty;
+
+asar = process.binding('atom_common_asar');
+
+child_process = require('child_process');
+
+path = require('path');
+
+util = require('util');
+
+
+/* Cache asar archive objects. */
+
+cachedArchives = {};
+
+getOrCreateArchive = function(p) {
+  var archive;
+  archive = cachedArchives[p];
+  if (archive != null) {
+    return archive;
+  }
+  archive = asar.createArchive(p);
+  if (!archive) {
+    return false;
+  }
+  return cachedArchives[p] = archive;
+};
+
+
+/* Clean cache on quit. */
+
+process.on('exit', function() {
+  var archive, p, results;
+  results = [];
+  for (p in cachedArchives) {
+    if (!hasProp.call(cachedArchives, p)) continue;
+    archive = cachedArchives[p];
+    results.push(archive.destroy());
+  }
+  return results;
+});
+
+
+/* Separate asar package's path from full path. */
+
+splitPath = function(p) {
+
+  /* shortcut to disable asar. */
+  var index;
+  if (process.noAsar) {
+    return [false];
+  }
+  if (typeof p !== 'string') {
+    return [false];
+  }
+  if (p.substr(-5) === '.asar') {
+    return [true, p, ''];
+  }
+  p = path.normalize(p);
+  index = p.lastIndexOf(".asar" + path.sep);
+  if (index === -1) {
+    return [false];
+  }
+  return [true, p.substr(0, index + 5), p.substr(index + 6)];
+};
+
+
+/* Convert asar archive's Stats object to fs's Stats object. */
+
+nextInode = 0;
+
+uid = process.getuid != null ? process.getuid() : 0;
+
+gid = process.getgid != null ? process.getgid() : 0;
+
+fakeTime = new Date();
+
+asarStatsToFsStats = function(stats) {
+  return {
+    dev: 1,
+    ino: ++nextInode,
+    mode: 33188,
+    nlink: 1,
+    uid: uid,
+    gid: gid,
+    rdev: 0,
+    atime: stats.atime || fakeTime,
+    birthtime: stats.birthtime || fakeTime,
+    mtime: stats.mtime || fakeTime,
+    ctime: stats.ctime || fakeTime,
+    size: stats.size,
+    isFile: function() {
+      return stats.isFile;
+    },
+    isDirectory: function() {
+      return stats.isDirectory;
+    },
+    isSymbolicLink: function() {
+      return stats.isLink;
+    },
+    isBlockDevice: function() {
+      return false;
+    },
+    isCharacterDevice: function() {
+      return false;
+    },
+    isFIFO: function() {
+      return false;
+    },
+    isSocket: function() {
+      return false;
+    }
+  };
+};
+
+
+/* Create a ENOENT error. */
+
+notFoundError = function(asarPath, filePath, callback) {
+  var error;
+  error = new Error("ENOENT, " + filePath + " not found in " + asarPath);
+  error.code = "ENOENT";
+  error.errno = -2;
+  if (typeof callback !== 'function') {
+    throw error;
+  }
+  return process.nextTick(function() {
+    return callback(error);
+  });
+};
+
+
+/* Create a ENOTDIR error. */
+
+notDirError = function(callback) {
+  var error;
+  error = new Error('ENOTDIR, not a directory');
+  error.code = 'ENOTDIR';
+  error.errno = -20;
+  if (typeof callback !== 'function') {
+    throw error;
+  }
+  return process.nextTick(function() {
+    return callback(error);
+  });
+};
+
+
+/* Create invalid archive error. */
+
+invalidArchiveError = function(asarPath, callback) {
+  var error;
+  error = new Error("Invalid package " + asarPath);
+  if (typeof callback !== 'function') {
+    throw error;
+  }
+  return process.nextTick(function() {
+    return callback(error);
+  });
+};
+
+
+/* Override APIs that rely on passing file path instead of content to C++. */
+
+overrideAPISync = function(module, name, arg) {
+  var old;
+  if (arg == null) {
+    arg = 0;
+  }
+  old = module[name];
+  return module[name] = function() {
+    var archive, asarPath, filePath, isAsar, newPath, p, ref;
+    p = arguments[arg];
+    ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+    if (!isAsar) {
+      return old.apply(this, arguments);
+    }
+    archive = getOrCreateArchive(asarPath);
+    if (!archive) {
+      invalidArchiveError(asarPath);
+    }
+    newPath = archive.copyFileOut(filePath);
+    if (!newPath) {
+      notFoundError(asarPath, filePath);
+    }
+    arguments[arg] = newPath;
+    return old.apply(this, arguments);
+  };
+};
+
+overrideAPI = function(module, name, arg) {
+  var old;
+  if (arg == null) {
+    arg = 0;
+  }
+  old = module[name];
+  return module[name] = function() {
+    var archive, asarPath, callback, filePath, isAsar, newPath, p, ref;
+    p = arguments[arg];
+    ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+    if (!isAsar) {
+      return old.apply(this, arguments);
+    }
+    callback = arguments[arguments.length - 1];
+    if (typeof callback !== 'function') {
+      return overrideAPISync(module, name, arg);
+    }
+    archive = getOrCreateArchive(asarPath);
+    if (!archive) {
+      return invalidArchiveError(asarPath, callback);
+    }
+    newPath = archive.copyFileOut(filePath);
+    if (!newPath) {
+      return notFoundError(asarPath, filePath, callback);
+    }
+    arguments[arg] = newPath;
+    return old.apply(this, arguments);
+  };
+};
+
+
+/* Override fs APIs. */
+
+exports.wrapFsWithAsar = function(fs) {
+  var exists, existsSync, internalModuleReadFile, internalModuleStat, lstat, lstatSync, mkdir, mkdirSync, open, openSync, readFile, readFileSync, readdir, readdirSync, realpath, realpathSync, stat, statSync, statSyncNoException;
+  lstatSync = fs.lstatSync;
+  fs.lstatSync = function(p) {
+    var archive, asarPath, filePath, isAsar, ref, stats;
+    ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+    if (!isAsar) {
+      return lstatSync(p);
+    }
+    archive = getOrCreateArchive(asarPath);
+    if (!archive) {
+      invalidArchiveError(asarPath);
+    }
+    stats = archive.stat(filePath);
+    if (!stats) {
+      notFoundError(asarPath, filePath);
+    }
+    return asarStatsToFsStats(stats);
+  };
+  lstat = fs.lstat;
+  fs.lstat = function(p, callback) {
+    var archive, asarPath, filePath, isAsar, ref, stats;
+    ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+    if (!isAsar) {
+      return lstat(p, callback);
+    }
+    archive = getOrCreateArchive(asarPath);
+    if (!archive) {
+      return invalidArchiveError(asarPath, callback);
+    }
+    stats = getOrCreateArchive(asarPath).stat(filePath);
+    if (!stats) {
+      return notFoundError(asarPath, filePath, callback);
+    }
+    return process.nextTick(function() {
+      return callback(null, asarStatsToFsStats(stats));
+    });
+  };
+  statSync = fs.statSync;
+  fs.statSync = function(p) {
+    var asarPath, filePath, isAsar, ref;
+    ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+    if (!isAsar) {
+      return statSync(p);
+    }
+
+    /* Do not distinguish links for now. */
+    return fs.lstatSync(p);
+  };
+  stat = fs.stat;
+  fs.stat = function(p, callback) {
+    var asarPath, filePath, isAsar, ref;
+    ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+    if (!isAsar) {
+      return stat(p, callback);
+    }
+
+    /* Do not distinguish links for now. */
+    return process.nextTick(function() {
+      return fs.lstat(p, callback);
+    });
+  };
+  statSyncNoException = fs.statSyncNoException;
+  fs.statSyncNoException = function(p) {
+    var archive, asarPath, filePath, isAsar, ref, stats;
+    ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+    if (!isAsar) {
+      return statSyncNoException(p);
+    }
+    archive = getOrCreateArchive(asarPath);
+    if (!archive) {
+      return false;
+    }
+    stats = archive.stat(filePath);
+    if (!stats) {
+      return false;
+    }
+    return asarStatsToFsStats(stats);
+  };
+  realpathSync = fs.realpathSync;
+  fs.realpathSync = function(p) {
+    var archive, asarPath, filePath, isAsar, real, ref;
+    ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+    if (!isAsar) {
+      return realpathSync.apply(this, arguments);
+    }
+    archive = getOrCreateArchive(asarPath);
+    if (!archive) {
+      invalidArchiveError(asarPath);
+    }
+    real = archive.realpath(filePath);
+    if (real === false) {
+      notFoundError(asarPath, filePath);
+    }
+    return path.join(realpathSync(asarPath), real);
+  };
+  realpath = fs.realpath;
+  fs.realpath = function(p, cache, callback) {
+    var archive, asarPath, filePath, isAsar, real, ref;
+    ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+    if (!isAsar) {
+      return realpath.apply(this, arguments);
+    }
+    if (typeof cache === 'function') {
+      callback = cache;
+      cache = void 0;
+    }
+    archive = getOrCreateArchive(asarPath);
+    if (!archive) {
+      return invalidArchiveError(asarPath, callback);
+    }
+    real = archive.realpath(filePath);
+    if (real === false) {
+      return notFoundError(asarPath, filePath, callback);
+    }
+    return realpath(asarPath, function(err, p) {
+      if (err) {
+        return callback(err);
+      }
+      return callback(null, path.join(p, real));
+    });
+  };
+  exists = fs.exists;
+  fs.exists = function(p, callback) {
+    var archive, asarPath, filePath, isAsar, ref;
+    ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+    if (!isAsar) {
+      return exists(p, callback);
+    }
+    archive = getOrCreateArchive(asarPath);
+    if (!archive) {
+      return invalidArchiveError(asarPath, callback);
+    }
+    return process.nextTick(function() {
+      return callback(archive.stat(filePath) !== false);
+    });
+  };
+  existsSync = fs.existsSync;
+  fs.existsSync = function(p) {
+    var archive, asarPath, filePath, isAsar, ref;
+    ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+    if (!isAsar) {
+      return existsSync(p);
+    }
+    archive = getOrCreateArchive(asarPath);
+    if (!archive) {
+      return false;
+    }
+    return archive.stat(filePath) !== false;
+  };
+  open = fs.open;
+  readFile = fs.readFile;
+  fs.readFile = function(p, options, callback) {
+    var archive, asarPath, buffer, encoding, fd, filePath, info, isAsar, realPath, ref;
+    ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+    if (!isAsar) {
+      return readFile.apply(this, arguments);
+    }
+    if (typeof options === 'function') {
+      callback = options;
+      options = void 0;
+    }
+    archive = getOrCreateArchive(asarPath);
+    if (!archive) {
+      return invalidArchiveError(asarPath, callback);
+    }
+    info = archive.getFileInfo(filePath);
+    if (!info) {
+      return notFoundError(asarPath, filePath, callback);
+    }
+    if (info.size === 0) {
+      return process.nextTick(function() {
+        return callback(null, new Buffer(0));
+      });
+    }
+    if (info.unpacked) {
+      realPath = archive.copyFileOut(filePath);
+      return fs.readFile(realPath, options, callback);
+    }
+    if (!options) {
+      options = {
+        encoding: null
+      };
+    } else if (util.isString(options)) {
+      options = {
+        encoding: options
+      };
+    } else if (!util.isObject(options)) {
+      throw new TypeError('Bad arguments');
+    }
+    encoding = options.encoding;
+    buffer = new Buffer(info.size);
+    fd = archive.getFd();
+    if (!(fd >= 0)) {
+      return notFoundError(asarPath, filePath, callback);
+    }
+    return fs.read(fd, buffer, 0, info.size, info.offset, function(error) {
+      return callback(error, encoding ? buffer.toString(encoding) : buffer);
+    });
+  };
+  openSync = fs.openSync;
+  readFileSync = fs.readFileSync;
+  fs.readFileSync = function(p, opts) {
+
+    /* this allows v8 to optimize this function */
+    var archive, asarPath, buffer, encoding, fd, filePath, info, isAsar, options, realPath, ref;
+    options = opts;
+    ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+    if (!isAsar) {
+      return readFileSync.apply(this, arguments);
+    }
+    archive = getOrCreateArchive(asarPath);
+    if (!archive) {
+      invalidArchiveError(asarPath);
+    }
+    info = archive.getFileInfo(filePath);
+    if (!info) {
+      notFoundError(asarPath, filePath);
+    }
+    if (info.size === 0) {
+      if (options) {
+        return '';
+      } else {
+        return new Buffer(0);
+      }
+    }
+    if (info.unpacked) {
+      realPath = archive.copyFileOut(filePath);
+      return fs.readFileSync(realPath, options);
+    }
+    if (!options) {
+      options = {
+        encoding: null
+      };
+    } else if (util.isString(options)) {
+      options = {
+        encoding: options
+      };
+    } else if (!util.isObject(options)) {
+      throw new TypeError('Bad arguments');
+    }
+    encoding = options.encoding;
+    buffer = new Buffer(info.size);
+    fd = archive.getFd();
+    if (!(fd >= 0)) {
+      notFoundError(asarPath, filePath);
+    }
+    fs.readSync(fd, buffer, 0, info.size, info.offset);
+    if (encoding) {
+      return buffer.toString(encoding);
+    } else {
+      return buffer;
+    }
+  };
+  readdir = fs.readdir;
+  fs.readdir = function(p, callback) {
+    var archive, asarPath, filePath, files, isAsar, ref;
+    ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+    if (!isAsar) {
+      return readdir.apply(this, arguments);
+    }
+    archive = getOrCreateArchive(asarPath);
+    if (!archive) {
+      return invalidArchiveError(asarPath, callback);
+    }
+    files = archive.readdir(filePath);
+    if (!files) {
+      return notFoundError(asarPath, filePath, callback);
+    }
+    return process.nextTick(function() {
+      return callback(null, files);
+    });
+  };
+  readdirSync = fs.readdirSync;
+  fs.readdirSync = function(p) {
+    var archive, asarPath, filePath, files, isAsar, ref;
+    ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+    if (!isAsar) {
+      return readdirSync.apply(this, arguments);
+    }
+    archive = getOrCreateArchive(asarPath);
+    if (!archive) {
+      invalidArchiveError(asarPath);
+    }
+    files = archive.readdir(filePath);
+    if (!files) {
+      notFoundError(asarPath, filePath);
+    }
+    return files;
+  };
+  internalModuleReadFile = process.binding('fs').internalModuleReadFile;
+  process.binding('fs').internalModuleReadFile = function(p) {
+    var archive, asarPath, buffer, fd, filePath, info, isAsar, realPath, ref;
+    ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+    if (!isAsar) {
+      return internalModuleReadFile(p);
+    }
+    archive = getOrCreateArchive(asarPath);
+    if (!archive) {
+      return void 0;
+    }
+    info = archive.getFileInfo(filePath);
+    if (!info) {
+      return void 0;
+    }
+    if (info.size === 0) {
+      return '';
+    }
+    if (info.unpacked) {
+      realPath = archive.copyFileOut(filePath);
+      return fs.readFileSync(realPath, {
+        encoding: 'utf8'
+      });
+    }
+    buffer = new Buffer(info.size);
+    fd = archive.getFd();
+    if (!(fd >= 0)) {
+      return void 0;
+    }
+    fs.readSync(fd, buffer, 0, info.size, info.offset);
+    return buffer.toString('utf8');
+  };
+  internalModuleStat = process.binding('fs').internalModuleStat;
+  process.binding('fs').internalModuleStat = function(p) {
+    var archive, asarPath, filePath, isAsar, ref, stats;
+    ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+    if (!isAsar) {
+      return internalModuleStat(p);
+    }
+    archive = getOrCreateArchive(asarPath);
+
+    /* -ENOENT */
+    if (!archive) {
+      return -34;
+    }
+    stats = archive.stat(filePath);
+
+    /* -ENOENT */
+    if (!stats) {
+      return -34;
+    }
+    if (stats.isDirectory) {
+      return 1;
+    } else {
+      return 0;
+    }
+  };
+
+  /*
+    Calling mkdir for directory inside asar archive should throw ENOTDIR
+    error, but on Windows it throws ENOENT.
+    This is to work around the recursive looping bug of mkdirp since it is
+    widely used.
+   */
+  if (process.platform === 'win32') {
+    mkdir = fs.mkdir;
+    fs.mkdir = function(p, mode, callback) {
+      var asarPath, filePath, isAsar, ref;
+      if (typeof mode === 'function') {
+        callback = mode;
+      }
+      ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+      if (isAsar && filePath.length) {
+        return notDirError(callback);
+      }
+      return mkdir(p, mode, callback);
+    };
+    mkdirSync = fs.mkdirSync;
+    fs.mkdirSync = function(p, mode) {
+      var asarPath, filePath, isAsar, ref;
+      ref = splitPath(p), isAsar = ref[0], asarPath = ref[1], filePath = ref[2];
+      if (isAsar && filePath.length) {
+        notDirError();
+      }
+      return mkdirSync(p, mode);
+    };
+  }
+  overrideAPI(fs, 'open');
+  overrideAPI(child_process, 'execFile');
+  overrideAPISync(process, 'dlopen', 1);
+  overrideAPISync(require('module')._extensions, '.node', 1);
+  overrideAPISync(fs, 'openSync');
+  return overrideAPISync(child_process, 'execFileSync');
+};
+})()

+ 0 - 22
atom/common/lib/asar_init.coffee

@@ -1,22 +0,0 @@
-return (process, require, asarSource) ->
-  {createArchive} = process.binding 'atom_common_asar'
-
-  # Make asar.coffee accessible via "require".
-  process.binding('natives').ATOM_SHELL_ASAR = asarSource
-
-  # Monkey-patch the fs module.
-  require('ATOM_SHELL_ASAR').wrapFsWithAsar require('fs')
-
-  # Make graceful-fs work with asar.
-  source = process.binding 'natives'
-  source['original-fs'] = source.fs
-  source['fs'] = """
-    var src = '(function (exports, require, module, __filename, __dirname) { ' +
-              process.binding('natives')['original-fs'] +
-              ' });';
-    var vm = require('vm');
-    var fn = vm.runInThisContext(src, { filename: 'fs.js' });
-    fn(exports, require, module);
-    var asar = require('ATOM_SHELL_ASAR');
-    asar.wrapFsWithAsar(exports);
-  """

+ 17 - 0
atom/common/lib/asar_init.js

@@ -0,0 +1,17 @@
+(function () {
+return function(process, require, asarSource) {
+  var createArchive, source;
+  createArchive = process.binding('atom_common_asar').createArchive;
+
+  /* Make asar.coffee accessible via "require". */
+  process.binding('natives').ATOM_SHELL_ASAR = asarSource;
+
+  /* Monkey-patch the fs module. */
+  require('ATOM_SHELL_ASAR').wrapFsWithAsar(require('fs'));
+
+  /* Make graceful-fs work with asar. */
+  source = process.binding('natives');
+  source['original-fs'] = source.fs;
+  return source['fs'] = "var src = '(function (exports, require, module, __filename, __dirname) { ' +\n          process.binding('natives')['original-fs'] +\n          ' });';\nvar vm = require('vm');\nvar fn = vm.runInThisContext(src, { filename: 'fs.js' });\nfn(exports, require, module);\nvar asar = require('ATOM_SHELL_ASAR');\nasar.wrapFsWithAsar(exports);";
+};
+})()

+ 0 - 36
atom/common/lib/init.coffee

@@ -1,36 +0,0 @@
-fs     = require 'fs'
-path   = require 'path'
-timers = require 'timers'
-Module = require 'module'
-
-process.atomBinding = (name) ->
-  try
-    process.binding "atom_#{process.type}_#{name}"
-  catch e
-    process.binding "atom_common_#{name}" if /No such module/.test e.message
-
-unless process.env.ELECTRON_HIDE_INTERNAL_MODULES
-  # Add common/api/lib to module search paths.
-  Module.globalPaths.push path.resolve(__dirname, '..', 'api', 'lib')
-
-# setImmediate and process.nextTick makes use of uv_check and uv_prepare to
-# run the callbacks, however since we only run uv loop on requests, the
-# callbacks wouldn't be called until something else activated the uv loop,
-# which would delay the callbacks for arbitrary long time. So we should
-# initiatively activate the uv loop once setImmediate and process.nextTick is
-# called.
-wrapWithActivateUvLoop = (func) ->
-  ->
-    process.activateUvLoop()
-    func.apply this, arguments
-process.nextTick = wrapWithActivateUvLoop process.nextTick
-global.setImmediate = wrapWithActivateUvLoop timers.setImmediate
-global.clearImmediate = timers.clearImmediate
-
-if process.type is 'browser'
-  # setTimeout needs to update the polling timeout of the event loop, when
-  # called under Chromium's event loop the node's event loop won't get a chance
-  # to update the timeout, so we have to force the node's event loop to
-  # recalculate the timeout in browser process.
-  global.setTimeout = wrapWithActivateUvLoop timers.setTimeout
-  global.setInterval = wrapWithActivateUvLoop timers.setInterval

+ 62 - 0
atom/common/lib/init.js

@@ -0,0 +1,62 @@
+var Module, fs, path, timers, wrapWithActivateUvLoop;
+
+fs = require('fs');
+
+path = require('path');
+
+timers = require('timers');
+
+Module = require('module');
+
+process.atomBinding = function(name) {
+  var e, error;
+  try {
+    return process.binding("atom_" + process.type + "_" + name);
+  } catch (error) {
+    e = error;
+    if (/No such module/.test(e.message)) {
+      return process.binding("atom_common_" + name);
+    }
+  }
+};
+
+if (!process.env.ELECTRON_HIDE_INTERNAL_MODULES) {
+
+  /* Add common/api/lib to module search paths. */
+  Module.globalPaths.push(path.resolve(__dirname, '..', 'api', 'lib'));
+}
+
+
+/*
+  setImmediate and process.nextTick makes use of uv_check and uv_prepare to
+  run the callbacks, however since we only run uv loop on requests, the
+  callbacks wouldn't be called until something else activated the uv loop,
+  which would delay the callbacks for arbitrary long time. So we should
+  initiatively activate the uv loop once setImmediate and process.nextTick is
+  called.
+ */
+
+wrapWithActivateUvLoop = function(func) {
+  return function() {
+    process.activateUvLoop();
+    return func.apply(this, arguments);
+  };
+};
+
+process.nextTick = wrapWithActivateUvLoop(process.nextTick);
+
+global.setImmediate = wrapWithActivateUvLoop(timers.setImmediate);
+
+global.clearImmediate = timers.clearImmediate;
+
+if (process.type === 'browser') {
+
+  /*
+    setTimeout needs to update the polling timeout of the event loop, when
+    called under Chromium's event loop the node's event loop won't get a chance
+    to update the timeout, so we have to force the node's event loop to
+    recalculate the timeout in browser process.
+   */
+  global.setTimeout = wrapWithActivateUvLoop(timers.setTimeout);
+  global.setInterval = wrapWithActivateUvLoop(timers.setInterval);
+}

+ 0 - 29
atom/common/lib/reset-search-paths.coffee

@@ -1,29 +0,0 @@
-path   = require 'path'
-Module = require 'module'
-
-# Clear Node's global search paths.
-Module.globalPaths.length = 0
-
-# Clear current and parent(init.coffee)'s search paths.
-module.paths = []
-module.parent.paths = []
-
-# Prevent Node from adding paths outside this app to search paths.
-Module._nodeModulePaths = (from) ->
-  from = path.resolve from
-
-  # If "from" is outside the app then we do nothing.
-  skipOutsidePaths = from.startsWith process.resourcesPath
-
-  # Following logoic is copied from module.js.
-  splitRe = if process.platform is 'win32' then /[\/\\]/ else /\//
-  paths = []
-
-  parts = from.split splitRe
-  for part, tip in parts by -1
-    continue if part is 'node_modules'
-    dir = parts.slice(0, tip + 1).join path.sep
-    break if skipOutsidePaths and not dir.startsWith process.resourcesPath
-    paths.push path.join(dir, 'node_modules')
-
-  paths

+ 45 - 0
atom/common/lib/reset-search-paths.js

@@ -0,0 +1,45 @@
+var Module, path;
+
+path = require('path');
+
+Module = require('module');
+
+
+/* Clear Node's global search paths. */
+
+Module.globalPaths.length = 0;
+
+
+/* Clear current and parent(init.coffee)'s search paths. */
+
+module.paths = [];
+
+module.parent.paths = [];
+
+
+/* Prevent Node from adding paths outside this app to search paths. */
+
+Module._nodeModulePaths = function(from) {
+  var dir, i, part, parts, paths, skipOutsidePaths, splitRe, tip;
+  from = path.resolve(from);
+
+  /* If "from" is outside the app then we do nothing. */
+  skipOutsidePaths = from.startsWith(process.resourcesPath);
+
+  /* Following logoic is copied from module.js. */
+  splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//;
+  paths = [];
+  parts = from.split(splitRe);
+  for (tip = i = parts.length - 1; i >= 0; tip = i += -1) {
+    part = parts[tip];
+    if (part === 'node_modules') {
+      continue;
+    }
+    dir = parts.slice(0, tip + 1).join(path.sep);
+    if (skipOutsidePaths && !dir.startsWith(process.resourcesPath)) {
+      break;
+    }
+    paths.push(path.join(dir, 'node_modules'));
+  }
+  return paths;
+};

+ 0 - 20
atom/renderer/api/lib/desktop-capturer.coffee

@@ -1,20 +0,0 @@
-{ipcRenderer, nativeImage} = require 'electron'
-
-nextId = 0
-getNextId = -> ++nextId
-
-# |options.type| can not be empty and has to include 'window' or 'screen'.
-isValid = (options) ->
-  return options?.types? and Array.isArray options.types
-
-exports.getSources = (options, callback) ->
-  return callback new Error('Invalid options') unless isValid options
-
-  captureWindow = 'window' in options.types
-  captureScreen = 'screen' in options.types
-  options.thumbnailSize ?= width: 150, height: 150
-
-  id = getNextId()
-  ipcRenderer.send 'ATOM_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', captureWindow, captureScreen, options.thumbnailSize, id
-  ipcRenderer.once "ATOM_RENDERER_DESKTOP_CAPTURER_RESULT_#{id}", (event, sources) ->
-    callback null, ({id: source.id, name: source.name, thumbnail: nativeImage.createFromDataURL source.thumbnail} for source in sources)

+ 50 - 0
atom/renderer/api/lib/desktop-capturer.js

@@ -0,0 +1,50 @@
+var getNextId, ipcRenderer, isValid, nativeImage, nextId, ref,
+  indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+ref = require('electron'), ipcRenderer = ref.ipcRenderer, nativeImage = ref.nativeImage;
+
+nextId = 0;
+
+getNextId = function() {
+  return ++nextId;
+};
+
+
+/* |options.type| can not be empty and has to include 'window' or 'screen'. */
+
+isValid = function(options) {
+  return ((options != null ? options.types : void 0) != null) && Array.isArray(options.types);
+};
+
+exports.getSources = function(options, callback) {
+  var captureScreen, captureWindow, id;
+  if (!isValid(options)) {
+    return callback(new Error('Invalid options'));
+  }
+  captureWindow = indexOf.call(options.types, 'window') >= 0;
+  captureScreen = indexOf.call(options.types, 'screen') >= 0;
+  if (options.thumbnailSize == null) {
+    options.thumbnailSize = {
+      width: 150,
+      height: 150
+    };
+  }
+  id = getNextId();
+  ipcRenderer.send('ATOM_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', captureWindow, captureScreen, options.thumbnailSize, id);
+  return ipcRenderer.once("ATOM_RENDERER_DESKTOP_CAPTURER_RESULT_" + id, function(event, sources) {
+    var source;
+    return callback(null, (function() {
+      var i, len, results;
+      results = [];
+      for (i = 0, len = sources.length; i < len; i++) {
+        source = sources[i];
+        results.push({
+          id: source.id,
+          name: source.name,
+          thumbnail: nativeImage.createFromDataURL(source.thumbnail)
+        });
+      }
+      return results;
+    })());
+  });
+};

+ 0 - 22
atom/renderer/api/lib/exports/electron.coffee

@@ -1,22 +0,0 @@
-common = require '../../../../common/api/lib/exports/electron'
-
-# Import common modules.
-common.defineProperties exports
-
-Object.defineProperties exports,
-  # Renderer side modules, please sort with alphabet order.
-  desktopCapturer:
-    enumerable: true
-    get: -> require '../desktop-capturer'
-  ipcRenderer:
-    enumerable: true
-    get: -> require '../ipc-renderer'
-  remote:
-    enumerable: true
-    get: -> require '../remote'
-  screen:
-    enumerable: true
-    get: -> require '../screen'
-  webFrame:
-    enumerable: true
-    get: -> require '../web-frame'

+ 43 - 0
atom/renderer/api/lib/exports/electron.js

@@ -0,0 +1,43 @@
+var common;
+
+common = require('../../../../common/api/lib/exports/electron');
+
+
+/* Import common modules. */
+
+common.defineProperties(exports);
+
+Object.defineProperties(exports, {
+
+  /* Renderer side modules, please sort with alphabet order. */
+  desktopCapturer: {
+    enumerable: true,
+    get: function() {
+      return require('../desktop-capturer');
+    }
+  },
+  ipcRenderer: {
+    enumerable: true,
+    get: function() {
+      return require('../ipc-renderer');
+    }
+  },
+  remote: {
+    enumerable: true,
+    get: function() {
+      return require('../remote');
+    }
+  },
+  screen: {
+    enumerable: true,
+    get: function() {
+      return require('../screen');
+    }
+  },
+  webFrame: {
+    enumerable: true,
+    get: function() {
+      return require('../web-frame');
+    }
+  }
+});

+ 0 - 18
atom/renderer/api/lib/ipc-renderer.coffee

@@ -1,18 +0,0 @@
-{EventEmitter} = require 'events'
-
-binding = process.atomBinding 'ipc'
-v8Util  = process.atomBinding 'v8_util'
-
-# Created by init.coffee.
-ipcRenderer = v8Util.getHiddenValue global, 'ipc'
-
-ipcRenderer.send = (args...) ->
-  binding.send 'ipc-message', [args...]
-
-ipcRenderer.sendSync = (args...) ->
-  JSON.parse binding.sendSync('ipc-message-sync', [args...])
-
-ipcRenderer.sendToHost = (args...) ->
-  binding.send 'ipc-message-host', [args...]
-
-module.exports = ipcRenderer

+ 33 - 0
atom/renderer/api/lib/ipc-renderer.js

@@ -0,0 +1,33 @@
+var EventEmitter, binding, ipcRenderer, v8Util,
+  slice = [].slice;
+
+EventEmitter = require('events').EventEmitter;
+
+binding = process.atomBinding('ipc');
+
+v8Util = process.atomBinding('v8_util');
+
+
+/* Created by init.coffee. */
+
+ipcRenderer = v8Util.getHiddenValue(global, 'ipc');
+
+ipcRenderer.send = function() {
+  var args;
+  args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+  return binding.send('ipc-message', slice.call(args));
+};
+
+ipcRenderer.sendSync = function() {
+  var args;
+  args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+  return JSON.parse(binding.sendSync('ipc-message-sync', slice.call(args)));
+};
+
+ipcRenderer.sendToHost = function() {
+  var args;
+  args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+  return binding.send('ipc-message-host', slice.call(args));
+};
+
+module.exports = ipcRenderer;

+ 0 - 19
atom/renderer/api/lib/ipc.coffee

@@ -1,19 +0,0 @@
-{ipcRenderer, deprecate} = require 'electron'
-{EventEmitter} = require 'events'
-
-# This module is deprecated, we mirror everything from ipcRenderer.
-deprecate.warn 'ipc module', 'require("electron").ipcRenderer'
-
-# Routes events of ipcRenderer.
-ipc = new EventEmitter
-ipcRenderer.emit = (channel, event, args...) ->
-  ipc.emit channel, args...
-  EventEmitter::emit.apply ipcRenderer, arguments
-
-# Deprecated.
-for method of ipcRenderer when method.startsWith 'send'
-  ipc[method] = ipcRenderer[method]
-deprecate.rename ipc, 'sendChannel', 'send'
-deprecate.rename ipc, 'sendChannelSync', 'sendSync'
-
-module.exports = ipc

+ 38 - 0
atom/renderer/api/lib/ipc.js

@@ -0,0 +1,38 @@
+var EventEmitter, deprecate, ipc, ipcRenderer, method, ref,
+  slice = [].slice;
+
+ref = require('electron'), ipcRenderer = ref.ipcRenderer, deprecate = ref.deprecate;
+
+EventEmitter = require('events').EventEmitter;
+
+
+/* This module is deprecated, we mirror everything from ipcRenderer. */
+
+deprecate.warn('ipc module', 'require("electron").ipcRenderer');
+
+
+/* Routes events of ipcRenderer. */
+
+ipc = new EventEmitter;
+
+ipcRenderer.emit = function() {
+  var args, channel, event;
+  channel = arguments[0], event = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : [];
+  ipc.emit.apply(ipc, [channel].concat(slice.call(args)));
+  return EventEmitter.prototype.emit.apply(ipcRenderer, arguments);
+};
+
+
+/* Deprecated. */
+
+for (method in ipcRenderer) {
+  if (method.startsWith('send')) {
+    ipc[method] = ipcRenderer[method];
+  }
+}
+
+deprecate.rename(ipc, 'sendChannel', 'send');
+
+deprecate.rename(ipc, 'sendChannelSync', 'sendSync');
+
+module.exports = ipc;

+ 0 - 199
atom/renderer/api/lib/remote.coffee

@@ -1,199 +0,0 @@
-{ipcRenderer, CallbacksRegistry} = require 'electron'
-v8Util = process.atomBinding 'v8_util'
-
-callbacksRegistry = new CallbacksRegistry
-
-# Check for circular reference.
-isCircular = (field, visited) ->
-  if typeof field is 'object'
-    if field in visited
-      return true
-    visited.push field
-  return false
-
-# Convert the arguments object into an array of meta data.
-wrapArgs = (args, visited=[]) ->
-  valueToMeta = (value) ->
-    if Array.isArray value
-      type: 'array', value: wrapArgs(value, visited)
-    else if Buffer.isBuffer value
-      type: 'buffer', value: Array::slice.call(value, 0)
-    else if value instanceof Date
-      type: 'date', value: value.getTime()
-    else if value?.constructor.name is 'Promise'
-      type: 'promise', then: valueToMeta(value.then.bind(value))
-    else if value? and typeof value is 'object' and v8Util.getHiddenValue value, 'atomId'
-      type: 'remote-object', id: v8Util.getHiddenValue value, 'atomId'
-    else if value? and typeof value is 'object'
-      ret = type: 'object', name: value.constructor.name, members: []
-      for prop, field of value
-        ret.members.push
-          name: prop
-          value: valueToMeta(if isCircular(field, visited) then null else field)
-      ret
-    else if typeof value is 'function' and v8Util.getHiddenValue value, 'returnValue'
-      type: 'function-with-return-value', value: valueToMeta(value())
-    else if typeof value is 'function'
-      type: 'function', id: callbacksRegistry.add(value), location: v8Util.getHiddenValue value, 'location'
-    else
-      type: 'value', value: value
-
-  Array::slice.call(args).map valueToMeta
-
-# Convert meta data from browser into real value.
-metaToValue = (meta) ->
-  switch meta.type
-    when 'value' then meta.value
-    when 'array' then (metaToValue(el) for el in meta.members)
-    when 'buffer' then new Buffer(meta.value)
-    when 'promise' then Promise.resolve(then: metaToValue(meta.then))
-    when 'error' then metaToPlainObject meta
-    when 'date' then new Date(meta.value)
-    when 'exception'
-      throw new Error("#{meta.message}\n#{meta.stack}")
-    else
-      if meta.type is 'function'
-        # A shadow class to represent the remote function object.
-        ret =
-        class RemoteFunction
-          constructor: ->
-            if @constructor == RemoteFunction
-              # Constructor call.
-              obj = ipcRenderer.sendSync 'ATOM_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(arguments)
-
-              # Returning object in constructor will replace constructed object
-              # with the returned object.
-              # http://stackoverflow.com/questions/1978049/what-values-can-a-constructor-return-to-avoid-returning-this
-              return metaToValue obj
-            else
-              # Function call.
-              obj = ipcRenderer.sendSync 'ATOM_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(arguments)
-              return metaToValue obj
-      else
-        ret = v8Util.createObjectWithName meta.name
-
-      # Polulate delegate members.
-      for member in meta.members
-        if member.type is 'function'
-          ret[member.name] = createRemoteMemberFunction meta.id, member.name
-        else
-          Object.defineProperty ret, member.name, createRemoteMemberProperty(meta.id, member.name)
-
-      # Track delegate object's life time, and tell the browser to clean up
-      # when the object is GCed.
-      v8Util.setDestructor ret, ->
-        ipcRenderer.send 'ATOM_BROWSER_DEREFERENCE', meta.id
-
-      # Remember object's id.
-      v8Util.setHiddenValue ret, 'atomId', meta.id
-
-      ret
-
-# Construct a plain object from the meta.
-metaToPlainObject = (meta) ->
-  obj = switch meta.type
-    when 'error' then new Error
-    else {}
-  obj[name] = value for {name, value} in meta.members
-  obj
-
-# Create a RemoteMemberFunction instance.
-# This function's content should not be inlined into metaToValue, otherwise V8
-# may consider it circular reference.
-createRemoteMemberFunction = (metaId, name) ->
-  class RemoteMemberFunction
-    constructor: ->
-      if @constructor is RemoteMemberFunction
-        # Constructor call.
-        ret = ipcRenderer.sendSync 'ATOM_BROWSER_MEMBER_CONSTRUCTOR', metaId, name, wrapArgs(arguments)
-        return metaToValue ret
-      else
-        # Call member function.
-        ret = ipcRenderer.sendSync 'ATOM_BROWSER_MEMBER_CALL', metaId, name, wrapArgs(arguments)
-        return metaToValue ret
-
-# Create configuration for defineProperty.
-# This function's content should not be inlined into metaToValue, otherwise V8
-# may consider it circular reference.
-createRemoteMemberProperty = (metaId, name) ->
-  enumerable: true,
-  configurable: false,
-  set: (value) ->
-    # Set member data.
-    ipcRenderer.sendSync 'ATOM_BROWSER_MEMBER_SET', metaId, name, value
-    value
-  get: ->
-    # Get member data.
-    metaToValue ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_GET', metaId, name)
-
-# Browser calls a callback in renderer.
-ipcRenderer.on 'ATOM_RENDERER_CALLBACK', (event, id, args) ->
-  callbacksRegistry.apply id, metaToValue(args)
-
-# A callback in browser is released.
-ipcRenderer.on 'ATOM_RENDERER_RELEASE_CALLBACK', (event, id) ->
-  callbacksRegistry.remove id
-
-# List all built-in modules in browser process.
-browserModules = require '../../../browser/api/lib/exports/electron'
-# And add a helper receiver for each one.
-for name of browserModules
-  do (name) ->
-    Object.defineProperty exports, name, get: -> exports.getBuiltin name
-
-# Get remote module.
-# (Just like node's require, the modules are cached permanently, note that this
-#  is safe leak since the object is not expected to get freed in browser)
-moduleCache = {}
-exports.require = (module) ->
-  return moduleCache[module] if moduleCache[module]?
-
-  meta = ipcRenderer.sendSync 'ATOM_BROWSER_REQUIRE', module
-  moduleCache[module] = metaToValue meta
-
-# Optimize require('electron').
-moduleCache.electron = exports
-
-# Alias to remote.require('electron').xxx.
-builtinCache = {}
-exports.getBuiltin = (module) ->
-  return builtinCache[module] if builtinCache[module]?
-
-  meta = ipcRenderer.sendSync 'ATOM_BROWSER_GET_BUILTIN', module
-  builtinCache[module] = metaToValue meta
-
-# Get current BrowserWindow object.
-windowCache = null
-exports.getCurrentWindow = ->
-  return windowCache if windowCache?
-  meta = ipcRenderer.sendSync 'ATOM_BROWSER_CURRENT_WINDOW'
-  windowCache = metaToValue meta
-
-# Get current WebContents object.
-webContentsCache = null
-exports.getCurrentWebContents = ->
-  return webContentsCache if webContentsCache?
-  meta = ipcRenderer.sendSync 'ATOM_BROWSER_CURRENT_WEB_CONTENTS'
-  webContentsCache = metaToValue meta
-
-# Get a global object in browser.
-exports.getGlobal = (name) ->
-  meta = ipcRenderer.sendSync 'ATOM_BROWSER_GLOBAL', name
-  metaToValue meta
-
-# Get the process object in browser.
-processCache = null
-exports.__defineGetter__ 'process', ->
-  processCache = exports.getGlobal('process') unless processCache?
-  processCache
-
-# Create a funtion that will return the specifed value when called in browser.
-exports.createFunctionWithReturnValue = (returnValue) ->
-  func = -> returnValue
-  v8Util.setHiddenValue func, 'returnValue', true
-  func
-
-# Get the guest WebContents from guestInstanceId.
-exports.getGuestWebContents = (guestInstanceId) ->
-  meta = ipcRenderer.sendSync 'ATOM_BROWSER_GUEST_WEB_CONTENTS', guestInstanceId
-  metaToValue meta

+ 394 - 0
atom/renderer/api/lib/remote.js

@@ -0,0 +1,394 @@
+var CallbacksRegistry, browserModules, builtinCache, callbacksRegistry, createRemoteMemberFunction, createRemoteMemberProperty, fn, ipcRenderer, isCircular, metaToPlainObject, metaToValue, moduleCache, name, processCache, ref, v8Util, webContentsCache, windowCache, wrapArgs,
+  indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+ref = require('electron'), ipcRenderer = ref.ipcRenderer, CallbacksRegistry = ref.CallbacksRegistry;
+
+v8Util = process.atomBinding('v8_util');
+
+callbacksRegistry = new CallbacksRegistry;
+
+
+/* Check for circular reference. */
+
+isCircular = function(field, visited) {
+  if (typeof field === 'object') {
+    if (indexOf.call(visited, field) >= 0) {
+      return true;
+    }
+    visited.push(field);
+  }
+  return false;
+};
+
+
+/* Convert the arguments object into an array of meta data. */
+
+wrapArgs = function(args, visited) {
+  var valueToMeta;
+  if (visited == null) {
+    visited = [];
+  }
+  valueToMeta = function(value) {
+    var field, prop, ret;
+    if (Array.isArray(value)) {
+      return {
+        type: 'array',
+        value: wrapArgs(value, visited)
+      };
+    } else if (Buffer.isBuffer(value)) {
+      return {
+        type: 'buffer',
+        value: Array.prototype.slice.call(value, 0)
+      };
+    } else if (value instanceof Date) {
+      return {
+        type: 'date',
+        value: value.getTime()
+      };
+    } else if ((value != null ? value.constructor.name : void 0) === 'Promise') {
+      return {
+        type: 'promise',
+        then: valueToMeta(value.then.bind(value))
+      };
+    } else if ((value != null) && typeof value === 'object' && v8Util.getHiddenValue(value, 'atomId')) {
+      return {
+        type: 'remote-object',
+        id: v8Util.getHiddenValue(value, 'atomId')
+      };
+    } else if ((value != null) && typeof value === 'object') {
+      ret = {
+        type: 'object',
+        name: value.constructor.name,
+        members: []
+      };
+      for (prop in value) {
+        field = value[prop];
+        ret.members.push({
+          name: prop,
+          value: valueToMeta(isCircular(field, visited) ? null : field)
+        });
+      }
+      return ret;
+    } else if (typeof value === 'function' && v8Util.getHiddenValue(value, 'returnValue')) {
+      return {
+        type: 'function-with-return-value',
+        value: valueToMeta(value())
+      };
+    } else if (typeof value === 'function') {
+      return {
+        type: 'function',
+        id: callbacksRegistry.add(value),
+        location: v8Util.getHiddenValue(value, 'location')
+      };
+    } else {
+      return {
+        type: 'value',
+        value: value
+      };
+    }
+  };
+  return Array.prototype.slice.call(args).map(valueToMeta);
+};
+
+
+/* Convert meta data from browser into real value. */
+
+metaToValue = function(meta) {
+  var RemoteFunction, el, i, j, len, len1, member, ref1, ref2, results, ret;
+  switch (meta.type) {
+    case 'value':
+      return meta.value;
+    case 'array':
+      ref1 = meta.members;
+      results = [];
+      for (i = 0, len = ref1.length; i < len; i++) {
+        el = ref1[i];
+        results.push(metaToValue(el));
+      }
+      return results;
+    case 'buffer':
+      return new Buffer(meta.value);
+    case 'promise':
+      return Promise.resolve({
+        then: metaToValue(meta.then)
+      });
+    case 'error':
+      return metaToPlainObject(meta);
+    case 'date':
+      return new Date(meta.value);
+    case 'exception':
+      throw new Error(meta.message + "\n" + meta.stack);
+      break;
+    default:
+      if (meta.type === 'function') {
+
+        /* A shadow class to represent the remote function object. */
+        ret = RemoteFunction = (function() {
+          function RemoteFunction() {
+            var obj;
+            if (this.constructor === RemoteFunction) {
+
+              /* Constructor call. */
+              obj = ipcRenderer.sendSync('ATOM_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(arguments));
+
+              /*
+                Returning object in constructor will replace constructed object
+                with the returned object.
+                http://stackoverflow.com/questions/1978049/what-values-can-a-constructor-return-to-avoid-returning-this
+               */
+              return metaToValue(obj);
+            } else {
+
+              /* Function call. */
+              obj = ipcRenderer.sendSync('ATOM_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(arguments));
+              return metaToValue(obj);
+            }
+          }
+
+          return RemoteFunction;
+
+        })();
+      } else {
+        ret = v8Util.createObjectWithName(meta.name);
+      }
+
+      /* Polulate delegate members. */
+      ref2 = meta.members;
+      for (j = 0, len1 = ref2.length; j < len1; j++) {
+        member = ref2[j];
+        if (member.type === 'function') {
+          ret[member.name] = createRemoteMemberFunction(meta.id, member.name);
+        } else {
+          Object.defineProperty(ret, member.name, createRemoteMemberProperty(meta.id, member.name));
+        }
+      }
+
+      /*
+        Track delegate object's life time, and tell the browser to clean up
+        when the object is GCed.
+       */
+      v8Util.setDestructor(ret, function() {
+        return ipcRenderer.send('ATOM_BROWSER_DEREFERENCE', meta.id);
+      });
+
+      /* Remember object's id. */
+      v8Util.setHiddenValue(ret, 'atomId', meta.id);
+      return ret;
+  }
+};
+
+
+/* Construct a plain object from the meta. */
+
+metaToPlainObject = function(meta) {
+  var i, len, name, obj, ref1, ref2, value;
+  obj = (function() {
+    switch (meta.type) {
+      case 'error':
+        return new Error;
+      default:
+        return {};
+    }
+  })();
+  ref1 = meta.members;
+  for (i = 0, len = ref1.length; i < len; i++) {
+    ref2 = ref1[i], name = ref2.name, value = ref2.value;
+    obj[name] = value;
+  }
+  return obj;
+};
+
+
+/*
+  Create a RemoteMemberFunction instance.
+  This function's content should not be inlined into metaToValue, otherwise V8
+  may consider it circular reference.
+ */
+
+createRemoteMemberFunction = function(metaId, name) {
+  var RemoteMemberFunction;
+  return RemoteMemberFunction = (function() {
+    function RemoteMemberFunction() {
+      var ret;
+      if (this.constructor === RemoteMemberFunction) {
+
+        /* Constructor call. */
+        ret = ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_CONSTRUCTOR', metaId, name, wrapArgs(arguments));
+        return metaToValue(ret);
+      } else {
+
+        /* Call member function. */
+        ret = ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_CALL', metaId, name, wrapArgs(arguments));
+        return metaToValue(ret);
+      }
+    }
+
+    return RemoteMemberFunction;
+
+  })();
+};
+
+
+/*
+  Create configuration for defineProperty.
+  This function's content should not be inlined into metaToValue, otherwise V8
+  may consider it circular reference.
+ */
+
+createRemoteMemberProperty = function(metaId, name) {
+  return {
+    enumerable: true,
+    configurable: false,
+    set: function(value) {
+
+      /* Set member data. */
+      ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_SET', metaId, name, value);
+      return value;
+    },
+    get: function() {
+
+      /* Get member data. */
+      return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_GET', metaId, name));
+    }
+  };
+};
+
+
+/* Browser calls a callback in renderer. */
+
+ipcRenderer.on('ATOM_RENDERER_CALLBACK', function(event, id, args) {
+  return callbacksRegistry.apply(id, metaToValue(args));
+});
+
+
+/* A callback in browser is released. */
+
+ipcRenderer.on('ATOM_RENDERER_RELEASE_CALLBACK', function(event, id) {
+  return callbacksRegistry.remove(id);
+});
+
+
+/* List all built-in modules in browser process. */
+
+browserModules = require('../../../browser/api/lib/exports/electron');
+
+
+/* And add a helper receiver for each one. */
+
+fn = function(name) {
+  return Object.defineProperty(exports, name, {
+    get: function() {
+      return exports.getBuiltin(name);
+    }
+  });
+};
+for (name in browserModules) {
+  fn(name);
+}
+
+
+/*
+  Get remote module.
+  (Just like node's require, the modules are cached permanently, note that this
+  is safe leak since the object is not expected to get freed in browser)
+ */
+
+moduleCache = {};
+
+exports.require = function(module) {
+  var meta;
+  if (moduleCache[module] != null) {
+    return moduleCache[module];
+  }
+  meta = ipcRenderer.sendSync('ATOM_BROWSER_REQUIRE', module);
+  return moduleCache[module] = metaToValue(meta);
+};
+
+
+/* Optimize require('electron'). */
+
+moduleCache.electron = exports;
+
+
+/* Alias to remote.require('electron').xxx. */
+
+builtinCache = {};
+
+exports.getBuiltin = function(module) {
+  var meta;
+  if (builtinCache[module] != null) {
+    return builtinCache[module];
+  }
+  meta = ipcRenderer.sendSync('ATOM_BROWSER_GET_BUILTIN', module);
+  return builtinCache[module] = metaToValue(meta);
+};
+
+
+/* Get current BrowserWindow object. */
+
+windowCache = null;
+
+exports.getCurrentWindow = function() {
+  var meta;
+  if (windowCache != null) {
+    return windowCache;
+  }
+  meta = ipcRenderer.sendSync('ATOM_BROWSER_CURRENT_WINDOW');
+  return windowCache = metaToValue(meta);
+};
+
+
+/* Get current WebContents object. */
+
+webContentsCache = null;
+
+exports.getCurrentWebContents = function() {
+  var meta;
+  if (webContentsCache != null) {
+    return webContentsCache;
+  }
+  meta = ipcRenderer.sendSync('ATOM_BROWSER_CURRENT_WEB_CONTENTS');
+  return webContentsCache = metaToValue(meta);
+};
+
+
+/* Get a global object in browser. */
+
+exports.getGlobal = function(name) {
+  var meta;
+  meta = ipcRenderer.sendSync('ATOM_BROWSER_GLOBAL', name);
+  return metaToValue(meta);
+};
+
+
+/* Get the process object in browser. */
+
+processCache = null;
+
+exports.__defineGetter__('process', function() {
+  if (processCache == null) {
+    processCache = exports.getGlobal('process');
+  }
+  return processCache;
+});
+
+
+/* Create a funtion that will return the specifed value when called in browser. */
+
+exports.createFunctionWithReturnValue = function(returnValue) {
+  var func;
+  func = function() {
+    return returnValue;
+  };
+  v8Util.setHiddenValue(func, 'returnValue', true);
+  return func;
+};
+
+
+/* Get the guest WebContents from guestInstanceId. */
+
+exports.getGuestWebContents = function(guestInstanceId) {
+  var meta;
+  meta = ipcRenderer.sendSync('ATOM_BROWSER_GUEST_WEB_CONTENTS', guestInstanceId);
+  return metaToValue(meta);
+};

+ 0 - 1
atom/renderer/api/lib/screen.coffee

@@ -1 +0,0 @@
-module.exports = require('electron').remote.screen

+ 1 - 0
atom/renderer/api/lib/screen.js

@@ -0,0 +1 @@
+module.exports = require('electron').remote.screen;

+ 0 - 9
atom/renderer/api/lib/web-frame.coffee

@@ -1,9 +0,0 @@
-{deprecate} = require 'electron'
-{webFrame} = process.atomBinding 'web_frame'
-
-# Deprecated.
-deprecate.rename webFrame, 'registerUrlSchemeAsSecure', 'registerURLSchemeAsSecure'
-deprecate.rename webFrame, 'registerUrlSchemeAsBypassingCSP', 'registerURLSchemeAsBypassingCSP'
-deprecate.rename webFrame, 'registerUrlSchemeAsPrivileged', 'registerURLSchemeAsPrivileged'
-
-module.exports = webFrame

+ 16 - 0
atom/renderer/api/lib/web-frame.js

@@ -0,0 +1,16 @@
+var deprecate, webFrame;
+
+deprecate = require('electron').deprecate;
+
+webFrame = process.atomBinding('web_frame').webFrame;
+
+
+/* Deprecated. */
+
+deprecate.rename(webFrame, 'registerUrlSchemeAsSecure', 'registerURLSchemeAsSecure');
+
+deprecate.rename(webFrame, 'registerUrlSchemeAsBypassingCSP', 'registerURLSchemeAsBypassingCSP');
+
+deprecate.rename(webFrame, 'registerUrlSchemeAsPrivileged', 'registerURLSchemeAsPrivileged');
+
+module.exports = webFrame;

+ 0 - 10
atom/renderer/lib/chrome-api.coffee

@@ -1,10 +0,0 @@
-url = require 'url'
-
-chrome = window.chrome = window.chrome || {}
-chrome.extension =
-  getURL: (path) ->
-    url.format
-      protocol: location.protocol
-      slashes: true
-      hostname: location.hostname
-      pathname: path

+ 16 - 0
atom/renderer/lib/chrome-api.js

@@ -0,0 +1,16 @@
+var chrome, url;
+
+url = require('url');
+
+chrome = window.chrome = window.chrome || {};
+
+chrome.extension = {
+  getURL: function(path) {
+    return url.format({
+      protocol: location.protocol,
+      slashes: true,
+      hostname: location.hostname,
+      pathname: path
+    });
+  }
+};

+ 0 - 109
atom/renderer/lib/init.coffee

@@ -1,109 +0,0 @@
-events = require 'events'
-path   = require 'path'
-url    = require 'url'
-Module = require 'module'
-
-# We modified the original process.argv to let node.js load the
-# atom-renderer.js, we need to restore it here.
-process.argv.splice 1, 1
-
-# Clear search paths.
-require path.resolve(__dirname, '..', '..', 'common', 'lib', 'reset-search-paths')
-
-# Import common settings.
-require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init')
-
-globalPaths = Module.globalPaths
-unless process.env.ELECTRON_HIDE_INTERNAL_MODULES
-  globalPaths.push path.resolve(__dirname, '..', 'api', 'lib')
-
-# Expose public APIs.
-globalPaths.push path.resolve(__dirname, '..', 'api', 'lib', 'exports')
-
-# The global variable will be used by ipc for event dispatching
-v8Util = process.atomBinding 'v8_util'
-v8Util.setHiddenValue global, 'ipc', new events.EventEmitter
-
-# Process command line arguments.
-nodeIntegration = 'false'
-for arg in process.argv
-  if arg.indexOf('--guest-instance-id=') == 0
-    # This is a guest web view.
-    process.guestInstanceId = parseInt arg.substr(arg.indexOf('=') + 1)
-  else if arg.indexOf('--opener-id=') == 0
-    # This is a guest BrowserWindow.
-    process.openerId = parseInt arg.substr(arg.indexOf('=') + 1)
-  else if arg.indexOf('--node-integration=') == 0
-    nodeIntegration = arg.substr arg.indexOf('=') + 1
-  else if arg.indexOf('--preload=') == 0
-    preloadScript = arg.substr arg.indexOf('=') + 1
-
-if location.protocol is 'chrome-devtools:'
-  # Override some inspector APIs.
-  require './inspector'
-  nodeIntegration = 'true'
-else if location.protocol is 'chrome-extension:'
-  # Add implementations of chrome API.
-  require './chrome-api'
-  nodeIntegration = 'true'
-else
-  # Override default web functions.
-  require './override'
-  # Load webview tag implementation.
-  unless process.guestInstanceId?
-    require './web-view/web-view'
-    require './web-view/web-view-attributes'
-
-if nodeIntegration in ['true', 'all', 'except-iframe', 'manual-enable-iframe']
-  # Export node bindings to global.
-  global.require = require
-  global.module = module
-
-  # Set the __filename to the path of html file if it is file: protocol.
-  if window.location.protocol is 'file:'
-    pathname =
-      if process.platform is 'win32' and window.location.pathname[0] is '/'
-        window.location.pathname.substr 1
-      else
-        window.location.pathname
-    global.__filename = path.normalize decodeURIComponent(pathname)
-    global.__dirname = path.dirname global.__filename
-
-    # Set module's filename so relative require can work as expected.
-    module.filename = global.__filename
-
-    # Also search for module under the html file.
-    module.paths = module.paths.concat Module._nodeModulePaths(global.__dirname)
-  else
-    global.__filename = __filename
-    global.__dirname = __dirname
-
-  # Redirect window.onerror to uncaughtException.
-  window.onerror = (message, filename, lineno, colno, error) ->
-    if global.process.listeners('uncaughtException').length > 0
-      global.process.emit 'uncaughtException', error
-      true
-    else
-      false
-
-  # Emit the 'exit' event when page is unloading.
-  window.addEventListener 'unload', ->
-    process.emit 'exit'
-else
-  # Delete Node's symbols after the Environment has been loaded.
-  process.once 'loaded', ->
-    delete global.process
-    delete global.setImmediate
-    delete global.clearImmediate
-    delete global.global
-
-# Load the script specfied by the "preload" attribute.
-if preloadScript
-  try
-    require preloadScript
-  catch error
-    if error.code is 'MODULE_NOT_FOUND'
-      console.error "Unable to load preload script #{preloadScript}"
-    else
-      console.error(error)
-      console.error(error.stack)

+ 154 - 0
atom/renderer/lib/init.js

@@ -0,0 +1,154 @@
+var Module, arg, error, error1, events, globalPaths, i, len, nodeIntegration, path, pathname, preloadScript, ref, url, v8Util;
+
+events = require('events');
+
+path = require('path');
+
+url = require('url');
+
+Module = require('module');
+
+
+/*
+  We modified the original process.argv to let node.js load the
+  atom-renderer.js, we need to restore it here.
+ */
+
+process.argv.splice(1, 1);
+
+
+/* Clear search paths. */
+
+require(path.resolve(__dirname, '..', '..', 'common', 'lib', 'reset-search-paths'));
+
+
+/* Import common settings. */
+
+require(path.resolve(__dirname, '..', '..', 'common', 'lib', 'init'));
+
+globalPaths = Module.globalPaths;
+
+if (!process.env.ELECTRON_HIDE_INTERNAL_MODULES) {
+  globalPaths.push(path.resolve(__dirname, '..', 'api', 'lib'));
+}
+
+
+/* Expose public APIs. */
+
+globalPaths.push(path.resolve(__dirname, '..', 'api', 'lib', 'exports'));
+
+
+/* The global variable will be used by ipc for event dispatching */
+
+v8Util = process.atomBinding('v8_util');
+
+v8Util.setHiddenValue(global, 'ipc', new events.EventEmitter);
+
+
+/* Process command line arguments. */
+
+nodeIntegration = 'false';
+
+ref = process.argv;
+for (i = 0, len = ref.length; i < len; i++) {
+  arg = ref[i];
+  if (arg.indexOf('--guest-instance-id=') === 0) {
+
+    /* This is a guest web view. */
+    process.guestInstanceId = parseInt(arg.substr(arg.indexOf('=') + 1));
+  } else if (arg.indexOf('--opener-id=') === 0) {
+
+    /* This is a guest BrowserWindow. */
+    process.openerId = parseInt(arg.substr(arg.indexOf('=') + 1));
+  } else if (arg.indexOf('--node-integration=') === 0) {
+    nodeIntegration = arg.substr(arg.indexOf('=') + 1);
+  } else if (arg.indexOf('--preload=') === 0) {
+    preloadScript = arg.substr(arg.indexOf('=') + 1);
+  }
+}
+
+if (location.protocol === 'chrome-devtools:') {
+
+  /* Override some inspector APIs. */
+  require('./inspector');
+  nodeIntegration = 'true';
+} else if (location.protocol === 'chrome-extension:') {
+
+  /* Add implementations of chrome API. */
+  require('./chrome-api');
+  nodeIntegration = 'true';
+} else {
+
+  /* Override default web functions. */
+  require('./override');
+
+  /* Load webview tag implementation. */
+  if (process.guestInstanceId == null) {
+    require('./web-view/web-view');
+    require('./web-view/web-view-attributes');
+  }
+}
+
+if (nodeIntegration === 'true' || nodeIntegration === 'all' || nodeIntegration === 'except-iframe' || nodeIntegration === 'manual-enable-iframe') {
+
+  /* Export node bindings to global. */
+  global.require = require;
+  global.module = module;
+
+  /* Set the __filename to the path of html file if it is file: protocol. */
+  if (window.location.protocol === 'file:') {
+    pathname = process.platform === 'win32' && window.location.pathname[0] === '/' ? window.location.pathname.substr(1) : window.location.pathname;
+    global.__filename = path.normalize(decodeURIComponent(pathname));
+    global.__dirname = path.dirname(global.__filename);
+
+    /* Set module's filename so relative require can work as expected. */
+    module.filename = global.__filename;
+
+    /* Also search for module under the html file. */
+    module.paths = module.paths.concat(Module._nodeModulePaths(global.__dirname));
+  } else {
+    global.__filename = __filename;
+    global.__dirname = __dirname;
+  }
+
+  /* Redirect window.onerror to uncaughtException. */
+  window.onerror = function(message, filename, lineno, colno, error) {
+    if (global.process.listeners('uncaughtException').length > 0) {
+      global.process.emit('uncaughtException', error);
+      return true;
+    } else {
+      return false;
+    }
+  };
+
+  /* Emit the 'exit' event when page is unloading. */
+  window.addEventListener('unload', function() {
+    return process.emit('exit');
+  });
+} else {
+
+  /* Delete Node's symbols after the Environment has been loaded. */
+  process.once('loaded', function() {
+    delete global.process;
+    delete global.setImmediate;
+    delete global.clearImmediate;
+    return delete global.global;
+  });
+}
+
+
+/* Load the script specfied by the "preload" attribute. */
+
+if (preloadScript) {
+  try {
+    require(preloadScript);
+  } catch (error1) {
+    error = error1;
+    if (error.code === 'MODULE_NOT_FOUND') {
+      console.error("Unable to load preload script " + preloadScript);
+    } else {
+      console.error(error);
+      console.error(error.stack);
+    }
+  }
+}

+ 0 - 60
atom/renderer/lib/inspector.coffee

@@ -1,60 +0,0 @@
-window.onload = ->
-  # Use menu API to show context menu.
-  InspectorFrontendHost.showContextMenuAtPoint = createMenu
-
-  # Use dialog API to override file chooser dialog.
-  WebInspector.createFileSelectorElement = createFileSelectorElement
-
-convertToMenuTemplate = (items) ->
-  template = []
-  for item in items
-    do (item) ->
-      transformed =
-        if item.type is 'subMenu'
-          type: 'submenu'
-          label: item.label
-          enabled: item.enabled
-          submenu: convertToMenuTemplate item.subItems
-        else if item.type is 'separator'
-          type: 'separator'
-        else if item.type is 'checkbox'
-          type: 'checkbox'
-          label: item.label
-          enabled: item.enabled
-          checked: item.checked
-        else
-          type: 'normal'
-          label: item.label
-          enabled: item.enabled
-      if item.id?
-        transformed.click = ->
-          DevToolsAPI.contextMenuItemSelected item.id
-          DevToolsAPI.contextMenuCleared()
-      template.push transformed
-  template
-
-createMenu = (x, y, items, document) ->
-  {remote} = require 'electron'
-  {Menu} = remote
-
-  menu = Menu.buildFromTemplate convertToMenuTemplate(items)
-  # The menu is expected to show asynchronously.
-  setTimeout -> menu.popup remote.getCurrentWindow()
-
-showFileChooserDialog = (callback) ->
-  {remote} = require 'electron'
-  {dialog} = remote
-  files = dialog.showOpenDialog {}
-  callback pathToHtml5FileObject files[0] if files?
-
-pathToHtml5FileObject = (path) ->
-  fs = require 'fs'
-  blob = new Blob([fs.readFileSync(path)])
-  blob.name = path
-  blob
-
-createFileSelectorElement = (callback) ->
-  fileSelectorElement = document.createElement 'span'
-  fileSelectorElement.style.display = 'none'
-  fileSelectorElement.click = showFileChooserDialog.bind this, callback
-  return fileSelectorElement

Some files were not shown because too many files changed in this diff