Compare commits

...

20 Commits

Author SHA1 Message Date
Electron Bot
462fa9d6ce Bump v11.0.0-nightly.20200713 2020-07-13 08:31:44 -07:00
Samuel Attard
cbb47570bd build: run the JS linter on the build folder (#24513) 2020-07-10 14:48:50 -07:00
Sam Saccone
e18f508e66 docs: fix incorrect formatting in browser docs. (#24473)
Address incorrect typing for isEnabled. The root cause of this was due
to missing backticks which caused the docs parser to think that the
return type of the `isEnabled` function was null, where it was supposed
to be a boolean type.

The side effect of this was that the generated typescript typings were
incorrect for this function.

Fixes #24409
2020-07-10 13:57:29 -07:00
Shelley Vohr
6c4017ff45 fix: always callback error with invalid print settings (#24476) 2020-07-10 09:42:22 -07:00
Samuel Attard
5737fda154 build: tsify worker/init (#24497) 2020-07-09 20:32:37 -07:00
Samuel Attard
8847517798 build: tsify isolated_renderer/init (#24496) 2020-07-09 20:32:26 -07:00
Samuel Attard
c9aa68e32c build: update octicons (#24492) 2020-07-09 18:12:18 -07:00
Samuel Attard
42f716bbc6 build: update in-range dependencies (#24480) 2020-07-09 16:32:21 -07:00
Samuel Attard
ef9addcb92 build: fix linting issue in spec-main 2020-07-09 11:25:43 -07:00
Samuel Attard
dcb56923cb build: update @types packages and fs-extra (#24475) 2020-07-09 10:57:50 -07:00
Samuel Attard
eb6616e4e9 build: update to standard 14 (#24479) 2020-07-09 10:18:49 -07:00
Jeremy Rose
9bd0fc5348 refactor: ginify BrowserView (#23578) 2020-07-09 08:48:39 -07:00
Electron Bot
66d65a6d35 Bump v11.0.0-nightly.20200709 2020-07-09 08:32:15 -07:00
Samuel Attard
4305707ca8 build: update typescript parser deps (#24474) 2020-07-09 01:12:23 -07:00
Samuel Attard
8d25847318 build: update webpack / TS build deps (#24460)
* build: update webpack / TS build deps

* chore: fix JS inferred types
2020-07-09 01:05:16 -07:00
Samuel Attard
ad16e6c647 build: update linting deps (#24461) 2020-07-08 21:19:49 -07:00
Jeremy Rose
80a6adb597 fix: coerce executeJavaScript arguments (#24396) 2020-07-08 16:13:50 -07:00
Robo
7dd365784d fix: clipboard.readBuffer returning empty value (#24454) 2020-07-08 15:02:42 -07:00
Samuel Attard
e59370f541 build: update ts defs generator (#24459) 2020-07-08 13:08:31 -07:00
Shelley Vohr
6cfbee9f34 fix: uv_walk crash on web worker close (#24436)
* fix: uv_walk crash on web worker close

* Use DCHECK_EQ
2020-07-08 11:00:43 -07:00
74 changed files with 1962 additions and 1730 deletions

View File

@@ -1 +1 @@
11.0.0-nightly.20200708
11.0.0-nightly.20200713

View File

@@ -1,2 +1,2 @@
process.env.PRINT_WEBPACK_GRAPH = true
require('./run-compiler')
process.env.PRINT_WEBPACK_GRAPH = true;
require('./run-compiler');

View File

@@ -1,25 +1,25 @@
const fs = require('fs');
const path = require('path')
const webpack = require('webpack')
const path = require('path');
const webpack = require('webpack');
const configPath = process.argv[2]
const outPath = path.resolve(process.argv[3])
const config = require(configPath)
const configPath = process.argv[2];
const outPath = path.resolve(process.argv[3]);
const config = require(configPath);
config.output = {
path: path.dirname(outPath),
filename: path.basename(outPath)
}
};
const { wrapInitWithProfilingTimeout } = config;
delete config.wrapInitWithProfilingTimeout;
webpack(config, (err, stats) => {
if (err) {
console.error(err)
process.exit(1)
console.error(err);
process.exit(1);
} else if (stats.hasErrors()) {
console.error(stats.toString('normal'))
process.exit(1)
console.error(stats.toString('normal'));
process.exit(1);
} else {
if (wrapInitWithProfilingTimeout) {
const contents = fs.readFileSync(outPath, 'utf8');
@@ -33,6 +33,6 @@ if ((globalThis.process || binding.process).argv.includes("--profile-electron-in
}`;
fs.writeFileSync(outPath, newContents);
}
process.exit(0)
process.exit(0);
}
})
});

View File

@@ -1,39 +1,39 @@
const fs = require('fs')
const path = require('path')
const webpack = require('webpack')
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const TerserPlugin = require('terser-webpack-plugin');
const electronRoot = path.resolve(__dirname, '../..')
const electronRoot = path.resolve(__dirname, '../..');
const onlyPrintingGraph = !!process.env.PRINT_WEBPACK_GRAPH
const onlyPrintingGraph = !!process.env.PRINT_WEBPACK_GRAPH;
class AccessDependenciesPlugin {
apply(compiler) {
apply (compiler) {
// Only hook into webpack when we are printing the dependency graph
if (!onlyPrintingGraph) return
if (!onlyPrintingGraph) return;
compiler.hooks.compilation.tap('AccessDependenciesPlugin', compilation => {
compilation.hooks.finishModules.tap('AccessDependenciesPlugin', modules => {
const filePaths = modules.map(m => m.resource).filter(p => p).map(p => path.relative(electronRoot, p))
console.info(JSON.stringify(filePaths))
})
})
const filePaths = modules.map(m => m.resource).filter(p => p).map(p => path.relative(electronRoot, p));
console.info(JSON.stringify(filePaths));
});
});
}
}
const defines = {
BUILDFLAG: onlyPrintingGraph ? '(a => a)' : ''
}
};
const buildFlagsPrefix = '--buildflags='
const buildFlagsPrefix = '--buildflags=';
const buildFlagArg = process.argv.find(arg => arg.startsWith(buildFlagsPrefix));
if (buildFlagArg) {
const buildFlagPath = buildFlagArg.substr(buildFlagsPrefix.length)
const buildFlagPath = buildFlagArg.substr(buildFlagsPrefix.length);
const flagFile = fs.readFileSync(buildFlagPath, 'utf8')
const flagFile = fs.readFileSync(buildFlagPath, 'utf8');
for (const line of flagFile.split(/(\r\n|\r|\n)/g)) {
const flagMatch = line.match(/#define BUILDFLAG_INTERNAL_(.+?)\(\) \(([01])\)/)
const flagMatch = line.match(/#define BUILDFLAG_INTERNAL_(.+?)\(\) \(([01])\)/);
if (flagMatch) {
const [, flagName, flagValue] = flagMatch;
defines[flagName] = JSON.stringify(Boolean(parseInt(flagValue, 10)));
@@ -41,27 +41,27 @@ if (buildFlagArg) {
}
}
const ignoredModules = []
const ignoredModules = [];
if (defines['ENABLE_DESKTOP_CAPTURER'] === 'false') {
if (defines.ENABLE_DESKTOP_CAPTURER === 'false') {
ignoredModules.push(
'@electron/internal/browser/desktop-capturer',
'@electron/internal/browser/api/desktop-capturer',
'@electron/internal/renderer/api/desktop-capturer'
)
);
}
if (defines['ENABLE_REMOTE_MODULE'] === 'false') {
if (defines.ENABLE_REMOTE_MODULE === 'false') {
ignoredModules.push(
'@electron/internal/browser/remote/server',
'@electron/internal/renderer/api/remote'
)
);
}
if (defines['ENABLE_VIEWS_API'] === 'false') {
if (defines.ENABLE_VIEWS_API === 'false') {
ignoredModules.push(
'@electron/internal/browser/api/views/image-view.js'
)
);
}
module.exports = ({
@@ -71,9 +71,9 @@ module.exports = ({
target,
wrapInitWithProfilingTimeout
}) => {
let entry = path.resolve(electronRoot, 'lib', target, 'init.ts')
let entry = path.resolve(electronRoot, 'lib', target, 'init.ts');
if (!fs.existsSync(entry)) {
entry = path.resolve(electronRoot, 'lib', target, 'init.js')
entry = path.resolve(electronRoot, 'lib', target, 'init.js');
}
return ({
@@ -88,16 +88,16 @@ module.exports = ({
resolve: {
alias: {
'@electron/internal': path.resolve(electronRoot, 'lib'),
'electron': path.resolve(electronRoot, 'lib', loadElectronFromAlternateTarget || target, 'api', 'exports', 'electron.ts'),
electron: path.resolve(electronRoot, 'lib', loadElectronFromAlternateTarget || target, 'api', 'exports', 'electron.ts'),
// Force timers to resolve to our dependency that doesn't use window.postMessage
'timers': path.resolve(electronRoot, 'node_modules', 'timers-browserify', 'main.js')
timers: path.resolve(electronRoot, 'node_modules', 'timers-browserify', 'main.js')
},
extensions: ['.ts', '.js']
},
module: {
rules: [{
test: (moduleName) => !onlyPrintingGraph && ignoredModules.includes(moduleName),
loader: 'null-loader',
loader: 'null-loader'
}, {
test: /\.ts$/,
loader: 'ts-loader',
@@ -106,7 +106,7 @@ module.exports = ({
transpileOnly: onlyPrintingGraph,
ignoreDiagnostics: [
// File '{0}' is not under 'rootDir' '{1}'.
6059,
6059
]
}
}]
@@ -116,7 +116,7 @@ module.exports = ({
__filename: false,
// We provide our own "timers" import above, any usage of setImmediate inside
// one of our renderer bundles should import it from the 'timers' package
setImmediate: false,
setImmediate: false
},
optimization: {
minimize: true,
@@ -124,10 +124,10 @@ module.exports = ({
new TerserPlugin({
terserOptions: {
keep_classnames: true,
keep_fnames: true,
},
}),
],
keep_fnames: true
}
})
]
},
plugins: [
new AccessDependenciesPlugin(),
@@ -135,13 +135,13 @@ module.exports = ({
new webpack.ProvidePlugin({
process: ['@electron/internal/renderer/webpack-provider', 'process'],
global: ['@electron/internal/renderer/webpack-provider', '_global'],
Buffer: ['@electron/internal/renderer/webpack-provider', 'Buffer'],
Buffer: ['@electron/internal/renderer/webpack-provider', 'Buffer']
})
] : []),
new webpack.ProvidePlugin({
Promise: ['@electron/internal/common/webpack-globals-provider', 'Promise'],
Promise: ['@electron/internal/common/webpack-globals-provider', 'Promise']
}),
new webpack.DefinePlugin(defines),
new webpack.DefinePlugin(defines)
]
})
}
});
};

View File

@@ -1,4 +1,4 @@
module.exports = require('./webpack.config.base')({
target: 'browser',
alwaysHasNode: true
})
});

View File

@@ -1,4 +1,4 @@
module.exports = require('./webpack.config.base')({
target: 'isolated_renderer',
alwaysHasNode: false
})
});

View File

@@ -3,4 +3,4 @@ module.exports = require('./webpack.config.base')({
alwaysHasNode: true,
targetDeletesNodeGlobals: true,
wrapInitWithProfilingTimeout: true
})
});

View File

@@ -1,5 +1,5 @@
module.exports = require('./webpack.config.base')({
target: 'sandboxed_renderer',
alwaysHasNode: false,
wrapInitWithProfilingTimeout: true,
})
wrapInitWithProfilingTimeout: true
});

View File

@@ -3,4 +3,4 @@ module.exports = require('./webpack.config.base')({
loadElectronFromAlternateTarget: 'renderer',
alwaysHasNode: true,
targetDeletesNodeGlobals: true
})
});

View File

@@ -53,31 +53,31 @@
<nav>
<div class="linkcol">
<a class="hero-link" target="_blank" href="https://electronjs.org/blog">
<span class="octicon hero-octicon octicon-gist" aria-hidden="true"></span>
<span class="octicon hero-octicon octicon-code-square-24" aria-hidden="true"></span>
<h4>Blog</h4>
</a>
</div>
<div class="linkcol">
<a class="hero-link" target="_blank" href="https://github.com/electron/electron">
<span class="octicon hero-octicon octicon-mark-github" aria-hidden="true"></span>
<span class="octicon hero-octicon octicon-mark-github-16" aria-hidden="true"></span>
<h4>Repository</h4>
</a>
</div>
<div class="linkcol">
<a class="hero-link" target="_blank" href="https://electronjs.org/docs">
<span class="octicon hero-octicon octicon-gear" aria-hidden="true"></span>
<span class="octicon hero-octicon octicon-book-24" aria-hidden="true"></span>
<h4>Docs</h4>
</a>
</div>
<div class="linkcol">
<a class="hero-link" target="_blank" href="https://github.com/electron/electron-api-demos">
<span class="octicon hero-octicon octicon-star" aria-hidden="true"></span>
<span class="octicon hero-octicon octicon-star-fill-24" aria-hidden="true"></span>
<h4>API Demos</h4>
</a>
</div>
<div class="linkcol">
<a class="hero-link" target="_blank" href="https://electronforge.io">
<span class="octicon hero-octicon octicon-gift" aria-hidden="true"></span>
<span class="octicon hero-octicon octicon-gift-24" aria-hidden="true"></span>
<h4>Forge</h4>
</a>
</div>

View File

@@ -990,6 +990,7 @@ if (!gotTheLock) {
// Create myWindow, load the rest of the app, etc...
app.whenReady().then(() => {
myWindow = createWindow()
})
}
```
@@ -1105,8 +1106,10 @@ For `infoType` equal to `complete`:
For `infoType` equal to `basic`:
Promise is fulfilled with `Object` containing fewer attributes than when requested with `complete`. Here's an example of basic response:
```js
{ auxAttributes:
{ amdSwitchable: true,
{
auxAttributes:
{
amdSwitchable: true,
canSupportThreadedTextureMailbox: false,
directComposition: false,
directRendering: true,
@@ -1119,12 +1122,14 @@ For `infoType` equal to `basic`:
sandboxed: false,
softwareRendering: false,
supportsOverlays: false,
videoDecodeAcceleratorFlags: 0 },
gpuDevice:
[ { active: true, deviceId: 26657, vendorId: 4098 },
{ active: false, deviceId: 3366, vendorId: 32902 } ],
machineModelName: 'MacBookPro',
machineModelVersion: '11.5' }
videoDecodeAcceleratorFlags: 0
},
gpuDevice:
[{ active: true, deviceId: 26657, vendorId: 4098 },
{ active: false, deviceId: 3366, vendorId: 32902 }],
machineModelName: 'MacBookPro',
machineModelVersion: '11.5'
}
```
Using `basic` should be preferred if only basic information like `vendorId` or `driverId` is needed.

View File

@@ -28,25 +28,6 @@ view.webContents.loadURL('https://electronjs.org')
* `options` Object (optional)
* `webPreferences` Object (optional) - See [BrowserWindow](browser-window.md).
### Static Methods
#### `BrowserView.getAllViews()`
Returns `BrowserView[]` - An array of all opened BrowserViews.
#### `BrowserView.fromWebContents(webContents)`
* `webContents` [WebContents](web-contents.md)
Returns `BrowserView | null` - The BrowserView that owns the given `webContents`
or `null` if the contents are not owned by a BrowserView.
#### `BrowserView.fromId(id)`
* `id` Integer
Returns `BrowserView` - The view with the given `id`.
### Instance Properties
Objects created with `new BrowserView` have the following properties:
@@ -55,10 +36,6 @@ Objects created with `new BrowserView` have the following properties:
A [`WebContents`](web-contents.md) object owned by this view.
#### `view.id` _Experimental_
A `Integer` representing the unique ID of the view.
### Instance Methods
Objects created with `new BrowserView` have the following instance methods:

View File

@@ -38,7 +38,7 @@ the window after this event will have no visual flash:
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ show: false })
const win = new BrowserWindow({ show: false })
win.once('ready-to-show', () => {
win.show()
})
@@ -60,7 +60,7 @@ immediately, and use a `backgroundColor` close to your app's background:
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ backgroundColor: '#2e2c29' })
const win = new BrowserWindow({ backgroundColor: '#2e2c29' })
win.loadURL('https://github.com')
```
@@ -74,8 +74,8 @@ By using `parent` option, you can create child windows:
```javascript
const { BrowserWindow } = require('electron')
let top = new BrowserWindow()
let child = new BrowserWindow({ parent: top })
const top = new BrowserWindow()
const child = new BrowserWindow({ parent: top })
child.show()
top.show()
```
@@ -90,7 +90,7 @@ window, you have to set both `parent` and `modal` options:
```javascript
const { BrowserWindow } = require('electron')
let child = new BrowserWindow({ parent: top, modal: true, show: false })
const child = new BrowserWindow({ parent: top, modal: true, show: false })
child.loadURL('https://github.com')
child.once('ready-to-show', () => {
child.show()
@@ -597,7 +597,7 @@ e.g. `APPCOMMAND_BROWSER_BACKWARD` is emitted as `browser-backward`.
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow()
const win = new BrowserWindow()
win.on('app-command', (e, cmd) => {
// Navigate the window back when the user hits their mouse back button
if (cmd === 'browser-backward' && win.webContents.canGoBack()) {
@@ -772,7 +772,7 @@ To check if a DevTools extension is installed you can run the following:
```javascript
const { BrowserWindow } = require('electron')
let installed = BrowserWindow.getDevToolsExtensions().hasOwnProperty('devtron')
const installed = 'devtron' in BrowserWindow.getDevToolsExtensions()
console.log(installed)
```
@@ -789,7 +789,7 @@ Objects created with `new BrowserWindow` have the following properties:
```javascript
const { BrowserWindow } = require('electron')
// In this example `win` is our instance
let win = new BrowserWindow({ width: 800, height: 600 })
const win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('https://github.com')
```
@@ -1123,7 +1123,7 @@ Disable or enable the window.
#### `win.isEnabled()`
Returns Boolean - whether the window is enabled.
Returns `Boolean` - whether the window is enabled.
#### `win.setSize(width, height[, animate])`
@@ -1314,9 +1314,9 @@ a HTML-rendered toolbar. For example:
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow()
const win = new BrowserWindow()
let toolbarRect = document.getElementById('toolbar').getBoundingClientRect()
const toolbarRect = document.getElementById('toolbar').getBoundingClientRect()
win.setSheetOffset(toolbarRect.height)
```
@@ -1440,7 +1440,7 @@ Node's [`url.format`](https://nodejs.org/api/url.html#url_url_format_urlobject)
method:
```javascript
let url = require('url').format({
const url = require('url').format({
protocol: 'file',
slashes: true,
pathname: require('path').join(__dirname, 'index.html')

View File

@@ -9,7 +9,7 @@ runtime that allows interacting with pages and instrumenting them.
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow()
const win = new BrowserWindow()
try {
win.webContents.debugger.attach('1.1')

View File

@@ -11,7 +11,7 @@ control the download item.
```javascript
// In the main process.
const { BrowserWindow } = require('electron')
let win = new BrowserWindow()
const win = new BrowserWindow()
win.webContents.session.on('will-download', (event, item, webContents) => {
// Set the save path, making Electron not to prompt a save dialog.
item.setSavePath('/tmp/save.pdf')

View File

@@ -15,7 +15,7 @@ To create a frameless window, you need to set `frame` to `false` in
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ width: 800, height: 600, frame: false })
const win = new BrowserWindow({ width: 800, height: 600, frame: false })
win.show()
```
@@ -33,7 +33,7 @@ Results in a hidden title bar and a full size content window, yet the title bar
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ titleBarStyle: 'hidden' })
const win = new BrowserWindow({ titleBarStyle: 'hidden' })
win.show()
```
@@ -43,7 +43,7 @@ Results in a hidden title bar with an alternative look where the traffic light b
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ titleBarStyle: 'hiddenInset' })
const win = new BrowserWindow({ titleBarStyle: 'hiddenInset' })
win.show()
```
@@ -58,7 +58,7 @@ This option is only applicable for frameless windows.
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ titleBarStyle: 'customButtonsOnHover', frame: false })
const win = new BrowserWindow({ titleBarStyle: 'customButtonsOnHover', frame: false })
win.show()
```
@@ -69,7 +69,7 @@ window transparent:
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ transparent: true, frame: false })
const win = new BrowserWindow({ transparent: true, frame: false })
win.show()
```
@@ -100,7 +100,7 @@ API:
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow()
const win = new BrowserWindow()
win.setIgnoreMouseEvents(true)
```
@@ -112,8 +112,8 @@ optional parameter can be used to forward mouse move messages to the web page,
allowing events such as `mouseleave` to be emitted:
```javascript
let win = require('electron').remote.getCurrentWindow()
let el = document.getElementById('clickThroughElement')
const win = require('electron').remote.getCurrentWindow()
const el = document.getElementById('clickThroughElement')
el.addEventListener('mouseenter', () => {
win.setIgnoreMouseEvents(true, { forward: true })
})

View File

@@ -17,7 +17,7 @@ renderer process:
```javascript
const { BrowserWindow } = require('electron').remote
let win = new BrowserWindow({ width: 800, height: 600 })
const win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('https://github.com')
```

View File

@@ -33,8 +33,8 @@ const { app, BrowserWindow, screen } = require('electron')
let win
app.whenReady().then(() => {
let displays = screen.getAllDisplays()
let externalDisplay = displays.find((display) => {
const displays = screen.getAllDisplays()
const externalDisplay = displays.find((display) => {
return display.bounds.x !== 0 || display.bounds.y !== 0
})

View File

@@ -12,7 +12,7 @@ property of [`WebContents`](web-contents.md), or from the `session` module.
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ width: 800, height: 600 })
const win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('http://github.com')
const ses = win.webContents.session
@@ -332,7 +332,7 @@ verify proc.
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow()
const win = new BrowserWindow()
win.webContents.session.setCertificateVerifyProc((request, callback) => {
const { hostname } = request
@@ -655,7 +655,7 @@ const path = require('path')
app.whenReady().then(() => {
const protocol = session.fromPartition('some-partition').protocol
protocol.registerFileProtocol('atom', (request, callback) => {
let url = request.url.substr(7)
const url = request.url.substr(7)
callback({ path: path.normalize(`${__dirname}/${url}`) })
}, (error) => {
if (error) console.error('Failed to register protocol')

View File

@@ -41,7 +41,7 @@ An example TraceConfig that roughly matches what Chrome DevTools records:
'disabled-by-default-v8.cpu_profiler',
'disabled-by-default-v8.cpu_profiler.hires'
],
excluded_categories: [ '*' ]
excluded_categories: ['*']
}
```

View File

@@ -209,7 +209,7 @@ not (transparent windows won't work correctly when DWM composition is disabled):
```javascript
const { BrowserWindow, systemPreferences } = require('electron')
let browserOptions = { width: 1000, height: 800 }
const browserOptions = { width: 1000, height: 800 }
// Make the window transparent only if the platform supports it.
if (process.platform !== 'win32' || systemPreferences.isAeroGlassEnabled()) {
@@ -218,7 +218,7 @@ if (process.platform !== 'win32' || systemPreferences.isAeroGlassEnabled()) {
}
// Create the window.
let win = new BrowserWindow(browserOptions)
const win = new BrowserWindow(browserOptions)
// Navigate.
if (browserOptions.transparent) {

View File

@@ -12,10 +12,10 @@ the [`BrowserWindow`](browser-window.md) object. An example of accessing the
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ width: 800, height: 1500 })
const win = new BrowserWindow({ width: 800, height: 1500 })
win.loadURL('http://github.com')
let contents = win.webContents
const contents = win.webContents
console.log(contents)
```
@@ -418,7 +418,7 @@ To only prevent the menu shortcuts, use
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ width: 800, height: 600 })
const win = new BrowserWindow({ width: 800, height: 600 })
win.webContents.on('before-input-event', (event, input) => {
// For example, only enable application menu keyboard shortcuts when
@@ -665,7 +665,7 @@ app.whenReady().then(() => {
win = new BrowserWindow({ width: 800, height: 600 })
win.webContents.on('select-bluetooth-device', (event, deviceList, callback) => {
event.preventDefault()
let result = deviceList.find((device) => {
const result = deviceList.find((device) => {
return device.deviceName === 'test'
})
if (!result) {
@@ -691,7 +691,7 @@ buffer.
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ webPreferences: { offscreen: true } })
const win = new BrowserWindow({ webPreferences: { offscreen: true } })
win.webContents.on('paint', (event, dirty, image) => {
// updateBitmap(dirty, image.getBitmap())
})
@@ -907,7 +907,7 @@ Returns `String` - The URL of the current web page.
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ width: 800, height: 600 })
const win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('http://github.com').then(() => {
const currentURL = win.webContents.getURL()
console.log(currentURL)
@@ -1311,6 +1311,8 @@ Returns [`PrinterInfo[]`](structures/printer-info.md)
* `success` Boolean - Indicates success of the print call.
* `failureReason` String - Error description called back if the print fails.
When a custom `pageSize` is passed, Chromium attempts to validate platform specific minumum values for `width_microns` and `height_microns`. Width and height must both be minimum 353 microns but may be higher on some operating systems.
Prints window's web page. When `silent` is set to `true`, Electron will pick
the system's default printer if `deviceName` is empty and the default settings for printing.
@@ -1334,13 +1336,12 @@ win.webContents.print(options, (success, errorType) => {
* `landscape` Boolean (optional) - `true` for landscape, `false` for portrait.
* `marginsType` Integer (optional) - Specifies the type of margins to use. Uses 0 for
default margin, 1 for no margin, and 2 for minimum margin.
and `width` in microns.
* `scaleFactor` Number (optional) - The scale factor of the web page. Can range from 0 to 100.
* `pageRanges` Record<string, number> (optional) - The page range to print.
* `from` Number - the first page to print.
* `to` Number - the last page to print (inclusive).
* `pageSize` String | Size (optional) - Specify page size of the generated PDF. Can be `A3`,
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` and `width` in microns.
* `printBackground` Boolean (optional) - Whether to print CSS backgrounds.
* `printSelectionOnly` Boolean (optional) - Whether to print selection only.
@@ -1372,7 +1373,7 @@ An example of `webContents.printToPDF`:
const { BrowserWindow } = require('electron')
const fs = require('fs')
let win = new BrowserWindow({ width: 800, height: 600 })
const win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('http://github.com')
win.webContents.on('did-finish-load', () => {
@@ -1397,7 +1398,7 @@ creation:
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow()
const win = new BrowserWindow()
win.webContents.on('devtools-opened', () => {
win.webContents.addWorkSpace(__dirname)
})
@@ -1718,7 +1719,7 @@ Returns `Promise<void>` - resolves if the page is saved.
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow()
const win = new BrowserWindow()
win.loadURL('https://github.com')

View File

@@ -816,7 +816,7 @@ const { shell } = require('electron')
const webview = document.querySelector('webview')
webview.addEventListener('new-window', async (e) => {
const protocol = require('url').parse(e.url).protocol
const protocol = (new URL(e.url)).protocol
if (protocol === 'http:' || protocol === 'https:') {
await shell.openExternal(e.url)
}

View File

@@ -94,6 +94,6 @@ mainWindow.webContents.on('new-window', (event, url, frameName, disposition, opt
```javascript
// renderer process (mainWindow)
let modal = window.open('', 'modal')
const modal = window.open('', 'modal')
modal.document.write('<h1>Hello</h1>')
```

View File

@@ -266,7 +266,7 @@ const getGuestForWebContents = (webContentsId, contents) => {
throw new Error(`Invalid webContentsId: ${webContentsId}`)
}
if (guest.hostWebContents !== contents) {
throw new Error(`Access denied to webContents`)
throw new Error('Access denied to webContents')
}
return guest
}
@@ -610,11 +610,11 @@ const { memory } = metrics[0] // Deprecated property
```js
// Deprecated
let optionsA = { webPreferences: { blinkFeatures: '' } }
let windowA = new BrowserWindow(optionsA)
const optionsA = { webPreferences: { blinkFeatures: '' } }
const windowA = new BrowserWindow(optionsA)
// Replace with
let optionsB = { webPreferences: { enableBlinkFeatures: '' } }
let windowB = new BrowserWindow(optionsB)
const optionsB = { webPreferences: { enableBlinkFeatures: '' } }
const windowB = new BrowserWindow(optionsB)
// Deprecated
window.on('app-command', (e, cmd) => {
@@ -785,11 +785,11 @@ The following list includes the breaking API changes made in Electron 2.0.
```js
// Deprecated
let optionsA = { titleBarStyle: 'hidden-inset' }
let windowA = new BrowserWindow(optionsA)
const optionsA = { titleBarStyle: 'hidden-inset' }
const windowA = new BrowserWindow(optionsA)
// Replace with
let optionsB = { titleBarStyle: 'hiddenInset' }
let windowB = new BrowserWindow(optionsB)
const optionsB = { titleBarStyle: 'hiddenInset' }
const windowB = new BrowserWindow(optionsB)
```
### `menu`

View File

@@ -107,7 +107,7 @@ To solve this, you can turn off node integration in Electron:
```javascript
// In the main process.
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({
const win = new BrowserWindow({
webPreferences: {
nodeIntegration: false
}
@@ -155,7 +155,7 @@ To achieve this goal, set the background in the constructor for [BrowserWindow][
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({
const win = new BrowserWindow({
backgroundColor: '#fff'
})
```

View File

@@ -15,7 +15,7 @@ can open them programmatically by calling the `openDevTools()` API on the
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow()
const win = new BrowserWindow()
win.webContents.openDevTools()
```

View File

@@ -70,7 +70,7 @@ fs.readdirSync('/path/to/example.asar')
Use a module from the archive:
```javascript
require('/path/to/example.asar/dir/module.js')
require('./path/to/example.asar/dir/module.js')
```
You can also display a web page in an `asar` archive with `BrowserWindow`:

View File

@@ -9,9 +9,9 @@ const childProcess = require('child_process')
const electronPath = require('electron')
// spawn the process
let env = { /* ... */ }
let stdio = ['inherit', 'inherit', 'inherit', 'ipc']
let appProcess = childProcess.spawn(electronPath, ['./app'], { stdio, env })
const env = { /* ... */ }
const stdio = ['inherit', 'inherit', 'inherit', 'ipc']
const appProcess = childProcess.spawn(electronPath, ['./app'], { stdio, env })
// listen for IPC messages from the app
appProcess.on('message', (msg) => {
@@ -50,7 +50,7 @@ class TestDriver {
// handle rpc responses
this.process.on('message', (message) => {
// pop the handler
let rpcCall = this.rpcCalls[message.msgId]
const rpcCall = this.rpcCalls[message.msgId]
if (!rpcCall) return
this.rpcCalls[message.msgId] = null
// reject/resolve
@@ -70,7 +70,7 @@ class TestDriver {
// to use: driver.rpc('method', 1, 2, 3).then(...)
async rpc (cmd, ...args) {
// send rpc request
let msgId = this.rpcCalls.length
const msgId = this.rpcCalls.length
this.process.send({ msgId, cmd, args })
return new Promise((resolve, reject) => this.rpcCalls.push({ resolve, reject }))
}
@@ -92,10 +92,10 @@ async function onMessage ({ msgId, cmd, args }) {
let method = METHODS[cmd]
if (!method) method = () => new Error('Invalid method: ' + cmd)
try {
let resolve = await method(...args)
const resolve = await method(...args)
process.send({ msgId, resolve })
} catch (err) {
let reject = {
const reject = {
message: err.message,
stack: err.stack,
name: err.name
@@ -119,7 +119,7 @@ Then, in your test suite, you can use your test-driver as follows:
const test = require('ava')
const electronPath = require('electron')
let app = new TestDriver({
const app = new TestDriver({
path: electronPath,
args: ['./app'],
env: {

View File

@@ -96,7 +96,7 @@ const { app, BrowserWindow } = require('electron')
function createWindow () {
// Create the browser window.
let win = new BrowserWindow({
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {

View File

@@ -37,18 +37,18 @@ inAppPurchase.on('transactions-updated', (event, transactions) => {
// Check each transaction.
transactions.forEach(function (transaction) {
let payment = transaction.payment
const payment = transaction.payment
switch (transaction.transactionState) {
case 'purchasing':
console.log(`Purchasing ${payment.productIdentifier}...`)
break
case 'purchased':
case 'purchased': {
console.log(`${payment.productIdentifier} purchased.`)
// Get the receipt url.
let receiptURL = inAppPurchase.getReceiptURL()
const receiptURL = inAppPurchase.getReceiptURL()
console.log(`Receipt URL: ${receiptURL}`)
@@ -62,6 +62,8 @@ inAppPurchase.on('transactions-updated', (event, transactions) => {
inAppPurchase.finishTransactionByDate(transaction.transactionDate)
break
}
case 'failed':
console.log(`Failed to purchase ${payment.productIdentifier}.`)
@@ -105,8 +107,8 @@ inAppPurchase.getProducts(PRODUCT_IDS).then(products => {
})
// Ask the user which product he/she wants to purchase.
let selectedProduct = products[0]
let selectedQuantity = 1
const selectedProduct = products[0]
const selectedQuantity = 1
// Purchase the selected product.
inAppPurchase.purchaseProduct(selectedProduct.productIdentifier, selectedQuantity).then(isProductValid => {

View File

@@ -10,7 +10,7 @@ so the `nodeIntegrationInWorker` option should be set to `true` in
`webPreferences`.
```javascript
let win = new BrowserWindow({
const win = new BrowserWindow({
webPreferences: {
nodeIntegrationInWorker: true
}
@@ -44,7 +44,7 @@ loads no native modules after the Web Workers get started.
process.dlopen = () => {
throw new Error('Load native module is not safe')
}
let worker = new Worker('script.js')
const worker = new Worker('script.js')
```
[web-workers]: https://developer.mozilla.org/en/docs/Web/API/Web_Workers_API/Using_web_workers

View File

@@ -10,7 +10,7 @@ you want to show Notifications in the main process please check out the
[Notification](../api/notification.md) module.
```javascript
let myNotification = new Notification('Title', {
const myNotification = new Notification('Title', {
body: 'Lorem Ipsum Dolor Sit Amet'
})

View File

@@ -42,7 +42,7 @@ app.commandLine.appendSwitch('ppapi-flash-path', path.join(__dirname, pluginName
app.commandLine.appendSwitch('ppapi-flash-version', '17.0.0.169')
app.whenReady().then(() => {
let win = new BrowserWindow({
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {

View File

@@ -146,7 +146,7 @@ const options = {
}
}
let client = webdriverio.remote(options)
const client = webdriverio.remote(options)
client
.init()

View File

@@ -149,7 +149,7 @@ To set the overlay icon for a window, you can use the
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow()
const win = new BrowserWindow()
win.setOverlayIcon('path/to/overlay.png', 'Description for overlay')
```
@@ -168,7 +168,7 @@ To flash the BrowserWindow taskbar button, you can use the
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow()
const win = new BrowserWindow()
win.once('focus', () => win.flashFrame(false))
win.flashFrame(true)
```

View File

@@ -174,7 +174,7 @@ auto_filenames = {
]
isolated_bundle_deps = [
"lib/isolated_renderer/init.js",
"lib/isolated_renderer/init.ts",
"lib/renderer/web-view/web-view-constants.ts",
"lib/renderer/web-view/web-view-element.ts",
"package.json",
@@ -327,7 +327,7 @@ auto_filenames = {
"lib/renderer/ipc-renderer-internal.ts",
"lib/renderer/remote/callbacks-registry.ts",
"lib/renderer/webpack-provider.ts",
"lib/worker/init.js",
"lib/worker/init.ts",
"package.json",
"tsconfig.electron.json",
"tsconfig.json",

View File

@@ -14,11 +14,11 @@ filenames = {
default_app_octicon_sources = [
"node_modules/@primer/octicons/build/build.css",
"node_modules/@primer/octicons/build/svg/gear.svg",
"node_modules/@primer/octicons/build/svg/gift.svg",
"node_modules/@primer/octicons/build/svg/gist.svg",
"node_modules/@primer/octicons/build/svg/mark-github.svg",
"node_modules/@primer/octicons/build/svg/star.svg",
"node_modules/@primer/octicons/build/svg/book-24.svg",
"node_modules/@primer/octicons/build/svg/code-square-24.svg",
"node_modules/@primer/octicons/build/svg/gift-24.svg",
"node_modules/@primer/octicons/build/svg/mark-github-16.svg",
"node_modules/@primer/octicons/build/svg/star-fill-24.svg",
]
lib_sources = [

View File

@@ -1,15 +1,3 @@
import { EventEmitter } from 'events';
const { BrowserView } = process._linkedBinding('electron_browser_browser_view');
Object.setPrototypeOf(BrowserView.prototype, EventEmitter.prototype);
BrowserView.fromWebContents = (webContents: Electron.WebContents) => {
for (const view of BrowserView.getAllViews()) {
if (view.webContents.equal(webContents)) return view;
}
return null;
};
export default BrowserView;

View File

@@ -134,6 +134,7 @@ class SlurpStream extends Writable {
this._data = Buffer.concat([this._data, chunk]);
callback();
}
data () { return this._data; }
}
@@ -300,6 +301,10 @@ class ClientRequest extends Writable implements Electron.ClientRequest {
this._redirectPolicy = redirectPolicy;
}
get chunkedEncoding () {
return this._chunkedEncoding || false;
}
set chunkedEncoding (value: boolean) {
if (this._started) {
throw new Error('chunkedEncoding can only be set before the request is started');

View File

@@ -72,6 +72,19 @@ const PDFPageSizes: Record<string, MediaSize> = {
}
};
// The minimum micron size Chromium accepts is that where:
// Per printing/units.h:
// * kMicronsPerInch - Length of an inch in 0.001mm unit.
// * kPointsPerInch - Length of an inch in CSS's 1pt unit.
//
// Formula: (kPointsPerInch / kMicronsPerInch) * size >= 1
//
// Practically, this means microns need to be > 352 microns.
// We therefore need to verify this or it will silently fail.
const isValidCustomPageSize = (width: number, height: number) => {
return [width, height].every(x => x > 352);
};
// Default printing setting
const defaultPrintingSetting = {
// Customizable.
@@ -204,11 +217,11 @@ const waitTillCanExecuteJavaScript = async (webContents: WebContentsInternal) =>
// 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);
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScript', String(code), !!hasUserGesture);
};
WebContents.prototype.executeJavaScriptInIsolatedWorld = async function (code, hasUserGesture) {
WebContents.prototype.executeJavaScriptInIsolatedWorld = async function (worldId, code, hasUserGesture) {
await waitTillCanExecuteJavaScript(this);
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScriptInIsolatedWorld', code, hasUserGesture);
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScriptInIsolatedWorld', worldId, code, !!hasUserGesture);
};
// Translate the options of printToPDF.
@@ -315,13 +328,20 @@ WebContents.prototype.printToPDF = function (options) {
const error = new Error('height and width properties are required for pageSize');
return Promise.reject(error);
}
// Dimensions in Microns
// 1 meter = 10^6 microns
// Dimensions in Microns - 1 meter = 10^6 microns
const height = Math.ceil(pageSize.height);
const width = Math.ceil(pageSize.width);
if (!isValidCustomPageSize(width, height)) {
const error = new Error('height and width properties must be minimum 352 microns.');
return Promise.reject(error);
}
printSettings.mediaSize = {
name: 'CUSTOM',
custom_display_name: 'Custom',
height_microns: Math.ceil(pageSize.height),
width_microns: Math.ceil(pageSize.width)
height_microns: height,
width_microns: width
};
} else if (Object.prototype.hasOwnProperty.call(PDFPageSizes, pageSize)) {
printSettings.mediaSize = PDFPageSizes[pageSize];
@@ -356,12 +376,19 @@ WebContents.prototype.print = function (options = {}, callback) {
if (!pageSize.height || !pageSize.width) {
throw new Error('height and width properties are required for pageSize');
}
// Dimensions in Microns - 1 meter = 10^6 microns
const height = Math.ceil(pageSize.height);
const width = Math.ceil(pageSize.width);
if (!isValidCustomPageSize(width, height)) {
throw new Error('height and width properties must be minimum 352 microns.');
}
(options as any).mediaSize = {
name: 'CUSTOM',
custom_display_name: 'Custom',
height_microns: Math.ceil(pageSize.height),
width_microns: Math.ceil(pageSize.width)
height_microns: height,
width_microns: width
};
} else if (PDFPageSizes[pageSize]) {
(options as any).mediaSize = PDFPageSizes[pageSize];

View File

@@ -1,6 +1,4 @@
'use strict';
/* global require */
// Monkey-patch the fs module.
require('electron/js2c/asar').wrapFsWithAsar(require('fs'));

View File

@@ -196,8 +196,6 @@ export class WebViewImpl {
this.internalElement.contentWindow!
);
// ResizeObserver is a browser global not recognized by "standard".
/* globals ResizeObserver */
// TODO(zcbenz): Should we deprecate the "resize" event? Wait, it is not
// even documented.
this.resizeObserver = new ResizeObserver(this.onElementResize.bind(this));

View File

@@ -1,5 +1,5 @@
/* eslint no-eval: "off" */
/* global binding, Buffer */
/* global binding */
import * as events from 'events';
const { EventEmitter } = events;

View File

@@ -1,6 +1,5 @@
'use strict';
import * as path from 'path';
const path = require('path');
const Module = require('module');
// We modified the original process.argv to let node.js load the

View File

@@ -1,68 +1,68 @@
{
"name": "electron",
"version": "11.0.0-nightly.20200708",
"version": "11.0.0-nightly.20200713",
"repository": "https://github.com/electron/electron",
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": {
"@electron/docs-parser": "^0.7.2",
"@electron/typescript-definitions": "^8.7.2",
"@electron/docs-parser": "^0.9.1",
"@electron/typescript-definitions": "^8.7.4",
"@octokit/rest": "^16.3.2",
"@primer/octicons": "^9.1.1",
"@primer/octicons": "^10.0.0",
"@types/basic-auth": "^1.1.3",
"@types/busboy": "^0.2.3",
"@types/chai": "^4.2.11",
"@types/chai-as-promised": "^7.1.2",
"@types/chai-as-promised": "^7.1.3",
"@types/dirty-chai": "^2.0.2",
"@types/express": "^4.17.3",
"@types/fs-extra": "^8.1.0",
"@types/express": "^4.17.7",
"@types/fs-extra": "^9.0.1",
"@types/mocha": "^7.0.2",
"@types/node": "^12.12.6",
"@types/semver": "^7.1.0",
"@types/semver": "^7.3.1",
"@types/send": "^0.14.5",
"@types/split": "^1.0.0",
"@types/uuid": "^3.4.6",
"@types/webpack": "^4.41.7",
"@types/webpack-env": "^1.15.1",
"@typescript-eslint/eslint-plugin": "^2.24.0",
"@typescript-eslint/parser": "^2.24.0",
"asar": "^3.0.1",
"@types/webpack": "^4.41.21",
"@types/webpack-env": "^1.15.2",
"@typescript-eslint/eslint-plugin": "^3.6.0",
"@typescript-eslint/parser": "^3.6.0",
"asar": "^3.0.3",
"check-for-leaks": "^1.2.1",
"colors": "^1.1.2",
"colors": "^1.4.0",
"dotenv-safe": "^4.0.4",
"dugite": "^1.45.0",
"eslint": "^5.13.0",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-import": "^2.17.2",
"eslint-plugin-mocha": "^5.2.0",
"eslint-plugin-node": "^8.0.1",
"eslint-plugin-standard": "^4.0.0",
"eslint": "^7.4.0",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-mocha": "^7.0.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-standard": "^4.0.1",
"eslint-plugin-typescript": "^0.14.0",
"express": "^4.16.4",
"folder-hash": "^2.1.1",
"fs-extra": "^7.0.1",
"fs-extra": "^9.0.1",
"husky": "^2.2.0",
"klaw": "^3.0.0",
"lint": "^1.1.2",
"lint-staged": "^8.1.0",
"minimist": "^1.2.0",
"lint-staged": "^10.2.11",
"minimist": "^1.2.5",
"nugget": "^2.0.1",
"null-loader": "^4.0.0",
"pre-flight": "^1.1.0",
"remark-cli": "^4.0.0",
"remark-preset-lint-markdown-style-guide": "^2.1.1",
"request": "^2.88.0",
"request": "^2.88.2",
"semver": "^5.6.0",
"shx": "^0.3.2",
"standard-markdown": "^5.0.0",
"standard-markdown": "^6.0.0",
"sumchecker": "^2.0.2",
"tap-xunit": "^2.4.1",
"temp": "^0.8.3",
"timers-browserify": "1.4.2",
"ts-loader": "^6.0.2",
"ts-node": "^6.0.3",
"typescript": "^3.8.3",
"webpack": "^4.42.0",
"webpack-cli": "^3.3.11"
"ts-loader": "^7.0.5",
"ts-node": "6.2.0",
"typescript": "^3.9.6",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12"
},
"private": true,
"scripts": {
@@ -105,28 +105,23 @@
},
"lint-staged": {
"*.{js,ts}": [
"node script/lint.js --js --fix --only --",
"git add"
"node script/lint.js --js --fix --only --"
],
"*.{js,ts,d.ts}": [
"node script/gen-filenames.js",
"git add"
"node script/gen-filenames.js"
],
"*.{cc,mm,c,h}": [
"python script/run-clang-format.py -r -c --fix",
"git add"
"python script/run-clang-format.py -r -c --fix"
],
"*.md": [
"npm run lint:docs"
],
"*.{gn,gni}": [
"npm run gn-check",
"python script/run-gn-format.py",
"git add"
"python script/run-gn-format.py"
],
"*.py": [
"node script/lint.js --py --fix --only --",
"git add"
"node script/lint.js --py --fix --only --"
],
"docs/api/**/*.md": [
"node script/gen-filenames.js",

View File

@@ -90,7 +90,7 @@ index adb208ba3589e32536527219aaf4e89e3ee3311a..301f6416898445eed814d67901254ef8
}
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc473bbd0da 100644
index 8a743d0dd74b087059ff812019ae568a22c5fa01..551dbc7b0bfdbf4ca549278bb3dfc4e3abb5cf0f 100644
--- a/chrome/browser/printing/print_view_manager_base.cc
+++ b/chrome/browser/printing/print_view_manager_base.cc
@@ -27,10 +27,7 @@
@@ -194,7 +194,19 @@ index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc4
#endif
ReleasePrinterQuery();
@@ -463,9 +476,13 @@ void PrintViewManagerBase::OnNotifyPrintJobEvent(
@@ -382,6 +395,11 @@ void PrintViewManagerBase::OnScriptedPrint(
}
void PrintViewManagerBase::OnShowInvalidPrinterSettingsError() {
+ if (!callback_.is_null()) {
+ std::string cb_str = "Invalid printer settings";
+ std::move(callback_).Run(printing_succeeded_, cb_str);
+ }
+
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&ShowWarningMessageBox,
l10n_util::GetStringUTF16(
@@ -463,9 +481,13 @@ void PrintViewManagerBase::OnNotifyPrintJobEvent(
content::NotificationService::NoDetails());
break;
}
@@ -210,7 +222,7 @@ index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc4
NOTREACHED();
break;
}
@@ -560,8 +577,10 @@ bool PrintViewManagerBase::CreateNewPrintJob(
@@ -560,8 +582,10 @@ bool PrintViewManagerBase::CreateNewPrintJob(
DCHECK(!quit_inner_loop_);
DCHECK(query);
@@ -223,7 +235,7 @@ index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc4
// We can't print if there is no renderer.
if (!web_contents()->GetRenderViewHost() ||
@@ -582,8 +601,6 @@ bool PrintViewManagerBase::CreateNewPrintJob(
@@ -582,8 +606,6 @@ bool PrintViewManagerBase::CreateNewPrintJob(
print_job_->SetSource(source, /*source_id=*/"");
#endif
@@ -232,7 +244,7 @@ index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc4
printing_succeeded_ = false;
return true;
}
@@ -632,14 +649,22 @@ void PrintViewManagerBase::ReleasePrintJob() {
@@ -632,14 +654,22 @@ void PrintViewManagerBase::ReleasePrintJob() {
content::RenderFrameHost* rfh = printing_rfh_;
printing_rfh_ = nullptr;
@@ -257,7 +269,7 @@ index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc4
// Don't close the worker thread.
print_job_ = nullptr;
}
@@ -675,7 +700,7 @@ bool PrintViewManagerBase::RunInnerMessageLoop() {
@@ -675,7 +705,7 @@ bool PrintViewManagerBase::RunInnerMessageLoop() {
}
bool PrintViewManagerBase::OpportunisticallyCreatePrintJob(int cookie) {

View File

@@ -90,7 +90,7 @@ const LINTERS = [{
}
}, {
key: 'javascript',
roots: ['lib', 'spec', 'spec-main', 'script', 'default_app'],
roots: ['lib', 'spec', 'spec-main', 'script', 'default_app', 'build'],
ignoreRoots: ['spec/node_modules', 'spec-main/node_modules'],
test: filename => filename.endsWith('.js') || filename.endsWith('.ts'),
run: (opts, filenames) => {

View File

@@ -40,6 +40,7 @@ class GHKey {
this.repo = repo;
this.number = number;
}
static NewFromPull (pull) {
const owner = pull.base.repo.owner.login;
const repo = pull.base.repo.name;
@@ -405,7 +406,7 @@ function getOldestMajorBranchOfPull (pull) {
}
function getOldestMajorBranchOfCommit (commit, pool) {
return [ ...commit.prKeys.values() ]
return [...commit.prKeys.values()]
.map(prKey => pool.pulls[prKey.number])
.filter(pull => !!pull)
.map(pull => getOldestMajorBranchOfPull(pull))
@@ -531,13 +532,13 @@ const removeSupercededStackUpdates = (commits) => {
notupdates.push(commit);
continue;
}
const [ , dep, version ] = match;
const [, dep, version] = match;
if (!newest[dep] || newest[dep].version < version) {
newest[dep] = { commit, version };
}
}
return [ ...notupdates, ...Object.values(newest).map(o => o.commit) ];
return [...notupdates, ...Object.values(newest).map(o => o.commit)];
};
/***

View File

@@ -738,11 +738,11 @@ void BaseWindow::AddBrowserView(v8::Local<v8::Value> value) {
gin::Handle<BrowserView> browser_view;
if (value->IsObject() &&
gin::ConvertFromV8(isolate(), value, &browser_view)) {
auto get_that_view = browser_views_.find(browser_view->weak_map_id());
auto get_that_view = browser_views_.find(browser_view->ID());
if (get_that_view == browser_views_.end()) {
window_->AddBrowserView(browser_view->view());
browser_view->web_contents()->SetOwnerWindow(window_.get());
browser_views_[browser_view->weak_map_id()].Reset(isolate(), value);
browser_views_[browser_view->ID()].Reset(isolate(), value);
}
}
}
@@ -751,7 +751,7 @@ void BaseWindow::RemoveBrowserView(v8::Local<v8::Value> value) {
gin::Handle<BrowserView> browser_view;
if (value->IsObject() &&
gin::ConvertFromV8(isolate(), value, &browser_view)) {
auto get_that_view = browser_views_.find(browser_view->weak_map_id());
auto get_that_view = browser_views_.find(browser_view->ID());
if (get_that_view != browser_views_.end()) {
window_->RemoveBrowserView(browser_view->view());
browser_view->web_contents()->SetOwnerWindow(nullptr);

View File

@@ -52,12 +52,24 @@ struct Converter<electron::AutoResizeFlags> {
} // namespace gin
namespace {
int32_t GetNextId() {
static int32_t next_id = 1;
return next_id++;
}
} // namespace
namespace electron {
namespace api {
gin::WrapperInfo BrowserView::kWrapperInfo = {gin::kEmbedderNativeGin};
BrowserView::BrowserView(gin::Arguments* args,
const gin_helper::Dictionary& options) {
const gin_helper::Dictionary& options)
: id_(GetNextId()) {
v8::Isolate* isolate = args->isolate();
gin_helper::Dictionary web_preferences =
gin::Dictionary::CreateEmpty(isolate);
@@ -72,8 +84,6 @@ BrowserView::BrowserView(gin::Arguments* args,
view_.reset(
NativeBrowserView::Create(api_web_contents_->managed_web_contents()));
InitWithArgs(args);
}
BrowserView::~BrowserView() {
@@ -87,24 +97,24 @@ BrowserView::~BrowserView() {
void BrowserView::WebContentsDestroyed() {
api_web_contents_ = nullptr;
web_contents_.Reset();
Unpin();
}
// static
gin_helper::WrappableBase* BrowserView::New(gin_helper::ErrorThrower thrower,
gin::Arguments* args) {
gin::Handle<BrowserView> BrowserView::New(gin_helper::ErrorThrower thrower,
gin::Arguments* args) {
if (!Browser::Get()->is_ready()) {
thrower.ThrowError("Cannot create BrowserView before app is ready");
return nullptr;
return gin::Handle<BrowserView>();
}
gin::Dictionary options = gin::Dictionary::CreateEmpty(args->isolate());
args->GetNext(&options);
return new BrowserView(args, options);
}
int32_t BrowserView::ID() const {
return weak_map_id();
auto handle =
gin::CreateHandle(args->isolate(), new BrowserView(args, options));
handle->Pin(args->isolate());
return handle;
}
void BrowserView::SetAutoResize(AutoResizeFlags flags) {
@@ -123,26 +133,25 @@ void BrowserView::SetBackgroundColor(const std::string& color_name) {
view_->SetBackgroundColor(ParseHexColor(color_name));
}
v8::Local<v8::Value> BrowserView::GetWebContents() {
v8::Local<v8::Value> BrowserView::GetWebContents(v8::Isolate* isolate) {
if (web_contents_.IsEmpty()) {
return v8::Null(isolate());
return v8::Null(isolate);
}
return v8::Local<v8::Value>::New(isolate(), web_contents_);
return v8::Local<v8::Value>::New(isolate, web_contents_);
}
// static
void BrowserView::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(gin::StringToV8(isolate, "BrowserView"));
gin_helper::Destroyable::MakeDestroyable(isolate, prototype);
gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
v8::Local<v8::ObjectTemplate> BrowserView::FillObjectTemplate(
v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> templ) {
return gin::ObjectTemplateBuilder(isolate, "BrowserView", templ)
.SetMethod("setAutoResize", &BrowserView::SetAutoResize)
.SetMethod("setBounds", &BrowserView::SetBounds)
.SetMethod("getBounds", &BrowserView::GetBounds)
.SetMethod("setBackgroundColor", &BrowserView::SetBackgroundColor)
.SetProperty("webContents", &BrowserView::GetWebContents)
.SetProperty("id", &BrowserView::ID);
.Build();
}
} // namespace api
@@ -158,16 +167,9 @@ void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Context> context,
void* priv) {
v8::Isolate* isolate = context->GetIsolate();
BrowserView::SetConstructor(isolate, base::BindRepeating(&BrowserView::New));
gin_helper::Dictionary browser_view(isolate,
BrowserView::GetConstructor(isolate)
->GetFunction(context)
.ToLocalChecked());
browser_view.SetMethod("fromId", &BrowserView::FromWeakMapID);
browser_view.SetMethod("getAllViews", &BrowserView::GetAll);
gin_helper::Dictionary dict(isolate, exports);
dict.Set("BrowserView", browser_view);
dict.Set("BrowserView", BrowserView::GetConstructor(context));
}
} // namespace

View File

@@ -10,9 +10,11 @@
#include "content/public/browser/web_contents_observer.h"
#include "gin/handle.h"
#include "gin/wrappable.h"
#include "shell/browser/native_browser_view.h"
#include "shell/common/gin_helper/constructible.h"
#include "shell/common/gin_helper/error_thrower.h"
#include "shell/common/gin_helper/trackable_object.h"
#include "shell/common/gin_helper/pinnable.h"
namespace gfx {
class Rect;
@@ -30,19 +32,25 @@ namespace api {
class WebContents;
class BrowserView : public gin_helper::TrackableObject<BrowserView>,
class BrowserView : public gin::Wrappable<BrowserView>,
public gin_helper::Constructible<BrowserView>,
public gin_helper::Pinnable<BrowserView>,
public content::WebContentsObserver {
public:
static gin_helper::WrappableBase* New(gin_helper::ErrorThrower thrower,
gin::Arguments* args);
// gin_helper::Constructible
static gin::Handle<BrowserView> New(gin_helper::ErrorThrower thrower,
gin::Arguments* args);
static v8::Local<v8::ObjectTemplate> FillObjectTemplate(
v8::Isolate*,
v8::Local<v8::ObjectTemplate>);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
// gin::Wrappable
static gin::WrapperInfo kWrapperInfo;
WebContents* web_contents() const { return api_web_contents_; }
NativeBrowserView* view() const { return view_.get(); }
int32_t ID() const;
int32_t ID() const { return id_; }
protected:
BrowserView(gin::Arguments* args, const gin_helper::Dictionary& options);
@@ -56,13 +64,15 @@ class BrowserView : public gin_helper::TrackableObject<BrowserView>,
void SetBounds(const gfx::Rect& bounds);
gfx::Rect GetBounds();
void SetBackgroundColor(const std::string& color_name);
v8::Local<v8::Value> GetWebContents();
v8::Local<v8::Value> GetWebContents(v8::Isolate*);
v8::Global<v8::Value> web_contents_;
class WebContents* api_web_contents_ = nullptr;
std::unique_ptr<NativeBrowserView> view_;
int32_t id_;
DISALLOW_COPY_AND_ASSIGN(BrowserView);
};

View File

@@ -276,6 +276,10 @@ void BrowserWindow::OnCloseButtonClicked(bool* prevent_default) {
}
void BrowserWindow::OnWindowClosed() {
// We need to reset the browser views before we call Cleanup, because the
// browser views are child views of the main web contents view, which will be
// deleted by Cleanup.
BaseWindow::ResetBrowserViews();
Cleanup();
// See BaseWindow::OnWindowClosed on why calling InvalidateWeakPtrs.
weak_factory_.InvalidateWeakPtrs();

View File

@@ -50,8 +50,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 11,0,0,20200708
PRODUCTVERSION 11,0,0,20200708
FILEVERSION 11,0,0,20200713
PRODUCTVERSION 11,0,0,20200713
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L

View File

@@ -71,9 +71,8 @@ void Clipboard::WriteBuffer(const std::string& format,
base::span<const uint8_t> payload_span(
reinterpret_cast<const uint8_t*>(node::Buffer::Data(buffer)),
node::Buffer::Length(buffer));
writer.WriteData(
base::UTF8ToUTF16(ui::ClipboardFormatType::GetType(format).Serialize()),
mojo_base::BigBuffer(payload_span));
writer.WriteData(base::UTF8ToUTF16(format),
mojo_base::BigBuffer(payload_span));
}
void Clipboard::Write(const gin_helper::Dictionary& data,

View File

@@ -5,7 +5,9 @@
#ifndef SHELL_COMMON_GIN_HELPER_CONSTRUCTIBLE_H_
#define SHELL_COMMON_GIN_HELPER_CONSTRUCTIBLE_H_
#include "gin/per_isolate_data.h"
#include "gin/wrappable.h"
#include "shell/browser/event_emitter_mixin.h"
#include "shell/common/gin_helper/function_template_extensions.h"
namespace gin_helper {

View File

@@ -96,25 +96,25 @@ ELECTRON_DESKTOP_CAPTURER_MODULE(V)
namespace {
void stop_and_close_uv_loop(uv_loop_t* loop) {
// Close any active handles
uv_stop(loop);
uv_walk(
loop,
[](uv_handle_t* handle, void*) {
if (!uv_is_closing(handle)) {
uv_close(handle, nullptr);
}
},
nullptr);
int error = uv_loop_close(loop);
// Run the loop to let it finish all the closing handles
// NB: after uv_stop(), uv_run(UV_RUN_DEFAULT) returns 0 when that's done
for (;;)
if (!uv_run(loop, UV_RUN_DEFAULT))
break;
while (error) {
uv_run(loop, UV_RUN_DEFAULT);
uv_stop(loop);
uv_walk(
loop,
[](uv_handle_t* handle, void*) {
if (!uv_is_closing(handle)) {
uv_close(handle, nullptr);
}
},
nullptr);
uv_run(loop, UV_RUN_DEFAULT);
error = uv_loop_close(loop);
}
DCHECK(!uv_loop_alive(loop));
uv_loop_close(loop);
DCHECK_EQ(error, 0);
}
bool g_is_initialized = false;
@@ -274,6 +274,7 @@ NodeBindings::~NodeBindings() {
// Quit the embed thread.
embed_closed_ = true;
uv_sem_post(&embed_sem_);
WakeupEmbedThread();
// Wait for everything to be done.
@@ -284,7 +285,7 @@ NodeBindings::~NodeBindings() {
uv_close(reinterpret_cast<uv_handle_t*>(&dummy_uv_handle_), nullptr);
// Clean up worker loop
if (uv_loop_ == &worker_loop_)
if (in_worker_loop())
stop_and_close_uv_loop(uv_loop_);
}
@@ -501,7 +502,8 @@ void NodeBindings::WakeupMainThread() {
}
void NodeBindings::WakeupEmbedThread() {
uv_async_send(&dummy_uv_handle_);
if (!in_worker_loop())
uv_async_send(&dummy_uv_handle_);
}
// static

View File

@@ -58,6 +58,8 @@ class NodeBindings {
uv_loop_t* uv_loop() const { return uv_loop_; }
bool in_worker_loop() const { return uv_loop_ == &worker_loop_; }
protected:
explicit NodeBindings(BrowserEnvironment browser_env);

View File

@@ -1,9 +1,9 @@
import { expect } from 'chai';
import * as ChildProcess from 'child_process';
import * as path from 'path';
import { emittedOnce } from './events-helpers';
import { BrowserView, BrowserWindow } from 'electron/main';
import { BrowserView, BrowserWindow, webContents } from 'electron/main';
import { closeWindow } from './window-helpers';
import { defer, startRemoteControlApp } from './spec-helpers';
describe('BrowserView module', () => {
const fixtures = path.resolve(__dirname, '..', 'spec', 'fixtures');
@@ -12,6 +12,7 @@ describe('BrowserView module', () => {
let view: BrowserView;
beforeEach(() => {
expect(webContents.getAllWebContents()).to.have.length(0);
w = new BrowserWindow({
show: false,
width: 400,
@@ -23,27 +24,19 @@ describe('BrowserView module', () => {
});
afterEach(async () => {
const p = emittedOnce(w.webContents, 'destroyed');
await closeWindow(w);
w = null as any;
await p;
if (view) {
view.destroy();
const p = emittedOnce(view.webContents, 'destroyed');
(view.webContents as any).destroy();
view = null as any;
await p;
}
});
describe('BrowserView.destroy()', () => {
it('does not throw', () => {
view = new BrowserView();
view.destroy();
});
});
describe('BrowserView.isDestroyed()', () => {
it('returns correct value', () => {
view = new BrowserView();
expect(view.isDestroyed()).to.be.false('view is destroyed');
view.destroy();
expect(view.isDestroyed()).to.be.true('view is destroyed');
});
expect(webContents.getAllWebContents()).to.have.length(0);
});
describe('BrowserView.setBackgroundColor()', () => {
@@ -119,7 +112,6 @@ describe('BrowserView module', () => {
it('returns the set view', () => {
view = new BrowserView();
w.setBrowserView(view);
expect(view.id).to.not.be.null('view id');
const view2 = w.getBrowserView();
expect(view2!.webContents.id).to.equal(view.webContents.id);
@@ -134,11 +126,13 @@ describe('BrowserView module', () => {
describe('BrowserWindow.addBrowserView()', () => {
it('does not throw for valid args', () => {
const view1 = new BrowserView();
defer(() => (view1.webContents as any).destroy());
w.addBrowserView(view1);
defer(() => w.removeBrowserView(view1));
const view2 = new BrowserView();
defer(() => (view2.webContents as any).destroy());
w.addBrowserView(view2);
view1.destroy();
view2.destroy();
defer(() => w.removeBrowserView(view2));
});
it('does not throw if called multiple times with same view', () => {
view = new BrowserView();
@@ -160,18 +154,18 @@ describe('BrowserView module', () => {
describe('BrowserWindow.getBrowserViews()', () => {
it('returns same views as was added', () => {
const view1 = new BrowserView();
defer(() => (view1.webContents as any).destroy());
w.addBrowserView(view1);
defer(() => w.removeBrowserView(view1));
const view2 = new BrowserView();
defer(() => (view2.webContents as any).destroy());
w.addBrowserView(view2);
defer(() => w.removeBrowserView(view2));
expect(view1.id).to.be.not.null('view id');
const views = w.getBrowserViews();
expect(views).to.have.lengthOf(2);
expect(views[0].webContents.id).to.equal(view1.webContents.id);
expect(views[1].webContents.id).to.equal(view2.webContents.id);
view1.destroy();
view2.destroy();
});
});
@@ -188,46 +182,33 @@ describe('BrowserView module', () => {
});
});
describe('BrowserView.fromId()', () => {
it('returns the view with given id', () => {
view = new BrowserView();
w.setBrowserView(view);
expect(view.id).to.not.be.null('view id');
const view2 = BrowserView.fromId(view.id);
expect(view2.webContents.id).to.equal(view.webContents.id);
});
});
describe('BrowserView.fromWebContents()', () => {
it('returns the view with given id', () => {
view = new BrowserView();
w.setBrowserView(view);
expect(view.id).to.not.be.null('view id');
const view2 = BrowserView.fromWebContents(view.webContents);
expect(view2!.webContents.id).to.equal(view.webContents.id);
});
});
describe('BrowserView.getAllViews()', () => {
it('returns all views', () => {
view = new BrowserView();
w.setBrowserView(view);
expect(view.id).to.not.be.null('view id');
const views = BrowserView.getAllViews();
expect(views).to.be.an('array').that.has.lengthOf(1);
expect(views[0].webContents.id).to.equal(view.webContents.id);
});
});
describe('new BrowserView()', () => {
describe('shutdown behavior', () => {
it('does not crash on exit', async () => {
const appPath = path.join(__dirname, 'fixtures', 'api', 'leak-exit-browserview.js');
const electronPath = process.execPath;
const appProcess = ChildProcess.spawn(electronPath, [appPath]);
const [code] = await emittedOnce(appProcess, 'exit');
const rc = await startRemoteControlApp();
await rc.remotely(() => {
const { BrowserView, app } = require('electron');
new BrowserView({}) // eslint-disable-line
setTimeout(() => {
app.quit();
});
});
const [code] = await emittedOnce(rc.process, 'exit');
expect(code).to.equal(0);
});
it('does not crash on exit if added to a browser window', async () => {
const rc = await startRemoteControlApp();
await rc.remotely(() => {
const { app, BrowserView, BrowserWindow } = require('electron');
const bv = new BrowserView();
bv.webContents.loadURL('about:blank');
const bw = new BrowserWindow({ show: false });
bw.addBrowserView(bv);
setTimeout(() => {
app.quit();
});
});
const [code] = await emittedOnce(rc.process, 'exit');
expect(code).to.equal(0);
});
});

View File

@@ -9,7 +9,7 @@ import { AddressInfo } from 'net';
import { app, BrowserWindow, BrowserView, ipcMain, OnBeforeSendHeadersListenerDetails, protocol, screen, webContents, session, WebContents } from 'electron/main';
import { emittedOnce, emittedUntil } from './events-helpers';
import { ifit, ifdescribe, delay } from './spec-helpers';
import { ifit, ifdescribe, defer, delay } from './spec-helpers';
import { closeWindow, closeAllWindows } from './window-helpers';
const features = process._linkedBinding('electron_common_features');
@@ -1007,7 +1007,7 @@ describe('BrowserWindow module', () => {
});
});
ifdescribe(process.platform === 'win32')(`Fullscreen state`, () => {
ifdescribe(process.platform === 'win32')('Fullscreen state', () => {
it('with properties', () => {
it('can be set with the fullscreen constructor option', () => {
w = new BrowserWindow({ fullscreen: true });
@@ -1021,7 +1021,7 @@ describe('BrowserWindow module', () => {
expect(w.fullScreen).to.be.true();
});
it(`checks normal bounds when fullscreen'ed`, async () => {
it('checks normal bounds when fullscreen\'ed', async () => {
const bounds = w.getBounds();
const enterFullScreen = emittedOnce(w, 'enter-full-screen');
w.show();
@@ -1030,7 +1030,7 @@ describe('BrowserWindow module', () => {
expectBoundsEqual(w.getNormalBounds(), bounds);
});
it(`checks normal bounds when unfullscreen'ed`, async () => {
it('checks normal bounds when unfullscreen\'ed', async () => {
const bounds = w.getBounds();
w.once('enter-full-screen', () => {
w.fullScreen = false;
@@ -1056,7 +1056,7 @@ describe('BrowserWindow module', () => {
expect(w.isFullScreen()).to.be.true();
});
it(`checks normal bounds when fullscreen'ed`, async () => {
it('checks normal bounds when fullscreen\'ed', async () => {
const bounds = w.getBounds();
w.show();
@@ -1067,7 +1067,7 @@ describe('BrowserWindow module', () => {
expectBoundsEqual(w.getNormalBounds(), bounds);
});
it(`checks normal bounds when unfullscreen'ed`, async () => {
it('checks normal bounds when unfullscreen\'ed', async () => {
const bounds = w.getBounds();
w.show();
@@ -1518,16 +1518,19 @@ describe('BrowserWindow module', () => {
const w = new BrowserWindow({ show: false });
const bv = new BrowserView();
w.setBrowserView(bv);
defer(() => {
w.removeBrowserView(bv);
(bv.webContents as any).destroy();
});
expect(BrowserWindow.fromBrowserView(bv)!.id).to.equal(w.id);
// if BrowserView isn't explicitly destroyed, it will crash in GC later
bv.destroy();
});
it('returns undefined if not attached', () => {
const bv = new BrowserView();
defer(() => {
(bv.webContents as any).destroy();
});
expect(BrowserWindow.fromBrowserView(bv)).to.be.null('BrowserWindow associated with bv');
// if BrowserView isn't explicitly destroyed, it will crash in GC later
bv.destroy();
});
});

View File

@@ -203,7 +203,7 @@ ifdescribe(!isLinuxOnArm && !process.mas && !process.env.DISABLE_CRASH_REPORTER_
require('electron').crashReporter.start({
submitURL: `http://127.0.0.1:${port}`,
ignoreSystemCrashHandler: true,
extra: { 'longParam': 'a'.repeat(130) }
extra: { longParam: 'a'.repeat(130) }
});
setTimeout(() => process.crash());
}, port);
@@ -381,7 +381,7 @@ ifdescribe(!isLinuxOnArm && !process.mas && !process.env.DISABLE_CRASH_REPORTER_
await remotely(() => {
require('electron').crashReporter.start({
submitURL: 'http://127.0.0.1',
extra: { 'extra1': 'hi' }
extra: { extra1: 'hi' }
});
});
const parameters = await remotely(() => require('electron').crashReporter.getParameters());
@@ -414,8 +414,8 @@ ifdescribe(!isLinuxOnArm && !process.mas && !process.env.DISABLE_CRASH_REPORTER_
crashReporter.start({ submitURL: 'http://' });
const bw = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } });
bw.loadURL('about:blank');
await bw.webContents.executeJavaScript(`require('electron').crashReporter.addExtraParameter('hello', 'world')`);
return bw.webContents.executeJavaScript(`require('electron').crashReporter.getParameters()`);
await bw.webContents.executeJavaScript('require(\'electron\').crashReporter.addExtraParameter(\'hello\', \'world\')');
return bw.webContents.executeJavaScript('require(\'electron\').crashReporter.getParameters()');
});
if (process.platform === 'linux') {
// On Linux, 'getParameters' will also include the global parameters,

View File

@@ -523,7 +523,7 @@ describe('net module', () => {
session: sess
});
const response = await getResponse(urlRequest);
expect(response.headers['x-cookie']).to.equal(`undefined`);
expect(response.headers['x-cookie']).to.equal('undefined');
});
it('should be able to use the sessions cookie store', async () => {

View File

@@ -105,7 +105,7 @@ describe('session module', () => {
});
}
it(`fails to set cookies with samesite=garbage`, async () => {
it('fails to set cookies with samesite=garbage', async () => {
const { cookies } = session.defaultSession;
const value = 'hithere';
await expect(cookies.set({ url, value, sameSite: 'garbage' as any })).to.eventually.be.rejectedWith('Failed to convert \'garbage\' to an appropriate cookie same site value');

View File

@@ -141,6 +141,17 @@ describe('webContents module', () => {
}).to.throw('Unsupported pageSize: i-am-a-bad-pagesize');
});
it('throws when an invalid custom pageSize is passed', () => {
expect(() => {
w.webContents.print({
pageSize: {
width: 100,
height: 200
}
});
}).to.throw('height and width properties must be minimum 352 microns.');
});
it('does not crash with custom margins', () => {
expect(() => {
w.webContents.print({
@@ -1905,7 +1916,7 @@ describe('webContents module', () => {
wasCalled = true;
});
await w.loadURL('about:blank');
await w.webContents.executeJavaScript(`window.open('about:blank')`);
await w.webContents.executeJavaScript('window.open(\'about:blank\')');
await new Promise((resolve) => { process.nextTick(resolve); });
expect(wasCalled).to.equal(false);
await closeAllWindows();

View File

@@ -274,7 +274,7 @@ describe('chrome extensions', () => {
await customSession.loadExtension(path.join(fixtures, 'extensions', 'persistent-background-page'));
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } });
const promise = emittedOnce(app, 'web-contents-created');
await w.loadURL(`about:blank`);
await w.loadURL('about:blank');
const [, bgPageContents] = await promise;
expect(bgPageContents.session).to.not.equal(undefined);
});

View File

@@ -1,6 +0,0 @@
const { BrowserView, app } = require('electron');
app.whenReady().then(function () {
new BrowserView({}) // eslint-disable-line
app.quit();
});

View File

@@ -1,22 +1,25 @@
const { app } = require('electron');
const http = require('http');
const v8 = require('v8');
const server = http.createServer((req, res) => {
const chunks = [];
req.on('data', chunk => { chunks.push(chunk); });
req.on('end', () => {
const js = Buffer.concat(chunks).toString('utf8');
(async () => {
try {
const result = await Promise.resolve(eval(js)); // eslint-disable-line no-eval
res.end(v8.serialize({ result }));
} catch (e) {
res.end(v8.serialize({ error: e.stack }));
}
})();
app.whenReady().then(() => {
const server = http.createServer((req, res) => {
const chunks = [];
req.on('data', chunk => { chunks.push(chunk); });
req.on('end', () => {
const js = Buffer.concat(chunks).toString('utf8');
(async () => {
try {
const result = await Promise.resolve(eval(js)); // eslint-disable-line no-eval
res.end(v8.serialize({ result }));
} catch (e) {
res.end(v8.serialize({ error: e.stack }));
}
})();
});
}).listen(0, '127.0.0.1', () => {
process.stdout.write(`Listening: ${server.address().port}\n`);
});
}).listen(0, '127.0.0.1', () => {
process.stdout.write(`Listening: ${server.address().port}\n`);
});
setTimeout(() => {

View File

@@ -1,7 +1,7 @@
const { BrowserWindow } = require('electron');
class Foo {
set bar (value) {
set bar (value) { // eslint-disable-line accessor-pairs
if (!(value instanceof BrowserWindow)) {
throw new Error('setting error');
}

View File

@@ -31,7 +31,7 @@ class GitFake {
// find the newest shared commit between branches a and b
mergeBase (a: string, b:string): string {
for (const commit of [ ...this.branches[a].reverse() ]) {
for (const commit of [...this.branches[a].reverse()]) {
if (this.branches[b].map((commit: Commit) => commit.sha1).includes(commit.sha1)) {
return commit.sha1;
}
@@ -57,7 +57,7 @@ class GitFake {
stdout = this.branches[branch].map((commit: Commit) => commit.sha1).join('\n');
} else if (args.length > 1 && args[0] === 'log' && args.includes('--format=%H,%s')) {
// expected form: `git log --format=%H,%s sha1..branchName
const [ start, branch ] = args[args.length - 1].split('..');
const [start, branch] = args[args.length - 1].split('..');
const lines : string[] = [];
let started = false;
for (const commit of this.branches[branch]) {
@@ -108,7 +108,7 @@ describe('release notes', () => {
const wrapper = (args: string[], path: string, options?: IGitExecutionOptions | undefined) => gitFake.exec(args, path, options);
sandbox.replace(GitProcess, 'exec', wrapper);
gitFake.setBranch(oldBranch, [ ...sharedHistory, oldFix ]);
gitFake.setBranch(oldBranch, [...sharedHistory, oldFix]);
});
afterEach(() => {
@@ -120,8 +120,8 @@ describe('release notes', () => {
// while oldBranch was the latest stable release
it('are skipped if the target version is a new major line (x.0.0)', async function () {
const version = 'v9.0.0';
gitFake.setBranch(oldBranch, [ ...sharedHistory, oldTropFix ]);
gitFake.setBranch(newBranch, [ ...sharedHistory, newTropFix ]);
gitFake.setBranch(oldBranch, [...sharedHistory, oldTropFix]);
gitFake.setBranch(newBranch, [...sharedHistory, newTropFix]);
const results: any = await notes.get(oldBranch, newBranch, version);
expect(results.fix).to.have.lengthOf(0);
});
@@ -130,8 +130,8 @@ describe('release notes', () => {
// multiple stable branches at once, including newBranch.
it('are included if the target version is a minor or patch bump', async function () {
const version = 'v9.0.1';
gitFake.setBranch(oldBranch, [ ...sharedHistory, oldTropFix ]);
gitFake.setBranch(newBranch, [ ...sharedHistory, newTropFix ]);
gitFake.setBranch(oldBranch, [...sharedHistory, oldTropFix]);
gitFake.setBranch(newBranch, [...sharedHistory, newTropFix]);
const results: any = await notes.get(oldBranch, newBranch, version);
expect(results.fix).to.have.lengthOf(1);
});
@@ -146,7 +146,7 @@ describe('release notes', () => {
const testCommit = new Commit('89eb309d0b22bd4aec058ffaf983e81e56a5c378', 'feat: lole u got troled hard (#21891)');
const version = 'v9.0.0';
gitFake.setBranch(newBranch, [ ...sharedHistory, testCommit ]);
gitFake.setBranch(newBranch, [...sharedHistory, testCommit]);
const results: any = await notes.get(oldBranch, newBranch, version);
expect(results.feat).to.have.lengthOf(1);
expect(results.feat[0].hash).to.equal(testCommit.sha1);
@@ -160,7 +160,7 @@ describe('release notes', () => {
it("honors 'feat' type", async function () {
const testCommit = newFeat;
gitFake.setBranch(newBranch, [ ...sharedHistory, testCommit ]);
gitFake.setBranch(newBranch, [...sharedHistory, testCommit]);
const results: any = await notes.get(oldBranch, newBranch, version);
expect(results.feat).to.have.lengthOf(1);
expect(results.feat[0].hash).to.equal(testCommit.sha1);
@@ -168,7 +168,7 @@ describe('release notes', () => {
it("honors 'fix' type", async function () {
const testCommit = newFix;
gitFake.setBranch(newBranch, [ ...sharedHistory, testCommit ]);
gitFake.setBranch(newBranch, [...sharedHistory, testCommit]);
const results: any = await notes.get(oldBranch, newBranch, version);
expect(results.fix).to.have.lengthOf(1);
expect(results.fix[0].hash).to.equal(testCommit.sha1);
@@ -176,7 +176,7 @@ describe('release notes', () => {
it("honors 'BREAKING CHANGE' message", async function () {
const testCommit = newBreaking;
gitFake.setBranch(newBranch, [ ...sharedHistory, testCommit ]);
gitFake.setBranch(newBranch, [...sharedHistory, testCommit]);
const results: any = await notes.get(oldBranch, newBranch, version);
expect(results.breaking).to.have.lengthOf(1);
expect(results.breaking[0].hash).to.equal(testCommit.sha1);

View File

@@ -38,106 +38,106 @@ function ToWebM (frames, outputAsArray) {
const EBML = [
{
'id': 0x1a45dfa3, // EBML
'data': [
id: 0x1a45dfa3, // EBML
data: [
{
'data': 1,
'id': 0x4286 // EBMLVersion
data: 1,
id: 0x4286 // EBMLVersion
},
{
'data': 1,
'id': 0x42f7 // EBMLReadVersion
data: 1,
id: 0x42f7 // EBMLReadVersion
},
{
'data': 4,
'id': 0x42f2 // EBMLMaxIDLength
data: 4,
id: 0x42f2 // EBMLMaxIDLength
},
{
'data': 8,
'id': 0x42f3 // EBMLMaxSizeLength
data: 8,
id: 0x42f3 // EBMLMaxSizeLength
},
{
'data': 'webm',
'id': 0x4282 // DocType
data: 'webm',
id: 0x4282 // DocType
},
{
'data': 2,
'id': 0x4287 // DocTypeVersion
data: 2,
id: 0x4287 // DocTypeVersion
},
{
'data': 2,
'id': 0x4285 // DocTypeReadVersion
data: 2,
id: 0x4285 // DocTypeReadVersion
}
]
},
{
'id': 0x18538067, // Segment
'data': [
id: 0x18538067, // Segment
data: [
{
'id': 0x1549a966, // Info
'data': [
id: 0x1549a966, // Info
data: [
{
'data': 1e6, // do things in millisecs (num of nanosecs for duration scale)
'id': 0x2ad7b1 // TimecodeScale
data: 1e6, // do things in millisecs (num of nanosecs for duration scale)
id: 0x2ad7b1 // TimecodeScale
},
{
'data': 'whammy',
'id': 0x4d80 // MuxingApp
data: 'whammy',
id: 0x4d80 // MuxingApp
},
{
'data': 'whammy',
'id': 0x5741 // WritingApp
data: 'whammy',
id: 0x5741 // WritingApp
},
{
'data': doubleToString(info.duration),
'id': 0x4489 // Duration
data: doubleToString(info.duration),
id: 0x4489 // Duration
}
]
},
{
'id': 0x1654ae6b, // Tracks
'data': [
id: 0x1654ae6b, // Tracks
data: [
{
'id': 0xae, // TrackEntry
'data': [
id: 0xae, // TrackEntry
data: [
{
'data': 1,
'id': 0xd7 // TrackNumber
data: 1,
id: 0xd7 // TrackNumber
},
{
'data': 1,
'id': 0x73c5 // TrackUID
data: 1,
id: 0x73c5 // TrackUID
},
{
'data': 0,
'id': 0x9c // FlagLacing
data: 0,
id: 0x9c // FlagLacing
},
{
'data': 'und',
'id': 0x22b59c // Language
data: 'und',
id: 0x22b59c // Language
},
{
'data': 'V_VP8',
'id': 0x86 // CodecID
data: 'V_VP8',
id: 0x86 // CodecID
},
{
'data': 'VP8',
'id': 0x258688 // CodecName
data: 'VP8',
id: 0x258688 // CodecName
},
{
'data': 1,
'id': 0x83 // TrackType
data: 1,
id: 0x83 // TrackType
},
{
'id': 0xe0, // Video
'data': [
id: 0xe0, // Video
data: [
{
'data': info.width,
'id': 0xb0 // PixelWidth
data: info.width,
id: 0xb0 // PixelWidth
},
{
'data': info.height,
'id': 0xba // PixelHeight
data: info.height,
id: 0xba // PixelHeight
}
]
}
@@ -146,8 +146,8 @@ function ToWebM (frames, outputAsArray) {
]
},
{
'id': 0x1c53bb6b, // Cues
'data': [
id: 0x1c53bb6b, // Cues
data: [
// cue insertion point
]
}
@@ -165,23 +165,23 @@ function ToWebM (frames, outputAsArray) {
let clusterTimecode = 0;
while (frameNumber < frames.length) {
const cuePoint = {
'id': 0xbb, // CuePoint
'data': [
id: 0xbb, // CuePoint
data: [
{
'data': Math.round(clusterTimecode),
'id': 0xb3 // CueTime
data: Math.round(clusterTimecode),
id: 0xb3 // CueTime
},
{
'id': 0xb7, // CueTrackPositions
'data': [
id: 0xb7, // CueTrackPositions
data: [
{
'data': 1,
'id': 0xf7 // CueTrack
data: 1,
id: 0xf7 // CueTrack
},
{
'data': 0, // to be filled in when we know it
'size': 8,
'id': 0xf1 // CueClusterPosition
data: 0, // to be filled in when we know it
size: 8,
id: 0xf1 // CueClusterPosition
}
]
}
@@ -200,11 +200,11 @@ function ToWebM (frames, outputAsArray) {
let clusterCounter = 0;
const cluster = {
'id': 0x1f43b675, // Cluster
'data': [
id: 0x1f43b675, // Cluster
data: [
{
'data': Math.round(clusterTimecode),
'id': 0xe7 // Timecode
data: Math.round(clusterTimecode),
id: 0xe7 // Timecode
}
].concat(clusterFrames.map(function (webp) {
const block = makeSimpleBlock({
@@ -453,12 +453,17 @@ function doubleToString (num) {
.join(''); // join the bytes in holy matrimony as a string
}
function WhammyVideo (speed, quality) { // a more abstract-ish API
function WhammyVideo (speed, quality = 0.8) { // a more abstract-ish API
this.frames = [];
this.duration = 1000 / speed;
this.quality = quality || 0.8;
this.quality = quality;
}
/**
*
* @param {string} frame
* @param {number} [duration]
*/
WhammyVideo.prototype.add = function (frame, duration) {
if (typeof duration !== 'undefined' && this.duration) throw new Error("you can't pass a duration if the fps is set");
if (typeof duration === 'undefined' && !this.duration) throw new Error("if you don't have the fps set, you need to have durations here.");

View File

@@ -112,17 +112,11 @@ describe('clipboard module', () => {
});
});
describe('clipboard.writeBuffer(format, buffer)', () => {
describe('clipboard.readBuffer(format)', () => {
it('writes a Buffer for the specified format', function () {
if (process.platform !== 'darwin') {
// FIXME(alexeykuzmin): Skip the test.
// this.skip()
return;
}
const buffer = Buffer.from('writeBuffer', 'utf8');
clipboard.writeBuffer('public.utf8-plain-text', buffer);
expect(clipboard.readText()).to.equal('writeBuffer');
expect(buffer.equals(clipboard.readBuffer('public.utf8-plain-text'))).to.equal(true);
});
it('throws an error when a non-Buffer is specified', () => {
@@ -131,18 +125,4 @@ describe('clipboard module', () => {
}).to.throw(/buffer must be a node Buffer/);
});
});
describe('clipboard.readBuffer(format)', () => {
before(function () {
if (process.platform !== 'darwin') {
this.skip();
}
});
it('returns a Buffer of the content for the specified format', () => {
const buffer = Buffer.from('this is binary', 'utf8');
clipboard.writeText(buffer.toString());
expect(buffer.equals(clipboard.readBuffer('public.utf8-plain-text'))).to.equal(true);
});
});
});

View File

@@ -1,4 +1,6 @@
declare var internalBinding: any;
declare var nodeProcess: any;
declare var isolatedWorld: any;
declare var binding: { get: (name: string) => any; process: NodeJS.Process; createPreloadScript: (src: string) => Function };
declare const BUILDFLAG: (flag: boolean) => boolean;

2626
yarn.lock

File diff suppressed because it is too large Load Diff