build: enable JS semicolons (#22783)

This commit is contained in:
Samuel Attard 2020-03-20 13:28:31 -07:00 committed by GitHub
parent 24e21467b9
commit 5d657dece4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
354 changed files with 21512 additions and 21510 deletions

View file

@ -1,44 +1,44 @@
import * as fs from 'fs'
import * as path from 'path'
import * as fs from 'fs';
import * as path from 'path';
import { deprecate, Menu } from 'electron'
import { EventEmitter } from 'events'
import { deprecate, Menu } from 'electron';
import { EventEmitter } from 'events';
const bindings = process.electronBinding('app')
const commandLine = process.electronBinding('command_line')
const { app, App } = bindings
const bindings = process.electronBinding('app');
const commandLine = process.electronBinding('command_line');
const { app, App } = bindings;
// Only one app object permitted.
export default app
export default app;
let dockMenu: Electron.Menu | null = null
let dockMenu: Electron.Menu | null = null;
// App is an EventEmitter.
Object.setPrototypeOf(App.prototype, EventEmitter.prototype)
EventEmitter.call(app as any)
Object.setPrototypeOf(App.prototype, EventEmitter.prototype);
EventEmitter.call(app as any);
// Properties.
const nativeASGetter = app.isAccessibilitySupportEnabled
const nativeASSetter = app.setAccessibilitySupportEnabled
const nativeASGetter = app.isAccessibilitySupportEnabled;
const nativeASSetter = app.setAccessibilitySupportEnabled;
Object.defineProperty(App.prototype, 'accessibilitySupportEnabled', {
get: () => nativeASGetter.call(app),
set: (enabled) => nativeASSetter.call(app, enabled)
})
});
const nativeBCGetter = app.getBadgeCount
const nativeBCSetter = app.setBadgeCount
const nativeBCGetter = app.getBadgeCount;
const nativeBCSetter = app.setBadgeCount;
Object.defineProperty(App.prototype, 'badgeCount', {
get: () => nativeBCGetter.call(app),
set: (count) => nativeBCSetter.call(app, count)
})
});
const nativeNGetter = app.getName
const nativeNSetter = app.setName
const nativeNGetter = app.getName;
const nativeNSetter = app.setName;
Object.defineProperty(App.prototype, 'name', {
get: () => nativeNGetter.call(app),
set: (name) => nativeNSetter.call(app, name)
})
});
Object.assign(app, {
commandLine: {
@ -47,98 +47,98 @@ Object.assign(app, {
appendSwitch: (theSwitch: string, value?: string) => commandLine.appendSwitch(String(theSwitch), typeof value === 'undefined' ? value : String(value)),
appendArgument: (arg: string) => commandLine.appendArgument(String(arg))
} as Electron.CommandLine
})
});
// we define this here because it'd be overly complicated to
// do in native land
Object.defineProperty(app, 'applicationMenu', {
get () {
return Menu.getApplicationMenu()
return Menu.getApplicationMenu();
},
set (menu: Electron.Menu | null) {
return Menu.setApplicationMenu(menu)
return Menu.setApplicationMenu(menu);
}
})
});
App.prototype.isPackaged = (() => {
const execFile = path.basename(process.execPath).toLowerCase()
const execFile = path.basename(process.execPath).toLowerCase();
if (process.platform === 'win32') {
return execFile !== 'electron.exe'
return execFile !== 'electron.exe';
}
return execFile !== 'electron'
})()
return execFile !== 'electron';
})();
app._setDefaultAppPaths = (packagePath) => {
// Set the user path according to application's name.
app.setPath('userData', path.join(app.getPath('appData'), app.name!))
app.setPath('userCache', path.join(app.getPath('cache'), app.name!))
app.setAppPath(packagePath)
app.setPath('userData', path.join(app.getPath('appData'), app.name!));
app.setPath('userCache', path.join(app.getPath('cache'), app.name!));
app.setAppPath(packagePath);
// Add support for --user-data-dir=
if (app.commandLine.hasSwitch('user-data-dir')) {
const userDataDir = app.commandLine.getSwitchValue('user-data-dir')
if (path.isAbsolute(userDataDir)) app.setPath('userData', userDataDir)
const userDataDir = app.commandLine.getSwitchValue('user-data-dir');
if (path.isAbsolute(userDataDir)) app.setPath('userData', userDataDir);
}
}
};
if (process.platform === 'darwin') {
const setDockMenu = app.dock!.setMenu
const setDockMenu = app.dock!.setMenu;
app.dock!.setMenu = (menu) => {
dockMenu = menu
setDockMenu(menu)
}
app.dock!.getMenu = () => dockMenu
dockMenu = menu;
setDockMenu(menu);
};
app.dock!.getMenu = () => dockMenu;
}
if (process.platform === 'linux') {
const patternVmRSS = /^VmRSS:\s*(\d+) kB$/m
const patternVmHWM = /^VmHWM:\s*(\d+) kB$/m
const patternVmRSS = /^VmRSS:\s*(\d+) kB$/m;
const patternVmHWM = /^VmHWM:\s*(\d+) kB$/m;
const getStatus = (pid: number) => {
try {
return fs.readFileSync(`/proc/${pid}/status`, 'utf8')
return fs.readFileSync(`/proc/${pid}/status`, 'utf8');
} catch {
return ''
return '';
}
}
};
const getEntry = (file: string, pattern: RegExp) => {
const match = file.match(pattern)
return match ? parseInt(match[1], 10) : 0
}
const match = file.match(pattern);
return match ? parseInt(match[1], 10) : 0;
};
const getProcessMemoryInfo = (pid: number) => {
const file = getStatus(pid)
const file = getStatus(pid);
return {
workingSetSize: getEntry(file, patternVmRSS),
peakWorkingSetSize: getEntry(file, patternVmHWM)
}
}
};
};
const nativeFn = app.getAppMetrics
const nativeFn = app.getAppMetrics;
app.getAppMetrics = () => {
const metrics = nativeFn.call(app)
const metrics = nativeFn.call(app);
for (const metric of metrics) {
metric.memory = getProcessMemoryInfo(metric.pid)
metric.memory = getProcessMemoryInfo(metric.pid);
}
return metrics
}
return metrics;
};
}
// Routes the events to webContents.
const events = ['certificate-error', 'select-client-certificate']
const events = ['certificate-error', 'select-client-certificate'];
for (const name of events) {
app.on(name as 'certificate-error', (event, webContents, ...args: any[]) => {
webContents.emit(name, event, ...args)
})
webContents.emit(name, event, ...args);
});
}
// Deprecate allowRendererProcessReuse but only if they set it to false, no need to log if
// they are setting it to true
deprecate.removeProperty(app, 'allowRendererProcessReuse', [false])
deprecate.removeProperty(app, 'allowRendererProcessReuse', [false]);
// Wrappers for native classes.
const { DownloadItem } = process.electronBinding('download_item')
Object.setPrototypeOf(DownloadItem.prototype, EventEmitter.prototype)
const { DownloadItem } = process.electronBinding('download_item');
Object.setPrototypeOf(DownloadItem.prototype, EventEmitter.prototype);

View file

@ -1,7 +1,7 @@
'use strict'
'use strict';
if (process.platform === 'win32') {
module.exports = require('@electron/internal/browser/api/auto-updater/auto-updater-win')
module.exports = require('@electron/internal/browser/api/auto-updater/auto-updater-win');
} else {
module.exports = require('@electron/internal/browser/api/auto-updater/auto-updater-native')
module.exports = require('@electron/internal/browser/api/auto-updater/auto-updater-native');
}

View file

@ -1,10 +1,10 @@
'use strict'
'use strict';
const EventEmitter = require('events').EventEmitter
const { autoUpdater, AutoUpdater } = process.electronBinding('auto_updater')
const EventEmitter = require('events').EventEmitter;
const { autoUpdater, AutoUpdater } = process.electronBinding('auto_updater');
// AutoUpdater is an EventEmitter.
Object.setPrototypeOf(AutoUpdater.prototype, EventEmitter.prototype)
EventEmitter.call(autoUpdater)
Object.setPrototypeOf(AutoUpdater.prototype, EventEmitter.prototype);
EventEmitter.call(autoUpdater);
module.exports = autoUpdater
module.exports = autoUpdater;

View file

@ -1,74 +1,74 @@
'use strict'
'use strict';
const { app } = require('electron')
const { EventEmitter } = require('events')
const squirrelUpdate = require('@electron/internal/browser/api/auto-updater/squirrel-update-win')
const { app } = require('electron');
const { EventEmitter } = require('events');
const squirrelUpdate = require('@electron/internal/browser/api/auto-updater/squirrel-update-win');
class AutoUpdater extends EventEmitter {
quitAndInstall () {
if (!this.updateAvailable) {
return this.emitError('No update available, can\'t quit and install')
return this.emitError('No update available, can\'t quit and install');
}
squirrelUpdate.processStart()
app.quit()
squirrelUpdate.processStart();
app.quit();
}
getFeedURL () {
return this.updateURL
return this.updateURL;
}
setFeedURL (options) {
let updateURL
let updateURL;
if (typeof options === 'object') {
if (typeof options.url === 'string') {
updateURL = options.url
updateURL = options.url;
} else {
throw new Error('Expected options object to contain a \'url\' string property in setFeedUrl call')
throw new Error('Expected options object to contain a \'url\' string property in setFeedUrl call');
}
} else if (typeof options === 'string') {
updateURL = options
updateURL = options;
} else {
throw new Error('Expected an options object with a \'url\' property to be provided')
throw new Error('Expected an options object with a \'url\' property to be provided');
}
this.updateURL = updateURL
this.updateURL = updateURL;
}
checkForUpdates () {
if (!this.updateURL) {
return this.emitError('Update URL is not set')
return this.emitError('Update URL is not set');
}
if (!squirrelUpdate.supported()) {
return this.emitError('Can not find Squirrel')
return this.emitError('Can not find Squirrel');
}
this.emit('checking-for-update')
this.emit('checking-for-update');
squirrelUpdate.checkForUpdate(this.updateURL, (error, update) => {
if (error != null) {
return this.emitError(error)
return this.emitError(error);
}
if (update == null) {
return this.emit('update-not-available')
return this.emit('update-not-available');
}
this.updateAvailable = true
this.emit('update-available')
this.updateAvailable = true;
this.emit('update-available');
squirrelUpdate.update(this.updateURL, (error) => {
if (error != null) {
return this.emitError(error)
return this.emitError(error);
}
const { releaseNotes, version } = update
const { releaseNotes, version } = update;
// Date is not available on Windows, so fake it.
const date = new Date()
const date = new Date();
this.emit('update-downloaded', {}, releaseNotes, version, date, this.updateURL, () => {
this.quitAndInstall()
})
})
})
this.quitAndInstall();
});
});
});
}
// Private: Emit both error object and message, this is to keep compatibility
// with Old APIs.
emitError (message) {
this.emit('error', new Error(message), message)
this.emit('error', new Error(message), message);
}
}
module.exports = new AutoUpdater()
module.exports = new AutoUpdater();

View file

@ -1,24 +1,24 @@
'use strict'
'use strict';
const fs = require('fs')
const path = require('path')
const spawn = require('child_process').spawn
const fs = require('fs');
const path = require('path');
const spawn = require('child_process').spawn;
// i.e. my-app/app-0.1.13/
const appFolder = path.dirname(process.execPath)
const appFolder = path.dirname(process.execPath);
// i.e. my-app/Update.exe
const updateExe = path.resolve(appFolder, '..', 'Update.exe')
const exeName = path.basename(process.execPath)
let spawnedArgs = []
let spawnedProcess
const updateExe = path.resolve(appFolder, '..', 'Update.exe');
const exeName = path.basename(process.execPath);
let spawnedArgs = [];
let spawnedProcess;
const isSameArgs = (args) => args.length === spawnedArgs.length && args.every((e, i) => e === spawnedArgs[i])
const isSameArgs = (args) => args.length === spawnedArgs.length && args.every((e, i) => e === spawnedArgs[i]);
// Spawn a command and invoke the callback when it completes with an error
// and the output from standard out.
const spawnUpdate = function (args, detached, callback) {
let error, errorEmitted, stderr, stdout
let error, errorEmitted, stderr, stdout;
try {
// Ensure we don't spawn multiple squirrel processes
@ -28,92 +28,92 @@ const spawnUpdate = function (args, detached, callback) {
if (spawnedProcess && !isSameArgs(args)) {
// Disabled for backwards compatibility:
// eslint-disable-next-line standard/no-callback-literal
return callback(`AutoUpdater process with arguments ${args} is already running`)
return callback(`AutoUpdater process with arguments ${args} is already running`);
} else if (!spawnedProcess) {
spawnedProcess = spawn(updateExe, args, {
detached: detached,
windowsHide: true
})
spawnedArgs = args || []
});
spawnedArgs = args || [];
}
} catch (error1) {
error = error1
error = error1;
// Shouldn't happen, but still guard it.
process.nextTick(function () {
return callback(error)
})
return
return callback(error);
});
return;
}
stdout = ''
stderr = ''
stdout = '';
stderr = '';
spawnedProcess.stdout.on('data', (data) => { stdout += data })
spawnedProcess.stderr.on('data', (data) => { stderr += data })
spawnedProcess.stdout.on('data', (data) => { stdout += data; });
spawnedProcess.stderr.on('data', (data) => { stderr += data; });
errorEmitted = false
errorEmitted = false;
spawnedProcess.on('error', (error) => {
errorEmitted = true
callback(error)
})
errorEmitted = true;
callback(error);
});
return spawnedProcess.on('exit', function (code, signal) {
spawnedProcess = undefined
spawnedArgs = []
spawnedProcess = undefined;
spawnedArgs = [];
// We may have already emitted an error.
if (errorEmitted) {
return
return;
}
// Process terminated with error.
if (code !== 0) {
// Disabled for backwards compatibility:
// eslint-disable-next-line standard/no-callback-literal
return callback(`Command failed: ${signal != null ? signal : code}\n${stderr}`)
return callback(`Command failed: ${signal != null ? signal : code}\n${stderr}`);
}
// Success.
callback(null, stdout)
})
}
callback(null, stdout);
});
};
// Start an instance of the installed app.
exports.processStart = function () {
return spawnUpdate(['--processStartAndWait', exeName], true, function () {})
}
return spawnUpdate(['--processStartAndWait', exeName], true, function () {});
};
// Download the releases specified by the URL and write new results to stdout.
exports.checkForUpdate = function (updateURL, callback) {
return spawnUpdate(['--checkForUpdate', updateURL], false, function (error, stdout) {
let ref, ref1, update
let ref, ref1, update;
if (error != null) {
return callback(error)
return callback(error);
}
try {
// Last line of output is the JSON details about the releases
const json = stdout.trim().split('\n').pop()
update = (ref = JSON.parse(json)) != null ? (ref1 = ref.releasesToApply) != null ? typeof ref1.pop === 'function' ? ref1.pop() : undefined : undefined : undefined
const json = stdout.trim().split('\n').pop();
update = (ref = JSON.parse(json)) != null ? (ref1 = ref.releasesToApply) != null ? typeof ref1.pop === 'function' ? ref1.pop() : undefined : undefined : undefined;
} catch {
// Disabled for backwards compatibility:
// eslint-disable-next-line standard/no-callback-literal
return callback(`Invalid result:\n${stdout}`)
return callback(`Invalid result:\n${stdout}`);
}
return callback(null, update)
})
}
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)
}
return spawnUpdate(['--update', updateURL], false, callback);
};
// Is the Update.exe installed with the current application?
exports.supported = function () {
try {
fs.accessSync(updateExe, fs.R_OK)
return true
fs.accessSync(updateExe, fs.R_OK);
return true;
} catch {
return false
return false;
}
}
};

View file

@ -1,16 +1,16 @@
'use strict'
'use strict';
const { EventEmitter } = require('events')
const { BrowserView } = process.electronBinding('browser_view')
const { EventEmitter } = require('events');
const { BrowserView } = process.electronBinding('browser_view');
Object.setPrototypeOf(BrowserView.prototype, EventEmitter.prototype)
Object.setPrototypeOf(BrowserView.prototype, EventEmitter.prototype);
BrowserView.fromWebContents = (webContents) => {
for (const view of BrowserView.getAllViews()) {
if (view.webContents.equal(webContents)) return view
if (view.webContents.equal(webContents)) return view;
}
return null
}
return null;
};
module.exports = BrowserView
module.exports = BrowserView;

View file

@ -1,29 +1,29 @@
'use strict'
'use strict';
const electron = require('electron')
const { WebContentsView, TopLevelWindow, deprecate } = electron
const { BrowserWindow } = process.electronBinding('window')
const electron = require('electron');
const { WebContentsView, TopLevelWindow, deprecate } = electron;
const { BrowserWindow } = process.electronBinding('window');
Object.setPrototypeOf(BrowserWindow.prototype, TopLevelWindow.prototype)
Object.setPrototypeOf(BrowserWindow.prototype, TopLevelWindow.prototype);
BrowserWindow.prototype._init = function () {
// Call parent class's _init.
TopLevelWindow.prototype._init.call(this)
TopLevelWindow.prototype._init.call(this);
// Avoid recursive require.
const { app } = electron
const { app } = electron;
// Create WebContentsView.
this.setContentView(new WebContentsView(this.webContents))
this.setContentView(new WebContentsView(this.webContents));
const nativeSetBounds = this.setBounds
const nativeSetBounds = this.setBounds;
this.setBounds = (bounds, ...opts) => {
bounds = {
...this.getBounds(),
...bounds
}
nativeSetBounds.call(this, bounds, ...opts)
}
};
nativeSetBounds.call(this, bounds, ...opts);
};
// 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
@ -34,172 +34,172 @@ BrowserWindow.prototype._init = function () {
// Finder, we still do it on all platforms in case of other bugs we don't
// know.
this.webContents.once('load-url', function () {
this.focus()
})
this.focus();
});
// Redirect focus/blur event to app instance too.
this.on('blur', (event) => {
app.emit('browser-window-blur', event, this)
})
app.emit('browser-window-blur', event, this);
});
this.on('focus', (event) => {
app.emit('browser-window-focus', event, this)
})
app.emit('browser-window-focus', event, this);
});
// Subscribe to visibilityState changes and pass to renderer process.
let isVisible = this.isVisible() && !this.isMinimized()
let isVisible = this.isVisible() && !this.isMinimized();
const visibilityChanged = () => {
const newState = this.isVisible() && !this.isMinimized()
const newState = this.isVisible() && !this.isMinimized();
if (isVisible !== newState) {
isVisible = newState
const visibilityState = isVisible ? 'visible' : 'hidden'
this.webContents.emit('-window-visibility-change', visibilityState)
isVisible = newState;
const visibilityState = isVisible ? 'visible' : 'hidden';
this.webContents.emit('-window-visibility-change', visibilityState);
}
}
};
const visibilityEvents = ['show', 'hide', 'minimize', 'maximize', 'restore']
const visibilityEvents = ['show', 'hide', 'minimize', 'maximize', 'restore'];
for (const event of visibilityEvents) {
this.on(event, visibilityChanged)
this.on(event, visibilityChanged);
}
// Notify the creation of the window.
const event = process.electronBinding('event').createEmpty()
app.emit('browser-window-created', event, this)
const event = process.electronBinding('event').createEmpty();
app.emit('browser-window-created', event, this);
Object.defineProperty(this, 'devToolsWebContents', {
enumerable: true,
configurable: false,
get () {
return this.webContents.devToolsWebContents
return this.webContents.devToolsWebContents;
}
})
});
// Properties
Object.defineProperty(this, 'autoHideMenuBar', {
get: () => this.isMenuBarAutoHide(),
set: (autoHide) => this.setAutoHideMenuBar(autoHide)
})
});
Object.defineProperty(this, 'minimizable', {
get: () => this.isMinimizable(),
set: (min) => this.setMinimizable(min)
})
});
Object.defineProperty(this, 'maximizable', {
get: () => this.isMaximizable(),
set: (max) => this.setMaximizable(max)
})
});
Object.defineProperty(this, 'resizable', {
get: () => this.isResizable(),
set: (res) => this.setResizable(res)
})
});
Object.defineProperty(this, 'fullScreenable', {
get: () => this.isFullScreenable(),
set: (full) => this.setFullScreenable(full)
})
});
Object.defineProperty(this, 'closable', {
get: () => this.isClosable(),
set: (close) => this.setClosable(close)
})
});
Object.defineProperty(this, 'movable', {
get: () => this.isMovable(),
set: (move) => this.setMovable(move)
})
}
});
};
const isBrowserWindow = (win) => {
return win && win.constructor.name === 'BrowserWindow'
}
return win && win.constructor.name === 'BrowserWindow';
};
BrowserWindow.fromId = (id) => {
const win = TopLevelWindow.fromId(id)
return isBrowserWindow(win) ? win : null
}
const win = TopLevelWindow.fromId(id);
return isBrowserWindow(win) ? win : null;
};
BrowserWindow.getAllWindows = () => {
return TopLevelWindow.getAllWindows().filter(isBrowserWindow)
}
return TopLevelWindow.getAllWindows().filter(isBrowserWindow);
};
BrowserWindow.getFocusedWindow = () => {
for (const window of BrowserWindow.getAllWindows()) {
if (window.isFocused() || window.isDevToolsFocused()) return window
if (window.isFocused() || window.isDevToolsFocused()) return window;
}
return null
}
return null;
};
BrowserWindow.fromWebContents = (webContents) => {
for (const window of BrowserWindow.getAllWindows()) {
if (window.webContents && window.webContents.equal(webContents)) return window
if (window.webContents && window.webContents.equal(webContents)) return window;
}
return null
}
return null;
};
BrowserWindow.fromBrowserView = (browserView) => {
for (const window of BrowserWindow.getAllWindows()) {
if (window.getBrowserView() === browserView) return window
if (window.getBrowserView() === browserView) return window;
}
return null
}
return null;
};
// Helpers.
Object.assign(BrowserWindow.prototype, {
loadURL (...args) {
return this.webContents.loadURL(...args)
return this.webContents.loadURL(...args);
},
getURL (...args) {
return this.webContents.getURL()
return this.webContents.getURL();
},
loadFile (...args) {
return this.webContents.loadFile(...args)
return this.webContents.loadFile(...args);
},
reload (...args) {
return this.webContents.reload(...args)
return this.webContents.reload(...args);
},
send (...args) {
return this.webContents.send(...args)
return this.webContents.send(...args);
},
openDevTools (...args) {
return this.webContents.openDevTools(...args)
return this.webContents.openDevTools(...args);
},
closeDevTools () {
return this.webContents.closeDevTools()
return this.webContents.closeDevTools();
},
isDevToolsOpened () {
return this.webContents.isDevToolsOpened()
return this.webContents.isDevToolsOpened();
},
isDevToolsFocused () {
return this.webContents.isDevToolsFocused()
return this.webContents.isDevToolsFocused();
},
toggleDevTools () {
return this.webContents.toggleDevTools()
return this.webContents.toggleDevTools();
},
inspectElement (...args) {
return this.webContents.inspectElement(...args)
return this.webContents.inspectElement(...args);
},
inspectSharedWorker () {
return this.webContents.inspectSharedWorker()
return this.webContents.inspectSharedWorker();
},
inspectServiceWorker () {
return this.webContents.inspectServiceWorker()
return this.webContents.inspectServiceWorker();
},
showDefinitionForSelection () {
return this.webContents.showDefinitionForSelection()
return this.webContents.showDefinitionForSelection();
},
capturePage (...args) {
return this.webContents.capturePage(...args)
return this.webContents.capturePage(...args);
},
setTouchBar (touchBar) {
electron.TouchBar._setOnWindow(touchBar, this)
electron.TouchBar._setOnWindow(touchBar, this);
},
setBackgroundThrottling (allowed) {
this.webContents.setBackgroundThrottling(allowed)
this.webContents.setBackgroundThrottling(allowed);
}
})
});
module.exports = BrowserWindow
module.exports = BrowserWindow;

View file

@ -1,2 +1,2 @@
'use strict'
module.exports = process.electronBinding('content_tracing')
'use strict';
module.exports = process.electronBinding('content_tracing');

View file

@ -1,12 +1,12 @@
'use strict'
'use strict';
const CrashReporter = require('@electron/internal/common/crash-reporter')
const { crashReporterInit } = require('@electron/internal/browser/crash-reporter-init')
const CrashReporter = require('@electron/internal/common/crash-reporter');
const { crashReporterInit } = require('@electron/internal/browser/crash-reporter-init');
class CrashReporterMain extends CrashReporter {
init (options) {
return crashReporterInit(options)
return crashReporterInit(options);
}
}
module.exports = new CrashReporterMain()
module.exports = new CrashReporterMain();

View file

@ -1,13 +1,13 @@
'use strict'
'use strict';
const { app, BrowserWindow, deprecate } = require('electron')
const binding = process.electronBinding('dialog')
const v8Util = process.electronBinding('v8_util')
const { app, BrowserWindow, deprecate } = require('electron');
const binding = process.electronBinding('dialog');
const v8Util = process.electronBinding('v8_util');
const DialogType = {
OPEN: 'OPEN',
SAVE: 'SAVE'
}
};
const saveFileDialogProperties = {
createDirectory: 1 << 0,
@ -15,7 +15,7 @@ const saveFileDialogProperties = {
treatPackageAsDirectory: 1 << 2,
showOverwriteConfirmation: 1 << 3,
dontAddToRecent: 1 << 4
}
};
const openFileDialogProperties = {
openFile: 1 << 0,
@ -27,15 +27,15 @@ const openFileDialogProperties = {
noResolveAliases: 1 << 6, // macOS
treatPackageAsDirectory: 1 << 7, // macOS
dontAddToRecent: 1 << 8 // Windows
}
};
const normalizeAccessKey = (text) => {
if (typeof text !== 'string') return text
if (typeof text !== 'string') return text;
// macOS does not have access keys so remove single ampersands
// and replace double ampersands with a single ampersand
if (process.platform === 'darwin') {
return text.replace(/&(&?)/g, '$1')
return text.replace(/&(&?)/g, '$1');
}
// Linux uses a single underscore as an access key prefix so escape
@ -44,41 +44,41 @@ const normalizeAccessKey = (text) => {
// a single underscore
if (process.platform === 'linux') {
return text.replace(/_/g, '__').replace(/&(.?)/g, (match, after) => {
if (after === '&') return after
return `_${after}`
})
if (after === '&') return after;
return `_${after}`;
});
}
return text
}
return text;
};
const checkAppInitialized = function () {
if (!app.isReady()) {
throw new Error('dialog module can only be used after app is ready')
throw new Error('dialog module can only be used after app is ready');
}
}
};
const setupDialogProperties = (type, properties) => {
const dialogPropertiesTypes = (type === DialogType.OPEN) ? openFileDialogProperties : saveFileDialogProperties
let dialogProperties = 0
const dialogPropertiesTypes = (type === DialogType.OPEN) ? openFileDialogProperties : saveFileDialogProperties;
let dialogProperties = 0;
for (const prop in dialogPropertiesTypes) {
if (properties.includes(prop)) {
dialogProperties |= dialogPropertiesTypes[prop]
dialogProperties |= dialogPropertiesTypes[prop];
}
}
return dialogProperties
}
return dialogProperties;
};
const saveDialog = (sync, window, options) => {
checkAppInitialized()
checkAppInitialized();
if (window && window.constructor !== BrowserWindow) {
options = window
window = null
options = window;
window = null;
}
if (options == null) options = { title: 'Save' }
if (options == null) options = { title: 'Save' };
const {
buttonLabel = '',
@ -90,33 +90,33 @@ const saveDialog = (sync, window, options) => {
securityScopedBookmarks = false,
nameFieldLabel = '',
showsTagField = true
} = options
} = options;
if (typeof title !== 'string') throw new TypeError('Title must be a string')
if (typeof buttonLabel !== 'string') throw new TypeError('Button label must be a string')
if (typeof defaultPath !== 'string') throw new TypeError('Default path must be a string')
if (typeof message !== 'string') throw new TypeError('Message must be a string')
if (typeof nameFieldLabel !== 'string') throw new TypeError('Name field label must be a string')
if (typeof title !== 'string') throw new TypeError('Title must be a string');
if (typeof buttonLabel !== 'string') throw new TypeError('Button label must be a string');
if (typeof defaultPath !== 'string') throw new TypeError('Default path must be a string');
if (typeof message !== 'string') throw new TypeError('Message must be a string');
if (typeof nameFieldLabel !== 'string') throw new TypeError('Name field label must be a string');
const settings = { buttonLabel, defaultPath, filters, title, message, securityScopedBookmarks, nameFieldLabel, showsTagField, window }
settings.properties = setupDialogProperties(DialogType.SAVE, properties)
const settings = { buttonLabel, defaultPath, filters, title, message, securityScopedBookmarks, nameFieldLabel, showsTagField, window };
settings.properties = setupDialogProperties(DialogType.SAVE, properties);
return (sync) ? binding.showSaveDialogSync(settings) : binding.showSaveDialog(settings)
}
return (sync) ? binding.showSaveDialogSync(settings) : binding.showSaveDialog(settings);
};
const openDialog = (sync, window, options) => {
checkAppInitialized()
checkAppInitialized();
if (window && window.constructor !== BrowserWindow) {
options = window
window = null
options = window;
window = null;
}
if (options == null) {
options = {
title: 'Open',
properties: ['openFile']
}
};
}
const {
@ -127,33 +127,33 @@ const openDialog = (sync, window, options) => {
title = '',
message = '',
securityScopedBookmarks = false
} = options
} = options;
if (!Array.isArray(properties)) throw new TypeError('Properties must be an array')
if (!Array.isArray(properties)) throw new TypeError('Properties must be an array');
if (typeof title !== 'string') throw new TypeError('Title must be a string')
if (typeof buttonLabel !== 'string') throw new TypeError('Button label must be a string')
if (typeof defaultPath !== 'string') throw new TypeError('Default path must be a string')
if (typeof message !== 'string') throw new TypeError('Message must be a string')
if (typeof title !== 'string') throw new TypeError('Title must be a string');
if (typeof buttonLabel !== 'string') throw new TypeError('Button label must be a string');
if (typeof defaultPath !== 'string') throw new TypeError('Default path must be a string');
if (typeof message !== 'string') throw new TypeError('Message must be a string');
const settings = { title, buttonLabel, defaultPath, filters, message, securityScopedBookmarks, window }
settings.properties = setupDialogProperties(DialogType.OPEN, properties)
const settings = { title, buttonLabel, defaultPath, filters, message, securityScopedBookmarks, window };
settings.properties = setupDialogProperties(DialogType.OPEN, properties);
return (sync) ? binding.showOpenDialogSync(settings) : binding.showOpenDialog(settings)
}
return (sync) ? binding.showOpenDialogSync(settings) : binding.showOpenDialog(settings);
};
const messageBox = (sync, window, options) => {
checkAppInitialized()
checkAppInitialized();
if (window && window.constructor !== BrowserWindow) {
options = window
window = null
options = window;
window = null;
}
if (options == null) options = { type: 'none' }
if (options == null) options = { type: 'none' };
const messageBoxTypes = ['none', 'info', 'warning', 'error', 'question']
const messageBoxOptions = { noLink: 1 << 0 }
const messageBoxTypes = ['none', 'info', 'warning', 'error', 'question'];
const messageBoxOptions = { noLink: 1 << 0 };
let {
buttons = [],
@ -167,32 +167,32 @@ const messageBox = (sync, window, options) => {
message = '',
title = '',
type = 'none'
} = options
} = options;
const messageBoxType = messageBoxTypes.indexOf(type)
if (messageBoxType === -1) throw new TypeError('Invalid message box type')
if (!Array.isArray(buttons)) throw new TypeError('Buttons must be an array')
if (options.normalizeAccessKeys) buttons = buttons.map(normalizeAccessKey)
if (typeof title !== 'string') throw new TypeError('Title must be a string')
if (typeof noLink !== 'boolean') throw new TypeError('noLink must be a boolean')
if (typeof message !== 'string') throw new TypeError('Message must be a string')
if (typeof detail !== 'string') throw new TypeError('Detail must be a string')
if (typeof checkboxLabel !== 'string') throw new TypeError('checkboxLabel must be a string')
const messageBoxType = messageBoxTypes.indexOf(type);
if (messageBoxType === -1) throw new TypeError('Invalid message box type');
if (!Array.isArray(buttons)) throw new TypeError('Buttons must be an array');
if (options.normalizeAccessKeys) buttons = buttons.map(normalizeAccessKey);
if (typeof title !== 'string') throw new TypeError('Title must be a string');
if (typeof noLink !== 'boolean') throw new TypeError('noLink must be a boolean');
if (typeof message !== 'string') throw new TypeError('Message must be a string');
if (typeof detail !== 'string') throw new TypeError('Detail must be a string');
if (typeof checkboxLabel !== 'string') throw new TypeError('checkboxLabel must be a string');
checkboxChecked = !!checkboxChecked
checkboxChecked = !!checkboxChecked;
if (checkboxChecked && !checkboxLabel) {
throw new Error('checkboxChecked requires that checkboxLabel also be passed')
throw new Error('checkboxChecked requires that checkboxLabel also be passed');
}
// Choose a default button to get selected when dialog is cancelled.
if (cancelId == null) {
// If the defaultId is set to 0, ensure the cancel button is a different index (1)
cancelId = (defaultId === 0 && buttons.length > 1) ? 1 : 0
cancelId = (defaultId === 0 && buttons.length > 1) ? 1 : 0;
for (let i = 0; i < buttons.length; i++) {
const text = buttons[i].toLowerCase()
const text = buttons[i].toLowerCase();
if (text === 'cancel' || text === 'no') {
cancelId = i
break
cancelId = i;
break;
}
}
}
@ -210,57 +210,57 @@ const messageBox = (sync, window, options) => {
checkboxLabel,
checkboxChecked,
icon
}
};
if (sync) {
return binding.showMessageBoxSync(settings)
return binding.showMessageBoxSync(settings);
} else {
return binding.showMessageBox(settings)
return binding.showMessageBox(settings);
}
}
};
module.exports = {
showOpenDialog: function (window, options) {
return openDialog(false, window, options)
return openDialog(false, window, options);
},
showOpenDialogSync: function (window, options) {
return openDialog(true, window, options)
return openDialog(true, window, options);
},
showSaveDialog: function (window, options) {
return saveDialog(false, window, options)
return saveDialog(false, window, options);
},
showSaveDialogSync: function (window, options) {
return saveDialog(true, window, options)
return saveDialog(true, window, options);
},
showMessageBox: function (window, options) {
return messageBox(false, window, options)
return messageBox(false, window, options);
},
showMessageBoxSync: function (window, options) {
return messageBox(true, window, options)
return messageBox(true, window, options);
},
showErrorBox: function (...args) {
return binding.showErrorBox(...args)
return binding.showErrorBox(...args);
},
showCertificateTrustDialog: function (window, options) {
if (window && window.constructor !== BrowserWindow) options = window
if (window && window.constructor !== BrowserWindow) options = window;
if (options == null || typeof options !== 'object') {
throw new TypeError('options must be an object')
throw new TypeError('options must be an object');
}
const { certificate, message = '' } = options
const { certificate, message = '' } = options;
if (certificate == null || typeof certificate !== 'object') {
throw new TypeError('certificate must be an object')
throw new TypeError('certificate must be an object');
}
if (typeof message !== 'string') throw new TypeError('message must be a string')
if (typeof message !== 'string') throw new TypeError('message must be a string');
return binding.showCertificateTrustDialog(window, certificate, message)
return binding.showCertificateTrustDialog(window, certificate, message);
}
}
};

View file

@ -1,8 +1,8 @@
import { defineProperties } from '@electron/internal/common/define-properties'
import { commonModuleList } from '@electron/internal/common/api/module-list'
import { browserModuleList } from '@electron/internal/browser/api/module-list'
import { defineProperties } from '@electron/internal/common/define-properties';
import { commonModuleList } from '@electron/internal/common/api/module-list';
import { browserModuleList } from '@electron/internal/browser/api/module-list';
module.exports = {}
module.exports = {};
defineProperties(module.exports, commonModuleList)
defineProperties(module.exports, browserModuleList)
defineProperties(module.exports, commonModuleList);
defineProperties(module.exports, browserModuleList);

View file

@ -1,3 +1,3 @@
'use strict'
'use strict';
module.exports = process.electronBinding('global_shortcut').globalShortcut
module.exports = process.electronBinding('global_shortcut').globalShortcut;

View file

@ -1,22 +1,22 @@
'use strict'
'use strict';
const { deprecate } = require('electron')
const { deprecate } = require('electron');
if (process.platform === 'darwin') {
const { EventEmitter } = require('events')
const { inAppPurchase, InAppPurchase } = process.electronBinding('in_app_purchase')
const { EventEmitter } = require('events');
const { inAppPurchase, InAppPurchase } = process.electronBinding('in_app_purchase');
// inAppPurchase is an EventEmitter.
Object.setPrototypeOf(InAppPurchase.prototype, EventEmitter.prototype)
EventEmitter.call(inAppPurchase)
Object.setPrototypeOf(InAppPurchase.prototype, EventEmitter.prototype);
EventEmitter.call(inAppPurchase);
module.exports = inAppPurchase
module.exports = inAppPurchase;
} else {
module.exports = {
purchaseProduct: (productID, quantity, callback) => {
throw new Error('The inAppPurchase module can only be used on macOS')
throw new Error('The inAppPurchase module can only be used on macOS');
},
canMakePayments: () => false,
getReceiptURL: () => ''
}
};
}

View file

@ -1,8 +1,8 @@
import { IpcMainImpl } from '@electron/internal/browser/ipc-main-impl'
import { IpcMainImpl } from '@electron/internal/browser/ipc-main-impl';
const ipcMain = new IpcMainImpl()
const ipcMain = new IpcMainImpl();
// Do not throw exception when channel name is "error".
ipcMain.on('error', () => {})
ipcMain.on('error', () => {});
export default ipcMain
export default ipcMain;

View file

@ -1,15 +1,15 @@
'use strict'
'use strict';
const { app } = require('electron')
const { app } = require('electron');
const isMac = process.platform === 'darwin'
const isWindows = process.platform === 'win32'
const isLinux = process.platform === 'linux'
const isMac = process.platform === 'darwin';
const isWindows = process.platform === 'win32';
const isLinux = process.platform === 'linux';
const roles = {
about: {
get label () {
return isLinux ? 'About' : `About ${app.name}`
return isLinux ? 'About' : `About ${app.name}`;
}
},
close: {
@ -38,7 +38,7 @@ const roles = {
accelerator: 'Shift+CmdOrCtrl+R',
nonNativeMacOSRole: true,
windowMethod: (window) => {
window.webContents.reloadIgnoringCache()
window.webContents.reloadIgnoringCache();
}
},
front: {
@ -49,7 +49,7 @@ const roles = {
},
hide: {
get label () {
return `Hide ${app.name}`
return `Hide ${app.name}`;
},
accelerator: 'Command+H'
},
@ -77,9 +77,9 @@ const roles = {
quit: {
get label () {
switch (process.platform) {
case 'darwin': return `Quit ${app.name}`
case 'win32': return 'Exit'
default: return 'Quit'
case 'darwin': return `Quit ${app.name}`;
case 'win32': return 'Exit';
default: return 'Quit';
}
},
accelerator: isWindows ? undefined : 'CommandOrControl+Q',
@ -101,7 +101,7 @@ const roles = {
accelerator: 'CommandOrControl+0',
nonNativeMacOSRole: true,
webContentsMethod: (webContents) => {
webContents.zoomLevel = 0
webContents.zoomLevel = 0;
}
},
selectall: {
@ -134,7 +134,7 @@ const roles = {
label: 'Toggle Full Screen',
accelerator: isMac ? 'Control+Command+F' : 'F11',
windowMethod: (window) => {
window.setFullScreen(!window.isFullScreen())
window.setFullScreen(!window.isFullScreen());
}
},
undo: {
@ -156,7 +156,7 @@ const roles = {
accelerator: 'CommandOrControl+Plus',
nonNativeMacOSRole: true,
webContentsMethod: (webContents) => {
webContents.zoomLevel += 0.5
webContents.zoomLevel += 0.5;
}
},
zoomout: {
@ -164,13 +164,13 @@ const roles = {
accelerator: 'CommandOrControl+-',
nonNativeMacOSRole: true,
webContentsMethod: (webContents) => {
webContents.zoomLevel -= 0.5
webContents.zoomLevel -= 0.5;
}
},
// App submenu should be used for Mac only
appmenu: {
get label () {
return app.name
return app.name;
},
submenu: [
{ role: 'about' },
@ -249,71 +249,71 @@ const roles = {
])
]
}
}
};
exports.roleList = roles
exports.roleList = roles;
const canExecuteRole = (role) => {
if (!Object.prototype.hasOwnProperty.call(roles, role)) return false
if (!isMac) return true
if (!Object.prototype.hasOwnProperty.call(roles, role)) return false;
if (!isMac) return true;
// macOS handles all roles natively except for a few
return roles[role].nonNativeMacOSRole
}
return roles[role].nonNativeMacOSRole;
};
exports.getDefaultLabel = (role) => {
return Object.prototype.hasOwnProperty.call(roles, role) ? roles[role].label : ''
}
return Object.prototype.hasOwnProperty.call(roles, role) ? roles[role].label : '';
};
exports.getDefaultAccelerator = (role) => {
if (Object.prototype.hasOwnProperty.call(roles, role)) return roles[role].accelerator
}
if (Object.prototype.hasOwnProperty.call(roles, role)) return roles[role].accelerator;
};
exports.shouldRegisterAccelerator = (role) => {
const hasRoleRegister = Object.prototype.hasOwnProperty.call(roles, role) && roles[role].registerAccelerator !== undefined
return hasRoleRegister ? roles[role].registerAccelerator : true
}
const hasRoleRegister = Object.prototype.hasOwnProperty.call(roles, role) && roles[role].registerAccelerator !== undefined;
return hasRoleRegister ? roles[role].registerAccelerator : true;
};
exports.getDefaultSubmenu = (role) => {
if (!Object.prototype.hasOwnProperty.call(roles, role)) return
if (!Object.prototype.hasOwnProperty.call(roles, role)) return;
let { submenu } = roles[role]
let { submenu } = roles[role];
// remove null items from within the submenu
if (Array.isArray(submenu)) {
submenu = submenu.filter((item) => item != null)
submenu = submenu.filter((item) => item != null);
}
return submenu
}
return submenu;
};
exports.execute = (role, focusedWindow, focusedWebContents) => {
if (!canExecuteRole(role)) return false
if (!canExecuteRole(role)) return false;
const { appMethod, webContentsMethod, windowMethod } = roles[role]
const { appMethod, webContentsMethod, windowMethod } = roles[role];
if (appMethod) {
app[appMethod]()
return true
app[appMethod]();
return true;
}
if (windowMethod && focusedWindow != null) {
if (typeof windowMethod === 'function') {
windowMethod(focusedWindow)
windowMethod(focusedWindow);
} else {
focusedWindow[windowMethod]()
focusedWindow[windowMethod]();
}
return true
return true;
}
if (webContentsMethod && focusedWebContents != null) {
if (typeof webContentsMethod === 'function') {
webContentsMethod(focusedWebContents)
webContentsMethod(focusedWebContents);
} else {
focusedWebContents[webContentsMethod]()
focusedWebContents[webContentsMethod]();
}
return true
return true;
}
return false
}
return false;
};

View file

@ -1,87 +1,87 @@
'use strict'
'use strict';
const roles = require('@electron/internal/browser/api/menu-item-roles')
const roles = require('@electron/internal/browser/api/menu-item-roles');
let nextCommandId = 0
let nextCommandId = 0;
const MenuItem = function (options) {
const { Menu } = require('electron')
const { Menu } = require('electron');
// Preserve extra fields specified by user
for (const key in options) {
if (!(key in this)) this[key] = options[key]
if (!(key in this)) this[key] = options[key];
}
if (typeof this.role === 'string' || this.role instanceof String) {
this.role = this.role.toLowerCase()
this.role = this.role.toLowerCase();
}
this.submenu = this.submenu || roles.getDefaultSubmenu(this.role)
this.submenu = this.submenu || roles.getDefaultSubmenu(this.role);
if (this.submenu != null && this.submenu.constructor !== Menu) {
this.submenu = Menu.buildFromTemplate(this.submenu)
this.submenu = Menu.buildFromTemplate(this.submenu);
}
if (this.type == null && this.submenu != null) {
this.type = 'submenu'
this.type = 'submenu';
}
if (this.type === 'submenu' && (this.submenu == null || this.submenu.constructor !== Menu)) {
throw new Error('Invalid submenu')
throw new Error('Invalid submenu');
}
this.overrideReadOnlyProperty('type', 'normal')
this.overrideReadOnlyProperty('role')
this.overrideReadOnlyProperty('accelerator')
this.overrideReadOnlyProperty('icon')
this.overrideReadOnlyProperty('submenu')
this.overrideReadOnlyProperty('type', 'normal');
this.overrideReadOnlyProperty('role');
this.overrideReadOnlyProperty('accelerator');
this.overrideReadOnlyProperty('icon');
this.overrideReadOnlyProperty('submenu');
this.overrideProperty('label', roles.getDefaultLabel(this.role))
this.overrideProperty('sublabel', '')
this.overrideProperty('toolTip', '')
this.overrideProperty('enabled', true)
this.overrideProperty('visible', true)
this.overrideProperty('checked', false)
this.overrideProperty('acceleratorWorksWhenHidden', true)
this.overrideProperty('registerAccelerator', roles.shouldRegisterAccelerator(this.role))
this.overrideProperty('label', roles.getDefaultLabel(this.role));
this.overrideProperty('sublabel', '');
this.overrideProperty('toolTip', '');
this.overrideProperty('enabled', true);
this.overrideProperty('visible', true);
this.overrideProperty('checked', false);
this.overrideProperty('acceleratorWorksWhenHidden', true);
this.overrideProperty('registerAccelerator', roles.shouldRegisterAccelerator(this.role));
if (!MenuItem.types.includes(this.type)) {
throw new Error(`Unknown menu item type: ${this.type}`)
throw new Error(`Unknown menu item type: ${this.type}`);
}
this.overrideReadOnlyProperty('commandId', ++nextCommandId)
this.overrideReadOnlyProperty('commandId', ++nextCommandId);
const click = options.click
const click = options.click;
this.click = (event, focusedWindow, focusedWebContents) => {
// Manually flip the checked flags when clicked.
if (this.type === 'checkbox' || this.type === 'radio') {
this.checked = !this.checked
this.checked = !this.checked;
}
if (!roles.execute(this.role, focusedWindow, focusedWebContents)) {
if (typeof click === 'function') {
click(this, focusedWindow, event)
click(this, focusedWindow, event);
} else if (typeof this.selector === 'string' && process.platform === 'darwin') {
Menu.sendActionToFirstResponder(this.selector)
Menu.sendActionToFirstResponder(this.selector);
}
}
}
}
};
};
MenuItem.types = ['normal', 'separator', 'submenu', 'checkbox', 'radio']
MenuItem.types = ['normal', 'separator', 'submenu', 'checkbox', 'radio'];
MenuItem.prototype.getDefaultRoleAccelerator = function () {
return roles.getDefaultAccelerator(this.role)
}
return roles.getDefaultAccelerator(this.role);
};
MenuItem.prototype.overrideProperty = function (name, defaultValue = null) {
if (this[name] == null) {
this[name] = defaultValue
this[name] = defaultValue;
}
}
};
MenuItem.prototype.overrideReadOnlyProperty = function (name, defaultValue) {
this.overrideProperty(name, defaultValue)
this.overrideProperty(name, defaultValue);
Object.defineProperty(this, name, {
enumerable: true,
writable: false,
value: this[name]
})
}
});
};
module.exports = MenuItem
module.exports = MenuItem;

View file

@ -1,41 +1,41 @@
'use strict'
'use strict';
function splitArray (arr, predicate) {
const result = arr.reduce((multi, item) => {
const current = multi[multi.length - 1]
const current = multi[multi.length - 1];
if (predicate(item)) {
if (current.length > 0) multi.push([])
if (current.length > 0) multi.push([]);
} else {
current.push(item)
current.push(item);
}
return multi
}, [[]])
return multi;
}, [[]]);
if (result[result.length - 1].length === 0) {
return result.slice(0, result.length - 1)
return result.slice(0, result.length - 1);
}
return result
return result;
}
function joinArrays (arrays, joinIDs) {
return arrays.reduce((joined, arr, i) => {
if (i > 0 && arr.length) {
if (joinIDs.length > 0) {
joined.push(joinIDs[0])
joinIDs.splice(0, 1)
joined.push(joinIDs[0]);
joinIDs.splice(0, 1);
} else {
joined.push({ type: 'separator' })
joined.push({ type: 'separator' });
}
}
return joined.concat(arr)
}, [])
return joined.concat(arr);
}, []);
}
function pushOntoMultiMap (map, key, value) {
if (!map.has(key)) {
map.set(key, [])
map.set(key, []);
}
map.get(key).push(value)
map.get(key).push(value);
}
function indexOfGroupContainingID (groups, id, ignoreGroup) {
@ -45,102 +45,102 @@ function indexOfGroupContainingID (groups, id, ignoreGroup) {
candidateGroup.some(
candidateItem => candidateItem.id === id
)
)
);
}
// Sort nodes topologically using a depth-first approach. Encountered cycles
// are broken.
function sortTopologically (originalOrder, edgesById) {
const sorted = []
const marked = new Set()
const sorted = [];
const marked = new Set();
const visit = (mark) => {
if (marked.has(mark)) return
marked.add(mark)
const edges = edgesById.get(mark)
if (marked.has(mark)) return;
marked.add(mark);
const edges = edgesById.get(mark);
if (edges != null) {
edges.forEach(visit)
edges.forEach(visit);
}
sorted.push(mark)
}
sorted.push(mark);
};
originalOrder.forEach(visit)
return sorted
originalOrder.forEach(visit);
return sorted;
}
function attemptToMergeAGroup (groups) {
for (let i = 0; i < groups.length; i++) {
const group = groups[i]
const group = groups[i];
for (const item of group) {
const toIDs = [...(item.before || []), ...(item.after || [])]
const toIDs = [...(item.before || []), ...(item.after || [])];
for (const id of toIDs) {
const index = indexOfGroupContainingID(groups, id, group)
if (index === -1) continue
const mergeTarget = groups[index]
const index = indexOfGroupContainingID(groups, id, group);
if (index === -1) continue;
const mergeTarget = groups[index];
mergeTarget.push(...group)
groups.splice(i, 1)
return true
mergeTarget.push(...group);
groups.splice(i, 1);
return true;
}
}
}
return false
return false;
}
function mergeGroups (groups) {
let merged = true
let merged = true;
while (merged) {
merged = attemptToMergeAGroup(groups)
merged = attemptToMergeAGroup(groups);
}
return groups
return groups;
}
function sortItemsInGroup (group) {
const originalOrder = group.map((node, i) => i)
const edges = new Map()
const idToIndex = new Map(group.map((item, i) => [item.id, i]))
const originalOrder = group.map((node, i) => i);
const edges = new Map();
const idToIndex = new Map(group.map((item, i) => [item.id, i]));
group.forEach((item, i) => {
if (item.before) {
item.before.forEach(toID => {
const to = idToIndex.get(toID)
const to = idToIndex.get(toID);
if (to != null) {
pushOntoMultiMap(edges, to, i)
pushOntoMultiMap(edges, to, i);
}
})
});
}
if (item.after) {
item.after.forEach(toID => {
const to = idToIndex.get(toID)
const to = idToIndex.get(toID);
if (to != null) {
pushOntoMultiMap(edges, i, to)
pushOntoMultiMap(edges, i, to);
}
})
});
}
})
});
const sortedNodes = sortTopologically(originalOrder, edges)
return sortedNodes.map(i => group[i])
const sortedNodes = sortTopologically(originalOrder, edges);
return sortedNodes.map(i => group[i]);
}
function findEdgesInGroup (groups, i, edges) {
const group = groups[i]
const group = groups[i];
for (const item of group) {
if (item.beforeGroupContaining) {
for (const id of item.beforeGroupContaining) {
const to = indexOfGroupContainingID(groups, id, group)
const to = indexOfGroupContainingID(groups, id, group);
if (to !== -1) {
pushOntoMultiMap(edges, to, i)
return
pushOntoMultiMap(edges, to, i);
return;
}
}
}
if (item.afterGroupContaining) {
for (const id of item.afterGroupContaining) {
const to = indexOfGroupContainingID(groups, id, group)
const to = indexOfGroupContainingID(groups, id, group);
if (to !== -1) {
pushOntoMultiMap(edges, i, to)
return
pushOntoMultiMap(edges, i, to);
return;
}
}
}
@ -148,29 +148,29 @@ function findEdgesInGroup (groups, i, edges) {
}
function sortGroups (groups) {
const originalOrder = groups.map((item, i) => i)
const edges = new Map()
const originalOrder = groups.map((item, i) => i);
const edges = new Map();
for (let i = 0; i < groups.length; i++) {
findEdgesInGroup(groups, i, edges)
findEdgesInGroup(groups, i, edges);
}
const sortedGroupIndexes = sortTopologically(originalOrder, edges)
return sortedGroupIndexes.map(i => groups[i])
const sortedGroupIndexes = sortTopologically(originalOrder, edges);
return sortedGroupIndexes.map(i => groups[i]);
}
function sortMenuItems (menuItems) {
const isSeparator = (item) => item.type === 'separator'
const separators = menuItems.filter(i => i.type === 'separator')
const isSeparator = (item) => item.type === 'separator';
const separators = menuItems.filter(i => i.type === 'separator');
// Split the items into their implicit groups based upon separators.
const groups = splitArray(menuItems, isSeparator)
const mergedGroups = mergeGroups(groups)
const mergedGroupsWithSortedItems = mergedGroups.map(sortItemsInGroup)
const sortedGroups = sortGroups(mergedGroupsWithSortedItems)
const groups = splitArray(menuItems, isSeparator);
const mergedGroups = mergeGroups(groups);
const mergedGroupsWithSortedItems = mergedGroups.map(sortItemsInGroup);
const sortedGroups = sortGroups(mergedGroupsWithSortedItems);
const joined = joinArrays(sortedGroups, separators)
return joined
const joined = joinArrays(sortedGroups, separators);
return joined;
}
module.exports = { sortMenuItems }
module.exports = { sortMenuItems };

View file

@ -1,16 +1,16 @@
'use strict'
'use strict';
const { TopLevelWindow, MenuItem, webContents } = require('electron')
const { sortMenuItems } = require('@electron/internal/browser/api/menu-utils')
const EventEmitter = require('events').EventEmitter
const v8Util = process.electronBinding('v8_util')
const bindings = process.electronBinding('menu')
const { TopLevelWindow, MenuItem, webContents } = require('electron');
const { sortMenuItems } = require('@electron/internal/browser/api/menu-utils');
const EventEmitter = require('events').EventEmitter;
const v8Util = process.electronBinding('v8_util');
const bindings = process.electronBinding('menu');
const { Menu } = bindings
let applicationMenu = null
let groupIdIndex = 0
const { Menu } = bindings;
let applicationMenu = null;
let groupIdIndex = 0;
Object.setPrototypeOf(Menu.prototype, EventEmitter.prototype)
Object.setPrototypeOf(Menu.prototype, EventEmitter.prototype);
// Menu Delegate.
// This object should hold no reference to |Menu| to avoid cyclic reference.
@ -20,172 +20,172 @@ const delegate = {
shouldCommandIdWorkWhenHidden: (menu, id) => menu.commandsMap[id] ? menu.commandsMap[id].acceleratorWorksWhenHidden : undefined,
isCommandIdVisible: (menu, id) => menu.commandsMap[id] ? menu.commandsMap[id].visible : undefined,
getAcceleratorForCommandId: (menu, id, useDefaultAccelerator) => {
const command = menu.commandsMap[id]
if (!command) return
if (command.accelerator != null) return command.accelerator
if (useDefaultAccelerator) return command.getDefaultRoleAccelerator()
const command = menu.commandsMap[id];
if (!command) return;
if (command.accelerator != null) return command.accelerator;
if (useDefaultAccelerator) return command.getDefaultRoleAccelerator();
},
shouldRegisterAcceleratorForCommandId: (menu, id) => menu.commandsMap[id] ? menu.commandsMap[id].registerAccelerator : undefined,
executeCommand: (menu, event, id) => {
const command = menu.commandsMap[id]
if (!command) return
command.click(event, TopLevelWindow.getFocusedWindow(), webContents.getFocusedWebContents())
const command = menu.commandsMap[id];
if (!command) return;
command.click(event, TopLevelWindow.getFocusedWindow(), webContents.getFocusedWebContents());
},
menuWillShow: (menu) => {
// Ensure radio groups have at least one menu item selected
for (const id of Object.keys(menu.groupsMap)) {
const found = menu.groupsMap[id].find(item => item.checked) || null
if (!found) v8Util.setHiddenValue(menu.groupsMap[id][0], 'checked', true)
const found = menu.groupsMap[id].find(item => item.checked) || null;
if (!found) v8Util.setHiddenValue(menu.groupsMap[id][0], 'checked', true);
}
}
}
};
/* Instance Methods */
Menu.prototype._init = function () {
this.commandsMap = {}
this.groupsMap = {}
this.items = []
this.delegate = delegate
}
this.commandsMap = {};
this.groupsMap = {};
this.items = [];
this.delegate = delegate;
};
Menu.prototype.popup = function (options = {}) {
if (options == null || typeof options !== 'object') {
throw new TypeError('Options must be an object')
throw new TypeError('Options must be an object');
}
let { window, x, y, positioningItem, callback } = options
let { window, x, y, positioningItem, callback } = options;
// no callback passed
if (!callback || typeof callback !== 'function') callback = () => {}
if (!callback || typeof callback !== 'function') callback = () => {};
// set defaults
if (typeof x !== 'number') x = -1
if (typeof y !== 'number') y = -1
if (typeof positioningItem !== 'number') positioningItem = -1
if (typeof x !== 'number') x = -1;
if (typeof y !== 'number') y = -1;
if (typeof positioningItem !== 'number') positioningItem = -1;
// find which window to use
const wins = TopLevelWindow.getAllWindows()
const wins = TopLevelWindow.getAllWindows();
if (!wins || wins.indexOf(window) === -1) {
window = TopLevelWindow.getFocusedWindow()
window = TopLevelWindow.getFocusedWindow();
if (!window && wins && wins.length > 0) {
window = wins[0]
window = wins[0];
}
if (!window) {
throw new Error('Cannot open Menu without a TopLevelWindow present')
throw new Error('Cannot open Menu without a TopLevelWindow present');
}
}
this.popupAt(window, x, y, positioningItem, callback)
return { browserWindow: window, x, y, position: positioningItem }
}
this.popupAt(window, x, y, positioningItem, callback);
return { browserWindow: window, x, y, position: positioningItem };
};
Menu.prototype.closePopup = function (window) {
if (window instanceof TopLevelWindow) {
this.closePopupAt(window.id)
this.closePopupAt(window.id);
} else {
// Passing -1 (invalid) would make closePopupAt close the all menu runners
// belong to this menu.
this.closePopupAt(-1)
this.closePopupAt(-1);
}
}
};
Menu.prototype.getMenuItemById = function (id) {
const items = this.items
const items = this.items;
let found = items.find(item => item.id === id) || null
let found = items.find(item => item.id === id) || null;
for (let i = 0; !found && i < items.length; i++) {
if (items[i].submenu) {
found = items[i].submenu.getMenuItemById(id)
found = items[i].submenu.getMenuItemById(id);
}
}
return found
}
return found;
};
Menu.prototype.append = function (item) {
return this.insert(this.getItemCount(), item)
}
return this.insert(this.getItemCount(), item);
};
Menu.prototype.insert = function (pos, item) {
if ((item ? item.constructor : undefined) !== MenuItem) {
throw new TypeError('Invalid item')
throw new TypeError('Invalid item');
}
if (pos < 0) {
throw new RangeError(`Position ${pos} cannot be less than 0`)
throw new RangeError(`Position ${pos} cannot be less than 0`);
} else if (pos > this.getItemCount()) {
throw new RangeError(`Position ${pos} cannot be greater than the total MenuItem count`)
throw new RangeError(`Position ${pos} cannot be greater than the total MenuItem count`);
}
// insert item depending on its type
insertItemByType.call(this, item, pos)
insertItemByType.call(this, item, pos);
// set item properties
if (item.sublabel) this.setSublabel(pos, item.sublabel)
if (item.toolTip) this.setToolTip(pos, item.toolTip)
if (item.icon) this.setIcon(pos, item.icon)
if (item.role) this.setRole(pos, item.role)
if (item.sublabel) this.setSublabel(pos, item.sublabel);
if (item.toolTip) this.setToolTip(pos, item.toolTip);
if (item.icon) this.setIcon(pos, item.icon);
if (item.role) this.setRole(pos, item.role);
// Make menu accessable to items.
item.overrideReadOnlyProperty('menu', this)
item.overrideReadOnlyProperty('menu', this);
// Remember the items.
this.items.splice(pos, 0, item)
this.commandsMap[item.commandId] = item
}
this.items.splice(pos, 0, item);
this.commandsMap[item.commandId] = item;
};
Menu.prototype._callMenuWillShow = function () {
if (this.delegate) this.delegate.menuWillShow(this)
if (this.delegate) this.delegate.menuWillShow(this);
this.items.forEach(item => {
if (item.submenu) item.submenu._callMenuWillShow()
})
}
if (item.submenu) item.submenu._callMenuWillShow();
});
};
/* Static Methods */
Menu.getApplicationMenu = () => applicationMenu
Menu.getApplicationMenu = () => applicationMenu;
Menu.sendActionToFirstResponder = bindings.sendActionToFirstResponder
Menu.sendActionToFirstResponder = bindings.sendActionToFirstResponder;
// set application menu with a preexisting menu
Menu.setApplicationMenu = function (menu) {
if (menu && menu.constructor !== Menu) {
throw new TypeError('Invalid menu')
throw new TypeError('Invalid menu');
}
applicationMenu = menu
v8Util.setHiddenValue(global, 'applicationMenuSet', true)
applicationMenu = menu;
v8Util.setHiddenValue(global, 'applicationMenuSet', true);
if (process.platform === 'darwin') {
if (!menu) return
menu._callMenuWillShow()
bindings.setApplicationMenu(menu)
if (!menu) return;
menu._callMenuWillShow();
bindings.setApplicationMenu(menu);
} else {
const windows = TopLevelWindow.getAllWindows()
return windows.map(w => w.setMenu(menu))
const windows = TopLevelWindow.getAllWindows();
return windows.map(w => w.setMenu(menu));
}
}
};
Menu.buildFromTemplate = function (template) {
if (!Array.isArray(template)) {
throw new TypeError('Invalid template for Menu: Menu template must be an array')
throw new TypeError('Invalid template for Menu: Menu template must be an array');
}
if (!areValidTemplateItems(template)) {
throw new TypeError('Invalid template for MenuItem: must have at least one of label, role or type')
throw new TypeError('Invalid template for MenuItem: must have at least one of label, role or type');
}
const filtered = removeExtraSeparators(template)
const sorted = sortTemplate(filtered)
const filtered = removeExtraSeparators(template);
const sorted = sortTemplate(filtered);
const menu = new Menu()
const menu = new Menu();
sorted.forEach(item => {
if (item instanceof MenuItem) {
menu.append(item)
menu.append(item);
} else {
menu.append(new MenuItem(item))
menu.append(new MenuItem(item));
}
})
});
return menu
}
return menu;
};
/* Helper Functions */
@ -196,50 +196,50 @@ function areValidTemplateItems (template) {
typeof item === 'object' &&
(Object.prototype.hasOwnProperty.call(item, 'label') ||
Object.prototype.hasOwnProperty.call(item, 'role') ||
item.type === 'separator'))
item.type === 'separator'));
}
function sortTemplate (template) {
const sorted = sortMenuItems(template)
const sorted = sortMenuItems(template);
for (const item of sorted) {
if (Array.isArray(item.submenu)) {
item.submenu = sortTemplate(item.submenu)
item.submenu = sortTemplate(item.submenu);
}
}
return sorted
return sorted;
}
// Search between separators to find a radio menu item and return its group id
function generateGroupId (items, pos) {
if (pos > 0) {
for (let idx = pos - 1; idx >= 0; idx--) {
if (items[idx].type === 'radio') return items[idx].groupId
if (items[idx].type === 'separator') break
if (items[idx].type === 'radio') return items[idx].groupId;
if (items[idx].type === 'separator') break;
}
} else if (pos < items.length) {
for (let idx = pos; idx <= items.length - 1; idx++) {
if (items[idx].type === 'radio') return items[idx].groupId
if (items[idx].type === 'separator') break
if (items[idx].type === 'radio') return items[idx].groupId;
if (items[idx].type === 'separator') break;
}
}
groupIdIndex += 1
return groupIdIndex
groupIdIndex += 1;
return groupIdIndex;
}
function removeExtraSeparators (items) {
// fold adjacent separators together
let ret = items.filter((e, idx, arr) => {
if (e.visible === false) return true
return e.type !== 'separator' || idx === 0 || arr[idx - 1].type !== 'separator'
})
if (e.visible === false) return true;
return e.type !== 'separator' || idx === 0 || arr[idx - 1].type !== 'separator';
});
// remove edge separators
ret = ret.filter((e, idx, arr) => {
if (e.visible === false) return true
return e.type !== 'separator' || (idx !== 0 && idx !== arr.length - 1)
})
if (e.visible === false) return true;
return e.type !== 'separator' || (idx !== 0 && idx !== arr.length - 1);
});
return ret
return ret;
}
function insertItemByType (item, pos) {
@ -250,28 +250,28 @@ function insertItemByType (item, pos) {
submenu: () => this.insertSubMenu(pos, item.commandId, item.label, item.submenu),
radio: () => {
// Grouping radio menu items
item.overrideReadOnlyProperty('groupId', generateGroupId(this.items, pos))
item.overrideReadOnlyProperty('groupId', generateGroupId(this.items, pos));
if (this.groupsMap[item.groupId] == null) {
this.groupsMap[item.groupId] = []
this.groupsMap[item.groupId] = [];
}
this.groupsMap[item.groupId].push(item)
this.groupsMap[item.groupId].push(item);
// Setting a radio menu item should flip other items in the group.
v8Util.setHiddenValue(item, 'checked', item.checked)
v8Util.setHiddenValue(item, 'checked', item.checked);
Object.defineProperty(item, 'checked', {
enumerable: true,
get: () => v8Util.getHiddenValue(item, 'checked'),
set: () => {
this.groupsMap[item.groupId].forEach(other => {
if (other !== item) v8Util.setHiddenValue(other, 'checked', false)
})
v8Util.setHiddenValue(item, 'checked', true)
if (other !== item) v8Util.setHiddenValue(other, 'checked', false);
});
v8Util.setHiddenValue(item, 'checked', true);
}
})
this.insertRadioItem(pos, item.commandId, item.label, item.groupId)
});
this.insertRadioItem(pos, item.commandId, item.label, item.groupId);
}
}
types[item.type]()
};
types[item.type]();
}
module.exports = Menu
module.exports = Menu;

View file

@ -1,12 +1,12 @@
import { MessagePortMain } from '@electron/internal/browser/message-port-main'
const { createPair } = process.electronBinding('message_port')
import { MessagePortMain } from '@electron/internal/browser/message-port-main';
const { createPair } = process.electronBinding('message_port');
export default class MessageChannelMain {
port1: MessagePortMain;
port2: MessagePortMain;
constructor () {
const { port1, port2 } = createPair()
this.port1 = new MessagePortMain(port1)
this.port2 = new MessagePortMain(port2)
const { port1, port2 } = createPair();
this.port1 = new MessagePortMain(port1);
this.port2 = new MessagePortMain(port2);
}
}

View file

@ -1,11 +1,11 @@
'use strict'
'use strict';
// TODO: Figure out a way to not duplicate this information between here and module-list
// It is currently duplicated as module-list "require"s all the browser API file and the
// remote module in the renderer process depends on that file. As a result webpack
// includes all the browser API files in the renderer process as well and we want to avoid that
const features = process.electronBinding('features')
const features = process.electronBinding('features');
// Browser side modules, please sort alphabetically.
module.exports = [
@ -38,7 +38,7 @@ module.exports = [
{ name: 'View' },
{ name: 'webContents' },
{ name: 'WebContentsView' }
]
];
if (features.isViewApiEnabled()) {
module.exports.push(
@ -49,5 +49,5 @@ if (features.isViewApiEnabled()) {
{ name: 'MdTextButton' },
{ name: 'ResizeArea' },
{ name: 'TextField' }
)
);
}

View file

@ -1,6 +1,6 @@
// TODO: Updating this file also required updating the module-keys file
const features = process.electronBinding('features')
const features = process.electronBinding('features');
// Browser side modules, please sort alphabetically.
export const browserModuleList: ElectronInternal.ModuleEntry[] = [
@ -33,7 +33,7 @@ export const browserModuleList: ElectronInternal.ModuleEntry[] = [
{ name: 'View', loader: () => require('./view') },
{ name: 'webContents', loader: () => require('./web-contents') },
{ name: 'WebContentsView', loader: () => require('./web-contents-view') }
]
];
if (features.isViewApiEnabled()) {
browserModuleList.push(
@ -44,5 +44,5 @@ if (features.isViewApiEnabled()) {
{ name: 'MdTextButton', loader: () => require('./views/md-text-button') },
{ name: 'ResizeArea', loader: () => require('./views/resize-area') },
{ name: 'TextField', loader: () => require('./views/text-field') }
)
);
}

View file

@ -1,8 +1,8 @@
import { EventEmitter } from 'events'
import { EventEmitter } from 'events';
const { NativeTheme, nativeTheme } = process.electronBinding('native_theme')
const { NativeTheme, nativeTheme } = process.electronBinding('native_theme');
Object.setPrototypeOf(NativeTheme.prototype, EventEmitter.prototype)
EventEmitter.call(nativeTheme as any)
Object.setPrototypeOf(NativeTheme.prototype, EventEmitter.prototype);
EventEmitter.call(nativeTheme as any);
module.exports = nativeTheme
module.exports = nativeTheme;

View file

@ -1,32 +1,32 @@
'use strict'
'use strict';
// TODO(deepak1556): Deprecate and remove standalone netLog module,
// it is now a property of session module.
const { app, session } = require('electron')
const { app, session } = require('electron');
// Fallback to default session.
Object.setPrototypeOf(module.exports, new Proxy({}, {
get (target, property) {
if (!app.isReady()) return
if (!app.isReady()) return;
const netLog = session.defaultSession.netLog
const netLog = session.defaultSession.netLog;
if (!Object.prototype.hasOwnProperty.call(Object.getPrototypeOf(netLog), property)) return
if (!Object.prototype.hasOwnProperty.call(Object.getPrototypeOf(netLog), property)) return;
// check for properties on the prototype chain that aren't functions
if (typeof netLog[property] !== 'function') return netLog[property]
if (typeof netLog[property] !== 'function') return netLog[property];
// Returning a native function directly would throw error.
return (...args) => netLog[property](...args)
return (...args) => netLog[property](...args);
},
ownKeys () {
if (!app.isReady()) return []
if (!app.isReady()) return [];
return Object.getOwnPropertyNames(Object.getPrototypeOf(session.defaultSession.netLog))
return Object.getOwnPropertyNames(Object.getPrototypeOf(session.defaultSession.netLog));
},
getOwnPropertyDescriptor (target) {
return { configurable: true, enumerable: true }
return { configurable: true, enumerable: true };
}
}))
}));

View file

@ -1,16 +1,16 @@
'use strict'
'use strict';
const url = require('url')
const { EventEmitter } = require('events')
const { Readable, Writable } = require('stream')
const { app } = require('electron')
const { Session } = process.electronBinding('session')
const { net, Net, _isValidHeaderName, _isValidHeaderValue } = process.electronBinding('net')
const { URLLoader } = net
const url = require('url');
const { EventEmitter } = require('events');
const { Readable, Writable } = require('stream');
const { app } = require('electron');
const { Session } = process.electronBinding('session');
const { net, Net, _isValidHeaderName, _isValidHeaderValue } = process.electronBinding('net');
const { URLLoader } = net;
Object.setPrototypeOf(URLLoader.prototype, EventEmitter.prototype)
Object.setPrototypeOf(URLLoader.prototype, EventEmitter.prototype);
const kSupportedProtocols = new Set(['http:', 'https:'])
const kSupportedProtocols = new Set(['http:', 'https:']);
// set of headers that Node.js discards duplicates for
// see https://nodejs.org/api/http.html#http_message_headers
@ -33,27 +33,27 @@ const discardableDuplicateHeaders = new Set([
'server',
'age',
'expires'
])
]);
class IncomingMessage extends Readable {
constructor (responseHead) {
super()
this._shouldPush = false
this._data = []
this._responseHead = responseHead
super();
this._shouldPush = false;
this._data = [];
this._responseHead = responseHead;
}
get statusCode () {
return this._responseHead.statusCode
return this._responseHead.statusCode;
}
get statusMessage () {
return this._responseHead.statusMessage
return this._responseHead.statusMessage;
}
get headers () {
const filteredHeaders = {}
const { rawHeaders } = this._responseHead
const filteredHeaders = {};
const { rawHeaders } = this._responseHead;
rawHeaders.forEach(header => {
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key) &&
discardableDuplicateHeaders.has(header.key)) {
@ -63,147 +63,147 @@ class IncomingMessage extends Readable {
// keep set-cookie as an array per Node.js rules
// see https://nodejs.org/api/http.html#http_message_headers
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key)) {
filteredHeaders[header.key].push(header.value)
filteredHeaders[header.key].push(header.value);
} else {
filteredHeaders[header.key] = [header.value]
filteredHeaders[header.key] = [header.value];
}
} else {
// for non-cookie headers, the values are joined together with ', '
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key)) {
filteredHeaders[header.key] += `, ${header.value}`
filteredHeaders[header.key] += `, ${header.value}`;
} else {
filteredHeaders[header.key] = header.value
filteredHeaders[header.key] = header.value;
}
}
}
})
return filteredHeaders
});
return filteredHeaders;
}
get httpVersion () {
return `${this.httpVersionMajor}.${this.httpVersionMinor}`
return `${this.httpVersionMajor}.${this.httpVersionMinor}`;
}
get httpVersionMajor () {
return this._responseHead.httpVersion.major
return this._responseHead.httpVersion.major;
}
get httpVersionMinor () {
return this._responseHead.httpVersion.minor
return this._responseHead.httpVersion.minor;
}
get rawTrailers () {
throw new Error('HTTP trailers are not supported')
throw new Error('HTTP trailers are not supported');
}
get trailers () {
throw new Error('HTTP trailers are not supported')
throw new Error('HTTP trailers are not supported');
}
_storeInternalData (chunk) {
this._data.push(chunk)
this._pushInternalData()
this._data.push(chunk);
this._pushInternalData();
}
_pushInternalData () {
while (this._shouldPush && this._data.length > 0) {
const chunk = this._data.shift()
this._shouldPush = this.push(chunk)
const chunk = this._data.shift();
this._shouldPush = this.push(chunk);
}
}
_read () {
this._shouldPush = true
this._pushInternalData()
this._shouldPush = true;
this._pushInternalData();
}
}
/** Writable stream that buffers up everything written to it. */
class SlurpStream extends Writable {
constructor () {
super()
this._data = Buffer.alloc(0)
super();
this._data = Buffer.alloc(0);
}
_write (chunk, encoding, callback) {
this._data = Buffer.concat([this._data, chunk])
callback()
this._data = Buffer.concat([this._data, chunk]);
callback();
}
data () { return this._data }
data () { return this._data; }
}
class ChunkedBodyStream extends Writable {
constructor (clientRequest) {
super()
this._clientRequest = clientRequest
super();
this._clientRequest = clientRequest;
}
_write (chunk, encoding, callback) {
if (this._downstream) {
this._downstream.write(chunk).then(callback, callback)
this._downstream.write(chunk).then(callback, callback);
} else {
// the contract of _write is that we won't be called again until we call
// the callback, so we're good to just save a single chunk.
this._pendingChunk = chunk
this._pendingCallback = callback
this._pendingChunk = chunk;
this._pendingCallback = callback;
// The first write to a chunked body stream begins the request.
this._clientRequest._startRequest()
this._clientRequest._startRequest();
}
}
_final (callback) {
this._downstream.done()
callback()
this._downstream.done();
callback();
}
startReading (pipe) {
if (this._downstream) {
throw new Error('two startReading calls???')
throw new Error('two startReading calls???');
}
this._downstream = pipe
this._downstream = pipe;
if (this._pendingChunk) {
const doneWriting = (maybeError) => {
const cb = this._pendingCallback
delete this._pendingCallback
delete this._pendingChunk
cb(maybeError)
}
this._downstream.write(this._pendingChunk).then(doneWriting, doneWriting)
const cb = this._pendingCallback;
delete this._pendingCallback;
delete this._pendingChunk;
cb(maybeError);
};
this._downstream.write(this._pendingChunk).then(doneWriting, doneWriting);
}
}
}
function parseOptions (options) {
if (typeof options === 'string') {
options = url.parse(options)
options = url.parse(options);
} else {
options = { ...options }
options = { ...options };
}
const method = (options.method || 'GET').toUpperCase()
let urlStr = options.url
const method = (options.method || 'GET').toUpperCase();
let urlStr = options.url;
if (!urlStr) {
const urlObj = {}
const protocol = options.protocol || 'http:'
const urlObj = {};
const protocol = options.protocol || 'http:';
if (!kSupportedProtocols.has(protocol)) {
throw new Error('Protocol "' + protocol + '" not supported')
throw new Error('Protocol "' + protocol + '" not supported');
}
urlObj.protocol = protocol
urlObj.protocol = protocol;
if (options.host) {
urlObj.host = options.host
urlObj.host = options.host;
} else {
if (options.hostname) {
urlObj.hostname = options.hostname
urlObj.hostname = options.hostname;
} else {
urlObj.hostname = 'localhost'
urlObj.hostname = 'localhost';
}
if (options.port) {
urlObj.port = options.port
urlObj.port = options.port;
}
}
@ -214,22 +214,22 @@ function parseOptions (options) {
// well, and b) possibly too restrictive for real-world usage. That's
// why it only scans for spaces because those are guaranteed to create
// an invalid request.
throw new TypeError('Request path contains unescaped characters')
throw new TypeError('Request path contains unescaped characters');
}
const pathObj = url.parse(options.path || '/')
urlObj.pathname = pathObj.pathname
urlObj.search = pathObj.search
urlObj.hash = pathObj.hash
urlStr = url.format(urlObj)
const pathObj = url.parse(options.path || '/');
urlObj.pathname = pathObj.pathname;
urlObj.search = pathObj.search;
urlObj.hash = pathObj.hash;
urlStr = url.format(urlObj);
}
const redirectPolicy = options.redirect || 'follow'
const redirectPolicy = options.redirect || 'follow';
if (!['follow', 'error', 'manual'].includes(redirectPolicy)) {
throw new Error('redirect mode should be one of follow, error or manual')
throw new Error('redirect mode should be one of follow, error or manual');
}
if (options.headers != null && typeof options.headers !== 'object') {
throw new TypeError('headers must be an object')
throw new TypeError('headers must be an object');
}
const urlLoaderOptions = {
@ -237,180 +237,180 @@ function parseOptions (options) {
url: urlStr,
redirectPolicy,
extraHeaders: options.headers || {}
}
};
for (const [name, value] of Object.entries(urlLoaderOptions.extraHeaders)) {
if (!_isValidHeaderName(name)) {
throw new Error(`Invalid header name: '${name}'`)
throw new Error(`Invalid header name: '${name}'`);
}
if (!_isValidHeaderValue(value.toString())) {
throw new Error(`Invalid value for header '${name}': '${value}'`)
throw new Error(`Invalid value for header '${name}': '${value}'`);
}
}
if (options.session) {
if (options.session instanceof Session) {
urlLoaderOptions.session = options.session
urlLoaderOptions.session = options.session;
} else {
throw new TypeError('`session` should be an instance of the Session class')
throw new TypeError('`session` should be an instance of the Session class');
}
} else if (options.partition) {
if (typeof options.partition === 'string') {
urlLoaderOptions.partition = options.partition
urlLoaderOptions.partition = options.partition;
} else {
throw new TypeError('`partition` should be a string')
throw new TypeError('`partition` should be a string');
}
}
return urlLoaderOptions
return urlLoaderOptions;
}
class ClientRequest extends Writable {
constructor (options, callback) {
super({ autoDestroy: true })
super({ autoDestroy: true });
if (!app.isReady()) {
throw new Error('net module can only be used after app is ready')
throw new Error('net module can only be used after app is ready');
}
if (callback) {
this.once('response', callback)
this.once('response', callback);
}
const { redirectPolicy, ...urlLoaderOptions } = parseOptions(options)
this._urlLoaderOptions = urlLoaderOptions
this._redirectPolicy = redirectPolicy
this._started = false
const { redirectPolicy, ...urlLoaderOptions } = parseOptions(options);
this._urlLoaderOptions = urlLoaderOptions;
this._redirectPolicy = redirectPolicy;
this._started = false;
}
set chunkedEncoding (value) {
if (this._started) {
throw new Error('chunkedEncoding can only be set before the request is started')
throw new Error('chunkedEncoding can only be set before the request is started');
}
if (typeof this._chunkedEncoding !== 'undefined') {
throw new Error('chunkedEncoding can only be set once')
throw new Error('chunkedEncoding can only be set once');
}
this._chunkedEncoding = !!value
this._chunkedEncoding = !!value;
if (this._chunkedEncoding) {
this._body = new ChunkedBodyStream(this)
this._body = new ChunkedBodyStream(this);
this._urlLoaderOptions.body = (pipe) => {
this._body.startReading(pipe)
}
this._body.startReading(pipe);
};
}
}
setHeader (name, value) {
if (typeof name !== 'string') {
throw new TypeError('`name` should be a string in setHeader(name, value)')
throw new TypeError('`name` should be a string in setHeader(name, value)');
}
if (value == null) {
throw new Error('`value` required in setHeader("' + name + '", value)')
throw new Error('`value` required in setHeader("' + name + '", value)');
}
if (this._started || this._firstWrite) {
throw new Error('Can\'t set headers after they are sent')
throw new Error('Can\'t set headers after they are sent');
}
if (!_isValidHeaderName(name)) {
throw new Error(`Invalid header name: '${name}'`)
throw new Error(`Invalid header name: '${name}'`);
}
if (!_isValidHeaderValue(value.toString())) {
throw new Error(`Invalid value for header '${name}': '${value}'`)
throw new Error(`Invalid value for header '${name}': '${value}'`);
}
const key = name.toLowerCase()
this._urlLoaderOptions.extraHeaders[key] = value
const key = name.toLowerCase();
this._urlLoaderOptions.extraHeaders[key] = value;
}
getHeader (name) {
if (name == null) {
throw new Error('`name` is required for getHeader(name)')
throw new Error('`name` is required for getHeader(name)');
}
const key = name.toLowerCase()
return this._urlLoaderOptions.extraHeaders[key]
const key = name.toLowerCase();
return this._urlLoaderOptions.extraHeaders[key];
}
removeHeader (name) {
if (name == null) {
throw new Error('`name` is required for removeHeader(name)')
throw new Error('`name` is required for removeHeader(name)');
}
if (this._started || this._firstWrite) {
throw new Error('Can\'t remove headers after they are sent')
throw new Error('Can\'t remove headers after they are sent');
}
const key = name.toLowerCase()
delete this._urlLoaderOptions.extraHeaders[key]
const key = name.toLowerCase();
delete this._urlLoaderOptions.extraHeaders[key];
}
_write (chunk, encoding, callback) {
this._firstWrite = true
this._firstWrite = true;
if (!this._body) {
this._body = new SlurpStream()
this._body = new SlurpStream();
this._body.on('finish', () => {
this._urlLoaderOptions.body = this._body.data()
this._startRequest()
})
this._urlLoaderOptions.body = this._body.data();
this._startRequest();
});
}
// TODO: is this the right way to forward to another stream?
this._body.write(chunk, encoding, callback)
this._body.write(chunk, encoding, callback);
}
_final (callback) {
if (this._body) {
// TODO: is this the right way to forward to another stream?
this._body.end(callback)
this._body.end(callback);
} else {
// end() called without a body, go ahead and start the request
this._startRequest()
callback()
this._startRequest();
callback();
}
}
_startRequest () {
this._started = true
this._started = true;
const stringifyValues = (obj) => {
const ret = {}
const ret = {};
for (const k of Object.keys(obj)) {
ret[k] = obj[k].toString()
ret[k] = obj[k].toString();
}
return ret
}
const opts = { ...this._urlLoaderOptions, extraHeaders: stringifyValues(this._urlLoaderOptions.extraHeaders) }
this._urlLoader = new URLLoader(opts)
return ret;
};
const opts = { ...this._urlLoaderOptions, extraHeaders: stringifyValues(this._urlLoaderOptions.extraHeaders) };
this._urlLoader = new URLLoader(opts);
this._urlLoader.on('response-started', (event, finalUrl, responseHead) => {
const response = this._response = new IncomingMessage(responseHead)
this.emit('response', response)
})
const response = this._response = new IncomingMessage(responseHead);
this.emit('response', response);
});
this._urlLoader.on('data', (event, data) => {
this._response._storeInternalData(Buffer.from(data))
})
this._response._storeInternalData(Buffer.from(data));
});
this._urlLoader.on('complete', () => {
if (this._response) { this._response._storeInternalData(null) }
})
if (this._response) { this._response._storeInternalData(null); }
});
this._urlLoader.on('error', (event, netErrorString) => {
const error = new Error(netErrorString)
if (this._response) this._response.destroy(error)
this._die(error)
})
const error = new Error(netErrorString);
if (this._response) this._response.destroy(error);
this._die(error);
});
this._urlLoader.on('login', (event, authInfo, callback) => {
const handled = this.emit('login', authInfo, callback)
const handled = this.emit('login', authInfo, callback);
if (!handled) {
// If there were no listeners, cancel the authentication request.
callback()
callback();
}
})
});
this._urlLoader.on('redirect', (event, redirectInfo, headers) => {
const { statusCode, newMethod, newUrl } = redirectInfo
const { statusCode, newMethod, newUrl } = redirectInfo;
if (this._redirectPolicy === 'error') {
this._die(new Error('Attempted to redirect, but redirect policy was \'error\''))
this._die(new Error('Attempted to redirect, but redirect policy was \'error\''));
} else if (this._redirectPolicy === 'manual') {
let _followRedirect = false
this._followRedirectCb = () => { _followRedirect = true }
let _followRedirect = false;
this._followRedirectCb = () => { _followRedirect = true; };
try {
this.emit('redirect', statusCode, newMethod, newUrl, headers)
this.emit('redirect', statusCode, newMethod, newUrl, headers);
} finally {
this._followRedirectCb = null
this._followRedirectCb = null;
if (!_followRedirect && !this._aborted) {
this._die(new Error('Redirect was cancelled'))
this._die(new Error('Redirect was cancelled'));
}
}
} else if (this._redirectPolicy === 'follow') {
@ -418,61 +418,61 @@ class ClientRequest extends Writable {
// allowed but does nothing. (Perhaps it should throw an error
// though...? Since the redirect will happen regardless.)
try {
this._followRedirectCb = () => {}
this.emit('redirect', statusCode, newMethod, newUrl, headers)
this._followRedirectCb = () => {};
this.emit('redirect', statusCode, newMethod, newUrl, headers);
} finally {
this._followRedirectCb = null
this._followRedirectCb = null;
}
} else {
this._die(new Error(`Unexpected redirect policy '${this._redirectPolicy}'`))
this._die(new Error(`Unexpected redirect policy '${this._redirectPolicy}'`));
}
})
});
this._urlLoader.on('upload-progress', (event, position, total) => {
this._uploadProgress = { active: true, started: true, current: position, total }
this.emit('upload-progress', position, total) // Undocumented, for now
})
this._uploadProgress = { active: true, started: true, current: position, total };
this.emit('upload-progress', position, total); // Undocumented, for now
});
this._urlLoader.on('download-progress', (event, current) => {
if (this._response) {
this._response.emit('download-progress', current) // Undocumented, for now
this._response.emit('download-progress', current); // Undocumented, for now
}
})
});
}
followRedirect () {
if (this._followRedirectCb) {
this._followRedirectCb()
this._followRedirectCb();
} else {
throw new Error('followRedirect() called, but was not waiting for a redirect')
throw new Error('followRedirect() called, but was not waiting for a redirect');
}
}
abort () {
if (!this._aborted) {
process.nextTick(() => { this.emit('abort') })
process.nextTick(() => { this.emit('abort'); });
}
this._aborted = true
this._die()
this._aborted = true;
this._die();
}
_die (err) {
this.destroy(err)
this.destroy(err);
if (this._urlLoader) {
this._urlLoader.cancel()
if (this._response) this._response.destroy(err)
this._urlLoader.cancel();
if (this._response) this._response.destroy(err);
}
}
getUploadProgress () {
return this._uploadProgress ? { ...this._uploadProgress } : { active: false }
return this._uploadProgress ? { ...this._uploadProgress } : { active: false };
}
}
Net.prototype.request = function (options, callback) {
return new ClientRequest(options, callback)
}
return new ClientRequest(options, callback);
};
net.ClientRequest = ClientRequest
net.ClientRequest = ClientRequest;
module.exports = net
module.exports = net;

View file

@ -1,10 +1,10 @@
'use strict'
'use strict';
const { EventEmitter } = require('events')
const { Notification, isSupported } = process.electronBinding('notification')
const { EventEmitter } = require('events');
const { Notification, isSupported } = process.electronBinding('notification');
Object.setPrototypeOf(Notification.prototype, EventEmitter.prototype)
Object.setPrototypeOf(Notification.prototype, EventEmitter.prototype);
Notification.isSupported = isSupported
Notification.isSupported = isSupported;
module.exports = Notification
module.exports = Notification;

View file

@ -1,14 +1,14 @@
'use strict'
'use strict';
import { createLazyInstance } from '../utils'
import { createLazyInstance } from '../utils';
const { EventEmitter } = require('events')
const { createPowerMonitor, PowerMonitor } = process.electronBinding('power_monitor')
const { EventEmitter } = require('events');
const { createPowerMonitor, PowerMonitor } = process.electronBinding('power_monitor');
// PowerMonitor is an EventEmitter.
Object.setPrototypeOf(PowerMonitor.prototype, EventEmitter.prototype)
Object.setPrototypeOf(PowerMonitor.prototype, EventEmitter.prototype);
const powerMonitor = createLazyInstance(createPowerMonitor, PowerMonitor, true)
const powerMonitor = createLazyInstance(createPowerMonitor, PowerMonitor, true);
if (process.platform === 'linux') {
// In order to delay system shutdown when e.preventDefault() is invoked
@ -18,21 +18,21 @@ if (process.platform === 'linux') {
//
// So here we watch for 'shutdown' listeners to be added or removed and
// set or unset our shutdown delay lock accordingly.
const { app } = require('electron')
const { app } = require('electron');
app.whenReady().then(() => {
powerMonitor.on('newListener', (event: string) => {
// whenever the listener count is incremented to one...
if (event === 'shutdown' && powerMonitor.listenerCount('shutdown') === 0) {
powerMonitor.blockShutdown()
powerMonitor.blockShutdown();
}
})
});
powerMonitor.on('removeListener', (event: string) => {
// whenever the listener count is decremented to zero...
if (event === 'shutdown' && powerMonitor.listenerCount('shutdown') === 0) {
powerMonitor.unblockShutdown()
powerMonitor.unblockShutdown();
}
})
})
});
});
}
module.exports = powerMonitor
module.exports = powerMonitor;

View file

@ -1,3 +1,3 @@
'use strict'
'use strict';
module.exports = process.electronBinding('power_save_blocker').powerSaveBlocker
module.exports = process.electronBinding('power_save_blocker').powerSaveBlocker;

View file

@ -1,29 +1,29 @@
import { app, session } from 'electron'
import { app, session } from 'electron';
// Global protocol APIs.
const protocol = process.electronBinding('protocol')
const protocol = process.electronBinding('protocol');
// Fallback protocol APIs of default session.
Object.setPrototypeOf(protocol, new Proxy({}, {
get (_target, property) {
if (!app.isReady()) return
if (!app.isReady()) return;
const protocol = session.defaultSession!.protocol
if (!Object.prototype.hasOwnProperty.call(Object.getPrototypeOf(protocol), property)) return
const protocol = session.defaultSession!.protocol;
if (!Object.prototype.hasOwnProperty.call(Object.getPrototypeOf(protocol), property)) return;
// Returning a native function directly would throw error.
return (...args: any[]) => (protocol[property as keyof Electron.Protocol] as Function)(...args)
return (...args: any[]) => (protocol[property as keyof Electron.Protocol] as Function)(...args);
},
ownKeys () {
if (!app.isReady()) return []
if (!app.isReady()) return [];
return Object.getOwnPropertyNames(Object.getPrototypeOf(session.defaultSession!.protocol))
return Object.getOwnPropertyNames(Object.getPrototypeOf(session.defaultSession!.protocol));
},
getOwnPropertyDescriptor () {
return { configurable: true, enumerable: true }
return { configurable: true, enumerable: true };
}
}))
}));
export default protocol
export default protocol;

View file

@ -1,10 +1,10 @@
'use strict'
'use strict';
import { createLazyInstance } from '../utils'
const { EventEmitter } = require('events')
const { Screen, createScreen } = process.electronBinding('screen')
import { createLazyInstance } from '../utils';
const { EventEmitter } = require('events');
const { Screen, createScreen } = process.electronBinding('screen');
// Screen is an EventEmitter.
Object.setPrototypeOf(Screen.prototype, EventEmitter.prototype)
Object.setPrototypeOf(Screen.prototype, EventEmitter.prototype);
module.exports = createLazyInstance(createScreen, Screen, true)
module.exports = createLazyInstance(createScreen, Screen, true);

View file

@ -1,25 +1,25 @@
'use strict'
'use strict';
const { EventEmitter } = require('events')
const { app, deprecate } = require('electron')
const { fromPartition, Session, Cookies, Protocol, ServiceWorkerContext } = process.electronBinding('session')
const { EventEmitter } = require('events');
const { app, deprecate } = require('electron');
const { fromPartition, Session, Cookies, Protocol, ServiceWorkerContext } = process.electronBinding('session');
// Public API.
Object.defineProperties(exports, {
defaultSession: {
enumerable: true,
get () { return fromPartition('') }
get () { return fromPartition(''); }
},
fromPartition: {
enumerable: true,
value: fromPartition
}
})
});
Object.setPrototypeOf(Cookies.prototype, EventEmitter.prototype)
Object.setPrototypeOf(ServiceWorkerContext.prototype, EventEmitter.prototype)
Object.setPrototypeOf(Session.prototype, EventEmitter.prototype)
Object.setPrototypeOf(Cookies.prototype, EventEmitter.prototype);
Object.setPrototypeOf(ServiceWorkerContext.prototype, EventEmitter.prototype);
Object.setPrototypeOf(Session.prototype, EventEmitter.prototype);
Session.prototype._init = function () {
app.emit('session-created', this)
}
app.emit('session-created', this);
};

View file

@ -1,41 +1,41 @@
import { EventEmitter } from 'events'
import { deprecate } from 'electron'
const { systemPreferences, SystemPreferences } = process.electronBinding('system_preferences')
import { EventEmitter } from 'events';
import { deprecate } from 'electron';
const { systemPreferences, SystemPreferences } = process.electronBinding('system_preferences');
// SystemPreferences is an EventEmitter.
Object.setPrototypeOf(SystemPreferences.prototype, EventEmitter.prototype)
EventEmitter.call(systemPreferences)
Object.setPrototypeOf(SystemPreferences.prototype, EventEmitter.prototype);
EventEmitter.call(systemPreferences);
if ('getAppLevelAppearance' in systemPreferences) {
const nativeALAGetter = systemPreferences.getAppLevelAppearance
const nativeALASetter = systemPreferences.setAppLevelAppearance
const nativeALAGetter = systemPreferences.getAppLevelAppearance;
const nativeALASetter = systemPreferences.setAppLevelAppearance;
Object.defineProperty(SystemPreferences.prototype, 'appLevelAppearance', {
get: () => nativeALAGetter.call(systemPreferences),
set: (appearance) => nativeALASetter.call(systemPreferences, appearance)
})
});
}
if ('getEffectiveAppearance' in systemPreferences) {
const nativeEAGetter = systemPreferences.getAppLevelAppearance
const nativeEAGetter = systemPreferences.getAppLevelAppearance;
Object.defineProperty(SystemPreferences.prototype, 'effectiveAppearance', {
get: () => nativeEAGetter.call(systemPreferences)
})
});
}
SystemPreferences.prototype.isDarkMode = deprecate.moveAPI(
SystemPreferences.prototype.isDarkMode,
'systemPreferences.isDarkMode()',
'nativeTheme.shouldUseDarkColors'
)
);
SystemPreferences.prototype.isInvertedColorScheme = deprecate.moveAPI(
SystemPreferences.prototype.isInvertedColorScheme,
'systemPreferences.isInvertedColorScheme()',
'nativeTheme.shouldUseInvertedColorScheme'
)
);
SystemPreferences.prototype.isHighContrastColorScheme = deprecate.moveAPI(
SystemPreferences.prototype.isHighContrastColorScheme,
'systemPreferences.isHighContrastColorScheme()',
'nativeTheme.shouldUseHighContrastColors'
)
);
module.exports = systemPreferences
module.exports = systemPreferences;

View file

@ -1,24 +1,24 @@
'use strict'
'use strict';
const electron = require('electron')
const { EventEmitter } = require('events')
const { TopLevelWindow } = process.electronBinding('top_level_window')
const electron = require('electron');
const { EventEmitter } = require('events');
const { TopLevelWindow } = process.electronBinding('top_level_window');
Object.setPrototypeOf(TopLevelWindow.prototype, EventEmitter.prototype)
Object.setPrototypeOf(TopLevelWindow.prototype, EventEmitter.prototype);
TopLevelWindow.prototype._init = function () {
// Avoid recursive require.
const { app } = electron
const { app } = electron;
// Simulate the application menu on platforms other than macOS.
if (process.platform !== 'darwin') {
const menu = app.applicationMenu
if (menu) this.setMenu(menu)
const menu = app.applicationMenu;
if (menu) this.setMenu(menu);
}
}
};
TopLevelWindow.getFocusedWindow = () => {
return TopLevelWindow.getAllWindows().find((win) => win.isFocused())
}
return TopLevelWindow.getAllWindows().find((win) => win.isFocused());
};
module.exports = TopLevelWindow
module.exports = TopLevelWindow;

View file

@ -1,365 +1,365 @@
'use strict'
'use strict';
const { EventEmitter } = require('events')
const { EventEmitter } = require('events');
let nextItemID = 1
let nextItemID = 1;
class TouchBar extends EventEmitter {
// Bind a touch bar to a window
static _setOnWindow (touchBar, window) {
if (window._touchBar != null) {
window._touchBar._removeFromWindow(window)
window._touchBar._removeFromWindow(window);
}
if (touchBar == null) {
window._setTouchBarItems([])
return
window._setTouchBarItems([]);
return;
}
if (Array.isArray(touchBar)) {
touchBar = new TouchBar(touchBar)
touchBar = new TouchBar(touchBar);
}
touchBar._addToWindow(window)
touchBar._addToWindow(window);
}
constructor (options) {
super()
super();
if (options == null) {
throw new Error('Must specify options object as first argument')
throw new Error('Must specify options object as first argument');
}
let { items, escapeItem } = options
let { items, escapeItem } = options;
if (!Array.isArray(items)) {
items = []
items = [];
}
this.changeListener = (item) => {
this.emit('change', item.id, item.type)
}
this.emit('change', item.id, item.type);
};
this.windowListeners = {}
this.items = {}
this.ordereredItems = []
this.escapeItem = escapeItem
this.windowListeners = {};
this.items = {};
this.ordereredItems = [];
this.escapeItem = escapeItem;
const registerItem = (item) => {
this.items[item.id] = item
item.on('change', this.changeListener)
this.items[item.id] = item;
item.on('change', this.changeListener);
if (item.child instanceof TouchBar) {
item.child.ordereredItems.forEach(registerItem)
item.child.ordereredItems.forEach(registerItem);
}
}
};
let hasOtherItemsProxy = false
const idSet = new Set()
let hasOtherItemsProxy = false;
const idSet = new Set();
items.forEach((item) => {
if (!(item instanceof TouchBarItem)) {
throw new Error('Each item must be an instance of TouchBarItem')
throw new Error('Each item must be an instance of TouchBarItem');
}
if (item.type === 'other_items_proxy') {
if (!hasOtherItemsProxy) {
hasOtherItemsProxy = true
hasOtherItemsProxy = true;
} else {
throw new Error('Must only have one OtherItemsProxy per TouchBar')
throw new Error('Must only have one OtherItemsProxy per TouchBar');
}
}
if (!idSet.has(item.id)) {
idSet.add(item.id)
idSet.add(item.id);
} else {
throw new Error('Cannot add a single instance of TouchBarItem multiple times in a TouchBar')
throw new Error('Cannot add a single instance of TouchBarItem multiple times in a TouchBar');
}
})
});
// register in separate loop after all items are validated
for (const item of items) {
this.ordereredItems.push(item)
registerItem(item)
this.ordereredItems.push(item);
registerItem(item);
}
}
set escapeItem (item) {
if (item != null && !(item instanceof TouchBarItem)) {
throw new Error('Escape item must be an instance of TouchBarItem')
throw new Error('Escape item must be an instance of TouchBarItem');
}
if (this.escapeItem != null) {
this.escapeItem.removeListener('change', this.changeListener)
this.escapeItem.removeListener('change', this.changeListener);
}
this._escapeItem = item
this._escapeItem = item;
if (this.escapeItem != null) {
this.escapeItem.on('change', this.changeListener)
this.escapeItem.on('change', this.changeListener);
}
this.emit('escape-item-change', item)
this.emit('escape-item-change', item);
}
get escapeItem () {
return this._escapeItem
return this._escapeItem;
}
_addToWindow (window) {
const { id } = window
const { id } = window;
// Already added to window
if (Object.prototype.hasOwnProperty.call(this.windowListeners, id)) return
if (Object.prototype.hasOwnProperty.call(this.windowListeners, id)) return;
window._touchBar = this
window._touchBar = this;
const changeListener = (itemID) => {
window._refreshTouchBarItem(itemID)
}
this.on('change', changeListener)
window._refreshTouchBarItem(itemID);
};
this.on('change', changeListener);
const escapeItemListener = (item) => {
window._setEscapeTouchBarItem(item != null ? item : {})
}
this.on('escape-item-change', escapeItemListener)
window._setEscapeTouchBarItem(item != null ? item : {});
};
this.on('escape-item-change', escapeItemListener);
const interactionListener = (event, itemID, details) => {
let item = this.items[itemID]
let item = this.items[itemID];
if (item == null && this.escapeItem != null && this.escapeItem.id === itemID) {
item = this.escapeItem
item = this.escapeItem;
}
if (item != null && item.onInteraction != null) {
item.onInteraction(details)
item.onInteraction(details);
}
}
window.on('-touch-bar-interaction', interactionListener)
};
window.on('-touch-bar-interaction', interactionListener);
const removeListeners = () => {
this.removeListener('change', changeListener)
this.removeListener('escape-item-change', escapeItemListener)
window.removeListener('-touch-bar-interaction', interactionListener)
window.removeListener('closed', removeListeners)
window._touchBar = null
delete this.windowListeners[id]
this.removeListener('change', changeListener);
this.removeListener('escape-item-change', escapeItemListener);
window.removeListener('-touch-bar-interaction', interactionListener);
window.removeListener('closed', removeListeners);
window._touchBar = null;
delete this.windowListeners[id];
const unregisterItems = (items) => {
for (const item of items) {
item.removeListener('change', this.changeListener)
item.removeListener('change', this.changeListener);
if (item.child instanceof TouchBar) {
unregisterItems(item.child.ordereredItems)
unregisterItems(item.child.ordereredItems);
}
}
}
unregisterItems(this.ordereredItems)
};
unregisterItems(this.ordereredItems);
if (this.escapeItem) {
this.escapeItem.removeListener('change', this.changeListener)
this.escapeItem.removeListener('change', this.changeListener);
}
}
window.once('closed', removeListeners)
this.windowListeners[id] = removeListeners
};
window.once('closed', removeListeners);
this.windowListeners[id] = removeListeners;
window._setTouchBarItems(this.ordereredItems)
escapeItemListener(this.escapeItem)
window._setTouchBarItems(this.ordereredItems);
escapeItemListener(this.escapeItem);
}
_removeFromWindow (window) {
const removeListeners = this.windowListeners[window.id]
if (removeListeners != null) removeListeners()
const removeListeners = this.windowListeners[window.id];
if (removeListeners != null) removeListeners();
}
}
class TouchBarItem extends EventEmitter {
constructor () {
super()
this._addImmutableProperty('id', `${nextItemID++}`)
this._parents = []
super();
this._addImmutableProperty('id', `${nextItemID++}`);
this._parents = [];
}
_addImmutableProperty (name, value) {
Object.defineProperty(this, name, {
get: function () {
return value
return value;
},
set: function () {
throw new Error(`Cannot override property ${name}`)
throw new Error(`Cannot override property ${name}`);
},
enumerable: true,
configurable: false
})
});
}
_addLiveProperty (name, initialValue) {
const privateName = `_${name}`
this[privateName] = initialValue
const privateName = `_${name}`;
this[privateName] = initialValue;
Object.defineProperty(this, name, {
get: function () {
return this[privateName]
return this[privateName];
},
set: function (value) {
this[privateName] = value
this.emit('change', this)
this[privateName] = value;
this.emit('change', this);
},
enumerable: true
})
});
}
_addParent (item) {
const existing = this._parents.some(test => test.id === item.id)
const existing = this._parents.some(test => test.id === item.id);
if (!existing) {
this._parents.push({
id: item.id,
type: item.type
})
});
}
}
}
TouchBar.TouchBarButton = class TouchBarButton extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
this._addImmutableProperty('type', 'button')
this._addLiveProperty('label', config.label)
this._addLiveProperty('accessibilityLabel', config.accessibilityLabel)
this._addLiveProperty('backgroundColor', config.backgroundColor)
this._addLiveProperty('icon', config.icon)
this._addLiveProperty('iconPosition', config.iconPosition)
this._addLiveProperty('enabled', typeof config.enabled !== 'boolean' ? true : config.enabled)
super();
if (config == null) config = {};
this._addImmutableProperty('type', 'button');
this._addLiveProperty('label', config.label);
this._addLiveProperty('accessibilityLabel', config.accessibilityLabel);
this._addLiveProperty('backgroundColor', config.backgroundColor);
this._addLiveProperty('icon', config.icon);
this._addLiveProperty('iconPosition', config.iconPosition);
this._addLiveProperty('enabled', typeof config.enabled !== 'boolean' ? true : config.enabled);
if (typeof config.click === 'function') {
this._addImmutableProperty('onInteraction', () => {
config.click()
})
config.click();
});
}
}
}
};
TouchBar.TouchBarColorPicker = class TouchBarColorPicker extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
this._addImmutableProperty('type', 'colorpicker')
this._addLiveProperty('availableColors', config.availableColors)
this._addLiveProperty('selectedColor', config.selectedColor)
super();
if (config == null) config = {};
this._addImmutableProperty('type', 'colorpicker');
this._addLiveProperty('availableColors', config.availableColors);
this._addLiveProperty('selectedColor', config.selectedColor);
if (typeof config.change === 'function') {
this._addImmutableProperty('onInteraction', (details) => {
this._selectedColor = details.color
config.change(details.color)
})
this._selectedColor = details.color;
config.change(details.color);
});
}
}
}
};
TouchBar.TouchBarGroup = class TouchBarGroup extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
this._addImmutableProperty('type', 'group')
const defaultChild = (config.items instanceof TouchBar) ? config.items : new TouchBar(config.items)
this._addLiveProperty('child', defaultChild)
this.child.ordereredItems.forEach((item) => item._addParent(this))
super();
if (config == null) config = {};
this._addImmutableProperty('type', 'group');
const defaultChild = (config.items instanceof TouchBar) ? config.items : new TouchBar(config.items);
this._addLiveProperty('child', defaultChild);
this.child.ordereredItems.forEach((item) => item._addParent(this));
}
}
};
TouchBar.TouchBarLabel = class TouchBarLabel extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
this._addImmutableProperty('type', 'label')
this._addLiveProperty('label', config.label)
this._addLiveProperty('accessibilityLabel', config.accessibilityLabel)
this._addLiveProperty('textColor', config.textColor)
super();
if (config == null) config = {};
this._addImmutableProperty('type', 'label');
this._addLiveProperty('label', config.label);
this._addLiveProperty('accessibilityLabel', config.accessibilityLabel);
this._addLiveProperty('textColor', config.textColor);
}
}
};
TouchBar.TouchBarPopover = class TouchBarPopover extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
this._addImmutableProperty('type', 'popover')
this._addLiveProperty('label', config.label)
this._addLiveProperty('icon', config.icon)
this._addLiveProperty('showCloseButton', config.showCloseButton)
const defaultChild = (config.items instanceof TouchBar) ? config.items : new TouchBar(config.items)
this._addLiveProperty('child', defaultChild)
this.child.ordereredItems.forEach((item) => item._addParent(this))
super();
if (config == null) config = {};
this._addImmutableProperty('type', 'popover');
this._addLiveProperty('label', config.label);
this._addLiveProperty('icon', config.icon);
this._addLiveProperty('showCloseButton', config.showCloseButton);
const defaultChild = (config.items instanceof TouchBar) ? config.items : new TouchBar(config.items);
this._addLiveProperty('child', defaultChild);
this.child.ordereredItems.forEach((item) => item._addParent(this));
}
}
};
TouchBar.TouchBarSlider = class TouchBarSlider extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
this._addImmutableProperty('type', 'slider')
this._addLiveProperty('label', config.label)
this._addLiveProperty('minValue', config.minValue)
this._addLiveProperty('maxValue', config.maxValue)
this._addLiveProperty('value', config.value)
super();
if (config == null) config = {};
this._addImmutableProperty('type', 'slider');
this._addLiveProperty('label', config.label);
this._addLiveProperty('minValue', config.minValue);
this._addLiveProperty('maxValue', config.maxValue);
this._addLiveProperty('value', config.value);
if (typeof config.change === 'function') {
this._addImmutableProperty('onInteraction', (details) => {
this._value = details.value
config.change(details.value)
})
this._value = details.value;
config.change(details.value);
});
}
}
}
};
TouchBar.TouchBarSpacer = class TouchBarSpacer extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
this._addImmutableProperty('type', 'spacer')
this._addImmutableProperty('size', config.size)
super();
if (config == null) config = {};
this._addImmutableProperty('type', 'spacer');
this._addImmutableProperty('size', config.size);
}
}
};
TouchBar.TouchBarSegmentedControl = class TouchBarSegmentedControl extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
this._addImmutableProperty('type', 'segmented_control')
this._addLiveProperty('segmentStyle', config.segmentStyle)
this._addLiveProperty('segments', config.segments || [])
this._addLiveProperty('selectedIndex', config.selectedIndex)
this._addLiveProperty('mode', config.mode)
super();
if (config == null) config = {};
this._addImmutableProperty('type', 'segmented_control');
this._addLiveProperty('segmentStyle', config.segmentStyle);
this._addLiveProperty('segments', config.segments || []);
this._addLiveProperty('selectedIndex', config.selectedIndex);
this._addLiveProperty('mode', config.mode);
if (typeof config.change === 'function') {
this._addImmutableProperty('onInteraction', (details) => {
this._selectedIndex = details.selectedIndex
config.change(details.selectedIndex, details.isSelected)
})
this._selectedIndex = details.selectedIndex;
config.change(details.selectedIndex, details.isSelected);
});
}
}
}
};
TouchBar.TouchBarScrubber = class TouchBarScrubber extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
let { select, highlight } = config
this._addImmutableProperty('type', 'scrubber')
this._addLiveProperty('items', config.items)
this._addLiveProperty('selectedStyle', config.selectedStyle || null)
this._addLiveProperty('overlayStyle', config.overlayStyle || null)
this._addLiveProperty('showArrowButtons', config.showArrowButtons || false)
this._addLiveProperty('mode', config.mode || 'free')
super();
if (config == null) config = {};
let { select, highlight } = config;
this._addImmutableProperty('type', 'scrubber');
this._addLiveProperty('items', config.items);
this._addLiveProperty('selectedStyle', config.selectedStyle || null);
this._addLiveProperty('overlayStyle', config.overlayStyle || null);
this._addLiveProperty('showArrowButtons', config.showArrowButtons || false);
this._addLiveProperty('mode', config.mode || 'free');
const cont = typeof config.continuous === 'undefined' ? true : config.continuous
this._addLiveProperty('continuous', cont)
const cont = typeof config.continuous === 'undefined' ? true : config.continuous;
this._addLiveProperty('continuous', cont);
if (typeof select === 'function' || typeof highlight === 'function') {
if (select == null) select = () => {}
if (highlight == null) highlight = () => {}
if (select == null) select = () => {};
if (highlight == null) highlight = () => {};
this._addImmutableProperty('onInteraction', (details) => {
if (details.type === 'select' && typeof select === 'function') {
select(details.selectedIndex)
select(details.selectedIndex);
} else if (details.type === 'highlight' && typeof highlight === 'function') {
highlight(details.highlightedIndex)
highlight(details.highlightedIndex);
}
})
});
}
}
}
};
TouchBar.TouchBarOtherItemsProxy = class TouchBarOtherItemsProxy extends TouchBarItem {
constructor (config) {
super()
this._addImmutableProperty('type', 'other_items_proxy')
super();
this._addImmutableProperty('type', 'other_items_proxy');
}
}
};
module.exports = TouchBar
module.exports = TouchBar;

View file

@ -1,9 +1,9 @@
'use strict'
'use strict';
const { EventEmitter } = require('events')
const { deprecate } = require('electron')
const { Tray } = process.electronBinding('tray')
const { EventEmitter } = require('events');
const { deprecate } = require('electron');
const { Tray } = process.electronBinding('tray');
Object.setPrototypeOf(Tray.prototype, EventEmitter.prototype)
Object.setPrototypeOf(Tray.prototype, EventEmitter.prototype);
module.exports = Tray
module.exports = Tray;

View file

@ -1,11 +1,11 @@
'use strict'
'use strict';
const { EventEmitter } = require('events')
const { View } = process.electronBinding('view')
const { EventEmitter } = require('events');
const { View } = process.electronBinding('view');
Object.setPrototypeOf(View.prototype, EventEmitter.prototype)
Object.setPrototypeOf(View.prototype, EventEmitter.prototype);
View.prototype._init = function () {
}
};
module.exports = View
module.exports = View;

View file

@ -1,15 +1,15 @@
'use strict'
'use strict';
const electron = require('electron')
const electron = require('electron');
const { LayoutManager } = electron
const { BoxLayout } = process.electronBinding('box_layout')
const { LayoutManager } = electron;
const { BoxLayout } = process.electronBinding('box_layout');
Object.setPrototypeOf(BoxLayout.prototype, LayoutManager.prototype)
Object.setPrototypeOf(BoxLayout.prototype, LayoutManager.prototype);
BoxLayout.prototype._init = function () {
// Call parent class's _init.
LayoutManager.prototype._init.call(this)
}
LayoutManager.prototype._init.call(this);
};
module.exports = BoxLayout
module.exports = BoxLayout;

View file

@ -1,15 +1,15 @@
'use strict'
'use strict';
const electron = require('electron')
const electron = require('electron');
const { View } = electron
const { Button } = process.electronBinding('button')
const { View } = electron;
const { Button } = process.electronBinding('button');
Object.setPrototypeOf(Button.prototype, View.prototype)
Object.setPrototypeOf(Button.prototype, View.prototype);
Button.prototype._init = function () {
// Call parent class's _init.
View.prototype._init.call(this)
}
View.prototype._init.call(this);
};
module.exports = Button
module.exports = Button;

View file

@ -1,15 +1,15 @@
'use strict'
'use strict';
const electron = require('electron')
const electron = require('electron');
const { Button } = electron
const { LabelButton } = process.electronBinding('label_button')
const { Button } = electron;
const { LabelButton } = process.electronBinding('label_button');
Object.setPrototypeOf(LabelButton.prototype, Button.prototype)
Object.setPrototypeOf(LabelButton.prototype, Button.prototype);
LabelButton.prototype._init = function () {
// Call parent class's _init.
Button.prototype._init.call(this)
}
Button.prototype._init.call(this);
};
module.exports = LabelButton
module.exports = LabelButton;

View file

@ -1,8 +1,8 @@
'use strict'
'use strict';
const { LayoutManager } = process.electronBinding('layout_manager')
const { LayoutManager } = process.electronBinding('layout_manager');
LayoutManager.prototype._init = function () {
}
};
module.exports = LayoutManager
module.exports = LayoutManager;

View file

@ -1,15 +1,15 @@
'use strict'
'use strict';
const electron = require('electron')
const electron = require('electron');
const { LabelButton } = electron
const { MdTextButton } = process.electronBinding('md_text_button')
const { LabelButton } = electron;
const { MdTextButton } = process.electronBinding('md_text_button');
Object.setPrototypeOf(MdTextButton.prototype, LabelButton.prototype)
Object.setPrototypeOf(MdTextButton.prototype, LabelButton.prototype);
MdTextButton.prototype._init = function () {
// Call parent class's _init.
LabelButton.prototype._init.call(this)
}
LabelButton.prototype._init.call(this);
};
module.exports = MdTextButton
module.exports = MdTextButton;

View file

@ -1,15 +1,15 @@
'use strict'
'use strict';
const electron = require('electron')
const electron = require('electron');
const { View } = electron
const { ResizeArea } = process.electronBinding('resize_area')
const { View } = electron;
const { ResizeArea } = process.electronBinding('resize_area');
Object.setPrototypeOf(ResizeArea.prototype, View.prototype)
Object.setPrototypeOf(ResizeArea.prototype, View.prototype);
ResizeArea.prototype._init = function () {
// Call parent class's _init.
View.prototype._init.call(this)
}
View.prototype._init.call(this);
};
module.exports = ResizeArea
module.exports = ResizeArea;

View file

@ -1,15 +1,15 @@
'use strict'
'use strict';
const electron = require('electron')
const electron = require('electron');
const { View } = electron
const { TextField } = process.electronBinding('text_field')
const { View } = electron;
const { TextField } = process.electronBinding('text_field');
Object.setPrototypeOf(TextField.prototype, View.prototype)
Object.setPrototypeOf(TextField.prototype, View.prototype);
TextField.prototype._init = function () {
// Call parent class's _init.
View.prototype._init.call(this)
}
View.prototype._init.call(this);
};
module.exports = TextField
module.exports = TextField;

View file

@ -1,15 +1,15 @@
'use strict'
'use strict';
const electron = require('electron')
const electron = require('electron');
const { View } = electron
const { WebContentsView } = process.electronBinding('web_contents_view')
const { View } = electron;
const { WebContentsView } = process.electronBinding('web_contents_view');
Object.setPrototypeOf(WebContentsView.prototype, View.prototype)
Object.setPrototypeOf(WebContentsView.prototype, View.prototype);
WebContentsView.prototype._init = function () {
// Call parent class's _init.
View.prototype._init.call(this)
}
View.prototype._init.call(this);
};
module.exports = WebContentsView
module.exports = WebContentsView;

View file

@ -1,27 +1,27 @@
'use strict'
'use strict';
const features = process.electronBinding('features')
const { EventEmitter } = require('events')
const electron = require('electron')
const path = require('path')
const url = require('url')
const { app, ipcMain, session } = electron
const features = process.electronBinding('features');
const { EventEmitter } = require('events');
const electron = require('electron');
const path = require('path');
const url = require('url');
const { app, ipcMain, session } = electron;
const { internalWindowOpen } = require('@electron/internal/browser/guest-window-manager')
const NavigationController = require('@electron/internal/browser/navigation-controller')
const { ipcMainInternal } = require('@electron/internal/browser/ipc-main-internal')
const ipcMainUtils = require('@electron/internal/browser/ipc-main-internal-utils')
const { MessagePortMain } = require('@electron/internal/browser/message-port-main')
const { internalWindowOpen } = require('@electron/internal/browser/guest-window-manager');
const NavigationController = require('@electron/internal/browser/navigation-controller');
const { ipcMainInternal } = require('@electron/internal/browser/ipc-main-internal');
const ipcMainUtils = require('@electron/internal/browser/ipc-main-internal-utils');
const { MessagePortMain } = require('@electron/internal/browser/message-port-main');
// session is not used here, the purpose is to make sure session is initalized
// before the webContents module.
// eslint-disable-next-line
session
let nextId = 0
let nextId = 0;
const getNextId = function () {
return ++nextId
}
return ++nextId;
};
// Stock page sizes
const PDFPageSizes = {
@ -62,7 +62,7 @@ const PDFPageSizes = {
width_microns: 279400,
custom_display_name: 'Tabloid'
}
}
};
// Default printing setting
const defaultPrintingSetting = {
@ -94,90 +94,90 @@ const defaultPrintingSetting = {
// 2 = color - see ColorModel in //printing/print_job_constants.h
color: 2,
collate: true
}
};
// JavaScript implementations of WebContents.
const binding = process.electronBinding('web_contents')
const { WebContents } = binding
const binding = process.electronBinding('web_contents');
const { WebContents } = binding;
Object.setPrototypeOf(NavigationController.prototype, EventEmitter.prototype)
Object.setPrototypeOf(WebContents.prototype, NavigationController.prototype)
Object.setPrototypeOf(NavigationController.prototype, EventEmitter.prototype);
Object.setPrototypeOf(WebContents.prototype, NavigationController.prototype);
// WebContents::send(channel, args..)
// WebContents::sendToAll(channel, args..)
WebContents.prototype.send = function (channel, ...args) {
if (typeof channel !== 'string') {
throw new Error('Missing required channel argument')
throw new Error('Missing required channel argument');
}
const internal = false
const sendToAll = false
const internal = false;
const sendToAll = false;
return this._send(internal, sendToAll, channel, args)
}
return this._send(internal, sendToAll, channel, args);
};
WebContents.prototype.postMessage = function (...args) {
if (Array.isArray(args[2])) {
args[2] = args[2].map(o => o instanceof MessagePortMain ? o._internalPort : o)
args[2] = args[2].map(o => o instanceof MessagePortMain ? o._internalPort : o);
}
this._postMessage(...args)
}
this._postMessage(...args);
};
WebContents.prototype.sendToAll = function (channel, ...args) {
if (typeof channel !== 'string') {
throw new Error('Missing required channel argument')
throw new Error('Missing required channel argument');
}
const internal = false
const sendToAll = true
const internal = false;
const sendToAll = true;
return this._send(internal, sendToAll, channel, args)
}
return this._send(internal, sendToAll, channel, args);
};
WebContents.prototype._sendInternal = function (channel, ...args) {
if (typeof channel !== 'string') {
throw new Error('Missing required channel argument')
throw new Error('Missing required channel argument');
}
const internal = true
const sendToAll = false
const internal = true;
const sendToAll = false;
return this._send(internal, sendToAll, channel, args)
}
return this._send(internal, sendToAll, channel, args);
};
WebContents.prototype._sendInternalToAll = function (channel, ...args) {
if (typeof channel !== 'string') {
throw new Error('Missing required channel argument')
throw new Error('Missing required channel argument');
}
const internal = true
const sendToAll = true
const internal = true;
const sendToAll = true;
return this._send(internal, sendToAll, channel, args)
}
return this._send(internal, sendToAll, channel, args);
};
WebContents.prototype.sendToFrame = function (frameId, channel, ...args) {
if (typeof channel !== 'string') {
throw new Error('Missing required channel argument')
throw new Error('Missing required channel argument');
} else if (typeof frameId !== 'number') {
throw new Error('Missing required frameId argument')
throw new Error('Missing required frameId argument');
}
const internal = false
const sendToAll = false
const internal = false;
const sendToAll = false;
return this._sendToFrame(internal, sendToAll, frameId, channel, args)
}
return this._sendToFrame(internal, sendToAll, frameId, channel, args);
};
WebContents.prototype._sendToFrameInternal = function (frameId, channel, ...args) {
if (typeof channel !== 'string') {
throw new Error('Missing required channel argument')
throw new Error('Missing required channel argument');
} else if (typeof frameId !== 'number') {
throw new Error('Missing required frameId argument')
throw new Error('Missing required frameId argument');
}
const internal = true
const sendToAll = false
const internal = true;
const sendToAll = false;
return this._sendToFrame(internal, sendToAll, frameId, channel, args)
}
return this._sendToFrame(internal, sendToAll, frameId, channel, args);
};
// Following methods are mapped to webFrame.
const webFrameMethods = [
@ -185,138 +185,138 @@ const webFrameMethods = [
'insertText',
'removeInsertedCSS',
'setVisualZoomLevelLimits'
]
];
for (const method of webFrameMethods) {
WebContents.prototype[method] = function (...args) {
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, ...args)
}
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, ...args);
};
}
const waitTillCanExecuteJavaScript = async (webContents) => {
if (webContents.getURL() && !webContents.isLoadingMainFrame()) return
if (webContents.getURL() && !webContents.isLoadingMainFrame()) return;
return new Promise((resolve) => {
webContents.once('did-stop-loading', () => {
resolve()
})
})
}
resolve();
});
});
};
// Make sure WebContents::executeJavaScript would run the code only when the
// WebContents has been loaded.
WebContents.prototype.executeJavaScript = async function (code, hasUserGesture) {
await waitTillCanExecuteJavaScript(this)
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScript', code, hasUserGesture)
}
await waitTillCanExecuteJavaScript(this);
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScript', code, hasUserGesture);
};
WebContents.prototype.executeJavaScriptInIsolatedWorld = async function (code, hasUserGesture) {
await waitTillCanExecuteJavaScript(this)
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScriptInIsolatedWorld', code, hasUserGesture)
}
await waitTillCanExecuteJavaScript(this);
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScriptInIsolatedWorld', code, hasUserGesture);
};
// Translate the options of printToPDF.
WebContents.prototype.printToPDF = function (options) {
const printSettings = {
...defaultPrintingSetting,
requestID: getNextId()
}
};
if (options.landscape !== undefined) {
if (typeof options.landscape !== 'boolean') {
const error = new Error('landscape must be a Boolean')
return Promise.reject(error)
const error = new Error('landscape must be a Boolean');
return Promise.reject(error);
}
printSettings.landscape = options.landscape
printSettings.landscape = options.landscape;
}
if (options.scaleFactor !== undefined) {
if (typeof options.scaleFactor !== 'number') {
const error = new Error('scaleFactor must be a Number')
return Promise.reject(error)
const error = new Error('scaleFactor must be a Number');
return Promise.reject(error);
}
printSettings.scaleFactor = options.scaleFactor
printSettings.scaleFactor = options.scaleFactor;
}
if (options.marginsType !== undefined) {
if (typeof options.marginsType !== 'number') {
const error = new Error('marginsType must be a Number')
return Promise.reject(error)
const error = new Error('marginsType must be a Number');
return Promise.reject(error);
}
printSettings.marginsType = options.marginsType
printSettings.marginsType = options.marginsType;
}
if (options.printSelectionOnly !== undefined) {
if (typeof options.printSelectionOnly !== 'boolean') {
const error = new Error('printSelectionOnly must be a Boolean')
return Promise.reject(error)
const error = new Error('printSelectionOnly must be a Boolean');
return Promise.reject(error);
}
printSettings.shouldPrintSelectionOnly = options.printSelectionOnly
printSettings.shouldPrintSelectionOnly = options.printSelectionOnly;
}
if (options.printBackground !== undefined) {
if (typeof options.printBackground !== 'boolean') {
const error = new Error('printBackground must be a Boolean')
return Promise.reject(error)
const error = new Error('printBackground must be a Boolean');
return Promise.reject(error);
}
printSettings.shouldPrintBackgrounds = options.printBackground
printSettings.shouldPrintBackgrounds = options.printBackground;
}
if (options.pageRanges !== undefined) {
const pageRanges = options.pageRanges
const pageRanges = options.pageRanges;
if (!Object.prototype.hasOwnProperty.call(pageRanges, 'from') || !Object.prototype.hasOwnProperty.call(pageRanges, 'to')) {
const error = new Error('pageRanges must be an Object with \'from\' and \'to\' properties')
return Promise.reject(error)
const error = new Error('pageRanges must be an Object with \'from\' and \'to\' properties');
return Promise.reject(error);
}
if (typeof pageRanges.from !== 'number') {
const error = new Error('pageRanges.from must be a Number')
return Promise.reject(error)
const error = new Error('pageRanges.from must be a Number');
return Promise.reject(error);
}
if (typeof pageRanges.to !== 'number') {
const error = new Error('pageRanges.to must be a Number')
return Promise.reject(error)
const error = new Error('pageRanges.to must be a Number');
return Promise.reject(error);
}
// Chromium uses 1-based page ranges, so increment each by 1.
printSettings.pageRange = [{
from: pageRanges.from + 1,
to: pageRanges.to + 1
}]
}];
}
if (options.headerFooter !== undefined) {
const headerFooter = options.headerFooter
printSettings.headerFooterEnabled = true
const headerFooter = options.headerFooter;
printSettings.headerFooterEnabled = true;
if (typeof headerFooter === 'object') {
if (!headerFooter.url || !headerFooter.title) {
const error = new Error('url and title properties are required for headerFooter')
return Promise.reject(error)
const error = new Error('url and title properties are required for headerFooter');
return Promise.reject(error);
}
if (typeof headerFooter.title !== 'string') {
const error = new Error('headerFooter.title must be a String')
return Promise.reject(error)
const error = new Error('headerFooter.title must be a String');
return Promise.reject(error);
}
printSettings.title = headerFooter.title
printSettings.title = headerFooter.title;
if (typeof headerFooter.url !== 'string') {
const error = new Error('headerFooter.url must be a String')
return Promise.reject(error)
const error = new Error('headerFooter.url must be a String');
return Promise.reject(error);
}
printSettings.url = headerFooter.url
printSettings.url = headerFooter.url;
} else {
const error = new Error('headerFooter must be an Object')
return Promise.reject(error)
const error = new Error('headerFooter must be an Object');
return Promise.reject(error);
}
}
// Optionally set size for PDF.
if (options.pageSize !== undefined) {
const pageSize = options.pageSize
const pageSize = options.pageSize;
if (typeof pageSize === 'object') {
if (!pageSize.height || !pageSize.width) {
const error = new Error('height and width properties are required for pageSize')
return Promise.reject(error)
const error = new Error('height and width properties are required for pageSize');
return Promise.reject(error);
}
// Dimensions in Microns
// 1 meter = 10^6 microns
@ -325,28 +325,28 @@ WebContents.prototype.printToPDF = function (options) {
custom_display_name: 'Custom',
height_microns: Math.ceil(pageSize.height),
width_microns: Math.ceil(pageSize.width)
}
};
} else if (PDFPageSizes[pageSize]) {
printSettings.mediaSize = PDFPageSizes[pageSize]
printSettings.mediaSize = PDFPageSizes[pageSize];
} else {
const error = new Error(`Unsupported pageSize: ${pageSize}`)
return Promise.reject(error)
const error = new Error(`Unsupported pageSize: ${pageSize}`);
return Promise.reject(error);
}
} else {
printSettings.mediaSize = PDFPageSizes.A4
printSettings.mediaSize = PDFPageSizes.A4;
}
// Chromium expects this in a 0-100 range number, not as float
printSettings.scaleFactor = Math.ceil(printSettings.scaleFactor) % 100
printSettings.scaleFactor = Math.ceil(printSettings.scaleFactor) % 100;
// PrinterType enum from //printing/print_job_constants.h
printSettings.printerType = 2
printSettings.printerType = 2;
if (features.isPrintingEnabled()) {
return this._printToPDF(printSettings)
return this._printToPDF(printSettings);
} else {
const error = new Error('Printing feature is disabled')
return Promise.reject(error)
const error = new Error('Printing feature is disabled');
return Promise.reject(error);
}
}
};
WebContents.prototype.print = function (options = {}, callback) {
// TODO(codebytere): deduplicate argument sanitization by moving rest of
@ -354,10 +354,10 @@ WebContents.prototype.print = function (options = {}, callback) {
if (typeof options === 'object') {
// Optionally set size for PDF.
if (options.pageSize !== undefined) {
const pageSize = options.pageSize
const pageSize = options.pageSize;
if (typeof pageSize === 'object') {
if (!pageSize.height || !pageSize.width) {
throw new Error('height and width properties are required for pageSize')
throw new Error('height and width properties are required for pageSize');
}
// Dimensions in Microns - 1 meter = 10^6 microns
options.mediaSize = {
@ -365,40 +365,40 @@ WebContents.prototype.print = function (options = {}, callback) {
custom_display_name: 'Custom',
height_microns: Math.ceil(pageSize.height),
width_microns: Math.ceil(pageSize.width)
}
};
} else if (PDFPageSizes[pageSize]) {
options.mediaSize = PDFPageSizes[pageSize]
options.mediaSize = PDFPageSizes[pageSize];
} else {
throw new Error(`Unsupported pageSize: ${pageSize}`)
throw new Error(`Unsupported pageSize: ${pageSize}`);
}
}
}
if (features.isPrintingEnabled()) {
if (callback) {
this._print(options, callback)
this._print(options, callback);
} else {
this._print(options)
this._print(options);
}
} else {
console.error('Error: Printing feature is disabled.')
console.error('Error: Printing feature is disabled.');
}
}
};
WebContents.prototype.getPrinters = function () {
if (features.isPrintingEnabled()) {
return this._getPrinters()
return this._getPrinters();
} else {
console.error('Error: Printing feature is disabled.')
return []
console.error('Error: Printing feature is disabled.');
return [];
}
}
};
WebContents.prototype.loadFile = function (filePath, options = {}) {
if (typeof filePath !== 'string') {
throw new Error('Must pass filePath as a string')
throw new Error('Must pass filePath as a string');
}
const { query, search, hash } = options
const { query, search, hash } = options;
return this.loadURL(url.format({
protocol: 'file',
@ -407,104 +407,104 @@ WebContents.prototype.loadFile = function (filePath, options = {}) {
query,
search,
hash
}))
}
}));
};
const addReplyToEvent = (event) => {
event.reply = (...args) => {
event.sender.sendToFrame(event.frameId, ...args)
}
}
event.sender.sendToFrame(event.frameId, ...args);
};
};
const addReplyInternalToEvent = (event) => {
Object.defineProperty(event, '_replyInternal', {
configurable: false,
enumerable: false,
value: (...args) => {
event.sender._sendToFrameInternal(event.frameId, ...args)
event.sender._sendToFrameInternal(event.frameId, ...args);
}
})
}
});
};
const addReturnValueToEvent = (event) => {
Object.defineProperty(event, 'returnValue', {
set: (value) => event.sendReply([value]),
get: () => {}
})
}
});
};
// Add JavaScript wrappers for WebContents class.
WebContents.prototype._init = function () {
// The navigation controller.
NavigationController.call(this, this)
NavigationController.call(this, this);
// Every remote callback from renderer process would add a listener to the
// render-view-deleted event, so ignore the listeners warning.
this.setMaxListeners(0)
this.setMaxListeners(0);
// Dispatch IPC messages to the ipc module.
this.on('-ipc-message', function (event, internal, channel, args) {
if (internal) {
addReplyInternalToEvent(event)
ipcMainInternal.emit(channel, event, ...args)
addReplyInternalToEvent(event);
ipcMainInternal.emit(channel, event, ...args);
} else {
addReplyToEvent(event)
this.emit('ipc-message', event, channel, ...args)
ipcMain.emit(channel, event, ...args)
addReplyToEvent(event);
this.emit('ipc-message', event, channel, ...args);
ipcMain.emit(channel, event, ...args);
}
})
});
this.on('-ipc-invoke', function (event, internal, channel, args) {
event._reply = (result) => event.sendReply({ result })
event._reply = (result) => event.sendReply({ result });
event._throw = (error) => {
console.error(`Error occurred in handler for '${channel}':`, error)
event.sendReply({ error: error.toString() })
}
const target = internal ? ipcMainInternal : ipcMain
console.error(`Error occurred in handler for '${channel}':`, error);
event.sendReply({ error: error.toString() });
};
const target = internal ? ipcMainInternal : ipcMain;
if (target._invokeHandlers.has(channel)) {
target._invokeHandlers.get(channel)(event, ...args)
target._invokeHandlers.get(channel)(event, ...args);
} else {
event._throw(`No handler registered for '${channel}'`)
event._throw(`No handler registered for '${channel}'`);
}
})
});
this.on('-ipc-message-sync', function (event, internal, channel, args) {
addReturnValueToEvent(event)
addReturnValueToEvent(event);
if (internal) {
addReplyInternalToEvent(event)
ipcMainInternal.emit(channel, event, ...args)
addReplyInternalToEvent(event);
ipcMainInternal.emit(channel, event, ...args);
} else {
addReplyToEvent(event)
this.emit('ipc-message-sync', event, channel, ...args)
ipcMain.emit(channel, event, ...args)
addReplyToEvent(event);
this.emit('ipc-message-sync', event, channel, ...args);
ipcMain.emit(channel, event, ...args);
}
})
});
this.on('-ipc-ports', function (event, internal, channel, message, ports) {
event.ports = ports.map(p => new MessagePortMain(p))
ipcMain.emit(channel, event, message)
})
event.ports = ports.map(p => new MessagePortMain(p));
ipcMain.emit(channel, event, message);
});
// Handle context menu action request from pepper plugin.
this.on('pepper-context-menu', function (event, params, callback) {
// Access Menu via electron.Menu to prevent circular require.
const menu = electron.Menu.buildFromTemplate(params.menu)
const menu = electron.Menu.buildFromTemplate(params.menu);
menu.popup({
window: event.sender.getOwnerBrowserWindow(),
x: params.x,
y: params.y,
callback
})
})
});
});
this.on('crashed', (event, ...args) => {
app.emit('renderer-process-crashed', event, this, ...args)
})
app.emit('renderer-process-crashed', event, this, ...args);
});
// The devtools requests the webContents to reload.
this.on('devtools-reload-page', function () {
this.reload()
})
this.reload();
});
// Handle window.open for BrowserWindow and BrowserView.
if (['browserView', 'window'].includes(this.getType())) {
@ -516,9 +516,9 @@ WebContents.prototype._init = function () {
show: true,
width: 800,
height: 600
}
internalWindowOpen(event, url, referrer, frameName, disposition, options, additionalFeatures, postData)
})
};
internalWindowOpen(event, url, referrer, frameName, disposition, options, additionalFeatures, postData);
});
// Create a new browser window for the native implementation of
// "window.open", used in sandbox and nativeWindowOpen mode.
@ -526,8 +526,8 @@ WebContents.prototype._init = function () {
userGesture, left, top, width, height, url, frameName) => {
if ((disposition !== 'foreground-tab' && disposition !== 'new-window' &&
disposition !== 'background-tab')) {
event.preventDefault()
return
event.preventDefault();
return;
}
const options = {
@ -537,70 +537,70 @@ WebContents.prototype._init = function () {
width: width || 800,
height: height || 600,
webContents
}
const referrer = { url: '', policy: 'default' }
internalWindowOpen(event, url, referrer, frameName, disposition, options)
})
};
const referrer = { url: '', policy: 'default' };
internalWindowOpen(event, url, referrer, frameName, disposition, options);
});
}
this.on('login', (event, ...args) => {
app.emit('login', event, this, ...args)
})
app.emit('login', event, this, ...args);
});
const event = process.electronBinding('event').createEmpty()
app.emit('web-contents-created', event, this)
const event = process.electronBinding('event').createEmpty();
app.emit('web-contents-created', event, this);
// Properties
Object.defineProperty(this, 'audioMuted', {
get: () => this.isAudioMuted(),
set: (muted) => this.setAudioMuted(muted)
})
});
Object.defineProperty(this, 'userAgent', {
get: () => this.getUserAgent(),
set: (agent) => this.setUserAgent(agent)
})
});
Object.defineProperty(this, 'zoomLevel', {
get: () => this.getZoomLevel(),
set: (level) => this.setZoomLevel(level)
})
});
Object.defineProperty(this, 'zoomFactor', {
get: () => this.getZoomFactor(),
set: (factor) => this.setZoomFactor(factor)
})
});
Object.defineProperty(this, 'frameRate', {
get: () => this.getFrameRate(),
set: (rate) => this.setFrameRate(rate)
})
}
});
};
// Public APIs.
module.exports = {
create (options = {}) {
return binding.create(options)
return binding.create(options);
},
fromId (id) {
return binding.fromId(id)
return binding.fromId(id);
},
getFocusedWebContents () {
let focused = null
let focused = null;
for (const contents of binding.getAllWebContents()) {
if (!contents.isFocused()) continue
if (focused == null) focused = contents
if (!contents.isFocused()) continue;
if (focused == null) focused = contents;
// Return webview web contents which may be embedded inside another
// web contents that is also reporting as focused
if (contents.getType() === 'webview') return contents
if (contents.getType() === 'webview') return contents;
}
return focused
return focused;
},
getAllWebContents () {
return binding.getAllWebContents()
return binding.getAllWebContents();
}
}
};