Merge pull request #3428 from atom/remote-enhance

Make it easier to use browser side modules
This commit is contained in:
Cheng Zhao 2015-11-14 00:26:03 +08:00
commit fe214e0806
12 changed files with 35 additions and 38 deletions

View file

@ -1,9 +1,6 @@
# Import common modules. # Import common modules.
module.exports = require '../../../../common/api/lib/exports/electron' module.exports = require '../../../../common/api/lib/exports/electron'
v8Util = process.atomBinding 'v8_util'
v8Util.setHiddenValue module.exports, 'electronModule', true
Object.defineProperties module.exports, Object.defineProperties module.exports,
# Browser side modules, please sort with alphabet order. # Browser side modules, please sort with alphabet order.
app: app:
@ -45,7 +42,7 @@ Object.defineProperties module.exports,
screen: screen:
enumerable: true enumerable: true
get: -> require '../screen' get: -> require '../screen'
tray: Tray:
enumerable: true enumerable: true
get: -> require '../tray' get: -> require '../tray'
# The internal modules, invisible unless you know their names. # The internal modules, invisible unless you know their names.

View file

@ -18,10 +18,6 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) ->
meta.type = 'date' if value instanceof Date meta.type = 'date' if value instanceof Date
meta.type = 'promise' if value?.constructor.name is 'Promise' meta.type = 'promise' if value?.constructor.name is 'Promise'
# require('electron').
if meta.type is 'object' and v8Util.getHiddenValue value, 'electronModule'
meta.type = 'electronModule'
# Treat simple objects as value. # Treat simple objects as value.
if optimizeSimpleObject and meta.type is 'object' and v8Util.getHiddenValue value, 'simple' if optimizeSimpleObject and meta.type is 'object' and v8Util.getHiddenValue value, 'simple'
meta.type = 'value' meta.type = 'value'
@ -49,8 +45,6 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) ->
meta.members = plainObjectToMeta value meta.members = plainObjectToMeta value
else if meta.type is 'date' else if meta.type is 'date'
meta.value = value.getTime() meta.value = value.getTime()
else if meta.type is 'electronModule'
meta.members = (name for name of value)
else else
meta.type = 'value' meta.type = 'value'
meta.value = value meta.value = value
@ -212,3 +206,6 @@ ipcMain.on 'ATOM_BROWSER_GUEST_WEB_CONTENTS', (event, guestInstanceId) ->
event.returnValue = valueToMeta event.sender, guestViewManager.getGuest(guestInstanceId) event.returnValue = valueToMeta event.sender, guestViewManager.getGuest(guestInstanceId)
catch e catch e
event.returnValue = exceptionToMeta e event.returnValue = exceptionToMeta e
ipcMain.on 'ATOM_BROWSER_LIST_MODULES', (event) ->
event.returnValue = (name for name of electron)

View file

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

View file

@ -16,11 +16,7 @@ class CrashReporter
submitURL ?= options.submitUrl submitURL ?= options.submitUrl
deprecate.warn 'submitUrl', 'submitURL' deprecate.warn 'submitUrl', 'submitURL'
{app} = {app} = if process.type is 'browser' then electron else electron.remote
if process.type is 'browser'
electron
else
electron.remote.require 'electron'
@productName ?= app.getName() @productName ?= app.getName()
companyName ?= 'GitHub, Inc' companyName ?= 'GitHub, Inc'

View file

@ -49,15 +49,6 @@ metaToValue = (meta) ->
when 'date' then new Date(meta.value) when 'date' then new Date(meta.value)
when 'exception' when 'exception'
throw new Error("#{meta.message}\n#{meta.stack}") throw new Error("#{meta.message}\n#{meta.stack}")
when 'electronModule'
# require('electron').
ret = {}
for member in meta.members
do (member) ->
Object.defineProperty ret, member,
enumerable: true
get: -> exports.getBuiltin member
ret
else else
if meta.type is 'function' if meta.type is 'function'
# A shadow class to represent the remote function object. # A shadow class to represent the remote function object.
@ -134,6 +125,13 @@ ipcRenderer.on 'ATOM_RENDERER_CALLBACK', (event, id, args) ->
ipcRenderer.on 'ATOM_RENDERER_RELEASE_CALLBACK', (event, id) -> ipcRenderer.on 'ATOM_RENDERER_RELEASE_CALLBACK', (event, id) ->
callbacksRegistry.remove id callbacksRegistry.remove id
# List all built-in modules in browser process.
browserModules = ipcRenderer.sendSync 'ATOM_BROWSER_LIST_MODULES'
# And add a helper receiver for each one.
for name in browserModules
do (name) ->
Object.defineProperty exports, name, get: -> exports.getBuiltin name
# Get remote module. # Get remote module.
# (Just like node's require, the modules are cached permanently, note that this # (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) # is safe leak since the object is not expected to get freed in browser)
@ -144,6 +142,9 @@ exports.require = (module) ->
meta = ipcRenderer.sendSync 'ATOM_BROWSER_REQUIRE', module meta = ipcRenderer.sendSync 'ATOM_BROWSER_REQUIRE', module
moduleCache[module] = metaToValue meta moduleCache[module] = metaToValue meta
# Optimize require('electron').
moduleCache.electron = exports
# Alias to remote.require('electron').xxx. # Alias to remote.require('electron').xxx.
builtinCache = {} builtinCache = {}
exports.getBuiltin = (module) -> exports.getBuiltin = (module) ->

View file

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

View file

@ -33,7 +33,7 @@ convertToMenuTemplate = (items) ->
createMenu = (x, y, items, document) -> createMenu = (x, y, items, document) ->
{remote} = require 'electron' {remote} = require 'electron'
{Menu} = remote.require 'electron' {Menu} = remote
menu = Menu.buildFromTemplate convertToMenuTemplate(items) menu = Menu.buildFromTemplate convertToMenuTemplate(items)
# The menu is expected to show asynchronously. # The menu is expected to show asynchronously.
@ -43,7 +43,7 @@ createMenu = (x, y, items, document) ->
showFileChooserDialog = (callback) -> showFileChooserDialog = (callback) ->
{remote} = require 'electron' {remote} = require 'electron'
{dialog} = remote.require 'electron' {dialog} = remote
files = dialog.showOpenDialog {} files = dialog.showOpenDialog {}
callback pathToHtml5FileObject files[0] if files? callback pathToHtml5FileObject files[0] if files?

View file

@ -67,19 +67,17 @@ window.open = (url, frameName='', features='') ->
# Use the dialog API to implement alert(). # Use the dialog API to implement alert().
window.alert = (message, title='') -> window.alert = (message, title='') ->
dialog = remote.require 'dialog'
buttons = ['OK'] buttons = ['OK']
message = message.toString() message = message.toString()
dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons} remote.dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons}
# Alert should always return undefined. # Alert should always return undefined.
return return
# And the confirm(). # And the confirm().
window.confirm = (message, title='') -> window.confirm = (message, title='') ->
dialog = remote.require 'dialog'
buttons = ['OK', 'Cancel'] buttons = ['OK', 'Cancel']
cancelId = 1 cancelId = 1
not dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons, cancelId} not remote.dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons, cancelId}
# But we do not support prompt(). # But we do not support prompt().
window.prompt = -> window.prompt = ->

View file

@ -17,8 +17,8 @@ the user right clicks the page:
<!-- index.html --> <!-- index.html -->
<script> <script>
const remote = require('electron').remote; const remote = require('electron').remote;
const Menu = remote.require('electron').Menu; const Menu = remote.Menu;
const MenuItem = remote.require('electron').MenuItem; const MenuItem = remote.MenuItem;
var menu = new Menu(); var menu = new Menu();
menu.append(new MenuItem({ label: 'MenuItem1', click: function() { console.log('item 1 clicked'); } })); menu.append(new MenuItem({ label: 'MenuItem1', click: function() { console.log('item 1 clicked'); } }));

View file

@ -13,7 +13,7 @@ renderer process:
```javascript ```javascript
const remote = require('electron').remote; const remote = require('electron').remote;
const BrowserWindow = remote.require('electron').BrowserWindow; const BrowserWindow = remote.BrowserWindow;
var win = new BrowserWindow({ width: 800, height: 600 }); var win = new BrowserWindow({ width: 800, height: 600 });
win.loadURL('https://github.com'); win.loadURL('https://github.com');
@ -118,6 +118,15 @@ passed to the main process. This involves cleaning up event handlers, or
ensuring the main process is explicitly told to deference callbacks that came ensuring the main process is explicitly told to deference callbacks that came
from a renderer process that is exiting. from a renderer process that is exiting.
## Accessing built-in modules in the main process
The built-in modules in the main process are added as getters in the `remote`
module, so you can use them directly like the `electron` module.
```javascript
const app = remote.app;
```
## Methods ## Methods
The `remote` module has the following methods: The `remote` module has the following methods:

View file

@ -38,7 +38,7 @@ extra ability to use node modules:
<body> <body>
<script> <script>
const remote = require('electron').remote; const remote = require('electron').remote;
console.log(remote.require('electron').app.getVersion()); console.log(remote.app.getVersion());
</script> </script>
</body> </body>
</html> </html>

View file

@ -24,7 +24,7 @@ Then you can load the extension in Electron by opening DevTools in any window,
and running the following code in the DevTools console: and running the following code in the DevTools console:
```javascript ```javascript
const BrowserWindow = require('electron').remote.require('electron').BrowserWindow; const BrowserWindow = require('electron').remote.BrowserWindow;
BrowserWindow.addDevToolsExtension('/some-directory/react-devtools/shells/chrome'); BrowserWindow.addDevToolsExtension('/some-directory/react-devtools/shells/chrome');
``` ```