mirror of
https://github.com/electron/electron.git
synced 2026-03-19 03:02:02 -04:00
Compare commits
4 Commits
fix-trace-
...
downloads-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c203d4c070 | ||
|
|
74c1811b35 | ||
|
|
313e501454 | ||
|
|
1f6dbb0917 |
@@ -192,6 +192,7 @@ gh label list --repo electron/electron --search target/ --json name,color --jq '
|
||||
```bash
|
||||
npm run lint # Run all linters
|
||||
npm run lint:clang-format # C++ formatting
|
||||
npm run lint:api-history # Validate API history YAML blocks in docs
|
||||
```
|
||||
|
||||
## Key Files
|
||||
|
||||
58
docs/CLAUDE.md
Normal file
58
docs/CLAUDE.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Electron Documentation Guide
|
||||
|
||||
## API History Migration
|
||||
|
||||
Guide: `docs/development/api-history-migration-guide.md`
|
||||
Style rules: `docs/development/style-guide.md` (see "API History" section)
|
||||
Schema: `docs/api-history.schema.json`
|
||||
Lint: `npm run lint:api-history`
|
||||
|
||||
### Format
|
||||
|
||||
Place YAML history block directly after the Markdown header, before parameters:
|
||||
|
||||
````md
|
||||
### `module.method(args)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/XXXXX
|
||||
```
|
||||
-->
|
||||
|
||||
* `arg` type - Description.
|
||||
````
|
||||
|
||||
### Finding when an API was added
|
||||
|
||||
- `git log --all --reverse --oneline -S "methodName" -- docs/api/file.md` — find first commit adding a method name
|
||||
- `git log --reverse -L :FunctionName:path/to/source.cc` — trace C++ implementation history
|
||||
- `git log --grep="keyword" --oneline` — find merge commits referencing PRs
|
||||
- `gh pr view <number> --repo electron/electron --json baseRefName` — verify PR targets main (not a backport)
|
||||
- Always use the main-branch PR URL in history blocks, not backport PRs
|
||||
|
||||
### Cross-referencing breaking changes
|
||||
|
||||
- Search `docs/breaking-changes.md` for the API name to find deprecations/removals
|
||||
- Use `git blame` on the breaking-changes entry to find the associated PR
|
||||
- Add `breaking-changes-header` field using the heading ID from breaking-changes.md
|
||||
|
||||
### Placement rules
|
||||
|
||||
- Only add blocks to actual API entries (methods, events, properties with backtick signatures)
|
||||
- Do NOT add blocks to section headers like `## Methods`, `### Instance Methods`, `## Events`
|
||||
- Module-level blocks go after the `# moduleName` heading, before the module description quote
|
||||
- For changes affecting multiple APIs, add a block under each affected top-level heading (see style guide "Change affecting multiple APIs")
|
||||
|
||||
### Key details
|
||||
|
||||
- `added` and `deprecated` arrays have `maxItems: 1`; `changes` can have multiple items
|
||||
- `changes` entries require a `description` field; `added`/`deprecated` do not
|
||||
- Wrap descriptions in double quotes to avoid YAML parsing issues with special characters
|
||||
- Early Electron APIs (pre-2015) use merge-commit PRs (e.g., `Merge pull request #534`)
|
||||
- Very early APIs (2013-2014, e.g., `ipcMain.on`, `ipcRenderer.send`) predate GitHub PRs — skip history blocks for these
|
||||
- When multiple APIs were added in the same PR, they all reference the same PR URL
|
||||
- Promisification PRs (e.g., #17355) count as `changes` entries with a description
|
||||
- These PRs are breaking changes and should have their notes as "This method now returns a Promise instead of using a callback function."
|
||||
- APIs that were deprecated and then removed from docs don't need history blocks (the removal is in `breaking-changes.md`)
|
||||
@@ -28,7 +28,10 @@ added:
|
||||
* `window` [BaseWindow](base-window.md) (optional)
|
||||
* `options` Object
|
||||
* `title` string (optional)
|
||||
* `defaultPath` string (optional)
|
||||
* `defaultPath` string (optional) - Absolute directory path, absolute file
|
||||
path, or file name to use by default. If not provided, the dialog will
|
||||
default to the user's Downloads folder, or their home directory if Downloads
|
||||
doesn't exist.
|
||||
* `buttonLabel` string (optional) - Custom label for the confirmation button, when
|
||||
left empty the default label will be used.
|
||||
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
|
||||
@@ -109,7 +112,10 @@ changes:
|
||||
* `window` [BaseWindow](base-window.md) (optional)
|
||||
* `options` Object
|
||||
* `title` string (optional)
|
||||
* `defaultPath` string (optional)
|
||||
* `defaultPath` string (optional) - Absolute directory path, absolute file
|
||||
path, or file name to use by default. If not provided, the dialog will
|
||||
default to the user's Downloads folder, or their home directory if Downloads
|
||||
doesn't exist.
|
||||
* `buttonLabel` string (optional) - Custom label for the confirmation button, when
|
||||
left empty the default label will be used.
|
||||
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
|
||||
@@ -198,7 +204,9 @@ added:
|
||||
* `options` Object
|
||||
* `title` string (optional) - The dialog title. Cannot be displayed on some _Linux_ desktop environments.
|
||||
* `defaultPath` string (optional) - Absolute directory path, absolute file
|
||||
path, or file name to use by default.
|
||||
path, or file name to use by default. If not provided, the dialog will
|
||||
default to the user's Downloads folder, or their home directory if Downloads
|
||||
doesn't exist.
|
||||
* `buttonLabel` string (optional) - Custom label for the confirmation button, when
|
||||
left empty the default label will be used.
|
||||
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
|
||||
@@ -238,7 +246,9 @@ changes:
|
||||
* `options` Object
|
||||
* `title` string (optional) - The dialog title. Cannot be displayed on some _Linux_ desktop environments.
|
||||
* `defaultPath` string (optional) - Absolute directory path, absolute file
|
||||
path, or file name to use by default.
|
||||
path, or file name to use by default. If not provided, the dialog will
|
||||
default to the user's Downloads folder, or their home directory if Downloads
|
||||
doesn't exist.
|
||||
* `buttonLabel` string (optional) - Custom label for the confirmation button, when
|
||||
left empty the default label will be used.
|
||||
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
|
||||
|
||||
@@ -55,6 +55,13 @@ The `globalShortcut` module has the following methods:
|
||||
|
||||
### `globalShortcut.register(accelerator, callback)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/534
|
||||
```
|
||||
-->
|
||||
|
||||
* `accelerator` string - An [accelerator](../tutorial/keyboard-shortcuts.md#accelerators) shortcut.
|
||||
* `callback` Function
|
||||
|
||||
@@ -77,6 +84,13 @@ the app has been authorized as a [trusted accessibility client](https://develope
|
||||
|
||||
### `globalShortcut.registerAll(accelerators, callback)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/15542
|
||||
```
|
||||
-->
|
||||
|
||||
* `accelerators` string[] - An array of [accelerator](../tutorial/keyboard-shortcuts.md#accelerators) shortcuts.
|
||||
* `callback` Function
|
||||
|
||||
@@ -96,6 +110,13 @@ the app has been authorized as a [trusted accessibility client](https://develope
|
||||
|
||||
### `globalShortcut.isRegistered(accelerator)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/534
|
||||
```
|
||||
-->
|
||||
|
||||
* `accelerator` string - An [accelerator](../tutorial/keyboard-shortcuts.md#accelerators) shortcut.
|
||||
|
||||
Returns `boolean` - Whether this application has registered `accelerator`.
|
||||
@@ -106,10 +127,24 @@ don't want applications to fight for global shortcuts.
|
||||
|
||||
### `globalShortcut.unregister(accelerator)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/534
|
||||
```
|
||||
-->
|
||||
|
||||
* `accelerator` string - An [accelerator](../tutorial/keyboard-shortcuts.md#accelerators) shortcut.
|
||||
|
||||
Unregisters the global shortcut of `accelerator`.
|
||||
|
||||
### `globalShortcut.unregisterAll()`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/534
|
||||
```
|
||||
-->
|
||||
|
||||
Unregisters all of the global shortcuts.
|
||||
|
||||
@@ -35,6 +35,13 @@ webContentsView.webContents.loadURL('https://electronjs.org')
|
||||
|
||||
## Class: ImageView extends `View`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/46760
|
||||
```
|
||||
-->
|
||||
|
||||
> A View that displays an image.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
@@ -49,6 +56,13 @@ Process: [Main](../glossary.md#main-process)
|
||||
|
||||
### `new ImageView()` _Experimental_
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/46760
|
||||
```
|
||||
-->
|
||||
|
||||
Creates an ImageView.
|
||||
|
||||
### Instance Methods
|
||||
@@ -58,6 +72,13 @@ addition to those inherited from [View](view.md):
|
||||
|
||||
#### `image.setImage(image)` _Experimental_
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/46760
|
||||
```
|
||||
-->
|
||||
|
||||
* `image` NativeImage
|
||||
|
||||
Sets the image for this `ImageView`. Note that only image formats supported by
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# inAppPurchase
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/11292
|
||||
```
|
||||
-->
|
||||
|
||||
> In-app purchases on Mac App Store.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
@@ -10,6 +17,13 @@ The `inAppPurchase` module emits the following events:
|
||||
|
||||
### Event: 'transactions-updated'
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/11292
|
||||
```
|
||||
-->
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
@@ -23,6 +37,19 @@ The `inAppPurchase` module has the following methods:
|
||||
|
||||
### `inAppPurchase.purchaseProduct(productID[, opts])`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/11292
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/17355
|
||||
description: "This method now returns a Promise instead of using a callback function."
|
||||
breaking-changes-header: api-changed-callback-based-versions-of-promisified-apis
|
||||
- pr-url: https://github.com/electron/electron/pull/35902
|
||||
description: "Added `username` option to `opts` parameter."
|
||||
```
|
||||
-->
|
||||
|
||||
* `productID` string
|
||||
* `opts` Integer | Object (optional) - If specified as an integer, defines the quantity.
|
||||
* `quantity` Integer (optional) - The number of items the user wants to purchase.
|
||||
@@ -34,6 +61,17 @@ You should listen for the `transactions-updated` event as soon as possible and c
|
||||
|
||||
### `inAppPurchase.getProducts(productIDs)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/12464
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/17355
|
||||
description: "This method now returns a Promise instead of using a callback function."
|
||||
breaking-changes-header: api-changed-callback-based-versions-of-promisified-apis
|
||||
```
|
||||
-->
|
||||
|
||||
* `productIDs` string[] - The identifiers of the products to get.
|
||||
|
||||
Returns `Promise<Product[]>` - Resolves with an array of [`Product`](structures/product.md) objects.
|
||||
@@ -42,24 +80,59 @@ Retrieves the product descriptions.
|
||||
|
||||
### `inAppPurchase.canMakePayments()`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/11292
|
||||
```
|
||||
-->
|
||||
|
||||
Returns `boolean` - whether a user can make a payment.
|
||||
|
||||
### `inAppPurchase.restoreCompletedTransactions()`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/21461
|
||||
```
|
||||
-->
|
||||
|
||||
Restores finished transactions. This method can be called either to install purchases on additional devices, or to restore purchases for an application that the user deleted and reinstalled.
|
||||
|
||||
[The payment queue](https://developer.apple.com/documentation/storekit/skpaymentqueue?language=objc) delivers a new transaction for each previously completed transaction that can be restored. Each transaction includes a copy of the original transaction.
|
||||
|
||||
### `inAppPurchase.getReceiptURL()`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/11292
|
||||
```
|
||||
-->
|
||||
|
||||
Returns `string` - the path to the receipt.
|
||||
|
||||
### `inAppPurchase.finishAllTransactions()`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/12464
|
||||
```
|
||||
-->
|
||||
|
||||
Completes all pending transactions.
|
||||
|
||||
### `inAppPurchase.finishTransactionByDate(date)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/12464
|
||||
```
|
||||
-->
|
||||
|
||||
* `date` string - The ISO formatted date of the transaction to finish.
|
||||
|
||||
Completes the pending transactions corresponding to the date.
|
||||
|
||||
@@ -46,6 +46,13 @@ Listens to `channel`, when a new message arrives `listener` would be called with
|
||||
|
||||
### `ipcMain.off(channel, listener)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/44651
|
||||
```
|
||||
-->
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function
|
||||
* `event` [IpcMainEvent][ipc-main-event]
|
||||
@@ -89,6 +96,13 @@ Removes all listeners from the specified `channel`. Removes all listeners from a
|
||||
|
||||
### `ipcMain.handle(channel, listener)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/18449
|
||||
```
|
||||
-->
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function\<Promise\<any\> | any\>
|
||||
* `event` [IpcMainInvokeEvent][ipc-main-invoke-event]
|
||||
@@ -126,6 +140,13 @@ provided to the renderer process. Please refer to
|
||||
|
||||
### `ipcMain.handleOnce(channel, listener)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/18449
|
||||
```
|
||||
-->
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function\<Promise\<any\> | any\>
|
||||
* `event` [IpcMainInvokeEvent][ipc-main-invoke-event]
|
||||
@@ -136,6 +157,13 @@ Handles a single `invoke`able IPC message, then removes the listener. See
|
||||
|
||||
### `ipcMain.removeHandler(channel)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/18449
|
||||
```
|
||||
-->
|
||||
|
||||
* `channel` string
|
||||
|
||||
Removes any handler for `channel`, if present.
|
||||
|
||||
@@ -59,6 +59,13 @@ for more info.
|
||||
|
||||
### `ipcRenderer.off(channel, listener)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/39816
|
||||
```
|
||||
-->
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function
|
||||
* `event` [IpcRendererEvent][ipc-renderer-event]
|
||||
@@ -79,6 +86,13 @@ only the next time a message is sent to `channel`, after which it is removed.
|
||||
|
||||
### `ipcRenderer.addListener(channel, listener)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/39816
|
||||
```
|
||||
-->
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function
|
||||
* `event` [IpcRendererEvent][ipc-renderer-event]
|
||||
@@ -129,6 +143,13 @@ If you want to receive a single response from the main process, like the result
|
||||
|
||||
### `ipcRenderer.invoke(channel, ...args)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/18449
|
||||
```
|
||||
-->
|
||||
|
||||
* `channel` string
|
||||
* `...args` any[]
|
||||
|
||||
@@ -209,6 +230,13 @@ and replies by setting `event.returnValue`.
|
||||
|
||||
### `ipcRenderer.postMessage(channel, message, [transfer])`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/22404
|
||||
```
|
||||
-->
|
||||
|
||||
* `channel` string
|
||||
* `message` any
|
||||
* `transfer` MessagePort[] (optional)
|
||||
|
||||
@@ -12,6 +12,34 @@ This document uses the following convention to categorize breaking changes:
|
||||
* **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
|
||||
* **Removed:** An API or feature was removed, and is no longer supported by Electron.
|
||||
|
||||
## Planned Breaking API Changes (43.0)
|
||||
|
||||
### Behavior Changed: Dialog methods default to Downloads directory
|
||||
|
||||
The `defaultPath` option for the following methods now defaults to the user's Downloads folder (or their home directory if Downloads doesn't exist) when not explicitly provided:
|
||||
|
||||
* `dialog.showOpenDialog`
|
||||
* `dialog.showOpenDialogSync`
|
||||
* `dialog.showSaveDialog`
|
||||
* `dialog.showSaveDialogSync`
|
||||
|
||||
Previously, when no `defaultPath` was provided, the underlying OS file dialog would determine the initial directory — typically remembering the last directory the user navigated to, or falling back to an OS-specific default. Now, Electron explicitly sets the initial directory to Downloads, which also means the OS will no longer track and restore the last-used directory between dialog invocations.
|
||||
|
||||
To preserve the old behavior, you can track the last-used directory yourself and pass it as `defaultPath`:
|
||||
|
||||
```js
|
||||
const path = require('node:path')
|
||||
|
||||
let lastUsedPath
|
||||
const result = await dialog.showOpenDialog({
|
||||
defaultPath: lastUsedPath
|
||||
})
|
||||
|
||||
if (!result.canceled && result.filePaths.length > 0) {
|
||||
lastUsedPath = path.dirname(result.filePaths[0])
|
||||
}
|
||||
```
|
||||
|
||||
## Planned Breaking API Changes (42.0)
|
||||
|
||||
### Behavior Changed: macOS notifications now use `UNNotification` API
|
||||
@@ -59,6 +87,17 @@ npm install electron --save-dev --ignore-scripts
|
||||
npx install-electron --no
|
||||
```
|
||||
|
||||
If you need to test changes across platforms or architectures, you should now use the
|
||||
`ELECTRON_INSTALL_ARCH` and `ELECTRON_INSTALL_PLATFORM` environment variables.
|
||||
|
||||
```sh
|
||||
# before: pass npm config flag on install command
|
||||
npm install --platform=mas electron --save-dev
|
||||
# after: add env var when you first run the Electron command
|
||||
npm install electron --save-dev
|
||||
ELECTRON_INSTALL_PLATFORM=mas npx electron . --no
|
||||
```
|
||||
|
||||
### Removed: `quotas` object from `Session.clearStorageData(options)`
|
||||
|
||||
When calling `Session.clearStorageData(options)`, the `options.quotas` object is no longer supported because it has been
|
||||
|
||||
@@ -51,20 +51,40 @@ any dependencies in your app will not be installed.
|
||||
## Customization
|
||||
|
||||
If you want to change the architecture that is downloaded (e.g., `x64` on an
|
||||
`arm64` machine), you can use the `--arch` flag with npm install or set the
|
||||
`npm_config_arch` environment variable:
|
||||
`arm64` machine), you can set the `ELECTRON_INSTALL_ARCH` environment variable:
|
||||
|
||||
```shell
|
||||
npm install --arch=x64 electron
|
||||
```sh
|
||||
# Inside an npm script or with npx
|
||||
ELECTRON_INSTALL_ARCH=x64 electron .
|
||||
```
|
||||
|
||||
Supported architectures are a subset of Node.js [`process.arch`](https://nodejs.org/api/process.html#processarch)
|
||||
values, and include:
|
||||
|
||||
* `x64` (Intel Mac and 64-bit Windows)
|
||||
* `ia32` (32-bit Windows)
|
||||
* `arm64` (Apple silicon, Windows on ARM, ARM64 Linux)
|
||||
* `arm` (32-bit ARM)
|
||||
|
||||
In addition to changing the architecture, you can also specify the platform
|
||||
(e.g., `win32`, `linux`, etc.) using the `--platform` flag:
|
||||
|
||||
```shell
|
||||
npm install --platform=win32 electron
|
||||
```sh
|
||||
# Inside an npm script or with npx
|
||||
ELECTRON_INSTALL_PLATFORM=mas electron .
|
||||
```
|
||||
|
||||
Supported platforms are Node-like [platform strings](https://nodejs.org/api/process.html#processplatform):
|
||||
|
||||
* `darwin`
|
||||
* `mas` ([Mac App Store](./mac-app-store-submission-guide.md))
|
||||
* `win32`
|
||||
* `linux`
|
||||
|
||||
> [!TIP]
|
||||
> To see all available platform/architecture combinations for a particular release, see the artifacts
|
||||
> on [Electron's GitHub Releases](https://github.com/electron/electron/releases).
|
||||
|
||||
## Proxies
|
||||
|
||||
If you need to use an HTTP proxy, you need to set the `ELECTRON_GET_USE_PROXY` variable to any
|
||||
|
||||
@@ -78,6 +78,7 @@ auto_filenames = {
|
||||
"docs/api/web-utils.md",
|
||||
"docs/api/webview-tag.md",
|
||||
"docs/api/window-open.md",
|
||||
"docs/api/structures/activation-arguments.md",
|
||||
"docs/api/structures/base-window-options.md",
|
||||
"docs/api/structures/bluetooth-device.md",
|
||||
"docs/api/structures/browser-window-options.md",
|
||||
|
||||
@@ -21,8 +21,11 @@ if (isInstalled()) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const platform = process.env.npm_config_platform || process.platform;
|
||||
let arch = process.env.npm_config_arch || process.arch;
|
||||
const platform = process.env.ELECTRON_INSTALL_PLATFORM || process.env.npm_config_platform || process.platform;
|
||||
let arch =
|
||||
process.env.ELECTRON_INSTALL_ARCH ||
|
||||
process.env.npm_config_arch ||
|
||||
process.arch;
|
||||
|
||||
if (platform === 'darwin' && process.platform === 'darwin' && arch === 'x64' &&
|
||||
process.env.npm_config_arch === undefined) {
|
||||
|
||||
@@ -63,31 +63,6 @@ index f8b4fd7c4ca5a0907806c7e804de8c951675a36a..209e3bcf8be5a23ac528dcd673bed82c
|
||||
}
|
||||
|
||||
function ipToInt(ip) {
|
||||
diff --git a/lib/internal/trace_events_async_hooks.js b/lib/internal/trace_events_async_hooks.js
|
||||
index a9f517ffc9e4eea5bc68997ffadc85d43dde2a52..d3db6bf119a6bb9cea1d069957f89cc7f99512b7 100644
|
||||
--- a/lib/internal/trace_events_async_hooks.js
|
||||
+++ b/lib/internal/trace_events_async_hooks.js
|
||||
@@ -11,15 +11,13 @@ const { trace } = internalBinding('trace_events');
|
||||
const async_wrap = internalBinding('async_wrap');
|
||||
const async_hooks = require('async_hooks');
|
||||
const {
|
||||
- CHAR_LOWERCASE_B,
|
||||
- CHAR_LOWERCASE_E,
|
||||
+ CHAR_UPPERCASE_B,
|
||||
+ CHAR_UPPERCASE_E,
|
||||
} = require('internal/constants');
|
||||
|
||||
-// Use small letters such that chrome://tracing groups by the name.
|
||||
-// The behavior is not only useful but the same as the events emitted using
|
||||
-// the specific C++ macros.
|
||||
-const kBeforeEvent = CHAR_LOWERCASE_B;
|
||||
-const kEndEvent = CHAR_LOWERCASE_E;
|
||||
+// See v8/src/builtins/builtins-trace.cc - must be uppercase for perfetto
|
||||
+const kBeforeEvent = CHAR_UPPERCASE_B;
|
||||
+const kEndEvent = CHAR_UPPERCASE_E;
|
||||
const kTraceEventCategory = 'node,node.async_hooks';
|
||||
|
||||
const kEnabled = Symbol('enabled');
|
||||
diff --git a/node.gyp b/node.gyp
|
||||
index f5cd416b5fe7a51084bc4af9a4427a8e62599fd8..5eb70ce3820f2b82121bc102c5182ab768cbef36 100644
|
||||
--- a/node.gyp
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "shell/browser/javascript_environment.h"
|
||||
#include "shell/browser/native_window_views.h"
|
||||
#include "shell/browser/ui/file_dialog.h"
|
||||
#include "shell/common/electron_paths.h"
|
||||
#include "shell/common/gin_converters/callback_converter.h"
|
||||
#include "shell/common/gin_converters/file_path_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
@@ -81,14 +82,18 @@ class FileChooserDialog : public ui::SelectFileDialog::Listener {
|
||||
ui::SelectFileDialog::FileTypeInfo file_info =
|
||||
GetFilterInfo(settings.filters);
|
||||
ApplySettings(settings);
|
||||
dialog_->SelectFile(
|
||||
ui::SelectFileDialog::SELECT_SAVEAS_FILE,
|
||||
base::UTF8ToUTF16(settings.title), settings.default_path,
|
||||
&file_info /* file_types */, 0 /* file_type_index */,
|
||||
base::FilePath::StringType() /* default_extension */,
|
||||
settings.parent_window ? settings.parent_window->GetNativeWindow()
|
||||
: nullptr,
|
||||
nullptr);
|
||||
base::FilePath default_path = settings.default_path.empty()
|
||||
? electron::GetDefaultPath()
|
||||
: settings.default_path;
|
||||
|
||||
dialog_->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE,
|
||||
base::UTF8ToUTF16(settings.title), default_path,
|
||||
&file_info /* file_types */, 0 /* file_type_index */,
|
||||
base::FilePath::StringType() /* default_extension */,
|
||||
settings.parent_window
|
||||
? settings.parent_window->GetNativeWindow()
|
||||
: nullptr,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
void RunSaveDialog(gin_helper::Promise<gin_helper::Dictionary> promise,
|
||||
@@ -108,9 +113,13 @@ class FileChooserDialog : public ui::SelectFileDialog::Listener {
|
||||
ui::SelectFileDialog::FileTypeInfo file_info =
|
||||
GetFilterInfo(settings.filters);
|
||||
ApplySettings(settings);
|
||||
base::FilePath default_path = settings.default_path.empty()
|
||||
? electron::GetDefaultPath()
|
||||
: settings.default_path;
|
||||
|
||||
dialog_->SelectFile(
|
||||
GetDialogType(settings.properties), base::UTF8ToUTF16(settings.title),
|
||||
settings.default_path, &file_info, 0 /* file_type_index */,
|
||||
default_path, &file_info, 0 /* file_type_index */,
|
||||
base::FilePath::StringType() /* default_extension */,
|
||||
settings.parent_window ? settings.parent_window->GetNativeWindow()
|
||||
: nullptr,
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "electron/mas.h"
|
||||
#include "shell/browser/native_window.h"
|
||||
#include "shell/common/electron_paths.h"
|
||||
#include "shell/common/gin_converters/file_path_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/gin_helper/promise.h"
|
||||
@@ -186,14 +187,18 @@ void SetupDialog(NSSavePanel* dialog, const DialogSettings& settings) {
|
||||
|
||||
[dialog setShowsTagField:settings.shows_tag_field];
|
||||
|
||||
base::FilePath default_path = settings.default_path.empty()
|
||||
? electron::GetDefaultPath()
|
||||
: settings.default_path;
|
||||
|
||||
NSString* default_dir = nil;
|
||||
NSString* default_filename = nil;
|
||||
if (!settings.default_path.empty()) {
|
||||
if (!default_path.empty()) {
|
||||
electron::ScopedAllowBlockingForElectron allow_blocking;
|
||||
if (base::DirectoryExists(settings.default_path)) {
|
||||
default_dir = base::SysUTF8ToNSString(settings.default_path.value());
|
||||
if (base::DirectoryExists(default_path)) {
|
||||
default_dir = base::SysUTF8ToNSString(default_path.value());
|
||||
} else {
|
||||
if (settings.default_path.IsAbsolute()) {
|
||||
if (default_path.IsAbsolute()) {
|
||||
default_dir =
|
||||
base::SysUTF8ToNSString(settings.default_path.DirName().value());
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "base/win/registry.h"
|
||||
#include "shell/browser/native_window_views.h"
|
||||
#include "shell/browser/ui/win/dialog_thread.h"
|
||||
#include "shell/common/electron_paths.h"
|
||||
#include "shell/common/gin_converters/file_path_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/gin_helper/promise.h"
|
||||
@@ -106,8 +107,12 @@ static HRESULT ShowFileDialog(IFileDialog* dialog,
|
||||
static void ApplySettings(IFileDialog* dialog, const DialogSettings& settings) {
|
||||
std::wstring file_part;
|
||||
|
||||
if (!IsDirectory(settings.default_path))
|
||||
file_part = settings.default_path.BaseName().value();
|
||||
base::FilePath default_path = settings.default_path.empty()
|
||||
? electron::GetDefaultPath()
|
||||
: settings.default_path;
|
||||
|
||||
if (!IsDirectory(default_path))
|
||||
file_part = default_path.BaseName().value();
|
||||
|
||||
dialog->SetFileName(file_part.c_str());
|
||||
|
||||
@@ -149,8 +154,8 @@ static void ApplySettings(IFileDialog* dialog, const DialogSettings& settings) {
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.default_path.IsAbsolute()) {
|
||||
SetDefaultFolder(dialog, settings.default_path);
|
||||
if (default_path.IsAbsolute()) {
|
||||
SetDefaultFolder(dialog, default_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,4 +114,18 @@ void RegisterPathProvider() {
|
||||
PATH_END);
|
||||
}
|
||||
|
||||
base::FilePath GetDefaultPath() {
|
||||
base::FilePath path;
|
||||
|
||||
ScopedAllowBlockingForElectron allow_blocking;
|
||||
if (base::PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &path) &&
|
||||
base::DirectoryExists(path))
|
||||
return path;
|
||||
|
||||
if (base::PathService::Get(base::DIR_HOME, &path))
|
||||
return path;
|
||||
|
||||
return base::FilePath();
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -51,6 +51,10 @@ static_assert(PATH_START < PATH_END, "invalid PATH boundaries");
|
||||
// Register the path provider with the base::PathService.
|
||||
void RegisterPathProvider();
|
||||
|
||||
// Returns a default directory for file dialogs when no default path is
|
||||
// provided.
|
||||
base::FilePath GetDefaultPath();
|
||||
|
||||
} // namespace electron
|
||||
|
||||
#endif // ELECTRON_SHELL_COMMON_ELECTRON_PATHS_H_
|
||||
|
||||
@@ -567,7 +567,14 @@ describe('command line switches', () => {
|
||||
});
|
||||
|
||||
it('creates startup trace', async () => {
|
||||
const rc = await startRemoteControlApp(['--trace-startup=*', `--trace-startup-file=${outputFilePath}`, '--trace-startup-duration=1', '--enable-logging']);
|
||||
// node.async_hooks relies on %trace builtin to log trace points from JS
|
||||
// https://github.com/nodejs/node/blob/8b199eef3dd4de910a6521adc42ae611a62a19e1/lib/internal/trace_events_async_hooks.js#L48-L53
|
||||
// The phase event arg TRACE_EVENT_PHASE_NESTABLE_ASYNC_(BEGIN | END) is not supported in v8_use_perfetto mode
|
||||
// https://source.chromium.org/chromium/chromium/src/+/main:v8/src/builtins/builtins-trace.cc;l=201-216
|
||||
// and leads to the following error: TypeError: Trace event phase must be a number.
|
||||
// TODO: Identify why the error started appearing with roll https://github.com/electron/electron/pull/47561
|
||||
// given both v8_use_perfetto has been enabled before the roll and builtins-trace macro hasn't changed.
|
||||
const rc = await startRemoteControlApp(['--trace-startup="*,-node.async_hooks"', `--trace-startup-file=${outputFilePath}`, '--trace-startup-duration=1', '--enable-logging']);
|
||||
const stderrComplete = new Promise<string>(resolve => {
|
||||
let stderr = '';
|
||||
rc.process.stderr!.on('data', (chunk) => {
|
||||
|
||||
Reference in New Issue
Block a user