diff --git a/docs/api/dialog.md b/docs/api/dialog.md index 8cebc727e488..97ab1e212a65 100644 --- a/docs/api/dialog.md +++ b/docs/api/dialog.md @@ -106,8 +106,8 @@ will be passed via `callback(filename)` * `cancelId` Integer (optional) - The value will be returned when user cancels the dialog instead of clicking the buttons of the dialog. By default it is the index of the buttons that have "cancel" or "no" as label, or 0 if there is no such - buttons. On macOS and Windows the index of "Cancel" button will always be - used as `cancelId`, not matter whether it is already specified. + buttons. On macOS and Windows the index of the "Cancel" button will always + be used as `cancelId` even if it is specified. * `noLink` Boolean (optional) - On Windows Electron will try to figure out which one of the `buttons` are common buttons (like "Cancel" or "Yes"), and show the others as command links in the dialog. This can make the dialog appear in diff --git a/lib/browser/rpc-server.js b/lib/browser/rpc-server.js index e52546415509..b12b518888a2 100644 --- a/lib/browser/rpc-server.js +++ b/lib/browser/rpc-server.js @@ -416,3 +416,34 @@ ipcMain.on('ELECTRON_BROWSER_SEND_TO', function (event, sendToAll, webContentsId contents.send(channel, ...args) } }) + +// Implements window.alert(message, title) +ipcMain.on('ELECTRON_BROWSER_WINDOW_ALERT', function (event, message, title) { + if (message == null) message = '' + if (title == null) title = '' + + event.returnValue = electron.dialog.showMessageBox(event.sender.getOwnerBrowserWindow(), { + message: `${message}`, + title: `${title}`, + buttons: ['OK'] + }) +}) + +// Implements window.confirm(message, title) +ipcMain.on('ELECTRON_BROWSER_WINDOW_CONFIRM', function (event, message, title) { + if (message == null) message = '' + if (title == null) title = '' + + event.returnValue = !electron.dialog.showMessageBox(event.sender.getOwnerBrowserWindow(), { + message: `${message}`, + title: `${title}`, + buttons: ['OK', 'Cancel'], + cancelId: 1 + }) +}) + +// Implements window.close() +ipcMain.on('ELECTRON_BROWSER_WINDOW_CLOSE', function (event) { + event.sender.getOwnerBrowserWindow().close() + event.returnValue = null +}) diff --git a/lib/common/init.js b/lib/common/init.js index b82102cf24d2..44939b52f41b 100644 --- a/lib/common/init.js +++ b/lib/common/init.js @@ -1,11 +1,13 @@ const timers = require('timers') +const {binding} = process + process.atomBinding = function (name) { try { - return process.binding(`atom_${process.type}_${name}`) + return binding(`atom_${process.type}_${name}`) } catch (error) { if (/No such module/.test(error.message)) { - return process.binding(`atom_common_${name}`) + return binding(`atom_common_${name}`) } else { throw error } diff --git a/lib/common/parse-features-string.js b/lib/common/parse-features-string.js index a700617e6c9e..d6682f639a10 100644 --- a/lib/common/parse-features-string.js +++ b/lib/common/parse-features-string.js @@ -2,6 +2,7 @@ // - `features` input string // - `emit` function(key, value) - called for each parsed KV module.exports = function parseFeaturesString (features, emit) { + features = `${features}` // split the string by ',' features.split(/,\s*/).forEach((feature) => { // expected form is either a key by itself or a key/value pair in the form of diff --git a/lib/renderer/api/remote.js b/lib/renderer/api/remote.js index be0b71af6d9e..c3c8e3b89cd1 100644 --- a/lib/renderer/api/remote.js +++ b/lib/renderer/api/remote.js @@ -88,7 +88,7 @@ const wrapArgs = function (args, visited) { } } } - return Array.prototype.slice.call(args).map(valueToMeta) + return args.map(valueToMeta) } // Populate object's members from descriptors. @@ -102,14 +102,14 @@ const setObjectMembers = function (ref, object, metaId, members) { let descriptor = { enumerable: member.enumerable } if (member.type === 'method') { - const remoteMemberFunction = function () { + const remoteMemberFunction = function (...args) { if (this && this.constructor === remoteMemberFunction) { // Constructor call. - let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', metaId, member.name, wrapArgs(arguments)) + let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', metaId, member.name, wrapArgs(args)) return metaToValue(ret) } else { // Call member function. - let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CALL', metaId, member.name, wrapArgs(arguments)) + let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CALL', metaId, member.name, wrapArgs(args)) return metaToValue(ret) } } @@ -220,17 +220,17 @@ const metaToValue = function (meta) { if (meta.type === 'function') { // A shadow class to represent the remote function object. - let remoteFunction = function () { + let remoteFunction = function (...args) { if (this && this.constructor === remoteFunction) { // Constructor call. - let obj = ipcRenderer.sendSync('ELECTRON_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(arguments)) + let obj = ipcRenderer.sendSync('ELECTRON_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(args)) // 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. - let obj = ipcRenderer.sendSync('ELECTRON_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(arguments)) + let obj = ipcRenderer.sendSync('ELECTRON_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(args)) return metaToValue(obj) } } diff --git a/lib/renderer/override.js b/lib/renderer/override.js index 6a8a50c378e8..a05eb898bbc0 100644 --- a/lib/renderer/override.js +++ b/lib/renderer/override.js @@ -1,24 +1,28 @@ 'use strict' -const ipcRenderer = require('electron').ipcRenderer -const remote = require('electron').remote +const {ipcRenderer} = require('electron') const parseFeaturesString = require('../common/parse-features-string') +const {defineProperty} = Object + // Helper function to resolve relative url. -var a = window.top.document.createElement('a') -var resolveURL = function (url) { +const a = window.top.document.createElement('a') +const resolveURL = function (url) { a.href = url return a.href } // Window object returned by "window.open". -var BrowserWindowProxy = (function () { +const BrowserWindowProxy = (function () { BrowserWindowProxy.proxies = {} BrowserWindowProxy.getOrCreate = function (guestId) { - var base = this.proxies - base[guestId] != null ? base[guestId] : base[guestId] = new BrowserWindowProxy(guestId) - return base[guestId] + let proxy = this.proxies[guestId] + if (proxy == null) { + proxy = new BrowserWindowProxy(guestId) + this.proxies[guestId] = proxy + } + return proxy } BrowserWindowProxy.remove = function (guestId) { @@ -26,7 +30,7 @@ var BrowserWindowProxy = (function () { } function BrowserWindowProxy (guestId1) { - Object.defineProperty(this, 'guestId', { + defineProperty(this, 'guestId', { configurable: false, enumerable: true, writeable: false, @@ -56,7 +60,7 @@ var BrowserWindowProxy = (function () { ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', this.guestId, 'print') } - Object.defineProperty(BrowserWindowProxy.prototype, 'location', { + defineProperty(BrowserWindowProxy.prototype, 'location', { get: function () { return ipcRenderer.sendSync('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD_SYNC', this.guestId, 'getURL') }, @@ -83,13 +87,13 @@ var BrowserWindowProxy = (function () { if (process.guestInstanceId == null) { // Override default window.close. window.close = function () { - return remote.getCurrentWindow().close() + ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_CLOSE') } } // Make the browser window or guest view emit "new-window" event. window.open = function (url, frameName, features) { - var guestId, j, len1, name, options, additionalFeatures + let guestId, j, len1, name, options, additionalFeatures if (frameName == null) { frameName = '' } @@ -160,29 +164,12 @@ window.open = function (url, frameName, features) { } } -// Use the dialog API to implement alert(). -window.alert = function (message = '', title = '') { - remote.dialog.showMessageBox(remote.getCurrentWindow(), { - message: String(message), - title: String(title), - buttons: ['OK'] - }) +window.alert = function (message, title) { + ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_ALERT', message, title) } -// And the confirm(). window.confirm = function (message, title) { - var buttons, cancelId - if (title == null) { - title = '' - } - buttons = ['OK', 'Cancel'] - cancelId = 1 - return !remote.dialog.showMessageBox(remote.getCurrentWindow(), { - message: message, - title: title, - buttons: buttons, - cancelId: cancelId - }) + return ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_CONFIRM', message, title) } // But we do not support prompt(). @@ -206,11 +193,11 @@ ipcRenderer.on('ELECTRON_GUEST_WINDOW_POSTMESSAGE', function (event, sourceId, m }) // Forward history operations to browser. -var sendHistoryOperation = function (...args) { +const sendHistoryOperation = function (...args) { ipcRenderer.send('ELECTRON_NAVIGATION_CONTROLLER', ...args) } -var getHistoryOperation = function (...args) { +const getHistoryOperation = function (...args) { return ipcRenderer.sendSync('ELECTRON_SYNC_NAVIGATION_CONTROLLER', ...args) } @@ -226,7 +213,7 @@ window.history.go = function (offset) { sendHistoryOperation('goToOffset', offset) } -Object.defineProperty(window.history, 'length', { +defineProperty(window.history, 'length', { get: function () { return getHistoryOperation('length') } @@ -244,13 +231,13 @@ ipcRenderer.on('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', function (event, vi }) // Make document.hidden and document.visibilityState return the correct value. -Object.defineProperty(document, 'hidden', { +defineProperty(document, 'hidden', { get: function () { return cachedVisibilityState !== 'visible' } }) -Object.defineProperty(document, 'visibilityState', { +defineProperty(document, 'visibilityState', { get: function () { return cachedVisibilityState }